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