diff options
author | Jo-Philipp Wich <jo@mein.io> | 2020-09-05 14:25:38 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2020-09-06 21:57:26 +0200 |
commit | 88099fdaf55a24854508b7a75d690fa76be6f44a (patch) | |
tree | d333186871ec1719bc03319f358583b655da46f2 | |
parent | b0153864c0cef2f4ba6202a0242f93d607ccbae9 (diff) |
treewide: refactor internal AST structures
- unify operand and value tag structures
- use a contiguous array for storing opcodes
- use relative offsets for next and children ops
- defer function creation to runtime
- rework "this" context handling by storing context pointer in scope tags
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r-- | ast.c | 223 | ||||
-rw-r--r-- | ast.h | 49 | ||||
-rw-r--r-- | eval.c | 403 | ||||
-rw-r--r-- | eval.h | 4 | ||||
-rw-r--r-- | lexer.c | 48 | ||||
-rw-r--r-- | lexer.h | 2 | ||||
-rw-r--r-- | lib.c | 294 | ||||
-rw-r--r-- | lib.h | 6 | ||||
-rw-r--r-- | lib/fs.c | 28 | ||||
-rw-r--r-- | main.c | 24 | ||||
-rw-r--r-- | parser.y | 57 |
11 files changed, 643 insertions, 495 deletions
@@ -15,6 +15,7 @@ */ #include "ast.h" +#include "lib.h" #include "lexer.h" #include "parser.h" @@ -27,65 +28,95 @@ static size_t ut_ext_types_count = 0; static struct ut_extended_type *ut_ext_types = NULL; -struct ut_opcode * +struct ut_op * +ut_get_op(struct ut_state *s, uint32_t off) +{ + if (off == 0 || off > s->poolsize) + return NULL; + + return &s->pool[off - 1]; +} + +struct ut_op * +ut_get_child(struct ut_state *s, uint32_t off, int n) +{ + struct ut_op *op = ut_get_op(s, off); + + if (!op || n >= ARRAY_SIZE(op->tree.operand) || !op->tree.operand[n]) + return NULL; + + return ut_get_op(s, op->tree.operand[n]); +} + +uint32_t ut_new_op(struct ut_state *s, int type, struct json_object *val, ...) { - struct ut_opcode *newop, *child; + struct ut_op *newop, *pool; + uint32_t child; int n_op = 0; va_list ap; - newop = calloc(1, sizeof(*newop)); + if ((s->poolsize + 1) == UINT32_MAX) { + fprintf(stderr, "Program too large\n"); + exit(127); + } + + pool = realloc(s->pool, (s->poolsize + 1) * sizeof(*newop)); - if (!newop) { + if (!pool) { fprintf(stderr, "Out of memory\n"); exit(127); } + newop = &pool[s->poolsize]; + memset(newop, 0, sizeof(*newop)); + + newop->is_first = !s->poolsize; + newop->is_op = true; newop->off = s->off; newop->type = type; newop->val = val; va_start(ap, val); - while ((child = va_arg(ap, void *)) != (void *)1) - if (n_op < sizeof(newop->operand) / sizeof(newop->operand[0])) - newop->operand[n_op++] = child; + while (n_op < ARRAY_SIZE(newop->tree.operand) && (child = va_arg(ap, uint32_t)) != UINT32_MAX) + newop->tree.operand[n_op++] = child; va_end(ap); - newop->next = s->pool; - s->pool = newop; + s->pool = pool; + s->poolsize++; - return newop; + return s->poolsize; } -struct ut_opcode * -ut_wrap_op(struct ut_opcode *parent, ...) +uint32_t +ut_wrap_op(struct ut_state *s, uint32_t parent, ...) { - struct ut_opcode *child; + struct ut_op *op = ut_get_op(s, parent); + uint32_t child; int n_op = 0; va_list ap; va_start(ap, parent); - while ((child = va_arg(ap, void *)) != (void *)1) - if (n_op < sizeof(parent->operand) / sizeof(parent->operand[0])) - parent->operand[n_op++] = child; + while (n_op < ARRAY_SIZE(op->tree.operand) && (child = va_arg(ap, uint32_t)) != UINT32_MAX) + op->tree.operand[n_op++] = child; va_end(ap); return parent; } -struct ut_opcode * -ut_append_op(struct ut_opcode *a, struct ut_opcode *b) +uint32_t +ut_append_op(struct ut_state *s, uint32_t a, uint32_t b) { - struct ut_opcode *tail = a; + struct ut_op *tail = ut_get_op(s, a); - while (tail->sibling) - tail = tail->sibling; + while (tail && tail->tree.next) + tail = ut_get_op(s, tail->tree.next); - tail->sibling = b; + tail->tree.next = b; return a; } @@ -136,69 +167,90 @@ ut_new_null(void) static void obj_free(struct json_object *v, void *ud) { - struct ut_tagvalue *tag = json_object_get_userdata(v); + struct ut_op *op = json_object_get_userdata(v); - json_object_put(tag->proto); + json_object_put(op->tag.proto); free(ud); } struct json_object * ut_new_object(struct ut_state *s, struct json_object *proto) { struct json_object *val = json_object_new_object(); - struct ut_tagvalue *tag; + struct ut_op *op; if (!val) return NULL; - tag = calloc(1, sizeof(*tag)); + op = calloc(1, sizeof(*op)); - if (!tag) { + if (!op) { json_object_put(val); return NULL; } - tag->val = val; - tag->type = T_LBRACE; - tag->proto = json_object_get(proto); + op->val = val; + op->type = T_LBRACE; + op->tag.proto = json_object_get(proto); - json_object_set_serializer(val, NULL, tag, obj_free); + json_object_set_serializer(val, NULL, op, obj_free); - return tag->val; + return op->val; } static int func_to_string(struct json_object *v, struct printbuf *pb, int level, int flags) { - struct ut_opcode *op = json_object_get_userdata(v); - struct ut_opcode *args = op ? op->operand[1] : NULL; - struct json_object *name = (op && op->operand[0]) ? op->operand[0]->val : NULL; + struct ut_op *op = json_object_get_userdata(v); + struct ut_op *base, *decl, *name, *args, *arg; + + if (!op->tag.data) + return 0; + + /* find start of operand array */ + for (decl = op->tag.data, base = decl; base && !base->is_first; base--) + ; + + name = base + (decl->tree.operand[0] ? decl->tree.operand[0] - 1 : 0); + args = base + (decl->tree.operand[1] ? decl->tree.operand[1] - 1 : 0); sprintbuf(pb, "%sfunction%s%s(", - level ? "\"" : "", - name ? " " : "", - name ? json_object_get_string(name) : ""); + level ? "\"" : "", + (name != base) ? " " : "", + (name != base) ? json_object_get_string(name->val) : ""); - while (args) { + for (arg = args; arg != base; arg = base + (arg->tree.next ? arg->tree.next - 1 : 0)) sprintbuf(pb, "%s%s", - (args != op->operand[1]) ? ", " : "", - json_object_get_string(args->val)); - - args = args->sibling; - } + (arg != args) ? ", " : "", + json_object_get_string(arg->val)); - return sprintbuf(pb, ") { ... }%s", - level ? "\"" : ""); + return sprintbuf(pb, ") { ... }%s", level ? "\"" : ""); } -struct ut_opcode * -ut_new_func(struct ut_state *s, struct ut_opcode *name, struct ut_opcode *args, struct ut_opcode *body) +struct json_object * +ut_new_func(struct ut_state *s, struct ut_op *decl) { - struct ut_opcode *op = ut_new_op(s, T_FUNC, json_object_new_boolean(0), name, args, body, (void *)1); + struct json_object *val = json_object_new_object(); + struct ut_op *op; - json_object_set_serializer(op->val, func_to_string, op, NULL); + if (!val) + return NULL; - return op; + op = calloc(1, sizeof(*op)); + + if (!op) { + json_object_put(val); + + return NULL; + } + + op->val = val; + op->type = T_FUNC; + op->tag.data = decl; + + json_object_set_serializer(val, func_to_string, op, obj_free); + + return op->val; } static void @@ -218,7 +270,7 @@ ut_reset(struct ut_state *s) void ut_free(struct ut_state *s) { - struct ut_opcode *op, *tmp; + size_t n; if (s) { while (s->stack.off > 0) @@ -226,14 +278,13 @@ ut_free(struct ut_state *s) free(s->stack.scope); - for (op = s->pool; op;) { - tmp = op->next; + for (n = 0; n < s->poolsize; n++) + json_object_put(s->pool[n].val); - json_object_put(op->val); + free(s->pool); - free(op); - op = tmp; - } + s->pool = NULL; + s->poolsize = 0; ut_reset(s); } @@ -247,9 +298,10 @@ ut_parse(struct ut_state *s, const char *expr) { int len = strlen(expr); const char *ptr = expr; - struct ut_opcode *op; + struct ut_op *op; void *pParser; int mlen = 0; + uint32_t off; if (!s) return UT_ERROR_OUT_OF_MEMORY; @@ -262,7 +314,8 @@ ut_parse(struct ut_state *s, const char *expr) return UT_ERROR_OUT_OF_MEMORY; while (len > 0) { - op = ut_get_token(s, ptr, &mlen); + off = ut_get_token(s, ptr, &mlen); + op = ut_get_op(s, off); if (mlen < 0) { s->error.code = -mlen; @@ -270,7 +323,7 @@ ut_parse(struct ut_state *s, const char *expr) } if (op) - Parse(pParser, op->type, op, s); + Parse(pParser, op->type, off, s); if (s->error.code) goto out; @@ -279,7 +332,7 @@ ut_parse(struct ut_state *s, const char *expr) ptr += mlen; } - Parse(pParser, 0, NULL, s); + Parse(pParser, 0, 0, s); out: ParseFree(pParser, free); @@ -308,32 +361,32 @@ ut_register_extended_type(const char *name, void (*freefn)(void *)) static int ut_extended_type_to_string(struct json_object *v, struct printbuf *pb, int level, int flags) { - struct ut_tagvalue *tag = json_object_get_userdata(v); + struct ut_op *op = json_object_get_userdata(v); struct ut_extended_type *et; - if (!tag) + if (!op) return 0; - et = &ut_ext_types[tag->tagtype - 1]; + et = &ut_ext_types[op->tag.type - 1]; - return sprintbuf(pb, "%s<%s %p>%s", level ? "\"" : "", et->name, tag->data, level ? "\"" : ""); + return sprintbuf(pb, "%s<%s %p>%s", level ? "\"" : "", et->name, op->tag.data, level ? "\"" : ""); } static void ut_extended_type_free(struct json_object *v, void *ud) { - struct ut_tagvalue *tag = json_object_get_userdata(v); + struct ut_op *op = json_object_get_userdata(v); struct ut_extended_type *et; - if (!tag) + if (!op) return; - et = &ut_ext_types[tag->tagtype - 1]; + et = &ut_ext_types[op->tag.type - 1]; if (et->free) - et->free(tag->data); + et->free(op->tag.data); - json_object_put(tag->proto); + json_object_put(op->tag.proto); free(ud); } @@ -341,7 +394,7 @@ struct json_object * ut_set_extended_type(struct ut_state *s, struct json_object *v, struct json_object *proto, const char *name, void *data) { struct ut_extended_type *et = NULL; - struct ut_tagvalue *tag; + struct ut_op *op; size_t n; for (n = 0; n < ut_ext_types_count; n++) { @@ -354,30 +407,30 @@ ut_set_extended_type(struct ut_state *s, struct json_object *v, struct json_obje if (!et) return NULL; - tag = calloc(1, sizeof(*tag)); + op = calloc(1, sizeof(*op)); - if (!tag) + if (!op) return NULL; - tag->val = v; - tag->type = T_RESSOURCE; - tag->proto = json_object_get(proto); - tag->tagtype = n + 1; - tag->data = data; + op->val = v; + op->type = T_RESSOURCE; + op->tag.proto = json_object_get(proto); + op->tag.type = n + 1; + op->tag.data = data; - json_object_set_serializer(tag->val, ut_extended_type_to_string, tag, ut_extended_type_free); + json_object_set_serializer(op->val, ut_extended_type_to_string, op, ut_extended_type_free); - return tag->val; + return op->val; } void ** ut_get_extended_type(struct json_object *v, const char *name) { - struct ut_tagvalue *tag = json_object_get_userdata(v); - size_t n = tag ? tag->tagtype : 0; + struct ut_op *op = json_object_get_userdata(v); + size_t n = op ? op->tag.type : 0; struct ut_extended_type *et; - if (!tag || tag->type != T_RESSOURCE || n == 0 || n > ut_ext_types_count) + if (!op || op->type != T_RESSOURCE || n == 0 || n > ut_ext_types_count) return NULL; et = &ut_ext_types[n - 1]; @@ -385,5 +438,5 @@ ut_get_extended_type(struct json_object *v, const char *name) if (name && strcmp(et->name, name)) return NULL; - return &tag->data; + return &op->tag.data; } @@ -50,24 +50,29 @@ enum ut_block_type { UT_BLOCK_COMMENT }; -struct ut_opcode { - int type; - struct json_object *val; - struct ut_opcode *operand[4], *next, *sibling; +struct ut_op { + uint16_t type; + uint16_t is_first:1; + uint16_t is_op:1; uint32_t off; -}; - -struct ut_tagvalue { - int type; struct json_object *val; - struct json_object *proto; - size_t tagtype; - void *data; + union { + struct { + struct json_object *proto; + size_t type; + void *data; + } tag; + struct { + uint32_t next; + uint32_t operand[4]; + } tree; + }; }; struct ut_state { - struct ut_opcode *pool; - struct ut_opcode *main; + struct ut_op *pool; + uint32_t poolsize; + uint32_t main; uint8_t semicolon_emitted:1; uint8_t start_tag_seen:1; uint8_t srand_called:1; @@ -93,14 +98,20 @@ struct ut_extended_type { void (*free)(void *); }; -struct ut_opcode *ut_new_op(struct ut_state *s, int type, struct json_object *val, ...); -struct ut_opcode *ut_wrap_op(struct ut_opcode *parent, ...); -struct ut_opcode *ut_append_op(struct ut_opcode *a, struct ut_opcode *b); +struct ut_op *ut_get_op(struct ut_state *s, uint32_t off); +struct ut_op *ut_get_child(struct ut_state *s, uint32_t off, int n); + +static inline uint32_t ut_get_off(struct ut_state *s, struct ut_op *op) { + return op ? (op - s->pool + 1) : 0; +}; + +uint32_t ut_new_op(struct ut_state *s, int type, struct json_object *val, ...); +uint32_t ut_wrap_op(struct ut_state *s, uint32_t parent, ...); +uint32_t ut_append_op(struct ut_state *s, uint32_t a, uint32_t b); enum ut_error_type ut_parse(struct ut_state *s, const char *expr); void ut_free(struct ut_state *s); -struct ut_opcode *ut_new_func(struct ut_state *s, struct ut_opcode *name, struct ut_opcode *args, struct ut_opcode *body); - +struct json_object *ut_new_func(struct ut_state *s, struct ut_op *decl); struct json_object *ut_new_object(struct ut_state *s, struct json_object *proto); struct json_object *ut_new_double(double v); struct json_object *ut_new_null(void); @@ -110,7 +121,7 @@ struct json_object *ut_set_extended_type(struct ut_state *s, struct json_object void **ut_get_extended_type(struct json_object *val, const char *name); void *ParseAlloc(void *(*mfunc)(size_t)); -void Parse(void *pParser, int type, struct ut_opcode *op, struct ut_state *s); +void Parse(void *pParser, int type, uint32_t off, struct ut_state *s); void ParseFree(void *pParser, void (*ffunc)(void *)); @@ -25,11 +25,11 @@ #include <stdlib.h> #include <stdarg.h> - -static struct ut_opcode exception_tag = { .type = T_EXCEPTION }; +char exception_tag_space[sizeof(struct ut_op) + sizeof(struct ut_op *)]; +static struct ut_op *exception_tag = (struct ut_op *)exception_tag_space; __attribute__((format(printf, 3, 0))) struct json_object * -ut_exception(struct ut_state *state, struct ut_opcode *op, const char *fmt, ...) +ut_exception(struct ut_state *state, uint32_t off, const char *fmt, ...) { struct json_object *msg; va_list ap; @@ -48,9 +48,10 @@ ut_exception(struct ut_state *state, struct ut_opcode *op, const char *fmt, ...) free(s); } - exception_tag.operand[0] = op; + exception_tag->type = T_EXCEPTION; + exception_tag->tree.operand[0] = off; - json_object_set_userdata(msg, &exception_tag, NULL); + json_object_set_userdata(msg, exception_tag, NULL); state->error.code = UT_ERROR_EXCEPTION; state->error.info.exception = msg; @@ -61,7 +62,7 @@ ut_exception(struct ut_state *state, struct ut_opcode *op, const char *fmt, ...) bool ut_val_is_truish(struct json_object *val) { - struct ut_opcode *tag = json_object_get_userdata(val); + struct ut_op *tag = json_object_get_userdata(val); double d; switch (tag ? tag->type : 0) { @@ -175,7 +176,7 @@ ut_getscope(struct ut_state *state, uint8_t depth) } static struct json_object * -ut_addscope(struct ut_state *state, struct ut_opcode *decl) +ut_addscope(struct ut_state *state, uint32_t decl) { struct json_object *scope, **tmp; @@ -192,7 +193,7 @@ ut_addscope(struct ut_state *state, struct ut_opcode *decl) state->stack.size++; } - scope = json_object_new_object(); + scope = ut_new_object(state, NULL); if (!scope) return ut_exception(state, decl, UT_ERRMSG_OOM); @@ -205,7 +206,7 @@ ut_addscope(struct ut_state *state, struct ut_opcode *decl) void ut_putval(struct json_object *val) { - struct ut_opcode *tag = json_object_get_userdata(val); + struct ut_op *tag = json_object_get_userdata(val); if (tag && tag->val != val) json_object_put(tag->val); @@ -214,20 +215,20 @@ ut_putval(struct json_object *val) } static struct json_object * -ut_execute_op(struct ut_state *state, struct ut_opcode *op); +ut_execute_op(struct ut_state *state, uint32_t off); static char * -ut_ref_to_str(struct ut_opcode *op) +ut_ref_to_str(struct ut_state *state, uint32_t off) { - struct ut_opcode *op1 = op->operand[0]; - struct ut_opcode *op2 = op->operand[1]; + struct ut_op *op = ut_get_op(state, off); + struct ut_op *op2 = ut_get_child(state, off, 1); const char *l; size_t n1, n2; char *s, *p; switch (op ? op->type : 0) { case T_DOT: - s = ut_ref_to_str(op1); + s = ut_ref_to_str(state, op->tree.operand[0]); n1 = strlen(s ? s : "(null)"); l = ((op2 ? op2->type : 0) == T_LABEL) ? json_object_get_string(op2->val) : "???"; @@ -247,7 +248,7 @@ ut_ref_to_str(struct ut_opcode *op) if (!op->val) return NULL; - s = ut_ref_to_str(op1); + s = ut_ref_to_str(state, op->tree.operand[0]); n1 = strlen(s ? s : "(null)"); l = "..."; @@ -272,20 +273,23 @@ ut_ref_to_str(struct ut_opcode *op) } static struct json_object * -ut_getref(struct ut_state *state, struct ut_opcode *op, struct json_object **key) +ut_getref(struct ut_state *state, uint32_t off, struct json_object **key) { + struct ut_op *op = ut_get_op(state, off); + uint32_t off1 = op ? op->tree.operand[0] : 0; + uint32_t off2 = op ? op->tree.operand[1] : 0; struct json_object *scope, *next; uint8_t i; if (op && op->type == T_DOT) { - *key = op->operand[1] ? op->operand[1]->val : NULL; + *key = off2 ? ut_get_op(state, off2)->val : NULL; - return ut_execute_op(state, op->operand[0]); + return ut_execute_op(state, off1); } else if (op && op->type == T_LBRACK && op->val) { - *key = op->operand[1] ? ut_execute_op(state, op->operand[1]) : NULL; + *key = off2 ? ut_execute_op(state, off2) : NULL; - return ut_execute_op(state, op->operand[0]); + return ut_execute_op(state, off1); } else if (op && op->type == T_LABEL) { i = 0; @@ -315,24 +319,26 @@ ut_getref(struct ut_state *state, struct ut_opcode *op, struct json_object **key } static struct json_object * -ut_getref_required(struct ut_state *state, struct ut_opcode *op, struct json_object **key) +ut_getref_required(struct ut_state *state, uint32_t off, struct json_object **key) { + struct ut_op *op = ut_get_op(state, off); + uint32_t off1 = op ? op->tree.operand[0] : 0; struct json_object *scope, *skey, *rv; char *lhs; - scope = ut_getref(state, op, &skey); + scope = ut_getref(state, off, &skey); if (!json_object_is_type(scope, json_type_array) && !json_object_is_type(scope, json_type_object)) { - lhs = op->operand[0] ? ut_ref_to_str(op->operand[0]) : NULL; + lhs = off1 ? ut_ref_to_str(state, off1) : NULL; if (lhs) { - rv = ut_exception(state, op->operand[0], "Type error: %s is null", lhs); + rv = ut_exception(state, off1, "Type error: %s is null", lhs); free(lhs); } else { - rv = ut_exception(state, op, + rv = ut_exception(state, off, "Syntax error: Invalid left-hand side operand %s", tokennames[op->type]); } @@ -349,12 +355,12 @@ ut_getref_required(struct ut_state *state, struct ut_opcode *op, struct json_obj static struct json_object * ut_getproto(struct json_object *obj) { - struct ut_tagvalue *tag = json_object_get_userdata(obj); + struct ut_op *op = json_object_get_userdata(obj); - if (!tag || (tag->type != T_LBRACE && tag->type <= __T_MAX) || !tag->val) + if (!op || (op->type != T_LBRACE && op->type <= __T_MAX) || !op->val) return NULL; - return tag->proto; + return op->tag.proto; } static struct json_object * @@ -427,10 +433,11 @@ ut_setval(struct json_object *scope, struct json_object *key, struct json_object } static struct json_object * -ut_execute_assign(struct ut_state *state, struct ut_opcode *op) +ut_execute_assign(struct ut_state *state, uint32_t off) { - struct ut_opcode *label = op->operand[0]; - struct ut_opcode *value = op->operand[1]; + struct ut_op *op = ut_get_op(state, off); + uint32_t label = op ? op->tree.operand[0] : 0; + uint32_t value = op ? op->tree.operand[1] : 0; struct json_object *scope, *key, *val; scope = ut_getref_required(state, label, &key); @@ -445,29 +452,33 @@ ut_execute_assign(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_local(struct ut_state *state, struct ut_opcode *op) +ut_execute_local(struct ut_state *state, uint32_t off) { - struct ut_opcode *as = op->operand[0]; + struct ut_op *as = ut_get_child(state, off, 0); struct json_object *rv = NULL; + struct ut_op *label; while (as) { - rv = ut_setval( - state->stack.scope[state->stack.off-1], as->operand[0]->val, - as->operand[1] ? ut_execute_op(state, as->operand[1]) : NULL); + label = ut_get_op(state, as->tree.operand[0]); + + if (label) + rv = ut_setval( + state->stack.scope[state->stack.off-1], label->val, + as->tree.operand[1] ? ut_execute_op(state, as->tree.operand[1]) : NULL); - as = as->sibling; + as = ut_get_op(state, as->tree.next); } return rv; } static struct json_object * -ut_execute_op_sequence(struct ut_state *state, struct ut_opcode *op); +ut_execute_op_sequence(struct ut_state *state, uint32_t off); static bool -ut_test_condition(struct ut_state *state, struct ut_opcode *op) +ut_test_condition(struct ut_state *state, uint32_t off) { - struct json_object *val = ut_execute_op_sequence(state, op); + struct json_object *val = ut_execute_op_sequence(state, off); bool istrue = ut_val_is_truish(val); ut_putval(val); @@ -476,11 +487,12 @@ ut_test_condition(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_if(struct ut_state *state, struct ut_opcode *op) +ut_execute_if(struct ut_state *state, uint32_t off) { - struct ut_opcode *cond = op->operand[0]; - struct ut_opcode *Then = op->operand[1]; - struct ut_opcode *Else = op->operand[2]; + struct ut_op *op = ut_get_op(state, off); + uint32_t cond = op ? op->tree.operand[0] : 0; + uint32_t Then = op ? op->tree.operand[1] : 0; + uint32_t Else = op ? op->tree.operand[2] : 0; if (ut_test_condition(state, cond)) return ut_execute_op_sequence(state, Then); @@ -491,23 +503,24 @@ ut_execute_if(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_for(struct ut_state *state, struct ut_opcode *op) +ut_execute_for(struct ut_state *state, uint32_t off) { struct json_object *ivar, *val, *item, *rv = NULL; - struct ut_opcode *init = op->operand[0]; - struct ut_opcode *test = op->operand[1]; - struct ut_opcode *incr = op->operand[2]; - struct ut_opcode *body = op->operand[3]; - struct ut_opcode *tag; + struct ut_op *init = ut_get_child(state, off, 0); + struct ut_op *test = ut_get_child(state, off, 1); + struct ut_op *incr = ut_get_child(state, off, 2); + struct ut_op *body = ut_get_child(state, off, 3); + struct ut_op *tag; size_t arridx, arrlen; /* for (x in ...) loop variant */ if (init != NULL && test == NULL && incr == NULL) { if (init->type != T_IN) - return ut_exception(state, init, "Syntax error: missing ';' after for loop initializer"); + return ut_exception(state, ut_get_off(state, init), + "Syntax error: missing ';' after for loop initializer"); - ivar = init->operand[0]->val; - val = ut_execute_op(state, init->operand[1]); + ivar = ut_get_op(state, init->tree.operand[0])->val; + val = ut_execute_op(state, init->tree.operand[1]); if (json_object_is_type(val, json_type_array)) { for (arridx = 0, arrlen = json_object_array_length(val); @@ -517,7 +530,7 @@ ut_execute_for(struct ut_state *state, struct ut_opcode *op) ut_setval(ut_getscope(state, 0), ivar, item); ut_putval(rv); - rv = ut_execute_op_sequence(state, body); + rv = ut_execute_op_sequence(state, ut_get_off(state, body)); tag = json_object_get_userdata(rv); switch (tag ? tag->type : 0) { @@ -540,7 +553,7 @@ ut_execute_for(struct ut_state *state, struct ut_opcode *op) ut_setval(ut_getscope(state, 0), ivar, json_object_new_string(key)); ut_putval(rv); - rv = ut_execute_op_sequence(state, body); + rv = ut_execute_op_sequence(state, ut_get_off(state, body)); tag = json_object_get_userdata(rv); switch (tag ? tag->type : 0) { @@ -566,12 +579,12 @@ ut_execute_for(struct ut_state *state, struct ut_opcode *op) } if (init) - ut_putval(ut_execute_op_sequence(state, init)); + ut_putval(ut_execute_op_sequence(state, ut_get_off(state, init))); - while (test ? ut_test_condition(state, test) : true) { + while (test ? ut_test_condition(state, ut_get_off(state, test)) : true) { ut_putval(rv); - rv = ut_execute_op_sequence(state, body); + rv = ut_execute_op_sequence(state, ut_get_off(state, body)); tag = json_object_get_userdata(rv); switch (tag ? tag->type : 0) { @@ -586,7 +599,7 @@ ut_execute_for(struct ut_state *state, struct ut_opcode *op) } if (incr) - ut_putval(ut_execute_op_sequence(state, incr)); + ut_putval(ut_execute_op_sequence(state, ut_get_off(state, incr))); } ut_putval(rv); @@ -595,12 +608,13 @@ ut_execute_for(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_while(struct ut_state *state, struct ut_opcode *op) +ut_execute_while(struct ut_state *state, uint32_t off) { - struct ut_opcode *test = op->operand[0]; - struct ut_opcode *body = op->operand[1]; + struct ut_op *op = ut_get_op(state, off); + uint32_t test = op ? op->tree.operand[0] : 0; + uint32_t body = op ? op->tree.operand[1] : 0; struct json_object *v, *rv = NULL; - struct ut_opcode *tag = NULL; + struct ut_op *tag = NULL; bool cond; while (1) { @@ -634,18 +648,16 @@ ut_execute_while(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_and_or(struct ut_state *state, struct ut_opcode *op) +ut_execute_and_or(struct ut_state *state, uint32_t off) { + struct ut_op *op = ut_get_op(state, off); struct json_object *val = NULL; int i; - for (i = 0; i < sizeof(op->operand) / sizeof(op->operand[0]); i++) { - if (!op->operand[i]) - break; - + for (i = 0; i < ARRAY_SIZE(op->tree.operand) && op->tree.operand[i]; i++) { ut_putval(val); - val = ut_execute_op(state, op->operand[i]); + val = ut_execute_op(state, op->tree.operand[i]); if (ut_val_is_truish(val) == (op->type == T_OR)) break; @@ -716,10 +728,13 @@ ut_cmp(int how, struct json_object *v1, struct json_object *v2) } static struct json_object * -ut_execute_rel(struct ut_state *state, struct ut_opcode *op) +ut_execute_rel(struct ut_state *state, uint32_t off) { - struct json_object *v1 = ut_execute_op(state, op->operand[0]); - struct json_object *v2 = ut_execute_op(state, op->operand[1]); + struct ut_op *op = ut_get_op(state, off); + uint32_t off1 = op ? op->tree.operand[0] : 0; + uint32_t off2 = op ? op->tree.operand[1] : 0; + struct json_object *v1 = ut_execute_op(state, off1); + struct json_object *v2 = ut_execute_op(state, off2); struct json_object *rv; rv = json_object_new_boolean(ut_cmp(op->type, v1, v2)); @@ -731,10 +746,11 @@ ut_execute_rel(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_in(struct ut_state *state, struct ut_opcode *op) +ut_execute_in(struct ut_state *state, uint32_t off) { - struct json_object *op1 = ut_execute_op(state, op->operand[0]); - struct json_object *op2 = ut_execute_op(state, op->operand[1]); + struct ut_op *op = ut_get_op(state, off); + struct json_object *op1 = ut_execute_op(state, op ? op->tree.operand[0] : 0); + struct json_object *op2 = ut_execute_op(state, op ? op->tree.operand[1] : 0); struct json_object *item; size_t arrlen, arridx; bool found = false; @@ -763,10 +779,11 @@ ut_execute_in(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_inc_dec(struct ut_state *state, struct ut_opcode *op) +ut_execute_inc_dec(struct ut_state *state, uint32_t off) { + struct ut_op *op = ut_get_op(state, off); struct json_object *val, *nval, *scope, *key; - struct ut_opcode *label = op->operand[0]; + uint32_t label = op ? op->tree.operand[0] : 0; int64_t n; double d; @@ -796,79 +813,85 @@ ut_execute_inc_dec(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_list(struct ut_state *state, struct ut_opcode *op) +ut_execute_list(struct ut_state *state, uint32_t off) { + struct ut_op *op = ut_get_op(state, off); struct json_object *arr = json_object_new_array(); if (!arr) - return ut_exception(state, op, UT_ERRMSG_OOM); + return ut_exception(state, off, UT_ERRMSG_OOM); while (op) { - json_object_array_add(arr, ut_execute_op(state, op)); - op = op->sibling; + json_object_array_add(arr, ut_execute_op(state, ut_get_off(state, op))); + op = ut_get_op(state, op->tree.next); } return arr; } static struct json_object * -ut_execute_object(struct ut_state *state, struct ut_opcode *op) +ut_execute_object(struct ut_state *state, uint32_t off) { struct json_object *obj = ut_new_object(state, NULL); - struct ut_opcode *key, *val; + struct ut_op *key, *val; if (!obj) - return ut_exception(state, op, UT_ERRMSG_OOM); + return ut_exception(state, off, UT_ERRMSG_OOM); - for (key = op->operand[0], val = key ? key->sibling : NULL; + for (key = ut_get_child(state, off, 0), val = ut_get_op(state, key ? key->tree.next : 0); key != NULL && val != NULL; - key = val->sibling, val = key ? key->sibling : NULL) { + key = ut_get_op(state, val->tree.next), val = ut_get_op(state, key ? key->tree.next : 0)) { json_object_object_add(obj, json_object_get_string(key->val), - ut_execute_op(state, val)); + ut_execute_op(state, ut_get_off(state, val))); } return obj; } struct json_object * -ut_invoke(struct ut_state *state, struct ut_opcode *op, struct json_object *scope, +ut_invoke(struct ut_state *state, uint32_t off, struct json_object *scope, struct json_object *func, struct json_object *argvals) { - struct ut_opcode *decl = json_object_get_userdata(func); - struct ut_opcode *arg = decl ? decl->operand[1] : NULL; - struct ut_tagvalue *tag = (struct ut_tagvalue *)decl; + struct ut_op *tag = json_object_get_userdata(func); + struct ut_op *arg, *decl; struct json_object *s, *rv = NULL; size_t arridx; ut_c_fn *cfn; - if (!decl) + if (!tag) return NULL; /* is native function */ if (tag->type == T_CFUNC) { - cfn = (ut_c_fn *)tag->data; + cfn = (ut_c_fn *)tag->tag.data; - return cfn ? cfn(state, op, argvals) : NULL; + return cfn ? cfn(state, off, argvals) : NULL; } - s = scope ? scope : ut_addscope(state, decl); + decl = tag->tag.data; + arg = ut_get_op(state, decl ? decl->tree.operand[1] : 0); + + s = scope ? scope : ut_addscope(state, ut_get_off(state, decl)); if (!json_object_is_type(s, json_type_object)) return s; - for (arridx = 0; arg; arridx++, arg = arg->sibling) + for (arridx = 0; arg; arridx++, arg = ut_get_op(state, arg->tree.next)) ut_setval(s, arg->val, argvals ? json_object_array_get_idx(argvals, arridx) : NULL); - json_object_set_userdata(s, json_object_get(state->ctx), NULL); + /* store the function "this" context in the proto member of the scope tag structure */ + tag = json_object_get_userdata(s); + tag->tag.proto = json_object_get(state->ctx); - rv = ut_execute_op_sequence(state, decl->operand[2]); + rv = ut_execute_op_sequence(state, decl->tree.operand[2]); tag = json_object_get_userdata(rv); switch (tag ? tag->type : 0) { case T_BREAK: case T_CONTINUE: ut_putval(rv); - rv = ut_exception(state, (struct ut_opcode *)tag, "Syntax error: %s statement must be inside loop", + rv = ut_exception(state, ut_get_off(state, tag), + "Syntax error: %s statement must be inside loop", tokennames[tag->type]); break; @@ -884,10 +907,13 @@ ut_invoke(struct ut_state *state, struct ut_opcode *op, struct json_object *scop break; } + /* we left the function, remove the "this" context from the scope tag structure */ + tag = json_object_get_userdata(s); + json_object_put(tag->tag.proto); + tag->tag.proto = NULL; + if (!scope) { state->stack.scope[--state->stack.off] = NULL; - - json_object_put(json_object_get_userdata(s)); json_object_put(s); } @@ -895,24 +921,27 @@ ut_invoke(struct ut_state *state, struct ut_opcode *op, struct json_object *scop } static struct json_object * -ut_execute_call(struct ut_state *state, struct ut_opcode *op) +ut_execute_call(struct ut_state *state, uint32_t off) { - struct json_object *func = ut_execute_op(state, op->operand[0]); - struct ut_opcode *decl = func ? json_object_get_userdata(func) : NULL; - struct json_object *argvals = ut_execute_list(state, op->operand[1]); + struct ut_op *op = ut_get_op(state, off); + uint32_t off1 = op ? op->tree.operand[0] : 0; + uint32_t off2 = op ? op->tree.operand[1] : 0; + struct json_object *func = ut_execute_op(state, off1); + struct ut_op *decl = func ? json_object_get_userdata(func) : NULL; + struct json_object *argvals = ut_execute_list(state, off2); struct json_object *rv; char *lhs; if (!decl || (decl->type != T_FUNC && decl->type != T_CFUNC)) { - lhs = ut_ref_to_str(op->operand[0]); - rv = ut_exception(state, op->operand[0], + lhs = ut_ref_to_str(state, off1); + rv = ut_exception(state, off1, "Type error: %s is not a function", lhs ? lhs : "left-hand side expression"); free(lhs); } else { - rv = ut_invoke(state, op, NULL, func, argvals); + rv = ut_invoke(state, off, NULL, func, argvals); } ut_putval(argvals); @@ -934,10 +963,11 @@ ut_write_str(struct json_object *v) } static struct json_object * -ut_execute_exp(struct ut_state *state, struct ut_opcode *op) +ut_execute_exp(struct ut_state *state, uint32_t off) { - struct json_object *val = ut_execute_op_sequence(state, op->operand[0]); - struct ut_opcode *tag = val ? json_object_get_userdata(val) : NULL; + struct ut_op *op = ut_get_op(state, off); + struct json_object *val = ut_execute_op_sequence(state, op ? op->tree.operand[0] : 0); + struct ut_op *tag = val ? json_object_get_userdata(val) : NULL; switch (tag ? tag->type : 0) { case T_RETURN: @@ -962,9 +992,10 @@ ut_execute_exp(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_unary_plus_minus(struct ut_state *state, struct ut_opcode *op) +ut_execute_unary_plus_minus(struct ut_state *state, uint32_t off) { - struct json_object *val = ut_execute_op(state, op->operand[0]); + struct ut_op *op = ut_get_op(state, off); + struct json_object *val = ut_execute_op(state, op ? op->tree.operand[0] : 0); enum json_type t; int64_t n; double d; @@ -983,8 +1014,9 @@ ut_execute_unary_plus_minus(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_arith(struct ut_state *state, struct ut_opcode *op) +ut_execute_arith(struct ut_state *state, uint32_t off) { + struct ut_op *op = ut_get_op(state, off); struct json_object *v1, *v2, *rv; enum json_type t1, t2; const char *s1, *s2; @@ -993,11 +1025,11 @@ ut_execute_arith(struct ut_state *state, struct ut_opcode *op) double d1, d2; char *s; - if (!op->operand[1]) - return ut_execute_unary_plus_minus(state, op); + if (!op->tree.operand[1]) + return ut_execute_unary_plus_minus(state, off); - v1 = ut_execute_op(state, op->operand[0]); - v2 = ut_execute_op(state, op->operand[1]); + v1 = ut_execute_op(state, op ? op->tree.operand[0] : 0); + v2 = ut_execute_op(state, op ? op->tree.operand[1] : 0); if (op->type == T_ADD && (json_object_is_type(v1, json_type_string) || @@ -1081,16 +1113,17 @@ ut_execute_arith(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_bitop(struct ut_state *state, struct ut_opcode *op) +ut_execute_bitop(struct ut_state *state, uint32_t off) { - struct ut_opcode *op1 = op->operand[0]; - struct ut_opcode *op2 = op->operand[1]; + struct ut_op *op = ut_get_op(state, off); + uint32_t off1 = op ? op->tree.operand[0] : 0; + uint32_t off2 = op ? op->tree.operand[1] : 0; struct json_object *v1, *v2; int64_t n1, n2; double d; - v1 = op1 ? ut_execute_op(state, op1) : NULL; - v2 = op2 ? ut_execute_op(state, op2) : NULL; + v1 = off1 ? ut_execute_op(state, off1) : NULL; + v2 = off2 ? ut_execute_op(state, off2) : NULL; if (ut_cast_number(v1, &n1, &d) == json_type_double) n1 = isnan(d) ? 0 : (int64_t)d; @@ -1123,15 +1156,19 @@ ut_execute_bitop(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_not(struct ut_state *state, struct ut_opcode *op) +ut_execute_not(struct ut_state *state, uint32_t off) { - return json_object_new_boolean(!ut_test_condition(state, op->operand[0])); + struct ut_op *op = ut_get_op(state, off); + + return json_object_new_boolean(!ut_test_condition(state, op ? op->tree.operand[0] : 0)); } static struct json_object * -ut_execute_compl(struct ut_state *state, struct ut_opcode *op) +ut_execute_compl(struct ut_state *state, uint32_t off) { - struct json_object *val = op->operand[0] ? ut_execute_op(state, op->operand[0]) : NULL; + struct ut_op *op = ut_get_op(state, off); + uint32_t off1 = op ? op->tree.operand[0] : 0; + struct json_object *val = off1 ? ut_execute_op(state, off1) : NULL; int64_t n; double d; @@ -1144,9 +1181,11 @@ ut_execute_compl(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_return(struct ut_state *state, struct ut_opcode *op) +ut_execute_return(struct ut_state *state, uint32_t off) { - struct json_object *val = op->operand[0] ? ut_execute_op(state, op->operand[0]) : NULL; + struct ut_op *op = ut_get_op(state, off); + uint32_t off1 = op ? op->tree.operand[0] : 0; + struct json_object *val = off1 ? ut_execute_op(state, off1) : NULL; if (!val) val = ut_new_null(); @@ -1157,8 +1196,9 @@ ut_execute_return(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_break_cont(struct ut_state *state, struct ut_opcode *op) +ut_execute_break_cont(struct ut_state *state, uint32_t off) { + struct ut_op *op = ut_get_op(state, off); struct json_object *rv = json_object_new_int64(0); json_object_set_userdata(rv, op, NULL); @@ -1167,8 +1207,28 @@ ut_execute_break_cont(struct ut_state *state, struct ut_opcode *op) } static struct json_object * -ut_execute_op(struct ut_state *state, struct ut_opcode *op) +ut_execute_function(struct ut_state *state, uint32_t off) +{ + struct ut_op *op = ut_get_op(state, off); + struct json_object *obj = ut_new_func(state, op); + + if (!obj) + return ut_exception(state, off, UT_ERRMSG_OOM); + + return obj; +} + +static struct json_object * +ut_execute_this(struct ut_state *state, uint32_t off) +{ + return ut_getproto(ut_getscope(state, 0)); +} + +static struct json_object * +ut_execute_op(struct ut_state *state, uint32_t off) { + struct ut_op *op = ut_get_op(state, off); + struct ut_op *op1 = ut_get_child(state, off, 0); struct json_object *scope, *key, *val; switch (op->type) { @@ -1180,13 +1240,15 @@ ut_execute_op(struct ut_state *state, struct ut_opcode *op) return json_object_get(op->val); case T_THIS: - return json_object_get_userdata(ut_getscope(state, 0)); + return ut_execute_this(state, off); case T_FUNC: - if (op->operand[0]) - ut_setval(ut_getscope(state, 0), op->operand[0]->val, op->val); + val = ut_execute_function(state, off); - return json_object_get(op->val); + if (op1) + ut_setval(ut_getscope(state, 0), op1->val, val); + + return val; case T_TEXT: printf("%s", json_object_get_string(op->val)); @@ -1194,13 +1256,13 @@ ut_execute_op(struct ut_state *state, struct ut_opcode *op) return NULL; case T_ASSIGN: - return ut_execute_assign(state, op); + return ut_execute_assign(state, off); case T_LOCAL: - return ut_execute_local(state, op); + return ut_execute_local(state, off); case T_LABEL: - scope = ut_getref(state, op, &key); + scope = ut_getref(state, off, &key); state->ctx = scope; val = ut_getval(scope, key); @@ -1209,7 +1271,7 @@ ut_execute_op(struct ut_state *state, struct ut_opcode *op) return val; case T_DOT: - scope = ut_getref_required(state, op, &key); + scope = ut_getref_required(state, off, &key); state->ctx = scope; if (!key) @@ -1223,7 +1285,7 @@ ut_execute_op(struct ut_state *state, struct ut_opcode *op) case T_LBRACK: /* postfix access */ if (op->val) { - scope = ut_getref_required(state, op, &key); + scope = ut_getref_required(state, off, &key); state->ctx = scope; if (!key) @@ -1235,24 +1297,24 @@ ut_execute_op(struct ut_state *state, struct ut_opcode *op) return val; } - return ut_execute_list(state, op->operand[0]); + return ut_execute_list(state, ut_get_off(state, op1)); case T_LBRACE: - return ut_execute_object(state, op); + return ut_execute_object(state, off); case T_IF: case T_QMARK: - return ut_execute_if(state, op); + return ut_execute_if(state, off); case T_FOR: - return ut_execute_for(state, op); + return ut_execute_for(state, off); case T_WHILE: - return ut_execute_while(state, op); + return ut_execute_while(state, off); case T_AND: case T_OR: - return ut_execute_and_or(state, op); + return ut_execute_and_or(state, off); case T_LT: case T_LE: @@ -1260,63 +1322,64 @@ ut_execute_op(struct ut_state *state, struct ut_opcode *op) case T_GE: case T_EQ: case T_NE: - return ut_execute_rel(state, op); + return ut_execute_rel(state, off); case T_IN: - return ut_execute_in(state, op); + return ut_execute_in(state, off); case T_INC: case T_DEC: - return ut_execute_inc_dec(state, op); + return ut_execute_inc_dec(state, off); case T_LPAREN: - return ut_execute_call(state, op); + return ut_execute_call(state, off); case T_LEXP: - return ut_execute_exp(state, op); + return ut_execute_exp(state, off); case T_ADD: case T_SUB: case T_MUL: case T_DIV: case T_MOD: - return ut_execute_arith(state, op); + return ut_execute_arith(state, off); case T_LSHIFT: case T_RSHIFT: case T_BAND: case T_BXOR: case T_BOR: - return ut_execute_bitop(state, op); + return ut_execute_bitop(state, off); case T_COMPL: - return ut_execute_compl(state, op); + return ut_execute_compl(state, off); case T_NOT: - return ut_execute_not(state, op); + return ut_execute_not(state, off); case T_RETURN: - return ut_execute_return(state, op); + return ut_execute_return(state, off); case T_BREAK: case T_CONTINUE: - return ut_execute_break_cont(state, op); + return ut_execute_break_cont(state, off); default: - return ut_exception(state, op, "Runtime error: Unrecognized opcode %d", op->type); + return ut_exception(state, off, "Runtime error: Unrecognized opcode %d", op->type); } } static struct json_object * -ut_execute_op_sequence(struct ut_state *state, struct ut_opcode *op) +ut_execute_op_sequence(struct ut_state *state, uint32_t off) { struct json_object *v = NULL; - struct ut_opcode *tag = NULL; + struct ut_op *tag = NULL; + struct ut_op *op = NULL; - while (op) { + while (off) { ut_putval(v); - v = ut_execute_op(state, op); + v = ut_execute_op(state, off); tag = v ? json_object_get_userdata(v) : NULL; switch (tag ? tag->type : 0) { @@ -1327,7 +1390,8 @@ ut_execute_op_sequence(struct ut_state *state, struct ut_opcode *op) return v; } - op = op->sibling; + op = ut_get_op(state, off); + off = op ? op->tree.next : 0; } return v; @@ -1359,14 +1423,20 @@ ut_globals_init(struct ut_state *state, struct json_object *scope) enum ut_error_type ut_run(struct ut_state *state) { - struct json_object *scope, *args, *rv; + struct ut_op *op = ut_get_op(state, state->main); + struct json_object *main, *scope, *args, *rv; - if (!state->main || state->main->type != T_FUNC || !state->main->val) { + if (!op || op->type != T_FUNC) { ut_exception(state, state->main, "Runtime error: Invalid root operation in AST"); return UT_ERROR_EXCEPTION; } + main = ut_execute_function(state, state->main); + + if (!main) + return UT_ERROR_EXCEPTION; + scope = ut_addscope(state, state->main); if (!json_object_is_type(scope, json_type_object)) @@ -1378,8 +1448,9 @@ ut_run(struct ut_state *state) ut_lib_init(state, scope); args = json_object_new_array(); - rv = ut_invoke(state, state->main, NULL, state->main->val, args); + rv = ut_invoke(state, state->main, NULL, main, args); + json_object_put(main); json_object_put(args); json_object_put(rv); @@ -25,7 +25,7 @@ #include "ast.h" __attribute__((format(printf, 3, 0))) struct json_object * -ut_exception(struct ut_state *state, struct ut_opcode *op, const char *fmt, ...); +ut_exception(struct ut_state *state, uint32_t op, const char *fmt, ...); void ut_putval(struct json_object *val); @@ -40,7 +40,7 @@ enum json_type ut_cast_number(struct json_object *v, int64_t *n, double *d); struct json_object * -ut_invoke(struct ut_state *, struct ut_opcode *, struct json_object *, struct json_object *, struct json_object *); +ut_invoke(struct ut_state *, uint32_t, struct json_object *, struct json_object *, struct json_object *); enum ut_error_type ut_run(struct ut_state *state); @@ -32,7 +32,7 @@ struct token { int type; const char *pat; int plen; - int (*parse)(const char *buf, struct ut_opcode *op, struct ut_state *s); + int (*parse)(const char *buf, struct ut_op *op, struct ut_state *s); }; #define dec(o) \ @@ -42,11 +42,11 @@ struct token { (((x) >= 'a') ? (10 + (x) - 'a') : \ (((x) >= 'A') ? (10 + (x) - 'A') : dec(x))) -static int parse_comment(const char *, struct ut_opcode *, struct ut_state *); -static int parse_string(const char *, struct ut_opcode *, struct ut_state *); -static int parse_number(const char *, struct ut_opcode *, struct ut_state *); -static int parse_label(const char *, struct ut_opcode *, struct ut_state *); -static int parse_bool(const char *, struct ut_opcode *, struct ut_state *); +static int parse_comment(const char *, struct ut_op *, struct ut_state *); +static int parse_string(const char *, struct ut_op *, struct ut_state *); +static int parse_number(const char *, struct ut_op *, struct ut_state *); +static int parse_label(const char *, struct ut_op *, struct ut_state *); +static int parse_bool(const char *, struct ut_op *, struct ut_state *); static const struct token tokens[] = { { 0, " ", 1 }, @@ -278,7 +278,7 @@ utf8enc(char **out, int *rem, int code) */ static int -parse_comment(const char *buf, struct ut_opcode *op, struct ut_state *s) +parse_comment(const char *buf, struct ut_op *op, struct ut_state *s) { const char *p = buf; @@ -314,7 +314,7 @@ parse_comment(const char *buf, struct ut_opcode *op, struct ut_state *s) */ static int -parse_string(const char *buf, struct ut_opcode *op, struct ut_state *s) +parse_string(const char *buf, struct ut_op *op, struct ut_state *s) { char q = *(buf++); char str[128] = { 0 }; @@ -483,7 +483,7 @@ parse_string(const char *buf, struct ut_opcode *op, struct ut_state *s) */ static int -parse_label(const char *buf, struct ut_opcode *op, struct ut_state *s) +parse_label(const char *buf, struct ut_op *op, struct ut_state *s) { const struct token *word; char str[128] = { 0 }; @@ -531,7 +531,7 @@ parse_label(const char *buf, struct ut_opcode *op, struct ut_state *s) */ static int -parse_number(const char *buf, struct ut_opcode *op, struct ut_state *s) +parse_number(const char *buf, struct ut_op *op, struct ut_state *s) { double d; char *e; @@ -581,7 +581,7 @@ parse_number(const char *buf, struct ut_opcode *op, struct ut_state *s) */ static int -parse_bool(const char *buf, struct ut_opcode *op, struct ut_state *s) +parse_bool(const char *buf, struct ut_op *op, struct ut_state *s) { if (!strncmp(buf, "false", 5)) { op->val = json_object_new_boolean(false); @@ -599,7 +599,7 @@ parse_bool(const char *buf, struct ut_opcode *op, struct ut_state *s) static int -match_token(const char *ptr, struct ut_opcode *op, struct ut_state *s) +match_token(const char *ptr, struct ut_op *op, struct ut_state *s) { int i; const struct token *tok; @@ -621,10 +621,10 @@ match_token(const char *ptr, struct ut_opcode *op, struct ut_state *s) return -UT_ERROR_UNEXPECTED_CHAR; } -struct ut_opcode * +uint32_t ut_get_token(struct ut_state *s, const char *input, int *mlen) { - struct ut_opcode op = { 0 }; + struct ut_op op = { 0 }; const char *o, *p; for (o = p = input; *p; p++) { @@ -647,9 +647,9 @@ ut_get_token(struct ut_state *s, const char *input, int *mlen) p--; if (p == o) - return NULL; + return 0; - return ut_new_op(s, T_TEXT, json_object_new_string_len(o, p - o), (void *)1); + return ut_new_op(s, T_TEXT, json_object_new_string_len(o, p - o), UINT32_MAX); } } else if (s->blocktype == UT_BLOCK_COMMENT) { @@ -669,7 +669,7 @@ ut_get_token(struct ut_state *s, const char *input, int *mlen) s->blocktype = UT_BLOCK_NONE; s->off += *mlen; - return NULL; + return 0; } } else if (s->blocktype == UT_BLOCK_STATEMENT || s->blocktype == UT_BLOCK_EXPRESSION) { @@ -678,7 +678,7 @@ ut_get_token(struct ut_state *s, const char *input, int *mlen) if (*mlen < 0) { s->error.code = -*mlen; - return NULL; + return 0; } /* disallow nesting blocks */ @@ -688,7 +688,7 @@ ut_get_token(struct ut_state *s, const char *input, int *mlen) (op.type == T_LSTM || op.type == T_RSTM || op.type == T_LEXP))) { s->error.code = UT_ERROR_NESTED_BLOCKS; - return NULL; + return 0; } /* emit additional empty statement (semicolon) at end of template block */ @@ -718,9 +718,9 @@ ut_get_token(struct ut_state *s, const char *input, int *mlen) /* do not report '{%' and '%}' tags to parser */ if (op.type == T_LSTM || op.type == T_RSTM || op.type == 0) - return NULL; + return 0; - return ut_new_op(s, op.type, op.val, (void *)1); + return ut_new_op(s, op.type, op.val, UINT32_MAX); } } @@ -728,15 +728,15 @@ ut_get_token(struct ut_state *s, const char *input, int *mlen) if (s->blocktype == UT_BLOCK_EXPRESSION || s->blocktype == UT_BLOCK_COMMENT) { s->error.code = UT_ERROR_UNTERMINATED_BLOCK; - return NULL; + return 0; } if (p > input) { *mlen = p - input; s->off += *mlen; - return ut_new_op(s, T_TEXT, json_object_new_string_len(o, p - o), (void *)1); + return ut_new_op(s, T_TEXT, json_object_new_string_len(o, p - o), UINT32_MAX); } - return NULL; + return 0; } @@ -29,7 +29,7 @@ extern const char *tokennames[__T_MAX]; bool utf8enc(char **out, int *rem, int code); -struct ut_opcode * +uint32_t ut_get_token(struct ut_state *s, const char *input, int *mlen); #endif /* __LEXER_H_ */ @@ -134,7 +134,7 @@ char * ut_format_error(struct ut_state *state, const char *expr) { size_t off = state ? state->off : 0; - struct ut_opcode *tag; + struct ut_op *tag; bool first = true; size_t msglen = 0; char *msg = NULL; @@ -203,7 +203,7 @@ ut_format_error(struct ut_state *state, const char *expr) case UT_ERROR_EXCEPTION: tag = json_object_get_userdata(state->error.info.exception); - off = (tag && tag->operand[0]) ? tag->operand[0]->off : 0; + off = (tag && tag->tree.operand[0]) ? ut_get_op(state, tag->tree.operand[0])->off : 0; sprintf_append(&msg, &msglen, "%s\n", json_object_get_string(state->error.info.exception)); break; @@ -271,9 +271,9 @@ ut_c_fn_to_string(struct json_object *v, struct printbuf *pb, int level, int fla static void ut_c_fn_free(struct json_object *v, void *ud) { - struct ut_tagvalue *tag = json_object_get_userdata(v); + struct ut_op *op = json_object_get_userdata(v); - json_object_put(tag->proto); + json_object_put(op->tag.proto); free(ud); } @@ -281,30 +281,30 @@ static bool ut_register_function(struct ut_state *state, struct json_object *scope, const char *name, ut_c_fn *fn) { struct json_object *val = json_object_new_object(); - struct ut_tagvalue *tag; + struct ut_op *op; if (!val) return NULL; - tag = calloc(1, sizeof(*tag)); + op = calloc(1, sizeof(*op)); - if (!tag) { + if (!op) { json_object_put(val); return NULL; } - tag->val = val; - tag->type = T_CFUNC; - tag->data = fn; + op->val = val; + op->type = T_CFUNC; + op->tag.data = fn; - json_object_set_serializer(val, ut_c_fn_to_string, tag, ut_c_fn_free); + json_object_set_serializer(val, ut_c_fn_to_string, op, ut_c_fn_free); - return json_object_object_add(scope, name, tag->val); + return json_object_object_add(scope, name, op->val); } static struct json_object * -ut_print(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_print(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *item; size_t arridx, arrlen; @@ -333,7 +333,7 @@ ut_print(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_length(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_length(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *arg = json_object_array_get_idx(args, 0); @@ -350,7 +350,7 @@ ut_length(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_index(struct ut_state *s, struct ut_opcode *op, struct json_object *args, bool right) +ut_index(struct ut_state *s, uint32_t off, struct json_object *args, bool right) { struct json_object *stack = json_object_array_get_idx(args, 0); struct json_object *needle = json_object_array_get_idx(args, 1); @@ -392,19 +392,19 @@ ut_index(struct ut_state *s, struct ut_opcode *op, struct json_object *args, boo } static struct json_object * -ut_lindex(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_lindex(struct ut_state *s, uint32_t off, struct json_object *args) { - return ut_index(s, op, args, false); + return ut_index(s, off, args, false); } static struct json_object * -ut_rindex(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_rindex(struct ut_state *s, uint32_t off, struct json_object *args) { - return ut_index(s, op, args, true); + return ut_index(s, off, args, true); } static struct json_object * -ut_push(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_push(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *arr = json_object_array_get_idx(args, 0); struct json_object *item = NULL; @@ -423,7 +423,7 @@ ut_push(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_pop(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_pop(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *arr = json_object_array_get_idx(args, 0); struct json_object *item = NULL; @@ -444,7 +444,7 @@ ut_pop(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_shift(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_shift(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *arr = json_object_array_get_idx(args, 0); struct json_object *item = NULL; @@ -467,7 +467,7 @@ ut_shift(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_unshift(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_unshift(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *arr = json_object_array_get_idx(args, 0); struct json_object *item = NULL; @@ -492,7 +492,7 @@ ut_unshift(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_abs(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_abs(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *v = json_object_array_get_idx(args, 0); enum json_type t; @@ -511,7 +511,7 @@ ut_abs(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_atan2(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_atan2(struct ut_state *s, uint32_t off, struct json_object *args) { double d1 = ut_cast_double(json_object_array_get_idx(args, 0)); double d2 = ut_cast_double(json_object_array_get_idx(args, 1)); @@ -523,7 +523,7 @@ ut_atan2(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_chr(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_chr(struct ut_state *s, uint32_t off, struct json_object *args) { size_t len = json_object_array_length(args); size_t idx; @@ -536,7 +536,7 @@ ut_chr(struct ut_state *s, struct ut_opcode *op, struct json_object *args) str = calloc(1, len); if (!str) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); for (idx = 0; idx < len; idx++) { n = ut_cast_int64(json_object_array_get_idx(args, idx)); @@ -553,7 +553,7 @@ ut_chr(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_cos(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_cos(struct ut_state *s, uint32_t off, struct json_object *args) { double d = ut_cast_double(json_object_array_get_idx(args, 0)); @@ -564,7 +564,7 @@ ut_cos(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_delete(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_delete(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *obj = json_object_array_get_idx(args, 0); struct json_object *rv = NULL; @@ -587,15 +587,15 @@ ut_delete(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_die(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_die(struct ut_state *s, uint32_t off, struct json_object *args) { const char *msg = json_object_get_string(json_object_array_get_idx(args, 0)); - return ut_exception(s, op, "%s", msg ? msg : "Died"); + return ut_exception(s, off, "%s", msg ? msg : "Died"); } static struct json_object * -ut_exists(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_exists(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *obj = json_object_array_get_idx(args, 0); const char *key = json_object_get_string(json_object_array_get_idx(args, 1)); @@ -607,7 +607,7 @@ ut_exists(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } __attribute__((noreturn)) static struct json_object * -ut_exit(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_exit(struct ut_state *s, uint32_t off, struct json_object *args) { int64_t n = ut_cast_int64(json_object_array_get_idx(args, 0)); @@ -615,7 +615,7 @@ ut_exit(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_exp(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_exp(struct ut_state *s, uint32_t off, struct json_object *args) { double d = ut_cast_double(json_object_array_get_idx(args, 0)); @@ -626,7 +626,7 @@ ut_exp(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_getenv(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_getenv(struct ut_state *s, uint32_t off, struct json_object *args) { const char *key = json_object_get_string(json_object_array_get_idx(args, 0)); char *val = key ? getenv(key) : NULL; @@ -635,7 +635,7 @@ ut_getenv(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_filter(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_filter(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *obj = json_object_array_get_idx(args, 0); struct json_object *func = json_object_array_get_idx(args, 1); @@ -652,7 +652,7 @@ ut_filter(struct ut_state *s, struct ut_opcode *op, struct json_object *args) ut_putval(arr); ut_putval(cmpargs); - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); } json_object_array_put_idx(cmpargs, 2, json_object_get(obj)); @@ -661,7 +661,7 @@ ut_filter(struct ut_state *s, struct ut_opcode *op, struct json_object *args) json_object_array_put_idx(cmpargs, 0, json_object_get(json_object_array_get_idx(obj, arridx))); json_object_array_put_idx(cmpargs, 1, json_object_new_int64(arridx)); - rv = ut_invoke(s, op, NULL, func, cmpargs); + rv = ut_invoke(s, off, NULL, func, cmpargs); if (ut_val_is_truish(rv)) json_object_array_add(arr, json_object_get(json_object_array_get_idx(obj, arridx))); @@ -675,7 +675,7 @@ ut_filter(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_hex(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_hex(struct ut_state *s, uint32_t off, struct json_object *args) { const char *val = json_object_get_string(json_object_array_get_idx(args, 0)); int64_t n; @@ -693,7 +693,7 @@ ut_hex(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_int(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_int(struct ut_state *s, uint32_t off, struct json_object *args) { int64_t n = ut_cast_int64(json_object_array_get_idx(args, 0)); @@ -704,7 +704,7 @@ ut_int(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_join(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_join(struct ut_state *s, uint32_t off, struct json_object *args) { const char *sep = json_object_get_string(json_object_array_get_idx(args, 0)); struct json_object *arr = json_object_array_get_idx(args, 1); @@ -728,7 +728,7 @@ ut_join(struct ut_state *s, struct ut_opcode *op, struct json_object *args) p = res = calloc(1, len); if (!res) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); for (arrlen = json_object_array_length(arr), arridx = 0; arridx < arrlen; arridx++) { if (arridx > 0) { @@ -763,7 +763,7 @@ out: } static struct json_object * -ut_keys(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_keys(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *obj = json_object_array_get_idx(args, 0); struct json_object *arr = NULL; @@ -774,7 +774,7 @@ ut_keys(struct ut_state *s, struct ut_opcode *op, struct json_object *args) arr = json_object_new_array(); if (!arr) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); json_object_object_foreach(obj, key, val) json_object_array_add(arr, json_object_new_string(key)); @@ -783,7 +783,7 @@ ut_keys(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_lc(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_lc(struct ut_state *s, uint32_t off, struct json_object *args) { const char *str = json_object_get_string(json_object_array_get_idx(args, 0)); size_t len = str ? strlen(str) : 0; @@ -796,7 +796,7 @@ ut_lc(struct ut_state *s, struct ut_opcode *op, struct json_object *args) res = p = calloc(1, len); if (!res) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); while (*str) if (*str >= 'A' && *str <= 'Z') @@ -811,7 +811,7 @@ ut_lc(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_log(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_log(struct ut_state *s, uint32_t off, struct json_object *args) { double d = ut_cast_double(json_object_array_get_idx(args, 0)); @@ -822,7 +822,7 @@ ut_log(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_map(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_map(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *obj = json_object_array_get_idx(args, 0); struct json_object *func = json_object_array_get_idx(args, 1); @@ -839,7 +839,7 @@ ut_map(struct ut_state *s, struct ut_opcode *op, struct json_object *args) ut_putval(arr); ut_putval(cmpargs); - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); } json_object_array_put_idx(cmpargs, 2, json_object_get(obj)); @@ -848,7 +848,7 @@ ut_map(struct ut_state *s, struct ut_opcode *op, struct json_object *args) json_object_array_put_idx(cmpargs, 0, json_object_get(json_object_array_get_idx(obj, arridx))); json_object_array_put_idx(cmpargs, 1, json_object_new_int64(arridx)); - json_object_array_add(arr, ut_invoke(s, op, NULL, func, cmpargs)); + json_object_array_add(arr, ut_invoke(s, off, NULL, func, cmpargs)); } ut_putval(cmpargs); @@ -857,7 +857,7 @@ ut_map(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_ord(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_ord(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *obj = json_object_array_get_idx(args, 0); const char *str; @@ -874,7 +874,7 @@ ut_ord(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_rand(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_rand(struct ut_state *s, uint32_t off, struct json_object *args) { struct timeval tv; @@ -889,7 +889,7 @@ ut_rand(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_srand(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_srand(struct ut_state *s, uint32_t off, struct json_object *args) { int64_t n = ut_cast_int64(json_object_array_get_idx(args, 0)); @@ -900,10 +900,10 @@ ut_srand(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_type(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_type(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *v = json_object_array_get_idx(args, 0); - struct ut_opcode *tag = json_object_get_userdata(v); + struct ut_op *tag = json_object_get_userdata(v); switch (tag ? tag->type : 0) { case T_FUNC: @@ -936,7 +936,7 @@ ut_type(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_reverse(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_reverse(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *obj = json_object_array_get_idx(args, 0); struct json_object *rv = NULL; @@ -948,7 +948,7 @@ ut_reverse(struct ut_state *s, struct ut_opcode *op, struct json_object *args) rv = json_object_new_array(); if (!rv) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); for (arridx = json_object_array_length(obj); arridx > 0; arridx--) json_object_array_add(rv, json_object_get(json_object_array_get_idx(obj, arridx - 1))); @@ -959,7 +959,7 @@ ut_reverse(struct ut_state *s, struct ut_opcode *op, struct json_object *args) p = dup = calloc(1, len + 1); if (!dup) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); while (len > 0) *p++ = str[--len]; @@ -973,7 +973,7 @@ ut_reverse(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_sin(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_sin(struct ut_state *s, uint32_t off, struct json_object *args) { double d = ut_cast_double(json_object_array_get_idx(args, 0)); @@ -986,7 +986,7 @@ ut_sin(struct ut_state *s, struct ut_opcode *op, struct json_object *args) static struct { struct ut_state *s; - struct ut_opcode *op; + uint32_t off; struct json_object *fn; struct json_object *args; } sort_ctx; @@ -1005,7 +1005,7 @@ sort_fn(const void *k1, const void *k2) json_object_array_put_idx(sort_ctx.args, 0, *v1); json_object_array_put_idx(sort_ctx.args, 1, *v2); - rv = ut_invoke(sort_ctx.s, sort_ctx.op, NULL, sort_ctx.fn, sort_ctx.args); + rv = ut_invoke(sort_ctx.s, sort_ctx.off, NULL, sort_ctx.fn, sort_ctx.args); ret = !ut_val_is_truish(rv); ut_putval(rv); @@ -1014,7 +1014,7 @@ sort_fn(const void *k1, const void *k2) } static struct json_object * -ut_sort(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_sort(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *arr = json_object_array_get_idx(args, 0); struct json_object *fn = json_object_array_get_idx(args, 1); @@ -1024,12 +1024,12 @@ ut_sort(struct ut_state *s, struct ut_opcode *op, struct json_object *args) if (fn) { sort_ctx.s = s; - sort_ctx.op = op; + sort_ctx.off = off; sort_ctx.fn = fn; sort_ctx.args = json_object_new_array(); if (!sort_ctx.args) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); } json_object_array_sort(arr, sort_fn); @@ -1039,10 +1039,10 @@ ut_sort(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_splice(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_splice(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *arr = json_object_array_get_idx(args, 0); - int64_t off = ut_cast_int64(json_object_array_get_idx(args, 1)); + int64_t ofs = ut_cast_int64(json_object_array_get_idx(args, 1)); int64_t remlen = ut_cast_int64(json_object_array_get_idx(args, 2)); size_t arrlen, addlen, idx; @@ -1053,66 +1053,66 @@ ut_splice(struct ut_state *s, struct ut_opcode *op, struct json_object *args) addlen = json_object_array_length(args); if (addlen == 1) { - off = 0; + ofs = 0; addlen = 0; remlen = arrlen; } else if (addlen == 2) { - if (off < 0) { - off = arrlen + off; + if (ofs < 0) { + ofs = arrlen + ofs; - if (off < 0) - off = 0; + if (ofs < 0) + ofs = 0; } - else if (off > arrlen) { - off = arrlen; + else if (ofs > arrlen) { + ofs = arrlen; } addlen = 0; - remlen = arrlen - off; + remlen = arrlen - ofs; } else { - if (off < 0) { - off = arrlen + off; + if (ofs < 0) { + ofs = arrlen + ofs; - if (off < 0) - off = 0; + if (ofs < 0) + ofs = 0; } - else if (off > arrlen) { - off = arrlen; + else if (ofs > arrlen) { + ofs = arrlen; } if (remlen < 0) { - remlen = arrlen - off + remlen; + remlen = arrlen - ofs + remlen; if (remlen < 0) remlen = 0; } - else if (remlen > arrlen - off) { - remlen = arrlen - off; + else if (remlen > arrlen - ofs) { + remlen = arrlen - ofs; } addlen -= 3; } if (addlen < remlen) { - json_object_array_del_idx(arr, off, remlen - addlen); + json_object_array_del_idx(arr, ofs, remlen - addlen); } else if (addlen > remlen) { - for (idx = arrlen; idx > off; idx--) + for (idx = arrlen; idx > ofs; idx--) json_object_array_put_idx(arr, idx + addlen - remlen - 1, json_object_get(json_object_array_get_idx(arr, idx - 1))); } for (idx = 0; idx < addlen; idx++) - json_object_array_put_idx(arr, off + idx, + json_object_array_put_idx(arr, ofs + idx, json_object_get(json_object_array_get_idx(args, 3 + idx))); return json_object_get(arr); } static struct json_object * -ut_split(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_split(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *sep = json_object_array_get_idx(args, 0); struct json_object *str = json_object_array_get_idx(args, 1); @@ -1126,7 +1126,7 @@ ut_split(struct ut_state *s, struct ut_opcode *op, struct json_object *args) arr = json_object_new_array(); if (!arr) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); sepstr = json_object_get_string(sep); splitstr = json_object_get_string(str); @@ -1148,7 +1148,7 @@ ut_split(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_sqrt(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_sqrt(struct ut_state *s, uint32_t off, struct json_object *args) { double d = ut_cast_double(json_object_array_get_idx(args, 0)); @@ -1159,10 +1159,10 @@ ut_sqrt(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_substr(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_substr(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *str = json_object_array_get_idx(args, 0); - int64_t off = ut_cast_int64(json_object_array_get_idx(args, 1)); + int64_t ofs = ut_cast_int64(json_object_array_get_idx(args, 1)); int64_t sublen = ut_cast_int64(json_object_array_get_idx(args, 2)); const char *p; size_t len; @@ -1175,55 +1175,55 @@ ut_substr(struct ut_state *s, struct ut_opcode *op, struct json_object *args) switch (json_object_array_length(args)) { case 1: - off = 0; + ofs = 0; sublen = len; break; case 2: - if (off < 0) { - off = len + off; + if (ofs < 0) { + ofs = len + ofs; - if (off < 0) - off = 0; + if (ofs < 0) + ofs = 0; } - else if (off > len) { - off = len; + else if (ofs > len) { + ofs = len; } - sublen = len - off; + sublen = len - ofs; break; default: - if (off < 0) { - off = len + off; + if (ofs < 0) { + ofs = len + ofs; - if (off < 0) - off = 0; + if (ofs < 0) + ofs = 0; } - else if (off > len) { - off = len; + else if (ofs > len) { + ofs = len; } if (sublen < 0) { - sublen = len - off + sublen; + sublen = len - ofs + sublen; if (sublen < 0) sublen = 0; } - else if (sublen > len - off) { - sublen = len - off; + else if (sublen > len - ofs) { + sublen = len - ofs; } break; } - return json_object_new_string_len(p + off, sublen); + return json_object_new_string_len(p + ofs, sublen); } static struct json_object * -ut_time(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_time(struct ut_state *s, uint32_t off, struct json_object *args) { time_t t = time(NULL); @@ -1231,7 +1231,7 @@ ut_time(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_uc(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_uc(struct ut_state *s, uint32_t off, struct json_object *args) { const char *str = json_object_get_string(json_object_array_get_idx(args, 0)); size_t len = str ? strlen(str) : 0; @@ -1244,7 +1244,7 @@ ut_uc(struct ut_state *s, struct ut_opcode *op, struct json_object *args) res = p = calloc(1, len); if (!res) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); while (*str) if (*str >= 'a' && *str <= 'z') @@ -1259,7 +1259,7 @@ ut_uc(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_uchr(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_uchr(struct ut_state *s, uint32_t off, struct json_object *args) { size_t len = json_object_array_length(args); size_t idx, ulen; @@ -1285,7 +1285,7 @@ ut_uchr(struct ut_state *s, struct ut_opcode *op, struct json_object *args) str = calloc(1, ulen); if (!str) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); for (idx = 0, p = str, rem = ulen; idx < len; idx++) { n = ut_cast_int64(json_object_array_get_idx(args, idx)); @@ -1301,7 +1301,7 @@ ut_uchr(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_values(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_values(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *obj = json_object_array_get_idx(args, 0); struct json_object *arr; @@ -1312,7 +1312,7 @@ ut_values(struct ut_state *s, struct ut_opcode *op, struct json_object *args) arr = json_object_new_array(); if (!arr) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); json_object_object_foreach(obj, key, val) { (void)key; @@ -1323,7 +1323,7 @@ ut_values(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_trim_common(struct ut_state *s, struct ut_opcode *op, struct json_object *args, bool start, bool end) +ut_trim_common(struct ut_state *s, uint32_t off, struct json_object *args, bool start, bool end) { struct json_object *str = json_object_array_get_idx(args, 0); struct json_object *chr = json_object_array_get_idx(args, 1); @@ -1363,25 +1363,25 @@ ut_trim_common(struct ut_state *s, struct ut_opcode *op, struct json_object *arg } static struct json_object * -ut_trim(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_trim(struct ut_state *s, uint32_t off, struct json_object *args) { - return ut_trim_common(s, op, args, true, true); + return ut_trim_common(s, off, args, true, true); } static struct json_object * -ut_ltrim(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_ltrim(struct ut_state *s, uint32_t off, struct json_object *args) { - return ut_trim_common(s, op, args, true, false); + return ut_trim_common(s, off, args, true, false); } static struct json_object * -ut_rtrim(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_rtrim(struct ut_state *s, uint32_t off, struct json_object *args) { - return ut_trim_common(s, op, args, false, true); + return ut_trim_common(s, off, args, false, true); } static size_t -ut_printf_common(struct ut_state *s, struct ut_opcode *op, struct json_object *args, char **res) +ut_printf_common(struct ut_state *s, uint32_t off, struct json_object *args, char **res) { struct json_object *fmt = json_object_array_get_idx(args, 0); char *fp, sfmt[sizeof("%0- 123456789.123456789%")]; @@ -1567,29 +1567,29 @@ err: } static struct json_object * -ut_sprintf(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_sprintf(struct ut_state *s, uint32_t off, struct json_object *args) { char *str = NULL; size_t len; - len = ut_printf_common(s, op, args, &str); + len = ut_printf_common(s, off, args, &str); if (!str) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); return json_object_new_string_len(str, len); } static struct json_object * -ut_printf(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_printf(struct ut_state *s, uint32_t off, struct json_object *args) { char *str = NULL; size_t len; - len = ut_printf_common(s, op, args, &str); + len = ut_printf_common(s, off, args, &str); if (!str) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); len = fwrite(str, 1, len, stdout); @@ -1597,7 +1597,7 @@ ut_printf(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_require_so(struct ut_state *s, struct ut_opcode *op, const char *path) +ut_require_so(struct ut_state *s, uint32_t off, const char *path) { void (*init)(const struct ut_ops *, struct ut_state *, struct json_object *); struct json_object *scope; @@ -1611,17 +1611,17 @@ ut_require_so(struct ut_state *s, struct ut_opcode *op, const char *path) dlh = dlopen(path, RTLD_LAZY|RTLD_LOCAL); if (!dlh) - return ut_exception(s, op, "Unable to dlopen file %s: %s", path, dlerror()); + return ut_exception(s, off, "Unable to dlopen file %s: %s", path, dlerror()); init = dlsym(dlh, "ut_module_init"); if (!init) - return ut_exception(s, op, "Module %s provides no 'ut_module_init' function", path); + return ut_exception(s, off, "Module %s provides no 'ut_module_init' function", path); scope = json_object_new_object(); if (!scope) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); init(&ut, s, scope); @@ -1629,7 +1629,7 @@ ut_require_so(struct ut_state *s, struct ut_opcode *op, const char *path) } static struct json_object * -ut_require_utpl(struct ut_state *s, struct ut_opcode *op, const char *path) +ut_require_utpl(struct ut_state *s, uint32_t off, const char *path) { struct json_object *ex, *scope; char *source, *msg; @@ -1642,14 +1642,14 @@ ut_require_utpl(struct ut_state *s, struct ut_opcode *op, const char *path) sfile = fopen(path, "rb"); if (!sfile) - return ut_exception(s, op, "Unable to open file %s: %s", path, strerror(errno)); + return ut_exception(s, off, "Unable to open file %s: %s", path, strerror(errno)); source = calloc(1, st.st_size + 1); if (!source) { fclose(sfile); - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); } fread(source, 1, st.st_size, sfile); @@ -1657,7 +1657,7 @@ ut_require_utpl(struct ut_state *s, struct ut_opcode *op, const char *path) if (ut_parse(s, source)) { msg = ut_format_error(s, source); - ex = ut_exception(s, op, "Module loading failed: %s", msg); + ex = ut_exception(s, off, "Module loading failed: %s", msg); free(source); free(msg); @@ -1670,13 +1670,13 @@ ut_require_utpl(struct ut_state *s, struct ut_opcode *op, const char *path) scope = json_object_new_object(); if (!scope) - return ut_exception(s, op, UT_ERRMSG_OOM); + return ut_exception(s, off, UT_ERRMSG_OOM); - return ut_invoke(s, op, scope, s->main->val, NULL); + return ut_invoke(s, off, scope, ut_get_op(s, s->main)->val, NULL); } static struct json_object * -ut_require_path(struct ut_state *s, struct ut_opcode *op, const char *path_template, const char *name) +ut_require_path(struct ut_state *s, uint32_t off, const char *path_template, const char *name) { struct json_object *rv = NULL; const char *p, *q, *last; @@ -1706,9 +1706,9 @@ ut_require_path(struct ut_state *s, struct ut_opcode *op, const char *path_templ } if (!strcmp(p, ".so")) - rv = ut_require_so(s, op, path); + rv = ut_require_so(s, off, path); else if (!strcmp(p, ".utpl")) - rv = ut_require_utpl(s, op, path); + rv = ut_require_utpl(s, off, path); invalid: free(path); @@ -1717,7 +1717,7 @@ invalid: } static struct json_object * -ut_require(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_require(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *val = json_object_array_get_idx(args, 0); struct json_object *search, *se, *res; @@ -1731,7 +1731,7 @@ ut_require(struct ut_state *s, struct ut_opcode *op, struct json_object *args) search = json_object_object_get(s->stack.scope[0], "REQUIRE_SEARCH_PATH"); if (!json_object_is_type(search, json_type_array)) - return ut_exception(s, op, "Global require search path not set"); + return ut_exception(s, off, "Global require search path not set"); for (arridx = 0, arrlen = json_object_array_length(search); arridx < arrlen; arridx++) { se = json_object_array_get_idx(search, arridx); @@ -1739,13 +1739,13 @@ ut_require(struct ut_state *s, struct ut_opcode *op, struct json_object *args) if (!json_object_is_type(se, json_type_string)) continue; - res = ut_require_path(s, op, json_object_get_string(se), name); + res = ut_require_path(s, off, json_object_get_string(se), name); if (res) return res; } - return ut_exception(s, op, "No module named '%s' could be found", name); + return ut_exception(s, off, "No module named '%s' could be found", name); } const struct ut_ops ut = { @@ -20,7 +20,11 @@ #include "ast.h" #include "lexer.h" -typedef struct json_object *(ut_c_fn)(struct ut_state *, struct ut_opcode *, struct json_object *); +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif + +typedef struct json_object *(ut_c_fn)(struct ut_state *, uint32_t, struct json_object *); void ut_lib_init(struct ut_state *state, struct json_object *scope); @@ -32,7 +32,7 @@ static struct json_object *dir_proto; static int last_error = 0; static struct json_object * -ut_fs_error(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_fs_error(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *errmsg; @@ -47,7 +47,7 @@ ut_fs_error(struct ut_state *s, struct ut_opcode *op, struct json_object *args) static struct json_object * -ut_fs_close(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_fs_close(struct ut_state *s, uint32_t off, struct json_object *args) { FILE **fp = (FILE **)ops->get_type(s->ctx, "fs.file"); @@ -61,7 +61,7 @@ ut_fs_close(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_fs_read(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_fs_read(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *limit = json_object_array_get_idx(args, 0); struct json_object *rv = NULL; @@ -153,7 +153,7 @@ ut_fs_read(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_fs_write(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_fs_write(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *data = json_object_array_get_idx(args, 0); size_t len, wsize; @@ -182,9 +182,9 @@ ut_fs_write(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_fs_seek(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_fs_seek(struct ut_state *s, uint32_t off, struct json_object *args) { - struct json_object *off = json_object_array_get_idx(args, 0); + struct json_object *ofs = json_object_array_get_idx(args, 0); struct json_object *how = json_object_array_get_idx(args, 1); int whence, res; long offset; @@ -194,12 +194,12 @@ ut_fs_seek(struct ut_state *s, struct ut_opcode *op, struct json_object *args) if (!fp || !*fp) err_return(EBADF); - if (!off) + if (!ofs) offset = 0; - else if (!json_object_is_type(off, json_type_int)) + else if (!json_object_is_type(ofs, json_type_int)) err_return(EINVAL); else - offset = (long)json_object_get_int64(off); + offset = (long)json_object_get_int64(ofs); if (!how) whence = 0; @@ -217,7 +217,7 @@ ut_fs_seek(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_fs_tell(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_fs_tell(struct ut_state *s, uint32_t off, struct json_object *args) { long offset; @@ -235,7 +235,7 @@ ut_fs_tell(struct ut_state *s, struct ut_opcode *op, struct json_object *args) } static struct json_object * -ut_fs_open(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_fs_open(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *path = json_object_array_get_idx(args, 0); struct json_object *mode = json_object_array_get_idx(args, 1); @@ -263,7 +263,7 @@ ut_fs_open(struct ut_state *s, struct ut_opcode *op, struct json_object *args) static struct json_object * -ut_fs_readdir(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_fs_readdir(struct ut_state *s, uint32_t off, struct json_object *args) { DIR **dp = (DIR **)ops->get_type(s->ctx, "fs.dir"); struct dirent *e; @@ -281,7 +281,7 @@ ut_fs_readdir(struct ut_state *s, struct ut_opcode *op, struct json_object *args } static struct json_object * -ut_fs_closedir(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_fs_closedir(struct ut_state *s, uint32_t off, struct json_object *args) { DIR **dp = (DIR **)ops->get_type(s->ctx, "fs.dir"); @@ -295,7 +295,7 @@ ut_fs_closedir(struct ut_state *s, struct ut_opcode *op, struct json_object *arg } static struct json_object * -ut_fs_opendir(struct ut_state *s, struct ut_opcode *op, struct json_object *args) +ut_fs_opendir(struct ut_state *s, uint32_t off, struct json_object *args) { struct json_object *path = json_object_array_get_idx(args, 0); struct json_object *diro; @@ -47,9 +47,9 @@ print_usage(char *app) } #ifndef NDEBUG -static void dump(struct ut_opcode *op, int level); +static void dump(struct ut_state *s, uint32_t off, int level); -static void dump_node(struct ut_opcode *op) { +static void dump_node(struct ut_op *op) { const char *p; switch (op->type) { @@ -96,22 +96,24 @@ static void dump_node(struct ut_opcode *op) { } } -static void dump(struct ut_opcode *op, int level) { - struct ut_opcode *prev, *cur; +static void dump(struct ut_state *s, uint32_t off, int level) { + struct ut_op *prev, *cur, *child; int i; if (level == 0) { printf("digraph G {\nmain [shape=box];\n"); } - for (prev = NULL, cur = op; cur; prev = cur, cur = cur->sibling) { + for (prev = NULL, cur = ut_get_op(s, off); cur; prev = cur, cur = ut_get_op(s, cur->tree.next)) { dump_node(cur); if (cur->type < __T_MAX) { - for (i = 0; i < sizeof(cur->operand) / sizeof(cur->operand[0]); i++) { - if (cur->operand[i]) { - dump(cur->operand[i], level + 1); - printf("n%p -> n%p [label=\"op%d\"];\n", cur, cur->operand[i], i + 1); + for (i = 0; i < ARRAY_SIZE(cur->tree.operand) && cur->tree.operand[i]; i++) { + child = ut_get_op(s, cur->tree.operand[i]); + + if (cur->tree.operand[i]) { + dump(s, cur->tree.operand[i], level + 1); + printf("n%p -> n%p [label=\"op%d\"];\n", cur, child, i + 1); } } } @@ -121,7 +123,7 @@ static void dump(struct ut_opcode *op, int level) { } if (level == 0) { - printf("main -> n%p [style=dotted];\n", op); + printf("main -> n%p [style=dotted];\n", ut_get_op(s, off)); printf("}\n"); } @@ -143,7 +145,7 @@ parse(const char *source, bool dumponly) fprintf(stderr, "Debug support not compiled in\n"); err = UT_ERROR_EXCEPTION; #else /* NDEBUG */ - dump(state->main, 0); + dump(state, state->main, 0); #endif /* NDEBUG */ } else { @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -%token_type {struct ut_opcode *} +%token_type {uint32_t} %extra_argument {struct ut_state *s} %nonassoc T_LEXP T_REXP T_LSTM T_RSTM. @@ -59,28 +59,35 @@ #define YYNOERRORRECOVERY #define new_op(type, val, ...) \ - ut_new_op(s, type, val, ##__VA_ARGS__, (void *)1) + ut_new_op(s, type, val, ##__VA_ARGS__, UINT32_MAX) #define wrap_op(op, ...) \ - ut_wrap_op(op, ##__VA_ARGS__, (void *)1) + ut_wrap_op(s, op, ##__VA_ARGS__, UINT32_MAX) -#define append_op ut_append_op +#define append_op(op1, op2) \ + ut_append_op(s, op1, op2) #define no_empty_obj(op) \ - ((!op || op->type != T_LBRACE || op->operand[0]) ? op : NULL) + ut_no_empty_obj(s, op) -#define new_func(name, args, body) \ - ut_new_func(s, name, args, body) +static inline uint32_t +ut_no_empty_obj(struct ut_state *s, uint32_t off) +{ + struct ut_op *op = ut_get_op(s, off); + + return (!op || op->type != T_LBRACE || op->tree.operand[0]) ? off : 0; +} } %syntax_error { + struct ut_op *op = TOKEN ? ut_get_op(s, TOKEN) : NULL; int i; s->error.code = UT_ERROR_UNEXPECTED_TOKEN; - if (TOKEN) - s->off = TOKEN->off; + if (op) + s->off = op->off; for (i = 0; i < sizeof(tokennames) / sizeof(tokennames[0]); i++) if (yy_find_shift_action(yypParser, (YYCODETYPE)i) < YYNSTATE + YYNRULE) @@ -88,8 +95,8 @@ } -input ::= chunks(A). { s->main = new_func(NULL, NULL, A); } -input ::= . { s->main = new_func(NULL, NULL, new_op(T_TEXT, json_object_new_string(""))); } +input ::= chunks(A). { s->main = new_op(T_FUNC, NULL, 0, 0, A); } +input ::= . { s->main = new_op(T_TEXT, json_object_new_string("")); s->main = new_op(T_FUNC, NULL, 0, 0, s->main); } chunks(A) ::= chunks(B) T_TEXT(C). { A = B ? append_op(B, C) : C; } chunks(A) ::= chunks(B) tplexp(C). { A = B ? append_op(B, C) : C; } @@ -116,7 +123,7 @@ stmt(A) ::= decl_stmt(B). { A = B; } cpd_stmt(A) ::= T_LBRACE stmts(B) T_RBRACE. { A = B; } exp_stmt(A) ::= exp(B) T_SCOL. { A = B; } -exp_stmt(A) ::= T_SCOL. { A = NULL; } +exp_stmt(A) ::= T_SCOL. { A = 0; } sel_stmt(A) ::= T_IF(B) T_LPAREN exp(C) T_RPAREN stmt(D) T_ELSE stmt(E). { A = wrap_op(B, C, no_empty_obj(D), no_empty_obj(E)); } @@ -145,17 +152,17 @@ iter_stmt(A) ::= T_FOR(B) T_LPAREN exp_stmt(C) exp_stmt(D) exp(E) T_RPAREN T_COL { A = wrap_op(B, C, D, E, F); } func_stmt(A) ::= T_FUNC T_LABEL(B) T_LPAREN T_RPAREN cpd_stmt(C). - { A = new_func(B, NULL, C); } + { A = new_op(T_FUNC, NULL, B, 0, C); } func_stmt(A) ::= T_FUNC T_LABEL(B) T_LPAREN T_RPAREN empty_object. - { A = new_func(B, NULL, NULL); } + { A = new_op(T_FUNC, NULL, B, 0, 0); } func_stmt(A) ::= T_FUNC T_LABEL(B) T_LPAREN T_RPAREN T_COLON chunks(C) T_ENDFUNC. - { A = new_func(B, NULL, C); } + { A = new_op(T_FUNC, NULL, B, 0, C); } func_stmt(A) ::= T_FUNC T_LABEL(B) T_LPAREN args(C) T_RPAREN cpd_stmt(D). - { A = new_func(B, C, D); } + { A = new_op(T_FUNC, NULL, B, C, D); } func_stmt(A) ::= T_FUNC T_LABEL(B) T_LPAREN args(C) T_RPAREN empty_object. - { A = new_func(B, C, NULL); } + { A = new_op(T_FUNC, NULL, B, C, 0); } func_stmt(A) ::= T_FUNC T_LABEL(B) T_LPAREN args(C) T_RPAREN T_COLON chunks(D) T_ENDFUNC. - { A = new_func(B, C, D); } + { A = new_op(T_FUNC, NULL, B, C, D); } args(A) ::= args(B) T_COMMA T_LABEL(C). { A = append_op(B, C); } args(A) ::= T_LABEL(B). { A = B; } @@ -245,14 +252,14 @@ unary_exp(A) ::= T_COMPL(B) unary_exp(C). { A = wrap_op(B, C); } unary_exp(A) ::= T_NOT(B) unary_exp(C). { A = wrap_op(B, C); } unary_exp(A) ::= postfix_exp(B). { A = B; } -postfix_exp(A) ::= unary_exp(B) T_INC(C). { A = wrap_op(C, B); A->val = (void *)1; } -postfix_exp(A) ::= unary_exp(B) T_DEC(C). { A = wrap_op(C, B); A->val = (void *)1; } +postfix_exp(A) ::= unary_exp(B) T_INC(C). { A = wrap_op(C, B); ut_get_op(s, A)->val = (void *)1; } +postfix_exp(A) ::= unary_exp(B) T_DEC(C). { A = wrap_op(C, B); ut_get_op(s, A)->val = (void *)1; } postfix_exp(A) ::= unary_exp(B) T_LPAREN(C) T_RPAREN. { A = wrap_op(C, B); } postfix_exp(A) ::= unary_exp(B) T_LPAREN(C) arg_exp(D) T_RPAREN. { A = wrap_op(C, B, D); } postfix_exp(A) ::= postfix_exp(B) T_DOT(C) T_LABEL(D). { A = wrap_op(C, B, D); } postfix_exp(A) ::= postfix_exp(B) T_LBRACK(C) assign_exp(D) T_RBRACK. - { A = wrap_op(C, B, D); A->val = (void *)1; } + { A = wrap_op(C, B, D); ut_get_op(s, A)->val = (void *)1; } postfix_exp(A) ::= primary_exp(B). { A = B; } primary_exp(A) ::= T_BOOL(B). { A = B; } @@ -266,13 +273,13 @@ primary_exp(A) ::= array(B). { A = B; } primary_exp(A) ::= object(B). { A = B; } primary_exp(A) ::= T_LPAREN assign_exp(B) T_RPAREN. { A = B; } primary_exp(A) ::= T_FUNC T_LPAREN T_RPAREN empty_object. - { A = new_func(NULL, NULL, NULL); } + { A = new_op(T_FUNC, NULL, 0, 0, 0); } primary_exp(A) ::= T_FUNC T_LPAREN args(B) T_RPAREN empty_object. - { A = new_func(NULL, B, NULL); } + { A = new_op(T_FUNC, NULL, 0, B, 0); } primary_exp(A) ::= T_FUNC T_LPAREN T_RPAREN cpd_stmt(B). - { A = new_func(NULL, NULL, B); } + { A = new_op(T_FUNC, NULL, 0, 0, B); } primary_exp(A) ::= T_FUNC T_LPAREN args(B) T_RPAREN cpd_stmt(C). - { A = new_func(NULL, B, C); } + { A = new_op(T_FUNC, NULL, 0, B, C); } array(A) ::= T_LBRACK(B) T_RBRACK. { A = B; } array(A) ::= T_LBRACK(B) exp(C) T_RBRACK. { A = wrap_op(B, C); } |