diff --git a/Makefile b/Makefile index 78b672a7..d9f9a2b9 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ TARGET=interp PREFIX=/usr/local # C sources -HEADERS=vm.h ds.h compile.h parse.h value.h disasm.h datatypes.h gc.h +HEADERS=vm.h ds.h compile.h parse.h value.h disasm.h datatypes.h gc.h util.h SOURCES=main.c parse.c value.c vm.c ds.c compile.c disasm.c gc.c OBJECTS=$(patsubst %.c,%.o,$(SOURCES)) diff --git a/compile.c b/compile.c index e4446a2c..f97d8eb9 100644 --- a/compile.c +++ b/compile.c @@ -2,7 +2,7 @@ #include "ds.h" #include "value.h" #include "vm.h" -#include +#include "util.h" /* During compilation, FormOptions are passed to ASTs * as configuration options to allow for some optimizations. */ @@ -34,7 +34,7 @@ struct Slot { uint16_t index; /* A nil Slot should not be expected to contain real data. (ignore index). * Forms that have side effects but don't evaulate to - * anything will try to return bil slots. */ + * anything will try to return nil slots. */ uint16_t isNil : 1; /* A temp Slot is a Slot on the stack that does not * belong to a named local. They can be freed whenever, @@ -170,7 +170,7 @@ static void compiler_free_local(GstCompiler *c, GstScope *scope, uint16_t slot) if (scope->heapSize >= scope->heapCapacity) { uint32_t newCap = 2 * scope->heapSize; uint16_t *newData = gst_alloc(c->vm, newCap * sizeof(uint16_t)); - memcpy(newData, scope->freeHeap, scope->heapSize * sizeof(uint16_t)); + gst_memcpy(newData, scope->freeHeap, scope->heapSize * sizeof(uint16_t)); scope->freeHeap = newData; scope->heapCapacity = newCap; } @@ -287,7 +287,7 @@ static void compiler_tracker_push(GstCompiler *c, SlotTracker *tracker, Slot slo if (tracker->count >= tracker->capacity) { uint32_t newCap = 2 * tracker->count; Slot *newData = gst_alloc(c->vm, newCap * sizeof(Slot)); - memcpy(newData, tracker->slots, tracker->count * sizeof(Slot)); + gst_memcpy(newData, tracker->slots, tracker->count * sizeof(Slot)); tracker->slots = newData; tracker->capacity = newCap; } @@ -536,34 +536,34 @@ static Slot compile_operator(GstCompiler *c, FormOptions opts, GstArray *form, /* Math specials */ static Slot compile_addition(GstCompiler *c, FormOptions opts, GstArray *form) { - return compile_operator(c, opts, form, GST_OP_LD0, -1, GST_OP_ADD, -1, 0); + return compile_operator(c, opts, form, -1, -1, GST_OP_ADD, -1, 0); } static Slot compile_subtraction(GstCompiler *c, FormOptions opts, GstArray *form) { - return compile_operator(c, opts, form, GST_OP_LD0, -1, GST_OP_SUB, -1, 0); + return compile_operator(c, opts, form, -1, -1, GST_OP_SUB, -1, 0); } static Slot compile_multiplication(GstCompiler *c, FormOptions opts, GstArray *form) { - return compile_operator(c, opts, form, GST_OP_LD1, -1, GST_OP_MUL, -1, 0); + return compile_operator(c, opts, form, -1, -1, GST_OP_MUL, -1, 0); } static Slot compile_division(GstCompiler *c, FormOptions opts, GstArray *form) { - return compile_operator(c, opts, form, GST_OP_LD1, -1, GST_OP_DIV, -1, 0); + return compile_operator(c, opts, form, -1, -1, GST_OP_DIV, -1, 0); } static Slot compile_equals(GstCompiler *c, FormOptions opts, GstArray *form) { - return compile_operator(c, opts, form, GST_OP_TRU, GST_OP_TRU, GST_OP_EQL, -1, 0); + return compile_operator(c, opts, form, -1, -1, GST_OP_EQL, -1, 0); } static Slot compile_lt(GstCompiler *c, FormOptions opts, GstArray *form) { - return compile_operator(c, opts, form, GST_OP_TRU, GST_OP_TRU, GST_OP_LTN, -1, 0); + return compile_operator(c, opts, form, -1, -1, GST_OP_LTN, -1, 0); } static Slot compile_lte(GstCompiler *c, FormOptions opts, GstArray *form) { - return compile_operator(c, opts, form, GST_OP_TRU, GST_OP_TRU, GST_OP_LTE, -1, 0); + return compile_operator(c, opts, form, -1, -1, GST_OP_LTE, -1, 0); } static Slot compile_gt(GstCompiler *c, FormOptions opts, GstArray *form) { - return compile_operator(c, opts, form, GST_OP_TRU, GST_OP_TRU, GST_OP_LTN, -1, 1); + return compile_operator(c, opts, form, -1, -1, GST_OP_LTN, -1, 1); } static Slot compile_gte(GstCompiler *c, FormOptions opts, GstArray *form) { - return compile_operator(c, opts, form, GST_OP_TRU, GST_OP_TRU, GST_OP_LTE, -1, 1); + return compile_operator(c, opts, form, -1, -1, GST_OP_LTE, -1, 1); } static Slot compile_not(GstCompiler *c, FormOptions opts, GstArray *form) { - return compile_operator(c, opts, form, GST_OP_FLS, GST_OP_NOT, -1, -1, 0); + return compile_operator(c, opts, form, -1, GST_OP_NOT, -1, -1, 0); } static Slot compile_get(GstCompiler *c, FormOptions opts, GstArray *form) { return compile_operator(c, opts, form, -1, -1, GST_OP_GET, -1, 0); @@ -686,13 +686,13 @@ static GstFuncDef *compiler_gen_funcdef(GstCompiler *c, uint32_t lastNBytes, uin def->byteCodeLen = lastNBytes / 2; /* Copy the last chunk of bytes in the buffer into the new * memory for the function's byteCOde */ - memcpy(byteCode, buffer->data + buffer->count - lastNBytes, lastNBytes); + gst_memcpy(byteCode, buffer->data + buffer->count - lastNBytes, lastNBytes); /* Remove the byteCode from the end of the buffer */ buffer->count -= lastNBytes; /* Create the literals used by this function */ if (scope->literalsArray->count) { def->literals = gst_alloc(c->vm, scope->literalsArray->count * sizeof(GstValue)); - memcpy(def->literals, scope->literalsArray->data, + gst_memcpy(def->literals, scope->literalsArray->data, scope->literalsArray->count * sizeof(GstValue)); } else { def->literals = NULL; @@ -1267,7 +1267,7 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) { GstFunction *func = gst_alloc(c->vm, sizeof(GstFunction)); if (envSize) { env->values = gst_alloc(c->vm, sizeof(GstValue) * envSize); - memcpy(env->values, c->env->data, envSize * sizeof(GstValue)); + gst_memcpy(env->values, c->env->data, envSize * sizeof(GstValue)); } else { env->values = NULL; } diff --git a/datatypes.h b/datatypes.h index d01caf53..417b190f 100644 --- a/datatypes.h +++ b/datatypes.h @@ -197,40 +197,43 @@ struct GstCompiler { /* Bytecode */ enum GstOpCode { - GST_OP_ADD = 0, /* 0x0000 */ - GST_OP_SUB, /* 0x0001 */ - GST_OP_MUL, /* 0x0002 */ - GST_OP_DIV, /* 0x0003 */ - GST_OP_NOT, /* 0x0004 */ - GST_OP_LD0, /* 0x0005 */ - GST_OP_LD1, /* 0x0006 */ - GST_OP_FLS, /* 0x0007 */ - GST_OP_TRU, /* 0x0008 */ - GST_OP_NIL, /* 0x0009 */ - GST_OP_I16, /* 0x000a */ - GST_OP_UPV, /* 0x000b */ - GST_OP_JIF, /* 0x000c */ - GST_OP_JMP, /* 0x000d */ - GST_OP_CAL, /* 0x000e */ - GST_OP_RET, /* 0x000f */ - GST_OP_SUV, /* 0x0010 */ - GST_OP_CST, /* 0x0011 */ - GST_OP_I32, /* 0x0012 */ - GST_OP_F64, /* 0x0013 */ - GST_OP_MOV, /* 0x0014 */ - GST_OP_CLN, /* 0x0015 */ - GST_OP_EQL, /* 0x0016 */ - GST_OP_LTN, /* 0x0017 */ - GST_OP_LTE, /* 0x0018 */ - GST_OP_ARR, /* 0x0019 */ - GST_OP_DIC, /* 0x001a */ - GST_OP_TCL, /* 0x001b */ - GST_OP_RTN, /* 0x0020 */ - GST_OP_SET, /* 0x0021 */ - GST_OP_GET, /* 0x0022 */ - GST_OP_ERR, /* 0x0023 */ - GST_OP_TRY, /* 0x0024 */ - GST_OP_UTY /* 0x0025 */ + GST_OP_ADD = 0, /* Addition */ + GST_OP_SUB, /* Subtraction */ + GST_OP_MUL, /* Multiplication */ + GST_OP_DIV, /* Division */ + GST_OP_MOD, /* Modulo division */ + GST_OP_EXP, /* Exponentiation */ + GST_OP_CCT, /* Concatenation */ + GST_OP_NOT, /* Invert */ + GST_OP_LEN, /* Length */ + GST_OP_TYP, /* Type */ + GST_OP_FLS, + GST_OP_TRU, + GST_OP_NIL, + GST_OP_I16, + GST_OP_UPV, + GST_OP_JIF, + GST_OP_JMP, + GST_OP_CAL, + GST_OP_RET, + GST_OP_SUV, + GST_OP_CST, + GST_OP_I32, + GST_OP_F64, + GST_OP_MOV, + GST_OP_CLN, + GST_OP_EQL, + GST_OP_LTN, + GST_OP_LTE, + GST_OP_ARR, + GST_OP_DIC, + GST_OP_TCL, + GST_OP_RTN, + GST_OP_SET, + GST_OP_GET, + GST_OP_ERR, + GST_OP_TRY, + GST_OP_UTY }; #endif diff --git a/dict.c b/dict.c new file mode 100644 index 00000000..ae6c3ded --- /dev/null +++ b/dict.c @@ -0,0 +1,147 @@ +#include "datatypes.h" +#include "util.h" +#include "value.h" + +#define GST_DICT_FLAG_OCCUPIED 1 +#define GST_DICT_FLAG_TOMBSTONE 2 + +typedef struct GstDictBucket GstDictBucket; +struct GstDictBucket { + GstValue key; + GstValue value; + uint8_t flags; +}; + +typedef struct GstDict GstDict; +struct GstDict { + uint32_t capacity; + uint32_t count; + GstDictBucket *buckets; +}; + +/* Initialize a dictionary */ +GstDict *gst_dict_init(GstDict *dict, uint32_t capacity) { + GstDictBucket *buckets = gst_raw_calloc(1, sizeof(GstDictBucket) * capacity); + if (data == NULL) + return NULL; + dict->buckets = buckets; + dict->capacity = capacity; + dict->count = 0; + return dict; +} + +/* Deinitialize a dictionary */ +GstDict *gst_dict_free(GstDict *dict) { + gst_raw_free(dict->buckets); +} + +/* Rehash a dictionary */ +GstDict *gst_dict_rehash(GstDict *dict, uint32_t newCapacity) { + GstDictBucket *newBuckets = gst_raw_calloc(1, sizeof(GstDictBucket) * newCapacity); + GstDictBucket *buckets = dict->buckets; + uint32_t i, j; + if (newBuckets == NULL) + return NULL; + for (i = 0; i < dict->capacity; ++i) { + int index; + if (!(buckets[i].flags & GST_DICT_FLAG_OCCUPIED)) continue; + if (buckets[i].flags & GST_DICT_FLAG_TOMBSTONE) continue; + index = gst_hash(buckets[i].key) % newCapacity; + for (j = index; j < dict->capacity; ++j) { + if (newBuckets[j].flags & GST_DICT_FLAG_OCCUPIED) continue; + newBuckets[j] = buckets[i]; + goto done; + } + for (j = 0; j < index; ++j) { + if (newBuckets[j].flags & GST_DICT_FLAG_OCCUPIED) continue; + newBuckets[j] = buckets[i]; + goto done; + } + /* Error - could not rehash a bucket - this should never happen */ + gst_raw_free(newBuckets); + return NULL; + /* Successfully rehashed bucket */ + done: + } + dict->capacity = newCapacity; + return dict; +} + +/* Find a bucket with a given key */ +static int gst_dict_find(GstDict *dict, GstValue key, GstDictBucket **out) { + uint32_t index, i; + GstDictBucket *buckets = dict->buckets; + index = gst_hash(key) % dict->capacity; + for (i = index; i < dict->capacity; ++i) { + if (buckets[i].flags & GST_DICT_FLAGS_TOMBSTONE) continue; + if (!(buckets[i].flags & GST_DICT_FLAGS_OCCUPIED)) continue; + if (!gst_equals(key, buckets[i].key)) continue; + *out = buckets + i; + return 1; + } + for (i = 0; i < index; ++i) { + if (buckets[i].flags & GST_DICT_FLAGS_TOMBSTONE) continue; + if (!(buckets[i].flags & GST_DICT_FLAGS_OCCUPIED)) continue; + if (!gst_equals(key, buckets[i].key)) continue; + *out = buckets + i; + return 1; + } + return 0; +} + +/* Get item from dictionary */ +int gst_dict_get(GstDict *dict, GstValue key, GstValue *value) { + GstDictBucket *bucket; + int found = gst_dict_find(dict, key, &bucket); + if (found) + *value = bucket->value; + return found; +} + +/* Add item to dictionary */ +GstDict *gst_dict_put(GstDict *dict, GstValue key, GstValue value) { +i /* Check if we need to increase capacity. The load factor is low + * because we are using linear probing */ + uint32_t index, i; + uint32_t newCap = dict->count * 2 + 1; + GstBucket *buckets; + if (newCap > dict->capacity) { + dict = gst_dict_rehash(dict, newCap); + if (!dict) return dict; + } + index = gst_hash(key) % dict->capacity; + buckets = dict->buckets; + for (i = index; i < dict->capacity; ++i) { + if ((buckets[i].flags & GST_DICT_FLAGS_TOMBSTONE) || + !(buckets[i].flags & GST_DICT_FLAGS_OCCUPIED)) + continue; + dict->buckets[i].key = key; + dict->buckets[i].value = value; + dict->buckets[i].flags &= GST_DICT_FLAGS_OCCUPIED; + dict->count++; + return dict; + } + for (i = 0; i < index; ++i) { + if ((buckets[i].flags & GST_DICT_FLAGS_TOMBSTONE) || + !(buckets[i].flags & GST_DICT_FLAGS_OCCUPIED)) + continue; + dict->buckets[i].key = key; + dict->buckets[i].value = value; + dict->buckets[i].flags &= GST_DICT_FLAGS_OCCUPIED; + dict->count++; + return dict; + } + /* Error should never get here */ + return NULL; +} + +/* Remove item from dictionary */ +int gst_dict_remove(GstDict *dict, GstValue key) { + GstDictBucket *bucket; + int found = gst_dict_find(dict, key, &bucket); + if (found) { + bucket->flags |= GST_DICT_FLAGS_TOMBSTONE; + dict->count--; + } + return found; +} diff --git a/disasm.c b/disasm.c index d66bed2b..5c9947ed 100644 --- a/disasm.c +++ b/disasm.c @@ -10,196 +10,193 @@ static void dasm_print_i32(FILE * out, int32_t number) { fprintf(out, "#%d ", nu static void dasm_print_f64(FILE * out, double number) { fprintf(out, "#%f ", number); } static void dasm_print_literal(FILE * out, uint16_t index) { fprintf(out, "(%d) ", index); } static void dasm_print_upvalue(FILE * out, uint16_t level, uint16_t index) { - fprintf(out, "<%d, %d> ", level, index); + fprintf(out, "<%d, %d> ", level, index); } /* Print the name of the argument but pad it */ static void dasm_print_arg(FILE * out, const char * name) { - uint32_t i = 0; - char c; - while ((c = *name++)) { - putc(c, out); - ++i; - } - for (; i < OP_WIDTH; ++i) - fputc(' ', out); + uint32_t i = 0; + char c; + while ((c = *name++)) { + putc(c, out); + ++i; + } + for (; i < OP_WIDTH; ++i) + fputc(' ', out); } /* Print instructions that take a fixed number of arguments */ static uint32_t dasm_fixed_op(FILE * out, const uint16_t * current, - const char * name, uint32_t size) { - uint32_t i; - dasm_print_arg(out, name); - for (i = 1; i <= size; ++i) - dasm_print_slot(out, current[i]); - return size + 1; + const char * name, uint32_t size) { + uint32_t i; + dasm_print_arg(out, name); + for (i = 1; i <= size; ++i) + dasm_print_slot(out, current[i]); + return size + 1; } /* Print instructions that take a variable number of arguments */ static uint32_t dasm_varg_op(FILE * out, const uint16_t * current, - const char * name, uint32_t extra) { - uint32_t i, argCount; - dasm_print_arg(out, name); - for (i = 0; i < extra; ++i) { - dasm_print_slot(out, current[i + 1]); - } - argCount = current[extra + 1]; - fprintf(out, ": "); /* Argument separator */ - for (i = 0; i < argCount; ++i) { - dasm_print_slot(out, current[i + extra + 2]); - } - return argCount + extra + 2; + const char * name, uint32_t extra) { + uint32_t i, argCount; + dasm_print_arg(out, name); + for (i = 0; i < extra; ++i) { + dasm_print_slot(out, current[i + 1]); + } + argCount = current[extra + 1]; + fprintf(out, ": "); /* Argument separator */ + for (i = 0; i < argCount; ++i) { + dasm_print_slot(out, current[i + extra + 2]); + } + return argCount + extra + 2; } /* Print the disassembly for a function definition */ void gst_dasm_funcdef(FILE * out, GstFuncDef * def) { - gst_dasm(out, def->byteCode, def->byteCodeLen); + gst_dasm(out, def->byteCode, def->byteCodeLen); } /* Print the disassembly for a function */ void gst_dasm_function(FILE * out, GstFunction * f) { - gst_dasm(out, f->def->byteCode, f->def->byteCodeLen); + gst_dasm(out, f->def->byteCode, f->def->byteCodeLen); } /* Disassemble some bytecode and display it as opcode + arguments assembly */ void gst_dasm(FILE * out, uint16_t *byteCode, uint32_t len) { - uint16_t *current = byteCode; - uint16_t *end = byteCode + len; + uint16_t *current = byteCode; + uint16_t *end = byteCode + len; - while (current < end) { - switch (*current) { - case GST_OP_ADD: - current += dasm_fixed_op(out, current, "add", 3); - break; - case GST_OP_SUB: - current += dasm_fixed_op(out, current, "sub", 3); - break; - case GST_OP_MUL: - current += dasm_fixed_op(out, current, "mul", 3); - break; - case GST_OP_DIV: - current += dasm_fixed_op(out, current, "div", 3); - break; - case GST_OP_NOT: - current += dasm_fixed_op(out, current, "not", 2); - break; - case GST_OP_LD0: - current += dasm_fixed_op(out, current, "load0", 1); - break; - case GST_OP_LD1: - current += dasm_fixed_op(out, current, "load1", 1); - break; - case GST_OP_FLS: - current += dasm_fixed_op(out, current, "loadFalse", 1); - break; - case GST_OP_TRU: - current += dasm_fixed_op(out, current, "loadTrue", 1); - break; - case GST_OP_NIL: - current += dasm_fixed_op(out, current, "loadNil", 1); - break; - case GST_OP_I16: - dasm_print_arg(out, "loadInt16"); - dasm_print_slot(out, current[1]); - dasm_print_i16(out, ((int16_t *)current)[2]); - current += 3; - break; - case GST_OP_UPV: - dasm_print_arg(out, "loadUpValue"); - dasm_print_slot(out, current[1]); - dasm_print_upvalue(out, current[2], current[3]); - current += 4; - break; - case GST_OP_JIF: - dasm_print_arg(out, "jumpIf"); - dasm_print_slot(out, current[1]); - dasm_print_i32(out, ((int32_t *)(current + 2))[0]); - current += 4; - break; - case GST_OP_JMP: - dasm_print_arg(out, "jump"); - dasm_print_i32(out, ((int32_t *)(current + 1))[0]); - current += 3; - break; - case GST_OP_CAL: - current += dasm_varg_op(out, current, "call", 2); - break; - case GST_OP_RET: - current += dasm_fixed_op(out, current, "return", 1); - break; - case GST_OP_SUV: - dasm_print_arg(out, "setUpValue"); - dasm_print_slot(out, current[1]); - dasm_print_upvalue(out, current[2], current[3]); - current += 4; - break; - case GST_OP_CST: - dasm_print_arg(out, "loadLiteral"); - dasm_print_slot(out, current[1]); - dasm_print_literal(out, current[2]); - current += 3; - break; - case GST_OP_I32: - dasm_print_arg(out, "loadInt32"); - dasm_print_slot(out, current[1]); - dasm_print_i32(out, ((int32_t *)(current + 2))[0]); - current += 4; - break; - case GST_OP_F64: - dasm_print_arg(out, "loadFloat64"); - dasm_print_slot(out, current[1]); - dasm_print_f64(out, ((double *)(current + 2))[0]); - current += 6; - break; - case GST_OP_MOV: - current += dasm_fixed_op(out, current, "move", 2); - break; - case GST_OP_CLN: - dasm_print_arg(out, "makeClosure"); - dasm_print_slot(out, current[1]); - dasm_print_literal(out, current[2]); - current += 3; - break; - case GST_OP_EQL: - current += dasm_fixed_op(out, current, "equals", 3); - break; - case GST_OP_LTN: - current += dasm_fixed_op(out, current, "lessThan", 3); - break; - case GST_OP_LTE: - current += dasm_fixed_op(out, current, "lessThanEquals", 3); - break; - case GST_OP_ARR: - current += dasm_varg_op(out, current, "array", 1); - break; - case GST_OP_DIC: - current += dasm_varg_op(out, current, "object", 1); - break; - case GST_OP_TCL: - current += dasm_varg_op(out, current, "tailCall", 1); - break; - case GST_OP_RTN: - current += dasm_fixed_op(out, current, "returnNil", 0); - break; - case GST_OP_GET: - current += dasm_fixed_op(out, current, "get", 3); - break; - case GST_OP_SET: - current += dasm_fixed_op(out, current, "set", 3); - break; - case GST_OP_ERR: - current += dasm_fixed_op(out, current, "error", 1); - break; - case GST_OP_TRY: - dasm_print_arg(out, "try"); - dasm_print_slot(out, current[1]); - dasm_print_i32(out, *(int32_t *)(current + 2)); - current += 4; - break; - case GST_OP_UTY: - current += dasm_fixed_op(out, current, "untry", 0); - break; + while (current < end) { + switch (*current) { + default: + current += dasm_fixed_op(out, current, "unknown", 0); + break; + case GST_OP_ADD: + current += dasm_fixed_op(out, current, "add", 3); + break; + case GST_OP_SUB: + current += dasm_fixed_op(out, current, "sub", 3); + break; + case GST_OP_MUL: + current += dasm_fixed_op(out, current, "mul", 3); + break; + case GST_OP_DIV: + current += dasm_fixed_op(out, current, "div", 3); + break; + case GST_OP_NOT: + current += dasm_fixed_op(out, current, "not", 2); + break; + case GST_OP_FLS: + current += dasm_fixed_op(out, current, "loadFalse", 1); + break; + case GST_OP_TRU: + current += dasm_fixed_op(out, current, "loadTrue", 1); + break; + case GST_OP_NIL: + current += dasm_fixed_op(out, current, "loadNil", 1); + break; + case GST_OP_I16: + dasm_print_arg(out, "loadInt16"); + dasm_print_slot(out, current[1]); + dasm_print_i16(out, ((int16_t *)current)[2]); + current += 3; + break; + case GST_OP_UPV: + dasm_print_arg(out, "loadUpValue"); + dasm_print_slot(out, current[1]); + dasm_print_upvalue(out, current[2], current[3]); + current += 4; + break; + case GST_OP_JIF: + dasm_print_arg(out, "jumpIf"); + dasm_print_slot(out, current[1]); + dasm_print_i32(out, ((int32_t *)(current + 2))[0]); + current += 4; + break; + case GST_OP_JMP: + dasm_print_arg(out, "jump"); + dasm_print_i32(out, ((int32_t *)(current + 1))[0]); + current += 3; + break; + case GST_OP_CAL: + current += dasm_varg_op(out, current, "call", 2); + break; + case GST_OP_RET: + current += dasm_fixed_op(out, current, "return", 1); + break; + case GST_OP_SUV: + dasm_print_arg(out, "setUpValue"); + dasm_print_slot(out, current[1]); + dasm_print_upvalue(out, current[2], current[3]); + current += 4; + break; + case GST_OP_CST: + dasm_print_arg(out, "loadLiteral"); + dasm_print_slot(out, current[1]); + dasm_print_literal(out, current[2]); + current += 3; + break; + case GST_OP_I32: + dasm_print_arg(out, "loadInt32"); + dasm_print_slot(out, current[1]); + dasm_print_i32(out, ((int32_t *)(current + 2))[0]); + current += 4; + break; + case GST_OP_F64: + dasm_print_arg(out, "loadFloat64"); + dasm_print_slot(out, current[1]); + dasm_print_f64(out, ((double *)(current + 2))[0]); + current += 6; + break; + case GST_OP_MOV: + current += dasm_fixed_op(out, current, "move", 2); + break; + case GST_OP_CLN: + dasm_print_arg(out, "makeClosure"); + dasm_print_slot(out, current[1]); + dasm_print_literal(out, current[2]); + current += 3; + break; + case GST_OP_EQL: + current += dasm_fixed_op(out, current, "equals", 3); + break; + case GST_OP_LTN: + current += dasm_fixed_op(out, current, "lessThan", 3); + break; + case GST_OP_LTE: + current += dasm_fixed_op(out, current, "lessThanEquals", 3); + break; + case GST_OP_ARR: + current += dasm_varg_op(out, current, "array", 1); + break; + case GST_OP_DIC: + current += dasm_varg_op(out, current, "object", 1); + break; + case GST_OP_TCL: + current += dasm_varg_op(out, current, "tailCall", 1); + break; + case GST_OP_RTN: + current += dasm_fixed_op(out, current, "returnNil", 0); + break; + case GST_OP_GET: + current += dasm_fixed_op(out, current, "get", 3); + break; + case GST_OP_SET: + current += dasm_fixed_op(out, current, "set", 3); + break; + case GST_OP_ERR: + current += dasm_fixed_op(out, current, "error", 1); + break; + case GST_OP_TRY: + dasm_print_arg(out, "try"); + dasm_print_slot(out, current[1]); + dasm_print_i32(out, *(int32_t *)(current + 2)); + current += 4; + break; + case GST_OP_UTY: + current += dasm_fixed_op(out, current, "untry", 0); + break; + } + fprintf(out, "\n"); } - fprintf(out, "\n"); - } } diff --git a/ds.c b/ds.c index 690c926e..67132226 100644 --- a/ds.c +++ b/ds.c @@ -1,7 +1,7 @@ +#include "util.h" #include "ds.h" #include "value.h" #include "vm.h" -#include /****/ /* Buffer functions */ @@ -23,7 +23,7 @@ void gst_buffer_ensure(Gst *vm, GstBuffer *buffer, uint32_t capacity) { uint8_t * newData; if (capacity <= buffer->capacity) return; newData = gst_alloc(vm, capacity * sizeof(uint8_t)); - memcpy(newData, buffer->data, buffer->count * sizeof(uint8_t)); + gst_memcpy(newData, buffer->data, buffer->count * sizeof(uint8_t)); buffer->data = newData; buffer->capacity = capacity; } @@ -51,7 +51,7 @@ void gst_buffer_append(Gst *vm, GstBuffer *buffer, uint8_t *string, uint32_t len if (newSize > buffer->capacity) { gst_buffer_ensure(vm, buffer, 2 * newSize); } - memcpy(buffer->data + buffer->count, string, length); + gst_memcpy(buffer->data + buffer->count, string, length); buffer->count = newSize; } @@ -61,7 +61,7 @@ uint8_t *gst_buffer_to_string(Gst *vm, GstBuffer *buffer) { data += 2 * sizeof(uint32_t); gst_string_length(data) = buffer->count; gst_string_hash(data) = 0; - memcpy(data, buffer->data, buffer->count * sizeof(uint8_t)); + gst_memcpy(data, buffer->data, buffer->count * sizeof(uint8_t)); return data; } @@ -85,7 +85,7 @@ void gst_array_ensure(Gst *vm, GstArray *array, uint32_t capacity) { GstValue *newData; if (capacity <= array->capacity) return; newData = gst_alloc(vm, capacity * sizeof(GstValue)); - memcpy(newData, array->data, array->capacity * sizeof(GstValue)); + gst_memcpy(newData, array->data, array->capacity * sizeof(GstValue)); array->data = newData; array->capacity = capacity; } diff --git a/gc.c b/gc.c index 2546861a..90dd1aca 100644 --- a/gc.c +++ b/gc.c @@ -1,7 +1,7 @@ #include "datatypes.h" #include "gc.h" #include "vm.h" -#include +#include "util.h" /* The metadata header associated with an allocated block of memory */ #define gc_header(mem) ((GCMemoryHeader *)(mem) - 1) @@ -160,7 +160,7 @@ void gst_sweep(Gst *vm) { } else { vm->blocks = next; } - free(current); + gst_raw_free(current); } else { previous = current; } @@ -187,13 +187,13 @@ static void *gst_alloc_prepare(Gst *vm, char *rawBlock, uint32_t size) { /* Allocate some memory that is tracked for garbage collection */ void *gst_alloc(Gst *vm, uint32_t size) { uint32_t totalSize = size + sizeof(GCMemoryHeader); - return gst_alloc_prepare(vm, malloc(totalSize), totalSize); + return gst_alloc_prepare(vm, gst_raw_alloc(totalSize), totalSize); } /* Allocate some zeroed memory that is tracked for garbage collection */ void *gst_zalloc(Gst *vm, uint32_t size) { uint32_t totalSize = size + sizeof(GCMemoryHeader); - return gst_alloc_prepare(vm, calloc(1, totalSize), totalSize); + return gst_alloc_prepare(vm, gst_raw_calloc(1, totalSize), totalSize); } /* Run garbage collection */ @@ -222,8 +222,8 @@ void gst_clear_memory(Gst *vm) { GCMemoryHeader *current = vm->blocks; while (current) { GCMemoryHeader *next = current->next; - free(current); + gst_raw_free(current); current = next; } vm->blocks = NULL; -} \ No newline at end of file +} diff --git a/parse.c b/parse.c index 33910e6e..17c2b074 100644 --- a/parse.c +++ b/parse.c @@ -1,7 +1,4 @@ -#include -#include -#include -#include +#include "util.h" #include "datatypes.h" #include "ds.h" #include "parse.h" diff --git a/parser.c b/parser.c new file mode 100644 index 00000000..c0db9446 --- /dev/null +++ b/parser.c @@ -0,0 +1 @@ +#include "datatypes.h" diff --git a/util.h b/util.h new file mode 100644 index 00000000..231d5ca7 --- /dev/null +++ b/util.h @@ -0,0 +1,34 @@ +#ifndef util_h_INCLUDED +#define util_h_INCLUDED + +/* Memcpy for moving memory */ +#ifndef gst_memcpy +#include +#define gst_memcpy memcpy +#endif + +/* Allocation */ +#ifndef gst_raw_alloc +#include +#define gst_raw_alloc malloc +#endif + +/* Clear allocation */ +#ifndef gst_raw_calloc +#include +#define gst_raw_calloc calloc +#endif + +/* Free */ +#ifndef gst_raw_free +#include +#define gst_raw_free free +#endif + +/* Null */ +#ifndef NULL +#define NULL ((void *)0) +#endif + +#endif // util_h_INCLUDED + diff --git a/value.c b/value.c index af72c915..0819620c 100644 --- a/value.c +++ b/value.c @@ -1,9 +1,8 @@ -#include -#include -#include +#include "util.h" #include "value.h" #include "ds.h" #include "vm.h" +#include /* Boolean truth definition */ int gst_truthy(GstValue v) { @@ -15,7 +14,7 @@ static uint8_t * load_cstring(Gst *vm, const char *string, uint32_t len) { data += 2 * sizeof(uint32_t); gst_string_hash(data) = 0; gst_string_length(data) = len; - memcpy(data, string, len); + gst_memcpy(data, string, len); return data; } @@ -30,6 +29,7 @@ static uint8_t * number_to_string(Gst *vm, GstNumber x) { static const uint32_t SIZE = 20; uint8_t *data = gst_alloc(vm, SIZE + 2 * sizeof(uint32_t)); data += 2 * sizeof(uint32_t); + /* TODO - not depend on stdio */ snprintf((char *) data, SIZE, "%.17g", x); gst_string_hash(data) = 0; gst_string_length(data) = strlen((char *) data); @@ -349,4 +349,4 @@ void gst_set(Gst *vm, GstValue ds, GstValue key, GstValue value) { default: gst_error(vm, "Cannot set."); } -} \ No newline at end of file +} diff --git a/vm.c b/vm.c index 3adb3925..65a772db 100644 --- a/vm.c +++ b/vm.c @@ -1,7 +1,5 @@ -#include -#include -#include #include "vm.h" +#include "util.h" #include "value.h" #include "ds.h" #include "gc.h" @@ -51,7 +49,7 @@ int gst_start(Gst *vm) { frame.env->thread = NULL; frame.env->stackOffset = frame.size; frame.env->values = gst_alloc(vm, sizeof(GstValue) * frame.size); - memcpy(frame.env->values, + gst_memcpy(frame.env->values, thread.data + thread.count, frame.size * sizeof(GstValue)); } @@ -112,20 +110,6 @@ int gst_start(Gst *vm) { pc += 3; break; - case GST_OP_LD0: /* Load 0 */ - temp.type = GST_NUMBER; - temp.data.number = 0; - stack[pc[1]] = temp; - pc += 2; - break; - - case GST_OP_LD1: /* Load 1 */ - temp.type = GST_NUMBER; - temp.data.number = 1; - stack[pc[1]] = temp; - pc += 2; - break; - case GST_OP_FLS: /* Load False */ temp.type = GST_BOOLEAN; temp.data.boolean = 0; @@ -224,7 +208,7 @@ int gst_start(Gst *vm) { if (nextCount + locals > thread.capacity) { uint32_t newCap = (nextCount + locals) * 2; GstValue *newData = gst_alloc(vm, sizeof(GstValue) * newCap); - memcpy(newData, thread.data, thread.capacity * sizeof(GstValue)); + gst_memcpy(newData, thread.data, thread.capacity * sizeof(GstValue)); thread.data = newData; thread.capacity = newCap; } @@ -388,7 +372,7 @@ int gst_start(Gst *vm) { frame.env->thread = NULL; frame.env->stackOffset = frame.size; frame.env->values = gst_alloc(vm, sizeof(GstValue) * frame.size); - memcpy(frame.env->values, + gst_memcpy(frame.env->values, thread.data + thread.count, frame.size * sizeof(GstValue)); frame.env = NULL; @@ -415,7 +399,7 @@ int gst_start(Gst *vm) { if (totalCapacity > thread.capacity) { uint32_t newCap = totalCapacity * 2; GstValue *newData = gst_alloc(vm, sizeof(GstValue) * newCap); - memcpy(newData, thread.data, thread.capacity * sizeof(GstValue)); + gst_memcpy(newData, thread.data, thread.capacity * sizeof(GstValue)); thread.data = newData; thread.capacity = newCap; stack = thread.data + thread.count; @@ -426,7 +410,7 @@ int gst_start(Gst *vm) { stack[workspace + i] = stack[pc[3 + i]]; /* Copy the end of the stack to the parameter position */ - memcpy(stack, stack + workspace, arity * sizeof(GstValue)); + gst_memcpy(stack, stack + workspace, arity * sizeof(GstValue)); /* Update the stack frame */ frame.callee = temp; @@ -492,7 +476,7 @@ int gst_start(Gst *vm) { frame.env->thread = NULL; frame.env->stackOffset = frame.size; frame.env->values = gst_alloc(vm, sizeof(GstValue) * frame.size); - memcpy(frame.env->values, + gst_memcpy(frame.env->values, thread.data + thread.count, frame.size * sizeof(GstValue)); }