#include using namespace Upp; template void Check(const char *op, X a, R r) { ArrayMap global; StdLib(global); global.Add("a", a); String exp = AsString(op) + "a"; EscValue v = Evaluate(exp, global); LOG("a = " << a << "; " << exp << " = " << v << " (" << r << ")"); } #define UCHK(op, a) Check(#op, a, op a) template void Check(X a, const char *op, Y b, R r) { ArrayMap global; StdLib(global); global.Add("a", a); global.Add("b", b); String exp = "a" + AsString(op) + "b"; EscValue v = Evaluate(exp, global); LOG("a = " << a << ", b = " << b << "; " << exp << " = " << v << " (" << r << ")"); if(v.IsInt64()) ASSERT(r == (R)v.GetInt64()); else ASSERT(r == (R)v.GetNumber()); } #define CHK(a, op, b) Check(a, #op, b, a op b) #define CHKDBL(a, b) \ LOG("============="); \ UCHK(+, a); \ UCHK(-, a); \ UCHK(!, a); \ CHK(a, +, b); \ CHK(a, -, b); \ CHK(a, *, b); \ CHK(a, /, b); \ CHK(a, <, b); \ CHK(a, >, b); \ CHK(a, <=, b); \ CHK(a, >=, b); \ CHK(a, ==, b); \ CHK(a, &&, b); \ CHK(a, ||, b); \ #define CHKINT(a, b) \ UCHK(~, a); \ CHKDBL(a, b); \ CHK(a, %, b); \ CHK(a, <<, b); \ CHK(a, >>, b); \ CHK(a, &, b); \ CHK(a, ^, b); \ CHK(a, |, b); \ #define CHKV(val, ref) \ { Value v = val; \ LOG(#val << " = " << v << ", ref: " << ref); \ ASSERT(v == ref); } bool DblMatch(double x, double y) { return abs(x - y) < min(abs(x), abs(y)) / 1e10; } #define CHKS(exp) \ { double x = Evaluate(#exp, global).GetNumber(); LOG(#exp << " = " << x << ", " << exp); ASSERT(DblMatch(x, exp)); } void SIC_Print(EscEscape& e) { if(e[0].IsArray()) LOG((String) e[0]); else if(e[0].IsNumber()) LOG(e[0].GetNumber()); else if(!e[0].IsVoid()) e.ThrowError("invalid argument to 'Print'"); } void Zero(EscEscape& e) { e = 0; } CONSOLE_APP_MAIN { StdLogSetup(LOG_FILE|LOG_COUT); CHKDBL(3.1, 2.1); CHKDBL(3.0, 2.0); CHKDBL(3.0, (int64)2); CHKDBL((int64)3, 2.0); CHKINT((int64)3, (int64)2); LOG("============================="); ArrayMap global; StdLib(global); Escape(global, "Zero()", Zero); global.Add("a", (int64)2); CHKV(Evaluate("a++", global).GetInt64(), 2); CHKV(global.Get("a").GetInt64(), 3); CHKV(Evaluate("++a", global).GetInt64(), 4); CHKV(global.Get("a").GetInt64(), 4); CHKV(Evaluate("a--", global).GetInt64(), 4); CHKV(global.Get("a").GetInt64(), 3); CHKV(Evaluate("--a", global).GetInt64(), 2); CHKV(global.Get("a").GetInt64(), 2); LOG("----"); global.GetAdd("a", (double)2); CHKV(Evaluate("a++", global).GetNumber(), 2); CHKV(global.Get("a").GetNumber(), 3); CHKV(Evaluate("++a", global).GetNumber(), 4); CHKV(global.Get("a").GetNumber(), 4); CHKV(Evaluate("a--", global).GetNumber(), 4); CHKV(global.Get("a").GetNumber(), 3); CHKV(Evaluate("--a", global).GetNumber(), 2); CHKV(global.Get("a").GetNumber(), 2); CHKV(Evaluate("a = 0", global).GetNumber(), 0); CHKV(Evaluate("a == 0", global).GetNumber(), 1); CHKV(Evaluate("Zero() == 0", global).GetNumber(), 1); CHKV(Evaluate("Zero() == 1", global).GetNumber(), 0); LOG("============================="); CHKS(sin(0.5)) CHKS(cos(0.5)) CHKS(tan(0.5)) CHKS(asin(0.5)) CHKS(acos(0.5)) CHKS(atan(0.5)) CHKS(atan2(0.5, 0.5)) CHKS(sinh(0.5)) CHKS(cosh(0.5)) CHKS(tanh(0.5)) CHKS(asinh(0.5)) CHKS(acosh(3.762196)) CHKS(atanh(0.5)) CHKS(exp(0.5)) CHKS(log(0.5)) CHKS(log10(0.5)) CHKS(exp2(8)) CHKS(log2(256)) CHKS(sqrt(0.5)) CHKS(cbrt(0.5)) CHKS(pow(10, 2)) LOG("============================="); global.GetAdd("s", "Test"); CHKV((WString)Evaluate("s", global), "Test"); LOG("----"); Escape(global, "Print(x)", SIC_Print); try { Scan(global, LoadFile(GetDataFile("script.esc"))); Execute(global, "main", INT_MAX); } catch(CParser::Error e) { Cout() << "ERROR: " << e << "\n"; } DDUMP(global.Get("out")); DDUMP(global.Get("out2")); DDUMP(global.Get("out3")); DDUMP(global.Get("out4")); DDUMP(global.Get("out5")); ASSERT(AsString(global.Get("out")) == "{ \"a\":123, \"b\":\"Hello!\" }"); ASSERT(AsString(global.Get("out2")) == "\"test\""); ASSERT(AsString(global.Get("out3")) == "[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]"); ASSERT(AsString(global.Get("out4")) == "1"); ASSERT(AsString(global.Get("out5")) == "5"); LOG("=========================== OK"); }