Modify some files. Also begin open addressing hash

dictionary for use in compiler. Might also move normal
object to open addressing for less pressure on gc.
This commit is contained in:
Calvin Rose 2017-02-28 20:20:29 -05:00
parent 08319e62cb
commit 7cdf33eb90
12 changed files with 424 additions and 261 deletions

View File

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

View File

@ -2,7 +2,7 @@
#include "ds.h"
#include "value.h"
#include "vm.h"
#include <string.h>
#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;
}

View File

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

147
dict.c Normal file
View File

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

329
disasm.c
View File

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

10
ds.c
View File

@ -1,7 +1,7 @@
#include "util.h"
#include "ds.h"
#include "value.h"
#include "vm.h"
#include <string.h>
/****/
/* 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;
}

12
gc.c
View File

@ -1,7 +1,7 @@
#include "datatypes.h"
#include "gc.h"
#include "vm.h"
#include <stdlib.h>
#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;
}
}

View File

@ -1,7 +1,4 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <setjmp.h>
#include "util.h"
#include "datatypes.h"
#include "ds.h"
#include "parse.h"

1
parser.c Normal file
View File

@ -0,0 +1 @@
#include "datatypes.h"

34
util.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef util_h_INCLUDED
#define util_h_INCLUDED
/* Memcpy for moving memory */
#ifndef gst_memcpy
#include <string.h>
#define gst_memcpy memcpy
#endif
/* Allocation */
#ifndef gst_raw_alloc
#include <stdlib.h>
#define gst_raw_alloc malloc
#endif
/* Clear allocation */
#ifndef gst_raw_calloc
#include <stdlib.h>
#define gst_raw_calloc calloc
#endif
/* Free */
#ifndef gst_raw_free
#include <stdlib.h>
#define gst_raw_free free
#endif
/* Null */
#ifndef NULL
#define NULL ((void *)0)
#endif
#endif // util_h_INCLUDED

10
value.c
View File

@ -1,9 +1,8 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "util.h"
#include "value.h"
#include "ds.h"
#include "vm.h"
#include <stdio.h>
/* 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.");
}
}
}

30
vm.c
View File

@ -1,7 +1,5 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#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));
}