diff options
-rw-r--r-- | ast.c | 78 | ||||
-rw-r--r-- | ast.h | 43 | ||||
-rw-r--r-- | eval.c | 416 | ||||
-rw-r--r-- | lexer.c | 83 | ||||
-rw-r--r-- | lib.c | 116 | ||||
-rw-r--r-- | main.c | 49 | ||||
-rw-r--r-- | parser.y | 139 |
7 files changed, 454 insertions, 470 deletions
@@ -54,28 +54,25 @@ uc_new_op(struct uc_state *s, int type, struct json_object *val, ...) va_start(ap, val); - while (n_op < ARRAY_SIZE(newop->tree.operand) && (child = va_arg(ap, uint32_t)) != UINT32_MAX) + while (n_op < OPn_NUM && (child = va_arg(ap, uint32_t)) != UINT32_MAX) newop->tree.operand[n_op++] = child; va_end(ap); - s->poolsize++; - - return s->poolsize; + return s->poolsize++; } uint32_t -uc_wrap_op(struct uc_state *s, uint32_t parent, ...) +uc_wrap_op(struct uc_state *state, uint32_t parent, ...) { - struct uc_op *op = uc_get_op(s, parent); uint32_t child; int n_op = 0; va_list ap; va_start(ap, parent); - while (n_op < ARRAY_SIZE(op->tree.operand) && (child = va_arg(ap, uint32_t)) != UINT32_MAX) - op->tree.operand[n_op++] = child; + while (n_op < OPn_NUM && (child = va_arg(ap, uint32_t)) != UINT32_MAX) + OPn(parent, n_op++) = child; va_end(ap); @@ -83,14 +80,16 @@ uc_wrap_op(struct uc_state *s, uint32_t parent, ...) } uint32_t -uc_append_op(struct uc_state *s, uint32_t a, uint32_t b) +uc_append_op(struct uc_state *state, uint32_t a, uint32_t b) { - struct uc_op *tail = uc_get_op(s, a); + uint32_t tail_off, next_off; - while (tail && tail->tree.next) - tail = uc_get_op(s, tail->tree.next); + for (tail_off = a, next_off = OP_NEXT(tail_off); + next_off != 0; + tail_off = next_off, next_off = OP_NEXT(next_off)) + ; - tail->tree.next = b; + OP_NEXT(tail_off) = b; return a; } @@ -303,49 +302,50 @@ func_to_string(struct json_object *v, struct printbuf *pb, int level, int flags) } struct json_object * -uc_new_func(struct uc_state *s, struct uc_op *decl, struct uc_scope *scope) +uc_new_func(struct uc_state *state, uint32_t decl, struct uc_scope *scope) { struct json_object *val = xjs_new_object(); - struct uc_op *op, *name, *args, *arg; + uint32_t name_off, args_off, arg_off; struct uc_function *fn; + struct uc_op *op; size_t sz; sz = ALIGN(sizeof(*op)) + ALIGN(sizeof(*fn)); - name = uc_get_op(s, decl->tree.operand[0]); - args = uc_get_op(s, decl->tree.operand[1]); + name_off = OPn(decl, 0); + args_off = OPn(decl, 1); - if (name) - sz += ALIGN(json_object_get_string_len(name->val) + 1); + if (name_off) + sz += ALIGN(json_object_get_string_len(OP_VAL(name_off)) + 1); op = xalloc(sz); fn = (void *)op + ALIGN(sizeof(*op)); - fn->entry = decl->tree.operand[2]; + fn->entry = OPn(decl, 2); - if (name) - fn->name = strcpy((char *)fn + ALIGN(sizeof(*fn)), json_object_get_string(name->val)); + if (name_off) + fn->name = strcpy((char *)fn + ALIGN(sizeof(*fn)), json_object_get_string(OP_VAL(name_off))); - if (args) { + if (args_off) { fn->args = xjs_new_array(); - for (arg = args; arg; arg = uc_get_op(s, arg->tree.next)) { - json_object_array_add(fn->args, json_object_get(arg->val)); + for (arg_off = args_off; arg_off != 0; arg_off = OP_NEXT(arg_off)) { + json_object_array_add(fn->args, json_object_get(OP_VAL(arg_off))); /* if the last argument is a rest one (...arg), add extra null entry */ - if (arg->is_ellip) { + if (OP_IS_ELLIP(arg_off)) { json_object_array_add(fn->args, NULL); break; } } } - fn->source = s->function ? s->function->source : NULL; + fn->source = state->function ? state->function->source : NULL; fn->parent_scope = uc_acquire_scope(scope); op->val = val; op->type = T_FUNC; - op->is_arrow = (decl->type == T_ARROW); + op->is_arrow = (OP_TYPE(decl) == T_ARROW); op->tag.data = fn; json_object_set_serializer(val, func_to_string, op, func_free); @@ -568,36 +568,34 @@ uc_free(struct uc_state *s) } struct json_object * -uc_parse(struct uc_state *s, FILE *fp) +uc_parse(struct uc_state *state, FILE *fp) { - struct uc_op *op; void *pParser; uint32_t off; - uc_reset(s); + uc_reset(state); pParser = ParseAlloc(xalloc); - while (s->lex.state != UT_LEX_EOF) { - off = uc_get_token(s, fp); - op = uc_get_op(s, off); + while (state->lex.state != UT_LEX_EOF) { + off = uc_get_token(state, fp); - if (s->exception) + if (state->exception) goto out; - if (op) - Parse(pParser, op->type, off, s); + if (off) + Parse(pParser, OP_TYPE(off), off, state); - if (s->exception) + if (state->exception) goto out; } - Parse(pParser, 0, 0, s); + Parse(pParser, 0, 0, state); out: ParseFree(pParser, free); - return s->exception; + return state->exception; } bool @@ -154,34 +154,31 @@ struct uc_extended_type { void (*free)(void *); }; -static inline struct uc_op *uc_get_op(struct uc_state *s, uint32_t off) -{ - if (off == 0 || off > s->poolsize) - return NULL; - - return &s->pool[off - 1]; -} - -static inline struct uc_op *uc_get_child(struct uc_state *s, uint32_t off, int n) -{ - struct uc_op *op = uc_get_op(s, off); - - if (!op || n >= ARRAY_SIZE(op->tree.operand) || !op->tree.operand[n]) - return NULL; - - return uc_get_op(s, op->tree.operand[n]); -} - -static inline uint32_t uc_get_off(struct uc_state *s, struct uc_op *op) { - return op ? (op - s->pool + 1) : 0; -}; - static inline bool uc_is_type(struct json_object *val, int type) { struct uc_op *tag = json_object_get_userdata(val); return (tag && tag->type == type); }; +#define OP(idx) (&state->pool[idx]) +#define OP_POS(idx) OP(idx)->off +#define OP_VAL(idx) OP(idx)->val +#define OP_TYPE(idx) OP(idx)->type +#define OP_NEXT(idx) OP(idx)->tree.next +#define OP_IS_LIST(idx) OP(idx)->is_list +#define OP_IS_ELLIP(idx) OP(idx)->is_ellip +#define OP_IS_FOR_IN(idx) OP(idx)->is_for_in +#define OP_IS_POSTFIX(idx) OP(idx)->is_postfix + +#define OPn_NUM ARRAY_SIZE(((struct uc_op *)NULL)->tree.operand) +#define OPn(idx, n) OP(idx)->tree.operand[n] +#define OPn_POS(idx, n) OP(OPn(idx, n))->off +#define OPn_VAL(idx, n) OP(OPn(idx, n))->val +#define OPn_TYPE(idx, n) OP(OPn(idx, n))->type +#define OPn_IS_LIST(idx, n) OP(OPn(idx, n))->is_list +#define OPn_IS_OVERFLOW(idx, n) OP(OPn(idx, n))->is_overflow + + uint32_t uc_new_op(struct uc_state *s, int type, struct json_object *val, ...); uint32_t uc_wrap_op(struct uc_state *s, uint32_t parent, ...); @@ -189,7 +186,7 @@ uint32_t uc_append_op(struct uc_state *s, uint32_t a, uint32_t b); struct json_object *uc_parse(struct uc_state *s, FILE *fp); void uc_free(struct uc_state *s); -struct json_object *uc_new_func(struct uc_state *s, struct uc_op *decl, struct uc_scope *scope); +struct json_object *uc_new_func(struct uc_state *s, uint32_t decl, struct uc_scope *scope); struct json_object *uc_new_object(struct json_object *proto); struct json_object *uc_new_double(double v); struct json_object *uc_new_null(void); @@ -145,15 +145,15 @@ uc_execute_list(struct uc_state *state, uint32_t off); static char * uc_ref_to_str(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); - struct uc_op *op2 = uc_get_child(state, off, 1); + int child_type = OPn_TYPE(off, 1); + int op_type = OP_TYPE(off); const char *l; char *s, *p; - switch (op ? op->type : 0) { + switch (op_type) { case T_DOT: - s = uc_ref_to_str(state, op->tree.operand[0]); - l = ((op2 ? op2->type : 0) == T_LABEL) ? json_object_get_string(op2->val) : "???"; + s = uc_ref_to_str(state, OPn(off, 0)); + l = (child_type == T_LABEL) ? json_object_get_string(OPn_VAL(off, 1)) : "???"; if (asprintf(&p, "%s.%s", s ? s : "(...)", l) == -1) p = NULL; @@ -163,23 +163,23 @@ uc_ref_to_str(struct uc_state *state, uint32_t off) return p; case T_LBRACK: - if (!op->is_postfix) + if (!OP_IS_POSTFIX(off)) return NULL; /* fall through */ case T_LPAREN: - s = uc_ref_to_str(state, op->tree.operand[0]); + s = uc_ref_to_str(state, OPn(off, 0)); - switch (op2 ? op2->type : 0) { + switch (child_type) { case T_STRING: - l = json_object_to_json_string_ext(op2->val, JSON_C_TO_STRING_NOSLASHESCAPE); + l = json_object_to_json_string_ext(OPn_VAL(off, 1), JSON_C_TO_STRING_NOSLASHESCAPE); break; case T_NUMBER: case T_LABEL: case T_BOOL: - l = json_object_get_string(op2->val); + l = json_object_get_string(OPn_VAL(off, 1)); break; default: @@ -187,8 +187,8 @@ uc_ref_to_str(struct uc_state *state, uint32_t off) } if (asprintf(&p, "%s%c%s%c", s ? s : "(...)", - (op->type == T_LPAREN) ? '(' : '[', l, - (op->type == T_LPAREN) ? ')' : ']') == -1) + (op_type == T_LPAREN) ? '(' : '[', l, + (op_type == T_LPAREN) ? ')' : ']') == -1) p = NULL; free(s); @@ -196,7 +196,7 @@ uc_ref_to_str(struct uc_state *state, uint32_t off) return p; case T_LABEL: - return strdup(json_object_get_string(op->val)); + return strdup(json_object_get_string(OP_VAL(off))); default: return NULL; @@ -206,22 +206,22 @@ uc_ref_to_str(struct uc_state *state, uint32_t off) static struct json_object * uc_getref(struct uc_state *state, uint32_t off, struct json_object **key) { - struct uc_op *op = uc_get_op(state, off); - uint32_t off1 = op ? op->tree.operand[0] : 0; - uint32_t off2 = op ? op->tree.operand[1] : 0; + uint32_t off1 = OPn(off, 0); + uint32_t off2 = OPn(off, 1); + int type = OP_TYPE(off); struct uc_scope *sc, *next; struct json_object *val; if (key) *key = NULL; - if (op && op->type == T_DOT) { + if (type == T_DOT) { if (key) - *key = off2 ? json_object_get(uc_get_op(state, off2)->val) : NULL; + *key = off2 ? json_object_get(OP_VAL(off2)) : NULL; return uc_execute_op_sequence(state, off1); } - else if (op && op->type == T_LBRACK && op->is_postfix) { + else if (type == T_LBRACK && OP_IS_POSTFIX(off)) { if (key) { val = off2 ? uc_execute_op_sequence(state, off2) : NULL; @@ -233,20 +233,20 @@ uc_getref(struct uc_state *state, uint32_t off, struct json_object **key) return uc_execute_op_sequence(state, off1); } - else if (op && op->type == T_LABEL) { + else if (type == T_LABEL) { sc = state->scope; while (true) { - if (json_object_object_get_ex(sc->scope, json_object_get_string(op->val), NULL)) + if (json_object_object_get_ex(sc->scope, json_object_get_string(OP_VAL(off)), NULL)) break; next = uc_parent_scope(sc); if (!next) { if (state->strict_declarations) { - return uc_new_exception(state, op->off, + return uc_new_exception(state, OP_POS(off), "Reference error: access to undeclared variable %s", - json_object_get_string(op->val)); + json_object_get_string(OP_VAL(off))); } break; @@ -256,7 +256,7 @@ uc_getref(struct uc_state *state, uint32_t off, struct json_object **key) } if (key) - *key = json_object_get(op->val); + *key = json_object_get(OP_VAL(off)); return json_object_get(sc->scope); } @@ -271,7 +271,7 @@ uc_getref(struct uc_state *state, uint32_t off, struct json_object **key) static struct json_object * uc_getref_required(struct uc_state *state, uint32_t off, struct json_object **key) { - struct uc_op *op1 = uc_get_child(state, off, 0); + uint32_t child_off = OPn(off, 0); struct json_object *scope, *skey, *rv; char *lhs; @@ -280,15 +280,17 @@ uc_getref_required(struct uc_state *state, uint32_t off, struct json_object **ke if (!json_object_is_type(scope, json_type_array) && !json_object_is_type(scope, json_type_object)) { if (!uc_is_type(scope, T_EXCEPTION)) { - lhs = op1 ? uc_ref_to_str(state, uc_get_off(state, op1)) : NULL; + lhs = child_off ? uc_ref_to_str(state, child_off) : NULL; if (lhs) { - rv = uc_new_exception(state, op1->off, "Type error: `%s` is %s", + rv = uc_new_exception(state, OPn_POS(off, 0), + "Type error: `%s` is %s", lhs, scope ? "not an array or object" : "null"); free(lhs); } else { - rv = uc_new_exception(state, op1->off, "Type error: left-hand side is not an array or object"); + rv = uc_new_exception(state, OPn_POS(off, 0), + "Type error: left-hand side is not an array or object"); } json_object_put(scope); @@ -310,12 +312,12 @@ uc_getref_required(struct uc_state *state, uint32_t off, struct json_object **ke static struct json_object * uc_getproto(struct json_object *obj) { - struct uc_op *op = json_object_get_userdata(obj); + struct uc_op *tag = json_object_get_userdata(obj); - if (!op || (op->type != T_LBRACE && op->type <= __T_MAX) || !op->val) + if (!tag || (tag->type != T_LBRACE && tag->type <= __T_MAX) || !tag->val) return NULL; - return op->tag.proto; + return tag->tag.proto; } static struct json_object * @@ -390,17 +392,16 @@ uc_setval(struct json_object *scope, struct json_object *key, struct json_object static struct json_object * uc_execute_assign(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); - uint32_t label = op ? op->tree.operand[0] : 0; - uint32_t value = op ? op->tree.operand[1] : 0; + uint32_t label_off = OPn(off, 0); + uint32_t value_off = OPn(off, 1); struct json_object *scope, *key, *val; - scope = uc_getref_required(state, label, &key); + scope = uc_getref_required(state, label_off, &key); if (!key) return scope; - val = uc_execute_op_sequence(state, value); + val = uc_execute_op_sequence(state, value_off); if (!uc_is_type(val, T_EXCEPTION)) uc_setval(scope, key, val); @@ -414,18 +415,14 @@ uc_execute_assign(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_local(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off), *asop, *alop; - uint32_t as = op ? op->tree.operand[0] : 0; struct json_object *val, *rv = NULL; + uint32_t assign_off, label_off; - while (as) { - asop = uc_get_op(state, as); - as = asop ? asop->tree.next : 0; - - switch (asop ? asop->type : 0) { + for (assign_off = OPn(off, 0); assign_off != 0; assign_off = OP_NEXT(assign_off)) { + switch (OP_TYPE(assign_off)) { case T_ASSIGN: - alop = uc_get_op(state, asop->tree.operand[0]); - val = uc_execute_op_sequence(state, asop->tree.operand[1]); + label_off = OPn(assign_off, 0); + val = uc_execute_op_sequence(state, OPn(assign_off, 1)); if (uc_is_type(val, T_EXCEPTION)) return val; @@ -433,7 +430,7 @@ uc_execute_local(struct uc_state *state, uint32_t off) break; case T_LABEL: - alop = asop; + label_off = assign_off; val = NULL; break; @@ -441,9 +438,9 @@ uc_execute_local(struct uc_state *state, uint32_t off) continue; } - if (alop) { + if (label_off) { json_object_put(rv); - rv = uc_setval(state->scope->scope, alop->val, val); + rv = uc_setval(state->scope->scope, OP_VAL(label_off), val); } } @@ -467,18 +464,17 @@ uc_test_condition(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_if(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_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; - bool res = uc_test_condition(state, cond); + uint32_t cond_off = OPn(off, 0); + uint32_t then_off = OPn(off, 1); + uint32_t else_off = OPn(off, 2); + bool res = uc_test_condition(state, cond_off); if (state->exception) return json_object_get(state->exception); else if (res) - return uc_execute_op_sequence(state, Then); - else if (Else) - return uc_execute_op_sequence(state, Else); + return uc_execute_op_sequence(state, then_off); + else if (else_off) + return uc_execute_op_sequence(state, else_off); return NULL; } @@ -487,39 +483,40 @@ static struct json_object * uc_execute_for(struct uc_state *state, uint32_t off) { struct json_object *kscope, *vscope, *val, *item, *ik, *iv = NULL, *rv = NULL; - struct uc_op *loop = uc_get_op(state, off); - struct uc_op *init = uc_get_child(state, off, 0); - uint32_t test = loop ? loop->tree.operand[1] : 0; - uint32_t incr = loop ? loop->tree.operand[2] : 0; - uint32_t body = loop ? loop->tree.operand[3] : 0; - struct uc_op *ikvar, *ivvar, *tag; + uint32_t init_off = OPn(off, 0); + uint32_t cond_off = OPn(off, 1); + uint32_t step_off = OPn(off, 2); + uint32_t body_off = OPn(off, 3); + uint32_t ik_off, iv_off; size_t arridx, arrlen; bool local = false; + struct uc_op *tag; /* for (x in ...) loop variant */ - if (loop->is_for_in) { - if (init->type == T_LOCAL) { + if (OP_IS_FOR_IN(off)) { + if (OP_TYPE(init_off) == T_LOCAL) { local = true; - init = uc_get_op(state, init->tree.operand[0]); + init_off = OPn(init_off, 0); } - ikvar = uc_get_op(state, init->tree.operand[0]); - ik = ikvar->val; - kscope = local ? state->scope->scope : uc_getref(state, uc_get_off(state, ikvar), NULL); + ik_off = OPn(init_off, 0); + ik = OP_VAL(ik_off); + kscope = local ? state->scope->scope : uc_getref(state, ik_off, NULL); if (uc_is_type(kscope, T_EXCEPTION)) return kscope; - if (ikvar->tree.next) { - ivvar = uc_get_op(state, ikvar->tree.next); - iv = ivvar->val; - vscope = local ? kscope : uc_getref(state, uc_get_off(state, ivvar), NULL); + iv_off = OP_NEXT(ik_off); + + if (iv_off) { + iv = OP_VAL(iv_off); + vscope = local ? kscope : uc_getref(state, iv_off, NULL); if (uc_is_type(vscope, T_EXCEPTION)) return vscope; } - val = uc_execute_op_sequence(state, init->tree.operand[1]); + val = uc_execute_op_sequence(state, OPn(init_off, 1)); if (uc_is_type(val, T_EXCEPTION)) return val; @@ -539,7 +536,7 @@ uc_execute_for(struct uc_state *state, uint32_t off) json_object_put(rv); - rv = uc_execute_op_sequence(state, body); + rv = uc_execute_op_sequence(state, body_off); tag = json_object_get_userdata(rv); switch (tag ? tag->type : 0) { @@ -566,7 +563,7 @@ uc_execute_for(struct uc_state *state, uint32_t off) json_object_put(rv); - rv = uc_execute_op_sequence(state, body); + rv = uc_execute_op_sequence(state, body_off); tag = json_object_get_userdata(rv); switch (tag ? tag->type : 0) { @@ -591,8 +588,8 @@ uc_execute_for(struct uc_state *state, uint32_t off) return NULL; } - if (init) { - val = uc_execute_op_sequence(state, uc_get_off(state, init)); + if (init_off) { + val = uc_execute_op_sequence(state, init_off); if (uc_is_type(val, T_EXCEPTION)) return val; @@ -600,10 +597,10 @@ uc_execute_for(struct uc_state *state, uint32_t off) json_object_put(val); } - while (test ? uc_test_condition(state, test) : true) { + while (cond_off ? uc_test_condition(state, cond_off) : true) { json_object_put(rv); - rv = uc_execute_op_sequence(state, body); + rv = uc_execute_op_sequence(state, body_off); tag = json_object_get_userdata(rv); switch (tag ? tag->type : 0) { @@ -617,8 +614,8 @@ uc_execute_for(struct uc_state *state, uint32_t off) return NULL; } - if (incr) { - val = uc_execute_op_sequence(state, incr); + if (step_off) { + val = uc_execute_op_sequence(state, step_off); if (uc_is_type(val, T_EXCEPTION)) { json_object_put(rv); @@ -638,9 +635,8 @@ uc_execute_for(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_while(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); - uint32_t test = op ? op->tree.operand[0] : 0; - uint32_t body = op ? op->tree.operand[1] : 0; + uint32_t test = OPn(off, 0); + uint32_t body = OPn(off, 1); struct json_object *v, *rv = NULL; struct uc_op *tag = NULL; bool cond; @@ -682,19 +678,20 @@ uc_execute_while(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_and_or(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); + bool is_or = (OP_TYPE(off) == T_OR); struct json_object *val = NULL; - int i; + uint32_t op_off; + int i = 0; - for (i = 0; i < ARRAY_SIZE(op->tree.operand) && op->tree.operand[i]; i++) { + for (op_off = OPn(off, 0); op_off != 0 && i < OPn_NUM; op_off = OPn(off, ++i)) { json_object_put(val); - val = uc_execute_op_sequence(state, op->tree.operand[i]); + val = uc_execute_op_sequence(state, op_off); if (uc_is_type(val, T_EXCEPTION)) break; - if (uc_val_is_truish(val) == (op->type == T_OR)) + if (uc_val_is_truish(val) == is_or) break; } @@ -763,19 +760,19 @@ uc_cmp(int how, struct json_object *v1, struct json_object *v2) } static struct json_object * -_uc_get_operands(struct uc_state *state, struct uc_op *op, size_t n, struct json_object **v) +_uc_get_operands(struct uc_state *state, uint32_t op_off, size_t n, struct json_object **v) { struct json_object *ctx = NULL; - struct uc_op *child; + uint32_t child_off; size_t i, j; for (i = 0; i < n; i++) { - child = op ? uc_get_op(state, op->tree.operand[i]) : NULL; + child_off = OPn(op_off, i); - if (child && child->is_list) - v[i] = uc_execute_list(state, uc_get_off(state, child)); - else if (child) - v[i] = uc_execute_op_sequence(state, uc_get_off(state, child)); + if (child_off && OP_IS_LIST(child_off)) + v[i] = uc_execute_list(state, child_off); + else if (child_off) + v[i] = uc_execute_op_sequence(state, child_off); else v[i] = NULL; @@ -798,21 +795,20 @@ _uc_get_operands(struct uc_state *state, struct uc_op *op, size_t n, struct json return NULL; } -#define uc_get_operands(state, op, vals) \ +#define uc_get_operands(state, off, vals) \ do { \ - struct json_object *ex = _uc_get_operands(state, op, ARRAY_SIZE(vals), vals); \ + struct json_object *ex = _uc_get_operands(state, off, ARRAY_SIZE(vals), vals); \ if (ex) return ex; \ } while(0) static struct json_object * uc_execute_rel(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); struct json_object *v[2], *rv; - uc_get_operands(state, op, v); + uc_get_operands(state, off, v); - rv = xjs_new_boolean(uc_cmp(op->type, v[0], v[1])); + rv = xjs_new_boolean(uc_cmp(OP_TYPE(off), v[0], v[1])); json_object_put(v[0]); json_object_put(v[1]); @@ -864,14 +860,13 @@ uc_eq(struct json_object *v1, struct json_object *v2) static struct json_object * uc_execute_equality(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); struct json_object *v[2], *rv; bool equal = false; - uc_get_operands(state, op, v); + uc_get_operands(state, off, v); equal = uc_eq(v[0], v[1]); - rv = xjs_new_boolean((op->type == T_EQS) ? equal : !equal); + rv = xjs_new_boolean((OP_TYPE(off) == T_EQS) ? equal : !equal); json_object_put(v[0]); json_object_put(v[1]); @@ -882,13 +877,12 @@ uc_execute_equality(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_in(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); struct json_object *v[2], *item; size_t arrlen, arridx; bool found = false; const char *key; - uc_get_operands(state, op, v); + uc_get_operands(state, off, v); if (json_object_is_type(v[1], json_type_array)) { for (arridx = 0, arrlen = json_object_array_length(v[1]); @@ -915,13 +909,12 @@ uc_execute_in(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_inc_dec(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); + bool is_inc = (OP_TYPE(off) == T_INC); struct json_object *val, *nval, *scope, *key; - uint32_t label = op ? op->tree.operand[0] : 0; int64_t n; double d; - scope = uc_getref_required(state, label, &key); + scope = uc_getref_required(state, OPn(off, 0), &key); if (!key) return scope; @@ -932,14 +925,14 @@ uc_execute_inc_dec(struct uc_state *state, uint32_t off) json_object_put(key); if (uc_cast_number(val, &n, &d) == json_type_double) - nval = uc_new_double(d + (op->type == T_INC ? 1.0 : -1.0)); + nval = uc_new_double(d + (is_inc ? 1.0 : -1.0)); else - nval = xjs_new_int64(n + (op->type == T_INC ? 1 : -1)); + nval = xjs_new_int64(n + (is_inc ? 1 : -1)); json_object_put(uc_setval(scope, key, nval)); /* postfix inc/dec, return old val */ - if (op->is_postfix) + if (OP_IS_POSTFIX(off)) return val; json_object_put(val); @@ -950,12 +943,11 @@ uc_execute_inc_dec(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_list(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); struct json_object *ex, *val, *arr = xjs_new_array(); size_t i; - while (op) { - val = uc_execute_op(state, uc_get_off(state, op)); + while (off) { + val = uc_execute_op(state, off); if (uc_is_type(val, T_EXCEPTION)) { json_object_put(arr); @@ -963,9 +955,10 @@ uc_execute_list(struct uc_state *state, uint32_t off) return val; } - if (op->is_ellip) { + if (OP_IS_ELLIP(off)) { if (!json_object_is_type(val, json_type_array)) { - ex = uc_new_exception(state, op->off, "Type error: (%s) is not iterable", + ex = uc_new_exception(state, OP_POS(off), + "Type error: (%s) is not iterable", json_object_get_string(val)); json_object_put(arr); @@ -983,7 +976,7 @@ uc_execute_list(struct uc_state *state, uint32_t off) json_object_array_add(arr, val); } - op = uc_get_op(state, op->tree.next); + off = OP_NEXT(off); } return arr; @@ -993,12 +986,12 @@ static struct json_object * uc_execute_object(struct uc_state *state, uint32_t off) { struct json_object *ex, *v, *obj = uc_new_object(NULL); - struct uc_op *key; + uint32_t key_off; char *istr; size_t i; - for (key = uc_get_child(state, off, 0); key; key = uc_get_op(state, key->tree.next)) { - v = uc_execute_op_sequence(state, key->tree.operand[0]); + for (key_off = OPn(off, 0); key_off != 0; key_off = OP_NEXT(key_off)) { + v = uc_execute_op_sequence(state, OPn(key_off, 0)); if (uc_is_type(v, T_EXCEPTION)) { json_object_put(obj); @@ -1006,7 +999,7 @@ uc_execute_object(struct uc_state *state, uint32_t off) return v; } - if (key->type == T_ELLIP) { + if (OP_TYPE(key_off) == T_ELLIP) { switch (json_object_get_type(v)) { case json_type_object: ; /* a label can only be part of a statement and a declaration is not a statement */ @@ -1029,7 +1022,8 @@ uc_execute_object(struct uc_state *state, uint32_t off) break; default: - ex = uc_new_exception(state, key->off, "Type error: (%s) is not iterable", + ex = uc_new_exception(state, OP_POS(key_off), + "Type error: (%s) is not iterable", json_object_get_string(v)); json_object_put(obj); @@ -1039,7 +1033,7 @@ uc_execute_object(struct uc_state *state, uint32_t off) } } else { - json_object_object_add(obj, json_object_get_string(key->val), v); + json_object_object_add(obj, json_object_get_string(OP_VAL(key_off)), v); } } @@ -1050,7 +1044,7 @@ struct json_object * uc_invoke(struct uc_state *state, uint32_t off, struct json_object *this, struct json_object *func, struct json_object *argvals) { - struct uc_op *op, *tag = json_object_get_userdata(func); + struct uc_op *tag = json_object_get_userdata(func); struct json_object *arr, *rv = NULL; struct uc_callstack callstack = {}; struct uc_function *fn, *prev_fn; @@ -1062,14 +1056,12 @@ uc_invoke(struct uc_state *state, uint32_t off, struct json_object *this, if (!tag) return NULL; - op = uc_get_op(state, off); - if (state->calldepth >= 1000) - return uc_new_exception(state, op->off, "Runtime error: Too much recursion"); + return uc_new_exception(state, OP_POS(off), "Runtime error: Too much recursion"); callstack.next = state->callstack; callstack.function = state->function; - callstack.off = op ? op->off : 0; + callstack.off = OP_POS(off); if (tag->is_arrow) callstack.ctx = state->callstack ? json_object_get(state->callstack->ctx) : NULL; @@ -1128,7 +1120,7 @@ uc_invoke(struct uc_state *state, uint32_t off, struct json_object *this, case T_BREAK: case T_CONTINUE: json_object_put(rv); - rv = uc_new_exception(state, uc_get_off(state, tag), + rv = uc_new_exception(state, tag->off, "Syntax error: %s statement must be inside loop", uc_get_tokenname(tag->type)); break; @@ -1160,19 +1152,19 @@ uc_invoke(struct uc_state *state, uint32_t off, struct json_object *this, static struct json_object * uc_execute_call(struct uc_state *state, uint32_t off) { - struct uc_op *decl, *op = uc_get_op(state, off); - struct uc_op *op1 = uc_get_child(state, off, 0); struct json_object *v[2], *rv; + struct uc_op *decl; char *lhs; - uc_get_operands(state, op, v); + uc_get_operands(state, off, v); decl = json_object_get_userdata(v[0]); if (!decl || (decl->type != T_FUNC && decl->type != T_CFUNC)) { - lhs = uc_ref_to_str(state, uc_get_off(state, op1)); + lhs = uc_ref_to_str(state, OPn(off, 0)); - rv = uc_new_exception(state, op1->off, "Type error: %s is not a function", + rv = uc_new_exception(state, OPn_POS(off, 0), + "Type error: %s is not a function", lhs ? lhs : "left-hand side expression"); free(lhs); @@ -1224,8 +1216,7 @@ uc_write_str(struct json_object *v) static struct json_object * uc_execute_exp(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); - struct json_object *val = uc_execute_op_sequence(state, op ? op->tree.operand[0] : 0); + struct json_object *val = uc_execute_op_sequence(state, OPn(off, 0)); struct uc_op *tag = val ? json_object_get_userdata(val) : NULL; switch (tag ? tag->type : 0) { @@ -1246,14 +1237,13 @@ uc_execute_exp(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_unary_plus_minus(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); - struct uc_op *op1 = uc_get_child(state, off, 0); + bool is_sub = (OP_TYPE(off) == T_SUB); struct json_object *v[1]; enum json_type t; int64_t n; double d; - uc_get_operands(state, op, v); + uc_get_operands(state, off, v); t = uc_cast_number(v[0], &n, &d); @@ -1261,20 +1251,20 @@ uc_execute_unary_plus_minus(struct uc_state *state, uint32_t off) switch (t) { case json_type_int: - if (op1->is_overflow) - return xjs_new_int64(((n >= 0) == (op->type == T_SUB)) ? INT64_MIN : INT64_MAX); + if (OPn_IS_OVERFLOW(off, 0)) + return xjs_new_int64(((n >= 0) == is_sub) ? INT64_MIN : INT64_MAX); - return xjs_new_int64((op->type == T_SUB) ? -n : n); + return xjs_new_int64(is_sub ? -n : n); default: - return uc_new_double((op->type == T_SUB) ? -d : d); + return uc_new_double(is_sub ? -d : d); } } static struct json_object * uc_execute_arith(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); + int type = OP_TYPE(off); struct json_object *v[2], *rv; enum json_type t1, t2; const char *s1, *s2; @@ -1283,12 +1273,12 @@ uc_execute_arith(struct uc_state *state, uint32_t off) double d1, d2; char *s; - if (!op->tree.operand[1]) + if (!OPn(off, 1)) return uc_execute_unary_plus_minus(state, off); - uc_get_operands(state, op, v); + uc_get_operands(state, off, v); - if (op->type == T_ADD && + if (type == T_ADD && (json_object_is_type(v[0], json_type_string) || json_object_is_type(v[1], json_type_string))) { s1 = v[0] ? json_object_get_string(v[0]) : "null"; @@ -1318,7 +1308,7 @@ uc_execute_arith(struct uc_state *state, uint32_t off) d1 = (t1 == json_type_double) ? d1 : (double)n1; d2 = (t2 == json_type_double) ? d2 : (double)n2; - switch (op->type) { + switch (type) { case T_ADD: return uc_new_double(d1 + d2); @@ -1343,7 +1333,7 @@ uc_execute_arith(struct uc_state *state, uint32_t off) } } - switch (op->type) { + switch (type) { case T_ADD: return xjs_new_int64(n1 + n2); @@ -1369,12 +1359,11 @@ uc_execute_arith(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_bitop(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); struct json_object *v[2]; int64_t n1, n2; double d; - uc_get_operands(state, op, v); + uc_get_operands(state, off, v); if (uc_cast_number(v[0], &n1, &d) == json_type_double) n1 = isnan(d) ? 0 : (int64_t)d; @@ -1385,7 +1374,7 @@ uc_execute_bitop(struct uc_state *state, uint32_t off) json_object_put(v[0]); json_object_put(v[1]); - switch (op->type) { + switch (OP_TYPE(off)) { case T_LSHIFT: return xjs_new_int64(n1 << n2); @@ -1409,20 +1398,17 @@ uc_execute_bitop(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_not(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); - - return xjs_new_boolean(!uc_test_condition(state, op ? op->tree.operand[0] : 0)); + return xjs_new_boolean(!uc_test_condition(state, OPn(off, 0))); } static struct json_object * uc_execute_compl(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); struct json_object *v[1]; int64_t n; double d; - uc_get_operands(state, op, v); + uc_get_operands(state, off, v); if (uc_cast_number(v[0], &n, &d) == json_type_double) n = isnan(d) ? 0 : (int64_t)d; @@ -1432,20 +1418,29 @@ uc_execute_compl(struct uc_state *state, uint32_t off) return xjs_new_int64(~n); } +static void +uc_free_tag(struct json_object *v, void *ud) +{ + free(ud); +} + static struct json_object * uc_execute_return(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); + struct uc_op *cpy = xalloc(sizeof(*cpy)); struct json_object *v[1], *rv; - uc_get_operands(state, op, v); + memcpy(cpy, OP(off), sizeof(*cpy)); + cpy->off = off; + + uc_get_operands(state, off, v); json_object_put(state->rval); state->rval = v[0]; rv = xjs_new_boolean(false); - json_object_set_userdata(rv, op, NULL); + json_object_set_userdata(rv, cpy, uc_free_tag); return rv; } @@ -1453,10 +1448,13 @@ uc_execute_return(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_break_cont(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); + struct uc_op *cpy = xalloc(sizeof(*cpy)); struct json_object *rv = xjs_new_int64(0); - json_object_set_userdata(rv, op, NULL); + memcpy(cpy, OP(off), sizeof(*cpy)); + cpy->off = off; + + json_object_set_userdata(rv, cpy, uc_free_tag); return rv; } @@ -1464,12 +1462,11 @@ uc_execute_break_cont(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_function(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); - struct uc_op *op1 = uc_get_child(state, off, 0); - struct json_object *obj = uc_new_func(state, op, state->scope); + struct json_object *obj = uc_new_func(state, off, state->scope); + struct json_object *val = OPn_VAL(off, 0); - if (op1) - uc_setval(state->scope->scope, op1->val, obj); + if (val) + uc_setval(state->scope->scope, val, obj); return obj; } @@ -1483,19 +1480,21 @@ uc_execute_this(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_try_catch(struct uc_state *state, uint32_t off) { - struct uc_op *tag, *op = uc_get_op(state, off); - struct json_object *rv; + struct json_object *evar, *rv; + struct uc_op *tag; - rv = uc_execute_op_sequence(state, op->tree.operand[0]); + rv = uc_execute_op_sequence(state, OPn(off, 0)); if (uc_is_type(rv, T_EXCEPTION)) { - if (op->tree.operand[1]) { + evar = OPn_VAL(off, 1); + + if (evar) { /* remove the T_EXCEPTION type from the object to avoid handling * it as a new exception in the catch block */ tag = json_object_get_userdata(rv); tag->type = T_LBRACE; - json_object_put(uc_setval(state->scope->scope, uc_get_child(state, off, 1)->val, + json_object_put(uc_setval(state->scope->scope, evar, json_object_get(rv))); } @@ -1503,16 +1502,16 @@ uc_execute_try_catch(struct uc_state *state, uint32_t off) state->exception = NULL; json_object_put(rv); - rv = uc_execute_op_sequence(state, op->tree.operand[2]); + rv = uc_execute_op_sequence(state, OPn(off, 2)); } return rv; } static bool -uc_match_case(struct uc_state *state, struct json_object *v, struct uc_op *Case) +uc_match_case(struct uc_state *state, struct json_object *v, uint32_t case_off) { - struct json_object *caseval = uc_execute_op_sequence(state, Case->tree.operand[0]); + struct json_object *caseval = uc_execute_op_sequence(state, OPn(case_off, 0)); bool rv = uc_eq(v, caseval); json_object_put(caseval); @@ -1522,48 +1521,41 @@ uc_match_case(struct uc_state *state, struct json_object *v, struct uc_op *Case) static struct json_object * uc_execute_switch_case(struct uc_state *state, uint32_t off) { - struct uc_op *Default = NULL, *Case = NULL, *jmp = NULL; - struct uc_op *op = uc_get_op(state, off); + uint32_t case_off, default_off = 0, jmp_off = 0; struct json_object *v[1], *rv = NULL; - uc_get_operands(state, op, v); + uc_get_operands(state, off, v); /* First try to find matching case... */ - for (Case = uc_get_child(state, off, 1); - Case != NULL; - Case = uc_get_op(state, Case->tree.next)) - { + for (case_off = OPn(off, 1); case_off != 0; case_off = OP_NEXT(case_off)) { /* remember default case and throw on dupes */ - if (Case->type == T_DEFAULT) { - if (Default) { + if (OP_TYPE(case_off) == T_DEFAULT) { + if (default_off) { json_object_put(v[0]); - return uc_new_exception(state, Case->off, + return uc_new_exception(state, OP_POS(case_off), "Syntax error: more than one switch default case"); } - Default = Case; + default_off = case_off; continue; } /* Found a matching case, remember jump offset */ - if (uc_match_case(state, v[0], Case)) { - jmp = Case; + if (uc_match_case(state, v[0], case_off)) { + jmp_off = case_off; break; } } /* jump to matching case (or default) and continue until break */ - for (Case = jmp ? jmp : Default; - Case != NULL; - Case = uc_get_op(state, Case->tree.next)) - { + for (case_off = jmp_off ? jmp_off : default_off; case_off != 0; case_off = OP_NEXT(case_off)) { json_object_put(rv); - if (Case == Default) - rv = uc_execute_op_sequence(state, Default->tree.operand[0]); + if (OP_TYPE(case_off) == T_DEFAULT) + rv = uc_execute_op_sequence(state, OPn(case_off, 0)); else - rv = uc_execute_op_sequence(state, Case->tree.operand[1]); + rv = uc_execute_op_sequence(state, OPn(case_off, 1)); if (uc_is_type(rv, T_BREAK)) { json_object_put(rv); @@ -1583,13 +1575,13 @@ uc_execute_switch_case(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_atom(struct uc_state *state, uint32_t off) { - return json_object_get(uc_get_op(state, off)->val); + return json_object_get(OP_VAL(off)); } static struct json_object * uc_execute_text(struct uc_state *state, uint32_t off) { - printf("%s", json_object_get_string(uc_get_op(state, off)->val)); + printf("%s", json_object_get_string(OP_VAL(off))); return NULL; } @@ -1597,7 +1589,6 @@ uc_execute_text(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_label(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); struct json_object *scope, *key, *val; scope = uc_getref(state, off, &key); @@ -1606,9 +1597,9 @@ uc_execute_label(struct uc_state *state, uint32_t off) state->ctx = NULL; if (state->strict_declarations && scope == NULL) { - return uc_new_exception(state, op->off, + return uc_new_exception(state, OP_POS(off), "Reference error: %s is not defined", - json_object_get_string(op->val)); + json_object_get_string(OP_VAL(off))); } val = uc_getval(scope, key); @@ -1641,21 +1632,17 @@ uc_execute_dot(struct uc_state *state, uint32_t off) static struct json_object * uc_execute_lbrack(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); - /* postfix access */ - if (op->is_postfix) + if (OP_IS_POSTFIX(off)) return uc_execute_dot(state, off); - return uc_execute_list(state, op->tree.operand[0]); + return uc_execute_list(state, OPn(off, 0)); } static struct json_object * uc_execute_exp_list(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); - - return uc_execute_op_sequence(state, op->tree.operand[0]); + return uc_execute_op_sequence(state, OPn(off, 0)); } static struct json_object *(*fns[__T_MAX])(struct uc_state *, uint32_t) = { @@ -1718,12 +1705,13 @@ static struct json_object *(*fns[__T_MAX])(struct uc_state *, uint32_t) = { static struct json_object * uc_execute_op(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(state, off); + int type = OP_TYPE(off); - if (!fns[op->type]) - return uc_new_exception(state, op->off, "Runtime error: Unrecognized opcode %d", op->type); + if (!fns[type]) + return uc_new_exception(state, OP_POS(off), + "Runtime error: Unrecognized opcode %d", type); - return fns[op->type](state, off); + return fns[type](state, off); } static struct json_object * @@ -1731,7 +1719,6 @@ uc_execute_op_sequence(struct uc_state *state, uint32_t off) { struct json_object *v = NULL; struct uc_op *tag = NULL; - struct uc_op *op = NULL; while (off) { json_object_put(v); @@ -1747,8 +1734,7 @@ uc_execute_op_sequence(struct uc_state *state, uint32_t off) return v; } - op = uc_get_op(state, off); - off = op ? op->tree.next : 0; + off = OP_NEXT(off); } return v; @@ -221,12 +221,11 @@ utf8enc(char **out, int *rem, int code) /* length of the longest token in our lookup table */ #define UT_LEX_MAX_TOKEN_LEN 3 -static uint32_t emit_op(struct uc_state *s, uint32_t pos, int type, struct json_object *val) +static uint32_t emit_op(struct uc_state *state, uint32_t pos, int type, struct json_object *val) { - uint32_t off = uc_new_op(s, type, val, UINT32_MAX); - struct uc_op *op = uc_get_op(s, off); + uint32_t off = uc_new_op(state, type, val, UINT32_MAX); - op->off = pos; + OP(off)->off = pos; /* Follow JSLint logic and treat a slash after any of the * `(,=:[!&|?{};` characters as the beginning of a regex @@ -272,11 +271,11 @@ static uint32_t emit_op(struct uc_state *s, uint32_t pos, int type, struct json_ case T_LEXP: case T_SCOL: - s->lex.expect_div = false; + state->lex.expect_div = false; break; default: - s->lex.expect_div = true; + state->lex.expect_div = true; } return off; @@ -616,62 +615,62 @@ enum { }; static uint32_t -parse_regexp(struct uc_state *s) +parse_regexp(struct uc_state *state) { struct json_object *pattern; struct uc_op *op; uint32_t rv; char *err; - switch (s->lex.esc[0]) { + switch (state->lex.esc[0]) { case UT_LEX_PARSE_REGEX_INIT: - if (s->lex.expect_div) { - s->lex.expect_div = false; + if (state->lex.expect_div) { + state->lex.expect_div = false; - if (buf_startswith(s, "=")) { - buf_consume(s, 1); + if (buf_startswith(state, "=")) { + buf_consume(state, 1); - return emit_op(s, s->source->off, T_ASDIV, NULL); + return emit_op(state, state->source->off, T_ASDIV, NULL); } - return emit_op(s, s->source->off, T_DIV, NULL); + return emit_op(state, state->source->off, T_DIV, NULL); } - s->lex.esc[0] = UT_LEX_PARSE_REGEX_PATTERN; + state->lex.esc[0] = UT_LEX_PARSE_REGEX_PATTERN; break; case UT_LEX_PARSE_REGEX_PATTERN: - rv = parse_string(s); + rv = parse_string(state); if (rv != 0 && rv != UINT32_MAX) { - s->lex.lookbehind = (char *)uc_get_op(s, rv); - s->lex.esc[0] = UT_LEX_PARSE_REGEX_FLAGS; + state->lex.lookbehind = (char *)OP(rv); + state->lex.esc[0] = UT_LEX_PARSE_REGEX_FLAGS; } break; case UT_LEX_PARSE_REGEX_FLAGS: - op = (struct uc_op *)s->lex.lookbehind; + op = (struct uc_op *)state->lex.lookbehind; - while (s->lex.bufstart < s->lex.bufend) { - switch (s->lex.bufstart[0]) { + while (state->lex.bufstart < state->lex.bufend) { + switch (state->lex.bufstart[0]) { case 'g': - buf_consume(s, 1); + buf_consume(state, 1); op->is_reg_global = true; break; case 'i': - buf_consume(s, 1); + buf_consume(state, 1); op->is_reg_icase = true; break; case 's': - buf_consume(s, 1); + buf_consume(state, 1); op->is_reg_newline = true; break; default: - s->lex.lookbehind = NULL; + state->lex.lookbehind = NULL; pattern = uc_new_regexp(json_object_get_string(op->val), op->is_reg_icase, @@ -685,13 +684,13 @@ parse_regexp(struct uc_state *s) op->val = pattern; if (!pattern) { - uc_new_exception(s, op->off, "Syntax error: %s", err); + uc_new_exception(state, op->off, "Syntax error: %s", err); free(err); return 0; } - return uc_get_off(s, op); + return op - state->pool; } } @@ -781,46 +780,46 @@ is_numeric_char(struct uc_state *s, char c) } static uint32_t -parse_number(struct uc_state *s) +parse_number(struct uc_state *state) { uint32_t rv = 0; long long int n; char *ptr, *e; double d; - if (!buf_remaining(s) || !is_numeric_char(s, s->lex.bufstart[0])) { - lookbehind_append(s, "\0", 1); + if (!buf_remaining(state) || !is_numeric_char(state, state->lex.bufstart[0])) { + lookbehind_append(state, "\0", 1); - n = strtoll(s->lex.lookbehind, &e, 0); + n = strtoll(state->lex.lookbehind, &e, 0); if (*e == '.' || *e == 'e' || *e == 'E') { - d = strtod(s->lex.lookbehind, &e); + d = strtod(state->lex.lookbehind, &e); - if (e > s->lex.lookbehind && *e == 0) - rv = emit_op(s, s->source->off - (e - s->lex.lookbehind), T_DOUBLE, uc_new_double(d)); + if (e > state->lex.lookbehind && *e == 0) + rv = emit_op(state, state->source->off - (e - state->lex.lookbehind), T_DOUBLE, uc_new_double(d)); else - uc_new_exception(s, s->source->off - (s->lex.lookbehindlen - (e - s->lex.lookbehind) - 1), + uc_new_exception(state, state->source->off - (state->lex.lookbehindlen - (e - state->lex.lookbehind) - 1), "Syntax error: Invalid number literal"); } else if (*e == 0) { - rv = emit_op(s, s->source->off - (e - s->lex.lookbehind), T_NUMBER, xjs_new_int64(n)); - uc_get_op(s, rv)->is_overflow = (errno == ERANGE); + rv = emit_op(state, state->source->off - (e - state->lex.lookbehind), T_NUMBER, xjs_new_int64(n)); + OP(rv)->is_overflow = (errno == ERANGE); } else { - uc_new_exception(s, s->source->off - (s->lex.lookbehindlen - (e - s->lex.lookbehind) - 1), + uc_new_exception(state, state->source->off - (state->lex.lookbehindlen - (e - state->lex.lookbehind) - 1), "Syntax error: Invalid number literal"); } - lookbehind_reset(s); + lookbehind_reset(state); return rv; } - for (ptr = s->lex.bufstart; ptr < s->lex.bufend && is_numeric_char(s, *ptr); ptr++) + for (ptr = state->lex.bufstart; ptr < state->lex.bufend && is_numeric_char(state, *ptr); ptr++) ; - lookbehind_append(s, s->lex.bufstart, ptr - s->lex.bufstart); - buf_consume(s, ptr - s->lex.bufstart); + lookbehind_append(state, state->lex.bufstart, ptr - state->lex.bufstart); + buf_consume(state, ptr - state->lex.bufstart); return 0; } @@ -186,9 +186,8 @@ format_error_context(char **msg, size_t *msglen, struct uc_source *src, struct j } struct json_object * -uc_parse_error(struct uc_state *s, uint32_t off, uint64_t *tokens, int max_token) +uc_parse_error(struct uc_state *state, uint32_t off, uint64_t *tokens, int max_token) { - struct uc_op *op = uc_get_op(s, off); struct json_object *rv; size_t msglen = 0; bool first = true; @@ -210,8 +209,8 @@ uc_parse_error(struct uc_state *s, uint32_t off, uint64_t *tokens, int max_token } } - rv = uc_new_exception(s, - op ? op->off : s->lex.lastoff, + rv = uc_new_exception(state, + off ? OP_POS(off) : state->lex.lastoff, "Syntax error: Unexpected token\n%s", msg); free(msg); @@ -1574,10 +1573,9 @@ uc_printf(struct uc_state *s, uint32_t off, struct json_object *args) } static struct json_object * -uc_require_so(struct uc_state *s, uint32_t off, const char *path) +uc_require_so(struct uc_state *state, uint32_t off, const char *path) { void (*init)(const struct uc_ops *, struct uc_state *, struct json_object *); - struct uc_op *op = uc_get_op(s, off); struct uc_function fn = {}, *prev_fn; struct uc_source *src, *prev_src; struct json_object *scope; @@ -1591,32 +1589,34 @@ uc_require_so(struct uc_state *s, uint32_t off, const char *path) dlh = dlopen(path, RTLD_LAZY|RTLD_LOCAL); if (!dlh) - return uc_new_exception(s, op->off, "Unable to dlopen file %s: %s", path, dlerror()); + return uc_new_exception(state, OP_POS(off), + "Unable to dlopen file %s: %s", path, dlerror()); init = dlsym(dlh, "uc_module_init"); if (!init) - return uc_new_exception(s, op->off, "Module %s provides no 'uc_module_init' function", path); + return uc_new_exception(state, OP_POS(off), + "Module %s provides no 'uc_module_init' function", path); src = xalloc(sizeof(*src)); src->filename = xstrdup(path); - src->next = s->sources; + src->next = state->sources; fn.name = "require"; fn.source = src; - prev_fn = s->function; - s->function = &fn; + prev_fn = state->function; + state->function = &fn; - prev_src = s->source; - s->source = s->sources = src; + prev_src = state->source; + state->source = state->sources = src; scope = xjs_new_object(); - init(&ut, s, scope); + init(&ut, state, scope); - s->source = prev_src; - s->function = prev_fn; + state->source = prev_src; + state->function = prev_fn; return scope; } @@ -1629,7 +1629,7 @@ uc_execute_source(struct uc_state *s, struct uc_source *src, struct uc_scope *sc rv = uc_parse(s, src->fp); if (!uc_is_type(rv, T_EXCEPTION)) { - entry = uc_new_func(s, uc_get_op(s, s->main), scope ? scope : s->scope); + entry = uc_new_func(s, s->main, scope ? scope : s->scope); json_object_put(rv); rv = uc_invoke(s, s->main, NULL, entry, NULL); @@ -1641,9 +1641,8 @@ uc_execute_source(struct uc_state *s, struct uc_source *src, struct uc_scope *sc } static struct json_object * -uc_require_utpl(struct uc_state *s, uint32_t off, const char *path, struct uc_scope *scope) +uc_require_utpl(struct uc_state *state, uint32_t off, const char *path, struct uc_scope *scope) { - struct uc_op *op = uc_get_op(s, off); struct uc_function fn = {}, *prev_fn; struct uc_source *src, *prev_src; struct json_object *rv; @@ -1656,26 +1655,27 @@ uc_require_utpl(struct uc_state *s, uint32_t off, const char *path, struct uc_sc fp = fopen(path, "rb"); if (!fp) - return uc_new_exception(s, op->off, "Unable to open file %s: %s", path, strerror(errno)); + return uc_new_exception(state, OP_POS(off), + "Unable to open file %s: %s", path, strerror(errno)); src = xalloc(sizeof(*src)); src->fp = fp; src->filename = path ? xstrdup(path) : NULL; - src->next = s->sources; + src->next = state->sources; - prev_src = s->source; - s->source = s->sources = src; + prev_src = state->source; + state->source = state->sources = src; fn.name = "require"; fn.source = src; - prev_fn = s->function; - s->function = &fn; + prev_fn = state->function; + state->function = &fn; - rv = uc_execute_source(s, src, scope); + rv = uc_execute_source(state, src, scope); - s->function = prev_fn; - s->source = prev_src; + state->function = prev_fn; + state->source = prev_src; return rv; } @@ -1722,11 +1722,10 @@ invalid: } static struct json_object * -uc_require(struct uc_state *s, uint32_t off, struct json_object *args) +uc_require(struct uc_state *state, uint32_t off, struct json_object *args) { struct json_object *val = json_object_array_get_idx(args, 0); struct json_object *search, *se, *res; - struct uc_op *op = uc_get_op(s, off); struct uc_scope *sc, *scparent; size_t arridx, arrlen; const char *name; @@ -1735,7 +1734,7 @@ uc_require(struct uc_state *s, uint32_t off, struct json_object *args) return NULL; /* find root scope */ - for (sc = s->scope; sc; ) { + for (sc = state->scope; sc; ) { scparent = uc_parent_scope(sc); if (!scparent) @@ -1748,7 +1747,7 @@ uc_require(struct uc_state *s, uint32_t off, struct json_object *args) search = sc ? json_object_object_get(sc->scope, "REQUIRE_SEARCH_PATH") : NULL; if (!json_object_is_type(search, json_type_array)) - return uc_new_exception(s, op ? op->off : 0, + return uc_new_exception(state, off ? OP_POS(off) : 0, "Global require search path not set"); for (arridx = 0, arrlen = json_object_array_length(search); arridx < arrlen; arridx++) { @@ -1757,13 +1756,13 @@ uc_require(struct uc_state *s, uint32_t off, struct json_object *args) if (!json_object_is_type(se, json_type_string)) continue; - res = uc_require_path(s, off, json_object_get_string(se), name); + res = uc_require_path(state, off, json_object_get_string(se), name); if (res) return res; } - return uc_new_exception(s, op ? op->off : 0, + return uc_new_exception(state, off ? OP_POS(off) : 0, "No module named '%s' could be found", name); } @@ -2103,17 +2102,17 @@ uc_replace(struct uc_state *s, uint32_t off, struct json_object *args) } static struct json_object * -uc_json(struct uc_state *s, uint32_t off, struct json_object *args) +uc_json(struct uc_state *state, uint32_t off, struct json_object *args) { struct json_object *rv, *src = json_object_array_get_idx(args, 0); - struct uc_op *op = uc_get_op(s, off); struct json_tokener *tok = NULL; enum json_tokener_error err; const char *str; size_t len; if (!json_object_is_type(src, json_type_string)) - return uc_new_exception(s, op->off, "Passed value is not a string"); + return uc_new_exception(state, OP_POS(off), + "Passed value is not a string"); tok = xjs_new_tokener(); str = json_object_get_string(src); @@ -2124,16 +2123,19 @@ uc_json(struct uc_state *s, uint32_t off, struct json_object *args) if (err == json_tokener_continue) { json_object_put(rv); - rv = uc_new_exception(s, op->off, "Unexpected end of string in JSON data"); + rv = uc_new_exception(state, OP_POS(off), + "Unexpected end of string in JSON data"); } else if (err != json_tokener_success) { json_object_put(rv); - rv = uc_new_exception(s, op->off, "Failed to parse JSON string: %s", - json_tokener_error_desc(err)); + rv = uc_new_exception(state, OP_POS(off), + "Failed to parse JSON string: %s", + json_tokener_error_desc(err)); } else if (json_tokener_get_parse_end(tok) < len) { json_object_put(rv); - rv = uc_new_exception(s, op->off, "Trailing garbage after JSON data"); + rv = uc_new_exception(state, OP_POS(off), + "Trailing garbage after JSON data"); } json_tokener_free(tok); @@ -2175,36 +2177,38 @@ include_path(const char *curpath, const char *incpath) } static struct json_object * -uc_include(struct uc_state *s, uint32_t off, struct json_object *args) +uc_include(struct uc_state *state, uint32_t off, struct json_object *args) { struct json_object *rv, *path = json_object_array_get_idx(args, 0); struct json_object *scope = json_object_array_get_idx(args, 1); - struct uc_op *op = uc_get_op(s, off); struct uc_scope *sc; char *p; if (!json_object_is_type(path, json_type_string)) - return uc_new_exception(s, op->off, "Passed filename is not a string"); + return uc_new_exception(state, OP_POS(off), + "Passed filename is not a string"); if (scope && !json_object_is_type(scope, json_type_object)) - return uc_new_exception(s, op->off, "Passed scope value is not an object"); + return uc_new_exception(state, OP_POS(off), + "Passed scope value is not an object"); - p = include_path(s->callstack->function->source->filename, json_object_get_string(path)); + p = include_path(state->callstack->function->source->filename, json_object_get_string(path)); if (!p) - return uc_new_exception(s, op->off, "Include file not found"); + return uc_new_exception(state, OP_POS(off), + "Include file not found"); if (scope) { - sc = uc_new_scope(s, NULL); + sc = uc_new_scope(state, NULL); json_object_object_foreach(scope, key, val) json_object_object_add(sc->scope, key, json_object_get(val)); } else { - sc = s->scope; + sc = state->scope; } - rv = uc_require_utpl(s, off, p, sc); + rv = uc_require_utpl(state, off, p, sc); free(p); @@ -2226,11 +2230,10 @@ uc_warn(struct uc_state *s, uint32_t off, struct json_object *args) } static struct json_object * -uc_system(struct uc_state *s, uint32_t off, struct json_object *args) +uc_system(struct uc_state *state, uint32_t off, struct json_object *args) { struct json_object *cmdline = json_object_array_get_idx(args, 0); struct json_object *timeout = json_object_array_get_idx(args, 1); - struct uc_op *op = uc_get_op(s, off); sigset_t sigmask, sigomask; const char **arglist, *fn; struct timespec ts; @@ -2259,11 +2262,13 @@ uc_system(struct uc_state *s, uint32_t off, struct json_object *args) break; default: - return uc_new_exception(s, op->off, "Passed command is neither string nor array"); + return uc_new_exception(state, OP_POS(off), + "Passed command is neither string nor array"); } if (timeout && (!json_object_is_type(timeout, json_type_int) || json_object_get_int64(timeout) < 0)) - return uc_new_exception(s, op->off, "Invalid timeout specified"); + return uc_new_exception(state, OP_POS(off), + "Invalid timeout specified"); tms = timeout ? json_object_get_int64(timeout) : 0; @@ -2334,7 +2339,8 @@ fail: sigprocmask(SIG_SETMASK, &sigomask, NULL); free(arglist); - return uc_new_exception(s, op->off, "%s(): %s", fn, strerror(errno)); + return uc_new_exception(state, OP_POS(off), + "%s(): %s", fn, strerror(errno)); } const struct uc_ops ut = { @@ -53,30 +53,30 @@ print_usage(char *app) } #ifndef NDEBUG -static void dump(struct uc_state *s, uint32_t off, int level); +static void dump(struct uc_state *state, uint32_t off, int level); -static void dump_node(struct uc_op *op) { +static void dump_node(struct uc_state *state, uint32_t off) { const char *p; - switch (op->type) { + switch (OP_TYPE(off)) { case T_NUMBER: - printf("n%p [label=\"%"PRId64"\"];\n", op, json_object_get_int64(op->val)); + printf("n%u [label=\"%"PRId64"\"];\n", off, json_object_get_int64(OP_VAL(off))); break; case T_DOUBLE: - printf("n%p [label=\"%f\"];\n", op, json_object_get_double(op->val)); + printf("n%u [label=\"%f\"];\n", off, json_object_get_double(OP_VAL(off))); break; case T_BOOL: - printf("n%p [label=\"%s\"];\n", op, json_object_get_boolean(op->val) ? "true" : "false"); + printf("n%u [label=\"%s\"];\n", off, json_object_get_boolean(OP_VAL(off)) ? "true" : "false"); break; case T_STRING: case T_LABEL: case T_TEXT: - printf("n%p [label=\"%s<", op, uc_get_tokenname(op->type)); + printf("n%u [label=\"%s<", off, uc_get_tokenname(OP_TYPE(off))); - for (p = json_object_get_string(op->val); *p; p++) + for (p = json_object_get_string(OP_VAL(off)); *p; p++) switch (*p) { case '\n': printf("\\\n"); @@ -98,43 +98,43 @@ static void dump_node(struct uc_op *op) { break; default: - printf("n%p [label=\"%s", op, uc_get_tokenname(op->type)); + printf("n%u [label=\"%s", off, uc_get_tokenname(OP_TYPE(off))); - if (op->is_postfix) + if (OP_IS_POSTFIX(off)) printf(", postfix"); printf("\"];\n"); } } -static void dump(struct uc_state *s, uint32_t off, int level) { - struct uc_op *prev, *cur, *child; +static void dump(struct uc_state *state, uint32_t off, int level) { + uint32_t prev_off, cur_off, child_off; int i; if (level == 0) { printf("digraph G {\nmain [shape=box];\n"); } - for (prev = NULL, cur = uc_get_op(s, off); cur; prev = cur, cur = uc_get_op(s, cur->tree.next)) { - dump_node(cur); + for (prev_off = 0, cur_off = off; cur_off != 0; prev_off = cur_off, cur_off = OP_NEXT(cur_off)) { + dump_node(state, cur_off); - if (cur->type < __T_MAX) { - for (i = 0; i < ARRAY_SIZE(cur->tree.operand); i++) { - child = uc_get_op(s, cur->tree.operand[i]); + if (OP_TYPE(cur_off) < __T_MAX) { + for (i = 0; i < OPn_NUM; i++) { + child_off = OPn(cur_off, 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); + if (child_off) { + dump(state, child_off, level + 1); + printf("n%u -> n%u [label=\"op%d\"];\n", cur_off, child_off, i + 1); } } } - if (prev) - printf("n%p -> n%p [style=dotted];\n", prev, cur); + if (prev_off) + printf("n%u -> n%u [style=dotted];\n", prev_off, cur_off); } if (level == 0) { - printf("main -> n%p [style=dotted];\n", uc_get_op(s, off)); + printf("main -> n%u [style=dotted];\n", off); printf("}\n"); } @@ -276,6 +276,9 @@ main(int argc, char **argv) state->lstrip_blocks = 1; state->trim_blocks = 1; + /* reserve opcode slot 0 */ + uc_new_op(state, 0, NULL, UINT32_MAX); + while ((opt = getopt(argc, argv, "dhlrSe:E:i:s:m:")) != -1) { switch (opt) { @@ -15,7 +15,7 @@ */ %token_type {uint32_t} -%extra_argument {struct uc_state *s} +%extra_argument {struct uc_state *state} %nonassoc T_LEXP T_REXP T_LSTM T_RSTM. @@ -59,55 +59,53 @@ #define YYNOERRORRECOVERY #define new_op(type, val, ...) \ - uc_new_op(s, type, val, ##__VA_ARGS__, UINT32_MAX) + uc_new_op(state, type, val, ##__VA_ARGS__, UINT32_MAX) #define wrap_op(op, ...) \ - uc_wrap_op(s, op, ##__VA_ARGS__, UINT32_MAX) + uc_wrap_op(state, op, ##__VA_ARGS__, UINT32_MAX) #define append_op(op1, op2) \ - uc_append_op(s, op1, op2) + uc_append_op(state, op1, op2) #define no_empty_obj(op) \ - uc_no_empty_obj(s, op) + uc_no_empty_obj(state, op) static inline uint32_t -uc_no_empty_obj(struct uc_state *s, uint32_t off) +uc_no_empty_obj(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(s, off); - - return (!op || op->type != T_LBRACE || op->tree.operand[0]) ? off : 0; + return (OP_TYPE(off) != T_LBRACE || OPn(off, 0)) ? off : 0; } static inline uint32_t -uc_add_else(struct uc_state *s, uint32_t off, uint32_t add) +uc_add_else(struct uc_state *state, uint32_t off, uint32_t add) { - struct uc_op *tail = uc_get_op(s, off); + uint32_t tail_off = off; - while (tail && tail->tree.operand[2]) - tail = uc_get_op(s, tail->tree.operand[2]); + while (OPn(tail_off, 2)) + tail_off = OPn(tail_off, 2); - tail->tree.operand[2] = add; + OPn(tail_off, 2) = add; return off; } static inline uint32_t -uc_expect_token(struct uc_state *s, uint32_t off, int token) +uc_expect_token(struct uc_state *state, uint32_t off, int token) { uint64_t tokens[(__T_MAX + 63) & -64] = {}; tokens[token / 64] |= ((uint64_t)1 << (token % 64)); - uc_parse_error(s, off, tokens, token); + uc_parse_error(state, off, tokens, token); return 0; } static inline uint32_t -_uc_check_op_seq_types(struct uc_state *s, uint32_t off, ...) +_uc_check_op_seq_types(struct uc_state *state, uint32_t off, ...) { uint64_t tokens[(__T_MAX + 63) & -64] = {}; - struct uc_op *arg = uc_get_op(s, off); - int token, max_token = 0; + int type, token, max_token = 0; + uint32_t arg_off; va_list ap; va_start(ap, off); @@ -119,28 +117,27 @@ _uc_check_op_seq_types(struct uc_state *s, uint32_t off, ...) va_end(ap); - while (arg) { - if (!(tokens[arg->type / 64] & ((uint64_t)1 << (arg->type % 64)))) { - uc_parse_error(s, off, tokens, max_token); + for (arg_off = off; arg_off != 0; arg_off = OP_NEXT(arg_off)) { + type = OP_TYPE(arg_off); + + if (!(tokens[type / 64] & ((uint64_t)1 << (type % 64)))) { + uc_parse_error(state, off, tokens, max_token); return 0; } - - arg = uc_get_op(s, arg->tree.next); } return off; } -#define uc_check_op_seq_types(s, off, ...) _uc_check_op_seq_types(s, off, __VA_ARGS__, 0) +#define uc_check_op_seq_types(state, off, ...) _uc_check_op_seq_types(state, off, __VA_ARGS__, 0) static inline uint32_t -uc_reject_local(struct uc_state *s, uint32_t off) +uc_reject_local(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(s, off); - - if (op->type == T_LOCAL) { - uc_new_exception(s, op->off, "Syntax error: Unexpected token\nDeclaration not allowed in this context"); + if (OP_TYPE(off) == T_LOCAL) { + uc_new_exception(state, OP_POS(off), + "Syntax error: Unexpected token\nDeclaration not allowed in this context"); return 0; } @@ -149,45 +146,43 @@ uc_reject_local(struct uc_state *s, uint32_t off) } static inline uint32_t -uc_check_for_in(struct uc_state *s, uint32_t off) +uc_check_for_in(struct uc_state *state, uint32_t off) { - struct uc_op *op = uc_get_op(s, off); - struct uc_op *arg; - uint32_t idx = 0; + uint32_t arg_off, idx = 0; - arg = (op->type == T_LOCAL) ? uc_get_op(s, op->tree.operand[0]) : op; + arg_off = (OP_TYPE(off) == T_LOCAL) ? OPn(off, 0) : off; - if (arg->type == T_LABEL) { - idx = uc_get_off(s, arg); + if (OP_TYPE(arg_off) == T_LABEL) { + idx = arg_off; - if (!arg->tree.next) { - uc_new_exception(s, arg->off + json_object_get_string_len(arg->val), + if (!OP_NEXT(arg_off)) { + uc_new_exception(state, OP_POS(arg_off) + json_object_get_string_len(OP_VAL(arg_off)), "Syntax error: Unexpected token\nExpecting ',' or 'in'"); return 0; } - arg = uc_get_op(s, arg->tree.next); + arg_off = OP_NEXT(arg_off); } - if (arg->type != T_IN || arg->tree.next || uc_get_op(s, arg->tree.operand[0])->type != T_LABEL) { - if (arg->type == T_IN && arg->tree.next) - arg = uc_get_op(s, arg->tree.next); + if (OP_TYPE(arg_off) != T_IN || OP_NEXT(arg_off) || OPn_TYPE(arg_off, 0) != T_LABEL) { + if (OP_TYPE(arg_off) == T_IN && OP_NEXT(arg_off)) + arg_off = OP_NEXT(arg_off); - uc_new_exception(s, arg->off, "Syntax error: Invalid for-in expression"); + uc_new_exception(state, OP_POS(arg_off), "Syntax error: Invalid for-in expression"); return 0; } /* transform T_LABEL->T_IN(T_LABEL, ...) into T_IN(T_LABEL->T_LABEL, ...) */ if (idx) { - uc_get_op(s, idx)->tree.next = 0; - arg->tree.operand[0] = append_op(idx, arg->tree.operand[0]); + OP_NEXT(idx) = 0; + OPn(arg_off, 0) = append_op(idx, OPn(arg_off, 0)); - if (op->type == T_LOCAL) - op->tree.operand[0] = uc_get_off(s, arg); + if (OP_TYPE(off) == T_LOCAL) + OPn(off, 0) = arg_off; else - off = uc_get_off(s, arg); + off = arg_off; } return off; @@ -206,12 +201,12 @@ uc_check_for_in(struct uc_state *s, uint32_t off) } } - uc_parse_error(s, TOKEN, tokens, max_token); + uc_parse_error(state, TOKEN, tokens, max_token); } -input ::= chunks(A). { s->main = new_op(T_FUNC, NULL, 0, 0, A); } -input ::= . { s->main = new_op(T_TEXT, xjs_new_string("")); s->main = new_op(T_FUNC, NULL, 0, 0, s->main); } +input ::= chunks(A). { state->main = new_op(T_FUNC, NULL, 0, 0, A); } +input ::= . { state->main = new_op(T_TEXT, xjs_new_string("")); state->main = new_op(T_FUNC, NULL, 0, 0, state->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; } @@ -249,13 +244,13 @@ sel_stmt(A) ::= T_IF(B) T_LPAREN exp(C) T_RPAREN stmt(D) T_ELSE stmt(E). sel_stmt(A) ::= T_IF(B) T_LPAREN exp(C) T_RPAREN stmt(D). [T_IF] { A = wrap_op(B, C, no_empty_obj(D)); } sel_stmt(A) ::= T_IF(B) T_LPAREN exp(C) T_RPAREN T_COLON chunks(D) sel_elifs(E) T_ELSE chunks(F) T_ENDIF. - { A = uc_add_else(s, wrap_op(B, C, D, E), F); } + { A = uc_add_else(state, wrap_op(B, C, D, E), F); } sel_stmt(A) ::= T_IF(B) T_LPAREN exp(C) T_RPAREN T_COLON chunks(D) T_ELSE chunks(E) T_ENDIF. { A = wrap_op(B, C, D, E); } sel_stmt(A) ::= T_IF(B) T_LPAREN exp(C) T_RPAREN T_COLON chunks(D) T_ENDIF. [T_IF] { A = wrap_op(B, C, D); } -sel_elifs(A) ::= sel_elifs(B) sel_elif(C). { A = uc_add_else(s, B, C); } +sel_elifs(A) ::= sel_elifs(B) sel_elif(C). { A = uc_add_else(state, B, C); } sel_elifs(A) ::= sel_elif(B). { A = B; } sel_elif(A) ::= T_ELIF(B) T_LPAREN exp(C) T_RPAREN T_COLON chunks(D). @@ -266,9 +261,9 @@ iter_stmt(A) ::= T_WHILE(B) T_LPAREN exp(C) T_RPAREN stmt(D). iter_stmt(A) ::= T_WHILE(B) T_LPAREN exp(C) T_RPAREN T_COLON chunks(D) T_ENDWHILE. { A = wrap_op(B, C, D); } iter_stmt(A) ::= T_FOR(B) paren_exp(C) stmt(D). - { A = wrap_op(B, uc_check_for_in(s, C), NULL, NULL, no_empty_obj(D)); uc_get_op(s, A)->is_for_in = 1; } + { A = wrap_op(B, uc_check_for_in(state, C), NULL, NULL, no_empty_obj(D)); OP(A)->is_for_in = 1; } iter_stmt(A) ::= T_FOR(B) paren_exp(C) T_COLON chunks(D) T_ENDFOR. - { A = wrap_op(B, uc_check_for_in(s, C), NULL, NULL, no_empty_obj(D)); uc_get_op(s, A)->is_for_in = 1; } + { A = wrap_op(B, uc_check_for_in(state, C), NULL, NULL, no_empty_obj(D)); OP(A)->is_for_in = 1; } iter_stmt(A) ::= T_FOR(B) T_LPAREN decl_or_exp(C) exp_stmt(D) T_RPAREN stmt(E). { A = wrap_op(B, C, D, NULL, no_empty_obj(E)); } iter_stmt(A) ::= T_FOR(B) T_LPAREN decl_or_exp(C) exp_stmt(D) exp(E) T_RPAREN stmt(F). @@ -311,8 +306,8 @@ switch_case(A) ::= T_CASE(B) exp(C) T_COLON stmts(D). { A = wrap_op(B, C, D); } switch_case(A) ::= T_CASE(B) exp(C) T_COLON. { A = wrap_op(B, C); } switch_case(A) ::= T_DEFAULT(B) T_COLON stmts(C). { A = wrap_op(B, C); } -args(A) ::= sargs(B) T_COMMA T_ELLIP T_LABEL(C). { A = append_op(B, C); uc_get_op(s, C)->is_ellip = 1; } -args(A) ::= T_ELLIP T_LABEL(B). { A = B; uc_get_op(s, B)->is_ellip = 1; } +args(A) ::= sargs(B) T_COMMA T_ELLIP T_LABEL(C). { A = append_op(B, C); OP(C)->is_ellip = 1; } +args(A) ::= T_ELLIP T_LABEL(B). { A = B; OP(B)->is_ellip = 1; } args(A) ::= sargs(B). { A = B; } sargs(A) ::= sargs(B) T_COMMA T_LABEL(C). { A = append_op(B, C); } @@ -327,7 +322,7 @@ ret_stmt(A) ::= T_RETURN(B) T_SCOL. { A = B; } break_stmt(A) ::= T_BREAK(B) T_SCOL. { A = B; } break_stmt(A) ::= T_CONTINUE(B) T_SCOL. { A = B; } -decl_stmt(A) ::= T_LOCAL(B) decls(C) T_SCOL. { A = wrap_op(B, uc_check_op_seq_types(s, C, T_ASSIGN, T_LABEL)); } +decl_stmt(A) ::= T_LOCAL(B) decls(C) T_SCOL. { A = wrap_op(B, uc_check_op_seq_types(state, C, T_ASSIGN, T_LABEL)); } decls(A) ::= decls(B) T_COMMA decl(C). { A = append_op(B, C); } decls(A) ::= decl(B). { A = B; } @@ -358,13 +353,13 @@ assign_exp(A) ::= unary_exp(B) T_ASBOR arrow_exp(C). { A = new_op(T_BOR, NULL, B assign_exp(A) ::= arrow_exp(B). { A = B; } arrow_exp(A) ::= unary_exp(B) T_ARROW(C) arrowfn_body(D). - { A = wrap_op(C, 0, uc_check_op_seq_types(s, B, T_LABEL), D); } + { A = wrap_op(C, 0, uc_check_op_seq_types(state, B, T_LABEL), D); } arrow_exp(A) ::= T_LPAREN T_RPAREN T_ARROW(C) arrowfn_body(D). { A = wrap_op(C, 0, 0, D); } arrow_exp(A) ::= T_LPAREN T_ELLIP T_LABEL(B) T_RPAREN T_ARROW(C) arrowfn_body(D). - { A = wrap_op(C, 0, B, D); uc_get_op(s, B)->is_ellip = 1; } + { A = wrap_op(C, 0, B, D); OP(B)->is_ellip = 1; } arrow_exp(A) ::= T_LPAREN exp(B) T_COMMA T_ELLIP T_LABEL(C) T_RPAREN T_ARROW(D) arrowfn_body(E). - { A = append_op(B, C); A = wrap_op(D, 0, uc_check_op_seq_types(s, A, T_LABEL), E); uc_get_op(s, C)->is_ellip = 1; } + { A = append_op(B, C); A = wrap_op(D, 0, uc_check_op_seq_types(state, A, T_LABEL), E); OP(C)->is_ellip = 1; } arrow_exp(A) ::= ternary_exp(B). { A = B; } ternary_exp(A) ::= or_exp(B) T_QMARK(C) assign_exp(D) T_COLON ternary_exp(E). @@ -420,14 +415,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); uc_get_op(s, A)->is_postfix = 1; } -postfix_exp(A) ::= unary_exp(B) T_DEC(C). { A = wrap_op(C, B); uc_get_op(s, A)->is_postfix = 1; } +postfix_exp(A) ::= unary_exp(B) T_INC(C). { A = wrap_op(C, B); OP(A)->is_postfix = 1; } +postfix_exp(A) ::= unary_exp(B) T_DEC(C). { A = wrap_op(C, B); OP(A)->is_postfix = 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_exps(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) exp(D) T_RBRACK. - { A = wrap_op(C, B, D); uc_get_op(s, A)->is_postfix = 1; } + { A = wrap_op(C, B, D); OP(A)->is_postfix = 1; } postfix_exp(A) ::= primary_exp(B). { A = B; } primary_exp(A) ::= T_BOOL(B). { A = B; } @@ -440,7 +435,7 @@ primary_exp(A) ::= T_NULL(B). { A = B; } primary_exp(A) ::= T_THIS(B). { A = B; } primary_exp(A) ::= array(B). { A = B; } primary_exp(A) ::= object(B). { A = B; } -primary_exp(A) ::= paren_exp(B). { A = uc_reject_local(s, B); } +primary_exp(A) ::= paren_exp(B). { A = uc_reject_local(state, B); } primary_exp(A) ::= T_FUNC(B) T_LPAREN T_RPAREN empty_object. { A = B; } primary_exp(A) ::= T_FUNC(B) T_LPAREN args(C) T_RPAREN empty_object. @@ -459,8 +454,8 @@ array(A) ::= T_LBRACK(B) items(C) T_RBRACK. { A = wrap_op(B, C); } items(A) ::= items(B) T_COMMA item(C). { A = append_op(B, C); } items(A) ::= item(B). { A = B; } -item(A) ::= T_ELLIP assign_exp(B). { A = uc_get_op(s, B)->tree.next ? new_op(T_COMMA, NULL, B) : B; uc_get_op(s, A)->is_ellip = 1; } -item(A) ::= assign_exp(B). { A = uc_get_op(s, B)->tree.next ? new_op(T_COMMA, NULL, B) : B; } +item(A) ::= T_ELLIP assign_exp(B). { A = OP_NEXT(B) ? new_op(T_COMMA, NULL, B) : B; OP(A)->is_ellip = 1; } +item(A) ::= assign_exp(B). { A = OP_NEXT(B) ? new_op(T_COMMA, NULL, B) : B; } object(A) ::= empty_object(B). { A = B; } object(A) ::= T_LBRACE(B) tuples(C) T_RBRACE. { A = wrap_op(B, C); } @@ -474,8 +469,8 @@ tuple(A) ::= T_LABEL(B) T_COLON exp(C). { A = wrap_op(B, C); } tuple(A) ::= T_STRING(B) T_COLON exp(C). { A = wrap_op(B, C); } tuple(A) ::= T_ELLIP(B) assign_exp(C). { A = wrap_op(B, C); } -arg_exps(A) ::= arg_exps(B) T_COMMA arg_exp(C). { A = append_op(B, C); uc_get_op(s, A)->is_list = 1; } -arg_exps(A) ::= arg_exp(B). { A = B; uc_get_op(s, A)->is_list = 1; } +arg_exps(A) ::= arg_exps(B) T_COMMA arg_exp(C). { A = append_op(B, C); OP(A)->is_list = 1; } +arg_exps(A) ::= arg_exp(B). { A = B; OP(A)->is_list = 1; } -arg_exp(A) ::= T_ELLIP assign_exp(B). { A = uc_get_op(s, B)->tree.next ? new_op(T_COMMA, NULL, B) : B; uc_get_op(s, A)->is_ellip = 1; } -arg_exp(A) ::= assign_exp(B). { A = uc_get_op(s, B)->tree.next ? new_op(T_COMMA, NULL, B) : B; } +arg_exp(A) ::= T_ELLIP assign_exp(B). { A = OP_NEXT(B) ? new_op(T_COMMA, NULL, B) : B; OP(A)->is_ellip = 1; } +arg_exp(A) ::= assign_exp(B). { A = OP_NEXT(B) ? new_op(T_COMMA, NULL, B) : B; } |