summaryrefslogtreecommitdiffhomepage
path: root/lib.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2021-02-17 18:28:01 +0100
committerGitHub <noreply@github.com>2021-02-17 18:28:01 +0100
commit679270fd3afa93cca84ab31b5041922037fec0c5 (patch)
treee55752bae52bf7eed38b91c42e990a8b116b6621 /lib.c
parent77580a893283f2bde7ab46496bd3a3d7b2fc6784 (diff)
parent14e46b8e225dc329f4e14777960b10abb8a09699 (diff)
Merge pull request #2 from jow-/rewrite
treewide: rewrite ucode interpreter
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c1220
1 files changed, 596 insertions, 624 deletions
diff --git a/lib.c b/lib.c
index d2c361b..c8b50b6 100644
--- a/lib.c
+++ b/lib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 Jo-Philipp Wich <jo@mein.io>
+ * Copyright (C) 2020-2021 Jo-Philipp Wich <jo@mein.io>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,13 +14,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "ast.h"
-#include "parser.h"
-#include "lexer.h"
-#include "eval.h"
-#include "lib.h"
-#include "module.h"
-
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -38,6 +31,40 @@
#include <sys/types.h>
#include <sys/wait.h>
+#include "lexer.h"
+#include "compiler.h"
+#include "vm.h"
+#include "lib.h"
+#include "object.h"
+
+
+const uc_ops uc = {
+ .value = {
+ .proto = uc_prototype_new,
+ .cfunc = uc_cfunction_new,
+ .dbl = uc_double_new,
+ .regexp = uc_regexp_new,
+ .tonumber = uc_cast_number,
+ .ressource = uc_ressource_new
+ },
+
+ .ressource = {
+ .define = uc_ressource_type_add,
+ .create = uc_ressource_new,
+ .data = uc_ressource_dataptr,
+ .proto = uc_ressource_prototype
+ },
+
+ .vm = {
+ .call = uc_vm_call,
+ .peek = uc_vm_stack_peek,
+ .pop = uc_vm_stack_pop,
+ .push = uc_vm_stack_push,
+ .raise = uc_vm_raise_exception
+ }
+};
+
+const uc_ops *ops = &uc;
__attribute__((format(printf, 3, 5))) static void
snprintf_append(char **dptr, size_t *dlen, const char *fmt, ssize_t sz, ...)
@@ -67,12 +94,15 @@ snprintf_append(char **dptr, size_t *dlen, const char *fmt, ssize_t sz, ...)
snprintf_append(dptr, dlen, fmt, -1, ##__VA_ARGS__)
static void
-format_context_line(char **msg, size_t *msglen, const char *line, size_t off)
+format_context_line(char **msg, size_t *msglen, const char *line, size_t off, bool compact)
{
const char *p;
int padlen, i;
for (p = line, padlen = 0; *p != '\n' && *p != '\0'; p++) {
+ if (compact && (p - line) == off)
+ sprintf_append(msg, msglen, "\033[22m");
+
switch (*p) {
case '\t':
sprintf_append(msg, msglen, " ");
@@ -94,6 +124,12 @@ format_context_line(char **msg, size_t *msglen, const char *line, size_t off)
}
}
+ if (compact) {
+ sprintf_append(msg, msglen, "\033[m\n");
+
+ return;
+ }
+
sprintf_append(msg, msglen, "`\n ");
if (padlen < strlen("Near here ^")) {
@@ -112,17 +148,73 @@ format_context_line(char **msg, size_t *msglen, const char *line, size_t off)
}
}
-static void
-format_error_context(char **msg, size_t *msglen, struct uc_source *src, struct json_object *stacktrace, size_t off)
+static char *
+source_filename(uc_source *src, uint32_t line)
{
- struct json_object *e, *fn, *file, *line, *byte;
- size_t len, rlen, idx;
- const char *path;
+ const char *name = src->filename ? basename(src->filename) : "[?]";
+ static char buf[sizeof("xxxxxxxxx.uc:0000000000")];
+ size_t len = strlen(name);
+
+ if (len > 12)
+ snprintf(buf, sizeof(buf), "...%s:%u", name + (len - 9), line);
+ else
+ snprintf(buf, sizeof(buf), "%12s:%u", name, line);
+
+ return buf;
+}
+
+void
+format_source_context(char **msg, size_t *msglen, uc_source *src, size_t off, bool compact)
+{
+ size_t len, rlen;
bool truncated;
char buf[256];
+ long srcpos;
int eline;
- for (idx = 0; idx < json_object_array_length(stacktrace); idx++) {
+ srcpos = ftell(src->fp);
+
+ if (srcpos == -1)
+ return;
+
+ fseek(src->fp, 0, SEEK_SET);
+
+ truncated = false;
+ eline = 1;
+ rlen = 0;
+
+ while (fgets(buf, sizeof(buf), src->fp)) {
+ len = strlen(buf);
+ rlen += len;
+
+ if (rlen > off) {
+ if (compact)
+ sprintf_append(msg, msglen, "\033[2;40;97m%17s %s",
+ source_filename(src, eline),
+ truncated ? "..." : "");
+ else
+ sprintf_append(msg, msglen, "\n `%s",
+ truncated ? "..." : "");
+
+ format_context_line(msg, msglen, buf, len - (rlen - off) + (truncated ? 3 : 0), compact);
+ break;
+ }
+
+ truncated = (len > 0 && buf[len-1] != '\n');
+ eline += !truncated;
+ }
+
+ fseek(src->fp, srcpos, SEEK_SET);
+}
+
+void
+format_error_context(char **msg, size_t *msglen, uc_source *src, json_object *stacktrace, size_t off)
+{
+ json_object *e, *fn, *file, *line, *byte;
+ const char *path;
+ size_t idx;
+
+ for (idx = 0; idx < (stacktrace ? json_object_array_length(stacktrace) : 0); idx++) {
e = json_object_array_get_idx(stacktrace, idx);
fn = json_object_object_get(e, "function");
file = json_object_object_get(e, "filename");
@@ -153,94 +245,22 @@ format_error_context(char **msg, size_t *msglen, struct uc_source *src, struct j
sprintf_append(msg, msglen, " called from %s%s (%s",
fn ? "function " : "anonymous function",
fn ? json_object_get_string(fn) : "",
- json_object_get_string(file));
+ file ? json_object_get_string(file) : "");
if (line && byte)
sprintf_append(msg, msglen, ":%" PRId64 ":%" PRId64 ")\n",
json_object_get_int64(line),
json_object_get_int64(byte));
else
- sprintf_append(msg, msglen, " [C])\n");
- }
- }
-
- fseek(src->fp, 0, SEEK_SET);
-
- truncated = false;
- eline = 1;
- rlen = 0;
-
- while (fgets(buf, sizeof(buf), src->fp)) {
- len = strlen(buf);
- rlen += len;
-
- if (rlen > off) {
- sprintf_append(msg, msglen, "\n `%s", truncated ? "..." : "");
- format_context_line(msg, msglen, buf, len - (rlen - off) + (truncated ? 3 : 0));
- break;
- }
-
- truncated = (len > 0 && buf[len-1] != '\n');
- eline += !truncated;
- }
-}
-
-struct json_object *
-uc_parse_error(struct uc_state *state, uint32_t off, uint64_t *tokens, int max_token)
-{
- struct json_object *rv;
- size_t msglen = 0;
- bool first = true;
- char *msg = NULL;
- int i;
-
- for (i = 0; i <= max_token; i++) {
- if (tokens[i / 64] & ((uint64_t)1 << (i % 64))) {
- if (first) {
- sprintf_append(&msg, &msglen, "Expecting %s", uc_get_tokenname(i));
- first = false;
- }
- else if (i < max_token) {
- sprintf_append(&msg, &msglen, ", %s", uc_get_tokenname(i));
- }
- else {
- sprintf_append(&msg, &msglen, " or %s", uc_get_tokenname(i));
- }
+ sprintf_append(msg, msglen, "[C])\n");
}
}
- rv = uc_new_exception(state,
- off ? OP_POS(off) : state->lex.lastoff,
- "Syntax error: Unexpected token\n%s", msg);
- free(msg);
-
- return rv;
-}
-
-char *
-uc_format_error(struct uc_state *state, FILE *fp)
-{
- struct uc_source *src;
- struct uc_op *tag;
- size_t msglen = 0;
- char *msg = NULL;
-
- tag = json_object_get_userdata(state->exception);
- src = tag->tag.data;
-
- sprintf_append(&msg, &msglen, "%s\n",
- json_object_get_string(json_object_object_get(state->exception, "message")));
-
- if (tag->off)
- format_error_context(&msg, &msglen, src,
- json_object_object_get(state->exception, "stacktrace"),
- tag->off);
-
- return msg;
+ format_source_context(msg, msglen, src, off, false);
}
static double
-uc_cast_double(struct json_object *v)
+uc_cast_double(json_object *v)
{
enum json_type t;
int64_t n;
@@ -262,7 +282,7 @@ uc_cast_double(struct json_object *v)
}
static int64_t
-uc_cast_int64(struct json_object *v)
+uc_cast_int64(json_object *v)
{
enum json_type t;
int64_t n;
@@ -285,60 +305,17 @@ uc_cast_int64(struct json_object *v)
return n;
}
-static int
-uc_c_fn_to_string(struct json_object *v, struct printbuf *pb, int level, int flags)
-{
- struct uc_op *op = json_object_get_userdata(v);
- struct uc_function *fn = (void *)op + ALIGN(sizeof(*op));
-
- return sprintbuf(pb, "%sfunction %s(...) { [native code] }%s",
- level ? "\"" : "", fn->name, level ? "\"" : "");
-}
-
-static void
-uc_c_fn_free(struct json_object *v, void *ud)
-{
- struct uc_op *op = ud;
-
- json_object_put(op->tag.proto);
- free(ud);
-}
-
-static bool
-uc_register_function(struct uc_state *state, struct json_object *scope, const char *name, uc_c_fn *cfn)
+static json_object *
+uc_print_common(uc_vm *vm, size_t nargs, FILE *fh)
{
- struct json_object *val = xjs_new_object();
- struct uc_function *fn;
- struct uc_op *op;
-
- op = xalloc(ALIGN(sizeof(*op)) + ALIGN(sizeof(*fn)) + ALIGN(strlen(name) + 1));
- op->val = val;
- op->type = T_CFUNC;
-
- fn = (void *)op + ALIGN(sizeof(*op));
- fn->source = state->function ? state->function->source : NULL;
- fn->name = strcpy((char *)fn + ALIGN(sizeof(*fn)), name);
- fn->cfn = cfn;
-
- op->tag.data = fn;
-
- json_object_set_serializer(val, uc_c_fn_to_string, op, uc_c_fn_free);
-
- return json_object_object_add(scope, name, op->val);
-}
-
-static struct json_object *
-uc_print_common(struct uc_state *s, uint32_t off, struct json_object *args, FILE *fh)
-{
- struct json_object *item;
- size_t arridx, arrlen;
+ json_object *item;
size_t reslen = 0;
size_t len = 0;
+ size_t arridx;
const char *p;
- for (arridx = 0, arrlen = json_object_array_length(args);
- arridx < arrlen; arridx++) {
- item = json_object_array_get_idx(args, arridx);
+ for (arridx = 0; arridx < nargs; arridx++) {
+ item = uc_get_arg(arridx);
if (json_object_is_type(item, json_type_string)) {
p = json_object_get_string(item);
@@ -357,16 +334,16 @@ uc_print_common(struct uc_state *s, uint32_t off, struct json_object *args, FILE
}
-static struct json_object *
-uc_print(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_print(uc_vm *vm, size_t nargs)
{
- return uc_print_common(s, off, args, stdout);
+ return uc_print_common(vm, nargs, stdout);
}
-static struct json_object *
-uc_length(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_length(uc_vm *vm, size_t nargs)
{
- struct json_object *arg = json_object_array_get_idx(args, 0);
+ json_object *arg = uc_get_arg(0);
switch (json_object_get_type(arg)) {
case json_type_object:
@@ -383,18 +360,18 @@ uc_length(struct uc_state *s, uint32_t off, struct json_object *args)
}
}
-static struct json_object *
-uc_index(struct uc_state *s, uint32_t off, struct json_object *args, bool right)
+static json_object *
+uc_index(uc_vm *vm, size_t nargs, bool right)
{
- struct json_object *stack = json_object_array_get_idx(args, 0);
- struct json_object *needle = json_object_array_get_idx(args, 1);
+ json_object *stack = uc_get_arg(0);
+ json_object *needle = uc_get_arg(1);
size_t arridx, len, ret = -1;
const char *sstr, *nstr, *p;
switch (json_object_get_type(stack)) {
case json_type_array:
for (arridx = 0, len = json_object_array_length(stack); arridx < len; arridx++) {
- if (uc_cmp(T_EQ, json_object_array_get_idx(stack, arridx), needle)) {
+ if (uc_cmp(TK_EQ, json_object_array_get_idx(stack, arridx), needle)) {
ret = arridx;
if (!right)
@@ -425,42 +402,41 @@ uc_index(struct uc_state *s, uint32_t off, struct json_object *args, bool right)
}
}
-static struct json_object *
-uc_lindex(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_lindex(uc_vm *vm, size_t nargs)
{
- return uc_index(s, off, args, false);
+ return uc_index(vm, nargs, false);
}
-static struct json_object *
-uc_rindex(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_rindex(uc_vm *vm, size_t nargs)
{
- return uc_index(s, off, args, true);
+ return uc_index(vm, nargs, true);
}
-static struct json_object *
-uc_push(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_push(uc_vm *vm, size_t nargs)
{
- struct json_object *arr = json_object_array_get_idx(args, 0);
- struct json_object *item = NULL;
- size_t arridx, arrlen;
+ json_object *arr = uc_get_arg(0);
+ json_object *item = NULL;
+ size_t arridx;
if (!json_object_is_type(arr, json_type_array))
return NULL;
- for (arridx = 1, arrlen = json_object_array_length(args);
- arridx < arrlen; arridx++) {
- item = json_object_array_get_idx(args, arridx);
- json_object_array_add(arr, json_object_get(item));
+ for (arridx = 1; arridx < nargs; arridx++) {
+ item = uc_get_arg(arridx);
+ json_object_array_add(arr, uc_value_get(item));
}
- return json_object_get(item);
+ return uc_value_get(item);
}
-static struct json_object *
-uc_pop(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_pop(uc_vm *vm, size_t nargs)
{
- struct json_object *arr = json_object_array_get_idx(args, 0);
- struct json_object *item = NULL;
+ json_object *arr = uc_get_arg(0);
+ json_object *item = NULL;
size_t arrlen;
if (!json_object_is_type(arr, json_type_array))
@@ -476,20 +452,20 @@ uc_pop(struct uc_state *s, uint32_t off, struct json_object *args)
#endif
}
- return json_object_get(item);
+ return uc_value_get(item);
}
-static struct json_object *
-uc_shift(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_shift(uc_vm *vm, size_t nargs)
{
- struct json_object *arr = json_object_array_get_idx(args, 0);
- struct json_object *item = NULL;
+ json_object *arr = uc_get_arg(0);
+ json_object *item = NULL;
size_t arridx, arrlen;
if (!json_object_is_type(arr, json_type_array))
return NULL;
- item = json_object_get(json_object_array_get_idx(arr, 0));
+ item = uc_value_get(json_object_array_get_idx(arr, 0));
arrlen = json_object_array_length(arr);
for (arridx = 0; arridx < arrlen - 1; arridx++)
@@ -504,46 +480,45 @@ uc_shift(struct uc_state *s, uint32_t off, struct json_object *args)
return item;
}
-static struct json_object *
-uc_unshift(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_unshift(uc_vm *vm, size_t nargs)
{
- struct json_object *arr = json_object_array_get_idx(args, 0);
- struct json_object *item = NULL;
+ json_object *arr = uc_get_arg(0);
+ json_object *item = NULL;
size_t arridx, arrlen, addlen;
if (!json_object_is_type(arr, json_type_array))
return NULL;
arrlen = json_object_array_length(arr);
- addlen = json_object_array_length(args) - 1;
+ addlen = nargs - 1;
for (arridx = arrlen; arridx > 0; arridx--)
json_object_array_put_idx(arr, arridx + addlen - 1,
- json_object_get(json_object_array_get_idx(arr, arridx - 1)));
+ uc_value_get(json_object_array_get_idx(arr, arridx - 1)));
for (arridx = 0; arridx < addlen; arridx++) {
- item = json_object_array_get_idx(args, arridx + 1);
- json_object_array_put_idx(arr, arridx, json_object_get(item));
+ item = uc_get_arg(arridx + 1);
+ json_object_array_put_idx(arr, arridx, uc_value_get(item));
}
return item;
}
-static struct json_object *
-uc_chr(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_chr(uc_vm *vm, size_t nargs)
{
- size_t len = json_object_array_length(args);
size_t idx;
int64_t n;
char *str;
- if (!len)
+ if (!nargs)
return xjs_new_string_len("", 0);
- str = xalloc(len);
+ str = xalloc(nargs);
- for (idx = 0; idx < len; idx++) {
- n = uc_cast_int64(json_object_array_get_idx(args, idx));
+ for (idx = 0; idx < nargs; idx++) {
+ n = uc_cast_int64(uc_get_arg(idx));
if (n < 0)
n = 0;
@@ -553,25 +528,25 @@ uc_chr(struct uc_state *s, uint32_t off, struct json_object *args)
str[idx] = (char)n;
}
- return xjs_new_string_len(str, len);
+ return xjs_new_string_len(str, nargs);
}
-static struct json_object *
-uc_delete(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_delete(uc_vm *vm, size_t nargs)
{
- struct json_object *obj = json_object_array_get_idx(args, 0);
- struct json_object *rv = NULL;
- size_t arridx, arrlen;
+ json_object *obj = uc_get_arg(0);
+ json_object *rv = NULL;
const char *key;
+ size_t arridx;
if (!json_object_is_type(obj, json_type_object))
return NULL;
- for (arrlen = json_object_array_length(args), arridx = 1; arridx < arrlen; arridx++) {
- json_object_put(rv);
+ for (arridx = 1; arridx < nargs; arridx++) {
+ uc_value_put(rv);
- key = json_object_get_string(json_object_array_get_idx(args, arridx));
- rv = json_object_get(json_object_object_get(obj, key ? key : "null"));
+ key = json_object_get_string(uc_get_arg(arridx));
+ rv = uc_value_get(json_object_object_get(obj, key ? key : "null"));
json_object_object_del(obj, key ? key : "null");
}
@@ -579,28 +554,21 @@ uc_delete(struct uc_state *s, uint32_t off, struct json_object *args)
return rv;
}
-static struct json_object *
-uc_die(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_die(uc_vm *vm, size_t nargs)
{
- const char *msg = json_object_get_string(json_object_array_get_idx(args, 0));
- struct uc_function *prev_fn;
- struct json_object *ex;
-
- prev_fn = s->function;
- s->function = s->callstack->function;
-
- ex = uc_new_exception(s, s->callstack->off, "%s", msg ? msg : "Died");
+ const char *msg = json_object_get_string(uc_get_arg(0));
- s->function = prev_fn;
+ uc_vm_raise_exception(vm, EXCEPTION_USER, msg ? msg : "Died");
- return ex;
+ return NULL;
}
-static struct json_object *
-uc_exists(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_exists(uc_vm *vm, size_t nargs)
{
- 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));
+ json_object *obj = uc_get_arg(0);
+ const char *key = json_object_get_string(uc_get_arg(1));
if (!json_object_is_type(obj, json_type_object))
return false;
@@ -608,98 +576,95 @@ uc_exists(struct uc_state *s, uint32_t off, struct json_object *args)
return xjs_new_boolean(json_object_object_get_ex(obj, key ? key : "null", NULL));
}
-__attribute__((noreturn)) static struct json_object *
-uc_exit(struct uc_state *s, uint32_t off, struct json_object *args)
+__attribute__((noreturn)) static json_object *
+uc_exit(uc_vm *vm, size_t nargs)
{
- int64_t n = uc_cast_int64(json_object_array_get_idx(args, 0));
+ int64_t n = uc_cast_int64(uc_get_arg(0));
exit(n);
}
-static struct json_object *
-uc_getenv(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_getenv(uc_vm *vm, size_t nargs)
{
- const char *key = json_object_get_string(json_object_array_get_idx(args, 0));
+ const char *key = json_object_get_string(uc_get_arg(0));
char *val = key ? getenv(key) : NULL;
return val ? xjs_new_string(val) : NULL;
}
-static struct json_object *
-uc_filter(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_filter(uc_vm *vm, size_t nargs)
{
- struct json_object *obj = json_object_array_get_idx(args, 0);
- struct json_object *func = json_object_array_get_idx(args, 1);
- struct json_object *rv, *arr, *cmpargs;
+ json_object *obj = uc_get_arg(0);
+ json_object *func = uc_get_arg(1);
+ json_object *rv, *arr;
size_t arridx, arrlen;
if (!json_object_is_type(obj, json_type_array))
return NULL;
arr = xjs_new_array();
- cmpargs = xjs_new_array();
-
- json_object_array_put_idx(cmpargs, 2, json_object_get(obj));
for (arrlen = json_object_array_length(obj), arridx = 0; arridx < arrlen; arridx++) {
- json_object_array_put_idx(cmpargs, 0, json_object_get(json_object_array_get_idx(obj, arridx)));
- json_object_array_put_idx(cmpargs, 1, xjs_new_int64(arridx));
+ /* XXX: revisit leaks */
+ uc_vm_stack_push(vm, uc_value_get(func));
+ uc_vm_stack_push(vm, uc_value_get(json_object_array_get_idx(obj, arridx)));
+ uc_vm_stack_push(vm, xjs_new_int64(arridx));
+ uc_vm_stack_push(vm, uc_value_get(obj));
- rv = uc_invoke(s, off, NULL, func, cmpargs);
+ if (uc_vm_call(vm, false, 3)) {
+ uc_value_put(arr);
- if (uc_is_type(rv, T_EXCEPTION)) {
- json_object_put(cmpargs);
- json_object_put(arr);
-
- return rv;
+ return NULL;
}
+ rv = uc_vm_stack_pop(vm);
+
if (uc_val_is_truish(rv))
- json_object_array_add(arr, json_object_get(json_object_array_get_idx(obj, arridx)));
+ json_object_array_add(arr, uc_value_get(json_object_array_get_idx(obj, arridx)));
- json_object_put(rv);
+ uc_value_put(rv);
}
- json_object_put(cmpargs);
-
return arr;
}
-static struct json_object *
-uc_hex(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_hex(uc_vm *vm, size_t nargs)
{
- const char *val = json_object_get_string(json_object_array_get_idx(args, 0));
+ const char *val = json_object_get_string(uc_get_arg(0));
int64_t n;
char *e;
if (!val || !isxdigit(*val))
- return uc_new_double(NAN);
+ return uc_double_new(NAN);
n = strtoll(val, &e, 16);
if (e == val || *e)
- return uc_new_double(NAN);
+ return uc_double_new(NAN);
return xjs_new_int64(n);
}
-static struct json_object *
-uc_int(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_int(uc_vm *vm, size_t nargs)
{
- int64_t n = uc_cast_int64(json_object_array_get_idx(args, 0));
+ int64_t n = uc_cast_int64(uc_get_arg(0));
if (errno == EINVAL || errno == EOVERFLOW)
- return uc_new_double(NAN);
+ return uc_double_new(NAN);
return xjs_new_int64(n);
}
-static struct json_object *
-uc_join(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_join(uc_vm *vm, size_t nargs)
{
- 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);
- struct json_object *rv = NULL;
+ const char *sep = json_object_get_string(uc_get_arg(0));
+ json_object *arr = uc_get_arg(1);
+ json_object *rv = NULL;
size_t arrlen, arridx, len = 1;
const char *item;
char *res, *p;
@@ -750,11 +715,11 @@ out:
return rv;
}
-static struct json_object *
-uc_keys(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_keys(uc_vm *vm, size_t nargs)
{
- struct json_object *obj = json_object_array_get_idx(args, 0);
- struct json_object *arr = NULL;
+ json_object *obj = uc_get_arg(0);
+ json_object *arr = NULL;
if (!json_object_is_type(obj, json_type_object))
return NULL;
@@ -767,12 +732,12 @@ uc_keys(struct uc_state *s, uint32_t off, struct json_object *args)
return arr;
}
-static struct json_object *
-uc_lc(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_lc(uc_vm *vm, size_t nargs)
{
- const char *str = json_object_get_string(json_object_array_get_idx(args, 0));
+ const char *str = json_object_get_string(uc_get_arg(0));
size_t len = str ? strlen(str) : 0;
- struct json_object *rv = NULL;
+ json_object *rv = NULL;
char *res, *p;
if (!str)
@@ -792,50 +757,47 @@ uc_lc(struct uc_state *s, uint32_t off, struct json_object *args)
return rv;
}
-static struct json_object *
-uc_map(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_map(uc_vm *vm, size_t nargs)
{
- struct json_object *obj = json_object_array_get_idx(args, 0);
- struct json_object *func = json_object_array_get_idx(args, 1);
- struct json_object *arr, *cmpargs, *rv;
+ json_object *obj = uc_get_arg(0);
+ json_object *func = uc_get_arg(1);
+ json_object *arr, *rv;
size_t arridx, arrlen;
if (!json_object_is_type(obj, json_type_array))
return NULL;
arr = xjs_new_array();
- cmpargs = xjs_new_array();
-
- json_object_array_put_idx(cmpargs, 2, json_object_get(obj));
for (arrlen = json_object_array_length(obj), arridx = 0; arridx < arrlen; arridx++) {
- json_object_array_put_idx(cmpargs, 0, json_object_get(json_object_array_get_idx(obj, arridx)));
- json_object_array_put_idx(cmpargs, 1, xjs_new_int64(arridx));
+ /* XXX: revisit leaks */
+ uc_vm_stack_push(vm, uc_value_get(func));
+ uc_vm_stack_push(vm, uc_value_get(json_object_array_get_idx(obj, arridx)));
+ uc_vm_stack_push(vm, xjs_new_int64(arridx));
+ uc_vm_stack_push(vm, uc_value_get(obj));
- rv = uc_invoke(s, off, NULL, func, cmpargs);
+ if (uc_vm_call(vm, false, 3)) {
+ uc_value_put(arr);
- if (uc_is_type(rv, T_EXCEPTION)) {
- json_object_put(cmpargs);
- json_object_put(arr);
-
- return rv;
+ return NULL;
}
+ rv = uc_vm_stack_pop(vm);
+
json_object_array_add(arr, rv);
}
- json_object_put(cmpargs);
-
return arr;
}
-static struct json_object *
-uc_ord(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_ord(uc_vm *vm, size_t nargs)
{
- struct json_object *obj = json_object_array_get_idx(args, 0);
- struct json_object *rv, *pos;
- size_t i, len, nargs;
+ json_object *obj = uc_get_arg(0);
+ json_object *rv, *pos;
const char *str;
+ size_t i, len;
int64_t n;
if (!json_object_is_type(obj, json_type_string))
@@ -844,15 +806,13 @@ uc_ord(struct uc_state *s, uint32_t off, struct json_object *args)
str = json_object_get_string(obj);
len = json_object_get_string_len(obj);
- nargs = json_object_array_length(args);
-
if (nargs == 1)
return str[0] ? xjs_new_int64((int64_t)str[0]) : NULL;
rv = xjs_new_array();
for (i = 1; i < nargs; i++) {
- pos = json_object_array_get_idx(args, i);
+ pos = uc_get_arg(i);
if (json_object_is_type(pos, json_type_int)) {
n = json_object_get_int64(pos);
@@ -872,17 +832,19 @@ uc_ord(struct uc_state *s, uint32_t off, struct json_object *args)
return rv;
}
-static struct json_object *
-uc_type(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_type(uc_vm *vm, size_t nargs)
{
- struct json_object *v = json_object_array_get_idx(args, 0);
- struct uc_op *tag = json_object_get_userdata(v);
+ json_object *v = uc_get_arg(0);
+ uc_objtype_t o = uc_object_type(v);
- switch (tag ? tag->type : 0) {
- case T_FUNC:
+ switch (o) {
+ case UC_OBJ_CFUNCTION:
+ case UC_OBJ_FUNCTION:
+ case UC_OBJ_CLOSURE:
return xjs_new_string("function");
- case T_RESSOURCE:
+ case UC_OBJ_RESSOURCE:
return xjs_new_string("ressource");
default:
@@ -911,11 +873,11 @@ uc_type(struct uc_state *s, uint32_t off, struct json_object *args)
}
}
-static struct json_object *
-uc_reverse(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_reverse(uc_vm *vm, size_t nargs)
{
- struct json_object *obj = json_object_array_get_idx(args, 0);
- struct json_object *rv = NULL;
+ json_object *obj = uc_get_arg(0);
+ json_object *rv = NULL;
size_t len, arridx;
const char *str;
char *dup, *p;
@@ -924,7 +886,7 @@ uc_reverse(struct uc_state *s, uint32_t off, struct json_object *args)
rv = xjs_new_array();
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)));
+ json_object_array_add(rv, uc_value_get(json_object_array_get_idx(obj, arridx - 1)));
}
else if (json_object_is_type(obj, json_type_string)) {
len = json_object_get_string_len(obj);
@@ -944,80 +906,74 @@ uc_reverse(struct uc_state *s, uint32_t off, struct json_object *args)
static struct {
- struct uc_state *s;
- uint32_t off;
- struct json_object *fn;
- struct json_object *args;
- struct json_object *ex;
+ uc_vm *vm;
+ bool ex;
+ json_object *fn;
} sort_ctx;
static int
sort_fn(const void *k1, const void *k2)
{
- struct json_object * const *v1 = k1;
- struct json_object * const *v2 = k2;
- struct json_object *rv;
+ json_object * const *v1 = k1;
+ json_object * const *v2 = k2;
+ json_object *rv;
int ret;
if (!sort_ctx.fn)
- return !uc_cmp(T_LT, *v1, *v2);
+ return !uc_cmp(TK_LT, *v1, *v2);
if (sort_ctx.ex)
return 0;
- json_object_array_put_idx(sort_ctx.args, 0, json_object_get(*v1));
- json_object_array_put_idx(sort_ctx.args, 1, json_object_get(*v2));
-
- rv = uc_invoke(sort_ctx.s, sort_ctx.off, NULL, sort_ctx.fn, sort_ctx.args);
+ uc_vm_stack_push(sort_ctx.vm, uc_value_get(sort_ctx.fn));
+ uc_vm_stack_push(sort_ctx.vm, uc_value_get(*v1));
+ uc_vm_stack_push(sort_ctx.vm, uc_value_get(*v2));
- if (uc_is_type(rv, T_EXCEPTION)) {
- sort_ctx.ex = rv;
+ if (uc_vm_call(sort_ctx.vm, false, 2)) {
+ sort_ctx.ex = true;
return 0;
}
+ rv = uc_vm_stack_pop(sort_ctx.vm);
+
ret = !uc_val_is_truish(rv);
- json_object_put(rv);
+ uc_value_put(rv);
return ret;
}
-static struct json_object *
-uc_sort(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_sort(uc_vm *vm, size_t nargs)
{
- struct json_object *arr = json_object_array_get_idx(args, 0);
- struct json_object *fn = json_object_array_get_idx(args, 1);
+ json_object *arr = uc_get_arg(0);
+ json_object *fn = uc_get_arg(1);
if (!json_object_is_type(arr, json_type_array))
return NULL;
- if (fn) {
- sort_ctx.s = s;
- sort_ctx.off = off;
- sort_ctx.fn = fn;
- sort_ctx.args = xjs_new_array();
- }
+ sort_ctx.vm = vm;
+ sort_ctx.fn = fn;
json_object_array_sort(arr, sort_fn);
- json_object_put(sort_ctx.args);
- return sort_ctx.ex ? sort_ctx.ex : json_object_get(arr);
+ return sort_ctx.ex ? NULL : uc_value_get(arr);
}
-static struct json_object *
-uc_splice(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_splice(uc_vm *vm, size_t nargs)
{
- struct json_object *arr = json_object_array_get_idx(args, 0);
- int64_t ofs = uc_cast_int64(json_object_array_get_idx(args, 1));
- int64_t remlen = uc_cast_int64(json_object_array_get_idx(args, 2));
+ json_object *arr = uc_get_arg(0);
+ int64_t ofs = uc_cast_int64(uc_get_arg(1));
+ int64_t remlen = uc_cast_int64(uc_get_arg(2));
size_t arrlen, addlen, idx;
if (!json_object_is_type(arr, json_type_array))
return NULL;
arrlen = json_object_array_length(arr);
- addlen = json_object_array_length(args);
+ addlen = nargs;
if (addlen == 1) {
ofs = 0;
@@ -1068,26 +1024,26 @@ uc_splice(struct uc_state *s, uint32_t off, struct json_object *args)
else if (addlen > remlen) {
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)));
+ uc_value_get(json_object_array_get_idx(arr, idx - 1)));
}
for (idx = 0; idx < addlen; idx++)
json_object_array_put_idx(arr, ofs + idx,
- json_object_get(json_object_array_get_idx(args, 3 + idx)));
+ uc_value_get(uc_get_arg(3 + idx)));
- return json_object_get(arr);
+ return uc_value_get(arr);
}
-static struct json_object *
-uc_split(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_split(uc_vm *vm, size_t nargs)
{
- struct json_object *str = json_object_array_get_idx(args, 0);
- struct json_object *sep = json_object_array_get_idx(args, 1);
- struct json_object *arr = NULL;
+ json_object *str = uc_get_arg(0);
+ json_object *sep = uc_get_arg(1);
+ json_object *arr = NULL;
const char *p, *sepstr, *splitstr;
int eflags = 0, res;
regmatch_t pmatch;
- struct uc_op *tag;
+ uc_regexp *re;
size_t seplen;
if (!sep || !json_object_is_type(str, json_type_string))
@@ -1096,11 +1052,11 @@ uc_split(struct uc_state *s, uint32_t off, struct json_object *args)
arr = xjs_new_array();
splitstr = json_object_get_string(str);
- if (uc_is_type(sep, T_REGEXP)) {
- tag = json_object_get_userdata(sep);
+ if (uc_object_is_type(sep, UC_OBJ_REGEXP)) {
+ re = uc_object_as_regexp(sep);
while (true) {
- res = regexec((regex_t *)tag->tag.data, splitstr, 1, &pmatch, eflags);
+ res = regexec(&re->re, splitstr, 1, &pmatch, eflags);
if (res == REG_NOMATCH)
break;
@@ -1130,7 +1086,7 @@ uc_split(struct uc_state *s, uint32_t off, struct json_object *args)
json_object_array_add(arr, xjs_new_string_len(splitstr, p - splitstr));
}
else {
- json_object_put(arr);
+ uc_value_put(arr);
return NULL;
}
@@ -1138,12 +1094,12 @@ uc_split(struct uc_state *s, uint32_t off, struct json_object *args)
return arr;
}
-static struct json_object *
-uc_substr(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_substr(uc_vm *vm, size_t nargs)
{
- struct json_object *str = json_object_array_get_idx(args, 0);
- int64_t ofs = uc_cast_int64(json_object_array_get_idx(args, 1));
- int64_t sublen = uc_cast_int64(json_object_array_get_idx(args, 2));
+ json_object *str = uc_get_arg(0);
+ int64_t ofs = uc_cast_int64(uc_get_arg(1));
+ int64_t sublen = uc_cast_int64(uc_get_arg(2));
const char *p;
size_t len;
@@ -1153,7 +1109,7 @@ uc_substr(struct uc_state *s, uint32_t off, struct json_object *args)
p = json_object_get_string(str);
len = json_object_get_string_len(str);
- switch (json_object_array_length(args)) {
+ switch (nargs) {
case 1:
ofs = 0;
sublen = len;
@@ -1202,20 +1158,20 @@ uc_substr(struct uc_state *s, uint32_t off, struct json_object *args)
return xjs_new_string_len(p + ofs, sublen);
}
-static struct json_object *
-uc_time(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_time(uc_vm *vm, size_t nargs)
{
time_t t = time(NULL);
return xjs_new_int64((int64_t)t);
}
-static struct json_object *
-uc_uc(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_uc(uc_vm *vm, size_t nargs)
{
- const char *str = json_object_get_string(json_object_array_get_idx(args, 0));
+ const char *str = json_object_get_string(uc_get_arg(0));
size_t len = str ? strlen(str) : 0;
- struct json_object *rv = NULL;
+ json_object *rv = NULL;
char *res, *p;
if (!str)
@@ -1235,17 +1191,16 @@ uc_uc(struct uc_state *s, uint32_t off, struct json_object *args)
return rv;
}
-static struct json_object *
-uc_uchr(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_uchr(uc_vm *vm, size_t nargs)
{
- size_t len = json_object_array_length(args);
size_t idx, ulen;
char *p, *str;
int64_t n;
int rem;
- for (idx = 0, ulen = 0; idx < len; idx++) {
- n = uc_cast_int64(json_object_array_get_idx(args, idx));
+ for (idx = 0, ulen = 0; idx < nargs; idx++) {
+ n = uc_cast_int64(uc_get_arg(idx));
if (errno == EINVAL || errno == EOVERFLOW || n < 0 || n > 0x10FFFF)
ulen += 3;
@@ -1261,8 +1216,8 @@ uc_uchr(struct uc_state *s, uint32_t off, struct json_object *args)
str = xalloc(ulen);
- for (idx = 0, p = str, rem = ulen; idx < len; idx++) {
- n = uc_cast_int64(json_object_array_get_idx(args, idx));
+ for (idx = 0, p = str, rem = ulen; idx < nargs; idx++) {
+ n = uc_cast_int64(uc_get_arg(idx));
if (errno == EINVAL || errno == EOVERFLOW || n < 0 || n > 0x10FFFF)
n = 0xFFFD;
@@ -1274,11 +1229,11 @@ uc_uchr(struct uc_state *s, uint32_t off, struct json_object *args)
return xjs_new_string_len(str, ulen);
}
-static struct json_object *
-uc_values(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_values(uc_vm *vm, size_t nargs)
{
- struct json_object *obj = json_object_array_get_idx(args, 0);
- struct json_object *arr;
+ json_object *obj = uc_get_arg(0);
+ json_object *arr;
if (!json_object_is_type(obj, json_type_object))
return NULL;
@@ -1287,17 +1242,17 @@ uc_values(struct uc_state *s, uint32_t off, struct json_object *args)
json_object_object_foreach(obj, key, val) {
(void)key;
- json_object_array_add(arr, json_object_get(val));
+ json_object_array_add(arr, uc_value_get(val));
}
return arr;
}
-static struct json_object *
-uc_trim_common(struct uc_state *s, uint32_t off, struct json_object *args, bool start, bool end)
+static json_object *
+uc_trim_common(uc_vm *vm, size_t nargs, 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);
+ json_object *str = uc_get_arg(0);
+ json_object *chr = uc_get_arg(1);
const char *p, *c;
size_t len;
@@ -1333,32 +1288,32 @@ uc_trim_common(struct uc_state *s, uint32_t off, struct json_object *args, bool
return xjs_new_string_len(p, len);
}
-static struct json_object *
-uc_trim(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_trim(uc_vm *vm, size_t nargs)
{
- return uc_trim_common(s, off, args, true, true);
+ return uc_trim_common(vm, nargs, true, true);
}
-static struct json_object *
-uc_ltrim(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_ltrim(uc_vm *vm, size_t nargs)
{
- return uc_trim_common(s, off, args, true, false);
+ return uc_trim_common(vm, nargs, true, false);
}
-static struct json_object *
-uc_rtrim(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_rtrim(uc_vm *vm, size_t nargs)
{
- return uc_trim_common(s, off, args, false, true);
+ return uc_trim_common(vm, nargs, false, true);
}
static size_t
-uc_printf_common(struct uc_state *s, uint32_t off, struct json_object *args, char **res)
+uc_printf_common(uc_vm *vm, size_t nargs, char **res)
{
- struct json_object *fmt = json_object_array_get_idx(args, 0);
+ json_object *fmt = uc_get_arg(0);
char *fp, sfmt[sizeof("%0- 123456789.123456789%")];
union { const char *s; int64_t n; double d; } arg;
- size_t len = 0, arglen, argidx;
const char *fstr, *last, *p;
+ size_t len = 0, argidx = 1;
enum json_type t;
*res = NULL;
@@ -1368,9 +1323,6 @@ uc_printf_common(struct uc_state *s, uint32_t off, struct json_object *args, cha
else
fstr = "";
- arglen = json_object_array_length(args);
- argidx = 1;
-
for (last = p = fstr; *p; p++) {
if (*p == '%') {
snprintf_append(res, &len, "%s", p - last, last);
@@ -1447,8 +1399,8 @@ uc_printf_common(struct uc_state *s, uint32_t off, struct json_object *args, cha
case 'X':
t = json_type_int;
- if (argidx < arglen)
- arg.n = uc_cast_int64(json_object_array_get_idx(args, argidx++));
+ if (argidx < nargs)
+ arg.n = uc_cast_int64(uc_get_arg(argidx++));
else
arg.n = 0;
@@ -1462,8 +1414,8 @@ uc_printf_common(struct uc_state *s, uint32_t off, struct json_object *args, cha
case 'G':
t = json_type_double;
- if (argidx < arglen)
- arg.d = uc_cast_double(json_object_array_get_idx(args, argidx++));
+ if (argidx < nargs)
+ arg.d = uc_cast_double(uc_get_arg(argidx++));
else
arg.d = 0;
@@ -1472,8 +1424,8 @@ uc_printf_common(struct uc_state *s, uint32_t off, struct json_object *args, cha
case 'c':
t = json_type_int;
- if (argidx < arglen)
- arg.n = uc_cast_int64(json_object_array_get_idx(args, argidx++)) & 0xff;
+ if (argidx < nargs)
+ arg.n = uc_cast_int64(uc_get_arg(argidx++)) & 0xff;
else
arg.n = 0;
@@ -1482,8 +1434,8 @@ uc_printf_common(struct uc_state *s, uint32_t off, struct json_object *args, cha
case 's':
t = json_type_string;
- if (argidx < arglen)
- arg.s = json_object_get_string(json_object_array_get_idx(args, argidx++));
+ if (argidx < nargs)
+ arg.s = json_object_get_string(uc_get_arg(argidx++));
else
arg.s = NULL;
@@ -1494,9 +1446,9 @@ uc_printf_common(struct uc_state *s, uint32_t off, struct json_object *args, cha
case 'J':
t = json_type_string;
- if (argidx < arglen)
+ if (argidx < nargs)
arg.s = json_object_to_json_string_ext(
- json_object_array_get_idx(args, argidx++),
+ uc_get_arg(argidx++),
JSON_C_TO_STRING_SPACED|JSON_C_TO_STRING_NOSLASHESCAPE|JSON_C_TO_STRING_STRICT);
else
arg.s = NULL;
@@ -1543,14 +1495,14 @@ next:
return len;
}
-static struct json_object *
-uc_sprintf(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_sprintf(uc_vm *vm, size_t nargs)
{
- struct json_object *rv;
+ json_object *rv;
char *str = NULL;
size_t len;
- len = uc_printf_common(s, off, args, &str);
+ len = uc_printf_common(vm, nargs, &str);
rv = xjs_new_string_len(str, len);
free(str);
@@ -1558,13 +1510,13 @@ uc_sprintf(struct uc_state *s, uint32_t off, struct json_object *args)
return rv;
}
-static struct json_object *
-uc_printf(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_printf(uc_vm *vm, size_t nargs)
{
char *str = NULL;
size_t len;
- len = uc_printf_common(s, off, args, &str);
+ len = uc_printf_common(vm, nargs, &str);
len = fwrite(str, 1, len, stdout);
free(str);
@@ -1572,121 +1524,108 @@ uc_printf(struct uc_state *s, uint32_t off, struct json_object *args)
return xjs_new_int64(len);
}
-static struct json_object *
-uc_require_so(struct uc_state *state, uint32_t off, const char *path)
+static bool
+uc_require_so(uc_vm *vm, const char *path, json_object **res)
{
- void (*init)(const struct uc_ops *, struct uc_state *, struct json_object *);
- struct uc_function fn = {}, *prev_fn;
- struct uc_source *src, *prev_src;
- struct json_object *scope;
+ void (*init)(const uc_ops *, uc_prototype *);
+ uc_prototype *scope;
struct stat st;
void *dlh;
if (stat(path, &st))
- return NULL;
+ return false;
dlerror();
dlh = dlopen(path, RTLD_LAZY|RTLD_LOCAL);
- if (!dlh)
- return uc_new_exception(state, OP_POS(off),
- "Unable to dlopen file %s: %s", path, dlerror());
-
- init = dlsym(dlh, "uc_module_init");
+ if (!dlh) {
+ uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
+ "Unable to dlopen file '%s': %s", path, dlerror());
- if (!init)
- return uc_new_exception(state, OP_POS(off),
- "Module %s provides no 'uc_module_init' function", path);
-
- src = xalloc(sizeof(*src));
- src->filename = xstrdup(path);
- src->next = state->sources;
+ return true;
+ }
- fn.name = "require";
- fn.source = src;
+ init = dlsym(dlh, "uc_module_entry");
- prev_fn = state->function;
- state->function = &fn;
+ if (!init) {
+ uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
+ "Module '%s' provides no 'uc_module_entry' function", path);
- prev_src = state->source;
- state->source = state->sources = src;
+ return true;
+ }
- scope = xjs_new_object();
+ scope = uc_prototype_new(NULL);
- init(&ut, state, scope);
+ init(&uc, scope);
- state->source = prev_src;
- state->function = prev_fn;
+ *res = scope->header.jso;
- return scope;
+ return true;
}
-struct json_object *
-uc_execute_source(struct uc_state *s, struct uc_source *src, struct uc_scope *scope)
+static bool
+uc_require_ucode(uc_vm *vm, const char *path, uc_prototype *scope, json_object **res)
{
- struct json_object *entry, *rv;
+ uc_exception_type_t extype;
+ uc_prototype *prev_scope;
+ uc_function *function;
+ uc_closure *closure;
+ uc_source *source;
+ struct stat st;
+ char *err;
- rv = uc_parse(s, src->fp);
+ if (stat(path, &st))
+ return false;
- if (!uc_is_type(rv, T_EXCEPTION)) {
- entry = uc_new_func(s, s->main, scope ? scope : s->scope);
+ source = uc_source_new_file(path);
- json_object_put(rv);
- rv = uc_invoke(s, s->main, NULL, entry, NULL);
+ if (!source) {
+ uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
+ "Unable to open file '%s': %s", path, strerror(errno));
- json_object_put(entry);
+ return true;
}
- return rv;
-}
+ function = uc_compile(vm->config, source, &err);
-static struct json_object *
-uc_require_utpl(struct uc_state *state, uint32_t off, const char *path, struct uc_scope *scope)
-{
- struct uc_function fn = {}, *prev_fn;
- struct uc_source *src, *prev_src;
- struct json_object *rv;
- struct stat st;
- FILE *fp;
+ if (!function) {
+ uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
+ "Unable to compile module '%s':\n%s", path, err);
- if (stat(path, &st))
- return NULL;
+ uc_source_put(source);
+ free(err);
- fp = fopen(path, "rb");
+ return true;
+ }
- if (!fp)
- return uc_new_exception(state, OP_POS(off),
- "Unable to open file %s: %s", path, strerror(errno));
+ closure = uc_closure_new(function, false);
- src = xalloc(sizeof(*src));
- src->fp = fp;
- src->filename = path ? xstrdup(path) : NULL;
- src->next = state->sources;
+ uc_vm_stack_push(vm, closure->header.jso);
- prev_src = state->source;
- state->source = state->sources = src;
+ prev_scope = vm->globals;
+ vm->globals = scope ? scope : prev_scope;
- fn.name = "require";
- fn.source = src;
+ extype = uc_vm_call(vm, false, 0);
- prev_fn = state->function;
- state->function = &fn;
+ vm->globals = prev_scope;
- rv = uc_execute_source(state, src, scope);
+ if (extype == EXCEPTION_NONE)
+ *res = uc_vm_stack_pop(vm);
- state->function = prev_fn;
- state->source = prev_src;
+ uc_source_put(source);
- return rv;
+ return true;
}
-static struct json_object *
-uc_require_path(struct uc_state *s, uint32_t off, const char *path_template, const char *name)
+static bool
+uc_require_path(uc_vm *vm, const char *path_template, const char *name, json_object **res)
{
- struct json_object *rv = NULL;
const char *p, *q, *last;
char *path = NULL;
size_t plen = 0;
+ bool rv = false;
+
+ *res = NULL;
p = strchr(path_template, '*');
@@ -1711,9 +1650,9 @@ uc_require_path(struct uc_state *s, uint32_t off, const char *path_template, con
}
if (!strcmp(p, ".so"))
- rv = uc_require_so(s, off, path);
+ rv = uc_require_so(vm, path, res);
else if (!strcmp(p, ".uc"))
- rv = uc_require_utpl(s, off, path, NULL);
+ rv = uc_require_ucode(vm, path, NULL, res);
invalid:
free(path);
@@ -1721,56 +1660,49 @@ invalid:
return rv;
}
-static struct json_object *
-uc_require(struct uc_state *state, uint32_t off, struct json_object *args)
+static json_object *
+uc_require(uc_vm *vm, size_t nargs)
{
- struct json_object *val = json_object_array_get_idx(args, 0);
- struct json_object *search, *se, *res;
- struct uc_scope *sc, *scparent;
+ const char *name = json_object_get_string(uc_get_arg(0));
+
+ json_object *val = uc_get_arg(0);
+ json_object *search, *se, *res;
size_t arridx, arrlen;
- const char *name;
if (!json_object_is_type(val, json_type_string))
return NULL;
- /* find root scope */
- for (sc = state->scope; sc; ) {
- scparent = uc_parent_scope(sc);
+ name = json_object_get_string(val);
+ search = vm->globals ? json_object_object_get(vm->globals->header.jso, "REQUIRE_SEARCH_PATH") : NULL;
- if (!scparent)
- break;
+ if (!json_object_is_type(search, json_type_array)) {
+ uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
+ "Global require search path not set");
- sc = scparent;
+ return NULL;
}
- name = json_object_get_string(val);
- search = sc ? json_object_object_get(sc->scope, "REQUIRE_SEARCH_PATH") : NULL;
-
- if (!json_object_is_type(search, json_type_array))
- return uc_new_exception(state, off ? OP_POS(off) : 0,
- "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);
if (!json_object_is_type(se, json_type_string))
continue;
- res = uc_require_path(state, off, json_object_get_string(se), name);
-
- if (res)
+ if (uc_require_path(vm, json_object_get_string(se), name, &res))
return res;
}
- return uc_new_exception(state, off ? OP_POS(off) : 0,
- "No module named '%s' could be found", name);
+ uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
+ "No module named '%s' could be found", name);
+
+ return NULL;
}
-static struct json_object *
-uc_iptoarr(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_iptoarr(uc_vm *vm, size_t nargs)
{
- struct json_object *ip = json_object_array_get_idx(args, 0);
- struct json_object *res;
+ json_object *ip = uc_get_arg(0);
+ json_object *res;
union {
uint8_t u8[4];
struct in_addr in;
@@ -1804,7 +1736,7 @@ uc_iptoarr(struct uc_state *s, uint32_t off, struct json_object *args)
}
static int
-check_byte(struct json_object *v)
+check_byte(json_object *v)
{
int n;
@@ -1819,10 +1751,10 @@ check_byte(struct json_object *v)
return n;
}
-static struct json_object *
-uc_arrtoip(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_arrtoip(uc_vm *vm, size_t nargs)
{
- struct json_object *arr = json_object_array_get_idx(args, 0);
+ json_object *arr = uc_get_arg(0);
union {
uint8_t u8[4];
struct in6_addr in6;
@@ -1867,24 +1799,25 @@ uc_arrtoip(struct uc_state *s, uint32_t off, struct json_object *args)
}
}
-static struct json_object *
-uc_match(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_match(uc_vm *vm, size_t nargs)
{
- struct json_object *subject = json_object_array_get_idx(args, 0);
- struct json_object *pattern = json_object_array_get_idx(args, 1);
- struct uc_op *tag = json_object_get_userdata(pattern);
- struct json_object *rv = NULL, *m;
+ json_object *subject = uc_get_arg(0);
+ json_object *pattern = uc_get_arg(1);
+ json_object *rv = NULL, *m;
int eflags = 0, res, i;
regmatch_t pmatch[10];
+ uc_regexp *re;
const char *p;
- if (!uc_is_type(pattern, T_REGEXP) || !subject)
+ if (!uc_object_is_type(pattern, UC_OBJ_REGEXP) || !subject)
return NULL;
p = json_object_get_string(subject);
+ re = uc_object_as_regexp(pattern);
while (true) {
- res = regexec((regex_t *)tag->tag.data, p, ARRAY_SIZE(pmatch), pmatch, eflags);
+ res = regexec(&re->re, p, ARRAY_SIZE(pmatch), pmatch, eflags);
if (res == REG_NOMATCH)
break;
@@ -1897,7 +1830,7 @@ uc_match(struct uc_state *s, uint32_t off, struct json_object *args)
pmatch[i].rm_eo - pmatch[i].rm_so));
}
- if (tag->is_reg_global) {
+ if (re->global) {
if (!rv)
rv = xjs_new_array();
@@ -1915,39 +1848,37 @@ uc_match(struct uc_state *s, uint32_t off, struct json_object *args)
return rv;
}
-static struct json_object *
-uc_replace_cb(struct uc_state *s, uint32_t off, struct json_object *func,
+static json_object *
+uc_replace_cb(uc_vm *vm, json_object *func,
const char *subject, regmatch_t *pmatch, size_t plen,
char **sp, size_t *sl)
{
- struct json_object *cbargs = xjs_new_array();
- struct json_object *rv;
+ json_object *rv;
size_t i;
+ /* XXX: revisit leaks */
+ uc_vm_stack_push(vm, uc_value_get(func));
+
for (i = 0; i < plen && pmatch[i].rm_so != -1; i++) {
- json_object_array_add(cbargs,
+ uc_vm_stack_push(vm,
xjs_new_string_len(subject + pmatch[i].rm_so,
pmatch[i].rm_eo - pmatch[i].rm_so));
}
- rv = uc_invoke(s, off, NULL, func, cbargs);
-
- if (uc_is_type(rv, T_EXCEPTION)) {
- json_object_put(cbargs);
+ if (uc_vm_call(vm, false, i))
+ return NULL;
- return rv;
- }
+ rv = uc_vm_stack_pop(vm);
sprintf_append(sp, sl, "%s", rv ? json_object_get_string(rv) : "null");
- json_object_put(cbargs);
- json_object_put(rv);
+ uc_value_put(rv);
return NULL;
}
static void
-uc_replace_str(struct uc_state *s, uint32_t off, struct json_object *str,
+uc_replace_str(uc_vm *vm, json_object *str,
const char *subject, regmatch_t *pmatch, size_t plen,
char **sp, size_t *sl)
{
@@ -2011,36 +1942,37 @@ uc_replace_str(struct uc_state *s, uint32_t off, struct json_object *str,
}
}
-static struct json_object *
-uc_replace(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_replace(uc_vm *vm, size_t nargs)
{
- struct json_object *subject = json_object_array_get_idx(args, 0);
- struct json_object *pattern = json_object_array_get_idx(args, 1);
- struct json_object *replace = json_object_array_get_idx(args, 2);
- struct uc_op *tag = json_object_get_userdata(pattern);
- struct json_object *rv = NULL;
+ json_object *subject = uc_get_arg(0);
+ json_object *pattern = uc_get_arg(1);
+ json_object *replace = uc_get_arg(2);
+ json_object *rv = NULL;
const char *sb, *p, *l;
regmatch_t pmatch[10];
int eflags = 0, res;
size_t sl = 0, pl;
char *sp = NULL;
+ uc_regexp *re;
if (!pattern || !subject || !replace)
return NULL;
- if (uc_is_type(pattern, T_REGEXP)) {
+ if (uc_object_is_type(pattern, UC_OBJ_REGEXP)) {
p = json_object_get_string(subject);
+ re = uc_object_as_regexp(pattern);
while (true) {
- res = regexec((regex_t *)tag->tag.data, p, ARRAY_SIZE(pmatch), pmatch, eflags);
+ res = regexec(&re->re, p, ARRAY_SIZE(pmatch), pmatch, eflags);
if (res == REG_NOMATCH)
break;
snprintf_append(&sp, &sl, "%s", pmatch[0].rm_so, p);
- if (uc_is_type(replace, T_FUNC) || uc_is_type(replace, T_CFUNC)) {
- rv = uc_replace_cb(s, off, replace, p, pmatch, ARRAY_SIZE(pmatch), &sp, &sl);
+ if (uc_object_is_callable(replace)) {
+ rv = uc_replace_cb(vm, replace, p, pmatch, ARRAY_SIZE(pmatch), &sp, &sl);
if (rv) {
free(sp);
@@ -2049,12 +1981,12 @@ uc_replace(struct uc_state *s, uint32_t off, struct json_object *args)
}
}
else {
- uc_replace_str(s, off, replace, p, pmatch, ARRAY_SIZE(pmatch), &sp, &sl);
+ uc_replace_str(vm, replace, p, pmatch, ARRAY_SIZE(pmatch), &sp, &sl);
}
p += pmatch[0].rm_eo;
- if (tag->is_reg_global)
+ if (re->global)
eflags |= REG_NOTBOL;
else
break;
@@ -2074,8 +2006,8 @@ uc_replace(struct uc_state *s, uint32_t off, struct json_object *args)
pmatch[0].rm_so = sb - l;
pmatch[0].rm_eo = pmatch[0].rm_so + pl;
- if (uc_is_type(replace, T_FUNC) || uc_is_type(replace, T_CFUNC)) {
- rv = uc_replace_cb(s, off, replace, l, pmatch, 1, &sp, &sl);
+ if (uc_object_is_callable(replace)) {
+ rv = uc_replace_cb(vm, replace, l, pmatch, 1, &sp, &sl);
if (rv) {
free(sp);
@@ -2084,7 +2016,7 @@ uc_replace(struct uc_state *s, uint32_t off, struct json_object *args)
}
}
else {
- uc_replace_str(s, off, replace, l, pmatch, 1, &sp, &sl);
+ uc_replace_str(vm, replace, l, pmatch, 1, &sp, &sl);
}
l = sb + pl;
@@ -2101,18 +2033,21 @@ uc_replace(struct uc_state *s, uint32_t off, struct json_object *args)
return rv;
}
-static struct json_object *
-uc_json(struct uc_state *state, uint32_t off, struct json_object *args)
+static json_object *
+uc_json(uc_vm *vm, size_t nargs)
{
- struct json_object *rv, *src = json_object_array_get_idx(args, 0);
+ json_object *rv, *src = uc_get_arg(0);
struct json_tokener *tok = NULL;
enum json_tokener_error err;
const char *str;
size_t len;
- if (!json_object_is_type(src, json_type_string))
- return uc_new_exception(state, OP_POS(off),
- "Passed value is not a string");
+ if (!json_object_is_type(src, json_type_string)) {
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE,
+ "Passed value is not a string");
+
+ return NULL;
+ }
tok = xjs_new_tokener();
str = json_object_get_string(src);
@@ -2122,20 +2057,26 @@ uc_json(struct uc_state *state, uint32_t off, struct json_object *args)
err = json_tokener_get_error(tok);
if (err == json_tokener_continue) {
- json_object_put(rv);
- rv = uc_new_exception(state, OP_POS(off),
+ uc_value_put(rv);
+ uc_vm_raise_exception(vm, EXCEPTION_SYNTAX,
"Unexpected end of string in JSON data");
+
+ return NULL;
}
else if (err != json_tokener_success) {
- json_object_put(rv);
- rv = uc_new_exception(state, OP_POS(off),
+ uc_value_put(rv);
+ uc_vm_raise_exception(vm, EXCEPTION_SYNTAX,
"Failed to parse JSON string: %s",
json_tokener_error_desc(err));
+
+ return NULL;
}
else if (json_tokener_get_parse_end(tok) < len) {
- json_object_put(rv);
- rv = uc_new_exception(state, OP_POS(off),
+ uc_value_put(rv);
+ uc_vm_raise_exception(vm, EXCEPTION_SYNTAX,
"Trailing garbage after JSON data");
+
+ return NULL;
}
json_tokener_free(tok);
@@ -2176,64 +2117,83 @@ include_path(const char *curpath, const char *incpath)
return dup;
}
-static struct json_object *
-uc_include(struct uc_state *state, uint32_t off, struct json_object *args)
+static json_object *
+uc_include(uc_vm *vm, size_t nargs)
{
- struct json_object *rv, *path = json_object_array_get_idx(args, 0);
- struct json_object *scope = json_object_array_get_idx(args, 1);
- struct uc_scope *sc;
+ json_object *path = uc_get_arg(0);
+ json_object *scope = uc_get_arg(1);
+ json_object *rv = NULL;
+ uc_closure *closure = NULL;
+ uc_prototype *sc;
+ size_t i;
char *p;
- if (!json_object_is_type(path, json_type_string))
- return uc_new_exception(state, OP_POS(off),
- "Passed filename is not a string");
+ if (!json_object_is_type(path, json_type_string)) {
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE,
+ "Passed filename is not a string");
- if (scope && !json_object_is_type(scope, json_type_object))
- return uc_new_exception(state, OP_POS(off),
- "Passed scope value is not an object");
+ return NULL;
+ }
- p = include_path(state->callstack->function->source->filename, json_object_get_string(path));
+ if (scope && !json_object_is_type(scope, json_type_object)) {
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE,
+ "Passed scope value is not an object");
- if (!p)
- return uc_new_exception(state, OP_POS(off),
- "Include file not found");
+ return NULL;
+ }
+
+ /* find calling closure */
+ for (i = vm->callframes.count; i > 0; i--) {
+ closure = vm->callframes.entries[i - 1].closure;
+
+ if (closure)
+ break;
+ }
+
+ if (!closure)
+ return NULL;
+
+ p = include_path(closure->function->source->filename, json_object_get_string(path));
+
+ if (!p) {
+ uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
+ "Include file not found");
+
+ return NULL;
+ }
if (scope) {
- sc = uc_new_scope(state, NULL);
+ sc = uc_prototype_new(NULL);
json_object_object_foreach(scope, key, val)
- json_object_object_add(sc->scope, key, json_object_get(val));
+ json_object_object_add(sc->header.jso, key, uc_value_get(val));
}
else {
- sc = state->scope;
+ sc = vm->globals;
}
- rv = uc_require_utpl(state, off, p, sc);
+ if (uc_require_ucode(vm, p, sc, &rv))
+ uc_value_put(rv);
free(p);
if (scope)
- json_object_put(sc->scope);
-
- if (uc_is_type(rv, T_EXCEPTION))
- return rv;
-
- json_object_put(rv);
+ uc_value_put(sc->header.jso);
return NULL;
}
-static struct json_object *
-uc_warn(struct uc_state *s, uint32_t off, struct json_object *args)
+static json_object *
+uc_warn(uc_vm *vm, size_t nargs)
{
- return uc_print_common(s, off, args, stderr);
+ return uc_print_common(vm, nargs, stderr);
}
-static struct json_object *
-uc_system(struct uc_state *state, uint32_t off, struct json_object *args)
+static json_object *
+uc_system(uc_vm *vm, size_t nargs)
{
- struct json_object *cmdline = json_object_array_get_idx(args, 0);
- struct json_object *timeout = json_object_array_get_idx(args, 1);
+ json_object *cmdline = uc_get_arg(0);
+ json_object *timeout = uc_get_arg(1);
sigset_t sigmask, sigomask;
const char **arglist, *fn;
struct timespec ts;
@@ -2262,13 +2222,18 @@ uc_system(struct uc_state *state, uint32_t off, struct json_object *args)
break;
default:
- return uc_new_exception(state, OP_POS(off),
- "Passed command is neither string nor array");
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE,
+ "Passed command is neither string nor array");
+
+ return NULL;
}
- if (timeout && (!json_object_is_type(timeout, json_type_int) || json_object_get_int64(timeout) < 0))
- return uc_new_exception(state, OP_POS(off),
- "Invalid timeout specified");
+ if (timeout && (!json_object_is_type(timeout, json_type_int) || json_object_get_int64(timeout) < 0)) {
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE,
+ "Invalid timeout specified");
+
+ return NULL;
+ }
tms = timeout ? json_object_get_int64(timeout) : 0;
@@ -2339,22 +2304,31 @@ fail:
sigprocmask(SIG_SETMASK, &sigomask, NULL);
free(arglist);
- return uc_new_exception(state, OP_POS(off),
- "%s(): %s", fn, strerror(errno));
+ uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
+ "%s(): %s", fn, strerror(errno));
+
+ return NULL;
}
-const struct uc_ops ut = {
- .register_function = uc_register_function,
- .register_type = uc_register_extended_type,
- .set_type = uc_set_extended_type,
- .get_type = uc_get_extended_type,
- .new_object = uc_new_object,
- .new_double = uc_new_double,
- .invoke = uc_invoke,
- .cast_number = uc_cast_number,
-};
+static json_object *
+uc_trace(uc_vm *vm, size_t nargs)
+{
+ json_object *level = uc_get_arg(0);
+ uint8_t prev_level;
-static const struct { const char *name; uc_c_fn *func; } functions[] = {
+ if (!json_object_is_type(level, json_type_int)) {
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Invalid level specified");
+
+ return NULL;
+ }
+
+ prev_level = vm->trace;
+ vm->trace = json_object_get_int64(level);
+
+ return xjs_new_int64(prev_level);
+}
+
+static const uc_cfunction_list functions[] = {
{ "chr", uc_chr },
{ "delete", uc_delete },
{ "die", uc_die },
@@ -2401,14 +2375,12 @@ static const struct { const char *name; uc_c_fn *func; } functions[] = {
{ "include", uc_include },
{ "warn", uc_warn },
{ "system", uc_system },
+ { "trace", uc_trace },
};
void
-uc_lib_init(struct uc_state *state, struct json_object *scope)
+uc_lib_init(uc_prototype *scope)
{
- int i;
-
- for (i = 0; i < sizeof(functions) / sizeof(functions[0]); i++)
- uc_register_function(state, scope, functions[i].name, functions[i].func);
+ uc_add_proto_functions(scope, functions);
}