From 7f64da46ffe3b2e2a2b46a3dd2effc4f4f7d45da Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Fri, 13 Apr 2018 08:43:47 -0400 Subject: [PATCH] arrays, implicit multiply --- builtins.c | 18 ++++++++- ops.c | 107 +++++++++++++++++++++++++++++++++-------------------- ops.h | 4 +- parser.c | 30 +++++++++++++-- test7 | 14 +++++++ test8 | 17 +++++++++ test9 | 7 ++++ variable.h | 1 + 8 files changed, 150 insertions(+), 48 deletions(-) create mode 100644 test7 create mode 100644 test8 create mode 100644 test9 diff --git a/builtins.c b/builtins.c index 73ce360..e3be39c 100644 --- a/builtins.c +++ b/builtins.c @@ -42,11 +42,11 @@ #define FUNC_SIG (uint32_t)-4 variable bopen = { - 0, CFUNC, 0, {.p = (uint32_t)bracket_open} + 0, CFUNC, 0, 0, {.p = (uint32_t)bracket_open} }; variable bclose = { - 0, CFUNC, 0, {.p = (uint32_t)bracket_close} + 0, CFUNC, 0, 0, {.p = (uint32_t)bracket_close} }; int bn_if(instance *it); @@ -55,6 +55,7 @@ int bn_end(instance *it); int bn_while(instance *it); int bn_func(instance *it); int bn_solve(instance *it); +int bn_array(instance *it); void iload_builtins(instance *it) { @@ -63,6 +64,7 @@ void iload_builtins(instance *it) inew_cfunc(it, "while", bn_while); inew_cfunc(it, "func", bn_func); inew_cfunc(it, "solve", bn_solve); + inew_cfunc(it, "array", bn_array); } /** @@ -187,3 +189,15 @@ int bn_solve(instance *it) return 0; } +int bn_array(instance *it) +{ + variable *a = igetarg(it, 0); + int size = igetarg(it, 1)->value.f; + uint32_t i0 = a->value.p; + variable *array = calloc(size, sizeof(variable)); + array[0].type = a->type; + array[0].value.p = i0; + a->array = size; + a->value.p = (uint32_t)array; + return 0; +} diff --git a/ops.c b/ops.c index 8e6cc66..f79503f 100644 --- a/ops.c +++ b/ops.c @@ -35,10 +35,11 @@ #include -#define OP_DEF(o) int op_##o(variable *r, variable *a, variable *b) -#define OP_VAR(o) {0, OPERATOR, 0, {.p = (uint32_t)op_##o}} -#define OP_NONE {0, OPERATOR, 0, {.p = 0x0BADCAFE}} +#define OP_DEF(o) int op_##o(variable **r, variable *a, variable *b) +#define OP_VAR(o) {0, OPERATOR, 0, 0, {.p = (uint32_t)op_##o}} +#define OP_NONE {0, OPERATOR, 0, 0, {.p = 0x0BADCAFE}} +OP_DEF(idx); OP_DEF(mul); OP_DEF(div); OP_DEF(mod); @@ -67,6 +68,7 @@ OP_DEF(set); * priority, they will be evaluated from left-to-right by the parser. */ variable opvars[] = { + OP_VAR(idx), OP_NONE, OP_VAR(mul), OP_VAR(div), OP_VAR(mod), OP_NONE, OP_VAR(add), OP_VAR(sub), OP_VAR(shl), OP_VAR(shr), OP_VAR(lte), OP_VAR(lt), OP_VAR(gte), OP_VAR(gt), @@ -75,6 +77,7 @@ variable opvars[] = { }; const char *opnames[] = { + ".", 0, "*", "/", "%", 0, "+", "-", "<<", ">>", "<=", "<", ">=", ">", @@ -97,103 +100,125 @@ variable *igetop(const char *name, int *retlen) return 0; } +OP_DEF(idx) +{ + if (a->array == 0) + return seterror(EBADPARAM); + + extern void itryfree(variable *); + itryfree(*r); + + int idx = b->value.f; + if (idx >= a->array) { + variable *newarray = calloc(idx + 1, sizeof(variable)); + void *old = (void *)a->value.p; + a->value.p = (uint32_t)memcpy(newarray, (variable *)a->value.p, + a->array * sizeof(variable)); + free(old); + a->array = idx + 1; + } + + variable *array = (variable *)a->value.p; + *r = &array[idx]; + return 0; +} OP_DEF(mul) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = a->value.f * b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = a->value.f * b->value.f; return 0; } OP_DEF(div) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = a->value.f / b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = a->value.f / b->value.f; return 0; } OP_DEF(mod) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = (int)a->value.f % (int)b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = (int)a->value.f % (int)b->value.f; return 0; } OP_DEF(add) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = a->value.f + b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = a->value.f + b->value.f; return 0; } OP_DEF(sub) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = a->value.f - b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = a->value.f - b->value.f; return 0; } OP_DEF(shl) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = (int)a->value.f << (int)b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = (int)a->value.f << (int)b->value.f; return 0; } OP_DEF(shr) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = (int)a->value.f >> (int)b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = (int)a->value.f >> (int)b->value.f; return 0; } OP_DEF(lte) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = a->value.f <= b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = a->value.f <= b->value.f; return 0; } OP_DEF(lt) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = a->value.f < b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = a->value.f < b->value.f; return 0; } OP_DEF(gte) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = a->value.f >= b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = a->value.f >= b->value.f; return 0; } OP_DEF(gt) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = a->value.f > b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = a->value.f > b->value.f; return 0; } OP_DEF(eq) { - r->type = NUMBER; + (*r)->type = NUMBER; if (a->type == NUMBER && b->type == NUMBER) - r->value.f = a->value.f == b->value.f; + (*r)->value.f = a->value.f == b->value.f; else if (a->type == STRING && b->type == STRING) - r->value.f = !strcmp((const char *)a->value.p, (const char *)b->value.p); + (*r)->value.f = !strcmp((const char *)a->value.p, (const char *)b->value.p); else - r->value.f = 0.0f; // *sshhh* + (*r)->value.f = 0.0f; // *sshhh* //return seterror(EBADPARAM); return 0; @@ -202,32 +227,32 @@ OP_DEF(ne) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = a->value.f != b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = a->value.f != b->value.f; return 0; } OP_DEF(and) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = (int)a->value.f & (int)b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = (int)a->value.f & (int)b->value.f; return 0; } OP_DEF(xor) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = (int)a->value.f ^ (int)b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = (int)a->value.f ^ (int)b->value.f; return 0; } OP_DEF(or) { if (a->type != NUMBER || b->type != NUMBER) return seterror(EBADPARAM); - r->type = NUMBER; - r->value.f = (int)a->value.f | (int)b->value.f; + (*r)->type = NUMBER; + (*r)->value.f = (int)a->value.f | (int)b->value.f; return 0; } OP_DEF(set) @@ -235,14 +260,14 @@ OP_DEF(set) if (b->type == NUMBER) { a->type = NUMBER; a->value.f = b->value.f; - r->type = NUMBER; - r->value.f = a->value.f; + (*r)->type = NUMBER; + (*r)->value.f = a->value.f; } else if (b->type == STRING) { a->type = STRING; free((void *)a->value.p); a->value.p = (uint32_t)strclone((char *)b->value.p); - r->type = STRING; - r->value.p = (uint32_t)strclone((char *)a->value.p); + (*r)->type = STRING; + (*r)->value.p = (uint32_t)strclone((char *)a->value.p); } else { return seterror(EBADPARAM); } diff --git a/ops.h b/ops.h index 4257f07..62e3821 100644 --- a/ops.h +++ b/ops.h @@ -26,11 +26,11 @@ /** * Defines the number of available operators. */ -#define OPS_COUNT 18 +#define OPS_COUNT 20 #define OP_MAGIC 0xCAFE3900 -typedef int (*opfunc_t)(variable *, variable *, variable *); +typedef int (*opfunc_t)(variable **, variable *, variable *); /** * An array of variable objects for each operator, exposed for the parser. diff --git a/parser.c b/parser.c index 691e296..2ae390b 100644 --- a/parser.c +++ b/parser.c @@ -46,8 +46,9 @@ void itryfree(variable *v) { if (v == 0 || v->tmp == 0) return; - if (v->type == STRING) + if (v->type == STRING)// || v->array > 0) free((void *)v->value.p); + free(v); } @@ -87,7 +88,7 @@ void idelinstance(instance *it) free(it->lines); for (uint32_t i = 0; i < MAX_VARS; i++) { - if (it->vars[i].type == STRING) + if (it->vars[i].type == STRING || it->vars[i].array > 0) free((void *)it->vars[i].value.p); free(it->names[i]); } @@ -356,7 +357,7 @@ variable *isolve_(instance *it, variable **ops, uint32_t count) if (!(it->sindent & SKIP)) { variable *v = !ops[aidx]->tmp ? make_varf(0, 0.0f) : ops[aidx]; - if (func(v, ops[aidx], ops[bidx]) != 0) + if (func(&v, ops[aidx], ops[bidx]) != 0) return 0; ops[aidx] = v; } else { @@ -387,6 +388,7 @@ variable **iparse(instance *it, const char *s) uint32_t ooffset = 0; int32_t boffset = 1; size_t offset = 0; + uint8_t prevNum = 0; // advance to first character // and insure there's runnable script on the line @@ -442,6 +444,8 @@ variable **iparse(instance *it, const char *s) ops[argidx] = (variable *)argcount; } else if (ops[ooffset - 1]->type == FUNC || ops[ooffset - 1]->type == CFUNC) { ops[ooffset++] = (variable *)1; + } else { + prevNum += 2; } offset = end; } else if (isdigit(s[offset])) {// || (s[offset] == '-' && isdigit(s[offset + 1]))) { @@ -452,6 +456,7 @@ variable **iparse(instance *it, const char *s) ops[ooffset++] = make_num(word); free(word); offset = end; + prevNum += 2; } else if (s[offset] == '\"') { size_t end = offset + 1; while (s[end] != '\"')// && s[end - 1] == '\\') @@ -483,6 +488,15 @@ variable **iparse(instance *it, const char *s) free(word); ops[parenidx] = (variable *)(OP_MAGIC | count); offset = i; + prevNum += 2; + } else if (s[offset] == '[') { + /*uint32_t i = offset + 1; + uint32_t j = i; + while (s[offset] != ']') { + if (s[offset] == ';') { + + } + }*/ } else if (!isblank(s[offset])) { if (s[offset] == '{' || s[offset] == '}') { for (int32_t i = ooffset - 1; i >= boffset - 1; i--) @@ -513,6 +527,16 @@ variable **iparse(instance *it, const char *s) } else { offset++; } + + if (prevNum > 0) { + if (--prevNum == 2) { + --prevNum; + variable *mul = igetop("*", 0); + ops[ooffset] = ops[ooffset - 1]; + ops[ooffset - 1] = mul; + ooffset++; + } + } } // mark end diff --git a/test7 b/test7 new file mode 100644 index 0000000..dd4defb --- /dev/null +++ b/test7 @@ -0,0 +1,14 @@ +j = 6 + +func(test) { + i = 0 + while (i < 10) { + i = i + 1 + } + + j = 15 +} + +print(i) +print(" ") +print(j) diff --git a/test8 b/test8 new file mode 100644 index 0000000..8081b4c --- /dev/null +++ b/test8 @@ -0,0 +1,17 @@ +array(a, 10) + +i = 0 +while (i < 10) { + a.i = i * 2 + i = i + 1 +} + +i = 0 +while (i < 10) { + print(a.i) + i = i + 1 +} + +a.20 = 143 +print(a.20) +print(a.19) diff --git a/test9 b/test9 new file mode 100644 index 0000000..3cfcd55 --- /dev/null +++ b/test9 @@ -0,0 +1,7 @@ +x = 9 +print(3x) +print(2x + 5) +print(x - 9x) +print(5 + (3x)) +print((x - 4 * 5)2) + diff --git a/variable.h b/variable.h index 0c4f584..e40d102 100644 --- a/variable.h +++ b/variable.h @@ -31,6 +31,7 @@ typedef struct { uint8_t tmp :1; /**< If zero, variable cannot be free'd */ uint8_t type :3; /**< The variable's type */ uint8_t unused :4; /**< Unused... */ + uint8_t array; /**< ">0?" -> array w/ this size */ union { float f; uint32_t p;