diff options
author | Jo-Philipp Wich <jo@mein.io> | 2020-09-02 22:11:02 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2020-09-02 22:11:02 +0200 |
commit | 12bb6730791e2f91a93279c742e94f29945caef6 (patch) | |
tree | 08de455ee5886dcd565ca01bd1bee126ccb93c91 | |
parent | d3240ccf01044b37a328a202303c0e3528aacf01 (diff) |
eval, lib: use tagged JSON objects to register C functions
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r-- | eval.c | 8 | ||||
-rw-r--r-- | lib.c | 44 | ||||
-rw-r--r-- | lib.h | 18 |
3 files changed, 47 insertions, 23 deletions
@@ -806,8 +806,8 @@ ut_invoke(struct ut_state *state, struct ut_opcode *op, struct json_object *scop { 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 json_object *s, *rv = NULL; - struct ut_opcode *tag; size_t arridx; ut_c_fn *cfn; @@ -815,8 +815,8 @@ ut_invoke(struct ut_state *state, struct ut_opcode *op, struct json_object *scop return NULL; /* is native function */ - if (decl->type == T_CFUNC) { - cfn = (ut_c_fn *)decl->operand[0]; + if (tag->type == T_CFUNC) { + cfn = (ut_c_fn *)tag->data; return cfn ? cfn(state, op, argvals) : NULL; } @@ -838,7 +838,7 @@ ut_invoke(struct ut_state *state, struct ut_opcode *op, struct json_object *scop case T_BREAK: case T_CONTINUE: ut_putval(rv); - rv = ut_exception(state, tag, "Syntax error: %s statement must be inside loop", + rv = ut_exception(state, (struct ut_opcode *)tag, "Syntax error: %s statement must be inside loop", tokennames[tag->type]); break; @@ -257,6 +257,48 @@ ut_cast_int64(struct json_object *v) return n; } +static int +ut_c_fn_to_string(struct json_object *v, struct printbuf *pb, int level, int flags) +{ + return sprintbuf(pb, "%sfunction(...) { [native code] }%s", + level ? "\"" : "", level ? "\"" : ""); +} + +static void +ut_c_fn_free(struct json_object *v, void *ud) +{ + struct ut_tagvalue *tag = json_object_get_userdata(v); + + json_object_put(tag->proto); + free(ud); +} + +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; + + if (!val) + return NULL; + + tag = calloc(1, sizeof(*tag)); + + if (!tag) { + json_object_put(val); + + return NULL; + } + + tag->val = val; + tag->type = T_CFUNC; + tag->data = fn; + + json_object_set_serializer(val, ut_c_fn_to_string, tag, ut_c_fn_free); + + return json_object_object_add(scope, name, tag->val); +} + static struct json_object * ut_print(struct ut_state *s, struct ut_opcode *op, struct json_object *args) { @@ -1605,5 +1647,5 @@ ut_lib_init(struct ut_state *state, struct json_object *scope) int i; for (i = 0; i < sizeof(functions) / sizeof(functions[0]); i++) - ut_add_function(state, scope, functions[i].name, functions[i].func); + ut_register_function(state, scope, functions[i].name, functions[i].func); } @@ -22,24 +22,6 @@ typedef struct json_object *(ut_c_fn)(struct ut_state *, struct ut_opcode *, struct json_object *); -static inline int -ut_c_fn_to_string(struct json_object *v, struct printbuf *pb, int level, int flags) -{ - return sprintbuf(pb, "%sfunction(...) { [native code] }%s", - level ? "\"" : "", level ? "\"" : ""); -} - -static inline bool -ut_add_function(struct ut_state *state, struct json_object *scope, const char *name, ut_c_fn *fn) -{ - struct ut_opcode *op = ut_new_op(state, T_CFUNC, - json_object_new_boolean(0), (struct ut_opcode *)fn, (void *)1); - - json_object_set_serializer(op->val, ut_c_fn_to_string, op, NULL); - - return json_object_object_add(scope, name, json_object_get(op->val)); -} - void ut_lib_init(struct ut_state *state, struct json_object *scope); char *ut_format_error(struct ut_state *state, const char *expr); |