From 5d5d88c5adeecfa180de1b73ae47c23525d7a4fe Mon Sep 17 00:00:00 2001 From: bakpakin Date: Wed, 17 Jan 2018 09:58:32 -0500 Subject: [PATCH] Add some more functions to stl. Fix integer hashing (doh). --- client/main.c | 77 ----------------------------------------------- core/context.c | 73 ++++++++++++++++++++++++++------------------ core/parse.c | 5 ++- core/stl.c | 32 ++++++++++++++++++++ core/struct.c | 2 +- core/table.c | 2 +- core/value.c | 8 ++++- include/dst/dst.h | 4 +++ 8 files changed, 92 insertions(+), 111 deletions(-) diff --git a/client/main.c b/client/main.c index 0e57a4b8..181c93d1 100644 --- a/client/main.c +++ b/client/main.c @@ -65,83 +65,6 @@ static const uint8_t *loadsource(const char *fpath, int32_t *len) { return NULL; } -/* Shift bytes in buffer down */ -static void bshift(DstBuffer *buf, int32_t delta) { - buf->count -= delta; - if (delta) { - memmove(buf->data, buf->data + delta, buf->count); - } -} - -/* Wrap a value to add to the env */ -static void set_underscore(Dst val) { - DstTable *t = dst_table(0); - dst_table_put(t, dst_csymbolv("value"), val); - dst_put(env, dst_csymbolv("_"), dst_wrap_table(t)); -} - -/* simple repl */ -static int repl() { - DstBuffer b; - dst_buffer_init(&b, 256); - set_underscore(dst_wrap_nil()); - for (;;) { - int c; - DstParseResult res; - DstCompileResult cres; - DstCompileOptions opts; - res = dst_parse(b.data, b.count); - switch (res.status) { - case DST_PARSE_NODATA: - b.count = 0; - case DST_PARSE_UNEXPECTED_EOS: - if (b.count == 0) - printf("> "); - else - printf(">> "); - for (;;) { - c = fgetc(stdin); - if (c == EOF) { - printf("\n"); - goto done; - } - dst_buffer_push_u8(&b, c); - if (c == '\n') break; - } - break; - case DST_PARSE_ERROR: - dst_puts(dst_formatc("syntax error: %S\n", res.error)); - b.count = 0; - 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_puts(dst_formatc("asm: %v\n", dst_disasm(cres.funcdef)));*/ - DstFunction *f = dst_compile_func(cres); - Dst ret; - if (dst_run(dst_wrap_function(f), &ret)) { - dst_puts(dst_formatc("runtime error: %S\n", dst_to_string(ret))); - } else { - dst_puts(dst_formatc("%v\n", ret)); - set_underscore(ret); - } - } else { - dst_puts(dst_formatc("compile error: %S\n", cres.error)); - } - bshift(&b, res.bytes_read); - } - break; - } - } - done: - dst_buffer_deinit(&b); - return 0; -} - /* Run file */ static void runfile(const uint8_t *src, int32_t len) { DstCompileOptions opts; diff --git a/core/context.c b/core/context.c index 98de628a..e25b67f2 100644 --- a/core/context.c +++ b/core/context.c @@ -73,6 +73,19 @@ static void replerror(DstContext *c, DstContextErrorType type, Dst err, size_t s dst_puts(dst_formatc("%s error: %v\n", errtype, err)); } +void dst_context_init(DstContext *c, Dst env) { + dst_buffer_init(&c->buffer, 1024); + c->env = env; + dst_gcroot(env); + c->flushed_bytes = 0; +} + +void dst_context_deinit(DstContext *c) { + dst_buffer_deinit(&c->buffer); + if (c->deinit) c->deinit(c); + dst_gcunroot(c->env); +} + void dst_context_repl(DstContext *c, Dst env) { dst_buffer_init(&c->buffer, 1024); c->env = env; @@ -81,7 +94,6 @@ void dst_context_repl(DstContext *c, Dst env) { c->user = NULL; if (dst_checktype(c->env, DST_TABLE)) dst_module_def(dst_unwrap_table(c->env), "_", dst_wrap_nil()); - c->read_chunk = replread; c->on_error = replerror; c->on_value = replonvalue; @@ -103,6 +115,22 @@ static void bshift(DstContext *c, int32_t delta) { } } +/* Do something on an error. Return flags to or with current flags. */ +static int doerror( + DstContext *c, + DstContextErrorType type, + Dst err, + int32_t bstart, + int32_t bend) { + if (c->on_error) { + c->on_error(c, type, + err, + c->flushed_bytes + bstart, + c->flushed_bytes + bend); + } + return 1 << type; +} + /* Start a context */ int dst_context_run(DstContext *c) { int done = 0; @@ -121,24 +149,18 @@ int dst_context_run(DstContext *c) { /* If the last chunk was empty, finish */ if (c->buffer.count == countbefore) { done = 1; - flags |= 1 << DST_CONTEXT_ERROR_PARSE; - if (c->on_error) { - c->on_error(c, DST_CONTEXT_ERROR_PARSE, - dst_wrap_string(res.error), - c->flushed_bytes + res.bytes_read, - c->flushed_bytes + res.bytes_read); - } + flags |= doerror(c, DST_CONTEXT_ERROR_PARSE, + dst_cstringv("unexpected end of source"), + res.bytes_read, + res.bytes_read); } break; } case DST_PARSE_ERROR: - if (c->on_error) { - flags |= 1 << DST_CONTEXT_ERROR_PARSE; - c->on_error(c, DST_CONTEXT_ERROR_PARSE, - dst_wrap_string(res.error), - c->flushed_bytes + res.bytes_read, - c->flushed_bytes + res.bytes_read); - } + 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: @@ -151,33 +173,24 @@ int dst_context_run(DstContext *c) { DstFunction *f = dst_compile_func(cres); Dst ret; if (dst_run(dst_wrap_function(f), &ret)) { - /* Get location from stacktrace */ - if (c->on_error) { - flags |= 1 << DST_CONTEXT_ERROR_RUNTIME; - c->on_error(c, DST_CONTEXT_ERROR_RUNTIME, ret, -1, -1); - } + /* 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 { - if (c->on_error) { - flags |= 1 << DST_CONTEXT_ERROR_COMPILE; - c->on_error(c, DST_CONTEXT_ERROR_COMPILE, - dst_wrap_string(cres.error), - c->flushed_bytes + cres.error_start, - c->flushed_bytes + cres.error_end); - } + flags |= doerror(c, DST_CONTEXT_ERROR_COMPILE, + dst_wrap_string(cres.error), + cres.error_start, + cres.error_end); } bshift(c, res.bytes_read); } break; } } - dst_buffer_deinit(&c->buffer); - if (c->deinit) c->deinit(c); - dst_gcunroot(c->env); return flags; } diff --git a/core/parse.c b/core/parse.c index bac5cfa2..740cd389 100644 --- a/core/parse.c +++ b/core/parse.c @@ -211,7 +211,10 @@ static const uint8_t *parse_recur( int ascii = 1; Dst numcheck; const uint8_t *tokenend = src; - if (!is_symbol_char(*src)) goto unexpected_character; + if (!is_symbol_char(*src)) { + src++; + goto unexpected_character; + } while (tokenend < end && is_symbol_char(*tokenend)) { if (*tokenend++ > 127) ascii = 0; } diff --git a/core/stl.c b/core/stl.c index df04c8c9..67061417 100644 --- a/core/stl.c +++ b/core/stl.c @@ -222,6 +222,36 @@ int dst_stl_type(DstArgs args) { } } +int dst_stl_next(DstArgs args) { + Dst ds; + const DstKV *kv; + if (args.n != 2) return dst_throw(args, "expected 2 arguments"); + ds = args.v[0]; + if (dst_checktype(ds, DST_TABLE)) { + DstTable *t = dst_unwrap_table(ds); + kv = dst_checktype(args.v[1], DST_NIL) + ? t->data + : dst_table_find(t, args.v[1]); + } else if (dst_checktype(ds, DST_STRUCT)) { + const DstKV *st = dst_unwrap_struct(ds); + kv = dst_checktype(args.v[1], DST_NIL) + ? st + : dst_struct_find(st, args.v[1]); + } else { + return dst_throw(args, "expected table/struct"); + } + kv = dst_next(ds, kv); + if (kv) { + return dst_return(args, kv->key); + } + return dst_return(args, dst_wrap_nil()); +} + +int dst_stl_hash(DstArgs args) { + if (args.n != 1) return dst_throw(args, "expected 1 argument"); + return dst_return(args, dst_wrap_integer(dst_hash(args.v[0]))); +} + Dst dst_stl_env() { Dst ret; DstArgs args; @@ -250,6 +280,8 @@ Dst dst_stl_env() { 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_module_def(module, "parse", dst_wrap_cfunction(dst_parse_cfun)); diff --git a/core/struct.c b/core/struct.c index eb192738..35e442e6 100644 --- a/core/struct.c +++ b/core/struct.c @@ -44,7 +44,7 @@ DstKV *dst_struct_begin(int32_t count) { } /* Find an item in a struct */ -static const DstKV *dst_struct_find(const DstKV *st, Dst key) { +const DstKV *dst_struct_find(const DstKV *st, Dst key) { int32_t cap = dst_struct_capacity(st); int32_t index = dst_struct_maphash(cap, dst_hash(key)); int32_t i; diff --git a/core/table.c b/core/table.c index c8004208..a3118eb6 100644 --- a/core/table.c +++ b/core/table.c @@ -59,7 +59,7 @@ DstTable *dst_table(int32_t capacity) { /* Find the bucket that contains the given key. Will also return * bucket where key should go if not in the table. */ -static DstKV *dst_table_find(DstTable *t, Dst key) { +DstKV *dst_table_find(DstTable *t, Dst key) { int32_t index = dst_table_maphash(t->capacity, dst_hash(key)); int32_t i; DstKV *first_bucket = NULL; diff --git a/core/value.c b/core/value.c index 9c69466f..da80c8c8 100644 --- a/core/value.c +++ b/core/value.c @@ -87,14 +87,20 @@ int32_t dst_hash(Dst x) { break; case DST_INTEGER: hash = dst_unwrap_integer(x); + break; default: + /* TODO - test performance with different hash functions */ if (sizeof(double) == sizeof(void *)) { /* Assuming 8 byte pointer */ uint64_t i = dst_u64(x); - hash = (int32_t)(i >> 32) ^ (int32_t)(i & 0xFFFFFFFF); + hash = (int32_t)(i & 0xFFFFFFFF); + /* Get a bit more entropy by shifting the low bits out */ + hash >>= 3; + hash ^= (int32_t) (i >> 32); } else { /* Assuming 4 byte pointer (or smaller) */ hash = (int32_t) (dst_unwrap_pointer(x) - NULL); + hash >>= 2; } break; } diff --git a/include/dst/dst.h b/include/dst/dst.h index 13119363..b8c4a696 100644 --- a/include/dst/dst.h +++ b/include/dst/dst.h @@ -109,6 +109,7 @@ const DstKV *dst_struct_next(const DstKV *st, const DstKV *kv); DstTable *dst_struct_to_table(const DstKV *st); int dst_struct_equal(const DstKV *lhs, const DstKV *rhs); int dst_struct_compare(const DstKV *lhs, const DstKV *rhs); +const DstKV *dst_struct_find(const DstKV *st, Dst key); /* Table functions */ DstTable *dst_table(int32_t capacity); @@ -121,6 +122,7 @@ const DstKV *dst_table_next(DstTable *t, const DstKV *kv); const DstKV *dst_table_to_struct(DstTable *t); void dst_table_merge_table(DstTable *table, DstTable *other); void dst_table_merge_struct(DstTable *table, const DstKV *other); +DstKV *dst_table_find(DstTable *t, Dst key); /* Fiber */ DstFiber *dst_fiber(int32_t capacity); @@ -201,6 +203,8 @@ 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);