summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ast.c78
-rw-r--r--ast.h43
-rw-r--r--eval.c416
-rw-r--r--lexer.c83
-rw-r--r--lib.c116
-rw-r--r--main.c49
-rw-r--r--parser.y139
7 files changed, 454 insertions, 470 deletions
diff --git a/ast.c b/ast.c
index bbaa733..5715afb 100644
--- a/ast.c
+++ b/ast.c
@@ -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
diff --git a/ast.h b/ast.h
index 126aa65..ecc67b3 100644
--- a/ast.h
+++ b/ast.h
@@ -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);
diff --git a/eval.c b/eval.c
index 3473235..2f7d968 100644
--- a/eval.c
+++ b/eval.c
@@ -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;
diff --git a/lexer.c b/lexer.c
index a9c9d29..46692ec 100644
--- a/lexer.c
+++ b/lexer.c
@@ -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;
}
diff --git a/lib.c b/lib.c
index f143a96..d2c361b 100644
--- a/lib.c
+++ b/lib.c
@@ -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 = {
diff --git a/main.c b/main.c
index 5cbab74..11c191b 100644
--- a/main.c
+++ b/main.c
@@ -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) {
diff --git a/parser.y b/parser.y
index a992162..ebd5f5c 100644
--- a/parser.y
+++ b/parser.y
@@ -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; }