// // Table of Delta standard functions // #include #include #include #include #include "stfunc.h" #include "value.h" // Mathematical constants are not defined in stupid MS Windows #ifndef M_E # define M_E 2.7182818284590452354 /* e */ #endif #ifndef M_PI # define M_PI 3.14159265358979323846 /* pi */ #endif #ifndef M_LN2 # define M_LN2 0.69314718055994530942 /* log_e 2 */ #endif #ifndef M_LN10 # define M_LN10 2.30258509299404568402 /* log_e 10 */ #endif using std::map; using std::string; // Interface functions to standard static void std_len(int numArgs, const ValuePtr* args, Value* res); static void std_append(int numArgs, const ValuePtr* args, Value* res); static void std_extend(int numArgs, const ValuePtr* args, Value* res); static void std_left(int numArgs, const ValuePtr* args, Value* res); static void std_right(int numArgs, const ValuePtr* args, Value* res); static void std_mid(int numArgs, const ValuePtr* args, Value* res); static void std_substr(int numArgs, const ValuePtr* args, Value* res); static void std_range(int numArgs, const ValuePtr* args, Value* res); static void std_clear(int numArgs, const ValuePtr* args, Value* res); static void std_print(int numArgs, const ValuePtr* args, Value* res); static void std_println(int numArgs, const ValuePtr* args, Value* res); static void std_scan(int numArgs, const ValuePtr* args, Value* res); // Math functions static void std_fabs(int numArgs, const ValuePtr* args, Value* res); static void std_fmod(int numArgs, const ValuePtr* args, Value* res); static void std_abs(int numArgs, const ValuePtr* args, Value* res); static void std_sqrt(int numArgs, const ValuePtr* args, Value* res); static void std_pow(int numArgs, const ValuePtr* args, Value* res); static void std_powmod(int numArgs, const ValuePtr* args, Value* res); static void std_exp(int numArgs, const ValuePtr* args, Value* res); static void std_log(int numArgs, const ValuePtr* args, Value* res); static void std_log2(int numArgs, const ValuePtr* args, Value* res); static void std_log10(int numArgs, const ValuePtr* args, Value* res); static void std_sin(int numArgs, const ValuePtr* args, Value* res); static void std_cos(int numArgs, const ValuePtr* args, Value* res); static void std_tan(int numArgs, const ValuePtr* args, Value* res); static void std_atan(int numArgs, const ValuePtr* args, Value* res); static void std_atan2(int numArgs, const ValuePtr* args, Value* res); static void std_gcd(int numArgs, const ValuePtr* args, Value* res); static void std_rand(int numArgs, const ValuePtr* args, Value* res); static void std_randrange(int numArgs, const ValuePtr* args, Value* res); const map stdFunctions = { { "len", StdFuncDef("len", 1, std_len) }, { "size", StdFuncDef("size", 1, std_len) }, { "append", StdFuncDef("append", 2, std_append, STDFUNC_RES_LVALUE) }, { "extend", StdFuncDef("extend", 2, std_extend, STDFUNC_RES_LVALUE) }, { "left", StdFuncDef("left", 2, std_left) }, { "right", StdFuncDef("right", 2, std_right) }, { "mid", StdFuncDef("mid", -1, std_mid) }, { "substr", StdFuncDef("substr", -1, std_substr) }, { "range", StdFuncDef("range", -1, std_range) }, { "clear", StdFuncDef("clear", 1, std_clear, STDFUNC_RES_LVALUE) }, { "print", StdFuncDef("print", -1, std_print) }, { "println", StdFuncDef("println", -1, std_println) }, { "scan", StdFuncDef("scan", 0, std_scan) }, { "fabs", StdFuncDef("fabs", 1, std_fabs) }, { "fmod", StdFuncDef("fmod", 1, std_fmod) }, { "abs", StdFuncDef("abs", 1, std_abs) }, { "sqrt", StdFuncDef("sqrt", 1, std_sqrt) }, { "pow", StdFuncDef("pow", 2, std_pow) }, { "powmod", StdFuncDef("pow", 3, std_powmod) }, { "exp", StdFuncDef("exp", 1, std_exp) }, { "log", StdFuncDef("log", 1, std_log) }, { "log2", StdFuncDef("log2", 1, std_log2) }, { "log10", StdFuncDef("log10", 1, std_log10) }, { "sin", StdFuncDef("sin", 1, std_sin) }, { "cos", StdFuncDef("cos", 1, std_cos) }, { "tan", StdFuncDef("tan", 1, std_tan) }, { "atan", StdFuncDef("atan", 1, std_atan) }, { "atan2", StdFuncDef("atan2", 2, std_atan2) }, { "gcd", StdFuncDef("gcd", 2, std_gcd) }, { "rand", StdFuncDef("rand", 0, std_rand) }, { "randrange", StdFuncDef("randrange", -1, std_randrange) }, }; const StdFuncDef* findStandardFunction(const string& name) { map::const_iterator i = stdFunctions.find(name); if (i == stdFunctions.end()) return 0; return &(i->second); } static void std_len(int numArgs, const ValuePtr* args, Value* res) { int l = 1; if (args[0]->isArray()) { l = int(args[0]->array_value.size()); } else if (args[0]->isString()) { l = int(args[0]->string_value.size()); } res->clear(); res->value_type = VALUE_TYPE_INT; res->int_value = l; } static void std_append(int numArgs, const ValuePtr* args, Value* res) { if (!(res->isArray() || res->isString())) throw InterpretatorException( "Cannot append to non-array object" ); if (res->isArray()) { res->array_value.push_back(*(args[1])); } else if (res->isString()) { Value v; args[1]->convertToString(v); string str = res->string_value + v.string_value; res->string_value = str; } } static void std_extend(int numArgs, const ValuePtr* args, Value* res) { if (!(res->isArray() || res->isString())) throw InterpretatorException( "Cannot extend non-array object" ); if (res->isArray()) { if (!args[1]->isArray()) throw InterpretatorException( "Illegal argument for extend" ); res->array_value.insert( res->array_value.end(), args[1]->array_value.cbegin(), args[1]->array_value.cend() ); } else if (res->isString()) { Value v; args[1]->convertToString(v); string str = res->string_value + v.string_value; res->string_value = str; } } static void std_left(int numArgs, const ValuePtr* args, Value* res) { if (!(args[0]->isArray() || args[0]->isString())) throw InterpretatorException( "Incorrect first argument of function \"left\"" ); Value v; args[1]->convertToInt(v); int64_t n = v.int_value; res->clear(); if (args[0]->isArray()) { res->value_type = VALUE_TYPE_ARRAY; if (n <= 0) return; if (size_t(n) > args[0]->array_value.size()) n = int64_t(args[0]->array_value.size()); res->array_value = vector( args[0]->array_value.cbegin(), args[0]->array_value.cbegin() + n ); } else { assert(args[0]->isString()); res->value_type = VALUE_TYPE_STRING; if (n <= 0) return; if (size_t(n) > args[0]->string_value.size()) n = int64_t(args[0]->string_value.size()); res->string_value =args[0]->string_value.substr(0, n); } } static void std_right(int numArgs, const ValuePtr* args, Value* res) { if (!(args[0]->isArray() || args[0]->isString())) throw InterpretatorException( "Incorrect first argument of function \"right\"" ); Value v; args[1]->convertToInt(v); int64_t n = v.int_value; res->clear(); if (args[0]->isArray()) { res->value_type = VALUE_TYPE_ARRAY; if (n <= 0) return; if (size_t(n) > args[0]->array_value.size()) n = int64_t(args[0]->array_value.size()); res->array_value = vector( args[0]->array_value.cend() - n, args[0]->array_value.cend() ); } else { assert(args[0]->isString()); res->value_type = VALUE_TYPE_STRING; if (n <= 0) return; if (size_t(n) > args[0]->string_value.size()) n = int64_t(args[0]->string_value.size()); res->string_value =args[0]->string_value.substr( args[0]->string_value.size() - size_t(n), size_t(n) ); } } static void std_mid(int numArgs, const ValuePtr* args, Value* res) { if (numArgs < 2) throw InterpretatorException( "Incorrect number of arguments of function \"mid\"" ); if (!(args[0]->isArray() || args[0]->isString())) throw InterpretatorException( "Incorrect first argument of function \"mid\"" ); Value v; args[1]->convertToInt(v); int64_t s = v.int_value; if (s < 0) s = 0; int64_t n = (-1); if (numArgs >= 3) { args[2]->convertToInt(v); n = v.int_value; } res->clear(); if (args[0]->isArray()) { res->value_type = VALUE_TYPE_ARRAY; if (n == 0 || size_t(s) >= args[0]->array_value.size()) return; if (n < 0) n = int64_t(args[0]->array_value.size()) - s; if (size_t(s + n) > args[0]->array_value.size()) n -= (s + n) - int64_t(args[0]->array_value.size()); res->array_value = vector( args[0]->array_value.cbegin() + s, args[0]->array_value.cbegin() + s + n ); } else { res->value_type = VALUE_TYPE_STRING; if (n == 0 || size_t(s) >= args[0]->string_value.size()) return; if (n < 0) n = int64_t(args[0]->string_value.size()) - s; if (size_t(s + n) > args[0]->string_value.size()) n -= (s + n) - int64_t(args[0]->string_value.size()); res->string_value =args[0]->string_value.substr( size_t(s), size_t(n) ); } } static void std_substr(int numArgs, const ValuePtr* args, Value* res) { if (numArgs < 2) throw InterpretatorException( "Incorrect number of arguments of function \"substr\"" ); if (!args[0]->isString()) throw InterpretatorException( "Incorrect first argument of function \"substr\"" ); Value v; args[1]->convertToInt(v); int64_t s = v.int_value; if (s < 0) s = 0; int64_t n = (-1); if (numArgs >= 3) { args[2]->convertToInt(v); n = v.int_value; } res->clear(); res->value_type = VALUE_TYPE_STRING; if (n == 0 || size_t(s) >= args[0]->string_value.size()) return; if (n < 0) n = int64_t(args[0]->string_value.size()) - s; if (size_t(s + n) > args[0]->string_value.size()) n -= (s + n) - int64_t(args[0]->string_value.size()); res->string_value =args[0]->string_value.substr( size_t(s), size_t(n) ); } static void std_range(int numArgs, const ValuePtr* args, Value* res) { res->clear(); res->value_type = VALUE_TYPE_ARRAY; Value v0; args[0]->convertToInt(v0); if (numArgs == 1) { for (int64_t i = 0; i < v0.int_value; ++i) { res->array_value.push_back(Value(i)); } } else if (numArgs >= 2) { Value v1; args[1]->convertToInt(v1); int64_t from = v0.int_value; int64_t to = v1.int_value; int xmin = from; int xmax = to - 1; if (to < from) { xmin = to + 1; xmax = from; } else if (to == from) { // Empty range return; } int64_t step = 1; if (numArgs >= 3) { Value v2; args[2]->convertToInt(v2); step = v2.int_value; } for ( int64_t i = from; xmin <= i && i <= xmax; i += step ) { res->array_value.push_back(Value(i)); } } } static void std_clear(int numArgs, const ValuePtr* args, Value* res) { if (!(res->isArray() || res->isString())) throw InterpretatorException( "Cannot clear non-array object" ); if (res->isArray()) { res->array_value.clear(); } else if (res->isString()) { res->string_value.clear(); } } static void std_print(int numArgs, const ValuePtr* args, Value* res) { for (int i = 0; i < numArgs; ++i) { args[i]->print(); } // Return none res->clear(); res->value_type = VALUE_TYPE_INT; } static void std_println(int numArgs, const ValuePtr* args, Value* res) { std_print(numArgs, args, res); printf("\n"); } static void std_scan(int numArgs, const ValuePtr* args, Value* res) { assert(numArgs == 0); res->scan(); } static void std_fabs(int numArgs, const ValuePtr* args, Value* res) { Value x; args[0]->convertToDouble(x); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = fabs(x.double_value); } static void std_fmod(int numArgs, const ValuePtr* args, Value* res) { Value x, y; args[0]->convertToDouble(x); args[1]->convertToDouble(y); if (fabs(y.double_value) <= 0.) throw InterpretatorException("Zero division"); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = fmod(x.double_value, y.double_value); } static void std_abs(int numArgs, const ValuePtr* args, Value* res) { Value x; args[0]->convertToInt(x); res->clear(); res->value_type = VALUE_TYPE_INT; res->int_value = llabs(x.int_value); } static void std_sqrt(int numArgs, const ValuePtr* args, Value* res) { Value x; args[0]->convertToDouble(x); if (x.double_value < 0.) throw InterpretatorException("Square root of negative number"); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = sqrt(x.double_value); } static void std_pow(int numArgs, const ValuePtr* args, Value* res) { Value x, y; args[0]->convertToDouble(x); args[1]->convertToDouble(y); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = pow(x.double_value, y.double_value); } // a^n (mod m) static void std_powmod(int numArgs, const ValuePtr* args, Value* res) { Value a, n, m; args[0]->convertToInt(a); args[1]->convertToInt(n); args[2]->convertToInt(m); int64_t aa = a.int_value; int64_t nn = n.int_value; int64_t mm = m.int_value; if (mm == 0) throw InterpretatorException("powmod(a, n, m): zero m"); // Compute a^n (mod m) int64_t p = 1; while (nn > 0) { if (nn%2 == 0) { nn /= 2; aa *= aa; aa %= mm; } else { --nn; p *= aa; p %= mm; } } res->clear(); res->value_type = VALUE_TYPE_INT; res->int_value = p; } static void std_exp(int numArgs, const ValuePtr* args, Value* res) { Value x; args[0]->convertToDouble(x); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = exp(x.double_value); } static void std_log(int numArgs, const ValuePtr* args, Value* res) { Value x; args[0]->convertToDouble(x); if (x.double_value <= 0.) throw InterpretatorException("log of non-positive number"); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = log(x.double_value); } static void std_log2(int numArgs, const ValuePtr* args, Value* res) { Value x; args[0]->convertToDouble(x); if (x.double_value <= 0.) throw InterpretatorException("log2 of non-positive number"); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = log(x.double_value)/M_LN2; } static void std_log10(int numArgs, const ValuePtr* args, Value* res) { Value x; args[0]->convertToDouble(x); if (x.double_value <= 0.) throw InterpretatorException("log10 of non-positive number"); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = log(x.double_value)/M_LN2; } static void std_sin(int numArgs, const ValuePtr* args, Value* res) { Value x; args[0]->convertToDouble(x); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = sin(x.double_value); } static void std_cos(int numArgs, const ValuePtr* args, Value* res) { Value x; args[0]->convertToDouble(x); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = cos(x.double_value); } static void std_tan(int numArgs, const ValuePtr* args, Value* res) { Value x; args[0]->convertToDouble(x); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = tan(x.double_value); } static void std_atan(int numArgs, const ValuePtr* args, Value* res) { Value x; args[0]->convertToDouble(x); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = atan(x.double_value); } static void std_atan2(int numArgs, const ValuePtr* args, Value* res) { Value y, x; args[0]->convertToDouble(y); args[1]->convertToDouble(x); if (fabs(x.double_value) <= 0. && fabs(y.double_value) <= 0.) throw InterpretatorException("atan2(0, 0) is undefined"); res->clear(); res->value_type = VALUE_TYPE_DOUBLE; res->double_value = atan2(y.double_value, x.double_value); } static void std_gcd(int numArgs, const ValuePtr* args, Value* res) { Value x, y; args[0]->convertToInt(x); args[1]->convertToInt(y); int64_t a = x.int_value; int64_t b = y.int_value; if (a == 0 && b == 0) throw InterpretatorException("gcd(0, 0) is undefined"); // Compute gcd(a, b) while (b != 0) { int64_t r = a%b; a = b; b = r; } if (a < 0) a = (-a); res->clear(); res->value_type = VALUE_TYPE_INT; res->int_value = a; } static void std_rand(int numArgs, const ValuePtr* args, Value* res) { res->clear(); res->value_type = VALUE_TYPE_INT; res->int_value = rand(); } static void std_randrange(int numArgs, const ValuePtr* args, Value* res) { if (numArgs == 0) throw InterpretatorException("No arguments for randrange"); res->clear(); res->value_type = VALUE_TYPE_INT; Value v0; args[0]->convertToInt(v0); int x0 = int(v0.int_value); if (numArgs <= 1) { res->int_value = rand()%x0; } else { assert (numArgs >= 2); Value v1; args[1]->convertToInt(v1); int x1 = int(v1.int_value); int d = x1 - x0; int s = 1; if (d == 0) { d = 1; } else if (d < 0) { d = (-d); s = (-1); } res->int_value = x0 + s*(rand()%d); } } void addStandardFunctionsToNameTable(NameTable& nt) { map::const_iterator i = stdFunctions.cbegin(); while (i != stdFunctions.cend()) { NameDef* n = nt.addName( i->second.name ); n->value.clear(); n->value.string_value = i->second.name; n->value.value_type = VALUE_TYPE_STANDARD_FUNCTION; n->value.setStdFuncPtr(&(i->second)); ++i; } }