mirror of
https://github.com/janet-lang/janet
synced 2024-12-25 07:50:27 +00:00
Change object to table type.
Tables are simpler and don't do inheritance via metatables. This means object polymorphism will be done through a different mechanism rather than Lua-like metatables. Perhaps smalltalk style messaging using functions as objects, or lisp-like method dispatch.
This commit is contained in:
parent
c33d4da994
commit
0a96e45c4a
@ -86,9 +86,9 @@ struct GstScope {
|
||||
uint32_t heapCapacity;
|
||||
uint32_t heapSize;
|
||||
uint16_t *freeHeap;
|
||||
GstObject *literals;
|
||||
GstTable *literals;
|
||||
GstArray *literalsArray;
|
||||
GstObject *locals;
|
||||
GstTable *locals;
|
||||
GstScope *parent;
|
||||
};
|
||||
|
||||
@ -124,7 +124,7 @@ static void c_error(GstCompiler *c, const char *e) {
|
||||
* the new scope is a function declaration. */
|
||||
static GstScope *compiler_push_scope(GstCompiler *c, int sameFunction) {
|
||||
GstScope *scope = gst_alloc(c->vm, sizeof(GstScope));
|
||||
scope->locals = gst_object(c->vm, 10);
|
||||
scope->locals = gst_table(c->vm, 10);
|
||||
scope->freeHeap = gst_alloc(c->vm, 10 * sizeof(uint16_t));
|
||||
scope->heapSize = 0;
|
||||
scope->heapCapacity = 10;
|
||||
@ -144,7 +144,7 @@ static GstScope *compiler_push_scope(GstCompiler *c, int sameFunction) {
|
||||
scope->literalsArray = c->tail->literalsArray;
|
||||
} else {
|
||||
scope->nextLocal = 0;
|
||||
scope->literals = gst_object(c->vm, 10);
|
||||
scope->literals = gst_table(c->vm, 10);
|
||||
scope->literalsArray = gst_array(c->vm, 10);
|
||||
}
|
||||
c->tail = scope;
|
||||
@ -318,7 +318,7 @@ static void compiler_tracker_push(GstCompiler *c, SlotTracker *tracker, Slot slo
|
||||
* that one instead of creating a new literal. This allows for some reuse
|
||||
* of things like string constants.*/
|
||||
static uint16_t compiler_add_literal(GstCompiler *c, GstScope *scope, GstValue x) {
|
||||
GstValue checkDup = gst_object_get(scope->literals, x);
|
||||
GstValue checkDup = gst_table_get(scope->literals, x);
|
||||
uint16_t literalIndex = 0;
|
||||
if (checkDup.type != GST_NIL) {
|
||||
/* An equal literal is already registered in the current scope */
|
||||
@ -329,7 +329,7 @@ static uint16_t compiler_add_literal(GstCompiler *c, GstScope *scope, GstValue x
|
||||
valIndex.type = GST_INTEGER;
|
||||
literalIndex = scope->literalsArray->count;
|
||||
valIndex.data.integer = literalIndex;
|
||||
gst_object_put(c->vm, scope->literals, x, valIndex);
|
||||
gst_table_put(c->vm, scope->literals, x, valIndex);
|
||||
gst_array_push(c->vm, scope->literalsArray, x);
|
||||
}
|
||||
return literalIndex;
|
||||
@ -344,7 +344,7 @@ static uint16_t compiler_declare_symbol(GstCompiler *c, GstScope *scope, GstValu
|
||||
target = compiler_get_local(c, scope);
|
||||
x.type = GST_INTEGER;
|
||||
x.data.integer = target;
|
||||
gst_object_put(c->vm, scope->locals, sym, x);
|
||||
gst_table_put(c->vm, scope->locals, sym, x);
|
||||
return target;
|
||||
}
|
||||
|
||||
@ -354,7 +354,7 @@ static int symbol_resolve(GstCompiler *c, GstValue x, uint16_t *level, uint16_t
|
||||
GstScope *scope = c->tail;
|
||||
uint32_t currentLevel = scope->level;
|
||||
while (scope) {
|
||||
GstValue check = gst_object_get(scope->locals, x);
|
||||
GstValue check = gst_table_get(scope->locals, x);
|
||||
if (check.type != GST_NIL) {
|
||||
*level = currentLevel - scope->level;
|
||||
*index = (uint16_t) check.data.integer;
|
||||
@ -925,28 +925,28 @@ static Slot compile_array(GstCompiler *c, FormOptions opts, GstArray *array) {
|
||||
}
|
||||
|
||||
/* Compile an object literal */
|
||||
static Slot compile_object(GstCompiler *c, FormOptions opts, GstObject *obj) {
|
||||
static Slot compile_table(GstCompiler *c, FormOptions opts, GstTable *tab) {
|
||||
GstScope *scope = c->tail;
|
||||
FormOptions subOpts = form_options_default();
|
||||
GstBuffer *buffer = c->buffer;
|
||||
Slot ret;
|
||||
SlotTracker tracker;
|
||||
uint32_t i, cap;
|
||||
cap = obj->capacity;
|
||||
cap = tab->capacity;
|
||||
ret = compiler_get_target(c, opts);
|
||||
tracker_init(c, &tracker);
|
||||
for (i = 0; i < cap; i += 2) {
|
||||
if (obj->data[i].type != GST_NIL) {
|
||||
Slot slot = compile_value(c, subOpts, obj->data[i]);
|
||||
if (tab->data[i].type != GST_NIL) {
|
||||
Slot slot = compile_value(c, subOpts, tab->data[i]);
|
||||
compiler_tracker_push(c, &tracker, compiler_realize_slot(c, slot));
|
||||
slot = compile_value(c, subOpts, obj->data[i + 1]);
|
||||
slot = compile_value(c, subOpts, tab->data[i + 1]);
|
||||
compiler_tracker_push(c, &tracker, compiler_realize_slot(c, slot));
|
||||
}
|
||||
}
|
||||
compiler_tracker_free(c, scope, &tracker);
|
||||
gst_buffer_push_u16(c->vm, buffer, GST_OP_DIC);
|
||||
gst_buffer_push_u16(c->vm, buffer, ret.index);
|
||||
gst_buffer_push_u16(c->vm, buffer, obj->count * 2);
|
||||
gst_buffer_push_u16(c->vm, buffer, tab->count * 2);
|
||||
compiler_tracker_write(c, &tracker, 0);
|
||||
return ret;
|
||||
}
|
||||
@ -1017,8 +1017,8 @@ static Slot compile_value(GstCompiler *c, FormOptions opts, GstValue x) {
|
||||
return compile_form(c, opts, x.data.tuple);
|
||||
case GST_ARRAY:
|
||||
return compile_array(c, opts, x.data.array);
|
||||
case GST_OBJECT:
|
||||
return compile_object(c, opts, x.data.object);
|
||||
case GST_TABLE:
|
||||
return compile_table(c, opts, x.data.table);
|
||||
default:
|
||||
return compile_literal(c, opts, x);
|
||||
}
|
||||
@ -1044,12 +1044,12 @@ void gst_compiler_global(GstCompiler *c, const char *name, GstValue x) {
|
||||
/* Add many global variables */
|
||||
void gst_compiler_globals(GstCompiler *c, GstValue env) {
|
||||
uint32_t i;
|
||||
if (env.type == GST_OBJECT) {
|
||||
GstObject *o = env.data.object;
|
||||
for (i = 0; i < o->capacity; i += 2) {
|
||||
if (o->data[i].type == GST_STRING) {
|
||||
compiler_declare_symbol(c, c->tail, o->data[i]);
|
||||
gst_array_push(c->vm, c->env, o->data[i + 1]);
|
||||
if (env.type == GST_TABLE) {
|
||||
GstTable *t = env.data.table;
|
||||
for (i = 0; i < t->capacity; i += 2) {
|
||||
if (t->data[i].type == GST_STRING) {
|
||||
compiler_declare_symbol(c, c->tail, t->data[i]);
|
||||
gst_array_push(c->vm, c->env, t->data[i + 1]);
|
||||
}
|
||||
}
|
||||
} else if (env.type == GST_STRUCT) {
|
||||
@ -1065,7 +1065,7 @@ void gst_compiler_globals(GstCompiler *c, GstValue env) {
|
||||
|
||||
/* Use a module that was loaded into the vm */
|
||||
void gst_compiler_usemodule(GstCompiler *c, const char *modulename) {
|
||||
GstValue mod = gst_object_get(c->vm->modules, gst_string_cv(c->vm, modulename));
|
||||
GstValue mod = gst_table_get(c->vm->modules, gst_string_cv(c->vm, modulename));
|
||||
gst_compiler_globals(c, mod);
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ void gst_dasm(FILE * out, uint16_t *byteCode, uint32_t len) {
|
||||
current += dasm_varg_op(out, current, "array", 1);
|
||||
break;
|
||||
case GST_OP_DIC:
|
||||
current += dasm_varg_op(out, current, "object", 1);
|
||||
current += dasm_varg_op(out, current, "table", 1);
|
||||
break;
|
||||
case GST_OP_TUP:
|
||||
current += dasm_varg_op(out, current, "tuple", 1);
|
||||
|
98
core/ds.c
98
core/ds.c
@ -169,55 +169,54 @@ void *gst_userdata(Gst *vm, uint32_t size, const GstValue *meta) {
|
||||
}
|
||||
|
||||
/****/
|
||||
/* Dictionary functions */
|
||||
/* Table functions */
|
||||
/****/
|
||||
|
||||
/* Create a new dictionary */
|
||||
GstObject* gst_object(Gst *vm, uint32_t capacity) {
|
||||
GstObject *o = gst_alloc(vm, sizeof(GstObject));
|
||||
/* Create a new table */
|
||||
GstTable *gst_table(Gst *vm, uint32_t capacity) {
|
||||
GstTable *t = gst_alloc(vm, sizeof(GstTable));
|
||||
GstValue *data = gst_zalloc(vm, capacity * sizeof(GstValue));
|
||||
o->data = data;
|
||||
o->capacity = capacity;
|
||||
o->count = 0;
|
||||
o->parent = NULL;
|
||||
o->deleted = 0;
|
||||
return o;
|
||||
t->data = data;
|
||||
t->capacity = capacity;
|
||||
t->count = 0;
|
||||
t->deleted = 0;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Find the bucket that contains the given key. Will also return
|
||||
* bucket where key should go if not in object. */
|
||||
static GstValue *gst_object_find(GstObject *o, GstValue key) {
|
||||
uint32_t index = (gst_hash(key) % (o->capacity / 2)) * 2;
|
||||
* bucket where key should go if not in the table. */
|
||||
static GstValue *gst_table_find(GstTable *t, GstValue key) {
|
||||
uint32_t index = (gst_hash(key) % (t->capacity / 2)) * 2;
|
||||
uint32_t i, j;
|
||||
uint32_t start[2], end[2];
|
||||
start[0] = index; end[0] = o->capacity;
|
||||
start[0] = index; end[0] = t->capacity;
|
||||
start[1] = 0; end[1] = index;
|
||||
for (j = 0; j < 2; ++j)
|
||||
for (i = start[j]; i < end[j]; i += 2) {
|
||||
if (o->data[i].type == GST_NIL) {
|
||||
if (o->data[i + 1].type == GST_NIL) {
|
||||
if (t->data[i].type == GST_NIL) {
|
||||
if (t->data[i + 1].type == GST_NIL) {
|
||||
/* Empty */
|
||||
return o->data + i;
|
||||
return t->data + i;
|
||||
}
|
||||
} else if (gst_equals(o->data[i], key)) {
|
||||
return o->data + i;
|
||||
} else if (gst_equals(t->data[i], key)) {
|
||||
return t->data + i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Resize the dictionary table. */
|
||||
static void gst_object_rehash(Gst *vm, GstObject *o, uint32_t size) {
|
||||
GstValue *olddata = o->data;
|
||||
static void gst_table_rehash(Gst *vm, GstTable *t, uint32_t size) {
|
||||
GstValue *olddata = t->data;
|
||||
GstValue *newdata = gst_zalloc(vm, size * sizeof(GstValue));
|
||||
uint32_t i, oldcapacity;
|
||||
oldcapacity = o->capacity;
|
||||
o->data = newdata;
|
||||
o->capacity = size;
|
||||
o->deleted = 0;
|
||||
oldcapacity = t->capacity;
|
||||
t->data = newdata;
|
||||
t->capacity = size;
|
||||
t->deleted = 0;
|
||||
for (i = 0; i < oldcapacity; i += 2) {
|
||||
if (olddata[i].type != GST_NIL) {
|
||||
GstValue *bucket = gst_object_find(o, olddata[i]);
|
||||
GstValue *bucket = gst_table_find(t, olddata[i]);
|
||||
bucket[0] = olddata[i];
|
||||
bucket[1] = olddata[i + 1];
|
||||
}
|
||||
@ -225,63 +224,58 @@ static void gst_object_rehash(Gst *vm, GstObject *o, uint32_t size) {
|
||||
}
|
||||
|
||||
/* Get a value out of the object */
|
||||
GstValue gst_object_get(GstObject *o, GstValue key) {
|
||||
GstValue *bucket = gst_object_find(o, key);
|
||||
if (bucket && bucket[0].type != GST_NIL) {
|
||||
GstValue gst_table_get(GstTable *t, GstValue key) {
|
||||
GstValue *bucket = gst_table_find(t, key);
|
||||
if (bucket && bucket[0].type != GST_NIL)
|
||||
return bucket[1];
|
||||
} else {
|
||||
GstValue nil;
|
||||
nil.type = GST_NIL;
|
||||
return nil;
|
||||
}
|
||||
else
|
||||
return gst_wrap_nil();
|
||||
}
|
||||
|
||||
/* Remove an entry from the dictionary */
|
||||
GstValue gst_object_remove(GstObject *o, GstValue key) {
|
||||
GstValue *bucket = gst_object_find(o, key);
|
||||
GstValue gst_table_remove(GstTable *t, GstValue key) {
|
||||
GstValue *bucket = gst_table_find(t, key);
|
||||
if (bucket && bucket[0].type != GST_NIL) {
|
||||
GstValue ret = bucket[1];
|
||||
o->count--;
|
||||
o->deleted++;
|
||||
t->count--;
|
||||
t->deleted++;
|
||||
bucket[0].type = GST_NIL;
|
||||
bucket[1].type = GST_BOOLEAN;
|
||||
return ret;
|
||||
} else {
|
||||
GstValue nil;
|
||||
nil.type = GST_NIL;
|
||||
return nil;
|
||||
return gst_wrap_nil();
|
||||
}
|
||||
}
|
||||
|
||||
/* Put a value into the object */
|
||||
void gst_object_put(Gst *vm, GstObject *o, GstValue key, GstValue value) {
|
||||
void gst_table_put(Gst *vm, GstTable *t, GstValue key, GstValue value) {
|
||||
if (key.type == GST_NIL) return;
|
||||
if (value.type == GST_NIL) {
|
||||
gst_object_remove(o, key);
|
||||
gst_table_remove(t, key);
|
||||
} else {
|
||||
GstValue *bucket = gst_object_find(o, key);
|
||||
GstValue *bucket = gst_table_find(t, key);
|
||||
if (bucket && bucket[0].type != GST_NIL) {
|
||||
bucket[1] = value;
|
||||
} else {
|
||||
if (!bucket || 4 * (o->count + o->deleted) >= o->capacity) {
|
||||
gst_object_rehash(vm, o, 4 * o->count + 6);
|
||||
if (!bucket || 4 * (t->count + t->deleted) >= t->capacity) {
|
||||
gst_table_rehash(vm, t, 4 * t->count + 6);
|
||||
}
|
||||
bucket = gst_object_find(o, key);
|
||||
bucket = gst_table_find(t, key);
|
||||
bucket[0] = key;
|
||||
bucket[1] = value;
|
||||
++o->count;
|
||||
++t->count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Find next key in an object. Returns nil if no next key. */
|
||||
GstValue gst_object_next(GstObject *o, GstValue key) {
|
||||
GstValue gst_table_next(GstTable *t, GstValue key) {
|
||||
const GstValue *bucket, *end;
|
||||
end = o->data + o->capacity;
|
||||
end = t->data + t->capacity;
|
||||
if (key.type == GST_NIL) {
|
||||
bucket = o->data;
|
||||
bucket = t->data;
|
||||
} else {
|
||||
bucket = gst_object_find(o, key);
|
||||
bucket = gst_table_find(t, key);
|
||||
if (!bucket || bucket[0].type == GST_NIL)
|
||||
return gst_wrap_nil();
|
||||
bucket += 2;
|
||||
|
23
core/gc.c
23
core/gc.c
@ -158,19 +158,14 @@ void gst_mark(Gst *vm, GstValueUnion x, GstType type) {
|
||||
}
|
||||
break;
|
||||
|
||||
case GST_OBJECT:
|
||||
if (gc_header(x.object)->color != vm->black) {
|
||||
case GST_TABLE:
|
||||
if (gc_header(x.table)->color != vm->black) {
|
||||
uint32_t i;
|
||||
gc_header(x.object)->color = vm->black;
|
||||
gc_header(x.object->data)->color = vm->black;
|
||||
for (i = 0; i < x.object->capacity; i += 2) {
|
||||
gst_mark_value(vm, x.object->data[i]);
|
||||
gst_mark_value(vm, x.object->data[i + 1]);
|
||||
}
|
||||
if (x.object->parent != NULL) {
|
||||
GstValueUnion temp;
|
||||
temp.object = x.object->parent;
|
||||
gst_mark(vm, temp, GST_OBJECT);
|
||||
gc_header(x.table)->color = vm->black;
|
||||
gc_header(x.table->data)->color = vm->black;
|
||||
for (i = 0; i < x.table->capacity; i += 2) {
|
||||
gst_mark_value(vm, x.table->data[i]);
|
||||
gst_mark_value(vm, x.table->data[i + 1]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -264,8 +259,8 @@ void gst_collect(Gst *vm) {
|
||||
/* Thread can be null */
|
||||
if (vm->thread)
|
||||
gst_mark_value(vm, gst_wrap_thread(vm->thread));
|
||||
gst_mark_value(vm, gst_wrap_object(vm->modules));
|
||||
gst_mark_value(vm, gst_wrap_object(vm->registry));
|
||||
gst_mark_value(vm, gst_wrap_table(vm->modules));
|
||||
gst_mark_value(vm, gst_wrap_table(vm->registry));
|
||||
gst_mark_value(vm, vm->ret);
|
||||
if (vm->scratch)
|
||||
gc_header(vm->scratch)->color = vm->black;
|
||||
|
12
core/parse.c
12
core/parse.c
@ -45,8 +45,8 @@ struct GstParseState {
|
||||
struct {
|
||||
GstValue key;
|
||||
int keyFound;
|
||||
GstObject *object;
|
||||
} object;
|
||||
GstTable *table;
|
||||
} table;
|
||||
struct {
|
||||
GstBuffer *buffer;
|
||||
uint32_t count;
|
||||
@ -432,13 +432,13 @@ static int form_state(GstParser *p, uint8_t c) {
|
||||
} else { /* c == '{' */
|
||||
uint32_t i;
|
||||
if (array->count % 2 != 0) {
|
||||
p_error(p, "object literal must have even number of elements");
|
||||
p_error(p, "table literal must have even number of elements");
|
||||
return 1;
|
||||
}
|
||||
x.type = GST_OBJECT;
|
||||
x.data.object = gst_object(p->vm, array->count);
|
||||
x.type = GST_TABLE;
|
||||
x.data.table = gst_table(p->vm, array->count);
|
||||
for (i = 0; i < array->count; i += 2) {
|
||||
gst_object_put(p->vm, x.data.object, array->data[i], array->data[i + 1]);
|
||||
gst_table_put(p->vm, x.data.table, array->data[i], array->data[i + 1]);
|
||||
}
|
||||
}
|
||||
parser_pop(p);
|
||||
|
@ -40,7 +40,7 @@
|
||||
* Byte 209: Tuple - [u32 length]*[value... elements]
|
||||
* Byte 210: Thread - [u8 state][u32 frames]*[[value callee][value env]
|
||||
* [u32 pcoffset][u16 ret][u16 args][u16 size]*[value ...stack]
|
||||
* Byte 211: Object - [value parent][u32 length]*2*[value... kvs]
|
||||
* Byte 211: Table - [u32 length]*2*[value... kvs]
|
||||
* Byte 212: FuncDef - [u32 locals][u32 arity][u32 flags][u32 literallen]*[value...
|
||||
* literals][u32 bytecodelen]*[u16... bytecode]
|
||||
* Byte 213: FunEnv - [value thread][u32 length]*[value ...upvalues]
|
||||
@ -290,24 +290,19 @@ static const char *gst_deserialize_impl(
|
||||
}
|
||||
break;
|
||||
|
||||
case 211: /* Object */
|
||||
case 211: /* Table */
|
||||
{
|
||||
GstValue parent;
|
||||
ret.type = GST_OBJECT;
|
||||
ret.data.object = gst_object(vm, 10);
|
||||
err = gst_deserialize_impl(vm, data, end, &data, visited, &parent);
|
||||
if (err != NULL) return err;
|
||||
ret.type = GST_TABLE;
|
||||
read_u32(length);
|
||||
ret.data.table = gst_table(vm, 2 * length);
|
||||
for (i = 0; i < length; i += 2) {
|
||||
GstValue key, value;
|
||||
err = gst_deserialize_impl(vm, data, end, &data, visited, &key);
|
||||
if (err != NULL) return err;
|
||||
err = gst_deserialize_impl(vm, data, end, &data, visited, &value);
|
||||
if (err != NULL) return err;
|
||||
gst_object_put(vm, ret.data.object, key, value);
|
||||
gst_table_put(vm, ret.data.table, key, value);
|
||||
}
|
||||
if (parent.type == GST_OBJECT)
|
||||
ret.data.object->parent = parent.data.object;
|
||||
gst_array_push(vm, visited, ret);
|
||||
}
|
||||
break;
|
||||
@ -461,7 +456,7 @@ BUFFER_DEFINE(u32, uint32_t)
|
||||
const char *gst_serialize_impl(
|
||||
Gst *vm,
|
||||
GstBuffer *buffer,
|
||||
GstObject *visited,
|
||||
GstTable *visited,
|
||||
uint32_t *nextId,
|
||||
GstValue x) {
|
||||
|
||||
@ -503,7 +498,7 @@ const char *gst_serialize_impl(
|
||||
}
|
||||
|
||||
/* Check if already seen - if so, use reference */
|
||||
check = gst_object_get(visited, x);
|
||||
check = gst_table_get(visited, x);
|
||||
if (check.type == GST_INTEGER) {
|
||||
write_byte(217);
|
||||
write_u32((uint32_t) check.data.integer);
|
||||
@ -568,7 +563,7 @@ const char *gst_serialize_impl(
|
||||
/* Record reference */
|
||||
check.type = GST_INTEGER;
|
||||
check.data.integer = *nextId++;
|
||||
gst_object_put(vm, visited, x, check);
|
||||
gst_table_put(vm, visited, x, check);
|
||||
|
||||
/* Return success */
|
||||
return NULL;
|
||||
@ -579,7 +574,7 @@ const char *gst_serialize(Gst *vm, GstBuffer *buffer, GstValue x) {
|
||||
uint32_t nextId = 0;
|
||||
uint32_t oldCount = buffer->count;
|
||||
const char *err;
|
||||
GstObject *visited = gst_object(vm, 10);
|
||||
GstTable *visited = gst_table(vm, 10);
|
||||
err = gst_serialize_impl(vm, buffer, visited, &nextId, x);
|
||||
if (err != NULL) {
|
||||
buffer->count = oldCount;
|
||||
|
42
core/stl.c
42
core/stl.c
@ -115,13 +115,11 @@ int gst_stl_not(Gst *vm) {
|
||||
|
||||
/* Get length of object */
|
||||
int gst_stl_length(Gst *vm) {
|
||||
GstValue ret;
|
||||
uint32_t count = gst_count_args(vm);
|
||||
if (count == 0) {
|
||||
ret.type = GST_NIL;
|
||||
gst_c_return(vm, ret);
|
||||
}
|
||||
if (count == 1) {
|
||||
gst_c_return(vm, gst_wrap_nil());
|
||||
} else {
|
||||
GstValue ret;
|
||||
ret.type = GST_INTEGER;
|
||||
GstValue x = gst_arg(vm, 0);
|
||||
switch (x.type) {
|
||||
@ -139,12 +137,12 @@ int gst_stl_length(Gst *vm) {
|
||||
case GST_TUPLE:
|
||||
ret.data.integer = gst_tuple_length(x.data.tuple);
|
||||
break;
|
||||
case GST_OBJECT:
|
||||
ret.data.integer = x.data.object->count;
|
||||
case GST_TABLE:
|
||||
ret.data.integer = x.data.table->count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
gst_c_return(vm, ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert to integer */
|
||||
@ -259,8 +257,8 @@ int gst_stl_type(Gst *vm) {
|
||||
case GST_CFUNCTION:
|
||||
typestr = "cfunction";
|
||||
break;
|
||||
case GST_OBJECT:
|
||||
typestr = "object";
|
||||
case GST_TABLE:
|
||||
typestr = "table";
|
||||
break;
|
||||
case GST_USERDATA:
|
||||
typestr = "userdata";
|
||||
@ -296,16 +294,16 @@ int gst_stl_tuple(Gst *vm) {
|
||||
}
|
||||
|
||||
/* Create object */
|
||||
int gst_stl_object(Gst *vm) {
|
||||
int gst_stl_table(Gst *vm) {
|
||||
uint32_t i;
|
||||
uint32_t count = gst_count_args(vm);
|
||||
GstObject *object;
|
||||
GstTable *table;
|
||||
if (count % 2 != 0)
|
||||
gst_c_throwc(vm, "expected even number of arguments");
|
||||
object = gst_object(vm, 4 * count);
|
||||
table = gst_table(vm, 4 * count);
|
||||
for (i = 0; i < count; i += 2)
|
||||
gst_object_put(vm, object, gst_arg(vm, i), gst_arg(vm, i + 1));
|
||||
gst_c_return(vm, gst_wrap_object(object));
|
||||
gst_table_put(vm, table, gst_arg(vm, i), gst_arg(vm, i + 1));
|
||||
gst_c_return(vm, gst_wrap_table(table));
|
||||
}
|
||||
|
||||
/* Create struct */
|
||||
@ -425,16 +423,16 @@ int gst_stl_ensure(Gst *vm) {
|
||||
gst_c_return(vm, ds);
|
||||
}
|
||||
|
||||
/* Get next key in struct or object */
|
||||
/* Get next key in struct or table */
|
||||
int gst_stl_next(Gst *vm) {
|
||||
GstValue ds = gst_arg(vm, 0);
|
||||
GstValue key = gst_arg(vm, 1);
|
||||
if (ds.type == GST_OBJECT) {
|
||||
gst_c_return(vm, gst_object_next(ds.data.object, key));
|
||||
if (ds.type == GST_TABLE) {
|
||||
gst_c_return(vm, gst_table_next(ds.data.table, key));
|
||||
} else if (ds.type == GST_STRUCT) {
|
||||
gst_c_return(vm, gst_struct_next(ds.data.st, key));
|
||||
} else {
|
||||
gst_c_throwc(vm, "expected object or struct");
|
||||
gst_c_throwc(vm, "expected table or struct");
|
||||
}
|
||||
}
|
||||
|
||||
@ -499,11 +497,11 @@ int gst_stl_serialize(Gst *vm) {
|
||||
/****/
|
||||
|
||||
int gst_stl_global(Gst *vm) {
|
||||
gst_c_return(vm, gst_object_get(vm->registry, gst_arg(vm, 0)));
|
||||
gst_c_return(vm, gst_table_get(vm->registry, gst_arg(vm, 0)));
|
||||
}
|
||||
|
||||
int gst_stl_setglobal(Gst *vm) {
|
||||
gst_object_put(vm, vm->registry, gst_arg(vm, 0), gst_arg(vm, 1));
|
||||
gst_table_put(vm, vm->registry, gst_arg(vm, 0), gst_arg(vm, 1));
|
||||
gst_c_return(vm, gst_wrap_nil());
|
||||
}
|
||||
|
||||
@ -577,7 +575,7 @@ static const GstModuleItem const std_module[] = {
|
||||
{"slice", gst_stl_slice},
|
||||
{"array", gst_stl_array},
|
||||
{"tuple", gst_stl_tuple},
|
||||
{"object", gst_stl_object},
|
||||
{"table", gst_stl_table},
|
||||
{"struct", gst_stl_struct},
|
||||
{"buffer", gst_stl_buffer},
|
||||
{"strcat", gst_stl_strcat},
|
||||
|
26
core/util.c
26
core/util.c
@ -62,21 +62,21 @@ GST_WRAP_DEFINE(thread, GstThread *, GST_THREAD, thread)
|
||||
GST_WRAP_DEFINE(buffer, GstBuffer *, GST_BYTEBUFFER, buffer)
|
||||
GST_WRAP_DEFINE(function, GstFunction *, GST_FUNCTION, function)
|
||||
GST_WRAP_DEFINE(cfunction, GstCFunction, GST_CFUNCTION, cfunction)
|
||||
GST_WRAP_DEFINE(object, GstObject *, GST_OBJECT, object)
|
||||
GST_WRAP_DEFINE(table, GstTable *, GST_TABLE, table)
|
||||
GST_WRAP_DEFINE(userdata, void *, GST_USERDATA, pointer)
|
||||
GST_WRAP_DEFINE(funcenv, GstFuncEnv *, GST_FUNCENV, env)
|
||||
GST_WRAP_DEFINE(funcdef, GstFuncDef *, GST_FUNCDEF, def)
|
||||
|
||||
#undef GST_WRAP_DEFINE
|
||||
|
||||
GstValue gst_cmodule_object(Gst *vm, const GstModuleItem *mod) {
|
||||
GstObject *module = gst_object(vm, 10);
|
||||
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);
|
||||
gst_object_put(vm, module, key, gst_wrap_cfunction(mod->data));
|
||||
gst_table_put(vm, module, key, gst_wrap_cfunction(mod->data));
|
||||
mod++;
|
||||
}
|
||||
return gst_wrap_object(module);
|
||||
return gst_wrap_table(module);
|
||||
}
|
||||
|
||||
GstValue gst_cmodule_struct(Gst *vm, const GstModuleItem *mod) {
|
||||
@ -100,19 +100,19 @@ GstValue gst_cmodule_struct(Gst *vm, const GstModuleItem *mod) {
|
||||
}
|
||||
|
||||
void gst_module_put(Gst *vm, const char *packagename, GstValue mod) {
|
||||
gst_object_put(vm, vm->modules, gst_string_cv(vm, packagename), mod);
|
||||
gst_table_put(vm, vm->modules, gst_string_cv(vm, packagename), mod);
|
||||
}
|
||||
|
||||
GstValue gst_module_get(Gst *vm, const char *packagename) {
|
||||
return gst_object_get(vm->modules, gst_string_cv(vm, packagename));
|
||||
return gst_table_get(vm->modules, gst_string_cv(vm, packagename));
|
||||
}
|
||||
|
||||
void gst_register_put(Gst *vm, const char *name, GstValue c) {
|
||||
gst_object_put(vm, vm->registry, gst_string_cv(vm, name), c);
|
||||
gst_table_put(vm, vm->registry, gst_string_cv(vm, name), c);
|
||||
}
|
||||
|
||||
GstValue gst_register_get(Gst *vm, const char *name) {
|
||||
return gst_object_get(vm->registry, gst_string_cv(vm, name));
|
||||
return gst_table_get(vm->registry, gst_string_cv(vm, name));
|
||||
}
|
||||
|
||||
/****/
|
||||
@ -151,13 +151,13 @@ int gst_chararray_view(GstValue str, const uint8_t **data, uint32_t *len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read both structs and objects as the entries of a hashtable with
|
||||
/* Read both structs and tables as the entries of a hashtable with
|
||||
* identical structure. Returns 1 if the view can be constructed and
|
||||
* 0 if the type is invalid. */
|
||||
int gst_hashtable_view(GstValue tab, const GstValue **data, uint32_t *cap) {
|
||||
if (tab.type == GST_OBJECT) {
|
||||
*data = tab.data.object->data;
|
||||
*cap = tab.data.object->capacity;
|
||||
if (tab.type == GST_TABLE) {
|
||||
*data = tab.data.table->data;
|
||||
*cap = tab.data.table->capacity;
|
||||
return 1;
|
||||
} else if (tab.type == GST_STRUCT) {
|
||||
*data = tab.data.st;
|
||||
|
16
core/value.c
16
core/value.c
@ -96,8 +96,8 @@ const uint8_t *gst_to_string(Gst *vm, GstValue x) {
|
||||
return string_description(vm, "tuple", x.data.pointer);
|
||||
case GST_STRUCT:
|
||||
return string_description(vm, "struct", x.data.pointer);
|
||||
case GST_OBJECT:
|
||||
return string_description(vm, "object", x.data.pointer);
|
||||
case GST_TABLE:
|
||||
return string_description(vm, "table", x.data.pointer);
|
||||
case GST_STRING:
|
||||
return x.data.string;
|
||||
case GST_BYTEBUFFER:
|
||||
@ -267,8 +267,8 @@ const char *gst_get(GstValue ds, GstValue key, GstValue *out) {
|
||||
case GST_STRUCT:
|
||||
ret = gst_struct_get(ds.data.st, key);
|
||||
break;
|
||||
case GST_OBJECT:
|
||||
ret = gst_object_get(ds.data.object, key);
|
||||
case GST_TABLE:
|
||||
ret = gst_table_get(ds.data.table, key);
|
||||
break;
|
||||
default:
|
||||
return "cannot get";
|
||||
@ -295,8 +295,8 @@ const char *gst_set(Gst *vm, GstValue ds, GstValue key, GstValue value) {
|
||||
if (index < 0) return "invalid buffer access";
|
||||
ds.data.buffer->data[index] = (uint8_t) value.data.integer;
|
||||
break;
|
||||
case GST_OBJECT:
|
||||
gst_object_put(vm, ds.data.object, key, value);
|
||||
case GST_TABLE:
|
||||
gst_table_put(vm, ds.data.table, key, value);
|
||||
break;
|
||||
default:
|
||||
return "cannot set";
|
||||
@ -326,8 +326,8 @@ GstInteger gst_length(Gst *vm, GstValue x) {
|
||||
case GST_STRUCT:
|
||||
length = gst_struct_length(x.data.st);
|
||||
break;
|
||||
case GST_OBJECT:
|
||||
length = x.data.object->count;
|
||||
case GST_TABLE:
|
||||
length = x.data.table->count;
|
||||
break;
|
||||
}
|
||||
return length;
|
||||
|
14
core/vm.c
14
core/vm.c
@ -330,19 +330,19 @@ int gst_continue(Gst *vm) {
|
||||
}
|
||||
break;
|
||||
|
||||
case GST_OP_DIC: /* Object literal */
|
||||
case GST_OP_DIC: /* Table literal */
|
||||
{
|
||||
uint32_t i = 3;
|
||||
uint32_t kvs = pc[2];
|
||||
GstObject *o = gst_object(vm, 2 * kvs);
|
||||
GstTable *t = gst_table(vm, 2 * kvs);
|
||||
kvs = kvs + 3;
|
||||
while (i < kvs) {
|
||||
v1 = stack[pc[i++]];
|
||||
v2 = stack[pc[i++]];
|
||||
gst_object_put(vm, o, v1, v2);
|
||||
gst_table_put(vm, t, v1, v2);
|
||||
}
|
||||
temp.type = GST_OBJECT;
|
||||
temp.data.object = o;
|
||||
temp.type = GST_TABLE;
|
||||
temp.data.table = t;
|
||||
stack[pc[1]] = temp;
|
||||
pc += kvs;
|
||||
}
|
||||
@ -466,8 +466,8 @@ void gst_init(Gst *vm) {
|
||||
vm->cache_count = 0;
|
||||
vm->cache_deleted = 0;
|
||||
/* Set up global env */
|
||||
vm->modules = gst_object(vm, 10);
|
||||
vm->registry = gst_object(vm, 10);
|
||||
vm->modules = gst_table(vm, 10);
|
||||
vm->registry = gst_table(vm, 10);
|
||||
}
|
||||
|
||||
/* Clear all memory associated with the VM */
|
||||
|
@ -125,7 +125,7 @@ typedef enum GstType {
|
||||
GST_BYTEBUFFER,
|
||||
GST_FUNCTION,
|
||||
GST_CFUNCTION,
|
||||
GST_OBJECT,
|
||||
GST_TABLE,
|
||||
GST_USERDATA,
|
||||
GST_FUNCENV,
|
||||
GST_FUNCDEF
|
||||
@ -144,7 +144,7 @@ typedef int GstBoolean;
|
||||
typedef struct GstFunction GstFunction;
|
||||
typedef struct GstArray GstArray;
|
||||
typedef struct GstBuffer GstBuffer;
|
||||
typedef struct GstObject GstObject;
|
||||
typedef struct GstTable GstTable;
|
||||
typedef struct GstThread GstThread;
|
||||
typedef int (*GstCFunction)(Gst * vm);
|
||||
|
||||
@ -170,7 +170,7 @@ union GstValueUnion {
|
||||
GstInteger integer;
|
||||
GstArray *array;
|
||||
GstBuffer *buffer;
|
||||
GstObject *object;
|
||||
GstTable *table;
|
||||
GstThread *thread;
|
||||
const GstValue *tuple;
|
||||
GstCFunction cfunction;
|
||||
@ -223,13 +223,12 @@ struct GstBuffer {
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
/* The main Gst type, an obect. Objects are just hashtables with a parent */
|
||||
struct GstObject {
|
||||
/* A mutable associative data type. Backed by a hashtable. */
|
||||
struct GstTable {
|
||||
uint32_t count;
|
||||
uint32_t capacity;
|
||||
uint32_t deleted;
|
||||
GstValue *data;
|
||||
GstObject *parent;
|
||||
};
|
||||
|
||||
/* Some function defintion flags */
|
||||
@ -288,8 +287,8 @@ struct Gst {
|
||||
uint32_t scratch_len;
|
||||
/* GC roots */
|
||||
GstThread *thread;
|
||||
GstObject *modules;
|
||||
GstObject *registry;
|
||||
GstTable *modules;
|
||||
GstTable *registry;
|
||||
/* Return state */
|
||||
const char *crash;
|
||||
GstValue ret; /* Returned value from gst_start. */
|
||||
@ -388,14 +387,14 @@ GstValue gst_struct_get(const GstValue *st, GstValue key);
|
||||
GstValue gst_struct_next(const GstValue *st, GstValue key);
|
||||
|
||||
/****/
|
||||
/* Object functions */
|
||||
/* Table functions */
|
||||
/****/
|
||||
|
||||
GstObject *gst_object(Gst *vm, uint32_t capacity);
|
||||
GstValue gst_object_get(GstObject *obj, GstValue key);
|
||||
GstValue gst_object_remove(GstObject *obj, GstValue key);
|
||||
void gst_object_put(Gst *vm, GstObject *obj, GstValue key, GstValue value);
|
||||
GstValue gst_object_next(GstObject *o, GstValue key);
|
||||
GstTable *gst_table(Gst *vm, uint32_t capacity);
|
||||
GstValue gst_table_get(GstTable *t, GstValue key);
|
||||
GstValue gst_table_remove(GstTable *t, GstValue key);
|
||||
void gst_table_put(Gst *vm, GstTable *t, GstValue key, GstValue value);
|
||||
GstValue gst_table_next(GstTable *o, GstValue key);
|
||||
|
||||
/****/
|
||||
/* Threads */
|
||||
@ -446,7 +445,7 @@ GstInteger gst_length(Gst *vm, GstValue x);
|
||||
* Byte 209: Tuple - [u32 length]*[value... elements]
|
||||
* Byte 210: Thread - [u8 state][u32 frames]*[[value callee][value env]
|
||||
* [u32 pcoffset][u32 erroffset][u16 ret][u16 errloc][u16 size]*[value ...stack]
|
||||
* Byte 211: Object - [value meta][u32 length]*2*[value... kvs]
|
||||
* Byte 211: Table - [u32 length]*2*[value... kvs]
|
||||
* Byte 212: FuncDef - [u32 locals][u32 arity][u32 flags][u32 literallen]*[value...
|
||||
* literals][u32 bytecodelen]*[u16... bytecode]
|
||||
* Byte 213: FunEnv - [value thread][u32 length]*[value ...upvalues]
|
||||
@ -501,7 +500,7 @@ uint16_t gst_count_args(Gst *vm);
|
||||
/* C Api */
|
||||
/****/
|
||||
|
||||
GstValue gst_cmodule_object(Gst *vm, const GstModuleItem *mod);
|
||||
GstValue gst_cmodule_table(Gst *vm, const GstModuleItem *mod);
|
||||
GstValue gst_cmodule_struct(Gst *vm, const GstModuleItem *mod);
|
||||
void gst_module_put(Gst *vm, const char *packagename, GstValue mod);
|
||||
GstValue gst_module_get(Gst *vm, const char *packagename);
|
||||
@ -521,7 +520,7 @@ GstValue gst_wrap_thread(GstThread *x);
|
||||
GstValue gst_wrap_buffer(GstBuffer *x);
|
||||
GstValue gst_wrap_function(GstFunction *x);
|
||||
GstValue gst_wrap_cfunction(GstCFunction x);
|
||||
GstValue gst_wrap_object(GstObject *x);
|
||||
GstValue gst_wrap_table(GstTable *x);
|
||||
GstValue gst_wrap_userdata(void *x);
|
||||
GstValue gst_wrap_funcenv(GstFuncEnv *x);
|
||||
GstValue gst_wrap_funcdef(GstFuncDef *x);
|
||||
@ -539,7 +538,7 @@ int gst_check_thread(Gst *vm, uint32_t i, GstThread *(*x));
|
||||
int gst_check_buffer(Gst *vm, uint32_t i, GstBuffer *(*x));
|
||||
int gst_check_function(Gst *vm, uint32_t i, GstFunction *(*x));
|
||||
int gst_check_cfunction(Gst *vm, uint32_t i, GstCFunction (*x));
|
||||
int gst_check_object(Gst *vm, uint32_t i, GstObject *(*x));
|
||||
int gst_check_table(Gst *vm, uint32_t i, GstTable *(*x));
|
||||
int gst_check_userdata(Gst *vm, uint32_t i, void *(*x));
|
||||
int gst_check_funcenv(Gst *vm, uint32_t i, GstFuncEnv *(*x));
|
||||
int gst_check_funcdef(Gst *vm, uint32_t i, GstFuncDef *(*x));
|
||||
|
Loading…
Reference in New Issue
Block a user