diff --git a/client/main.c b/client/main.c index e9418f75..a1da6fb5 100644 --- a/client/main.c +++ b/client/main.c @@ -103,9 +103,6 @@ static int debug_run(Gst *vm, FILE *in) { while (p.status != GST_PARSER_ERROR && p.status != GST_PARSER_FULL) { if (*reader == '\0') { if (!fgets(buffer, sizeof(buffer), in)) { - /* Add possible end of line */ - if (p.status == GST_PARSER_PENDING) - gst_parse_cstring(&p, "\n"); /* Check that parser is complete */ if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) { printf("Unexpected end of source\n"); @@ -144,7 +141,6 @@ static int debug_repl(Gst *vm, uint64_t flags) { /* Init parser */ gst_parser(&p, vm); while (p.status != GST_PARSER_ERROR && p.status != GST_PARSER_FULL) { - gst_parse_cstring(&p, "\n"); if (p.status == GST_PARSER_ERROR || p.status == GST_PARSER_FULL) break; if (!reader || *reader == '\0') { diff --git a/core/compile.c b/core/compile.c index a8b9a017..a43b6918 100644 --- a/core/compile.c +++ b/core/compile.c @@ -126,14 +126,6 @@ static void c_error1(GstCompiler *c, GstValue e) { longjmp(c->onError, 1); } -/* Quote something */ -static GstValue quote(Gst *vm, GstValue x) { - GstValue *q = gst_tuple_begin(vm, 2); - q[0] = gst_string_cv(vm, "quote"); - q[1] = x; /* lit contains the var container of the environment */ - return gst_wrap_tuple(gst_tuple_end(vm, q)); -} - /* Push a new scope in the compiler and return * a pointer to it for configuration. There is * more configuration that needs to be done if @@ -383,8 +375,8 @@ static uint16_t compiler_add_literal(GstCompiler *c, GstScope *scope, GstValue x static uint16_t compiler_declare_symbol(GstCompiler *c, GstScope *scope, GstValue sym, uint16_t flags) { GstValue x; uint16_t target; - if (sym.type != GST_STRING) - c_error(c, "expected string"); + if (sym.type != GST_SYMBOL) + c_error(c, "expected symbol"); target = compiler_get_local(c, scope); x.type = GST_INTEGER; x.data.integer = target + (flags << 16); @@ -415,7 +407,7 @@ static int symbol_resolve(GstCompiler *c, GstValue x, uint16_t *level, uint16_t GstTable *metas = gst_env_meta(c->vm, c->env); GstValue maybeMeta = gst_table_get(metas, x); if (maybeMeta.type == GST_TABLE) { - GstValue isMutable = gst_table_get(maybeMeta.data.table, gst_string_cv(c->vm, "mutable")); + GstValue isMutable = gst_table_get(maybeMeta.data.table, gst_string_cvs(c->vm, "mutable")); if (gst_truthy(isMutable)) { if (flags) *flags = GST_LOCAL_FLAG_MUTABLE; *out = check; @@ -509,6 +501,14 @@ static Slot compile_literal(GstCompiler *c, FormOptions opts, GstValue x) { return ret; } +/* Quote a value */ +static GstValue quote(Gst *vm, GstValue x) { + GstValue *tuple = gst_tuple_begin(vm, 2); + tuple[0] = gst_string_cvs(vm, "quote"); + tuple[1] = x; + return gst_wrap_tuple(gst_tuple_end(vm, tuple)); +} + /* Compile a symbol. Resolves any kind of symbol. */ static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) { GstValue lit = gst_wrap_nil(); @@ -529,7 +529,7 @@ static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) { const GstValue *tup; Gst *vm= c->vm; GstValue *t = gst_tuple_begin(vm, 3); - t[0] = gst_string_cv(vm, "get"); /* Todo - replace with actual cfunc or bytecode */ + t[0] = gst_string_cvs(vm, "get"); /* Todo - replace with actual cfunc or bytecode */ t[1] = quote(vm, lit); t[2] = gst_wrap_integer(0); tup = gst_tuple_end(vm, t); @@ -608,8 +608,8 @@ static Slot compile_assign(GstCompiler *c, FormOptions opts, GstValue left, GstV const GstValue *tup; Gst *vm= c->vm; GstValue *t = gst_tuple_begin(vm, 4); - t[0] = gst_string_cv(vm, "set!"); /* Todo - replace with ref ro actual cfunc */ - t[1] = quote(vm, lit); + t[0] = gst_string_cvs(vm, "set!"); /* Todo - replace with ref ro actual cfunc */ + t[1] = quote(c->vm, lit); t[2] = gst_wrap_integer(0); t[3] = right; tup = gst_tuple_end(vm, t); @@ -631,7 +631,7 @@ static Slot compile_assign(GstCompiler *c, FormOptions opts, GstValue left, GstV static Slot compile_varset(GstCompiler *c, FormOptions opts, const GstValue *form) { if (gst_tuple_length(form) != 3) c_error(c, "expected 2 arguments to varset"); - if (GST_STRING != form[1].type) + if (GST_SYMBOL != form[1].type) c_error(c, "expected symbol as first argument"); return compile_assign(c, opts, form[1], form[2]); } @@ -641,11 +641,9 @@ static Slot compile_global_var(GstCompiler *c, FormOptions opts, const GstValue const GstValue *tup; Gst *vm= c->vm; GstValue *t = gst_tuple_begin(vm, 3); - GstValue *q = gst_tuple_begin(vm, 2); - q[0] = gst_string_cv(vm, "quote"); - q[1] = form[1]; - t[0] = gst_string_cv(vm, "global-var"); /* Todo - replace with ref ro actual cfunc */ - t[1] = gst_wrap_tuple(gst_tuple_end(vm, q)); + t[0] = gst_string_cvs(vm, "global-var"); /* Todo - replace with ref ro actual cfunc */ + t[1] = form[1]; + t[1].type = GST_STRING; t[2] = form[2]; tup = gst_tuple_end(vm, t); return compile_value(c, opts, gst_wrap_tuple(tup)); @@ -656,11 +654,9 @@ static Slot compile_global_def(GstCompiler *c, FormOptions opts, const GstValue const GstValue *tup; Gst *vm= c->vm; GstValue *t = gst_tuple_begin(vm, 3); - GstValue *q = gst_tuple_begin(vm, 2); - q[0] = gst_string_cv(vm, "quote"); - q[1] = form[1]; - t[0] = gst_string_cv(vm, "global-def"); /* Todo - replace with ref ro actual cfunc */ - t[1] = gst_wrap_tuple(gst_tuple_end(vm, q)); + t[0] = gst_string_cvs(vm, "global-def"); /* Todo - replace with ref ro actual cfunc */ + t[1] = form[1]; + t[1].type = GST_STRING; t[2] = form[2]; tup = gst_tuple_end(vm, t); return compile_value(c, opts, gst_wrap_tuple(tup)); @@ -671,7 +667,7 @@ static Slot compile_def(GstCompiler *c, FormOptions opts, const GstValue *form) GstScope *scope = c->tail; if (gst_tuple_length(form) != 3) c_error(c, "expected 2 arguments to def"); - if (GST_STRING != form[1].type) + if (GST_SYMBOL != form[1].type) c_error(c, "expected symbol as first argument"); if (scope->parent) { FormOptions subOpts; @@ -692,7 +688,7 @@ static Slot compile_var(GstCompiler *c, FormOptions opts, const GstValue *form) GstScope *scope = c->tail; if (gst_tuple_length(form) != 3) c_error(c, "expected 2 arguments to var"); - if (GST_STRING != form[1].type) + if (GST_SYMBOL != form[1].type) c_error(c, "expected symbol as first argument"); if (scope->parent) { FormOptions subOpts; @@ -798,8 +794,8 @@ static Slot compile_function(GstCompiler *c, FormOptions opts, const GstValue *f arity = params->count; for (i = 0; i < params->count; ++i) { GstValue param = params->data[i]; - if (param.type != GST_STRING) - c_error(c, "function parameters should be strings"); + if (param.type != GST_SYMBOL) + c_error(c, "function parameters should be symbols"); /* Check for varargs */ if (equal_cstr(param.data.string, "&")) { if (i != params->count - 1) { @@ -1057,7 +1053,7 @@ typedef Slot (*SpecialFormHelper) (GstCompiler *c, FormOptions opts, const GstVa /* Dispatch to a special form */ static SpecialFormHelper get_special(const GstValue *form) { const uint8_t *name; - if (gst_tuple_length(form) < 1 || form[0].type != GST_STRING) + if (gst_tuple_length(form) < 1 || form[0].type != GST_SYMBOL) return NULL; name = form[0].data.string; /* If we have a symbol with a zero length name, we have other @@ -1277,7 +1273,7 @@ static Slot compile_value(GstCompiler *c, FormOptions opts, GstValue x) { case GST_INTEGER: ret = compile_nonref_type(c, opts, x); break; - case GST_STRING: + case GST_SYMBOL: ret = compile_symbol(c, opts, x); break; case GST_TUPLE: diff --git a/core/gc.c b/core/gc.c index 6c52c7ae..7051db49 100644 --- a/core/gc.c +++ b/core/gc.c @@ -97,6 +97,7 @@ void gst_mark(Gst *vm, GstValueUnion x, GstType type) { break; case GST_STRING: + case GST_SYMBOL: gc_header(gst_string_raw(x.string))->color = vm->black; break; diff --git a/core/ids.c b/core/ids.c index 0ee4cf52..92ea1677 100644 --- a/core/ids.c +++ b/core/ids.c @@ -437,6 +437,16 @@ GstValue gst_string_cv(Gst *vm, const char *str) { return ret; } +/* Load a c string and return it as a GstValue. Return the symbol. */ +GstValue gst_string_cvs(Gst *vm, const char *str) { + GstValue ret; + /* Only put strings in cache */ + const uint8_t *data = gst_string_c(vm, str); + ret.type = GST_SYMBOL; + ret.data.string = data; + return ret; +} + /* Compares two strings */ int gst_string_compare(const uint8_t *lhs, const uint8_t *rhs) { uint32_t xlen = gst_string_length(lhs); diff --git a/core/parse.c b/core/parse.c index fb107c64..fee6aaa2 100644 --- a/core/parse.c +++ b/core/parse.c @@ -44,15 +44,15 @@ static GstParseState *parser_pop(GstParser * p) { return p->data + --p->count; } -/* Quote a value */ -static GstValue quote(GstParser *p, GstValue x) { - /* Load a quote form to get the string literal */ - GstValue *tuple; - tuple = gst_tuple_begin(p->vm, 2); - tuple[0] = gst_string_cv(p->vm, "quote"); - tuple[1] = x; - return gst_wrap_tuple(gst_tuple_end(p->vm, tuple)); -} +// /* Quote a value */ +// static GstValue quote(GstParser *p, GstValue x) { +// /* Load a quote form to get the string literal */ +// GstValue *tuple; +// tuple = gst_tuple_begin(p->vm, 2); +// tuple[0] = gst_string_cv(p->vm, "quote"); +// tuple[1] = x; +// return gst_wrap_tuple(gst_tuple_end(p->vm, tuple)); +// } /* Add a new, empty ParseState to the ParseStack. */ static void parser_push(GstParser *p, ParseType type, uint8_t character) { @@ -239,7 +239,7 @@ static GstValue build_token(GstParser *p, GstBuffer *buf) { p_error(p, "symbols cannot start with digits"); x.type = GST_NIL; } else { - x.type = GST_STRING; + x.type = GST_SYMBOL; x.data.string = gst_buffer_to_string(p->vm, buf); } } @@ -289,7 +289,7 @@ static int string_state(GstParser *p, uint8_t c) { x.type = GST_STRING; x.data.string = gst_buffer_to_string(p->vm, top->buf.string.buffer); parser_pop(p); - parser_append(p, quote(p, x)); + parser_append(p, x); } else { gst_buffer_push(p->vm, top->buf.string.buffer, c); } diff --git a/core/serialize.c b/core/serialize.c index c38d96b0..bb8d4499 100644 --- a/core/serialize.c +++ b/core/serialize.c @@ -51,6 +51,7 @@ * Byte 216: CFunc - [u32 length]*[u8... idstring] * Byte 217: Ref - [u32 id] * Byte 218: Integer - [i64 value] + * Byte 219: Symbol - [u32 length]*[u8... characters] */ /* Error at buffer end */ @@ -173,7 +174,8 @@ static const char *gst_deserialize_impl( break; case 205: /* String */ - ret.type = GST_STRING; + case 219: /* Symbol */ + ret.type = data[-1] == 205 ? GST_STRING : GST_SYMBOL; read_u32(length); deser_datacheck(length); ret.data.string = gst_string_b(vm, data, length); @@ -582,7 +584,8 @@ static const char *gst_serialize_impl( return "unable to serialize type"; case GST_STRING: - write_byte(205); + case GST_SYMBOL: + write_byte(x.type == GST_STRING ? 205 : 219); count = gst_string_length(x.data.string); write_u32(count); for (i = 0; i < count; ++i) { diff --git a/core/stl.c b/core/stl.c index 840d0df2..6f902e4f 100644 --- a/core/stl.c +++ b/core/stl.c @@ -180,6 +180,7 @@ int gst_stl_length(Gst *vm) { default: gst_c_throwc(vm, "cannot get length"); case GST_STRING: + case GST_SYMBOL: ret.data.integer = gst_string_length(x.data.string); break; case GST_ARRAY: @@ -284,6 +285,8 @@ int gst_stl_slice(Gst *vm) { gst_c_return(vm, gst_wrap_array(arr)); } else if (x.type == GST_STRING) { gst_c_return(vm, gst_wrap_string(gst_string_b(vm, x.data.string + from, newlength))); + } else if (x.type == GST_SYMBOL) { + gst_c_return(vm, gst_wrap_symbol(gst_string_b(vm, x.data.string + from, newlength))); } else { /* buffer */ GstBuffer *b = gst_buffer(vm, newlength); gst_memcpy(b->data, x.data.buffer->data, newlength); @@ -315,6 +318,9 @@ int gst_stl_type(Gst *vm) { case GST_STRING: typestr = "string"; break; + case GST_SYMBOL: + typestr = "symbol"; + break; case GST_ARRAY: typestr = "array"; break; @@ -659,7 +665,7 @@ int gst_stl_deserialize(Gst *vm) { const uint8_t *data; const char *err; if (!gst_chararray_view(gst_arg(vm, 0), &data, &len)) - gst_c_throwc(vm, "expected string/buffer"); + gst_c_throwc(vm, "expected string/buffer/symbol"); err = gst_deserialize(vm, data, len, &ret, &data); if (err != NULL) gst_c_throwc(vm, err); @@ -679,8 +685,9 @@ int gst_stl_namespace(Gst *vm) { int gst_stl_namespace_set(Gst *vm) { GstValue name = gst_arg(vm, 0); GstValue check; - if (name.type != GST_STRING) - gst_c_throwc(vm, "expected string"); + if (name.type != GST_STRING || name.type == GST_SYMBOL) + gst_c_throwc(vm, "expected string/symbol"); + name.type = GST_SYMBOL; check = gst_table_get(vm->modules, name); if (check.type == GST_TABLE) { vm->registry = check.data.table; @@ -731,24 +738,28 @@ int gst_stl_funcparent(Gst *vm) { } int gst_stl_def(Gst *vm) { + GstValue key = gst_arg(vm, 0); if (gst_count_args(vm) != 2) { gst_c_throwc(vm, "expected 2 arguments to global-def"); } - if (GST_STRING != gst_arg(vm, 0).type) { - gst_c_throwc(vm, "expected string as first argument"); + if (key.type != GST_STRING && key.type != GST_SYMBOL) { + gst_c_throwc(vm, "expected string/symbol as first argument"); } - gst_env_put(vm, vm->env, gst_arg(vm, 0), gst_arg(vm, 1)); + key.type = GST_SYMBOL; + gst_env_put(vm, vm->env, key, gst_arg(vm, 1)); gst_c_return(vm, gst_arg(vm, 1)); } int gst_stl_var(Gst *vm) { + GstValue key = gst_arg(vm, 0); if (gst_count_args(vm) != 2) { gst_c_throwc(vm, "expected 2 arguments to global-var"); } - if (GST_STRING != gst_arg(vm, 0).type) { + if (key.type != GST_STRING && key.type != GST_SYMBOL) { gst_c_throwc(vm, "expected string as first argument"); } - gst_env_putvar(vm, vm->env, gst_arg(vm, 0), gst_arg(vm, 1)); + key.type = GST_SYMBOL; + gst_env_putvar(vm, vm->env, key, gst_arg(vm, 1)); gst_c_return(vm, gst_arg(vm, 1)); } @@ -937,7 +948,7 @@ static int gst_stl_parser_charseq(Gst *vm) { if (p == NULL) gst_c_throwc(vm, "expected parser"); if (!gst_chararray_view(gst_arg(vm, 1), &data, &len)) - gst_c_throwc(vm, "expected string/buffer"); + gst_c_throwc(vm, "expected string/buffer/symbol"); for (i = 0; i < len; ++i) { if (p->status != GST_PARSER_PENDING && p->status != GST_PARSER_ROOT) break; gst_parse_byte(p, data[i]); @@ -983,7 +994,7 @@ static int gst_stl_parse(Gst *vm) { GstParser p; const uint8_t *data; if (!gst_chararray_view(gst_arg(vm, 0), &data, &len)) - gst_c_throwc(vm, "expected string/buffer to parse"); + gst_c_throwc(vm, "expected string/buffer/symbol to parse"); gst_parser(&p, vm); for (i = 0; i < len; ++i) { if (p.status != GST_PARSER_PENDING && p.status != GST_PARSER_ROOT) break; @@ -1129,7 +1140,7 @@ void gst_stl_load(Gst *vm) { gst_module_put(vm, "std", "stdin", gst_wrap_userdata(inp)); gst_module_put(vm, "std", "stdout", gst_wrap_userdata(outp)); gst_module_put(vm, "std", "stderr", gst_wrap_userdata(outp)); - maybeEnv = gst_table_get(vm->modules, gst_string_cv(vm, "std")); + maybeEnv = gst_table_get(vm->modules, gst_string_cvs(vm, "std")); if (maybeEnv.type == GST_TABLE) gst_env_merge(vm, vm->env, maybeEnv.data.table); } diff --git a/core/util.c b/core/util.c index 0b195a22..73f1322d 100644 --- a/core/util.c +++ b/core/util.c @@ -55,6 +55,7 @@ GST_WRAP_DEFINE(real, GstReal, GST_REAL, real) GST_WRAP_DEFINE(integer, GstInteger, GST_INTEGER, integer) GST_WRAP_DEFINE(boolean, int, GST_BOOLEAN, boolean) GST_WRAP_DEFINE(string, const uint8_t *, GST_STRING, string) +GST_WRAP_DEFINE(symbol, const uint8_t *, GST_SYMBOL, string) GST_WRAP_DEFINE(array, GstArray *, GST_ARRAY, array) GST_WRAP_DEFINE(tuple, const GstValue *, GST_TUPLE, tuple) GST_WRAP_DEFINE(struct, const GstValue *, GST_STRUCT, st) @@ -94,7 +95,7 @@ static void gst_cmodule_register(Gst *vm, const char *name, const GstModuleItem GstValue key; buffer->count = startLength; gst_buffer_append_cstring(vm, buffer, mod->name); - key = gst_wrap_string(gst_buffer_to_string(vm, buffer)); + key = gst_wrap_symbol(gst_buffer_to_string(vm, buffer)); gst_table_put(vm, vm->registry, key, gst_wrap_cfunction(mod->data)); gst_table_put(vm, vm->registry, gst_wrap_cfunction(mod->data), key); mod++; @@ -104,7 +105,7 @@ static void gst_cmodule_register(Gst *vm, const char *name, const GstModuleItem static GstValue gst_cmodule_table(Gst *vm, const GstModuleItem *mod) { GstTable *module = gst_table(vm, 10); while (mod->name != NULL) { - GstValue key = gst_string_cv(vm, mod->name); + GstValue key = gst_string_cvs(vm, mod->name); gst_table_put(vm, module, key, gst_wrap_cfunction(mod->data)); mod++; } @@ -123,7 +124,7 @@ static GstValue gst_cmodule_struct(Gst *vm, const GstModuleItem *mod) { m = mod; while (m->name != NULL) { gst_struct_put(st, - gst_string_cv(vm, m->name), + gst_string_cvs(vm, m->name), gst_wrap_cfunction(m->data)); ++m; } @@ -131,17 +132,17 @@ static GstValue gst_cmodule_struct(Gst *vm, const GstModuleItem *mod) { } void gst_module(Gst *vm, const char *packagename, const GstModuleItem *mod) { - gst_table_put(vm, vm->modules, gst_string_cv(vm, packagename), gst_cmodule_struct(vm, mod)); + gst_table_put(vm, vm->modules, gst_string_cvs(vm, packagename), gst_cmodule_struct(vm, mod)); gst_cmodule_register(vm, packagename, mod); } void gst_module_mutable(Gst *vm, const char *packagename, const GstModuleItem *mod) { - gst_table_put(vm, vm->modules, gst_string_cv(vm, packagename), gst_cmodule_table(vm, mod)); + gst_table_put(vm, vm->modules, gst_string_cvs(vm, packagename), gst_cmodule_table(vm, mod)); gst_cmodule_register(vm, packagename, mod); } void gst_module_put(Gst *vm, const char *packagename, const char *name, GstValue v) { - GstValue modtable = gst_table_get(vm->modules, gst_string_cv(vm, packagename)); + GstValue modtable = gst_table_get(vm->modules, gst_string_cvs(vm, packagename)); if (modtable.type == GST_TABLE) { GstTable *table = modtable.data.table; if (v.type == GST_CFUNCTION) { @@ -154,12 +155,12 @@ void gst_module_put(Gst *vm, const char *packagename, const char *name, GstValue gst_table_put(vm, vm->registry, key, v); gst_table_put(vm, vm->registry, v, key); } - gst_table_put(vm, table, gst_string_cv(vm, name), v); + gst_table_put(vm, table, gst_string_cvs(vm, name), v); } } GstValue gst_module_get(Gst *vm, const char *packagename) { - return gst_table_get(vm->modules, gst_string_cv(vm, packagename)); + return gst_table_get(vm->modules, gst_string_cvs(vm, packagename)); } /****/ @@ -186,7 +187,7 @@ int gst_seq_view(GstValue seq, const GstValue **data, uint32_t *len) { /* Read both strings and buffer as unsigned character array + uint32_t len. * Returns 1 if the view can be constructed and 0 if the type is invalid. */ int gst_chararray_view(GstValue str, const uint8_t **data, uint32_t *len) { - if (str.type == GST_STRING) { + if (str.type == GST_STRING || str.type == GST_SYMBOL) { *data = str.data.string; *len = gst_string_length(str.data.string); return 1; @@ -281,7 +282,7 @@ static void mergenils(Gst *vm, GstTable *destEnv, GstTable *nils) { uint32_t i; GstTable *destNils = gst_env_nils(vm, destEnv); for (i = 0; i < len; i += 2) { - if (data[i].type == GST_STRING) { + if (data[i].type == GST_SYMBOL) { gst_table_put(vm, destEnv, data[i], gst_wrap_nil()); gst_table_put(vm, destNils, data[i], gst_wrap_boolean(1)); } @@ -295,7 +296,7 @@ static void mergemeta(Gst *vm, GstTable *destEnv, GstTable *meta) { uint32_t i; GstTable *destMeta = gst_env_meta(vm, destEnv); for (i = 0; i < len; i += 2) { - if (data[i].type == GST_STRING) { + if (data[i].type == GST_SYMBOL) { gst_table_put(vm, destMeta, data[i], data[i + 1]); } } @@ -307,7 +308,7 @@ void gst_env_merge(Gst *vm, GstTable *destEnv, GstTable *srcEnv) { uint32_t len = srcEnv->capacity; uint32_t i; for (i = 0; i < len; i += 2) { - if (data[i].type == GST_STRING) { + if (data[i].type == GST_SYMBOL) { gst_table_put(vm, destEnv, data[i], data[i + 1]); } else if (data[i].type == GST_INTEGER) { switch (data[i].data.integer) { @@ -336,7 +337,7 @@ void gst_env_put(Gst *vm, GstTable *env, GstValue key, GstValue value) { } void gst_env_putc(Gst *vm, GstTable *env, const char *key, GstValue value) { - GstValue keyv = gst_string_cv(vm, key); + GstValue keyv = gst_string_cvs(vm, key); gst_env_put(vm, env, keyv, value); } @@ -347,11 +348,11 @@ void gst_env_putvar(Gst *vm, GstTable *env, GstValue key, GstValue value) { ref->count = 1; ref->data[0] = value; gst_table_put(vm, env, key, gst_wrap_array(ref)); - gst_table_put(vm, newmeta, gst_string_cv(vm, "mutable"), gst_wrap_boolean(1)); + gst_table_put(vm, newmeta, gst_string_cvs(vm, "mutable"), gst_wrap_boolean(1)); gst_table_put(vm, meta, key, gst_wrap_table(newmeta)); } void gst_env_putvarc(Gst *vm, GstTable *env, const char *key, GstValue value) { - GstValue keyv = gst_string_cv(vm, key); + GstValue keyv = gst_string_cvs(vm, key); gst_env_putvar(vm, env, keyv, value); } \ No newline at end of file diff --git a/core/value.c b/core/value.c index 617c26af..57392b81 100644 --- a/core/value.c +++ b/core/value.c @@ -180,6 +180,8 @@ const uint8_t *gst_short_description(Gst *vm, GstValue x) { return string_description(vm, "struct", x.data.pointer); case GST_TABLE: return string_description(vm, "table", x.data.pointer); + case GST_SYMBOL: + return x.data.string; case GST_STRING: { GstBuffer *buf = gst_buffer(vm, gst_string_length(x.data.string) + 4); @@ -227,6 +229,9 @@ static GstInteger gst_description_helper(Gst *vm, GstBuffer *b, GstTable *seen, case GST_STRING: gst_escape_string(vm, b, x.data.string); return next; + case GST_SYMBOL: + gst_buffer_append(vm, b, x.data.string, gst_string_length(x.data.string)); + return next; case GST_NIL: gst_buffer_append_cstring(vm, b, "nil"); return next; @@ -287,7 +292,7 @@ const uint8_t *gst_description(Gst *vm, GstValue x) { } const uint8_t *gst_to_string(Gst *vm, GstValue x) { - if (x.type == GST_STRING) { + if (x.type == GST_STRING || x.type == GST_SYMBOL) { return x.data.string; } else if (x.type == GST_BYTEBUFFER) { return gst_buffer_to_string(vm, x.data.buffer); @@ -335,6 +340,7 @@ uint32_t gst_hash(GstValue x) { hash = x.data.boolean; break; case GST_STRING: + case GST_SYMBOL: hash = gst_string_hash(x.data.string); break; case GST_TUPLE: @@ -436,6 +442,7 @@ const char *gst_get(GstValue ds, GstValue key, GstValue *out) { ret.data.integer = ds.data.buffer->data[index]; break; case GST_STRING: + case GST_SYMBOL: if (key.type != GST_INTEGER) return "expected integer key"; index = gst_startrange(key.data.integer, gst_string_length(ds.data.string)); if (index < 0) return "invalid string access"; diff --git a/gsttests/basic.gst b/gsttests/basic.gst index 939d1da2..1d92ca8e 100644 --- a/gsttests/basic.gst +++ b/gsttests/basic.gst @@ -43,13 +43,20 @@ (assert (= 7 (bor 3 4)) "bit or") (assert (= 0 (band 3 4)) "bit and") +((fn [] + (var accum 1) + (var count 0) + (while (< count 16) + (varset! accum (blshift accum 1)) + (varset! count (+ 1 count))) + (assert (= accum 65536) "loop in closure"))) + (var accum 1) (var count 0) (while (< count 16) (varset! accum (blshift accum 1)) (varset! count (+ 1 count))) - -(assert (= accum 65536) "loop") +(assert (= accum 65536) "loop globally") (assert (= (struct 1 2 3 4 5 6 7 8) (struct 7 8 5 6 3 4 1 2)) "struct order does not matter") diff --git a/include/gst/gst.h b/include/gst/gst.h index 580676b6..148533ee 100644 --- a/include/gst/gst.h +++ b/include/gst/gst.h @@ -129,6 +129,7 @@ typedef enum GstType { GST_INTEGER, GST_BOOLEAN, GST_STRING, + GST_SYMBOL, GST_ARRAY, GST_TUPLE, GST_TABLE, @@ -459,7 +460,7 @@ GstValue *gst_tuple_begin(Gst *vm, uint32_t length); const GstValue *gst_tuple_end(Gst *vm, GstValue *tuple); /****/ -/* String functions */ +/* String/Symbol functions */ /****/ uint8_t *gst_string_begin(Gst *vm, uint32_t len); @@ -467,6 +468,7 @@ const uint8_t *gst_string_end(Gst *vm, uint8_t *str); const uint8_t *gst_string_b(Gst *vm, const uint8_t *buf, uint32_t len); const uint8_t *gst_string_c(Gst *vm, const char *cstring); GstValue gst_string_cv(Gst *vm, const char *string); +GstValue gst_string_cvs(Gst *vm, const char *string); int gst_string_compare(const uint8_t *lhs, const uint8_t *rhs); /****/ @@ -609,6 +611,7 @@ GstValue gst_wrap_real(GstReal x); GstValue gst_wrap_integer(GstInteger x); GstValue gst_wrap_boolean(int x); GstValue gst_wrap_string(const uint8_t *x); +GstValue gst_wrap_symbol(const uint8_t *x); GstValue gst_wrap_array(GstArray *x); GstValue gst_wrap_tuple(const GstValue *x); GstValue gst_wrap_struct(const GstValue *x); @@ -627,6 +630,7 @@ int gst_check_real(Gst *vm, uint32_t i, GstReal (*x)); int gst_check_integer(Gst *vm, uint32_t i, GstInteger (*x)); int gst_check_boolean(Gst *vm, uint32_t i, int (*x)); int gst_check_string(Gst *vm, uint32_t i, const uint8_t *(*x)); +int gst_check_symbol(Gst *vm, uint32_t i, const uint8_t *(*x)); int gst_check_array(Gst *vm, uint32_t i, GstArray *(*x)); int gst_check_tuple(Gst *vm, uint32_t i, const GstValue *(*x)); int gst_check_struct(Gst *vm, uint32_t i, const GstValue *(*x));