diff --git a/Makefile b/Makefile index 5fe8aaa7..0ae4210a 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ PREFIX=/usr/local DST_TARGET=dst DEBUGGER=lldb DST_INTERNAL_HEADERS=$(addprefix core/,symcache.h opcodes.h compile.h gc.h util.h) -DST_HEADERS=$(addprefix include/dst/,dst.h dstconfig.h dsttypes.h dststate.h dststl.h) +DST_HEADERS=$(addprefix include/dst/,dst.h dstconfig.h dstcontext.h dsttypes.h dststate.h dststl.h) DST_C_LIBS=$(addprefix libs/,testlib.so) ############################# @@ -81,7 +81,7 @@ valgrind: $(DST_TARGET) @ valgrind --leak-check=full -v ./$(DST_TARGET) test: $(DST_TARGET) - @ ./$(DST_TARGET) --gcinterval=0 dsttest/suite0.dst + @ ./$(DST_TARGET) --gcinterval=0x10000 dsttest/suite0.dst valtest: $(DST_TARGET) valgrind --leak-check=full -v ./$(DST_TARGET) dsttests/basic.dst diff --git a/client/main.c b/client/main.c index 186ab26f..1a32b503 100644 --- a/client/main.c +++ b/client/main.c @@ -23,6 +23,7 @@ #include #include #include +#include #define DST_CLIENT_HELP 1 #define DST_CLIENT_VERBOSE 2 @@ -30,8 +31,6 @@ #define DST_CLIENT_REPL 8 #define DST_CLIENT_UNKNOWN 16 -static Dst env; - static int client_strequal(const char *a, const char *b) { while (*a) if (*a++ != *b++) return 0; return *a == *b; @@ -42,78 +41,13 @@ static int client_strequal_witharg(const char *a, const char *b) { return *a == '='; } -/* Load source from a file */ -static const uint8_t *loadsource(const char *fpath, int32_t *len) { - FILE *f = fopen(fpath, "rb"); - long fsize; - size_t fsizet; - uint8_t *source = NULL; - if (fseek(f, 0, SEEK_END)) goto error; - fsize = ftell(f); - if (fsize > INT32_MAX || fsize < 0) goto error; - fsizet = fsize; - if (fseek(f, 0, SEEK_SET)) goto error; - if (!fsize) goto error; - source = malloc(fsize); - if (fread(source, 1, fsize, f) != fsizet) goto error; - if (fclose(f)) goto error; - *len = (int32_t) fsizet; - return source; - - error: - free(source); - return NULL; -} - -/* Run file */ -static void runfile(const uint8_t *src, int32_t len) { - DstCompileOptions opts; - DstCompileResult cres; - DstParseResult res; - const uint8_t *s = src; - const uint8_t *end = src + len; - while (s < end) { - res = dst_parse(s, end - s, DST_PARSEFLAG_SOURCEMAP); - switch (res.status) { - case DST_PARSE_NODATA: - return; - case DST_PARSE_UNEXPECTED_EOS: - case DST_PARSE_ERROR: - dst_puts(dst_formatc("syntax error at %d: %S\n", - s - src + res.bytes_read + 1, res.error)); - if (res.bytes_read == 0) { - s++; - } - break; - case DST_PARSE_OK: - { - opts.source = res.value; - opts.flags = 0; - opts.env = env; - cres = dst_compile(opts); - if (cres.status == DST_COMPILE_OK) { - Dst ret = dst_wrap_nil(); - DstFunction *f = dst_compile_func(cres); - if (dst_run(dst_wrap_function(f), &ret)) { - dst_puts(dst_formatc("runtime error: %v\n", ret)); - } - } else { - dst_puts(dst_formatc("compile error at %d: %S\n", - s - src + cres.error_start + 1, cres.error)); - } - } - break; - } - s += res.bytes_read; - } -} - int main(int argc, char **argv) { int status = 0; int i; int fileRead = 0; uint32_t gcinterval = 0x10000; uint64_t flags = 0; + DstTable *env; /* Read the arguments. Ignore files. */ for (i = 1; i < argc; ++i) { @@ -192,20 +126,19 @@ int main(int argc, char **argv) { dst_init(); dst_vm_gc_interval = gcinterval; env = dst_stl_env(); - dst_gcroot(env); + dst_gcroot(dst_wrap_table(env)); /* Read the arguments. Only process files. */ for (i = 1; i < argc; ++i) { const char *arg = argv[i]; if (*arg != '-') { + DstContext ctxt; fileRead = 1; - int32_t len; - const uint8_t *s = loadsource(arg, &len); - if (NULL == s) { - printf("could not load file %s\n", arg); - } else { - runfile(s, len); + if (dst_context_file(&ctxt, env, arg)) { + printf("file %s not found\n", arg); + continue; } + status = dst_context_run(&ctxt, DST_PARSEFLAG_SOURCEMAP); } } @@ -213,7 +146,7 @@ int main(int argc, char **argv) { if (!fileRead || (flags & DST_CLIENT_REPL)) { DstContext ctxt; dst_context_repl(&ctxt, env); - status = dst_context_run(&ctxt); + status = dst_context_run(&ctxt, DST_PARSEFLAG_SOURCEMAP); } dst_deinit(); diff --git a/core/array.c b/core/array.c index 8ff2060e..210dc8f8 100644 --- a/core/array.c +++ b/core/array.c @@ -102,3 +102,58 @@ Dst dst_array_peek(DstArray *array) { return dst_wrap_nil(); } } + +/* C Functions */ + +static int cfun_pop(DstArgs args) { + if (args.n != 1 || !dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array"); + return dst_return(args, dst_array_pop(dst_unwrap_array(args.v[0]))); +} + +static int cfun_peek(DstArgs args) { + if (args.n != 1 || !dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array"); + return dst_return(args, dst_array_peek(dst_unwrap_array(args.v[0]))); +} + +static int cfun_push(DstArgs args) { + DstArray *array; + int32_t newcount; + if (args.n < 1 || !dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array"); + array = dst_unwrap_array(args.v[0]); + newcount = array->count - 1 + args.n; + dst_array_ensure(array, newcount); + if (args.n > 1) memcpy(array->data + array->count, args.v + 1, (args.n - 1) * sizeof(Dst)); + array->count = newcount; + return dst_return(args, args.v[0]); +} + +static int cfun_setcount(DstArgs args) { + int32_t newcount; + if (args.n != 2 || !dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array"); + if (!dst_checktype(args.v[1], DST_INTEGER)) return dst_throw(args, "expected positive integer"); + newcount = dst_unwrap_integer(args.v[1]); + if (newcount < 0) return dst_throw(args, "expected positive integer"); + dst_array_setcount(dst_unwrap_array(args.v[0]), newcount); + return dst_return(args, args.v[0]); +} + +static int cfun_ensure(DstArgs args) { + int32_t newcount; + if (args.n != 2 || !dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array"); + if (!dst_checktype(args.v[1], DST_INTEGER)) return dst_throw(args, "expected positive integer"); + newcount = dst_unwrap_integer(args.v[1]); + if (newcount < 0) return dst_throw(args, "expected positive integer"); + dst_array_ensure(dst_unwrap_array(args.v[0]), newcount); + return dst_return(args, args.v[0]); +} + +/* Load the array module */ +int dst_lib_array(DstArgs args) { + DstTable *env = dst_env_arg(args); + dst_env_def(env, "array-pop", dst_wrap_cfunction(cfun_pop)); + dst_env_def(env, "array-peek", dst_wrap_cfunction(cfun_peek)); + dst_env_def(env, "array-push", dst_wrap_cfunction(cfun_push)); + dst_env_def(env, "array-setcount", dst_wrap_cfunction(cfun_setcount)); + dst_env_def(env, "array-ensure", dst_wrap_cfunction(cfun_ensure)); + return 0; +} diff --git a/core/asm.c b/core/asm.c index 1896f67a..bb8d77e7 100644 --- a/core/asm.c +++ b/core/asm.c @@ -481,14 +481,15 @@ static uint32_t read_instruction( } /* Helper to assembly. Return the assembly result */ -static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts) { +static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) { DstAssembleResult result; DstAssembler a; - Dst s = opts.source; + Dst s = source; DstFuncDef *def; int32_t count, i; const Dst *arr; Dst x; + (void) flags; /* Initialize funcdef */ def = dst_gcalloc(DST_MEMORY_FUNCDEF, sizeof(DstFuncDef)); @@ -619,12 +620,9 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts) int32_t i; for (i = 0; i < count; i++) { DstAssembleResult subres; - DstAssembleOptions subopts; Dst subname; int32_t newlen; - subopts.source = arr[i]; - subopts.flags = opts.flags; - subres = dst_asm1(&a, subopts); + subres = dst_asm1(&a, arr[i], flags); if (subres.status != DST_ASSEMBLE_OK) { dst_asm_errorv(&a, subres.error); } @@ -730,8 +728,8 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts) } /* Assemble a function */ -DstAssembleResult dst_asm(DstAssembleOptions opts) { - return dst_asm1(NULL, opts); +DstAssembleResult dst_asm(Dst source, int flags) { + return dst_asm1(NULL, source, flags); } /* Build a function from the result */ @@ -915,12 +913,9 @@ Dst dst_disasm(DstFuncDef *def) { /* C Function for assembly */ int dst_asm_cfun(DstArgs args) { - DstAssembleOptions opts; DstAssembleResult res; if (args.n < 1) return dst_throw(args, "expected assembly source"); - opts.source = args.v[0]; - opts.flags = 0; - res = dst_asm(opts); + res = dst_asm(args.v[0], 0); if (res.status == DST_ASSEMBLE_OK) { return dst_return(args, dst_wrap_function(dst_asm_func(res))); } else { diff --git a/core/buffer.c b/core/buffer.c index 705029e0..504fbb38 100644 --- a/core/buffer.c +++ b/core/buffer.c @@ -139,3 +139,50 @@ int dst_buffer_push_u64(DstBuffer *buffer, uint64_t x) { buffer->count += 8; return 0; } + +/* C functions */ +static int cfun_u8(DstArgs args) { + int32_t i; + DstBuffer *buffer; + if (args.n < 1 || !dst_checktype(args.v[0], DST_BUFFER)) return dst_throw(args, "expected buffer"); + buffer = dst_unwrap_buffer(args.v[0]); + for (i = 1; i < args.n; i++) { + if (!dst_checktype(args.v[i], DST_INTEGER)) return dst_throw(args, "expected integer"); + if (dst_buffer_push_u8(buffer, (uint8_t) (dst_unwrap_integer(args.v[i]) & 0xFF))) return dst_throw(args, "buffer overflow"); + } + return dst_return(args, args.v[0]); +} + +static int cfun_int(DstArgs args) { + int32_t i; + DstBuffer *buffer; + if (args.n < 1 || !dst_checktype(args.v[0], DST_BUFFER)) return dst_throw(args, "expected buffer"); + buffer = dst_unwrap_buffer(args.v[0]); + for (i = 1; i < args.n; i++) { + if (!dst_checktype(args.v[i], DST_INTEGER)) return dst_throw(args, "expected integer"); + if (dst_buffer_push_u32(buffer, (uint32_t) dst_unwrap_integer(args.v[i]))) return dst_throw(args, "buffer overflow"); + } + return dst_return(args, args.v[0]); +} + +static int cfun_chars(DstArgs args) { + int32_t i; + DstBuffer *buffer; + if (args.n < 1 || !dst_checktype(args.v[0], DST_BUFFER)) return dst_throw(args, "expected buffer"); + buffer = dst_unwrap_buffer(args.v[0]); + for (i = 1; i < args.n; i++) { + int32_t len; + const uint8_t *str; + if (!dst_chararray_view(args.v[i], &str, &len)) return dst_throw(args, "expected string/buffer"); + if (dst_buffer_push_bytes(buffer, str, len)) return dst_throw(args, "buffer overflow"); + } + return dst_return(args, args.v[0]); +} + +int dst_lib_buffer(DstArgs args) { + DstTable *env = dst_env_arg(args); + dst_env_def(env, "buffer-push-byte", dst_wrap_cfunction(cfun_u8)); + dst_env_def(env, "buffer-push-integer", dst_wrap_cfunction(cfun_int)); + dst_env_def(env, "buffer-push-string", dst_wrap_cfunction(cfun_chars)); + return 0; +} diff --git a/core/compile.c b/core/compile.c index 2ef43761..f4510574 100644 --- a/core/compile.c +++ b/core/compile.c @@ -235,7 +235,7 @@ DstSlot dstc_resolve( /* Symbol not found - check for global */ { - Dst check = dst_get(c->env, dst_wrap_symbol(sym)); + Dst check = dst_table_get(c->env, dst_wrap_symbol(sym)); Dst ref; if (!(dst_checktype(check, DST_STRUCT) || dst_checktype(check, DST_TABLE))) { dstc_error(c, ast, dst_formatc("unknown symbol %q", sym)); @@ -846,7 +846,7 @@ DstFuncDef *dstc_pop_funcdef(DstCompiler *c) { /* Initialize a compiler */ -static void dstc_init(DstCompiler *c, Dst env) { +static void dstc_init(DstCompiler *c, DstTable *env) { c->scopes = NULL; c->buffer = NULL; c->mapbuffer = NULL; @@ -866,15 +866,16 @@ static void dstc_deinit(DstCompiler *c) { dst_v_free(c->scopes); dst_v_free(c->buffer); dst_v_free(c->mapbuffer); - c->env = dst_wrap_nil(); + c->env = NULL; } /* Compile a form. */ -DstCompileResult dst_compile(DstCompileOptions opts) { +DstCompileResult dst_compile(Dst source, DstTable *env, int flags) { DstCompiler c; DstFopts fopts; + (void) flags; - dstc_init(&c, opts.env); + dstc_init(&c, env); /* Push a function scope */ dstc_scope(&c, DST_SCOPE_FUNCTION | DST_SCOPE_TOP); @@ -885,7 +886,7 @@ DstCompileResult dst_compile(DstCompileOptions opts) { fopts.hint = dstc_cslot(dst_wrap_nil()); /* Compile the value */ - dstc_value(fopts, opts.source); + dstc_value(fopts, source); if (c.result.status == DST_COMPILE_OK) { c.result.funcdef = dstc_pop_funcdef(&c); @@ -916,15 +917,18 @@ DstFunction *dst_compile_func(DstCompileResult res) { /* C Function for compiling */ int dst_compile_cfun(DstArgs args) { - DstCompileOptions opts; DstCompileResult res; DstTable *t; + DstTable *env; if (args.n < 1) return dst_throw(args, "expected at least one argument"); - opts.source = args.v[0]; - opts.env = args.n >= 2 ? args.v[1] : dst_stl_env(); - opts.flags = 0; - res = dst_compile(opts); + if (args.n >= 2) { + if (!dst_checktype(args.v[1], DST_TABLE)) return dst_throw(args, "expected table as environment"); + env = dst_unwrap_table(args.v[1]); + } else { + env = dst_stl_env(); + } + res = dst_compile(args.v[0], env, 0); if (res.status == DST_COMPILE_OK) { DstFunction *fun = dst_compile_func(res); return dst_return(args, dst_wrap_function(fun)); diff --git a/core/compile.h b/core/compile.h index 4553b560..6fe5281f 100644 --- a/core/compile.h +++ b/core/compile.h @@ -104,7 +104,7 @@ struct DstCompiler { int32_t *mapbuffer; /* Hold the environment */ - Dst env; + DstTable *env; DstCompileResult result; }; diff --git a/core/compile_specials.c b/core/compile_specials.c index e9ca2e11..797ea82e 100644 --- a/core/compile_specials.c +++ b/core/compile_specials.c @@ -103,7 +103,7 @@ DstSlot dstc_var(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { dst_array_push(ref, dst_wrap_nil()); dst_table_put(reftab, dst_csymbolv("ref"), dst_wrap_array(ref)); handleattr(c, argn, argv, reftab); - dst_put(c->env, head, dst_wrap_table(reftab)); + dst_table_put(c->env, head, dst_wrap_table(reftab)); refslot = dstc_cslot(dst_wrap_array(ref)); refarrayslot = refslot; refslot.flags |= DST_SLOT_REF | DST_SLOT_NAMED | DST_SLOT_MUTABLE; @@ -163,7 +163,7 @@ DstSlot dstc_def(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { /* Add env entry to env */ handleattr(c, argn, argv, tab); - dst_put(c->env, head, dst_wrap_table(tab)); + dst_table_put(c->env, head, dst_wrap_table(tab)); /* Put value in table when evaulated */ tableindex = dstc_preread(c, ast, 0xFF, 1, tabslot); diff --git a/core/context.c b/core/context.c index a49f3dce..da6d9301 100644 --- a/core/context.c +++ b/core/context.c @@ -21,14 +21,12 @@ */ #include +#include -/*static void deinit_file(DstContext *c) {*/ - /*FILE *f = (FILE *) (c->user);*/ - /*fclose(f);*/ -/*}*/ +#define CHUNKSIZE 1024 /* Read input for a repl */ -static void replread(DstContext *c) { +static int replread(DstContext *c) { if (c->buffer.count == 0) printf("> "); else @@ -43,18 +41,18 @@ static void replread(DstContext *c) { dst_buffer_push_u8(&c->buffer, x); if (x == '\n') break; } + return 0; } /* Output for a repl */ static void replonvalue(DstContext *c, Dst value) { (void) c; dst_puts(dst_formatc("%v\n", value)); - if (dst_checktype(c->env, DST_TABLE)) - dst_module_def(dst_unwrap_table(c->env), "_", value); + dst_env_def(c->env, "_", value); } /* Handle errors on repl */ -static void replerror(DstContext *c, DstContextErrorType type, Dst err, size_t start, size_t end) { +static void simpleerror(DstContext *c, DstContextErrorType type, Dst err, size_t start, size_t end) { const char *errtype; (void) c; (void) start; @@ -70,49 +68,63 @@ static void replerror(DstContext *c, DstContextErrorType type, Dst err, size_t s errtype = "compile"; break; } - dst_puts(dst_formatc("%s error: %v\n", errtype, err)); + dst_puts(dst_formatc("%s error: %s\n", errtype, dst_to_string(err))); } -void dst_context_init(DstContext *c, Dst env) { - dst_buffer_init(&c->buffer, 1024); +static void filedeinit(DstContext *c) { + fclose((FILE *) (c->user)); +} + +static int fileread(DstContext *c) { + size_t nread; + FILE *f = (FILE *) c->user; + dst_buffer_ensure(&c->buffer, CHUNKSIZE); + nread = fread(c->buffer.data, 1, CHUNKSIZE, f); + if (nread != CHUNKSIZE && ferror(f)) { + return -1; + } + c->buffer.count = (int32_t) nread; + return 0; +} + +void dst_context_init(DstContext *c, DstTable *env) { + dst_buffer_init(&c->buffer, CHUNKSIZE); c->env = env; - dst_gcroot(env); - c->flushed_bytes = 0; + dst_gcroot(dst_wrap_table(env)); + c->index = 0; + c->read_chunk = NULL; + c->on_error = NULL; + c->on_value = NULL; + c->deinit = NULL; } void dst_context_deinit(DstContext *c) { dst_buffer_deinit(&c->buffer); if (c->deinit) c->deinit(c); - dst_gcunroot(c->env); + dst_gcunroot(dst_wrap_table(c->env)); } -void dst_context_repl(DstContext *c, Dst env) { - dst_buffer_init(&c->buffer, 1024); - c->env = env; - dst_gcroot(env); - c->flushed_bytes = 0; +int dst_context_repl(DstContext *c, DstTable *env) { + dst_context_init(c, env); c->user = NULL; - if (dst_checktype(c->env, DST_TABLE)) - dst_module_def(dst_unwrap_table(c->env), "_", dst_wrap_nil()); + dst_env_def(c->env, "_", dst_wrap_nil()); c->read_chunk = replread; - c->on_error = replerror; + c->on_error = simpleerror; c->on_value = replonvalue; + return 0; } -/* Remove everything in the current buffer */ -static void flushcontext(DstContext *c) { - c->flushed_bytes += c->buffer.count; - c->buffer.count = 0; -} - -/* Shift bytes in buffer down */ -/* TODO Make parser online so there is no need to - * do too much book keeping with the buffer. */ -static void bshift(DstContext *c, int32_t delta) { - c->buffer.count -= delta; - if (delta) { - memmove(c->buffer.data, c->buffer.data + delta, c->buffer.count); +int dst_context_file(DstContext *c, DstTable *env, const char *path) { + FILE *f = fopen(path, "r"); + if (!f) { + return -1; } + dst_context_init(c, env); + c->user = f; + c->read_chunk = fileread; + c->on_error = simpleerror; + c->deinit = filedeinit; + return 0; } /* Do something on an error. Return flags to or with current flags. */ @@ -125,72 +137,69 @@ static int doerror( if (c->on_error) { c->on_error(c, type, err, - c->flushed_bytes + bstart, - c->flushed_bytes + bend); + bstart, + bend); } return 1 << type; } /* Start a context */ -int dst_context_run(DstContext *c) { +int dst_context_run(DstContext *c, int flags) { int done = 0; - int flags = 0; + int errflags = 0; + DstParser parser; + dst_parser_init(&parser, flags); while (!done) { - DstCompileResult cres; - DstCompileOptions opts; - DstParseResult res = dst_parse(c->buffer.data, c->buffer.count, DST_PARSEFLAG_SOURCEMAP); - switch (res.status) { - case DST_PARSE_NODATA: - flushcontext(c); - case DST_PARSE_UNEXPECTED_EOS: - { - int32_t countbefore = c->buffer.count; - c->read_chunk(c); - /* If the last chunk was empty, finish */ - if (c->buffer.count == countbefore) { - done = 1; - flags |= doerror(c, DST_CONTEXT_ERROR_PARSE, - dst_cstringv("unexpected end of source"), - res.bytes_read, - res.bytes_read); + int bufferdone = 0; + while (!bufferdone) { + DstParserStatus status = dst_parser_status(&parser); + switch (status) { + case DST_PARSE_FULL: + { + DstCompileResult cres = dst_compile(dst_parser_produce(&parser), c->env, flags); + if (cres.status == DST_COMPILE_OK) { + DstFunction *f = dst_compile_func(cres); + Dst ret; + if (dst_run(dst_wrap_function(f), &ret)) { + /* Get location from stacktrace? */ + errflags |= doerror(c, DST_CONTEXT_ERROR_RUNTIME, ret, -1, -1); + } else { + if (c->on_value) { + c->on_value(c, ret); + } + } + } else { + errflags |= doerror(c, DST_CONTEXT_ERROR_COMPILE, + dst_wrap_string(cres.error), + cres.error_start, + cres.error_end); + } } break; - } - case DST_PARSE_ERROR: - flags |= doerror(c, DST_CONTEXT_ERROR_PARSE, - dst_wrap_string(res.error), - res.bytes_read, - res.bytes_read); - bshift(c, res.bytes_read); - break; - case DST_PARSE_OK: - { - opts.source = res.value; - opts.flags = 0; - opts.env = c->env; - cres = dst_compile(opts); - if (cres.status == DST_COMPILE_OK) { - DstFunction *f = dst_compile_func(cres); - Dst ret; - if (dst_run(dst_wrap_function(f), &ret)) { - /* Get location from stacktrace? */ - flags |= doerror(c, DST_CONTEXT_ERROR_RUNTIME, ret, -1, -1); - } else { - if (c->on_value) { - c->on_value(c, ret); - } - } - } else { - flags |= doerror(c, DST_CONTEXT_ERROR_COMPILE, - dst_wrap_string(cres.error), - cres.error_start, - cres.error_end); + case DST_PARSE_ERROR: + doerror(c, DST_CONTEXT_ERROR_PARSE, + dst_cstringv(dst_parser_error(&parser)), + parser.index, + parser.index); + break; + case DST_PARSE_PENDING: + case DST_PARSE_ROOT: + if (c->index >= c->buffer.count) { + bufferdone = 1; + break; } - bshift(c, res.bytes_read); - } - break; + dst_parser_consume(&parser, c->buffer.data[c->index++]); + break; + } + } + /* Refill the buffer */ + c->buffer.count = 0; + c->index = 0; + if (c->read_chunk(c) || c->buffer.count == 0) { + done = 1; } } - return flags; + dst_parser_deinit(&parser); + return errflags; } diff --git a/core/io.c b/core/io.c index 2ba4d613..abc887b6 100644 --- a/core/io.c +++ b/core/io.c @@ -227,28 +227,28 @@ static int dst_io_fclose(DstArgs args) { /* Define the entry point of the library */ #ifdef DST_LIB -#define dst_io_init _dst_init +#define dst_lib_io _dst_init #endif /* Module entry point */ -int dst_io_init(DstArgs args) { - DstTable *module = dst_get_module(args); - dst_module_def(module, "fopen", dst_wrap_cfunction(dst_io_fopen)); - dst_module_def(module, "fclose", dst_wrap_cfunction(dst_io_fclose)); - dst_module_def(module, "fread", dst_wrap_cfunction(dst_io_fread)); - dst_module_def(module, "fwrite", dst_wrap_cfunction(dst_io_fwrite)); - dst_module_def(module, "fflush", dst_wrap_cfunction(dst_io_fflush)); +int dst_lib_io(DstArgs args) { + DstTable *env = dst_env_arg(args); + dst_env_def(env, "fopen", dst_wrap_cfunction(dst_io_fopen)); + dst_env_def(env, "fclose", dst_wrap_cfunction(dst_io_fclose)); + dst_env_def(env, "fread", dst_wrap_cfunction(dst_io_fread)); + dst_env_def(env, "fwrite", dst_wrap_cfunction(dst_io_fwrite)); + dst_env_def(env, "fflush", dst_wrap_cfunction(dst_io_fflush)); /* stdout */ - dst_module_def(module, "stdout", + dst_env_def(env, "stdout", makef(stdout, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE)); /* stderr */ - dst_module_def(module, "stderr", + dst_env_def(env, "stderr", makef(stderr, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE)); /* stdin */ - dst_module_def(module, "stdin", + dst_env_def(env, "stdin", makef(stdin, IO_READ | IO_NOT_CLOSEABLE | IO_SERIALIZABLE)); return 0; diff --git a/core/math.c b/core/math.c index fc9a05f1..e21d79ed 100644 --- a/core/math.c +++ b/core/math.c @@ -343,52 +343,45 @@ static int dst_math_not(DstArgs args) { return 0; } -/* CMath entry point */ - -/* Define the entry point of the library */ -#ifdef DST_LIB -#define dst_math_init _dst_init -#endif - /* Module entry point */ -int dst_math_init(DstArgs args) { - DstTable *module = dst_get_module(args); - dst_module_def(module, "int", dst_wrap_cfunction(dst_int)); - dst_module_def(module, "real", dst_wrap_cfunction(dst_real)); - dst_module_def(module, "+", dst_wrap_cfunction(dst_add)); - dst_module_def(module, "-", dst_wrap_cfunction(dst_subtract)); - dst_module_def(module, "*", dst_wrap_cfunction(dst_multiply)); - dst_module_def(module, "/", dst_wrap_cfunction(dst_divide)); - dst_module_def(module, "%", dst_wrap_cfunction(dst_modulo)); - dst_module_def(module, "=", dst_wrap_cfunction(dst_math_equal)); - dst_module_def(module, "not=", dst_wrap_cfunction(dst_math_notequal)); - dst_module_def(module, "<", dst_wrap_cfunction(dst_math_ascending)); - dst_module_def(module, ">", dst_wrap_cfunction(dst_math_descending)); - dst_module_def(module, "<=", dst_wrap_cfunction(dst_math_notdescending)); - dst_module_def(module, ">=", dst_wrap_cfunction(dst_math_notascending)); - dst_module_def(module, "|", dst_wrap_cfunction(dst_bor)); - dst_module_def(module, "&", dst_wrap_cfunction(dst_band)); - dst_module_def(module, "^", dst_wrap_cfunction(dst_bxor)); - dst_module_def(module, "~", dst_wrap_cfunction(dst_bnot)); - dst_module_def(module, ">>", dst_wrap_cfunction(dst_lshift)); - dst_module_def(module, "<<", dst_wrap_cfunction(dst_rshift)); - dst_module_def(module, ">>>", dst_wrap_cfunction(dst_lshiftu)); - dst_module_def(module, "not", dst_wrap_cfunction(dst_math_not)); - dst_module_def(module, "cos", dst_wrap_cfunction(dst_cos)); - dst_module_def(module, "sin", dst_wrap_cfunction(dst_sin)); - dst_module_def(module, "tan", dst_wrap_cfunction(dst_tan)); - dst_module_def(module, "acos", dst_wrap_cfunction(dst_acos)); - dst_module_def(module, "asin", dst_wrap_cfunction(dst_asin)); - dst_module_def(module, "atan", dst_wrap_cfunction(dst_atan)); - dst_module_def(module, "exp", dst_wrap_cfunction(dst_exp)); - dst_module_def(module, "log", dst_wrap_cfunction(dst_log)); - dst_module_def(module, "log10", dst_wrap_cfunction(dst_log10)); - dst_module_def(module, "sqrt", dst_wrap_cfunction(dst_sqrt)); - dst_module_def(module, "floor", dst_wrap_cfunction(dst_floor)); - dst_module_def(module, "ceil", dst_wrap_cfunction(dst_ceil)); - dst_module_def(module, "pow", dst_wrap_cfunction(dst_pow)); - dst_module_def(module, "pi", dst_wrap_real(M_PI)); - dst_module_def(module, "\xCF\x80", dst_wrap_real(M_PI)); - dst_module_def(module, "e", dst_wrap_real(M_E)); +int dst_lib_math(DstArgs args) { + DstTable *env = dst_env_arg(args); + dst_env_def(env, "int", dst_wrap_cfunction(dst_int)); + dst_env_def(env, "real", dst_wrap_cfunction(dst_real)); + dst_env_def(env, "+", dst_wrap_cfunction(dst_add)); + dst_env_def(env, "-", dst_wrap_cfunction(dst_subtract)); + dst_env_def(env, "*", dst_wrap_cfunction(dst_multiply)); + dst_env_def(env, "/", dst_wrap_cfunction(dst_divide)); + dst_env_def(env, "%", dst_wrap_cfunction(dst_modulo)); + dst_env_def(env, "=", dst_wrap_cfunction(dst_math_equal)); + dst_env_def(env, "not=", dst_wrap_cfunction(dst_math_notequal)); + dst_env_def(env, "<", dst_wrap_cfunction(dst_math_ascending)); + dst_env_def(env, ">", dst_wrap_cfunction(dst_math_descending)); + dst_env_def(env, "<=", dst_wrap_cfunction(dst_math_notdescending)); + dst_env_def(env, ">=", dst_wrap_cfunction(dst_math_notascending)); + dst_env_def(env, "|", dst_wrap_cfunction(dst_bor)); + dst_env_def(env, "&", dst_wrap_cfunction(dst_band)); + dst_env_def(env, "^", dst_wrap_cfunction(dst_bxor)); + dst_env_def(env, "~", dst_wrap_cfunction(dst_bnot)); + dst_env_def(env, ">>", dst_wrap_cfunction(dst_lshift)); + dst_env_def(env, "<<", dst_wrap_cfunction(dst_rshift)); + dst_env_def(env, ">>>", dst_wrap_cfunction(dst_lshiftu)); + dst_env_def(env, "not", dst_wrap_cfunction(dst_math_not)); + dst_env_def(env, "cos", dst_wrap_cfunction(dst_cos)); + dst_env_def(env, "sin", dst_wrap_cfunction(dst_sin)); + dst_env_def(env, "tan", dst_wrap_cfunction(dst_tan)); + dst_env_def(env, "acos", dst_wrap_cfunction(dst_acos)); + dst_env_def(env, "asin", dst_wrap_cfunction(dst_asin)); + dst_env_def(env, "atan", dst_wrap_cfunction(dst_atan)); + dst_env_def(env, "exp", dst_wrap_cfunction(dst_exp)); + dst_env_def(env, "log", dst_wrap_cfunction(dst_log)); + dst_env_def(env, "log10", dst_wrap_cfunction(dst_log10)); + dst_env_def(env, "sqrt", dst_wrap_cfunction(dst_sqrt)); + dst_env_def(env, "floor", dst_wrap_cfunction(dst_floor)); + dst_env_def(env, "ceil", dst_wrap_cfunction(dst_ceil)); + dst_env_def(env, "pow", dst_wrap_cfunction(dst_pow)); + dst_env_def(env, "pi", dst_wrap_real(3.1415926535897931)); + dst_env_def(env, "\xCF\x80", dst_wrap_real(3.1415926535897931)); + dst_env_def(env, "e", dst_wrap_real(2.7182818284590451)); return 0; } diff --git a/core/parse.c b/core/parse.c index 287058ca..67e1a83d 100644 --- a/core/parse.c +++ b/core/parse.c @@ -21,16 +21,7 @@ */ #include - -/* Checks if a string slice is equal to a string constant */ -static int check_str_const(const char *ref, const uint8_t *start, const uint8_t *end) { - while (*ref && start < end) { - if (*ref != *(char *)start) return 0; - ++ref; - ++start; - } - return !*ref && start == end; -} +#include "util.h" /* Quote a value */ static Dst quote(Dst x) { @@ -155,381 +146,404 @@ static int to_hex(uint8_t c) { } } -typedef struct { - DstArray stack; - const uint8_t *srcstart; - const uint8_t *end; - const char *errmsg; - DstParseStatus status; +typedef int (*Consumer)(DstParser *p, DstParseState *state, uint8_t c); +struct DstParseState { + int32_t qcount; + int32_t argn; int flags; -} ParseArgs; + size_t start; + Consumer consumer; +}; +#define PFLAG_CONTAINER 1 -/* Entry point of the recursive descent parser */ -static const uint8_t *parse_recur( - ParseArgs *args, - const uint8_t *src, - int32_t recur) { - - const uint8_t *end = args->end; - const uint8_t *mapstart; - int32_t qcount = 0; - Dst ret; - - /* Prevent stack overflow */ - if (recur == 0) goto too_much_recur; - - /* try parsing again */ - begin: - - /* Trim leading whitespace and count quotes */ - while (src < end && (is_whitespace(*src) || *src == '\'')) { - if (*src == '\'') { - ++qcount; - } - ++src; - } - - /* Check for end of source */ - if (src >= end) { - if (qcount || recur != DST_RECURSION_GUARD) { - goto unexpected_eos; - } else { - goto nodata; - } - } - - /* Open mapping */ - mapstart = src; - - /* Detect token type based on first character */ - switch (*src) { - - /* Numbers, symbols, simple literals */ - default: - atom: - { - int ascii = 1; - Dst numcheck; - const uint8_t *tokenend = src; - if (!is_symbol_char(*src)) { - src++; - goto unexpected_character; - } - while (tokenend < end && is_symbol_char(*tokenend)) { - if (*tokenend++ > 127) ascii = 0; - } - numcheck = dst_scan_number(src, tokenend - src); - if (!dst_checktype(numcheck, DST_NIL)) { - ret = numcheck; - } else if (check_str_const("nil", src, tokenend)) { - ret = dst_wrap_nil(); - } else if (check_str_const("false", src, tokenend)) { - ret = dst_wrap_boolean(0); - } else if (check_str_const("true", src, tokenend)) { - ret = dst_wrap_boolean(1); - } else { - if (*src >= '0' && *src <= '9') { - goto sym_nodigits; - } else { - /* Don't do full utf8 check unless we have seen non ascii characters. */ - int valid = ascii || valid_utf8(src, tokenend - src); - if (!valid) - goto invalid_utf8; - if (*src == ':') { - ret = dst_stringv(src + 1, tokenend - src - 1); - } else { - ret = dst_symbolv(src, tokenend - src); - } - } - } - src = tokenend; - break; - } - - case '#': - { - /* Jump to next newline */ - while (src < end && *src != '\n') - ++src; - goto begin; - } - - /* String literals */ - case '"': - { - const uint8_t *strend = ++src; - const uint8_t *strstart = strend; - int32_t len = 0; - int containsEscape = 0; - /* Preprocess string to check for escapes and string end */ - while (strend < end && *strend != '"') { - len++; - if (*strend++ == '\\') { - containsEscape = 1; - if (strend >= end) goto unexpected_eos; - if (*strend == 'h') { - strend += 3; - if (strend >= end) goto unexpected_eos; - } else { - strend++; - if (strend >= end) goto unexpected_eos; - } - } - } - if (containsEscape) { - uint8_t *buf = dst_string_begin(len); - uint8_t *write = buf; - while (src < strend) { - if (*src == '\\') { - src++; - switch (*src++) { - case 'n': *write++ = '\n'; break; - case 'r': *write++ = '\r'; break; - case 't': *write++ = '\t'; break; - case 'f': *write++ = '\f'; break; - case '0': *write++ = '\0'; break; - case '"': *write++ = '"'; break; - case '\'': *write++ = '\''; break; - case 'z': *write++ = '\0'; break; - case 'e': *write++ = 27; break; - case 'h': { - int d1 = to_hex(*src++); - int d2 = to_hex(*src++); - if (d1 < 0 || d2 < 0) goto invalid_hex; - *write++ = 16 * d1 + d2; - break; - } - default: - goto unknown_strescape; - } - } else { - *write++ = *src++; - } - } - ret = dst_wrap_string(dst_string_end(buf)); - } else { - ret = dst_wrap_string(dst_string(strstart, strend - strstart)); - } - src = strend + 1; - break; - } - - /* Data Structure literals */ - case '@': - if (src[1] != '{') - goto atom; - case '(': - case '[': - case '{': - { - int32_t n = 0, i = 0; - int32_t istable = 0; - uint8_t close; - switch (*src++) { - case '[': close = ']'; break; - case '{': close = '}'; break; - case '@': close = '}'; src++; istable = 1; break; - default: close = ')'; break; - } - /* Trim trailing whitespace */ - while (src < end && (is_whitespace(*src))) - ++src; - /* Recursively parse inside literal */ - while (*src != close) { - src = parse_recur(args, src, recur - 1); - if (args->errmsg || !src) return src; - n++; - /* Trim trailing whitespace */ - while (src < end && (is_whitespace(*src))) - ++src; - } - src++; - switch (close) { - case ')': - { - Dst *tup = dst_tuple_begin(n); - for (i = n; i > 0; i--) { - tup[i - 1] = dst_array_pop(&args->stack); - } - ret = dst_wrap_tuple(dst_tuple_end(tup)); - break; - } - case ']': - { - DstArray *arr = dst_array(n); - for (i = n; i > 0; i--) { - arr->data[i - 1] = dst_array_pop(&args->stack); - } - arr->count = n; - ret = dst_wrap_array(arr); - break; - } - case '}': - { - if (n & 1) { - if (istable) - goto table_oddargs; - goto struct_oddargs; - } - if (istable) { - DstTable *t = dst_table(n); - for (i = n; i > 0; i -= 2) { - Dst val = dst_array_pop(&args->stack); - Dst key = dst_array_pop(&args->stack); - dst_table_put(t, key, val); - } - ret = dst_wrap_table(t); - } else { - DstKV *st = dst_struct_begin(n >> 1); - for (i = n; i > 0; i -= 2) { - Dst val = dst_array_pop(&args->stack); - Dst key = dst_array_pop(&args->stack); - dst_struct_put(st, key, val); - } - ret = dst_wrap_struct(dst_struct_end(st)); - } - break; - } - } - break; - } - } - - /* Quote the returned value qcount times */ - while (qcount--) { - if (args->flags & DST_PARSEFLAG_SOURCEMAP) - ret = dst_ast_wrap(ret, mapstart - args->srcstart, src - args->srcstart); - ret = quote(ret); - } - - /* Ast wrap */ - if (args->flags & DST_PARSEFLAG_SOURCEMAP) - ret = dst_ast_wrap(ret, mapstart - args->srcstart, src - args->srcstart); - - /* Push the result to the stack */ - dst_array_push(&args->stack, ret); - - /* Return the new source position for further calls */ - return src; - - /* Errors below */ - - nodata: - args->status = DST_PARSE_NODATA; - return NULL; - - unexpected_eos: - args->errmsg = "unexpected end of source"; - args->status = DST_PARSE_UNEXPECTED_EOS; - return NULL; - - unexpected_character: - args->errmsg = "unexpected character"; - args->status = DST_PARSE_ERROR; - return src; - - sym_nodigits: - args->errmsg = "symbols cannot start with digits"; - args->status = DST_PARSE_ERROR; - return src; - - table_oddargs: - args->errmsg = "table literal needs an even number of arguments"; - args->status = DST_PARSE_ERROR; - return src; - - struct_oddargs: - args->errmsg = "struct literal needs an even number of arguments"; - args->status = DST_PARSE_ERROR; - return src; - - unknown_strescape: - args->errmsg = "unknown string escape sequence"; - args->status = DST_PARSE_ERROR; - return src; - - invalid_hex: - args->errmsg = "invalid hex escape in string"; - args->status = DST_PARSE_ERROR; - return src; - - invalid_utf8: - args->errmsg = "identifier is not valid utf-8"; - args->status = DST_PARSE_ERROR; - return src; - - too_much_recur: - args->errmsg = "recursed too deeply in parsing"; - args->status = DST_PARSE_ERROR; - return src; +static void pushstate(DstParser *p, Consumer consumer, int flags) { + DstParseState s; + s.qcount = 0; + s.argn = 0; + s.flags = flags; + s.consumer = consumer; + s.start = p->index; + dst_v_push(p->states, s); } -/* Parse an array of bytes. Return value in the fiber return value. */ -DstParseResult dst_parse(const uint8_t *src, int32_t len, int flags) { - DstParseResult res; - ParseArgs args; - const uint8_t *newsrc; +static void popstate(DstParser *p, Dst val) { + DstParseState top = dst_v_last(p->states); + DstParseState *newtop; + dst_v_pop(p->states); + newtop = &dst_v_last(p->states); + if (newtop->flags & PFLAG_CONTAINER) { + int32_t i, len; + len = newtop->qcount; + /* Quote the returned value qcount times */ + for (i = 0; i < len; i++) { + if (p->flags & DST_PARSEFLAG_SOURCEMAP) + val = dst_ast_wrap(val, (int32_t) top.start, (int32_t) p->index); + val = quote(val); + } + newtop->qcount = 0; - dst_array_init(&args.stack, 10); - args.status = DST_PARSE_OK; - args.srcstart = src; - args.end = src + len; - args.errmsg = NULL; - args.flags = flags; + /* Ast wrap */ + if (p->flags & DST_PARSEFLAG_SOURCEMAP) + val = dst_ast_wrap(val, (int32_t) top.start, (int32_t) p->index); - newsrc = parse_recur(&args, src, DST_RECURSION_GUARD); - res.status = args.status; - res.bytes_read = (int32_t) (newsrc - src); + newtop->argn++; + dst_v_push(p->argstack, val); + } +} - if (args.errmsg) { - res.error = dst_cstring(args.errmsg); - res.value = dst_wrap_nil(); +static uint8_t checkescape(uint8_t c) { + switch (c) { + default: return 0; + case 'h': return 1; + case 'n': return '\n'; + case 't': return '\t'; + case 'r': return '\r'; + case '0': return '\0'; + case 'z': return '\0'; + case 'f': return '\f'; + case 'e': return 27; + case '"': return '"'; + case '\'': return '\''; + case '\\': return '\\'; + } +} + +/* Forward declare */ +static int stringchar(DstParser *p, DstParseState *state, uint8_t c); + +static int escapeh(DstParser *p, DstParseState *state, uint8_t c) { + int digit = to_hex(c); + if (digit < 0) { + p->error = "invalid hex digit in hex escape"; + return 1; + } + state->argn = (state->argn << 4) + digit;; + state->qcount--; + if (!state->qcount) { + dst_v_push(p->buf, (state->argn & 0xFF)); + state->argn = 0; + state->consumer = stringchar; + } + return 1; +} + +static int escape1(DstParser *p, DstParseState *state, uint8_t c) { + uint8_t e = checkescape(c); + if (!e) { + p->error = "invalid string escape sequence"; + return 1; + } + if (c == 'h') { + state->qcount = 2; + state->argn = 0; + state->consumer = escapeh; } else { - res.value = dst_array_pop(&args.stack); - res.error = NULL; + dst_v_push(p->buf, e); + state->consumer = stringchar; } - - dst_array_deinit(&args.stack); - - return res; + return 1; } -/* Parse a c string */ -DstParseResult dst_parsec(const char *src, int flags) { - int32_t len = 0; - while (src[len]) ++len; - return dst_parse((const uint8_t *)src, len, flags); +static int stringchar(DstParser *p, DstParseState *state, uint8_t c) { + /* Enter escape */ + if (c == '\\') { + state->consumer = escape1; + return 1; + } + /* String end */ + if (c == '"') { + /* String end */ + Dst ret = dst_wrap_string(dst_string(p->buf, dst_v_count(p->buf))); + dst_v_empty(p->buf); + popstate(p, ret); + return 1; + } + /* normal char */ + dst_v_push(p->buf, c); + return 1; } +/* Check for string equality in the buffer */ +static int check_str_const(const char *cstr, const uint8_t *str, int32_t len) { + int32_t index; + for (index = 0; index < len; index++) { + uint8_t c = str[index]; + uint8_t k = ((const uint8_t *)cstr)[index]; + if (c < k) return -1; + if (c > k) return 1; + if (k == '\0') break; + } + return (cstr[index] == '\0') ? 0 : -1; +} + +static int tokenchar(DstParser *p, DstParseState *state, uint8_t c) { + Dst numcheck, ret; + int32_t blen; + if (is_symbol_char(c)) { + dst_v_push(p->buf, (uint8_t) c); + if (c > 127) state->argn = 1; /* Use to indicate non ascii */ + return 1; + } + /* Token finished */ + blen = dst_v_count(p->buf); + numcheck = dst_scan_number(p->buf, blen); + if (!dst_checktype(numcheck, DST_NIL)) { + ret = numcheck; + } else if (!check_str_const("nil", p->buf, blen)) { + ret = dst_wrap_nil(); + } else if (!check_str_const("false", p->buf, blen)) { + ret = dst_wrap_false(); + } else if (!check_str_const("true", p->buf, blen)) { + ret = dst_wrap_true(); + } else { + if (p->buf[0] >= '0' && p->buf[0] <= '9') { + p->error = "symbol literal cannot start with a digit"; + return 0; + } else { + /* Don't do full utf8 check unless we have seen non ascii characters. */ + int valid = (!state->argn) || valid_utf8(p->buf, blen); + if (!valid) { + p->error = "invalid utf-8 in symbol"; + return 0; + } + if (p->buf[0] == ':') { + ret = dst_stringv(p->buf + 1, blen - 1); + } else { + ret = dst_symbolv(p->buf, blen); + } + } + } + dst_v_empty(p->buf); + popstate(p, ret); + return 0; +} + +static int comment(DstParser *p, DstParseState *state, uint8_t c) { + (void) state; + if (c == '\n') dst_v_pop(p->states); + return 1; +} + +/* Forward declaration */ +static int root(DstParser *p, DstParseState *state, uint8_t c); + +static int dotuple(DstParser *p, DstParseState *state, uint8_t c) { + if (c == ')') { + int32_t i; + Dst *ret = dst_tuple_begin(state->argn); + for (i = state->argn - 1; i >= 0; i--) { + ret[i] = dst_v_last(p->argstack); dst_v_pop(p->argstack); + } + popstate(p, dst_wrap_tuple(dst_tuple_end(ret))); + return 1; + } + return root(p, state, c); +} + +static int doarray(DstParser *p, DstParseState *state, uint8_t c) { + if (c == ']') { + int32_t i; + DstArray *array = dst_array(state->argn); + for (i = state->argn - 1; i >= 0; i--) { + array->data[i] = dst_v_last(p->argstack); dst_v_pop(p->argstack); + } + array->count = state->argn; + popstate(p, dst_wrap_array(array)); + return 1; + } + return root(p, state, c); +} + +static int dostruct(DstParser *p, DstParseState *state, uint8_t c) { + if (c == '}') { + int32_t i; + DstKV *st; + if (state->argn & 1) { + p->error = "struct literal expects even number of arguments"; + return 1; + } + st = dst_struct_begin(state->argn >> 1); + for (i = state->argn; i > 0; i -= 2) { + Dst value = dst_v_last(p->argstack); dst_v_pop(p->argstack); + Dst key = dst_v_last(p->argstack); dst_v_pop(p->argstack); + dst_struct_put(st, key, value); + } + popstate(p, dst_wrap_struct(dst_struct_end(st))); + return 1; + } + return root(p, state, c); +} + +static int dotable(DstParser *p, DstParseState *state, uint8_t c) { + if (c == '}') { + int32_t i; + DstTable *table; + if (state->argn & 1) { + p->error = "table literal expects even number of arguments"; + return 1; + } + table = dst_table(state->argn >> 1); + for (i = state->argn; i > 0; i -= 2) { + Dst value = dst_v_last(p->argstack); dst_v_pop(p->argstack); + Dst key = dst_v_last(p->argstack); dst_v_pop(p->argstack); + dst_table_put(table, key, value); + } + popstate(p, dst_wrap_table(table)); + return 1; + } + return root(p, state, c); +} + +static int ampersand(DstParser *p, DstParseState *state, uint8_t c) { + (void) state; + dst_v_pop(p->states); + if (c == '{') { + pushstate(p, dotable, PFLAG_CONTAINER); + return 1; + } + pushstate(p, tokenchar, 0); + dst_v_push(p->buf, '@'); /* Push the leading ampersand that was dropped */ + return 0; +} + +static int root(DstParser *p, DstParseState *state, uint8_t c) { + switch (c) { + default: + if (is_whitespace(c)) return 1; + pushstate(p, tokenchar, 0); + return 0; + case '\'': + state->qcount++; + return 1; + case '"': + pushstate(p, stringchar, 0); + return 1; + case '#': + pushstate(p, comment, 0); + return 1; + case '@': + pushstate(p, ampersand, 0); + return 1; + case ')': + case ']': + case '}': + p->error = "mismatched delimiter"; + return 1; + case '(': + pushstate(p, dotuple, PFLAG_CONTAINER); + return 1; + case '[': + pushstate(p, doarray, PFLAG_CONTAINER); + return 1; + case '{': + pushstate(p, dostruct, PFLAG_CONTAINER); + return 1; + } +} + +int dst_parser_consume(DstParser *parser, uint8_t c) { + int consumed = 0; + if (parser->error) return 0; + while (!consumed && !parser->error) { + DstParseState *state = &dst_v_last(parser->states); + consumed = state->consumer(parser, state, c); + } + parser->lookback = c; + return 1; +} + +DstParserStatus dst_parser_status(DstParser *parser) { + if (parser->error) return DST_PARSE_ERROR; + if (dst_v_count(parser->states) > 1) return DST_PARSE_PENDING; + if (dst_v_count(parser->argstack)) return DST_PARSE_FULL; + return DST_PARSE_ROOT; +} + +const char *dst_parser_error(DstParser *parser) { + DstParserStatus status = dst_parser_status(parser); + if (status == DST_PARSE_ERROR) { + const char *e = parser->error; + dst_v_empty(parser->argstack); + dst_v__cnt(parser->states) = 1; + parser->error = NULL; + dst_v_empty(parser->buf); + return e; + } + return NULL; +} + +Dst dst_parser_produce(DstParser *parser) { + Dst ret; + DstParserStatus status = dst_parser_status(parser); + if (status != DST_PARSE_FULL) return dst_wrap_nil(); + ret = dst_v_last(parser->argstack); + dst_v_pop(parser->argstack); + return ret; +} + +void dst_parser_init(DstParser *parser, int flags) { + parser->argstack = NULL; + parser->states = NULL; + parser->buf = NULL; + parser->error = NULL; + parser->index = 0; + parser->lookback = -1; + parser->flags = flags; + pushstate(parser, root, PFLAG_CONTAINER); +} + +void dst_parser_deinit(DstParser *parser) { + dst_v_free(parser->argstack); + dst_v_free(parser->buf); + dst_v_free(parser->states); +} + +/* C functions */ + +static int parsermark(void *p, size_t size) { + int32_t i; + DstParser *parser = (DstParser *)p; + (void) size; + for (i = 0; i < dst_v_count(parser->argstack); i++) { + dst_mark(parser->argstack[i]); + } + return 0; +} + +static int parsergc(void *p, size_t size) { + DstParser *parser = (DstParser *)p; + (void) size; + dst_parser_deinit(parser); + return 0; +} + +DstAbstractType dst_parse_parsertype = { + "stl.parser", + parsergc, + parsermark +}; + /* C Function parser */ -int dst_parse_cfun(DstArgs args) { - const uint8_t *src; - int32_t len; - DstParseResult res; - const char *status_string = "ok"; - DstTable *t; - if (args.n < 1) return dst_throw(args, "expected at least on argument"); - if (!dst_chararray_view(args.v[0], &src, &len)) return dst_throw(args, "expected string/buffer"); - res = dst_parse(src, len, 0); - t = dst_table(4); - switch (res.status) { - case DST_PARSE_OK: - status_string = "ok"; - break; - case DST_PARSE_ERROR: - status_string = "error"; - break; - case DST_PARSE_NODATA: - status_string = "nodata"; - break; - case DST_PARSE_UNEXPECTED_EOS: - status_string = "eos"; - break; +static int cfun_parser(DstArgs args) { + int flags; + if (args.n > 1) return dst_throw(args, "expected 1 argument"); + if (args.n) { + if (!dst_checktype(args.v[0], DST_INTEGER)) return dst_throw(args, "expected integer"); + flags = dst_unwrap_integer(args.v[0]); + } else { + flags = 0; } - dst_table_put(t, dst_cstringv("status"), dst_cstringv(status_string)); - if (res.status == DST_PARSE_OK) dst_table_put(t, dst_cstringv("value"), res.value); - if (res.status == DST_PARSE_ERROR) dst_table_put(t, dst_cstringv("error"), dst_wrap_string(res.error)); - dst_table_put(t, dst_cstringv("bytes-read"), dst_wrap_integer(res.bytes_read)); - return dst_return(args, dst_wrap_table(t)); + DstParser *p = dst_abstract(&dst_parse_parsertype, sizeof(DstParser)); + dst_parser_init(p, 0); + return dst_return(args, dst_wrap_abstract(p)); +} + +/* Load the library */ +int dst_lib_parse(DstArgs args) { + DstTable *env = dst_env_arg(args); + + dst_env_def(env, "parser", dst_wrap_cfunction(cfun_parser)); + + return 0; } diff --git a/core/stl.c b/core/stl.c index 67061417..8e7ddf3f 100644 --- a/core/stl.c +++ b/core/stl.c @@ -23,13 +23,6 @@ #include #include -int dst_stl_push(DstArgs args) { - if (args.n != 2) return dst_throw(args, "expected 2 arguments"); - if (!dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array"); - dst_array_push(dst_unwrap_array(args.v[0]), args.v[1]); - return dst_return(args, args.v[0]); -} - int dst_stl_exit(DstArgs args) { int32_t exitcode = 0; if (args.n > 0) { @@ -252,49 +245,51 @@ int dst_stl_hash(DstArgs args) { return dst_return(args, dst_wrap_integer(dst_hash(args.v[0]))); } -Dst dst_stl_env() { - Dst ret; - DstArgs args; - DstTable *module = dst_table(0); - ret = dst_wrap_table(module); - args.n = 1; - args.v = &ret; - args.ret = &ret; +DstTable *dst_stl_env() { + DstTable *env = dst_table(0); + Dst ret = dst_wrap_table(env); - dst_module_def(module, "native", dst_wrap_cfunction(dst_load_native)); - dst_module_def(module, "push", dst_wrap_cfunction(dst_stl_push)); - dst_module_def(module, "print", dst_wrap_cfunction(dst_stl_print)); - dst_module_def(module, "describe", dst_wrap_cfunction(dst_stl_describe)); - dst_module_def(module, "string", dst_wrap_cfunction(dst_stl_string)); - dst_module_def(module, "buffer-to-string", dst_wrap_cfunction(dst_stl_buffer_to_string)); - dst_module_def(module, "table", dst_wrap_cfunction(dst_cfun_table)); - dst_module_def(module, "array", dst_wrap_cfunction(dst_cfun_array)); - dst_module_def(module, "tuple", dst_wrap_cfunction(dst_cfun_tuple)); - dst_module_def(module, "struct", dst_wrap_cfunction(dst_cfun_struct)); - dst_module_def(module, "fiber", dst_wrap_cfunction(dst_stl_fiber)); - dst_module_def(module, "status", dst_wrap_cfunction(dst_stl_status)); - dst_module_def(module, "buffer", dst_wrap_cfunction(dst_stl_buffer)); - dst_module_def(module, "gensym", dst_wrap_cfunction(dst_stl_gensym)); - dst_module_def(module, "get", dst_wrap_cfunction(dst_stl_get)); - dst_module_def(module, "put", dst_wrap_cfunction(dst_stl_put)); - dst_module_def(module, "length", dst_wrap_cfunction(dst_stl_length)); - dst_module_def(module, "gccollect", dst_wrap_cfunction(dst_stl_gccollect)); - dst_module_def(module, "type", dst_wrap_cfunction(dst_stl_type)); - dst_module_def(module, "next", dst_wrap_cfunction(dst_stl_next)); - dst_module_def(module, "hash", dst_wrap_cfunction(dst_stl_hash)); - dst_module_def(module, "exit", dst_wrap_cfunction(dst_stl_exit)); + dst_env_def(env, "native", dst_wrap_cfunction(dst_load_native)); + dst_env_def(env, "print", dst_wrap_cfunction(dst_stl_print)); + dst_env_def(env, "describe", dst_wrap_cfunction(dst_stl_describe)); + dst_env_def(env, "string", dst_wrap_cfunction(dst_stl_string)); + dst_env_def(env, "buffer-to-string", dst_wrap_cfunction(dst_stl_buffer_to_string)); + dst_env_def(env, "table", dst_wrap_cfunction(dst_cfun_table)); + dst_env_def(env, "array", dst_wrap_cfunction(dst_cfun_array)); + dst_env_def(env, "tuple", dst_wrap_cfunction(dst_cfun_tuple)); + dst_env_def(env, "struct", dst_wrap_cfunction(dst_cfun_struct)); + dst_env_def(env, "fiber", dst_wrap_cfunction(dst_stl_fiber)); + dst_env_def(env, "status", dst_wrap_cfunction(dst_stl_status)); + dst_env_def(env, "buffer", dst_wrap_cfunction(dst_stl_buffer)); + dst_env_def(env, "gensym", dst_wrap_cfunction(dst_stl_gensym)); + dst_env_def(env, "get", dst_wrap_cfunction(dst_stl_get)); + dst_env_def(env, "put", dst_wrap_cfunction(dst_stl_put)); + dst_env_def(env, "length", dst_wrap_cfunction(dst_stl_length)); + dst_env_def(env, "gccollect", dst_wrap_cfunction(dst_stl_gccollect)); + dst_env_def(env, "type", dst_wrap_cfunction(dst_stl_type)); + dst_env_def(env, "next", dst_wrap_cfunction(dst_stl_next)); + dst_env_def(env, "hash", dst_wrap_cfunction(dst_stl_hash)); + dst_env_def(env, "exit", dst_wrap_cfunction(dst_stl_exit)); - dst_module_def(module, "parse", dst_wrap_cfunction(dst_parse_cfun)); - dst_module_def(module, "compile", dst_wrap_cfunction(dst_compile_cfun)); - dst_module_def(module, "asm", dst_wrap_cfunction(dst_asm_cfun)); - dst_module_def(module, "disasm", dst_wrap_cfunction(dst_disasm_cfun)); + dst_env_def(env, "compile", dst_wrap_cfunction(dst_compile_cfun)); + dst_env_def(env, "asm", dst_wrap_cfunction(dst_asm_cfun)); + dst_env_def(env, "disasm", dst_wrap_cfunction(dst_disasm_cfun)); /* Allow references to the environment */ - dst_module_def(module, "_env", ret); + dst_env_def(env, "_env", ret); - /*Load auxiliary modules */ - dst_io_init(args); - dst_math_init(args); + /*Load auxiliary envs */ + { + DstArgs args; + args.n = 1; + args.v = &ret; + args.ret = &ret; + dst_lib_io(args); + dst_lib_math(args); + dst_lib_array(args); + dst_lib_buffer(args); + dst_lib_parse(args); + } - return ret; + return env; } diff --git a/core/string.c b/core/string.c index 6d943a2a..3eccf143 100644 --- a/core/string.c +++ b/core/string.c @@ -217,6 +217,7 @@ static int32_t dst_escape_string_length(const uint8_t *str, int32_t slen) { case '\n': case '\r': case '\0': + case '\\': len += 2; break; default: @@ -249,6 +250,10 @@ static void dst_escape_string_impl(uint8_t *buf, const uint8_t *str, int32_t len buf[j++] = '\\'; buf[j++] = '0'; break; + case '\\': + buf[j++] = '\\'; + buf[j++] = '\\'; + break; default: buf[j++] = c; break; diff --git a/core/util.c b/core/util.c index d2a52247..a58e7b24 100644 --- a/core/util.c +++ b/core/util.c @@ -108,23 +108,36 @@ int dst_cstrcmp(const uint8_t *str, const char *other) { } /* Add a module definition */ -void dst_module_def(DstTable *module, const char *name, Dst val) { +void dst_env_def(DstTable *env, const char *name, Dst val) { DstTable *subt = dst_table(1); dst_table_put(subt, dst_csymbolv("value"), val); - dst_table_put(module, dst_csymbolv(name), dst_wrap_table(subt)); + dst_table_put(env, dst_csymbolv(name), dst_wrap_table(subt)); } -/* Add a module var */ -void dst_module_var(DstTable *module, const char *name, Dst val) { +/* Add a var to the environment */ +void dst_env_var(DstTable *env, const char *name, Dst val) { DstArray *array = dst_array(1); DstTable *subt = dst_table(1); dst_array_push(array, val); dst_table_put(subt, dst_csymbolv("ref"), dst_wrap_array(array)); - dst_table_put(module, dst_csymbolv(name), dst_wrap_table(subt)); + dst_table_put(env, dst_csymbolv(name), dst_wrap_table(subt)); +} + +/* Resolve a symbol in the environment. Undefined symbols will + * resolve to nil */ +Dst dst_env_resolve(DstTable *env, const char *name) { + Dst ref; + Dst entry = dst_table_get(env, dst_csymbolv(name)); + if (dst_checktype(entry, DST_NIL)) return dst_wrap_nil(); + ref = dst_get(entry, dst_csymbolv("ref")); + if (dst_checktype(ref, DST_ARRAY)) { + return dst_getindex(ref, 0); + } + return dst_get(entry, dst_csymbolv("value")); } /* Get module from the arguments passed to library */ -DstTable *dst_get_module(DstArgs args) { +DstTable *dst_env_arg(DstArgs args) { DstTable *module; if (args.n >= 1 && dst_checktype(args.v[0], DST_TABLE)) { module = dst_unwrap_table(args.v[0]); diff --git a/core/util.h b/core/util.h index 4bc51690..cdd60be2 100644 --- a/core/util.h +++ b/core/util.h @@ -61,6 +61,7 @@ const void *dst_strbinsearch( #define dst_v_count(v) (((v) != NULL) ? dst_v__cnt(v) : 0) #define dst_v_add(v, n) (dst_v__maybegrow(v, n), dst_v_cnt(v) += (n), &(v)[dst_v__cnt(v) - (n)]) #define dst_v_last(v) ((v)[dst_v__cnt(v) - 1]) +#define dst_v_empty(v) (((v) != NULL) ? (dst_v__cnt(v) = 0) : 0) #define dst_v_copy(v) (dst_v_copymem((v), sizeof(*(v)))) #define dst_v_flatten(v) (dst_v_flattenmem((v), sizeof(*(v)))) diff --git a/dsttest/suite0.dst b/dsttest/suite0.dst index beaa03b9..c23a4958 100644 --- a/dsttest/suite0.dst +++ b/dsttest/suite0.dst @@ -195,7 +195,7 @@ # Merge sort -# Impertiave merge sort merge +# Imperative merge sort merge (def merge (fn [xs ys] (def ret []) (def xlen (length xs)) @@ -207,17 +207,17 @@ (def xi (get xs i)) (def yj (get ys j)) (if (< xi yj) - (do (push ret xi) (varset! i (+ i 1))) - (do (push ret yj) (varset! j (+ j 1))))) + (do (array-push ret xi) (varset! i (+ i 1))) + (do (array-push ret yj) (varset! j (+ j 1))))) # Push rest of xs (while (< i xlen) (def xi (get xs i)) - (push ret xi) + (array-push ret xi) (varset! i (+ i 1))) # Push rest of ys (while (< j ylen) (def yj (get ys j)) - (push ret yj) + (array-push ret yj) (varset! j (+ j 1))) ret)) diff --git a/include/dst/dst.h b/include/dst/dst.h index 37dff91b..157a382a 100644 --- a/include/dst/dst.h +++ b/include/dst/dst.h @@ -139,14 +139,6 @@ void dst_fiber_funcframe_tail(DstFiber *fiber, DstFunction *func); void dst_fiber_cframe(DstFiber *fiber); void dst_fiber_popframe(DstFiber *fiber); -/* Assembly */ -DstAssembleResult dst_asm(DstAssembleOptions opts); -DstFunction *dst_asm_func(DstAssembleResult result); -Dst dst_disasm(DstFuncDef *def); -Dst dst_asm_decode_instruction(uint32_t instr); -int dst_asm_cfun(DstArgs args); -int dst_disasm_cfun(DstArgs args); - /* Treat similar types through uniform interfaces for iteration */ int dst_seq_view(Dst seq, const Dst **data, int32_t *len); int dst_chararray_view(Dst str, const uint8_t **data, int32_t *len); @@ -163,6 +155,17 @@ int dst_equals(Dst x, Dst y); int32_t dst_hash(Dst x); int dst_compare(Dst x, Dst y); +/* GC */ +void dst_mark(Dst x); +void dst_sweep(); +void dst_collect(); +void dst_clear_memory(); +void dst_gcroot(Dst root); +int dst_gcunroot(Dst root); +int dst_gcunrootall(Dst root); +#define dst_maybe_collect() do {\ + if (dst_vm_next_collection >= dst_vm_gc_interval) dst_collect(); } while (0) + /* Data structure functions */ Dst dst_get(Dst ds, Dst key); void dst_put(Dst ds, Dst key, Dst value); @@ -178,11 +181,6 @@ DstAst *dst_ast_node(Dst x); Dst dst_ast_unwrap1(Dst x); Dst dst_ast_unwrap(Dst x); -/* Parsing */ -DstParseResult dst_parse(const uint8_t *src, int32_t len, int flags); -DstParseResult dst_parsec(const char *src, int flags); -int dst_parse_cfun(DstArgs args); - /* Native */ DstCFunction dst_native(const char *name, const uint8_t **error); int dst_load_native(DstArgs args); @@ -198,40 +196,89 @@ int32_t dst_scan_integer(const uint8_t *str, int32_t len, int *err); double dst_scan_real(const uint8_t *str, int32_t len, int *err); /* Module helpers */ -DstTable *dst_get_module(DstArgs args); -void dst_module_def(DstTable *module, const char *name, Dst val); -void dst_module_var(DstTable *module, const char *name, Dst val); - -/* Context functions */ -void dst_context_init(DstContext *c, Dst env); -void dst_context_deinit(DstContext *c); -void dst_context_repl(DstContext *c, Dst env); -int dst_context_run(DstContext *c); +void dst_env_def(DstTable *env, const char *name, Dst val); +void dst_env_var(DstTable *env, const char *name, Dst val); +Dst dst_env_resolve(DstTable *env, const char *name); +DstTable *dst_env_arg(DstArgs args); /* C Function helpers */ #define dst_throw(a, e) (*((a).ret) = dst_cstringv(e), 1) #define dst_throwv(a, v) (*((a).ret) = (v), 1) #define dst_return(a, v) (*((a).ret) = (v), 0) +/* Parsing */ +typedef enum DstParserStatus DstParserStatus; +typedef struct DstParseState DstParseState; +typedef struct DstParser DstParser; +enum DstParserStatus { + DST_PARSE_ROOT, + DST_PARSE_ERROR, + DST_PARSE_FULL, + DST_PARSE_PENDING +}; +struct DstParser { + Dst* argstack; + DstParseState *states; + uint8_t *buf; + const char *error; + size_t index; + int lookback; + int flags; +}; +#define DST_PARSEFLAG_SOURCEMAP 1 +void dst_parser_init(DstParser *parser, int flags); +void dst_parser_deinit(DstParser *parser); +int dst_parser_consume(DstParser *parser, uint8_t c); +DstParserStatus dst_parser_status(DstParser *parser); +Dst dst_parser_produce(DstParser *parser); +const char *dst_parser_error(DstParser *parser); +int dst_parse_cfun(DstArgs args); + /* Compile */ -DstCompileResult dst_compile(DstCompileOptions opts); +typedef enum DstCompileStatus DstCompileStatus; +typedef struct DstCompileOptions DstCompileOptions; +typedef struct DstCompileResult DstCompileResult; +enum DstCompileStatus { + DST_COMPILE_OK, + DST_COMPILE_ERROR +}; +struct DstCompileResult { + DstCompileStatus status; + DstFuncDef *funcdef; + const uint8_t *error; + int32_t error_start; + int32_t error_end; +}; +DstCompileResult dst_compile(Dst source, DstTable *env, int flags); DstFunction *dst_compile_func(DstCompileResult result); int dst_compile_cfun(DstArgs args); -/* STL */ -Dst dst_stl_env(); -int dst_io_init(DstArgs args); -int dst_math_init(DstArgs args); +/* Assembly */ +typedef enum DstAssembleStatus DstAssembleStatus; +typedef struct DstAssembleResult DstAssembleResult; +typedef struct DstAssembleOptions DstAssembleOptions; +enum DstAssembleStatus { + DST_ASSEMBLE_OK, + DST_ASSEMBLE_ERROR +}; +struct DstAssembleResult { + DstFuncDef *funcdef; + const uint8_t *error; + DstAssembleStatus status; +}; +DstAssembleResult dst_asm(Dst source, int flags); +DstFunction *dst_asm_func(DstAssembleResult result); +Dst dst_disasm(DstFuncDef *def); +Dst dst_asm_decode_instruction(uint32_t instr); +int dst_asm_cfun(DstArgs args); +int dst_disasm_cfun(DstArgs args); -/* GC */ -void dst_mark(Dst x); -void dst_sweep(); -void dst_collect(); -void dst_clear_memory(); -void dst_gcroot(Dst root); -int dst_gcunroot(Dst root); -int dst_gcunrootall(Dst root); -#define dst_maybe_collect() do {\ - if (dst_vm_next_collection >= dst_vm_gc_interval) dst_collect(); } while (0) +/* STL */ +DstTable *dst_stl_env(); +int dst_lib_io(DstArgs args); +int dst_lib_math(DstArgs args); +int dst_lib_array(DstArgs args); +int dst_lib_buffer(DstArgs args); +int dst_lib_parse(DstArgs args); #endif /* DST_H_defined */ diff --git a/include/dst/dstconfig.h b/include/dst/dstconfig.h index 88e4e745..64dbc30a 100644 --- a/include/dst/dstconfig.h +++ b/include/dst/dstconfig.h @@ -24,7 +24,6 @@ #define DST_CONFIG_H_defined #include -#include "dst.h" /* * Detect OS and endianess. diff --git a/include/dst/dsttypes.h b/include/dst/dsttypes.h index 62fbeae1..888ce116 100644 --- a/include/dst/dsttypes.h +++ b/include/dst/dsttypes.h @@ -23,7 +23,6 @@ #ifndef DST_TYPES_H_defined #define DST_TYPES_H_defined -#include #include "dstconfig.h" #ifdef DST_NANBOX @@ -48,18 +47,8 @@ typedef struct DstStackFrame DstStackFrame; typedef struct DstAbstractType DstAbstractType; typedef struct DstArgs DstArgs; typedef struct DstAst DstAst; -typedef struct DstContext DstContext; typedef int (*DstCFunction)(DstArgs args); -typedef enum DstAssembleStatus DstAssembleStatus; -typedef struct DstAssembleResult DstAssembleResult; -typedef struct DstAssembleOptions DstAssembleOptions; -typedef enum DstCompileStatus DstCompileStatus; -typedef struct DstCompileOptions DstCompileOptions; -typedef struct DstCompileResult DstCompileResult; -typedef struct DstParseResult DstParseResult; -typedef enum DstParseStatus DstParseStatus; - /* Basic types for all Dst Values */ typedef enum DstType { DST_NIL, @@ -424,42 +413,7 @@ struct DstAbstractHeader { size_t size; }; -/* Assemble structs */ -enum DstAssembleStatus { - DST_ASSEMBLE_OK, - DST_ASSEMBLE_ERROR -}; - -struct DstAssembleOptions { - Dst source; - uint32_t flags; -}; - -struct DstAssembleResult { - DstFuncDef *funcdef; - const uint8_t *error; - DstAssembleStatus status; -}; - /* Compile structs */ -enum DstCompileStatus { - DST_COMPILE_OK, - DST_COMPILE_ERROR -}; - -struct DstCompileResult { - DstCompileStatus status; - DstFuncDef *funcdef; - const uint8_t *error; - int32_t error_start; - int32_t error_end; -}; - -struct DstCompileOptions { - uint32_t flags; - Dst source; - Dst env; -}; /* ASTs are simple wrappers around values. They contain information about sourcemapping * and other meta data. Possibly types? They are used mainly during compilation and parsing */ @@ -470,41 +424,4 @@ struct DstAst { int flags; }; -#define DST_PARSEFLAG_SOURCEMAP 1 - -/* Parse structs */ -enum DstParseStatus { - DST_PARSE_OK, - DST_PARSE_ERROR, - DST_PARSE_UNEXPECTED_EOS, - DST_PARSE_NODATA -}; - -struct DstParseResult { - Dst value; - const uint8_t *error; - int32_t bytes_read; - DstParseStatus status; -}; - -typedef enum { - DST_CONTEXT_ERROR_PARSE, - DST_CONTEXT_ERROR_COMPILE, - DST_CONTEXT_ERROR_RUNTIME -} DstContextErrorType; - -/* Evaluation context. Encapsulates parsing and compiling for easier integration - * with client programs. */ -struct DstContext { - Dst env; - DstBuffer buffer; - size_t flushed_bytes; - void *user; - - void (*read_chunk)(DstContext *self); - void (*on_error)(DstContext *self, DstContextErrorType type, Dst err, size_t start, size_t end); - void (*on_value)(DstContext *self, Dst value); - void (*deinit)(DstContext *self); -}; - #endif /* DST_TYPES_H_defined */