mirror of
https://github.com/janet-lang/janet
synced 2025-01-22 13:16:52 +00:00
Add some more functions to stl. Fix integer hashing (doh).
This commit is contained in:
parent
d373d38aee
commit
5d5d88c5ad
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
32
core/stl.c
32
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));
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user