mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
326 lines
6.5 KiB
C++
326 lines
6.5 KiB
C++
#include <Esc/Esc.h>
|
|
|
|
|
|
namespace Upp {
|
|
|
|
#define LTIMING(x) // RTIMING(x)
|
|
|
|
void ESC_count(EscEscape& e)
|
|
{
|
|
e = e[0].GetCount();
|
|
}
|
|
|
|
void ESC_is_void(EscEscape& e)
|
|
{
|
|
e = e[0].IsVoid();
|
|
}
|
|
|
|
void ESC_is_number(EscEscape& e)
|
|
{
|
|
e = e[0].IsNumber();
|
|
}
|
|
|
|
void ESC_is_array(EscEscape& e)
|
|
{
|
|
e = e[0].IsArray();
|
|
}
|
|
|
|
void ESC_is_map(EscEscape& e)
|
|
{
|
|
e = e[0].IsMap();
|
|
}
|
|
|
|
void ESC_int(EscEscape& e)
|
|
{
|
|
if(e[0].IsNumber())
|
|
e = (int)e[0].GetNumber();
|
|
}
|
|
|
|
void ESC_to_string(EscEscape& e)
|
|
{
|
|
e = e[0].ToString();
|
|
}
|
|
|
|
void ESC_to_number(EscEscape& e)
|
|
{
|
|
if(e[0].IsArray()) {
|
|
double d = ScanDouble((String)e[0]);
|
|
if(!IsNull(d)) {
|
|
if(FitsInInt64(d))
|
|
e = ScanInt64((String)e[0]);
|
|
else
|
|
e = d;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ESC_rand(EscEscape& e)
|
|
{
|
|
e = rand();
|
|
}
|
|
|
|
void ESC_keys(EscEscape& e)
|
|
{
|
|
e.CheckMap(0);
|
|
EscValue v;
|
|
const VectorMap<EscValue, EscValue>& m = e[0].GetMap();
|
|
for(int i = 0; i < m.GetCount(); i++)
|
|
if(!m.IsUnlinked(i))
|
|
v.ArrayAdd(m.GetKey(i));
|
|
e = v;
|
|
}
|
|
|
|
void ESC_values(EscEscape& e)
|
|
{
|
|
e.CheckMap(0);
|
|
EscValue v;
|
|
const VectorMap<EscValue, EscValue>& m = e[0].GetMap();
|
|
for(int i = 0; i < m.GetCount(); i++)
|
|
if(!m.IsUnlinked(i))
|
|
v.ArrayAdd(m[i]);
|
|
e = v;
|
|
}
|
|
|
|
void ESC_reverse(EscEscape& e)
|
|
{
|
|
e.CheckArray(0);
|
|
const Vector<EscValue>& a = e[0].GetArray();
|
|
EscValue r;
|
|
for(int i = a.GetCount() - 1; i >= 0; i--)
|
|
r.ArrayAdd(a[i]);
|
|
e = r;
|
|
}
|
|
|
|
struct EscCmp {
|
|
Esc *esc;
|
|
bool operator()(const EscValue& a, const EscValue& b) const {
|
|
return esc->DoCompare(a, b, "< (sort)") < 0;
|
|
}
|
|
};
|
|
|
|
Vector<int> EscGetSortOrder(EscEscape& e)
|
|
{
|
|
e.CheckArray(0);
|
|
const Vector<EscValue>& va = e[0].GetArray();
|
|
EscCmp cmp;
|
|
cmp.esc = &e.esc;
|
|
return GetSortOrder(va, cmp);
|
|
}
|
|
|
|
void ESC_sort(EscEscape& e)
|
|
{
|
|
Vector<int> so = EscGetSortOrder(e);
|
|
EscValue r;
|
|
for(int i = 0; i < so.GetCount(); i++)
|
|
r.ArrayAdd(e[0].ArrayGet(so[i]));
|
|
e = r;
|
|
}
|
|
|
|
void ESC_order(EscEscape& e)
|
|
{
|
|
Vector<int> so = EscGetSortOrder(e);
|
|
EscValue r;
|
|
for(int i = 0; i < so.GetCount(); i++)
|
|
r.ArrayAdd(so[i]);
|
|
e = r;
|
|
}
|
|
|
|
// ---------------------------
|
|
|
|
void ESC_mid(EscEscape& e)
|
|
{
|
|
e.CheckArray(0);
|
|
int pos = e.Int(1);
|
|
int count = e.Int(2);
|
|
if(pos < 0 || pos + count > e[0].GetCount())
|
|
e.ThrowError("out of bounds in call to 'mid'");
|
|
e.ret_val = e[0].ArrayGet(pos, count);
|
|
}
|
|
|
|
void ESC_exists(EscEscape& e)
|
|
{
|
|
e.CheckMap(0);
|
|
e = !e[0].MapGet(e[1]).IsVoid();
|
|
}
|
|
|
|
struct ESC_FileOut : public EscHandle {
|
|
FileStream file;
|
|
void Put(EscEscape& e) { if(file) file.Put(e.Int(0)); }
|
|
void PutLine(EscEscape& e) { if(file) file.PutLine(String(e[0])); }
|
|
void Close(EscEscape& e) { if(file) file.Close(); }
|
|
|
|
typedef ESC_FileOut CLASSNAME;
|
|
|
|
ESC_FileOut(EscEscape& e, EscValue& v, int style) {
|
|
file.Open(String(e[0]), style);
|
|
v.Escape("Put(a)", this, THISBACK(Put));
|
|
v.Escape("PutLine(a)", this, THISBACK(PutLine));
|
|
v.Escape("Close()", this, THISBACK(Close));
|
|
}
|
|
};
|
|
|
|
void ESC_OpenFileOut(EscEscape& e)
|
|
{
|
|
EscValue v;
|
|
ESC_FileOut *f = new ESC_FileOut(e, v, FileStream::CREATE);
|
|
if(f->file)
|
|
e = v;
|
|
}
|
|
|
|
void ESC_OpenFileAppend(EscEscape& e)
|
|
{
|
|
EscValue v;
|
|
ESC_FileOut *f = new ESC_FileOut(e, v, FileStream::APPEND);
|
|
if(f->file)
|
|
e = v;
|
|
}
|
|
|
|
struct ESC_FileIn : public EscHandle {
|
|
FileIn file;
|
|
void IsEof(EscEscape& e) { e = file.IsEof(); }
|
|
void Get(EscEscape& e) { e = file.Get(); }
|
|
void GetLine(EscEscape& e) { e = file.GetLine(); }
|
|
void Close(EscEscape& e) { if(file) file.Close(); }
|
|
|
|
typedef ESC_FileIn CLASSNAME;
|
|
|
|
ESC_FileIn(EscEscape& e, EscValue& v) {
|
|
file.Open(String(e[0]));
|
|
v.Escape("IsEof()", this, THISBACK(IsEof));
|
|
v.Escape("Get()", this, THISBACK(Get));
|
|
v.Escape("GetLine()", this, THISBACK(GetLine));
|
|
v.Escape("Close()", this, THISBACK(Close));
|
|
}
|
|
};
|
|
|
|
void ESC_OpenFileIn(EscEscape& e)
|
|
{
|
|
EscValue v;
|
|
ESC_FileIn *f = new ESC_FileIn(e, v);
|
|
if(f->file)
|
|
e = v;
|
|
}
|
|
|
|
// ---------------------------
|
|
|
|
bool IsDate(const EscValue& v)
|
|
{
|
|
return v.HasNumberField("year") && v.HasNumberField("month") && v.HasNumberField("day");
|
|
}
|
|
|
|
bool IsTime(const EscValue& v)
|
|
{
|
|
return IsDate(v) && v.HasNumberField("hour") && v.HasNumberField("minute") && v.HasNumberField("second");
|
|
}
|
|
|
|
void SIC_IsDate(EscEscape& e)
|
|
{
|
|
e = IsDate(e[0]);
|
|
}
|
|
|
|
void SIC_IsTime(EscEscape& e)
|
|
{
|
|
e = IsTime(e[0]);
|
|
}
|
|
|
|
void SIC_GetSysTime(EscEscape& e)
|
|
{
|
|
Time tm = GetSysTime();
|
|
EscValue v;
|
|
v.MapSet("year", (int)tm.year);
|
|
v.MapSet("month", (int)tm.month);
|
|
v.MapSet("day", (int)tm.day);
|
|
v.MapSet("hour", (int)tm.hour);
|
|
v.MapSet("minute", (int)tm.minute);
|
|
v.MapSet("second", (int)tm.second);
|
|
e = v;
|
|
}
|
|
|
|
void ESC_ToLower(EscEscape& e)
|
|
{
|
|
String s = e[0];
|
|
e = ToLower(s);
|
|
}
|
|
|
|
void ESC_ToUpper(EscEscape& e)
|
|
{
|
|
String s = e[0];
|
|
e = ToUpper(s);
|
|
}
|
|
|
|
// ---------------------------
|
|
|
|
void ESC_replace(EscEscape& e)
|
|
{
|
|
String str = e[0];
|
|
str.Replace(e[1], e[2]);
|
|
e = str;
|
|
}
|
|
|
|
// ---------------------------
|
|
|
|
void StdLib(ArrayMap<String, EscValue>& global)
|
|
{
|
|
Escape(global, "is_number(value)", ESC_is_number);
|
|
Escape(global, "is_array(value)", ESC_is_array);
|
|
Escape(global, "is_map(value)", ESC_is_map);
|
|
Escape(global, "is_void(value)", ESC_is_void);
|
|
Escape(global, "int(value)", ESC_int);
|
|
Escape(global, "to_string(value)", ESC_to_string);
|
|
Escape(global, "to_number(value)", ESC_to_number);
|
|
Escape(global, "count(value)", ESC_count);
|
|
Escape(global, "keys(map)", ESC_keys);
|
|
Escape(global, "values(map)", ESC_values);
|
|
Escape(global, "rand()", ESC_rand);
|
|
Escape(global, "reverse(array)", ESC_reverse);
|
|
Escape(global, "sort(array)", ESC_sort);
|
|
Escape(global, "order(array)", ESC_order);
|
|
|
|
Escape(global, "replace(str, find, replace)", ESC_replace);
|
|
|
|
Escape(global, "ToUpper(value)", ESC_ToUpper);
|
|
Escape(global, "ToLower(value)", ESC_ToLower);
|
|
|
|
Escape(global, "len(x)", ESC_count);
|
|
Escape(global, "mid(array, pos, count)", ESC_mid);
|
|
Escape(global, "exists(map, key)", ESC_exists);
|
|
|
|
Escape(global, "OpenFileOut(x)", ESC_OpenFileOut);
|
|
Escape(global, "OpenFileAppend(x)", ESC_OpenFileOut);
|
|
Escape(global, "OpenFileIn(x)", ESC_OpenFileIn);
|
|
|
|
Escape(global, "GetSysTime()", SIC_GetSysTime);
|
|
Escape(global, "IsDate(x)", SIC_IsDate);
|
|
Escape(global, "IsTime(x)", SIC_IsTime);
|
|
|
|
#define FN(fn) Escfn(global, #fn "(value)", [](EscEscape& e) { e = fn(e[0].GetNumber()); });
|
|
|
|
FN(sin)
|
|
FN(cos)
|
|
FN(tan)
|
|
FN(asin)
|
|
FN(acos)
|
|
FN(atan)
|
|
|
|
FN(sinh)
|
|
FN(cosh)
|
|
FN(tanh)
|
|
FN(asinh)
|
|
FN(acosh)
|
|
FN(atanh)
|
|
|
|
FN(exp)
|
|
FN(log)
|
|
FN(log10)
|
|
FN(exp2)
|
|
FN(log2)
|
|
FN(sqrt)
|
|
FN(cbrt)
|
|
|
|
#undef FN
|
|
|
|
Escfn(global, "pow(base, exponent)", [](EscEscape& e) { e = pow(e[0].GetNumber(), e[1].GetNumber()); });
|
|
Escfn(global, "atan2(a, b)", [](EscEscape& e) { e = atan2(e[0].GetNumber(), e[1].GetNumber()); });
|
|
}
|
|
|
|
}
|