diff --git a/builtins.c b/builtins.c index 7dba1aa..5186e8b 100644 --- a/builtins.c +++ b/builtins.c @@ -12,13 +12,14 @@ 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); const func_t indent_up[IUP_COUNT] = { ifunc_if, ifunc_do, ifunc_label }; const func_t indent_down[IDOWN_COUNT] = { - ifunc_end, ifunc_while + ifunc_else, ifunc_end, ifunc_while, }; void iload_core(interpreter *interp) @@ -30,6 +31,7 @@ void iload_core(interpreter *interp) inew_cfunc(interp, "do", ifunc_do); inew_cfunc(interp, "while", ifunc_while); inew_cfunc(interp, "ret", ifunc_ret); + inew_cfunc(interp, "else", ifunc_else); } int ifunc_set(interpreter *it) @@ -65,9 +67,10 @@ int ifunc_if(interpreter *it) int v = igetarg(it, 0)->value.p; if (v == 0) iskip(it); - void *tmp = ipop(it); + void *arg = ipop(it); + ipush(it, (void *)v); ipush(it, (void *)-1); - ipush(it, tmp); + ipush(it, arg); return 0; } @@ -77,8 +80,33 @@ int ifunc_end(interpreter *it) return 0; uint32_t lnidx = (uint32_t)ipop(it) + 1; - if (lnidx != 0) + if (lnidx == 0) { // from an if, have conditional + ipop(it); // whatever + } else { + if (lnidx == (uint32_t)-1) { + // script-func call + lnidx = (uint32_t)ipop(it); + it->indent = (uint32_t)ipop(it); + } it->lnidx = 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, 0); + ipush(it, (void *)-1); + return 0; } diff --git a/builtins.h b/builtins.h index 9d18093..5c8e350 100644 --- a/builtins.h +++ b/builtins.h @@ -4,7 +4,7 @@ #include "parser.h" #define IUP_COUNT 3 -#define IDOWN_COUNT 2 +#define IDOWN_COUNT 3 void iload_core(interpreter *it); diff --git a/ops.c b/ops.c index cb07093..5267b6f 100644 --- a/ops.c +++ b/ops.c @@ -1,5 +1,7 @@ #include "ops.h" +#include + void iop_add(variable *, variable *, variable *); void iop_sub(variable *, variable *, variable *); void iop_mult(variable *, variable *, variable *); @@ -18,15 +20,15 @@ void iop_ne(variable *, variable *, variable *); void iop_mod(variable *, variable *, variable *); char *iops[IOPS_COUNT] = { - "+", "-", "*", "/", "&", "|", "^", ">>", "<<", - "==", "<", ">", "<=", ">=", "!=", "%" + "*", "/", "%", "+", "-", "<<", ">>", "<=", + "<", ">=", ">", "==", "!=", "&", "^", "|" }; operation_t iopfuncs[IOPS_COUNT] = { - iop_add, iop_sub, iop_mult, iop_div, iop_and, - iop_or, iop_xor, iop_shr, iop_shl, - iop_eq, iop_lt, iop_gt, iop_lte, iop_gte, iop_ne, - iop_mod + iop_mult, iop_div, iop_mod, iop_add, iop_sub, + iop_shl, iop_shr, iop_lte, iop_lt, iop_gte, + iop_gt, iop_eq, iop_ne, iop_and, iop_xor, + iop_or }; @@ -77,7 +79,10 @@ void iop_shl(variable *r, variable *a, variable *b) void iop_eq(variable *r, variable *a, variable *b) { - r->value.f = a->value.f == b->value.f; + if (a->valtype == STRING && b->valtype == STRING) + r->value.f = (float)!strcmp((char *)a->value.p, (char *)b->value.p); + else + r->value.f = a->value.f == b->value.f; } void iop_lt(variable *r, variable *a, variable *b) diff --git a/parser.c b/parser.c index 3311d5c..d7ba5ac 100644 --- a/parser.c +++ b/parser.c @@ -10,7 +10,7 @@ #include #include -#define MAX_VARS 64 +#define MAX_VARS 100 #define MAX_STACK 32 #define MAX_LINES 1000 @@ -100,9 +100,9 @@ variable *inew_string(interpreter *interp, const char *name, const char *value) { variable *v = interpreter_get_variable(interp, name); if (v != 0) { - v->valtype = STRING; - if (v->value.p != 0) + if (v->valtype == STRING && v->value.p != 0) free((void *)v->value.p); + v->valtype = STRING; v->value.p = (uint32_t)strclone(value); } return v; @@ -326,7 +326,9 @@ cont: } } - ipush(interp, (void *)(interp->lnidx)); + ipush(interp, (void *)(uint32_t)interp->indent); + ipush(interp, (void *)interp->lnidx); + ipush(interp, (void *)-2); // magic interp->lnidx = ops[0]->value.p; interp->indent++; } @@ -365,6 +367,8 @@ variable *idoexpr(interpreter *interp, const char *line) uint32_t next = 0; // step 1 - break apart line + for (uint8_t i = 0; i < 16; i++) + ops[i] = 0; // skip whitespace skipblank(line, eol, &offset); @@ -429,21 +433,52 @@ variable *idoexpr(interpreter *interp, const char *line) return 0; // step 2 - do operations - variable *result = (variable *)calloc(1, sizeof(variable)); - result->valtype = ((variable *)ops[0])->valtype; - result->value.p = ((variable *)ops[0])->value.p; - for (uint32_t i = 1; i < ooffset; i += 2) - iopfuncs[(uint32_t)ops[i] - 1](result, result, ops[i + 1]); - - for (uint32_t i = 0; i < ooffset; i += 2) { - variable *v = (variable *)ops[i]; - if (!v->used) { - if (v->valtype == STRING || v->valtype == EXPR) - free((void *)v->value.p); - free(ops[i]); + // for every operator, ordered by importance + for (uint32_t i = 0; i < IOPS_COUNT; i++) { + // find instances of the operation + for (uint32_t j = 1; j < ooffset; j += 2) { + // if a match + if ((uint32_t)ops[j] == i + 1) { + // find args + uint32_t ai = j - 1; + uint32_t bi = j + 1; + while (ops[ai] == 0) + ai--; + while (ops[bi] == 0) + bi++; + + variable *r = (variable *)calloc(1, sizeof(variable)); + iopfuncs[i](r, ops[ai], ops[bi]); + + variable *v = (variable *)ops[ai]; + if (!v->used) + free(v); + ops[ai] = r; + v = (variable *)ops[bi]; + if (!v->used) + free(v); + ops[bi] = 0; + ops[j] = 0; + } } } + variable *result = make_varn(0, ((variable *)ops[0])->value.f); + if (!((variable *)ops[0])->used) + free(ops[0]); + + //for (uint32_t i = 1; i < ooffset; i += 2) + // iopfuncs[(uint32_t)ops[i] - 1](result, result, ops[i + 1]); + + //for (uint32_t i = 0; i < ooffset; i += 2) { + // variable *v = (variable *)ops[i]; + // if (!v->used) { + // if (v->valtype == STRING || v->valtype == EXPR) + // free((void *)v->value.p); + // free(ops[i]); + // } + //} + return result; }