1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-21 12:43:15 +00:00

Add symbol type.

This commit is contained in:
bakpakin 2017-07-02 17:17:24 -04:00
parent 31ec1e9147
commit e2c78b36d0
11 changed files with 114 additions and 78 deletions

View File

@ -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') {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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