Add some more functions to stl. Fix integer hashing (doh).

This commit is contained in:
bakpakin 2018-01-17 09:58:32 -05:00
parent d373d38aee
commit 5d5d88c5ad
8 changed files with 92 additions and 111 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);