O_TYPE mpsl_exec_i(O_ARGS) /* Executes one MPSL instruction in the MPSL virtual machine. Called from mpsl_exec_p() (which holds the flow control status variable) */ { mpdm_t ret = NULL; mpdm_ref(c); mpdm_ref(a); mpdm_ref(l); /* if aborted or NULL, do nothing */ if (!mpsl_abort && c != NULL) { /* gets the opcode and calls it */ ret = op_table[mpdm_ival(C0)].func(c, a, l, f); if (mpsl_trap_func != NULL) { mpdm_t f = mpsl_trap_func; mpdm_ref(ret); mpsl_trap_func = NULL; mpdm_exec_3(f, c, a, ret, l); mpsl_trap_func = f; mpdm_unrefnd(ret); } } mpdm_unref(l); mpdm_unref(a); mpdm_unref(c); return ret; }
/** * mpsl_set_symbol - Sets value to a symbol. * @s: symbol name * @v: value * @l: local symbol table * * Assigns the value @v to the @s symbol. If the value exists as * a local symbol, it's assigned to it; otherwise, it's set as a global * symbol (and created if it does not exist). */ mpdm_t mpsl_set_symbol(mpdm_t s, mpdm_t v, mpdm_t l) { int n; mpdm_t r, p, w; mpdm_ref(l); mpdm_ref(s); mpdm_ref(v); /* get the local or global symbol table */ if ((r = find_local_symtbl(s, l)) == NULL) r = mpdm_root(); /* splits the path, if needed */ if (MPDM_IS_ARRAY(s)) p = mpdm_ref(s); else p = mpdm_ref(mpdm_split_s(s, L".")); w = r; for (n = 0; w != NULL && n < mpdm_size(p); n++) { /* is executable? run it and take its output */ while (MPDM_IS_EXEC(w)) w = mpdm_exec(w, NULL, NULL); /* last component? */ if (n == mpdm_size(p) - 1) { /* yes; do the setting */ if (MPDM_IS_HASH(w)) w = mpdm_hset(w, mpdm_aget(p, n), v); else if (MPDM_IS_ARRAY(w)) w = mpdm_aset(w, v, mpdm_ival(mpdm_aget(p, n))); } else { if (MPDM_IS_HASH(w)) w = mpdm_hget(w, mpdm_aget(p, n)); else if (MPDM_IS_ARRAY(w)) w = mpdm_aget(w, mpdm_ival(mpdm_aget(p, n))); else { mpdm_void(w); w = NULL; } } } mpdm_unref(p); mpdm_unref(v); mpdm_unref(s); mpdm_unref(l); return w; }
/** * mpdm_set_o - Sets a value in an object. * @o: the object * @v: the value * @i: the index * * Sets the value @v inside the object @o, accesible by index @i. * Returns @v. * [Objects] */ mpdm_t mpdm_set_o(mpdm_t o, mpdm_t v, mpdm_t i) /* do not use it; use mpdm_set() */ { mpdm_t b, r; int n; mpdm_ref(i); mpdm_ref(v); /* if hash is empty, create an optimal number of buckets */ if (mpdm_size(o) == 0) mpdm_expand(o, 0, mpdm_hash_buckets); n = HASH_BUCKET(o, i); if ((b = mpdm_get_i(o, n)) != NULL) { int pos; /* bucket exists; try to find the key there */ n = mpdm_bseek(b, i, 2, &pos); if (n < 0) { /* the pair does not exist: create it */ n = pos; mpdm_expand(b, n, 2); mpdm_set_i(b, i, n); } } else { /* the bucket does not exist; create it */ b = MPDM_A(2); /* put the bucket into the hash */ mpdm_set_i(o, b, n); /* offset 0 */ n = 0; /* insert the key */ mpdm_set_i(b, i, n); } r = mpdm_set_i(b, v, n + 1); mpdm_unref(v); mpdm_unref(i); return r; }
/** array = sort(a, sorting_func); */ static mpdm_t F_sort(F_ARGS) { mpdm_t r, v; v = mpdm_ref(A0); r = mpdm_sort_cb(mpdm_clone(v), 1, A1); mpdm_unref(v); return r; }
/** * mpdm_get_o - Gets a value from an object. * @o: the object * @i: the index * * Returns the value from @o by index @i, or NULL if there is no * value addressable by that index. * [Objects] */ mpdm_t mpdm_get_o(const mpdm_t o, const mpdm_t i) /* do not use it; use mpdm_get() */ { mpdm_t r; mpdm_ref(i); r = mpdm_get_wcs(o, mpdm_string(i)); mpdm_unref(i); return r; }
/** v = eval(code, args); */ static mpdm_t F_eval(F_ARGS) { mpdm_t r, c; a = mpdm_ref(mpdm_clone(a)); c = mpdm_shift(a); r = mpsl_eval(c, a, l); mpdm_unref(a); return r; }
/** argn = push(a, arg1 [, arg2, ... argn]); */ static mpdm_t F_push(F_ARGS) { int n; mpdm_t r = NULL; for (n = 1; n < mpdm_size(a); n++) { mpdm_unref(r); r = mpdm_push(A0, A(n)); mpdm_ref(r); } return mpdm_unrefnd(r); }
static void set_local_symbols(mpdm_t s, mpdm_t v, mpdm_t l) /* sets (or creates) a list of local symbols with a list of values */ { if (l != NULL) { mpdm_t h; mpdm_ref(s); mpdm_ref(v); mpdm_ref(l); /* gets the top local variable frame */ h = mpdm_aget(l, -1); if (MPDM_IS_ARRAY(s) || MPDM_IS_ARRAY(v)) { int n; mpdm_t a; for (n = 0; n < mpdm_size(s); n++) mpdm_hset(h, mpdm_aget(s, n), mpdm_aget(v, n)); if (n < mpdm_size(v)) { /* store the rest of arguments into _ */ a = mpdm_hset_s(h, L"_", MPDM_A(0)); for (; n < mpdm_size(v); n++) mpdm_push(a, mpdm_aget(v, n)); } } else mpdm_hset(h, s, v); mpdm_unref(l); mpdm_unref(v); mpdm_unref(s); } }
void test_mpsl_file(void) { mpdm_t v; mpdm_t inc; mpsl_trap(NULL); inc = mpdm_ref(MPDM_A(0)); mpdm_push(inc, MPDM_S(L".")); printf("Compiling from file:\n"); v = do_test_mpsl_file("test.mpsl", inc); v = do_test_exec(v, NULL); mpdm_unref(inc); }
/** string = sprintf(fmt, arg1 [,arg2 ... argn]); */ static mpdm_t F_sprintf(F_ARGS) { mpdm_t f, v, r; a = mpdm_ref(mpdm_clone(a)); f = mpdm_shift(a); /* if the first argument is an array, take it as the arguments */ if ((v = mpdm_get_i(a, 0)) != NULL && mpdm_type(v) == MPDM_TYPE_ARRAY) a = v; r = mpdm_sprintf(f, a); mpdm_unref(a); return r; }
/** * mpdm_exists - Tests if there is a value available by index. * @o: the object * @i: the index * * Returns 1 if exists a value indexable by @i in @h, or 0 othersize. * [Hashes] */ int mpdm_exists(const mpdm_t o, const mpdm_t i) { mpdm_t b; int ret = 0; mpdm_ref(i); if (mpdm_size(o)) { if ((b = mpdm_get_i(o, HASH_BUCKET(o, i))) != NULL) { /* if bucket exists, binary-seek it */ if (mpdm_bseek(b, i, 2, NULL) >= 0) ret = 1; } } mpdm_unref(i); return ret; }
/** * mpdm_keys - Returns the keys of a hash. * @h: the hash * * Returns an array containing all the keys of the @h hash. * [Hashes] * [Arrays] */ mpdm_t mpdm_keys(const mpdm_t h) { int c; mpdm_t a, i; printf("Warning: deprecated function mpdm_keys()\n"); mpdm_ref(h); /* create an array with the same number of elements */ a = MPDM_A(0); c = 0; while (mpdm_iterator(h, &c, NULL, &i)) mpdm_push(a, i); mpdm_unref(h); return a; }
void test_abort_and_eval(void) { mpdm_t v; mpdm_t e; mpsl_abort = 0; v = mpdm_ref(mpsl_compile(MPDM_S(L"1000;"), NULL)); do_test("Abort 1", mpdm_ival(mpdm_exec(v, NULL, NULL)) == 1000); /* set global abort function */ mpsl_abort = 1; do_test("Abort 2", mpdm_exec(v, NULL, NULL) == NULL); mpsl_abort = 0; do_test("Abort 3", mpdm_ival(mpdm_exec(v, NULL, NULL)) == 1000); mpdm_unref(v); mpsl_error(NULL); v = mpsl_eval(MPDM_S(L"invalid_code()"), NULL, NULL); e = mpdm_get_wcs(mpdm_root(), L"ERROR"); printf("The following error is OK:\n"); mpdm_dump(e); do_test("eval 1", v == NULL && e != NULL); v = mpsl_eval(MPDM_S(L"undef_func();"), NULL, NULL); e = mpdm_get_wcs(mpdm_root(), L"ERROR"); printf("The following error is also OK:\n"); mpdm_dump(e); do_test("eval 2", v == NULL && e != NULL); v = mpsl_eval(MPDM_S(L"load('unexistent_file.mpsl');"), NULL, NULL); e = mpdm_get_wcs(mpdm_root(), L"ERROR"); printf("The following error is also OK:\n"); mpdm_dump(e); do_test("eval 3", v == NULL && e != NULL); v = mpsl_eval(MPDM_S(L"2000;"), NULL, NULL); e = mpdm_get_wcs(mpdm_root(), L"ERROR"); do_test("eval 4", mpdm_ival(v) == 2000 && e == NULL); }
/** o = new(c1 [, c2, ...cn]); */ static mpdm_t F_new(F_ARGS) { int n; mpdm_t r = MPDM_O(); for (n = 0; n < mpdm_size(a); n++) { mpdm_t w, v, i; int m = 0; w = mpdm_ref(A(n)); if (mpdm_type(w) == MPDM_TYPE_OBJECT) { while (mpdm_iterator(w, &m, &v, &i)) mpdm_set(r, mpdm_clone(v), i); } mpdm_unref(w); } return r; }
/** * mpdm_del_o - Deletes a value from an object. * @o: the value * @i: the index * * Deletes the element accesible by index @i from @o. Returns NULL * (versions prior to 1.0.10 returned the deleted value). * [Objects] */ mpdm_t mpdm_del_o(mpdm_t o, const mpdm_t i) /* do not use it; use mpdm_del() */ { mpdm_t b; int n; mpdm_ref(i); if (mpdm_size(o)) { if ((b = mpdm_get_i(o, HASH_BUCKET(o, i))) != NULL) { /* bucket exists */ if ((n = mpdm_bseek(b, i, 2, NULL)) >= 0) { /* collapse the bucket */ mpdm_collapse(b, n, 2); } } } mpdm_unref(i); return NULL; }
void test_compiler_diffs(void) { mpdm_t r, cc, ac; int n; struct { wchar_t *code; int line; } compiler_tests[] = { // CT(L"local a = 1, b = 2, c, d = 3;"), // CT(L"local a = 1;"), // CT(L"local v; 1;"), // CT(L"local x, y, z; 2;"), CT(L"a |= 6;"), CT(L"a %= 6;"), CT(L"a /= 6;"), CT(L"a *= 6;"), CT(L"a -= 6;"), CT(L"a += 6;"), CT(L"for (n = 0; n < 100; n = n + 1) { print('kill'); } 1234;"), CT(L"for (;;) { print('kill'); } 1234;"), CT(L"foreach (v, i, [1, 2, 3]) { print(e); } 666;"), CT(L"eol = driver == 'win32' && 'crlf' || 'lf';"), CT(L"255 $ '%x';"), CT(L"foreach (e, [1, 2, 3]) { print(e); } 666;"), // CT(L"global v; 1;"), // CT(L"global x, y, z; 2;"), CT(L"sub pi { 3.1416; } 100;"), CT(L"sub pi () { 3.1416; } 200;"), CT(L"sub by2(v) { v * 2; } 250;"), CT(L"sub mul(v1, v2) { v1 * v2; } 300;"), CT(L"mul = sub (v1, v2) { v1 * v2; }; 123;"), CT(L"by2 = sub (e) { e * 2; }; 100;"), CT(L"pi = sub { 3.14; }; 6;"), CT(L"f->write('hi', string(1 + 3), eol); 1;"), CT(L"f->read(); 1;"), CT(L"while (1) 2;"), CT(L"while (1) { 2; 3; }"), CT(L"while (a < 10) { a = a + 1; }"), CT(L"if (a == 1) { b = 2 + 4; c = 3 * 2; } else { d = 3; e = d / 2; }"), CT(L"if (1) 2; else 3;"), CT(L"if (1) { 2; 3; }"), CT(L"if (1) { 2; }"), CT(L"if (1) 2;"), CT(L"if (2 + 3) 4 + 5;"), CT(L"if (a == 1) b = 2;"), CT(L"list[0];"), CT(L"list[1] = 1;"), CT(L"MPSL['OPCODE'];"), CT(L"q = 1 + 2 * 3;"), CT(L"q.q = 1 * 2 + 3; q2 = [];"), CT(L"q = 100;"), CT(L"MPSL.CORE.random;"), CT(L"1 + 2; [1, 2] ; {};"), CT(L"a + 1;"), CT(L"1 * (2 + 3);"), CT(L"{};"), CT(L"{a: 1};"), CT(L"{c: 2, d: 3};"), CT(L"{'e' => 4, 'f' => 5};"), CT(L"{g: 6, 'h' => 7};"), CT(L"{a: 2 * 3, b: 5 + 8};"), CT(L"[];"), CT(L"[1, 2, 3];"), CT(L"[1, 2 + 3, 4];"), CT(L"MPSL.CORE.random();"), CT(L"bool(1, 2) + 666;"), CT(L"1 ; 2 ; 3;"), CT(L"random();"), CT(L"5 != '5';"), CT(L"10 == '10';"), CT(L"10 > 1 + 2;"), CT(L"1 + 2 * 3;"), CT(L"1 * 2 + 3;"), CT(L"1.2 + 3.4;"), CT(L"/* test test */"), CT(L"1;"), CT(L"!1;"), CT(L"'abcde';"), CT(L"3.14;"), CT(NULL) }; printf("\nComparing the output of the two compilers:\n"); r = mpdm_get_wcs(mpdm_root(), L"MPSL"); cc = mpdm_get_wcs(r, L"c_compiler"); ac = mpdm_get_wcs(r, L"a_compiler"); for (n = 0; compiler_tests[n].code; n++) { mpdm_t c, x1, x2, d1, d2; c = MPDM_S(compiler_tests[n].code); mpdm_ref(c); mpdm_set_wcs(r, cc, L"compiler"); x1 = mpsl_compile(c, NULL); d1 = mpsl_decompile(x1); mpdm_set_wcs(r, ac, L"compiler"); x2 = mpsl_compile(c, NULL); d2 = mpsl_decompile(x2); /* printf("%ls\n", mpdm_string(d1)); printf("%ls\n", mpdm_string(d2));*/ _do_test("compiler output equal", mpdm_cmp(d1, d2) == 0, compiler_tests[n].line); mpdm_unref(c); } mpdm_set_wcs(r, cc, L"compiler"); }
void do_set(mpdm_t * v1, mpdm_t v2) { mpdm_ref(v2); mpdm_unref(*v1); *v1 = v2; }
void test_mpsl2(void) { mpdm_t v; mpdm_t w; /* execution tests */ v = do_test_mpsl("666;"); mpdm_dump(v); v = do_test_exec(v, NULL); do_test("literal number", mpdm_ival(v) == 666); v = do_test_mpsl("\"goodbye\";"); v = do_test_exec(v, NULL); do_test("literal string", mpdm_cmp(v, MPDM_S(L"goodbye")) == 0); v = do_test_mpsl("1 + 3 + 5;"); v = do_test_exec(v, NULL); do_test("mpsl calculator 1", mpdm_rval(v) == 9.0); v = do_test_mpsl("1 + ((3 - 5) * 8);"); v = do_test_exec(v, NULL); do_test("mpsl calculator 2", mpdm_rval(v) == -15.0); /* next value cannot be tested as an exact equality, as rounding errors will manifest */ v = do_test_mpsl("1.5 + ((3.1 - 5.8) * 8.0);"); v = do_test_exec(v, NULL); do_test("mpsl calculator 3", mpdm_rval(v) < -20.0 && mpdm_rval(v) > -21.0); v = do_test_mpsl("2 + 3 * 4;"); v = do_test_exec(v, NULL); do_test("mpsl calculator 4", mpdm_rval(v) == 14.0); v = do_test_mpsl("2 * 3 + 4;"); v = do_test_exec(v, NULL); do_test("mpsl calculator 5", mpdm_rval(v) == 10.0); v = do_test_exec(do_test_mpsl("2 + 3 * 4;"), NULL); mpdm_ref(v); w = do_test_exec(do_test_mpsl("2 + (3 * 4);"), NULL); do_test("mpsl calculator 6 (operator precedence)", mpdm_rval(v) == mpdm_rval(w)); mpdm_unref(v); v = do_test_exec(do_test_mpsl("2 + 3 * 4;"), NULL); mpdm_ref(v); w = do_test_exec(do_test_mpsl("(2 + 3) * 4;"), NULL); do_test("mpsl calculator 7 (operator precedence)", mpdm_rval(v) != mpdm_rval(w)); mpdm_unref(v); v = do_test_mpsl("/* array */ [\"this\", \"one\", \"is\", 666, \"cool\"];"); v = do_test_exec(v, NULL); mpdm_dump(v); do_test("mpsl array", mpdm_ival(mpdm_get_i(v, 3)) == 666); v = do_test_mpsl ("/* hash */ { \"enero\" => \"january\", \"febrero\" => \"february\" };"); v = do_test_exec(v, NULL); mpdm_dump(v); do_test("mpsl hash", mpdm_cmp(mpdm_get(v, MPDM_S(L"febrero")), MPDM_S(L"february")) == 0); v = do_test_mpsl("! 1;"); v = do_test_exec(v, NULL); do_test("boolean not 1", !mpdm_is_true(v)); v = do_test_mpsl("! 0;"); v = do_test_exec(v, NULL); do_test("boolean not 2", v != NULL); v = do_test_mpsl("1 && 3;"); v = do_test_exec(v, NULL); do_test("boolean and 1", mpdm_ival(v) == 3); v = do_test_mpsl("1 && 0;"); v = do_test_exec(v, NULL); do_test("boolean and 2", !mpdm_is_true(v)); v = do_test_mpsl("0 && 1;"); v = do_test_exec(v, NULL); do_test("boolean and 3", !mpdm_is_true(v)); v = do_test_mpsl("1 || 3;"); v = do_test_exec(v, NULL); do_test("boolean or 1", mpdm_ival(v) == 1); v = do_test_mpsl("2 || 0;"); v = do_test_exec(v, NULL); do_test("boolean or 2", mpdm_ival(v) == 2); v = do_test_mpsl("0 || 3;"); v = do_test_exec(v, NULL); do_test("boolean or 3", mpdm_ival(v) == 3); v = do_test_mpsl("6 == 6;"); v = do_test_exec(v, NULL); do_test("numeric == 1", v != NULL); v = do_test_mpsl("8.0 == 8.0;"); v = do_test_exec(v, NULL); do_test("numeric == 2", v != NULL); v = do_test_mpsl("6 == 8;"); v = do_test_exec(v, NULL); do_test("numeric == 3", !mpdm_is_true(v)); v = do_test_mpsl("6 != 6;"); v = do_test_exec(v, NULL); do_test("numeric != 1", !mpdm_is_true(v)); v = do_test_mpsl("8.0 != 8.0;"); v = do_test_exec(v, NULL); do_test("numeric != 2", !mpdm_is_true(v)); v = do_test_mpsl("6 != 8;"); v = do_test_exec(v, NULL); do_test("numeric != 3", v != NULL); v = do_test_mpsl("6 < 6;"); v = do_test_exec(v, NULL); do_test("numeric < 1", !mpdm_is_true(v)); v = do_test_mpsl("8 < 6;"); v = do_test_exec(v, NULL); do_test("numeric < 2", !mpdm_is_true(v)); v = do_test_mpsl("5 < 6;"); v = do_test_exec(v, NULL); do_test("numeric < 3", v != NULL); v = do_test_mpsl("6 > 6;"); v = do_test_exec(v, NULL); do_test("numeric > 1", !mpdm_is_true(v)); v = do_test_mpsl("8 > 6;"); v = do_test_exec(v, NULL); do_test("numeric > 2", v != NULL); v = do_test_mpsl("5 > 6;"); v = do_test_exec(v, NULL); do_test("numeric > 3", !mpdm_is_true(v)); v = do_test_mpsl("6 <= 6;"); v = do_test_exec(v, NULL); do_test("numeric <= 1", v != NULL); v = do_test_mpsl("8 <= 6;"); v = do_test_exec(v, NULL); do_test("numeric <= 2", !mpdm_is_true(v)); v = do_test_mpsl("5 <= 6;"); v = do_test_exec(v, NULL); do_test("numeric <= 3", v != NULL); v = do_test_mpsl("6 >= 6;"); v = do_test_exec(v, NULL); do_test("numeric >= 1", v != NULL); v = do_test_mpsl("8 >= 6;"); v = do_test_exec(v, NULL); do_test("numeric >= 2", v != NULL); v = do_test_mpsl("5 >= 6;"); v = do_test_exec(v, NULL); do_test("numeric >= 3", !mpdm_is_true(v)); v = do_test_mpsl("11 % 6;"); v = do_test_exec(v, NULL); do_test("modulo", mpdm_ival(v) == 5); v = do_test_mpsl("variable=16384;"); mpdm_dump(v); v = do_test_exec(v, NULL); do_test("assign 1", mpdm_ival(v) == 16384); v = do_test_mpsl("array=[10, 20, 30, 40];"); v = do_test_exec(v, NULL); do_test("assign 2", mpdm_ival(mpdm_get_i(v, 2)) == 30); v = do_test_mpsl("a=1; b=2; c=3;"); mpdm_dump(v); v = do_test_exec(v, NULL); v = do_test_mpsl("CACHE={}; CACHE.regex=[]; CACHE.regex[0]=12345;"); v = do_test_exec(v, NULL); v = do_test_mpsl("variable;"); v = do_test_exec(v, NULL); do_test("symval 1", mpdm_ival(v) == 16384); v = do_test_mpsl("variable2=1 + ((3 - 5) * 8); variable2;"); mpdm_dump(v); v = do_test_exec(v, NULL); do_test("symval 2", mpdm_rval(v) == -15); v = do_test_mpsl("variable3=variable2 * 2;"); v = do_test_exec(v, NULL); do_test("symval 3", mpdm_ival(v) == -30); v = do_test_mpsl("sub mysum(a, b) { a + b; }"); mpdm_dump(v); v = do_test_exec(v, NULL); do_test("sub 1", v != NULL); v = do_test_mpsl("sub pi() { 3.1416; }"); mpdm_dump(v); v = do_test_exec(v, NULL); do_test("sub 2", v != NULL); v = do_test_mpsl("var10=pi();"); v = do_test_exec(v, NULL); do_test("exec 1", mpdm_rval(v) == 3.1416); v = do_test_mpsl("var11=pi() * 10000; var11;"); v = do_test_exec(v, NULL); do_test("exec 2", mpdm_rval(v) == 31416); v = do_test_mpsl("mysum(100, 20);"); v = do_test_exec(v, NULL); do_test("exec 3", mpdm_rval(v) == 120.0); v = do_test_mpsl("a = NULL;"); v = do_test_exec(v, NULL); do_test("NULL 1", v == NULL); v = do_test_mpsl("a == NULL;"); v = do_test_exec(v, NULL); do_test("NULL 2", mpdm_ival(v) == 1); v = do_test_mpsl("local a, b; a = 1; b = 2;"); v = do_test_exec(v, NULL); v = do_test_mpsl("a == NULL;"); v = do_test_exec(v, NULL); do_test("local 1", mpdm_ival(v) == 1); v = do_test_mpsl("66 * -1;"); v = do_test_exec(v, NULL); do_test("uminus", mpdm_ival(v) == -66); v = do_test_mpsl("\"test\" eq \"test\";"); v = do_test_exec(v, NULL); do_test("streq 1", mpdm_is_true(v)); v = do_test_mpsl("\"test\" eq \"prueba\";"); v = do_test_exec(v, NULL); do_test("streq 1", !mpdm_is_true(v)); v = do_test_mpsl("a = 6; ++ a;"); v = do_test_exec(v, NULL); do_test("pinc", mpdm_ival(v) == 7); v = do_test_mpsl("a++;"); v = do_test_exec(v, NULL); do_test("sinc", mpdm_ival(v) == 7); v = do_test_mpsl("a += 10;"); v = do_test_exec(v, NULL); do_test("iadd", mpdm_ival(v) == 18); v = do_test_mpsl("local a, b, c; a=1; b=2; c=3; if(a == b) c=1000; c;"); v = do_test_exec(v, NULL); do_test("if 1", mpdm_ival(v) == 3); v = do_test_mpsl("local a, b, c; a=1; b=2; c=3; if(a <= b) c=1000; c;"); v = do_test_exec(v, NULL); do_test("if 2", mpdm_ival(v) == 1000); v = do_test_mpsl("local a, b, c; a=1; b=2; if(a == b) c=1000; else c=2000; c;"); v = do_test_exec(v, NULL); do_test("ifelse", mpdm_ival(v) == 2000); v = do_test_mpsl("local a; a = 0; while(a < 100) { a++; } a;"); v = do_test_exec(v, NULL); do_test("ifelse", mpdm_ival(v) == 100); v = do_test_mpsl("a=mysum(100, 50); a;"); v = do_test_exec(v, NULL); do_test("mysum 1", mpdm_ival(v) == 150); v = do_test_mpsl("a=mysum(2000, 500); a;"); v = do_test_exec(v, NULL); do_test("mysum 2", mpdm_ival(v) == 2500); w = mpdm_ref(MPDM_A(2)); mpdm_set_i(w, MPDM_I(100), 0); mpdm_set_i(w, MPDM_I(50), 1); /* asks for the value of the mysum symbol (the code) */ v = do_test_mpsl("mysum;"); /* executes, so mysum() itself is being returned */ v = do_test_exec(v, NULL); mpdm_dump(v); do_test("mysum 3", mpdm_ival(do_test_exec(v, w)) == 150); mpdm_set_i(w, MPDM_I(75), 1); do_test("mysum 4", mpdm_ival(do_test_exec(v, w)) == 175); /* compiles (and executes) the definition of gcd() */ v = do_test_mpsl ("/* greatest common divisor (Euclid's algorithm) */ sub gcd(m, n) { while (m > 0) { if(n > m) { local t = m; m = n; n = t; } m -= n; } n; }"); do_test_exec(v, NULL); /* gets a pointer to gcd() */ v = do_test_exec(do_test_mpsl("gcd;"), NULL); mpdm_dump(v); /* executes gcd(100, 50); */ mpdm_set_i(w, MPDM_I(50), 1); do_test("gcd() 1", mpdm_ival(do_test_exec(v, w)) == 50); /* executes gcd(100, 75); */ mpdm_set_i(w, MPDM_I(75), 1); do_test("gcd() 2", mpdm_ival(do_test_exec(v, w)) == 25); mpdm_unref(w); /* string concatenation */ w = mpdm_ref(MPDM_S(L"big lebowski")); v = do_test_mpsl("\"big\" ~ \" lebowski\";"); do_test("~ (strcat 1)", mpdm_cmp(do_test_exec(v, NULL), w) == 0); v = do_test_mpsl("\"big\" ~ \" \" ~ \"lebowski\";"); do_test("~ (strcat 2)", mpdm_cmp(do_test_exec(v, NULL), w) == 0); mpdm_unref(w); }