aboutsummaryrefslogtreecommitdiffstats
path: root/builtins.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtins.c')
-rw-r--r--builtins.c225
1 files changed, 85 insertions, 140 deletions
diff --git a/builtins.c b/builtins.c
index 0ab6f3b..ea1cc95 100644
--- a/builtins.c
+++ b/builtins.c
@@ -1,179 +1,124 @@
#include "builtins.h"
-#include "stack.h"
-#include "shelpers.h"
-
-#include <memory.h>
-#include <string.h>
-
-int ifunc_set(interpreter *it);
-int ifunc_label(interpreter *it);
-int ifunc_end(interpreter *it);
-int ifunc_if(interpreter *it);
-int ifunc_do(interpreter *it);
-int ifunc_while(interpreter *it);
-int ifunc_ret(interpreter *it);
-int ifunc_else(interpreter *it);
-int ifunc_solve(interpreter *it);
-
-const func_t indent_up[IUP_COUNT] = {
- ifunc_if, ifunc_do, ifunc_label
-};
-
-const func_t indent_down[IDOWN_COUNT] = {
- ifunc_else, ifunc_end, ifunc_while,
-};
-
-void iload_core(interpreter *interp)
+
+#include <stdlib.h>
+
+#define IF_SIG (uint32_t)-1
+#define WHILE_SIG (uint32_t)-2
+#define ELSE_SIG (uint32_t)-3
+#define FUNC_SIG (uint32_t)-4
+
+int bn_set(instance *it);
+int bn_if(instance *it);
+int bn_else(instance *it);
+int bn_end(instance *it);
+int bn_while(instance *it);
+int bn_func(instance *it);
+int bn_solve(instance *it);
+
+void iload_builtins(instance *it)
{
- inew_cfunc(interp, "set", ifunc_set);
- inew_cfunc(interp, "func", ifunc_label);
- inew_cfunc(interp, "end", ifunc_end);
- inew_cfunc(interp, "if", ifunc_if);
- inew_cfunc(interp, "do", ifunc_do);
- inew_cfunc(interp, "while", ifunc_while);
- inew_cfunc(interp, "ret", ifunc_ret);
- inew_cfunc(interp, "else", ifunc_else);
- inew_cfunc(interp, "solve", ifunc_solve);
+ inew_cfunc(it, "set", bn_set);
+ inew_cfunc(it, "if", bn_if);
+ inew_cfunc(it, "else", bn_else);
+ inew_cfunc(it, "while", bn_while);
+ inew_cfunc(it, "func", bn_func);
+ inew_cfunc(it, "solve", bn_solve);
}
-int ifunc_solve(interpreter *it)
+int bn_set(instance *it)
{
- const char *expr = igetarg_string(it, 0);
- int len = strlen(expr);
- char *buf = (char *)malloc(len + 2);
- strcpy(buf, expr);
- buf[len] = ')';
- buf[len + 1] = '\0';
- variable *r = idoexpr(it, buf);
- free(buf);
- if (r == 0)
- r = make_varn(0, 0.0f);
- iret(it, r);
- free(r);
+ variable *var = igetarg(it, 0);
+ variable *value = igetarg(it, 1);
+ var->type = value->type;
+ var->value.p = value->value.p;
+ ipush(it, (uint32_t)var);
return 0;
}
-int ifunc_set(interpreter *it)
+int bn_if(instance *it)
{
- variable *n = igetarg(it, 0);
- variable *v = igetarg(it, 1);
+ variable *cond = (variable *)ipop(it);
+ uint32_t result = cond->value.p;
- if (n == 0)
- return -1;
+ ipush(it, result);
+ ipush(it, IF_SIG);
+ if (result == 0)
+ it->sindent = SKIP | it->indent;
+ ipush(it, 0);
+ ipush(it, 0); // need to return because stack modify
- if (n->valtype == STRING)
- free((void *)n->value.p);
- n->valtype = v->valtype;
- n->value.p = v->value.p;
return 0;
}
-int ifunc_label(interpreter *it)
+static uint32_t if_cond = 0;
+int bn_else(instance *it)
{
- variable *n = igetarg(it, 0);
-
- if (n == 0)
- return -1;
-
- n->valtype = FUNC;
- n->value.p = it->lnidx;
- iskip(it);
+ uint32_t cond = if_cond;
+ if (cond != 0)
+ it->sindent = SKIP | it->indent;
+ ipush(it, ELSE_SIG);
+ ipush(it, 0); // for ret
return 0;
}
-int ifunc_if(interpreter *it)
+int bn_end(instance *it)
{
- int v = igetarg(it, 0)->value.p;
- if (v == 0)
- iskip(it);
- void *arg = ipop(it);
- ipush(it, (void *)v);
- ipush(it, (void *)-1);
- ipush(it, arg);
- return 0;
+ uint32_t sig = ipop(it);
+ if (sig == IF_SIG) {
+ if_cond = ipop(it);
+ } else if (sig == WHILE_SIG) {
+ uint32_t lnidx = ipop(it);
+ if (lnidx != (int32_t)-1)
+ it->lnidx = lnidx - 1;
+ } else if (sig == CALL_SIG) {
+ it->lnidx = ipop(it);
+ it->indent++;
+ }
+ return 0;
}
-int ifunc_end(interpreter *it)
+int bn_while(instance *it)
{
- if (it->stidx == 0)
- return 0;
+ variable *cond = (variable *)ipop(it);
+ uint32_t result = cond->value.p;
- uint32_t lnidx = (uint32_t)ipop(it) + 1;
- if (lnidx == 0) { // from an if, have conditional
- ipop(it); // whatever
+ if (result == 0) {
+ it->sindent = SKIP | it->indent;
+ ipush(it, (uint32_t)-1);
} else {
- if (lnidx == (uint32_t)-1) {
- // script-func call
- lnidx = (uint32_t)ipop(it);
- it->indent = (uint32_t)ipop(it);
- }
- it->lnidx = lnidx;
+ ipush(it, it->lnidx);
}
- return 0;
-}
-
-int ifunc_else(interpreter *it)
-{
- if (it->stidx == 0)
- return 0;
-
- ipop(it); // the -1
- int cond = (int)ipop(it);
- it->indent++;
- if (cond != 0)
- iskip(it);
- // otherwise it's whatever?
+ ipush(it, WHILE_SIG);
ipush(it, 0);
- ipush(it, (void *)-1);
-
+ ipush(it, 0); // need to ret
return 0;
}
-int ifunc_do(interpreter *it)
+int bn_func(instance *it)
{
- ipush(it, (void *)it->lnidx);
- return 0;
-}
+ variable *f = igetarg(it, 0);
+ if (f == 0)
+ return -1;
-int ifunc_while(interpreter *it)
-{
- int c = igetarg(it, 0)->value.p;
- ipop(it);
- int nidx = (int)ipop(it);
- if (c != 0) {
- //ipush(it, (void *)nidx);
- it->lnidx = nidx - 1;
- }
- ipush(it, 0);
+ f->type = FUNC;
+ f->value.p = it->lnidx;
+ it->sindent = SKIP | it->indent;
+ ipush(it, FUNC_SIG);
+ ipush(it, 0); // for ret
return 0;
}
-void iret(interpreter *it, variable *v)
+int bn_solve(instance *it)
{
- switch (v->valtype) {
- case NUMBER:
- inew_number(it, "RET", v->value.f);
- break;
- case STRING:
- inew_string(it, "RET", (char *)v->value.p);
- break;
- default:
- return;
- break;
- }
- if (it->ret != 0) {
- if (it->ret->valtype == STRING && it->ret->value.p != 0)
- free((void *)it->ret->value.p);
- it->ret->valtype = v->valtype;
- it->ret->value.p = v->value.p;
- it->ret = 0;
- }
-}
+ variable *s = igetarg(it, 0);
+ variable **ops = iparse(it, (const char *)s->value.p);
+ if (ops == 0)
+ return -1;
-int ifunc_ret(interpreter *it)
-{
- variable *v = igetarg(it, 0);
- iret(it, v);
+ variable *a = isolve(it, ops, 0);
+ free(ops);
+
+ ipush(it, (uint32_t)a);
return 0;
}