From 6677dff337f07d921c5c3b3995afe1269a407b95 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Wed, 15 Feb 2017 21:02:00 -0500 Subject: [PATCH] Rename everything to be prefixed with gst. No particluar meaning or reason for that name, but its available and it irked me to see non prefixed c code for something that is supposed to be emeddable. --- compile.c | 826 ++++++++++++++++++++++++++-------------------------- compile.h | 10 +- datatypes.h | 313 ++++++++++---------- disasm.c | 212 +++++++------- disasm.h | 6 +- ds.c | 203 ++++++------- ds.h | 52 ++-- main.c | 46 ++- parse.c | 199 +++++++------ parse.h | 10 +- value.c | 251 ++++++++-------- value.h | 23 +- vm.c | 642 ++++++++++++++++++++-------------------- vm.h | 36 +-- 14 files changed, 1407 insertions(+), 1422 deletions(-) diff --git a/compile.c b/compile.c index 22aac974..295cc140 100644 --- a/compile.c +++ b/compile.c @@ -17,7 +17,7 @@ struct FormOptions { uint16_t resultUnused : 1; /* Allows the sub expression to evaluate into a * temporary slot of it's choice. A temporary Slot - * can be allocated with CompilerGetLocal. */ + * can be allocated with GstCompilerGetLocal. */ uint16_t canChoose : 1; /* True if the form is in the tail position. This allows * for tail call optimization. If a helper receives this @@ -50,31 +50,31 @@ struct Slot { * Slots on the stack and free them in bulk. */ typedef struct SlotTracker SlotTracker; struct SlotTracker { - Slot * slots; + Slot *slots; uint32_t count; uint32_t capacity; }; -/* A Scope is a lexical scope in the program. It is +/* A GstScope is a lexical scope in the program. It is * responsible for aliasing programmer facing names to * Slots and for keeping track of literals. It also - * points to the parent Scope, and its current child - * Scope. */ -struct Scope { + * points to the parent GstScope, and its current child + * GstScope. */ +struct GstScope { uint32_t level; uint16_t nextLocal; uint16_t frameSize; uint32_t heapCapacity; uint32_t heapSize; - uint16_t * freeHeap; - Dictionary * literals; - Array * literalsArray; - Dictionary * locals; - Scope * parent; + uint16_t *freeHeap; + GstObject *literals; + GstArray *literalsArray; + GstObject *locals; + GstScope *parent; }; /* Provides default FormOptions */ -static FormOptions FormOptionsDefault() { +static FormOptions form_options_default() { FormOptions opts; opts.canChoose = 1; opts.isTail = 0; @@ -86,15 +86,15 @@ static FormOptions FormOptionsDefault() { /* Create some helpers that allows us to push more than just raw bytes * to the byte buffer. This helps us create the byte code for the compiled * functions. */ -BufferDefine(UInt32, uint32_t) -BufferDefine(Int32, int32_t) -BufferDefine(Number, Number) -BufferDefine(UInt16, uint16_t) -BufferDefine(Int16, int16_t) +BUFFER_DEFINE(u32, uint32_t) +BUFFER_DEFINE(i32, int32_t) +BUFFER_DEFINE(number, GstNumber) +BUFFER_DEFINE(u16, uint16_t) +BUFFER_DEFINE(i16, int16_t) /* If there is an error during compilation, * jump back to start */ -static void CError(Compiler * c, const char * e) { +static void c_error(GstCompiler *c, const char *e) { c->error = e; longjmp(c->onError, 1); } @@ -103,10 +103,10 @@ static void CError(Compiler * c, const char * e) { * a pointer to it for configuration. There is * more configuration that needs to be done if * the new scope is a function declaration. */ -static Scope * CompilerPushScope(Compiler * c, int sameFunction) { - Scope * scope = VMAlloc(c->vm, sizeof(Scope)); - scope->locals = DictNew(c->vm, 10); - scope->freeHeap = VMAlloc(c->vm, 10 * sizeof(uint16_t)); +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->freeHeap = gst_alloc(c->vm, 10 * sizeof(uint16_t)); scope->heapSize = 0; scope->heapCapacity = 10; scope->parent = c->tail; @@ -118,25 +118,25 @@ static Scope * CompilerPushScope(Compiler * c, int sameFunction) { } if (sameFunction) { if (!c->tail) { - CError(c, "Cannot inherit scope when root scope"); + c_error(c, "Cannot inherit scope when root scope"); } scope->nextLocal = c->tail->nextLocal; scope->literals = c->tail->literals; scope->literalsArray = c->tail->literalsArray; } else { scope->nextLocal = 0; - scope->literals = DictNew(c->vm, 10); - scope->literalsArray = ArrayNew(c->vm, 10); + scope->literals = gst_object(c->vm, 10); + scope->literalsArray = gst_array(c->vm, 10); } c->tail = scope; return scope; } /* Remove the inner most scope from the compiler stack */ -static void CompilerPopScope(Compiler * c) { - Scope * last = c->tail; +static void compiler_pop_scope(GstCompiler *c) { + GstScope *last = c->tail; if (last == NULL) { - CError(c, "No scope to pop."); + c_error(c, "No scope to pop."); } else { if (last->nextLocal > last->frameSize) { last->frameSize = last->nextLocal; @@ -152,10 +152,10 @@ static void CompilerPopScope(Compiler * c) { /* Get the next stack position that is open for * a variable */ -static uint16_t CompilerGetLocal(Compiler * c, Scope * scope) { +static uint16_t compiler_get_local(GstCompiler *c, GstScope *scope) { if (scope->heapSize == 0) { if (scope->nextLocal + 1 == 0) { - CError(c, "Too many local variables. Try splitting up your functions :)"); + c_error(c, "Too many local variables. Try splitting up your functions :)"); } return scope->nextLocal++; } else { @@ -166,11 +166,11 @@ static uint16_t CompilerGetLocal(Compiler * c, Scope * scope) { /* Free a slot on the stack for other locals and/or * intermediate values */ -static void CompilerFreeLocal(Compiler * c, Scope * scope, uint16_t slot) { +static void compiler_free_local(GstCompiler *c, GstScope *scope, uint16_t slot) { /* Ensure heap has space */ if (scope->heapSize >= scope->heapCapacity) { uint32_t newCap = 2 * scope->heapSize; - uint16_t * newData = VMAlloc(c->vm, newCap * sizeof(uint16_t)); + uint16_t *newData = gst_alloc(c->vm, newCap * sizeof(uint16_t)); memcpy(newData, scope->freeHeap, scope->heapSize * sizeof(uint16_t)); scope->freeHeap = newData; scope->heapCapacity = newCap; @@ -181,8 +181,8 @@ static void CompilerFreeLocal(Compiler * c, Scope * scope, uint16_t slot) { /* Initializes a SlotTracker. SlotTrackers * are used during compilation to free up slots on the stack * after they are no longer needed. */ -static void CompilerTrackerInit(Compiler * c, SlotTracker * tracker) { - tracker->slots = VMAlloc(c->vm, 10 * sizeof(Slot)); +static void tracker_init(GstCompiler *c, SlotTracker *tracker) { + tracker->slots = gst_alloc(c->vm, 10 * sizeof(Slot)); tracker->count = 0; tracker->capacity = 10; } @@ -190,16 +190,16 @@ static void CompilerTrackerInit(Compiler * c, SlotTracker * tracker) { /* Free up a slot if it is a temporary slot (does not * belong to a named local). If the slot does belong * to a named variable, does nothing. */ -static void CompilerDropSlot(Compiler * c, Scope * scope, Slot slot) { +static void compiler_drop_slot(GstCompiler *c, GstScope *scope, Slot slot) { if (!slot.isNil && slot.isTemp) { - CompilerFreeLocal(c, scope, slot.index); + compiler_free_local(c, scope, slot.index); } } /* Helper function to return a slot. Useful for compiling things that return * nil. (set, while, etc.). Use this to wrap compilation calls that need * to return things. */ -static Slot CompilerReturn(Compiler * c, Slot slot) { +static Slot compiler_return(GstCompiler *c, Slot slot) { Slot ret; ret.hasReturned = 1; ret.isNil = 1; @@ -207,31 +207,31 @@ static Slot CompilerReturn(Compiler * c, Slot slot) { /* Do nothing */ } else if (slot.isNil) { /* Return nil */ - BufferPushUInt16(c->vm, c->buffer, VM_OP_RTN); + gst_buffer_push_u16(c->vm, c->buffer, GST_OP_RTN); } else { /* Return normal value */ - BufferPushUInt16(c->vm, c->buffer, VM_OP_RET); - BufferPushUInt16(c->vm, c->buffer, slot.index); + gst_buffer_push_u16(c->vm, c->buffer, GST_OP_RET); + gst_buffer_push_u16(c->vm, c->buffer, slot.index); } return ret; } /* Gets a temporary slot for the bottom-most scope. */ -static Slot CompilerGetTemp(Compiler * c) { - Scope * scope = c->tail; +static Slot compiler_get_temp(GstCompiler *c) { + GstScope *scope = c->tail; Slot ret; ret.isTemp = 1; ret.isNil = 0; ret.hasReturned = 0; - ret.index = CompilerGetLocal(c, scope); + ret.index = compiler_get_local(c, scope); return ret; } /* Return a slot that is the target Slot given some FormOptions. Will * Create a temporary slot if needed, so be sure to drop the slot after use. */ -static Slot CompilerGetTarget(Compiler * c, FormOptions opts) { +static Slot compiler_get_target(GstCompiler *c, FormOptions opts) { if (opts.canChoose) { - return CompilerGetTemp(c); + return compiler_get_temp(c); } else { Slot ret; ret.isTemp = 0; @@ -244,22 +244,22 @@ static Slot CompilerGetTarget(Compiler * c, FormOptions opts) { /* If a slot is a nil slot, create a slot that has * an actual location on the stack. */ -static Slot CompilerRealizeSlot(Compiler * c, Slot slot) { +static Slot compiler_realize_slot(GstCompiler *c, Slot slot) { if (slot.isNil) { - slot = CompilerGetTemp(c); - BufferPushUInt16(c->vm, c->buffer, VM_OP_NIL); - BufferPushUInt16(c->vm, c->buffer, slot.index); + slot = compiler_get_temp(c); + gst_buffer_push_u16(c->vm, c->buffer, GST_OP_NIL); + gst_buffer_push_u16(c->vm, c->buffer, slot.index); } return slot; } /* Helper to get a nil slot */ -static Slot NilSlot() { Slot ret; ret.isNil = 1; return ret; } +static Slot nil_slot() { Slot ret; ret.isNil = 1; return ret; } /* Writes all of the slots in the tracker to the compiler */ -static void CompilerTrackerWrite(Compiler * c, SlotTracker * tracker, int reverse) { +static void compiler_tracker_write(GstCompiler *c, SlotTracker *tracker, int reverse) { uint32_t i; - Buffer * buffer = c->buffer; + GstBuffer *buffer = c->buffer; for (i = 0; i < tracker->count; ++i) { Slot s; if (reverse) @@ -267,27 +267,27 @@ static void CompilerTrackerWrite(Compiler * c, SlotTracker * tracker, int revers else s = tracker->slots[i]; if (s.isNil) - CError(c, "Trying to write nil slot."); - BufferPushUInt16(c->vm, buffer, s.index); + c_error(c, "Trying to write nil slot."); + gst_buffer_push_u16(c->vm, buffer, s.index); } } /* Free the tracker after creation. This unlocks the memory * that was allocated by the GC an allows it to be collected. Also * frees slots that were tracked by this tracker in the given scope. */ -static void CompilerTrackerFree(Compiler * c, Scope * scope, SlotTracker * tracker) { +static void compiler_tracker_free(GstCompiler *c, GstScope *scope, SlotTracker *tracker) { uint32_t i; /* Free in reverse order */ for (i = tracker->count - 1; i < tracker->count; --i) { - CompilerDropSlot(c, scope, tracker->slots[i]); + compiler_drop_slot(c, scope, tracker->slots[i]); } } /* Add a new Slot to a slot tracker. */ -static void CompilerTrackerPush(Compiler * c, SlotTracker * tracker, Slot slot) { +static void compiler_tracker_push(GstCompiler *c, SlotTracker *tracker, Slot slot) { if (tracker->count >= tracker->capacity) { uint32_t newCap = 2 * tracker->count; - Slot * newData = VMAlloc(c->vm, newCap * sizeof(Slot)); + Slot *newData = gst_alloc(c->vm, newCap * sizeof(Slot)); memcpy(newData, tracker->slots, tracker->count * sizeof(Slot)); tracker->slots = newData; tracker->capacity = newCap; @@ -298,45 +298,45 @@ static void CompilerTrackerPush(Compiler * c, SlotTracker * tracker, Slot slot) /* Registers a literal in the given scope. If an equal literal is found, uses * that one instead of creating a new literal. This allows for some reuse * of things like string constants.*/ -static uint16_t CompilerAddLiteral(Compiler * c, Scope * scope, Value x) { - Value checkDup = DictGet(scope->literals, x); +static uint16_t compiler_add_literal(GstCompiler *c, GstScope *scope, GstValue x) { + GstValue checkDup = gst_object_get(scope->literals, x); uint16_t literalIndex = 0; - if (checkDup.type != TYPE_NIL) { + if (checkDup.type != GST_NIL) { /* An equal literal is already registered in the current scope */ return (uint16_t) checkDup.data.number; } else { /* Add our literal for tracking */ - Value valIndex; - valIndex.type = TYPE_NUMBER; + GstValue valIndex; + valIndex.type = GST_NUMBER; literalIndex = scope->literalsArray->count; valIndex.data.number = literalIndex; - DictPut(c->vm, scope->literals, x, valIndex); - ArrayPush(c->vm, scope->literalsArray, x); + gst_object_put(c->vm, scope->literals, x, valIndex); + gst_array_push(c->vm, scope->literalsArray, x); } return literalIndex; } /* Declare a symbol in a given scope. */ -static uint16_t CompilerDeclareSymbol(Compiler * c, Scope * scope, Value sym) { - if (sym.type != TYPE_STRING) { - CError(c, "Expected symbol"); +static uint16_t compiler_declare_symbol(GstCompiler *c, GstScope *scope, GstValue sym) { + GstValue x; + uint16_t target; + if (sym.type != GST_STRING) { + c_error(c, "Expected symbol"); } - Value x; - uint16_t target = CompilerGetLocal(c, scope); - x.type = TYPE_NUMBER; + target = compiler_get_local(c, scope); + x.type = GST_NUMBER; x.data.number = target; - DictPut(c->vm, scope->locals, sym, x); + gst_object_put(c->vm, scope->locals, sym, x); return target; } /* Try to resolve a symbol. If the symbol can be resovled, return true and * pass back the level and index by reference. */ -static int ScopeSymbolResolve(Scope * scope, Value x, - uint16_t * level, uint16_t * index) { +static int symbol_resolve(GstScope *scope, GstValue x, uint16_t *level, uint16_t *index) { uint32_t currentLevel = scope->level; while (scope) { - Value check = DictGet(scope->locals, x); - if (check.type != TYPE_NIL) { + GstValue check = gst_object_get(scope->locals, x); + if (check.type != GST_NIL) { *level = currentLevel - scope->level; *index = (uint16_t) check.data.number; return 1; @@ -349,87 +349,87 @@ static int ScopeSymbolResolve(Scope * scope, Value x, /* Forward declaration */ /* Compile a value and return it stack location after loading. * If a target > 0 is passed, the returned value must be equal - * to the targtet. If target < 0, the Compiler can choose whatever + * to the targtet. If target < 0, the GstCompiler can choose whatever * slot location it likes. If, for example, a symbol resolves to * whatever is in a given slot, it makes sense to use that location * to 'return' the value. For other expressions, like function * calls, the compiler will just pick the lowest free slot * as the location on the stack. */ -static Slot CompileValue(Compiler * c, FormOptions opts, Value x); +static Slot compile_value(GstCompiler *c, FormOptions opts, GstValue x); /* Compile a structure that evaluates to a literal value. Useful * for objects like strings, or anything else that cannot be instatiated else { break; } * from bytecode and doesn't do anything in the AST. */ -static Slot CompileLiteral(Compiler * c, FormOptions opts, Value x) { - Scope * scope = c->tail; - Buffer * buffer = c->buffer; +static Slot compile_literal(GstCompiler *c, FormOptions opts, GstValue x) { + GstScope *scope = c->tail; + GstBuffer *buffer = c->buffer; Slot ret; uint16_t literalIndex; - if (opts.resultUnused) return NilSlot(); - ret = CompilerGetTarget(c, opts); - literalIndex = CompilerAddLiteral(c, scope, x); - BufferPushUInt16(c->vm, buffer, VM_OP_CST); - BufferPushUInt16(c->vm, buffer, ret.index); - BufferPushUInt16(c->vm, buffer, literalIndex); + if (opts.resultUnused) return nil_slot(); + ret = compiler_get_target(c, opts); + literalIndex = compiler_add_literal(c, scope, x); + gst_buffer_push_u16(c->vm, buffer, GST_OP_CST); + gst_buffer_push_u16(c->vm, buffer, ret.index); + gst_buffer_push_u16(c->vm, buffer, literalIndex); return ret; } /* Compile boolean, nil, and number values. */ -static Slot CompileNonReferenceType(Compiler * c, FormOptions opts, Value x) { - Buffer * buffer = c->buffer; +static Slot compile_nonref_type(GstCompiler *c, FormOptions opts, GstValue x) { + GstBuffer *buffer = c->buffer; Slot ret; - if (opts.resultUnused) return NilSlot(); - ret = CompilerGetTarget(c, opts); - if (x.type == TYPE_NIL) { - BufferPushUInt16(c->vm, buffer, VM_OP_NIL); - BufferPushUInt16(c->vm, buffer, ret.index); - } else if (x.type == TYPE_BOOLEAN) { - BufferPushUInt16(c->vm, buffer, x.data.boolean ? VM_OP_TRU : VM_OP_FLS); - BufferPushUInt16(c->vm, buffer, ret.index); - } else if (x.type == TYPE_NUMBER) { - Number number = x.data.number; + if (opts.resultUnused) return nil_slot(); + ret = compiler_get_target(c, opts); + if (x.type == GST_NIL) { + gst_buffer_push_u16(c->vm, buffer, GST_OP_NIL); + gst_buffer_push_u16(c->vm, buffer, ret.index); + } else if (x.type == GST_BOOLEAN) { + gst_buffer_push_u16(c->vm, buffer, x.data.boolean ? GST_OP_TRU : GST_OP_FLS); + gst_buffer_push_u16(c->vm, buffer, ret.index); + } else if (x.type == GST_NUMBER) { + GstNumber number = x.data.number; int32_t int32Num = (int32_t) number; - if (number == (Number) int32Num) { + if (number == (GstNumber) int32Num) { if (int32Num <= 32767 && int32Num >= -32768) { int16_t int16Num = (int16_t) number; - BufferPushUInt16(c->vm, buffer, VM_OP_I16); - BufferPushUInt16(c->vm, buffer, ret.index); - BufferPushInt16(c->vm, buffer, int16Num); + gst_buffer_push_u16(c->vm, buffer, GST_OP_I16); + gst_buffer_push_u16(c->vm, buffer, ret.index); + gst_buffer_push_i16(c->vm, buffer, int16Num); } else { - BufferPushUInt16(c->vm, buffer, VM_OP_I32); - BufferPushUInt16(c->vm, buffer, ret.index); - BufferPushInt32(c->vm, buffer, int32Num); + gst_buffer_push_u16(c->vm, buffer, GST_OP_I32); + gst_buffer_push_u16(c->vm, buffer, ret.index); + gst_buffer_push_i32(c->vm, buffer, int32Num); } } else { - BufferPushUInt16(c->vm, buffer, VM_OP_F64); - BufferPushUInt16(c->vm, buffer, ret.index); - BufferPushNumber(c->vm, buffer, number); + gst_buffer_push_u16(c->vm, buffer, GST_OP_F64); + gst_buffer_push_u16(c->vm, buffer, ret.index); + gst_buffer_push_number(c->vm, buffer, number); } } else { - CError(c, "Expected boolean, nil, or number type."); + c_error(c, "Expected boolean, nil, or number type."); } return ret; } /* Compile a symbol. Resolves any kind of symbol. */ -static Slot CompileSymbol(Compiler * c, FormOptions opts, Value sym) { - Buffer * buffer = c->buffer; - Scope * scope = c->tail; +static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) { + GstBuffer * buffer = c->buffer; + GstScope * scope = c->tail; uint16_t index = 0; uint16_t level = 0; Slot ret; - if (opts.resultUnused) return NilSlot(); - if (!ScopeSymbolResolve(scope, sym, &level, &index)) - CError(c, "Undefined symbol"); + if (opts.resultUnused) return nil_slot(); + if (!symbol_resolve(scope, sym, &level, &index)) + c_error(c, "Undefined symbol"); if (level > 0) { /* We have an upvalue */ - ret = CompilerGetTarget(c, opts); - BufferPushUInt16(c->vm, buffer, VM_OP_UPV); - BufferPushUInt16(c->vm, buffer, ret.index); - BufferPushUInt16(c->vm, buffer, level); - BufferPushUInt16(c->vm, buffer, index); + ret = compiler_get_target(c, opts); + gst_buffer_push_u16(c->vm, buffer, GST_OP_UPV); + gst_buffer_push_u16(c->vm, buffer, ret.index); + gst_buffer_push_u16(c->vm, buffer, level); + gst_buffer_push_u16(c->vm, buffer, index); } else { /* Local variable on stack */ ret.isTemp = 0; @@ -441,9 +441,9 @@ static Slot CompileSymbol(Compiler * c, FormOptions opts, Value sym) { /* We need to move the variable. This * would occur in a simple assignment like a = b. */ ret.index = opts.target; - BufferPushUInt16(c->vm, buffer, VM_OP_MOV); - BufferPushUInt16(c->vm, buffer, ret.index); - BufferPushUInt16(c->vm, buffer, index); + gst_buffer_push_u16(c->vm, buffer, GST_OP_MOV); + gst_buffer_push_u16(c->vm, buffer, ret.index); + gst_buffer_push_u16(c->vm, buffer, index); } } return ret; @@ -452,24 +452,24 @@ static Slot CompileSymbol(Compiler * c, FormOptions opts, Value sym) { /* Compile values in an array sequentail and track the returned slots. * If the result is unused, immediately drop slots we don't need. Can * also ignore the end of an array. */ -static void CompilerTrackerInitArray(Compiler * c, FormOptions opts, - SlotTracker * tracker, Array * array, uint32_t start, uint32_t fromEnd) { - Scope * scope = c->tail; - FormOptions subOpts = FormOptionsDefault(); +static void tracker_init_array(GstCompiler *c, FormOptions opts, + SlotTracker *tracker, GstArray *array, uint32_t start, uint32_t fromEnd) { + GstScope *scope = c->tail; + FormOptions subOpts = form_options_default(); uint32_t i; /* Calculate sub flags */ subOpts.resultUnused = opts.resultUnused; /* Compile all of the arguments */ - CompilerTrackerInit(c, tracker); + tracker_init(c, tracker); /* Nothing to compile */ if (array->count <= fromEnd) return; /* Compile body of array */ for (i = start; i < (array->count - fromEnd); ++i) { - Slot slot = CompileValue(c, subOpts, array->data[i]); + Slot slot = compile_value(c, subOpts, array->data[i]); if (subOpts.resultUnused) - CompilerDropSlot(c, scope, slot); + compiler_drop_slot(c, scope, slot); else - CompilerTrackerPush(c, tracker, CompilerRealizeSlot(c, slot)); + compiler_tracker_push(c, tracker, compiler_realize_slot(c, slot)); } } @@ -484,171 +484,171 @@ static void CompilerTrackerInitArray(Compiler * c, FormOptions opts, * is unused, it's calculation can be ignored (the evaluation of * its argument is still carried out, but their results can * also be ignored). */ -static Slot CompileOperator(Compiler * c, FormOptions opts, Array * form, +static Slot compile_operator(GstCompiler *c, FormOptions opts, GstArray *form, int16_t op0, int16_t op1, int16_t op2, int16_t opn, int reverseOperands) { - Scope * scope = c->tail; - Buffer * buffer = c->buffer; + GstScope *scope = c->tail; + GstBuffer *buffer = c->buffer; Slot ret; SlotTracker tracker; /* Compile operands */ - CompilerTrackerInitArray(c, opts, &tracker, form, 1, 0); + tracker_init_array(c, opts, &tracker, form, 1, 0); /* Free up space */ - CompilerTrackerFree(c, scope, &tracker); + compiler_tracker_free(c, scope, &tracker); if (opts.resultUnused) { - ret = NilSlot(); + ret = nil_slot(); } else { - ret = CompilerGetTarget(c, opts); + ret = compiler_get_target(c, opts); /* Write the correct opcode */ if (form->count < 2) { if (op0 < 0) { - if (opn < 0) CError(c, "This operator does not take 0 arguments."); + if (opn < 0) c_error(c, "This operator does not take 0 arguments."); goto opn; } else { - BufferPushUInt16(c->vm, buffer, op0); - BufferPushUInt16(c->vm, buffer, ret.index); + gst_buffer_push_u16(c->vm, buffer, op0); + gst_buffer_push_u16(c->vm, buffer, ret.index); } } else if (form->count == 2) { if (op1 < 0) { - if (opn < 0) CError(c, "This operator does not take 1 argument."); + if (opn < 0) c_error(c, "This operator does not take 1 argument."); goto opn; } else { - BufferPushUInt16(c->vm, buffer, op1); - BufferPushUInt16(c->vm, buffer, ret.index); + gst_buffer_push_u16(c->vm, buffer, op1); + gst_buffer_push_u16(c->vm, buffer, ret.index); } } else if (form->count == 3) { if (op2 < 0) { - if (opn < 0) CError(c, "This operator does not take 2 arguments."); + if (opn < 0) c_error(c, "This operator does not take 2 arguments."); goto opn; } else { - BufferPushUInt16(c->vm, buffer, op2); - BufferPushUInt16(c->vm, buffer, ret.index); + gst_buffer_push_u16(c->vm, buffer, op2); + gst_buffer_push_u16(c->vm, buffer, ret.index); } } else { opn: - if (opn < 0) CError(c, "This operator does not take n arguments."); - BufferPushUInt16(c->vm, buffer, opn); - BufferPushUInt16(c->vm, buffer, ret.index); - BufferPushUInt16(c->vm, buffer, form->count - 1); + if (opn < 0) c_error(c, "This operator does not take n arguments."); + gst_buffer_push_u16(c->vm, buffer, opn); + gst_buffer_push_u16(c->vm, buffer, ret.index); + gst_buffer_push_u16(c->vm, buffer, form->count - 1); } } /* Write the location of all of the arguments */ - CompilerTrackerWrite(c, &tracker, reverseOperands); + compiler_tracker_write(c, &tracker, reverseOperands); return ret; } /* Math specials */ -static Slot CompileAddition(Compiler * c, FormOptions opts, Array * form) { - return CompileOperator(c, opts, form, VM_OP_LD0, -1, VM_OP_ADD, VM_OP_ADM, 0); +static Slot compile_addition(GstCompiler *c, FormOptions opts, GstArray *form) { + return compile_operator(c, opts, form, GST_OP_LD0, -1, GST_OP_ADD, GST_OP_ADM, 0); } -static Slot CompileSubtraction(Compiler * c, FormOptions opts, Array * form) { - return CompileOperator(c, opts, form, VM_OP_LD0, -1, VM_OP_SUB, VM_OP_SBM, 0); +static Slot compile_subtraction(GstCompiler *c, FormOptions opts, GstArray *form) { + return compile_operator(c, opts, form, GST_OP_LD0, -1, GST_OP_SUB, GST_OP_SBM, 0); } -static Slot CompileMultiplication(Compiler * c, FormOptions opts, Array * form) { - return CompileOperator(c, opts, form, VM_OP_LD1, -1, VM_OP_MUL, VM_OP_MUM, 0); +static Slot compile_multiplication(GstCompiler *c, FormOptions opts, GstArray *form) { + return compile_operator(c, opts, form, GST_OP_LD1, -1, GST_OP_MUL, GST_OP_MUM, 0); } -static Slot CompileDivision(Compiler * c, FormOptions opts, Array * form) { - return CompileOperator(c, opts, form, VM_OP_LD1, -1, VM_OP_DIV, VM_OP_DVM, 0); +static Slot compile_division(GstCompiler *c, FormOptions opts, GstArray *form) { + return compile_operator(c, opts, form, GST_OP_LD1, -1, GST_OP_DIV, GST_OP_DVM, 0); } -static Slot CompileEquals(Compiler * c, FormOptions opts, Array * form) { - return CompileOperator(c, opts, form, VM_OP_TRU, VM_OP_TRU, VM_OP_EQL, -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); } -static Slot CompileLessThan(Compiler * c, FormOptions opts, Array * form) { - return CompileOperator(c, opts, form, VM_OP_TRU, VM_OP_TRU, VM_OP_LTN, -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); } -static Slot CompileLessThanOrEqual(Compiler * c, FormOptions opts, Array * form) { - return CompileOperator(c, opts, form, VM_OP_TRU, VM_OP_TRU, VM_OP_LTE, -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); } -static Slot CompileGreaterThan(Compiler * c, FormOptions opts, Array * form) { - return CompileOperator(c, opts, form, VM_OP_TRU, VM_OP_TRU, VM_OP_LTN, -1, 1); +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); } -static Slot CompileGreaterThanOrEqual(Compiler * c, FormOptions opts, Array * form) { - return CompileOperator(c, opts, form, VM_OP_TRU, VM_OP_TRU, VM_OP_LTE, -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); } -static Slot CompileNot(Compiler * c, FormOptions opts, Array * form) { - return CompileOperator(c, opts, form, VM_OP_FLS, VM_OP_NOT, -1, -1, 0); +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); } -static Slot CompileGet(Compiler * c, FormOptions opts, Array * form) { - return CompileOperator(c, opts, form, -1, -1, VM_OP_GET, -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); } -static Slot CompileArray(Compiler * c, FormOptions opts, Array * form) { - return CompileOperator(c, opts, form, -1, -1, -1, VM_OP_ARR, 0); +static Slot compile_array(GstCompiler *c, FormOptions opts, GstArray *form) { + return compile_operator(c, opts, form, -1, -1, -1, GST_OP_ARR, 0); } -static Slot CompileDict(Compiler * c, FormOptions opts, Array * form) { +static Slot compile_object(GstCompiler *c, FormOptions opts, GstArray *form) { if ((form->count % 2) == 0) { - CError(c, "Dictionary literal requires an even number of arguments"); - return NilSlot(); + c_error(c, "Dictionary literal requires an even number of arguments"); + return nil_slot(); } else { - return CompileOperator(c, opts, form, -1, -1, -1, VM_OP_DIC, 0); + return compile_operator(c, opts, form, -1, -1, -1, GST_OP_DIC, 0); } } /* Associative set */ -static Slot CompileSet(Compiler * c, FormOptions opts, Array * form) { - Buffer * buffer = c->buffer; - FormOptions subOpts = FormOptionsDefault(); +static Slot compile_set(GstCompiler *c, FormOptions opts, GstArray *form) { + GstBuffer *buffer = c->buffer; + FormOptions subOpts = form_options_default(); Slot ds, key, val; - if (form->count != 4) CError(c, "Set expects 4 arguments"); + if (form->count != 4) c_error(c, "Set expects 4 arguments"); if (opts.resultUnused) { - ds = CompilerRealizeSlot(c, CompileValue(c, subOpts, form->data[1])); + ds = compiler_realize_slot(c, compile_value(c, subOpts, form->data[1])); } else { subOpts = opts; subOpts.isTail = 0; - ds = CompilerRealizeSlot(c, CompileValue(c, subOpts, form->data[1])); - subOpts = FormOptionsDefault(); + ds = compiler_realize_slot(c, compile_value(c, subOpts, form->data[1])); + subOpts = form_options_default(); } - key = CompilerRealizeSlot(c, CompileValue(c, subOpts, form->data[2])); - val = CompilerRealizeSlot(c, CompileValue(c, subOpts, form->data[3])); - BufferPushUInt16(c->vm, buffer, VM_OP_SET); - BufferPushUInt16(c->vm, buffer, ds.index); - BufferPushUInt16(c->vm, buffer, key.index); - BufferPushUInt16(c->vm, buffer, val.index); - CompilerDropSlot(c, c->tail, key); - CompilerDropSlot(c, c->tail, val); + key = compiler_realize_slot(c, compile_value(c, subOpts, form->data[2])); + val = compiler_realize_slot(c, compile_value(c, subOpts, form->data[3])); + gst_buffer_push_u16(c->vm, buffer, GST_OP_SET); + gst_buffer_push_u16(c->vm, buffer, ds.index); + gst_buffer_push_u16(c->vm, buffer, key.index); + gst_buffer_push_u16(c->vm, buffer, val.index); + compiler_drop_slot(c, c->tail, key); + compiler_drop_slot(c, c->tail, val); if (opts.resultUnused) { - CompilerDropSlot(c, c->tail, ds); - return NilSlot(); + compiler_drop_slot(c, c->tail, ds); + return nil_slot(); } else { return ds; } } /* Compile an assignment operation */ -static Slot CompileAssign(Compiler * c, FormOptions opts, Value left, Value right) { - Scope * scope = c->tail; - Buffer * buffer = c->buffer; +static Slot compile_assign(GstCompiler *c, FormOptions opts, GstValue left, GstValue right) { + GstScope *scope = c->tail; + GstBuffer *buffer = c->buffer; FormOptions subOpts; uint16_t target = 0; uint16_t level = 0; Slot slot; subOpts.isTail = 0; subOpts.resultUnused = 0; - if (ScopeSymbolResolve(scope, left, &level, &target)) { + if (symbol_resolve(scope, left, &level, &target)) { /* Check if we have an up value. Otherwise, it's just a normal * local variable */ if (level != 0) { subOpts.canChoose = 1; /* Evaluate the right hand side */ - slot = CompilerRealizeSlot(c, CompileValue(c, subOpts, right)); + slot = compiler_realize_slot(c, compile_value(c, subOpts, right)); /* Set the up value */ - BufferPushUInt16(c->vm, buffer, VM_OP_SUV); - BufferPushUInt16(c->vm, buffer, slot.index); - BufferPushUInt16(c->vm, buffer, level); - BufferPushUInt16(c->vm, buffer, target); + gst_buffer_push_u16(c->vm, buffer, GST_OP_SUV); + gst_buffer_push_u16(c->vm, buffer, slot.index); + gst_buffer_push_u16(c->vm, buffer, level); + gst_buffer_push_u16(c->vm, buffer, target); } else { /* Local variable */ subOpts.canChoose = 0; subOpts.target = target; - slot = CompileValue(c, subOpts, right); + slot = compile_value(c, subOpts, right); } } else { /* We need to declare a new symbol */ - subOpts.target = CompilerDeclareSymbol(c, scope, left); + subOpts.target = compiler_declare_symbol(c, scope, left); subOpts.canChoose = 0; - slot = CompileValue(c, subOpts, right); + slot = compile_value(c, subOpts, right); } if (opts.resultUnused) { - CompilerDropSlot(c, scope, slot); - return NilSlot(); + compiler_drop_slot(c, scope, slot); + return nil_slot(); } else { return slot; } @@ -656,35 +656,35 @@ static Slot CompileAssign(Compiler * c, FormOptions opts, Value left, Value righ /* Compile series of expressions. This compiles the meat of * function definitions and the inside of do forms. */ -static Slot CompileBlock(Compiler * c, FormOptions opts, Array * form, uint32_t startIndex) { - Scope * scope = c->tail; - FormOptions subOpts = FormOptionsDefault(); +static Slot compile_block(GstCompiler *c, FormOptions opts, GstArray *form, uint32_t startIndex) { + GstScope *scope = c->tail; + FormOptions subOpts = form_options_default(); uint32_t current = startIndex; /* Check for empty body */ - if (form->count <= startIndex) return NilSlot(); + if (form->count <= startIndex) return nil_slot(); /* Compile the body */ subOpts.resultUnused = 1; subOpts.isTail = 0; subOpts.canChoose = 1; while (current < form->count - 1) { - CompilerDropSlot(c, scope, CompileValue(c, subOpts, form->data[current])); + compiler_drop_slot(c, scope, compile_value(c, subOpts, form->data[current])); ++current; } /* Compile the last expression in the body */ - return CompileValue(c, opts, form->data[form->count - 1]); + return compile_value(c, opts, form->data[form->count - 1]); } /* Extract the last n bytes from the buffer and use them to construct * a function definition. */ -static FuncDef * CompilerGenFuncDef(Compiler * c, uint32_t lastNBytes, uint32_t arity) { - Scope * scope = c->tail; - Buffer * buffer = c->buffer; - FuncDef * def = VMAlloc(c->vm, sizeof(FuncDef)); +static GstFuncDef * compiler_gen_funcdef(GstCompiler *c, uint32_t lastNBytes, uint32_t arity) { + GstScope *scope = c->tail; + GstBuffer *buffer = c->buffer; + GstFuncDef *def = gst_alloc(c->vm, sizeof(GstFuncDef)); /* Create enough space for the new byteCode */ if (lastNBytes > buffer->count) - CError(c, "Trying to extract more bytes from buffer than in buffer."); - uint8_t * byteCode = VMAlloc(c->vm, lastNBytes); - def->byteCode = (uint16_t *) byteCode; + c_error(c, "Trying to extract more bytes from buffer than in buffer."); + uint8_t * byteCode = gst_alloc(c->vm, lastNBytes); + def->byteCode = (uint16_t *)byteCode; def->byteCodeLen = lastNBytes / 2; /* Copy the last chunk of bytes in the buffer into the new * memory for the function's byteCOde */ @@ -693,15 +693,15 @@ static FuncDef * CompilerGenFuncDef(Compiler * c, uint32_t lastNBytes, uint32_t buffer->count -= lastNBytes; /* Create the literals used by this function */ if (scope->literalsArray->count) { - def->literals = VMAlloc(c->vm, scope->literalsArray->count * sizeof(Value)); + def->literals = gst_alloc(c->vm, scope->literalsArray->count * sizeof(GstValue)); memcpy(def->literals, scope->literalsArray->data, - scope->literalsArray->count * sizeof(Value)); + scope->literalsArray->count * sizeof(GstValue)); } else { def->literals = NULL; } def->literalsLen = scope->literalsArray->count; /* Delete the sub scope */ - CompilerPopScope(c); + compiler_pop_scope(c); /* Initialize the new FuncDef */ def->locals = scope->frameSize; def->arity = arity; @@ -709,62 +709,62 @@ static FuncDef * CompilerGenFuncDef(Compiler * c, uint32_t lastNBytes, uint32_t } /* Compile a function from a function literal */ -static Slot CompileFunction(Compiler * c, FormOptions opts, Array * form) { - Scope * scope = c->tail; - Buffer * buffer = c->buffer; +static Slot compile_function(GstCompiler *c, FormOptions opts, GstArray *form) { + GstScope * scope = c->tail; + GstBuffer * buffer = c->buffer; uint32_t current = 1; uint32_t i; uint32_t sizeBefore; /* Size of buffer before compiling function */ - Scope * subScope; - Array * params; - FormOptions subOpts = FormOptionsDefault(); + GstScope * subGstScope; + GstArray * params; + FormOptions subOpts = form_options_default(); Slot ret; - if (opts.resultUnused) return NilSlot(); - ret = CompilerGetTarget(c, opts); - subScope = CompilerPushScope(c, 0); + if (opts.resultUnused) return nil_slot(); + ret = compiler_get_target(c, opts); + subGstScope = compiler_push_scope(c, 0); /* Check for function documentation - for now just ignore. */ - if (form->data[current].type == TYPE_STRING) + if (form->data[current].type == GST_STRING) ++current; /* Define the function parameters */ - if (form->data[current].type != TYPE_ARRAY) - CError(c, "Expected function arguments"); + if (form->data[current].type != GST_ARRAY) + c_error(c, "Expected function arguments"); params = form->data[current++].data.array; for (i = 0; i < params->count; ++i) { - Value param = params->data[i]; - if (param.type != TYPE_STRING) - CError(c, "Function parameters should be symbols"); + GstValue param = params->data[i]; + if (param.type != GST_STRING) + c_error(c, "Function parameters should be symbols"); /* The compiler puts the parameter locals * in the right place by default - at the beginning * of the stack frame. */ - CompilerDeclareSymbol(c, subScope, param); + compiler_declare_symbol(c, subGstScope, param); } /* Mark where we are on the stack so we can * return to it later. */ sizeBefore = buffer->count; /* Compile the body in the subscope */ subOpts.isTail = 1; - CompilerReturn(c, CompileBlock(c, subOpts, form, current)); + compiler_return(c, compile_block(c, subOpts, form, current)); /* Create a new FuncDef as a constant in original scope by splicing * out the relevant code from the buffer. */ { - Value newVal; + GstValue newVal; uint16_t literalIndex; - FuncDef * def = CompilerGenFuncDef(c, buffer->count - sizeBefore, params->count); + GstFuncDef *def = compiler_gen_funcdef(c, buffer->count - sizeBefore, params->count); /* Add this FuncDef as a literal in the outer scope */ - newVal.type = TYPE_NIL; + newVal.type = GST_NIL; newVal.data.pointer = def; - literalIndex = CompilerAddLiteral(c, scope, newVal); - BufferPushUInt16(c->vm, buffer, VM_OP_CLN); - BufferPushUInt16(c->vm, buffer, ret.index); - BufferPushUInt16(c->vm, buffer, literalIndex); + literalIndex = compiler_add_literal(c, scope, newVal); + gst_buffer_push_u16(c->vm, buffer, GST_OP_CLN); + gst_buffer_push_u16(c->vm, buffer, ret.index); + gst_buffer_push_u16(c->vm, buffer, literalIndex); } return ret; } /* Branching special */ -static Slot CompileIf(Compiler * c, FormOptions opts, Array * form) { - Scope * scope = c->tail; - Buffer * buffer = c->buffer; +static Slot compile_if(GstCompiler *c, FormOptions opts, GstArray *form) { + GstScope * scope = c->tail; + GstBuffer * buffer = c->buffer; FormOptions condOpts = opts; FormOptions branchOpts = opts; Slot left, right, condition; @@ -773,15 +773,15 @@ static Slot CompileIf(Compiler * c, FormOptions opts, Array * form) { uint32_t countAfterFirstBranch; /* Check argument count */ if (form->count < 3 || form->count > 4) - CError(c, "if takes either 2 or 3 arguments"); + c_error(c, "if takes either 2 or 3 arguments"); /* Compile the condition */ condOpts.isTail = 0; condOpts.resultUnused = 0; - condition = CompileValue(c, condOpts, form->data[1]); + condition = compile_value(c, condOpts, form->data[1]); /* If the condition is nil, just compile false path */ if (condition.isNil) { if (form->count == 4) { - return CompileValue(c, opts, form->data[3]); + return compile_value(c, opts, form->data[3]); } return condition; } @@ -789,46 +789,46 @@ static Slot CompileIf(Compiler * c, FormOptions opts, Array * form) { * length later */ countAtJumpIf = buffer->count; /* Write jump instruction. Will later be replaced with correct index. */ - BufferPushUInt16(c->vm, buffer, VM_OP_JIF); - BufferPushUInt16(c->vm, buffer, condition.index); - BufferPushUInt32(c->vm, buffer, 0); + gst_buffer_push_u16(c->vm, buffer, GST_OP_JIF); + gst_buffer_push_u16(c->vm, buffer, condition.index); + gst_buffer_push_u32(c->vm, buffer, 0); /* Configure branch form options */ branchOpts.canChoose = 0; branchOpts.target = condition.index; /* Compile true path */ - left = CompileValue(c, branchOpts, form->data[2]); + left = compile_value(c, branchOpts, form->data[2]); if (opts.isTail) { - CompilerReturn(c, left); + compiler_return(c, left); } else { /* If we need to jump again, do so */ if (form->count == 4) { countAtJump = buffer->count; - BufferPushUInt16(c->vm, buffer, VM_OP_JMP); - BufferPushUInt32(c->vm, buffer, 0); + gst_buffer_push_u16(c->vm, buffer, GST_OP_JMP); + gst_buffer_push_u32(c->vm, buffer, 0); } } - CompilerDropSlot(c, scope, left); + compiler_drop_slot(c, scope, left); /* Reinsert jump with correct index */ countAfterFirstBranch = buffer->count; buffer->count = countAtJumpIf; - BufferPushUInt16(c->vm, buffer, VM_OP_JIF); - BufferPushUInt16(c->vm, buffer, condition.index); - BufferPushUInt32(c->vm, buffer, (countAfterFirstBranch - countAtJumpIf) / 2); + gst_buffer_push_u16(c->vm, buffer, GST_OP_JIF); + gst_buffer_push_u16(c->vm, buffer, condition.index); + gst_buffer_push_u32(c->vm, buffer, (countAfterFirstBranch - countAtJumpIf) / 2); buffer->count = countAfterFirstBranch; /* Compile false path */ if (form->count == 4) { - right = CompileValue(c, branchOpts, form->data[3]); - if (opts.isTail) CompilerReturn(c, right); - CompilerDropSlot(c, scope, right); + right = compile_value(c, branchOpts, form->data[3]); + if (opts.isTail) compiler_return(c, right); + compiler_drop_slot(c, scope, right); } else if (opts.isTail) { - CompilerReturn(c, condition); + compiler_return(c, condition); } /* Reset the second jump length */ if (!opts.isTail && form->count == 4) { countAfterFirstBranch = buffer->count; buffer->count = countAtJump; - BufferPushUInt16(c->vm, buffer, VM_OP_JMP); - BufferPushUInt32(c->vm, buffer, (countAfterFirstBranch - countAtJump) / 2); + gst_buffer_push_u16(c->vm, buffer, GST_OP_JMP); + gst_buffer_push_u32(c->vm, buffer, (countAfterFirstBranch - countAtJump) / 2); buffer->count = countAfterFirstBranch; } if (opts.isTail) @@ -837,15 +837,15 @@ static Slot CompileIf(Compiler * c, FormOptions opts, Array * form) { } /* While special */ -static Slot CompileWhile(Compiler * c, FormOptions opts, Array * form) { +static Slot compile_while(GstCompiler *c, FormOptions opts, GstArray *form) { Slot cond; uint32_t countAtStart = c->buffer->count; uint32_t countAtJumpDelta; uint32_t countAtFinish; - FormOptions defaultOpts = FormOptionsDefault(); - CompilerPushScope(c, 1); + FormOptions defaultOpts = form_options_default(); + compiler_push_scope(c, 1); /* Compile condition */ - cond = CompileValue(c, defaultOpts, form->data[1]); + cond = compile_value(c, defaultOpts, form->data[1]); /* Assert that cond is a real value - otherwise do nothing (nil is false, * so loop never runs.) */ if (cond.isNil) return cond; @@ -854,202 +854,202 @@ static Slot CompileWhile(Compiler * c, FormOptions opts, Array * form) { c->buffer->count += sizeof(uint16_t) * 2 + sizeof(int32_t); /* Compile loop body */ defaultOpts.resultUnused = 1; - CompilerDropSlot(c, c->tail, CompileBlock(c, defaultOpts, form, 2)); + compiler_drop_slot(c, c->tail, compile_block(c, defaultOpts, form, 2)); /* Jump back to the loop start */ countAtFinish = c->buffer->count; - BufferPushUInt16(c->vm, c->buffer, VM_OP_JMP); - BufferPushInt32(c->vm, c->buffer, (int32_t)(countAtFinish - countAtStart) / -2); + gst_buffer_push_u16(c->vm, c->buffer, GST_OP_JMP); + gst_buffer_push_i32(c->vm, c->buffer, (int32_t)(countAtFinish - countAtStart) / -2); countAtFinish = c->buffer->count; /* Set the jump to the correct length */ c->buffer->count = countAtJumpDelta; - BufferPushUInt16(c->vm, c->buffer, VM_OP_JIF); - BufferPushUInt16(c->vm, c->buffer, cond.index); - BufferPushInt32(c->vm, c->buffer, (int32_t)(countAtFinish - countAtJumpDelta) / 2); + gst_buffer_push_u16(c->vm, c->buffer, GST_OP_JIF); + gst_buffer_push_u16(c->vm, c->buffer, cond.index); + gst_buffer_push_i32(c->vm, c->buffer, (int32_t)(countAtFinish - countAtJumpDelta) / 2); /* Pop scope */ c->buffer->count = countAtFinish; - CompilerPopScope(c); + compiler_pop_scope(c); /* Return nil */ if (opts.resultUnused) - return NilSlot(); + return nil_slot(); else return cond; } /* Do special */ -static Slot CompileDo(Compiler * c, FormOptions opts, Array * form) { +static Slot compile_do(GstCompiler *c, FormOptions opts, GstArray *form) { Slot ret; - CompilerPushScope(c, 1); - ret = CompileBlock(c, opts, form, 1); - CompilerPopScope(c); + compiler_push_scope(c, 1); + ret = compile_block(c, opts, form, 1); + compiler_pop_scope(c); return ret; } /* Quote special - returns its argument as is. */ -static Slot CompileQuote(Compiler * c, FormOptions opts, Array * form) { - Scope * scope = c->tail; - Buffer * buffer = c->buffer; +static Slot compile_quote(GstCompiler *c, FormOptions opts, GstArray *form) { + GstScope *scope = c->tail; + GstBuffer *buffer = c->buffer; Slot ret; uint16_t literalIndex; if (form->count != 2) - CError(c, "Quote takes exactly 1 argument."); - Value x = form->data[1]; - if (x.type == TYPE_NIL || - x.type == TYPE_BOOLEAN || - x.type == TYPE_NUMBER) { - return CompileNonReferenceType(c, opts, x); + c_error(c, "Quote takes exactly 1 argument."); + GstValue x = form->data[1]; + if (x.type == GST_NIL || + x.type == GST_BOOLEAN || + x.type == GST_NUMBER) { + return compile_nonref_type(c, opts, x); } - if (opts.resultUnused) return NilSlot(); - ret = CompilerGetTarget(c, opts); - literalIndex = CompilerAddLiteral(c, scope, x); - BufferPushUInt16(c->vm, buffer, VM_OP_CST); - BufferPushUInt16(c->vm, buffer, ret.index); - BufferPushUInt16(c->vm, buffer, literalIndex); + if (opts.resultUnused) return nil_slot(); + ret = compiler_get_target(c, opts); + literalIndex = compiler_add_literal(c, scope, x); + gst_buffer_push_u16(c->vm, buffer, GST_OP_CST); + gst_buffer_push_u16(c->vm, buffer, ret.index); + gst_buffer_push_u16(c->vm, buffer, literalIndex); return ret; } /* Assignment special */ -static Slot CompileVar(Compiler * c, FormOptions opts, Array * form) { +static Slot compile_var(GstCompiler *c, FormOptions opts, GstArray *form) { if (form->count != 3) - CError(c, "Assignment expects 2 arguments"); - return CompileAssign(c, opts, form->data[1], form->data[2]); + c_error(c, "Assignment expects 2 arguments"); + return compile_assign(c, opts, form->data[1], form->data[2]); } /* Define a function type for Special Form helpers */ -typedef Slot (*SpecialFormHelper) (Compiler * c, FormOptions opts, Array * form); +typedef Slot (*SpecialFormHelper) (GstCompiler *c, FormOptions opts, GstArray *form); /* Dispatch to a special form */ -static SpecialFormHelper GetSpecial(Array * form) { - uint8_t * name; - if (form->count < 1 || form->data[0].type != TYPE_STRING) +static SpecialFormHelper get_special(GstArray *form) { + uint8_t *name; + if (form->count < 1 || form->data[0].type != GST_STRING) return NULL; name = form->data[0].data.string; /* If we have a symbol with a zero length name, we have other * problems. */ - if (VStringSize(name) == 0) + if (gst_string_length(name) == 0) return NULL; /* One character specials. Mostly math. */ - if (VStringSize(name) == 1) { + if (gst_string_length(name) == 1) { switch(name[0]) { - case '+': return CompileAddition; - case '-': return CompileSubtraction; - case '*': return CompileMultiplication; - case '/': return CompileDivision; - case '>': return CompileGreaterThan; - case '<': return CompileLessThan; - case '=': return CompileEquals; + case '+': return compile_addition; + case '-': return compile_subtraction; + case '*': return compile_multiplication; + case '/': return compile_division; + case '>': return compile_gt; + case '<': return compile_lt; + case '=': return compile_equals; default: - break; + break; } } /* Multi character specials. Mostly control flow. */ switch (name[0]) { case '>': { - if (VStringSize(name) == 2 && + if (gst_string_length(name) == 2 && name[1] == '=') { - return CompileGreaterThanOrEqual; + return compile_gte; } } break; case '<': { - if (VStringSize(name) == 2 && + if (gst_string_length(name) == 2 && name[1] == '=') { - return CompileLessThanOrEqual; + return compile_lte; } } break; case 'a': { - if (VStringSize(name) == 5 && + if (gst_string_length(name) == 5 && name[1] == 'r' && name[2] == 'r' && name[3] == 'a' && name[4] == 'y') { - return CompileArray; + return compile_array; } } case 'g': { - if (VStringSize(name) == 3 && + if (gst_string_length(name) == 3 && name[1] == 'e' && name[2] == 't') { - return CompileGet; + return compile_get; } } case 'd': { - if (VStringSize(name) == 2 && + if (gst_string_length(name) == 2 && name[1] == 'o') { - return CompileDo; - } else if (VStringSize(name) == 4 && + return compile_do; + } else if (gst_string_length(name) == 4 && name[1] == 'i' && name[2] == 'c' && name[3] == 't') { - return CompileDict; + return compile_object; } } break; case 'i': { - if (VStringSize(name) == 2 && + if (gst_string_length(name) == 2 && name[1] == 'f') { - return CompileIf; + return compile_if; } } break; case 'f': { - if (VStringSize(name) == 2 && + if (gst_string_length(name) == 2 && name[1] == 'n') { - return CompileFunction; + return compile_function; } } break; case 'n': { - if (VStringSize(name) == 3 && + if (gst_string_length(name) == 3 && name[1] == 'o' && name[2] == 't') { - return CompileNot; + return compile_not; } } case 'q': { - if (VStringSize(name) == 5 && + if (gst_string_length(name) == 5 && name[1] == 'u' && name[2] == 'o' && name[3] == 't' && name[4] == 'e') { - return CompileQuote; + return compile_quote; } } break; case 's': { - if (VStringSize(name) == 3 && + if (gst_string_length(name) == 3 && name[1] == 'e' && name[2] == 't') { - return CompileSet; + return compile_set; } } break; case 'w': { - if (VStringSize(name) == 5 && + if (gst_string_length(name) == 5 && name[1] == 'h' && name[2] == 'i' && name[3] == 'l' && name[4] == 'e') { - return CompileWhile; + return compile_while; } } break; case ':': { - if (VStringSize(name) == 2 && + if (gst_string_length(name) == 2 && name[1] == '=') { - return CompileVar; + return compile_var; } } break; @@ -1060,102 +1060,102 @@ static SpecialFormHelper GetSpecial(Array * form) { } /* Compile a form. Checks for special forms and macros. */ -static Slot CompileForm(Compiler * c, FormOptions opts, Array * form) { - Scope * scope = c->tail; - Buffer * buffer = c->buffer; +static Slot compile_form(GstCompiler *c, FormOptions opts, GstArray *form) { + GstScope *scope = c->tail; + GstBuffer *buffer = c->buffer; SpecialFormHelper helper; /* Empty forms evaluate to nil. */ if (form->count == 0) { - Value temp; - temp.type = TYPE_NIL; - return CompileNonReferenceType(c, opts, temp); + GstValue temp; + temp.type = GST_NIL; + return compile_nonref_type(c, opts, temp); } /* Check and handle special forms */ - helper = GetSpecial(form); + helper = get_special(form); if (helper != NULL) { return helper(c, opts, form); } else { Slot ret, callee; SlotTracker tracker; - FormOptions subOpts = FormOptionsDefault(); + FormOptions subOpts = form_options_default(); uint32_t i; - CompilerTrackerInit(c, &tracker); + tracker_init(c, &tracker); /* Compile function to be called */ - callee = CompilerRealizeSlot(c, CompileValue(c, subOpts, form->data[0])); + callee = compiler_realize_slot(c, compile_value(c, subOpts, form->data[0])); /* Compile all of the arguments */ for (i = 1; i < form->count; ++i) { - Slot slot = CompileValue(c, subOpts, form->data[i]); - CompilerTrackerPush(c, &tracker, slot); + Slot slot = compile_value(c, subOpts, form->data[i]); + compiler_tracker_push(c, &tracker, slot); } /* Free up some slots */ - CompilerDropSlot(c, scope, callee); - CompilerTrackerFree(c, scope, &tracker); + compiler_drop_slot(c, scope, callee); + compiler_tracker_free(c, scope, &tracker); /* If this is in tail position do a tail call. */ if (opts.isTail) { - BufferPushUInt16(c->vm, buffer, VM_OP_TCL); - BufferPushUInt16(c->vm, buffer, callee.index); + gst_buffer_push_u16(c->vm, buffer, GST_OP_TCL); + gst_buffer_push_u16(c->vm, buffer, callee.index); ret.hasReturned = 1; ret.isNil = 1; } else { - ret = CompilerGetTarget(c, opts); - BufferPushUInt16(c->vm, buffer, VM_OP_CAL); - BufferPushUInt16(c->vm, buffer, callee.index); - BufferPushUInt16(c->vm, buffer, ret.index); + ret = compiler_get_target(c, opts); + gst_buffer_push_u16(c->vm, buffer, GST_OP_CAL); + gst_buffer_push_u16(c->vm, buffer, callee.index); + gst_buffer_push_u16(c->vm, buffer, ret.index); } - BufferPushUInt16(c->vm, buffer, form->count - 1); + gst_buffer_push_u16(c->vm, buffer, form->count - 1); /* Write the location of all of the arguments */ - CompilerTrackerWrite(c, &tracker, 0); + compiler_tracker_write(c, &tracker, 0); return ret; } } /* Recursively compile any value or form */ -static Slot CompileValue(Compiler * c, FormOptions opts, Value x) { +static Slot compile_value(GstCompiler *c, FormOptions opts, GstValue x) { switch (x.type) { - case TYPE_NIL: - case TYPE_BOOLEAN: - case TYPE_NUMBER: - return CompileNonReferenceType(c, opts, x); - case TYPE_STRING: - return CompileSymbol(c, opts, x); - case TYPE_ARRAY: - return CompileForm(c, opts, x.data.array); + case GST_NIL: + case GST_BOOLEAN: + case GST_NUMBER: + return compile_nonref_type(c, opts, x); + case GST_STRING: + return compile_symbol(c, opts, x); + case GST_ARRAY: + return compile_form(c, opts, x.data.array); default: - return CompileLiteral(c, opts, x); + return compile_literal(c, opts, x); } } -/* Initialize a Compiler struct */ -void CompilerInit(Compiler * c, VM * vm) { +/* Initialize a GstCompiler struct */ +void gst_compiler(GstCompiler *c, Gst *vm) { c->vm = vm; - c->buffer = BufferNew(vm, 128); - c->env = ArrayNew(vm, 10); + c->buffer = gst_buffer(vm, 128); + c->env = gst_array(vm, 10); c->tail = NULL; c->error = NULL; - CompilerPushScope(c, 0); + compiler_push_scope(c, 0); } /* Register a global for the compilation environment. */ -void CompilerAddGlobal(Compiler * c, const char * name, Value x) { - Value sym = ValueLoadCString(c->vm, name); - sym.type = TYPE_STRING; - CompilerDeclareSymbol(c, c->tail, sym); - ArrayPush(c->vm, c->env, x); +void gst_compiler_add_global(GstCompiler *c, const char *name, GstValue x) { + GstValue sym = gst_load_cstring(c->vm, name); + sym.type = GST_STRING; + compiler_declare_symbol(c, c->tail, sym); + gst_array_push(c->vm, c->env, x); } /* Register a global c function for the compilation environment. */ -void CompilerAddGlobalCFunc(Compiler * c, const char * name, CFunction f) { - Value func; - func.type = TYPE_CFUNCTION; +void gst_compiler_add_global_cfunction(GstCompiler *c, const char *name, GstCFunction f) { + GstValue func; + func.type = GST_CFUNCTION; func.data.cfunction = f; - CompilerAddGlobal(c, name, func); + gst_compiler_add_global(c, name, func); } /* Compile interface. Returns a function that evaluates the * given AST. Returns NULL if there was an error during compilation. */ -Func * CompilerCompile(Compiler * c, Value form) { - FormOptions opts = FormOptionsDefault(); - FuncDef * def; +GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) { + FormOptions opts = form_options_default(); + GstFuncDef *def; if (setjmp(c->onError)) { /* Clear all but root scope */ if (c->tail) @@ -1164,16 +1164,16 @@ Func * CompilerCompile(Compiler * c, Value form) { } /* Create a scope */ opts.isTail = 1; - CompilerPushScope(c, 0); - CompilerReturn(c, CompileValue(c, opts, form)); - def = CompilerGenFuncDef(c, c->buffer->count, 0); + compiler_push_scope(c, 0); + compiler_return(c, compile_value(c, opts, form)); + def = compiler_gen_funcdef(c, c->buffer->count, 0); { uint32_t envSize = c->env->count; - FuncEnv * env = VMAlloc(c->vm, sizeof(FuncEnv)); - Func * func = VMAlloc(c->vm, sizeof(Func)); + GstFuncEnv *env = gst_alloc(c->vm, sizeof(GstFuncEnv)); + GstFunction *func = gst_alloc(c->vm, sizeof(GstFunction)); if (envSize) { - env->values = VMAlloc(c->vm, sizeof(Value) * envSize); - memcpy(env->values, c->env->data, envSize * sizeof(Value)); + env->values = gst_alloc(c->vm, sizeof(GstValue) * envSize); + memcpy(env->values, c->env->data, envSize * sizeof(GstValue)); } else { env->values = NULL; } @@ -1190,16 +1190,16 @@ Func * CompilerCompile(Compiler * c, Value form) { * and is completely separate. This allows the compilation to not have to worry * about garbage collection and other issues that would complicate both the * runtime and the compilation. */ -int CompileMacroExpand(VM * vm, Value x, Dictionary * macros, Value * out) { - while (x.type == TYPE_ARRAY) { - Array * form = x.data.array; - Value sym, macroFn; +int gst_macro_expand(Gst *vm, GstValue x, GstObject *macros, GstValue *out) { + while (x.type == GST_ARRAY) { + GstArray *form = x.data.array; + GstValue sym, macroFn; if (form->count == 0) break; sym = form->data[0]; - macroFn = DictGet(macros, sym); - if (macroFn.type != TYPE_FUNCTION && macroFn.type != TYPE_CFUNCTION) break; - VMLoad(vm, macroFn); - if (VMStart(vm)) { + macroFn = gst_object_get(macros, sym); + if (macroFn.type != GST_FUNCTION && macroFn.type != GST_CFUNCTION) break; + gst_load(vm, macroFn); + if (gst_start(vm)) { /* We encountered an error during parsing */ return 1; } else { diff --git a/compile.h b/compile.h index 1f384fc4..4b2f3d6c 100644 --- a/compile.h +++ b/compile.h @@ -4,21 +4,21 @@ #include "datatypes.h" /* Initialize the Compiler */ -void CompilerInit(Compiler * c, VM * vm); +void gst_compiler(GstCompiler *c, Gst *vm); /* Register a global for the compilation environment. */ -void CompilerAddGlobal(Compiler * c, const char * name, Value x); +void gst_compiler_add_global(GstCompiler *c, const char *name, GstValue x); /* Register a global c function for the compilation environment. */ -void CompilerAddGlobalCFunc(Compiler * c, const char * name, CFunction f); +void gst_compiler_add_global_cfunction(GstCompiler *c, const char *name, GstCFunction f); /* Compile a function that evaluates the given form. */ -Func * CompilerCompile(Compiler * c, Value form); +GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form); /* Macro expansion. Macro expansion happens prior to the compilation process * and is completely separate. This allows the compilation to not have to worry * about garbage collection and other issues that would complicate both the * runtime and the compilation. */ -int CompileMacroExpand(VM * vm, Value x, Dictionary * macros, Value * out); +int gst_macro_expand(Gst *vm, GstValue x, GstObject *macros, GstValue *out); #endif /* end of include guard: COMPILE_H_9VXF71HY */ diff --git a/datatypes.h b/datatypes.h index 9fee407d..f6be01e6 100644 --- a/datatypes.h +++ b/datatypes.h @@ -4,227 +4,234 @@ #include #include -typedef enum Type { - TYPE_NIL = 0, - TYPE_NUMBER, - TYPE_BOOLEAN, - TYPE_STRING, - TYPE_ARRAY, - TYPE_THREAD, - TYPE_BYTEBUFFER, - TYPE_FUNCTION, - TYPE_CFUNCTION, - TYPE_DICTIONARY -} Type; +typedef enum GstType { + GST_NIL = 0, + GST_NUMBER, + GST_BOOLEAN, + GST_STRING, + GST_ARRAY, + GST_THREAD, + GST_BYTEBUFFER, + GST_FUNCTION, + GST_CFUNCTION, + GST_OBJECT +} GstType; -typedef double Number; -typedef uint8_t Boolean; -typedef struct VM VM; -typedef struct Value Value; -typedef Value (*CFunction)(VM * vm); -typedef struct Func Func; -typedef struct FuncDef FuncDef; -typedef struct FuncEnv FuncEnv; -typedef union ValueData ValueData; -typedef struct DictBucket DictBucket; -typedef struct Array Array; -typedef struct Buffer Buffer; -typedef struct Dictionary Dictionary; -typedef struct DictionaryIterator DictionaryIterator; -typedef struct Parser Parser; -typedef struct ParseState ParseState; -typedef struct Scope Scope; -typedef struct Compiler Compiler; -typedef struct Thread Thread; -typedef struct StackFrame StackFrame; +/* The state of the virtual machine */ +typedef struct Gst Gst; -union ValueData { - Boolean boolean; - Number number; - uint8_t * string; - Array * array; - Buffer * buffer; - Dictionary * dict; - Func * func; - Thread * thread; - void * pointer; - CFunction cfunction; - uint16_t u16[4]; - uint8_t u8[8]; -} data; +/* A general gst value type */ +typedef struct GstValue GstValue; -struct Value { - Type type; - ValueData data; +/* All of the gst types */ +typedef double GstNumber; +typedef uint8_t GstBoolean; +typedef struct GstFunction GstFunction; +typedef struct GstArray GstArray; +typedef struct GstBuffer GstBuffer; +typedef struct GstObject GstObject; +typedef struct GstThread GstThread; +typedef GstValue (*GstCFunction)(Gst * vm); + +/* Implementation details */ +typedef struct GstParser GstParser; +typedef struct GstCompiler GstCompiler; +typedef struct GstFuncDef GstFuncDef; +typedef struct GstFuncEnv GstFuncEnv; + +/* Definitely implementation details */ +typedef struct GstStackFrame GstStackFrame; +typedef struct GstParseState GstParseState; +typedef struct GstBucket GstBucket; +typedef struct GstScope GstScope; + +/* The general gst value type. Contains a large union and + * the type information of the value */ +struct GstValue { + GstType type; + union { + /* The various types */ + GstBoolean boolean; + GstNumber number; + GstArray *array; + GstBuffer *buffer; + GstObject *object; + GstThread *thread; + GstCFunction cfunction; + GstFunction *function; + uint8_t *string; + void *pointer; + } data; }; -struct Thread { +/* A lightweight thread in gst. Does not correspond to + * operating system threads. Used in coroutines. */ +struct GstThread { uint32_t count; uint32_t capacity; - Value * data; + GstValue *data; enum { - THREAD_PENDING = 0, - THREAD_ALIVE, - TRHEAD_DEAD + GST_THREAD_PENDING = 0, + GST_THREAD_ALIVE, + GST_TRHEAD_DEAD } status; }; -struct Array { +/* A dynamic array type */ +struct GstArray { uint32_t count; uint32_t capacity; - Value * data; + GstValue *data; uint32_t flags; }; -struct Buffer { +/* A bytebuffer type. Used as a mutable string or string builder. */ +struct GstBuffer { uint32_t count; uint32_t capacity; - uint8_t * data; + uint8_t *data; uint32_t flags; }; -struct Dictionary { +/* The main Gst type, an obect. Objects are just hashtables with some meta + * information attached in the meta value */ +struct GstObject { uint32_t count; uint32_t capacity; - DictBucket ** buckets; + GstBucket **buckets; uint32_t flags; - Value meta; + GstValue meta; }; -struct DictionaryIterator { - Dictionary * dict; - uint32_t index; - DictBucket * bucket; -}; - -struct FuncDef { +/* A function defintion. Contains information need to instatiate closures. */ +struct GstFuncDef { uint32_t locals; uint32_t arity; uint32_t literalsLen; uint32_t byteCodeLen; - Value * literals; /* Contains strings, FuncDefs, etc. */ - uint16_t * byteCode; + GstValue *literals; /* Contains strings, FuncDefs, etc. */ + uint16_t *byteCode; }; -struct FuncEnv { - Thread * thread; /* When nil, index the local values */ +/* A fuction environment */ +struct GstFuncEnv { + GstThread *thread; /* When nil, index the local values */ uint32_t stackOffset; /* Used as environment size when off stack */ - Value * values; + GstValue *values; }; -struct Func { - FuncDef * def; - FuncEnv * env; - Func * parent; +/* A function */ +struct GstFunction { + GstFuncDef *def; + GstFuncEnv *env; + GstFunction *parent; }; -struct DictBucket { - Value key; - Value value; - DictBucket * next; +/* A hash table bucket in an object */ +struct GstBucket { + GstValue key; + GstValue value; + GstBucket *next; }; -struct StackFrame { - Value callee; +/* A stack frame in the VM */ +struct GstStackFrame { + GstValue callee; uint16_t size; uint16_t prevSize; uint16_t ret; - FuncEnv * env; - uint16_t * pc; + GstFuncEnv *env; + uint16_t *pc; }; -struct VM { +/* The VM state */ +struct Gst { /* Garbage collection */ - void * blocks; + void *blocks; uint32_t memoryInterval; uint32_t nextCollection; uint32_t black : 1; uint32_t lock : 31; /* Thread */ - uint16_t * pc; - Thread * thread; - Value * base; - StackFrame * frame; + uint16_t *pc; + GstThread *thread; + GstValue *base; + GstStackFrame *frame; /* Return state */ - const char * error; + const char *error; jmp_buf jump; - Value ret; /* Returned value from VMStart */ + GstValue ret; /* Returned value from VMStart */ /* Object definitions */ - Value metas[TYPE_DICTIONARY]; + GstValue metas[GST_OBJECT]; }; -/* Parsing */ - -struct Parser { - VM * vm; - const char * error; - ParseState * data; - Value value; +struct GstParser { + Gst *vm; + const char *error; + GstParseState *data; + GstValue value; uint32_t count; uint32_t cap; uint32_t index; enum { - PARSER_PENDING = 0, - PARSER_FULL, - PARSER_ERROR + GST_PARSER_PENDING = 0, + GST_PARSER_FULL, + GST_PARSER_ERROR } status; }; -/* Compiling */ - -struct Compiler { - VM * vm; - const char * error; +/* Compilation state */ +struct GstCompiler { + Gst *vm; + const char *error; jmp_buf onError; - Scope * tail; - Array * env; - Buffer * buffer; + GstScope *tail; + GstArray *env; + GstBuffer *buffer; }; /* String utils */ - -#define VStringRaw(s) ((uint32_t *)(s) - 2) -#define VStringSize(v) (VStringRaw(v)[0]) -#define VStringHash(v) (VStringRaw(v)[1]) +#define gst_string_raw(s) ((uint32_t *)(s) - 2) +#define gst_string_length(v) (gst_string_raw(v)[0]) +#define gst_string_hash(v) (gst_string_raw(v)[1]) /* Bytecode */ - -enum OpCode { - VM_OP_ADD = 0, /* 0x0000 */ - VM_OP_SUB, /* 0x0001 */ - VM_OP_MUL, /* 0x0002 */ - VM_OP_DIV, /* 0x0003 */ - VM_OP_NOT, /* 0x0004 */ - VM_OP_LD0, /* 0x0005 */ - VM_OP_LD1, /* 0x0006 */ - VM_OP_FLS, /* 0x0007 */ - VM_OP_TRU, /* 0x0008 */ - VM_OP_NIL, /* 0x0009 */ - VM_OP_I16, /* 0x000a */ - VM_OP_UPV, /* 0x000b */ - VM_OP_JIF, /* 0x000c */ - VM_OP_JMP, /* 0x000d */ - VM_OP_CAL, /* 0x000e */ - VM_OP_RET, /* 0x000f */ - VM_OP_SUV, /* 0x0010 */ - VM_OP_CST, /* 0x0011 */ - VM_OP_I32, /* 0x0012 */ - VM_OP_F64, /* 0x0013 */ - VM_OP_MOV, /* 0x0014 */ - VM_OP_CLN, /* 0x0015 */ - VM_OP_EQL, /* 0x0016 */ - VM_OP_LTN, /* 0x0017 */ - VM_OP_LTE, /* 0x0018 */ - VM_OP_ARR, /* 0x0019 */ - VM_OP_DIC, /* 0x001a */ - VM_OP_TCL, /* 0x001b */ - VM_OP_ADM, /* 0x001c */ - VM_OP_SBM, /* 0x001d */ - VM_OP_MUM, /* 0x001e */ - VM_OP_DVM, /* 0x001f */ - VM_OP_RTN, /* 0x0020 */ - VM_OP_SET, /* 0x0021 */ - VM_OP_GET /* 0x0022 */ +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_ADM, /* 0x001c */ + GST_OP_SBM, /* 0x001d */ + GST_OP_MUM, /* 0x001e */ + GST_OP_DVM, /* 0x001f */ + GST_OP_RTN, /* 0x0020 */ + GST_OP_SET, /* 0x0021 */ + GST_OP_GET /* 0x0022 */ }; #endif diff --git a/disasm.c b/disasm.c index 67ad0d5f..d03a4d5b 100644 --- a/disasm.c +++ b/disasm.c @@ -4,17 +4,17 @@ #define OP_WIDTH 20 /* Print various register and arguments to instructions */ -static void dasmPrintSlot(FILE * out, uint16_t index) { fprintf(out, "%d ", index); } -static void dasmPrintI16(FILE * out, int16_t number) { fprintf(out, "#%d ", number); } -static void dasmPrintI32(FILE * out, int32_t number) { fprintf(out, "#%d ", number); } -static void dasmPrintF64(FILE * out, double number) { fprintf(out, "#%f ", number); } -static void dasmPrintLiteral(FILE * out, uint16_t index) { fprintf(out, "(%d) ", index); } -static void dasmPrintUpValue(FILE * out, uint16_t level, uint16_t index) { +static void dasm_print_slot(FILE * out, uint16_t index) { fprintf(out, "%d ", index); } +static void dasm_print_i16(FILE * out, int16_t number) { fprintf(out, "#%d ", number); } +static void dasm_print_i32(FILE * out, int32_t number) { fprintf(out, "#%d ", number); } +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); } /* Print the name of the argument but pad it */ -static void dasmPrintArg(FILE * out, const char * name) { +static void dasm_print_arg(FILE * out, const char * name) { uint32_t i = 0; char c; while ((c = *name++)) { @@ -26,44 +26,44 @@ static void dasmPrintArg(FILE * out, const char * name) { } /* Print instructions that take a fixed number of arguments */ -static uint32_t dasmPrintFixedOp(FILE * out, const uint16_t * current, +static uint32_t dasm_fixed_op(FILE * out, const uint16_t * current, const char * name, uint32_t size) { uint32_t i; - dasmPrintArg(out, name); + dasm_print_arg(out, name); for (i = 1; i <= size; ++i) { - dasmPrintSlot(out, current[i]); + dasm_print_slot(out, current[i]); } return size + 1; } /* Print instructions that take a variable number of arguments */ -static uint32_t dasmPrintVarArgOp(FILE * out, const uint16_t * current, +static uint32_t dasm_varg_op(FILE * out, const uint16_t * current, const char * name, uint32_t extra) { uint32_t i, argCount; - dasmPrintArg(out, name); + dasm_print_arg(out, name); for (i = 0; i < extra; ++i) { - dasmPrintSlot(out, current[i + 1]); + dasm_print_slot(out, current[i + 1]); } argCount = current[extra + 1]; fprintf(out, ": "); /* Argument separator */ for (i = 0; i < argCount; ++i) { - dasmPrintSlot(out, current[i + extra + 2]); + dasm_print_slot(out, current[i + extra + 2]); } return argCount + extra + 2; } /* Print the disassembly for a function definition */ -void dasmFuncDef(FILE * out, FuncDef * def) { - dasm(out, def->byteCode, def->byteCodeLen); +void gst_dasm_funcdef(FILE * out, GstFuncDef * def) { + gst_dasm(out, def->byteCode, def->byteCodeLen); } /* Print the disassembly for a function */ -void dasmFunc(FILE * out, Func * f) { - dasm(out, f->def->byteCode, f->def->byteCodeLen); +void gst_dasm_function(FILE * out, GstFunction * f) { + gst_dasm(out, f->def->byteCode, f->def->byteCodeLen); } /* Disassemble some bytecode and display it as opcode + arguments assembly */ -void dasm(FILE * out, uint16_t *byteCode, uint32_t len) { +void gst_dasm(FILE * out, uint16_t *byteCode, uint32_t len) { uint16_t *current = byteCode; uint16_t *end = byteCode + len; @@ -71,136 +71,136 @@ void dasm(FILE * out, uint16_t *byteCode, uint32_t len) { while (current < end) { switch (*current) { - case VM_OP_ADD: - current += dasmPrintFixedOp(out, current, "add", 3); + case GST_OP_ADD: + current += dasm_fixed_op(out, current, "add", 3); break; - case VM_OP_SUB: - current += dasmPrintFixedOp(out, current, "sub", 3); + case GST_OP_SUB: + current += dasm_fixed_op(out, current, "sub", 3); break; - case VM_OP_MUL: - current += dasmPrintFixedOp(out, current, "mul", 3); + case GST_OP_MUL: + current += dasm_fixed_op(out, current, "mul", 3); break; - case VM_OP_DIV: - current += dasmPrintFixedOp(out, current, "div", 3); + case GST_OP_DIV: + current += dasm_fixed_op(out, current, "div", 3); break; - case VM_OP_NOT: - current += dasmPrintFixedOp(out, current, "not", 2); + case GST_OP_NOT: + current += dasm_fixed_op(out, current, "not", 2); break; - case VM_OP_LD0: - current += dasmPrintFixedOp(out, current, "load0", 1); + case GST_OP_LD0: + current += dasm_fixed_op(out, current, "load0", 1); break; - case VM_OP_LD1: - current += dasmPrintFixedOp(out, current, "load1", 1); + case GST_OP_LD1: + current += dasm_fixed_op(out, current, "load1", 1); break; - case VM_OP_FLS: - current += dasmPrintFixedOp(out, current, "loadFalse", 1); + case GST_OP_FLS: + current += dasm_fixed_op(out, current, "loadFalse", 1); break; - case VM_OP_TRU: - current += dasmPrintFixedOp(out, current, "loadTrue", 1); + case GST_OP_TRU: + current += dasm_fixed_op(out, current, "loadTrue", 1); break; - case VM_OP_NIL: - current += dasmPrintFixedOp(out, current, "loadNil", 1); + case GST_OP_NIL: + current += dasm_fixed_op(out, current, "loadNil", 1); break; - case VM_OP_I16: - dasmPrintArg(out, "loadInt16"); - dasmPrintSlot(out, current[1]); - dasmPrintI16(out, ((int16_t *)current)[2]); + 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 VM_OP_UPV: - dasmPrintArg(out, "loadUpValue"); - dasmPrintSlot(out, current[1]); - dasmPrintUpValue(out, current[2], current[3]); + 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 VM_OP_JIF: - dasmPrintArg(out, "jumpIf"); - dasmPrintSlot(out, current[1]); - dasmPrintI32(out, ((int32_t *)(current + 2))[0]); + 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 VM_OP_JMP: - dasmPrintArg(out, "jump"); - dasmPrintI32(out, ((int32_t *)(current + 1))[0]); + case GST_OP_JMP: + dasm_print_arg(out, "jump"); + dasm_print_i32(out, ((int32_t *)(current + 1))[0]); current += 3; break; - case VM_OP_CAL: - current += dasmPrintVarArgOp(out, current, "call", 2); + case GST_OP_CAL: + current += dasm_varg_op(out, current, "call", 2); break; - case VM_OP_RET: - current += dasmPrintFixedOp(out, current, "return", 1); + case GST_OP_RET: + current += dasm_fixed_op(out, current, "return", 1); break; - case VM_OP_SUV: - dasmPrintArg(out, "setUpValue"); - dasmPrintSlot(out, current[1]); - dasmPrintUpValue(out, current[2], current[3]); + 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 VM_OP_CST: - dasmPrintArg(out, "loadLiteral"); - dasmPrintSlot(out, current[1]); - dasmPrintLiteral(out, current[2]); + 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 VM_OP_I32: - dasmPrintArg(out, "loadInt32"); - dasmPrintSlot(out, current[1]); - dasmPrintI32(out, ((int32_t *)(current + 2))[0]); + 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 VM_OP_F64: - dasmPrintArg(out, "loadFloat64"); - dasmPrintSlot(out, current[1]); - dasmPrintF64(out, ((double *)(current + 2))[0]); + 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 VM_OP_MOV: - current += dasmPrintFixedOp(out, current, "move", 2); + case GST_OP_MOV: + current += dasm_fixed_op(out, current, "move", 2); break; - case VM_OP_CLN: - dasmPrintArg(out, "makeClosure"); - dasmPrintSlot(out, current[1]); - dasmPrintLiteral(out, current[2]); + 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 VM_OP_EQL: - current += dasmPrintFixedOp(out, current, "equals", 3); + case GST_OP_EQL: + current += dasm_fixed_op(out, current, "equals", 3); break; - case VM_OP_LTN: - current += dasmPrintFixedOp(out, current, "lessThan", 3); + case GST_OP_LTN: + current += dasm_fixed_op(out, current, "lessThan", 3); break; - case VM_OP_LTE: - current += dasmPrintFixedOp(out, current, "lessThanEquals", 3); + case GST_OP_LTE: + current += dasm_fixed_op(out, current, "lessThanEquals", 3); break; - case VM_OP_ARR: - current += dasmPrintVarArgOp(out, current, "array", 1); + case GST_OP_ARR: + current += dasm_varg_op(out, current, "array", 1); break; - case VM_OP_DIC: - current += dasmPrintVarArgOp(out, current, "dictionary", 1); + case GST_OP_DIC: + current += dasm_varg_op(out, current, "dictionary", 1); break; - case VM_OP_TCL: - current += dasmPrintVarArgOp(out, current, "tailCall", 1); + case GST_OP_TCL: + current += dasm_varg_op(out, current, "tailCall", 1); break; - case VM_OP_ADM: - current += dasmPrintVarArgOp(out, current, "addMultiple", 1); + case GST_OP_ADM: + current += dasm_varg_op(out, current, "addMultiple", 1); break; - case VM_OP_SBM: - current += dasmPrintVarArgOp(out, current, "subMultiple", 1); + case GST_OP_SBM: + current += dasm_varg_op(out, current, "subMultiple", 1); break; - case VM_OP_MUM: - current += dasmPrintVarArgOp(out, current, "mulMultiple", 1); + case GST_OP_MUM: + current += dasm_varg_op(out, current, "mulMultiple", 1); break; - case VM_OP_DVM: - current += dasmPrintVarArgOp(out, current, "divMultiple", 1); + case GST_OP_DVM: + current += dasm_varg_op(out, current, "divMultiple", 1); break; - case VM_OP_RTN: - current += dasmPrintFixedOp(out, current, "returnNil", 0); + case GST_OP_RTN: + current += dasm_fixed_op(out, current, "returnNil", 0); break; - case VM_OP_GET: - current += dasmPrintFixedOp(out, current, "get", 3); + case GST_OP_GET: + current += dasm_fixed_op(out, current, "get", 3); break; - case VM_OP_SET: - current += dasmPrintFixedOp(out, current, "set", 3); + case GST_OP_SET: + current += dasm_fixed_op(out, current, "set", 3); break; } fprintf(out, "\n"); diff --git a/disasm.h b/disasm.h index 4e56ff13..5df1cbaa 100644 --- a/disasm.h +++ b/disasm.h @@ -5,13 +5,13 @@ #include /* Print disassembly for a given funciton */ -void dasm(FILE * out, uint16_t * byteCode, uint32_t len); +void gst_dasm(FILE * out, uint16_t * byteCode, uint32_t len); /* Print the disassembly for a function definition */ -void dasmFuncDef(FILE * out, FuncDef * def); +void gst_dasm_funcdef(FILE * out, GstFuncDef * def); /* Print the disassembly for a function */ -void dasmFunc(FILE * out, Func * f); +void gst_dasm_function(FILE * out, GstFunction * f); #endif // disasm_h_INCLUDED diff --git a/ds.c b/ds.c index 794275d5..690c926e 100644 --- a/ds.c +++ b/ds.c @@ -8,9 +8,9 @@ /****/ /* Create a new Buffer */ -Buffer * BufferNew(VM * vm, uint32_t capacity) { - Buffer * buffer = VMAlloc(vm, sizeof(Buffer)); - uint8_t * data = VMAlloc(vm, sizeof(uint8_t) * capacity); +GstBuffer *gst_buffer(Gst *vm, uint32_t capacity) { + GstBuffer *buffer = gst_alloc(vm, sizeof(GstBuffer)); + uint8_t *data = gst_alloc(vm, sizeof(uint8_t) * capacity); buffer->data = data; buffer->count = 0; buffer->capacity = capacity; @@ -19,17 +19,17 @@ Buffer * BufferNew(VM * vm, uint32_t capacity) { } /* Ensure that the buffer has enough internal capacity */ -void BufferEnsure(VM * vm, Buffer * buffer, uint32_t capacity) { +void gst_buffer_ensure(Gst *vm, GstBuffer *buffer, uint32_t capacity) { uint8_t * newData; if (capacity <= buffer->capacity) return; - newData = VMAlloc(vm, capacity * sizeof(uint8_t)); + newData = gst_alloc(vm, capacity * sizeof(uint8_t)); memcpy(newData, buffer->data, buffer->count * sizeof(uint8_t)); buffer->data = newData; buffer->capacity = capacity; } /* Get a byte from an index in the buffer */ -int32_t BufferGet(Buffer * buffer, uint32_t index) { +int gst_buffer_get(GstBuffer *buffer, uint32_t index) { if (index < buffer->count) { return buffer->data[index]; } else { @@ -38,29 +38,29 @@ int32_t BufferGet(Buffer * buffer, uint32_t index) { } /* Push a byte into the buffer */ -void BufferPush(VM * vm, Buffer * buffer, uint8_t c) { +void gst_buffer_push(Gst *vm, GstBuffer * buffer, uint8_t c) { if (buffer->count >= buffer->capacity) { - BufferEnsure(vm, buffer, 2 * buffer->count); + gst_buffer_ensure(vm, buffer, 2 * buffer->count); } buffer->data[buffer->count++] = c; } /* Push multiple bytes into the buffer */ -void BufferAppendData(VM * vm, Buffer * buffer, uint8_t * string, uint32_t length) { +void gst_buffer_append(Gst *vm, GstBuffer *buffer, uint8_t *string, uint32_t length) { uint32_t newSize = buffer->count + length; if (newSize > buffer->capacity) { - BufferEnsure(vm, buffer, 2 * newSize); + gst_buffer_ensure(vm, buffer, 2 * newSize); } memcpy(buffer->data + buffer->count, string, length); buffer->count = newSize; } /* Convert the buffer to a string */ -uint8_t * BufferToString(VM * vm, Buffer * buffer) { - uint8_t * data = VMAlloc(vm, buffer->count + 2 * sizeof(uint32_t)); +uint8_t *gst_buffer_to_string(Gst *vm, GstBuffer *buffer) { + uint8_t *data = gst_alloc(vm, buffer->count + 2 * sizeof(uint32_t)); data += 2 * sizeof(uint32_t); - VStringSize(data) = buffer->count; - VStringHash(data) = 0; + gst_string_length(data) = buffer->count; + gst_string_hash(data) = 0; memcpy(data, buffer->data, buffer->count * sizeof(uint8_t)); return data; } @@ -70,9 +70,9 @@ uint8_t * BufferToString(VM * vm, Buffer * buffer) { /****/ /* Creates a new array */ -Array * ArrayNew(VM * vm, uint32_t capacity) { - Array * array = VMAlloc(vm, sizeof(Array)); - Value * data = VMAlloc(vm, capacity * sizeof(Value)); +GstArray *gst_array(Gst * vm, uint32_t capacity) { + GstArray *array = gst_alloc(vm, sizeof(GstArray)); + GstValue *data = gst_alloc(vm, capacity * sizeof(GstValue)); array->data = data; array->count = 0; array->capacity = capacity; @@ -81,30 +81,29 @@ Array * ArrayNew(VM * vm, uint32_t capacity) { } /* Ensure the array has enough capacity for capacity elements */ -void ArrayEnsure(VM * vm, Array * array, uint32_t capacity) { - Value * newData; +void gst_array_ensure(Gst *vm, GstArray *array, uint32_t capacity) { + GstValue *newData; if (capacity <= array->capacity) return; - newData = VMAlloc(vm, capacity * sizeof(Value)); - memcpy(newData, array->data, array->capacity * sizeof(Value)); + newData = gst_alloc(vm, capacity * sizeof(GstValue)); + memcpy(newData, array->data, array->capacity * sizeof(GstValue)); array->data = newData; array->capacity = capacity; } /* Get a value of an array with bounds checking. */ -Value ArrayGet(Array * array, uint32_t index) { +GstValue gst_array_get(GstArray *array, uint32_t index) { if (index < array->count) { return array->data[index]; } else { - Value v; - v.type = TYPE_NIL; - v.data.boolean = 0; + GstValue v; + v.type = GST_NIL; return v; } } /* Try to set an index in the array. Return 1 if successful, 0 * on failiure */ -int ArraySet(Array * array, uint32_t index, Value x) { +int gst_array_set(GstArray *array, uint32_t index, GstValue x) { if (index < array->count) { array->data[index] = x; return 1; @@ -114,33 +113,31 @@ int ArraySet(Array * array, uint32_t index, Value x) { } /* Add an item to the end of the array */ -void ArrayPush(VM * vm, Array * array, Value x) { +void gst_array_push(Gst *vm, GstArray *array, GstValue x) { if (array->count >= array->capacity) { - ArrayEnsure(vm, array, 2 * array->count); + gst_array_ensure(vm, array, 2 * array->count); } array->data[array->count++] = x; } /* Remove the last item from the Array and return it */ -Value ArrayPop(Array * array) { +GstValue gst_array_pop(GstArray *array) { if (array->count) { return array->data[--array->count]; } else { - Value v; - v.type = TYPE_NIL; - v.data.boolean = 0; + GstValue v; + v.type = GST_NIL; return v; } } /* Look at the last item in the Array */ -Value ArrayPeek(Array * array) { +GstValue gst_array_peek(GstArray *array) { if (array->count) { return array->data[array->count - 1]; } else { - Value v; - v.type = TYPE_NIL; - v.data.boolean = 0; + GstValue v; + v.type = GST_NIL; return v; } } @@ -150,76 +147,76 @@ Value ArrayPeek(Array * array) { /****/ /* Create a new dictionary */ -Dictionary * DictNew(VM * vm, uint32_t capacity) { - Dictionary * dict = VMAlloc(vm, sizeof(Dictionary)); - DictBucket ** buckets = VMZalloc(vm, capacity * sizeof(DictBucket *)); - dict->buckets = buckets; - dict->capacity = capacity; - dict->count = 0; - dict->flags = 0; - return dict; +GstObject* gst_object(Gst *vm, uint32_t capacity) { + GstObject *o = gst_alloc(vm, sizeof(GstObject)); + GstBucket **buckets = gst_zalloc(vm, capacity * sizeof(GstBucket *)); + o->buckets = buckets; + o->capacity = capacity; + o->count = 0; + o->flags = 0; + return o; } /* Resize the dictionary table. */ -static void DictReHash(VM * vm, Dictionary * dict, uint32_t size) { - DictBucket ** newBuckets = VMZalloc(vm, size * sizeof(DictBucket *)); +static void gst_object_rehash(Gst *vm, GstObject *o, uint32_t size) { + GstBucket **newBuckets = gst_zalloc(vm, size * sizeof(GstBucket *)); uint32_t i, count; - for (i = 0, count = dict->capacity; i < count; ++i) { - DictBucket * bucket = dict->buckets[i]; + for (i = 0, count = o->capacity; i < count; ++i) { + GstBucket *bucket = o->buckets[i]; while (bucket) { uint32_t index; - DictBucket * next = bucket->next; - index = ValueHash(bucket->key) % size; + GstBucket *next = bucket->next; + index = gst_hash(bucket->key) % size; bucket->next = newBuckets[index]; newBuckets[index] = bucket; bucket = next; } } - dict->buckets = newBuckets; - dict->capacity = size; + o->buckets = newBuckets; + o->capacity = size; } /* Find the bucket that contains the given key */ -static DictBucket * DictFind(Dictionary * dict, Value key) { - uint32_t index = ValueHash(key) % dict->capacity; - DictBucket * bucket = dict->buckets[index]; +static GstBucket *gst_object_find(GstObject *o, GstValue key) { + uint32_t index = gst_hash(key) % o->capacity; + GstBucket *bucket = o->buckets[index]; while (bucket) { - if (ValueEqual(bucket->key, key)) + if (gst_equals(bucket->key, key)) return bucket; bucket = bucket->next; } - return (DictBucket *)0; + return (GstBucket *)0; } /* Get a value out of the dictionary */ -Value DictGet(Dictionary * dict, Value key) { - DictBucket * bucket = DictFind(dict, key); +GstValue gst_object_get(GstObject *o, GstValue key) { + GstBucket *bucket = gst_object_find(o, key); if (bucket) { return bucket->value; } else { - Value nil; - nil.type = TYPE_NIL; + GstValue nil; + nil.type = GST_NIL; return nil; } } /* Remove an entry from the dictionary */ -Value DictRemove(VM * vm, Dictionary * dict, Value key) { - DictBucket * bucket, * previous; - uint32_t index = ValueHash(key) % dict->capacity; - bucket = dict->buckets[index]; - previous = (DictBucket *)0; +GstValue gst_object_remove(Gst * vm, GstObject *o, GstValue key) { + GstBucket *bucket, *previous; + uint32_t index = gst_hash(key) % o->capacity; + bucket = o->buckets[index]; + previous = (GstBucket *)0; while (bucket) { - if (ValueEqual(bucket->key, key)) { + if (gst_equals(bucket->key, key)) { if (previous) { previous->next = bucket->next; } else { - dict->buckets[index] = bucket->next; + o->buckets[index] = bucket->next; } - if (dict->count < dict->capacity / 4) { - DictReHash(vm, dict, dict->capacity / 2); + if (o->count < o->capacity / 4) { + gst_object_rehash(vm, o, o->capacity / 2); } - --dict->count; + --o->count; return bucket->value; } previous = bucket; @@ -227,74 +224,52 @@ Value DictRemove(VM * vm, Dictionary * dict, Value key) { } /* Return nil if we found nothing */ { - Value nil; - nil.type = TYPE_NIL; + GstValue nil; + nil.type = GST_NIL; return nil; } } /* Put a value into the dictionary. Returns 1 if successful, 0 if out of memory. * The VM pointer is needed for memory allocation. */ -void DictPut(VM * vm, Dictionary * dict, Value key, Value value) { - DictBucket * bucket, * previous; - uint32_t index = ValueHash(key) % dict->capacity; - if (key.type == TYPE_NIL) return; +void gst_object_put(Gst *vm, GstObject *o, GstValue key, GstValue value) { + GstBucket *bucket, *previous; + uint32_t index = gst_hash(key) % o->capacity; + if (key.type == GST_NIL) return; /* Do a removal if value is nil */ - if (value.type == TYPE_NIL) { - bucket = dict->buckets[index]; - previous = (DictBucket *)0; + if (value.type == GST_NIL) { + bucket = o->buckets[index]; + previous = (GstBucket *)0; while (bucket) { - if (ValueEqual(bucket->key, key)) { + if (gst_equals(bucket->key, key)) { if (previous) { previous->next = bucket->next; } else { - dict->buckets[index] = bucket->next; + o->buckets[index] = bucket->next; } - if (dict->count < dict->capacity / 4) { - DictReHash(vm, dict, dict->capacity / 2); + if (o->count < o->capacity / 4) { + gst_object_rehash(vm, o, o->capacity / 2); } - --dict->count; + --o->count; return; } previous = bucket; bucket = bucket->next; } } else { - bucket = DictFind(dict, key); + bucket = gst_object_find(o, key); if (bucket) { bucket->value = value; } else { - if (dict->count >= 2 * dict->capacity) { - DictReHash(vm, dict, 2 * dict->capacity); + if (o->count >= 2 * o->capacity) { + gst_object_rehash(vm, o, 2 * o->capacity); } - bucket = VMAlloc(vm, sizeof(DictBucket)); - bucket->next = dict->buckets[index]; + bucket = gst_alloc(vm, sizeof(GstBucket)); + bucket->next = o->buckets[index]; bucket->value = value; bucket->key = key; - dict->buckets[index] = bucket; - ++dict->count; + o->buckets[index] = bucket; + ++o->count; } } } - -/* Begin iteration through a dictionary */ -void DictIterate(Dictionary * dict, DictionaryIterator * iterator) { - iterator->index = 0; - iterator->dict = dict; - iterator->bucket = dict->buckets[0]; -} - -/* Provides a mechanism for iterating through a table. */ -int DictIterateNext(DictionaryIterator * iterator, DictBucket ** bucket) { - Dictionary * dict = iterator->dict; - for (;;) { - if (iterator->bucket) { - *bucket = iterator->bucket; - iterator->bucket = iterator->bucket->next; - return 1; - } - if (++iterator->index >= dict->capacity) break; - iterator->bucket = dict->buckets[iterator->index]; - } - return 0; -} diff --git a/ds.h b/ds.h index c7f7b2e5..725340b8 100644 --- a/ds.h +++ b/ds.h @@ -6,35 +6,35 @@ /* * Data type flags */ -#define DS_LOCKED 0x01 +#define GST_DS_LOCKED 0x01 /****/ /* Buffer functions */ /****/ /* Create a new buffer */ -Buffer * BufferNew(VM * vm, uint32_t capacity); +GstBuffer *gst_buffer(Gst *vm, uint32_t capacity); /* Ensure the buffer has enough capacity */ -void BufferEnsure(VM * vm, Buffer * buffer, uint32_t capacity); +void gst_buffer_ensure(Gst *vm, GstBuffer *buffer, uint32_t capacity); /* Get a value from the buffer */ -int32_t BufferGet(Buffer * buffer, uint32_t index); +int gst_buffer_get(GstBuffer *buffer, uint32_t index); /* Push a value to the buffer */ -void BufferPush(VM * vm, Buffer * buffer, uint8_t c); +void gst_buffer_push(Gst *vm, GstBuffer *buffer, uint8_t c); /* Append a piece of memory to the buffer */ -void BufferAppendData(VM * vm, Buffer * buffer, uint8_t * string, uint32_t length); +void gst_buffer_append(Gst *vm, GstBuffer *buffer, uint8_t *string, uint32_t length); /* Convert the buffer to a string */ -uint8_t * BufferToString(VM * vm, Buffer * buffer); +uint8_t *gst_buffer_to_string(Gst * vm, GstBuffer * buffer); /* Define a push function for pushing a certain type to the buffer */ -#define BufferDefine(name, type) \ -static void BufferPush##name (VM * vm, Buffer * buffer, type x) { \ +#define BUFFER_DEFINE(name, type) \ +static void gst_buffer_push_##name(Gst * vm, GstBuffer * buffer, type x) { \ union { type t; uint8_t bytes[sizeof(type)]; } u; \ - u.t = x; BufferAppendData(vm, buffer, u.bytes, sizeof(type)); \ + u.t = x; gst_buffer_append(vm, buffer, u.bytes, sizeof(type)); \ } /****/ @@ -42,51 +42,45 @@ static void BufferPush##name (VM * vm, Buffer * buffer, type x) { \ /****/ /* Create a new Array */ -Array * ArrayNew(VM * vm, uint32_t capacity); +GstArray *gst_array(Gst *vm, uint32_t capacity); /* Get a value of an array with bounds checking. Returns nil if * outside bounds. */ -Value ArrayGet(Array * array, uint32_t index); +GstValue gst_array_get(GstArray *array, uint32_t index); /* Set a value in the array. Does bounds checking but will not grow * or shrink the array */ -int ArraySet(Array * array, uint32_t index, Value x); +int gst_array_set(GstArray *array, uint32_t index, GstValue x); /* Ensure that the internal memory hash enough space for capacity items */ -void ArrayEnsure(VM * vm, Array * array, uint32_t capacity); +void gst_array_ensure(Gst *vm, GstArray *array, uint32_t capacity); /* Set a value in an array. Will also append to the array if the index is * greater than the current max index. */ -void ArrayPush(VM * vm, Array * array, Value x); +void gst_array_push(Gst *vm, GstArray *array, GstValue x); /* Pop the last item in the array, or return NIL if empty */ -Value ArrayPop(Array * array); +GstValue gst_array_pop(GstArray *array); /* Look at the top most item of an Array */ -Value ArrayPeek(Array * array); +GstValue ArrayPeek(GstArray *array); /****/ -/* Dictionary functions */ +/* Object functions */ /****/ -/* Create a new dictionary */ -Dictionary * DictNew(VM * vm, uint32_t capacity); +/* Create a new object */ +GstObject *gst_object(Gst *vm, uint32_t capacity); /* Get a value out of the dictionary */ -Value DictGet(Dictionary * dict, Value key); +GstValue gst_object_get(GstObject *obj, GstValue key); /* Get a Value from the dictionary, but remove it at the same * time. */ -Value DictRemove(VM * vm, Dictionary * dict, Value key); +GstValue gst_object_remove(Gst *vm, GstObject *obj, GstValue key); /* Put a value into the dictionary. Returns 1 if successful, 0 if out of memory. * The VM pointer is needed for memory allocation. */ -void DictPut(VM * vm, Dictionary * dict, Value key, Value value); - -/* Begin iteration through a dictionary */ -void DictIterate(Dictionary * dict, DictionaryIterator * iterator); - -/* Provides a mechanism for iterating through a table. */ -int DictIterateNext(DictionaryIterator * iterator, DictBucket ** bucket); +void gst_object_put(Gst *vm, GstObject *obj, GstValue key, GstValue value); #endif // ds_h_INCLUDED diff --git a/main.c b/main.c index 6e8eda85..2bc3e1be 100644 --- a/main.c +++ b/main.c @@ -7,24 +7,23 @@ #include "value.h" #include "disasm.h" -void StringPut(uint8_t * string) { +void string_put(uint8_t * string) { uint32_t i; - uint32_t len = VStringSize(string); + uint32_t len = gst_string_length(string); for (i = 0; i < len; ++i) fputc(string[i], stdout); } /* Test c function */ -Value print(VM * vm) { +GstValue print(Gst *vm) { uint32_t j, count; - Value nil; - count = VMCountArgs(vm); + GstValue nil; + count = gst_count_args(vm); for (j = 0; j < count; ++j) { - uint8_t * string = ValueToString(vm, VMGetArg(vm, j)); - StringPut(string); + string_put(gst_to_string(vm, gst_arg(vm, j))); fputc('\n', stdout); } - nil.type = TYPE_NIL; + nil.type = GST_NIL; return nil; } @@ -32,20 +31,20 @@ Value print(VM * vm) { void debugRepl() { char buffer[1024] = {0}; const char * reader = buffer; - Value func; - VM vm; - Parser p; - Compiler c; + GstValue func; + Gst vm; + GstParser p; + GstCompiler c; - VMInit(&vm); + gst_init(&vm); for (;;) { /* Reset state */ - ParserInit(&p, &vm); + gst_parser(&p, &vm); /* Get and parse input until we have a full form */ - while (p.status == PARSER_PENDING) { + while (p.status == GST_PARSER_PENDING) { /* Get some input if we are done */ if (*reader == '\0') { printf(">> "); @@ -55,7 +54,7 @@ void debugRepl() { p.index = 0; reader = buffer; } - reader += ParserParseCString(&p, reader); + reader += gst_parse_cstring(&p, reader); } /* Check for parsing errors */ @@ -74,10 +73,10 @@ void debugRepl() { } /* Try to compile generated AST */ - CompilerInit(&c, &vm); - CompilerAddGlobalCFunc(&c, "print", print); - func.type = TYPE_FUNCTION; - func.data.func = CompilerCompile(&c, p.value); + gst_compiler(&c, &vm); + gst_compiler_add_global_cfunction(&c, "print", print); + func.type = GST_FUNCTION; + func.data.function = gst_compiler_compile(&c, p.value); /* Check for compilation errors */ if (c.error) { @@ -93,15 +92,14 @@ void debugRepl() { //printf("\n"); /* Execute function */ - VMLoad(&vm, func); - if (VMStart(&vm)) { + gst_load(&vm, func); + if (gst_start(&vm)) { printf("VM error: %s\n", vm.error); reader = buffer; buffer[0] = 0; continue; } else { - uint8_t * string = ValueToString(&vm, vm.ret); - StringPut(string); + string_put(gst_to_string(&vm, vm.ret)); printf("\n"); } } diff --git a/parse.c b/parse.c index 8a5f6483..68ea5a8c 100644 --- a/parse.c +++ b/parse.c @@ -19,15 +19,15 @@ typedef enum ParseType { } ParseType; /* Contain a parse state that goes on the parse stack */ -struct ParseState { +struct GstParseState { ParseType type; union { struct { uint8_t endDelimiter; - Array * array; + GstArray * array; } form; struct { - Buffer * buffer; + GstBuffer * buffer; enum { STRING_STATE_BASE, STRING_STATE_ESCAPE, @@ -39,37 +39,37 @@ struct ParseState { }; /* Handle error in parsing */ -#define PError(p, e) ((p)->error = (e), (p)->status = PARSER_ERROR) +#define p_error(p, e) ((p)->error = (e), (p)->status = GST_PARSER_ERROR) /* Get the top ParseState in the parse stack */ -static ParseState * ParserPeek(Parser * p) { +static GstParseState *parser_peek(GstParser *p) { if (!p->count) { - PError(p, "Parser stack underflow. (Peek)"); + p_error(p, "Parser stack underflow. (Peek)"); return NULL; } return p->data + p->count - 1; } /* Remove the top state from the ParseStack */ -static ParseState * ParserPop(Parser * p) { +static GstParseState *parser_pop(GstParser * p) { if (!p->count) { - PError(p, "Parser stack underflow. (Pop)"); + p_error(p, "Parser stack underflow. (Pop)"); return NULL; } return p->data + --p->count; } /* Add a new, empty ParseState to the ParseStack. */ -static void ParserPush(Parser *p, ParseType type, uint8_t character) { - ParseState * top; +static void parser_push(GstParser *p, ParseType type, uint8_t character) { + GstParseState *top; if (p->count >= p->cap) { uint32_t newCap = 2 * p->count; - ParseState * data = VMAlloc(p->vm, newCap); + GstParseState *data = gst_alloc(p->vm, newCap); p->data = data; p->cap = newCap; } ++p->count; - top = ParserPeek(p); + top = parser_peek(p); if (!top) return; top->type = type; switch (type) { @@ -78,48 +78,48 @@ static void ParserPush(Parser *p, ParseType type, uint8_t character) { case PTYPE_STRING: top->buf.string.state = STRING_STATE_BASE; case PTYPE_TOKEN: - top->buf.string.buffer = BufferNew(p->vm, 10); + top->buf.string.buffer = gst_buffer(p->vm, 10); break; case PTYPE_FORM: - top->buf.form.array = ArrayNew(p->vm, 10); + top->buf.form.array = gst_array(p->vm, 10); if (character == '(') top->buf.form.endDelimiter = ')'; if (character == '[') { top->buf.form.endDelimiter = ']'; - ArrayPush(p->vm, top->buf.form.array, ValueLoadCString(p->vm, "array")); + gst_array_push(p->vm, top->buf.form.array, gst_load_cstring(p->vm, "array")); } if (character == '{') { top->buf.form.endDelimiter = '}'; - ArrayPush(p->vm, top->buf.form.array, ValueLoadCString(p->vm, "dict")); + gst_array_push(p->vm, top->buf.form.array, gst_load_cstring(p->vm, "dict")); } break; } } /* Append a value to the top-most state in the Parser's stack. */ -static void ParserTopAppend(Parser * p, Value x) { - ParseState * top = ParserPeek(p); +static void parser_append(GstParser *p, GstValue x) { + GstParseState *top = parser_peek(p); if (!top) return; switch (top->type) { case PTYPE_ROOT: p->value = x; - p->status = PARSER_FULL; + p->status = GST_PARSER_FULL; break; case PTYPE_FORM: - ArrayPush(p->vm, top->buf.form.array, x); + gst_array_push(p->vm, top->buf.form.array, x); break; default: - PError(p, "Expected container type."); + p_error(p, "Expected container type."); break; } } /* Check if a character is whitespace */ -static int isWhitespace(uint8_t c) { +static int is_whitespace(uint8_t c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\0' || c == ','; } /* Check if a character is a valid symbol character */ -static int isSymbolChar(uint8_t c) { +static int is_symbol_char(uint8_t c) { if (c >= 'a' && c <= 'z') return 1; if (c >= 'A' && c <= 'Z') return 1; if (c >= '0' && c <= ':') return 1; @@ -148,10 +148,13 @@ static double exp10(int power) { } } -/* Read a number from a string */ -static int ParseReadNumber(const uint8_t * string, const uint8_t * end, double * ret, int forceInt) { +/* Read a number from a string. Returns if successfuly + * parsed a number from the enitre input string. + * If returned 1, output is int ret.*/ +static int read_number(const uint8_t *string, const uint8_t *end, double *ret, int forceInt) { int sign = 1, x = 0; double accum = 0, exp = 1, place = 1; + /* Check the sign */ if (*string == '-') { sign = -1; ++string; @@ -163,8 +166,10 @@ static int ParseReadNumber(const uint8_t * string, const uint8_t * end, double * if (*string == '.' && !forceInt) { place = 0.1; } else if (!forceInt && (*string == 'e' || *string == 'E')) { + /* Read the exponent */ ++string; - if (!ParseReadNumber(string, end, &exp, 1)) + if (string >= end) return 0; + if (!read_number(string, end, &exp, 1)) return 0; exp = exp10(exp); break; @@ -187,7 +192,7 @@ static int ParseReadNumber(const uint8_t * string, const uint8_t * end, double * } /* Checks if a string slice is equal to a string constant */ -static int checkStrConst(const char * ref, const uint8_t * start, const uint8_t * end) { +static int check_str_const(const char *ref, const uint8_t *start, const uint8_t *end) { while (*ref && start < end) { if (*ref != *(char *)start) return 0; ++ref; @@ -197,72 +202,72 @@ static int checkStrConst(const char * ref, const uint8_t * start, const uint8_t } /* Build from the token buffer */ -static Value ParserBuildTokenBuffer(Parser * p, Buffer * buf) { - Value x; - Number number; +static GstValue build_token(GstParser *p, GstBuffer *buf) { + GstValue x; + GstNumber number; uint8_t * data = buf->data; uint8_t * back = data + buf->count; - if (ParseReadNumber(data, back, &number, 0)) { - x.type = TYPE_NUMBER; + if (read_number(data, back, &number, 0)) { + x.type = GST_NUMBER; x.data.number = number; - } else if (checkStrConst("nil", data, back)) { - x.type = TYPE_NIL; + } else if (check_str_const("nil", data, back)) { + x.type = GST_NIL; x.data.boolean = 0; - } else if (checkStrConst("false", data, back)) { - x.type = TYPE_BOOLEAN; + } else if (check_str_const("false", data, back)) { + x.type = GST_BOOLEAN; x.data.boolean = 0; - } else if (checkStrConst("true", data, back)) { - x.type = TYPE_BOOLEAN; + } else if (check_str_const("true", data, back)) { + x.type = GST_BOOLEAN; x.data.boolean = 1; } else { if (buf->data[0] >= '0' && buf->data[0] <= '9') { - PError(p, "Symbols cannot start with digits."); - x.type = TYPE_NIL; + p_error(p, "Symbols cannot start with digits."); + x.type = GST_NIL; } else { - x.type = TYPE_STRING; - x.data.string = BufferToString(p->vm, buf); + x.type = GST_STRING; + x.data.string = gst_buffer_to_string(p->vm, buf); } } return x; } /* Handle parsing a token */ -static int ParserTokenState(Parser * p, uint8_t c) { - ParseState * top = ParserPeek(p); - Buffer * buf = top->buf.string.buffer; - if (isWhitespace(c) || c == ')' || c == ']' || c == '}') { - ParserPop(p); - ParserTopAppend(p, ParserBuildTokenBuffer(p, buf)); +static int token_state(GstParser *p, uint8_t c) { + GstParseState *top = parser_peek(p); + GstBuffer *buf = top->buf.string.buffer; + if (is_whitespace(c) || c == ')' || c == ']' || c == '}') { + parser_pop(p); + parser_append(p, build_token(p, buf)); return !(c == ')' || c == ']' || c == '}'); - } else if (isSymbolChar(c)) { - BufferPush(p->vm, buf, c); + } else if (is_symbol_char(c)) { + gst_buffer_push(p->vm, buf, c); return 1; } else { - PError(p, "Expected symbol character."); + p_error(p, "Expected symbol character."); return 1; } } /* Handle parsing a string literal */ -static int ParserStringState(Parser * p, uint8_t c) { - ParseState * top = ParserPeek(p); +static int string_state(GstParser *p, uint8_t c) { + GstParseState *top = parser_peek(p); switch (top->buf.string.state) { case STRING_STATE_BASE: if (c == '\\') { top->buf.string.state = STRING_STATE_ESCAPE; } else if (c == '"') { /* Load a quote form to get the string literal */ - Value x, array; - x.type = TYPE_STRING; - x.data.string = BufferToString(p->vm, top->buf.string.buffer); - array.type = TYPE_ARRAY; - array.data.array = ArrayNew(p->vm, 2); - ArrayPush(p->vm, array.data.array, ValueLoadCString(p->vm, "quote")); - ArrayPush(p->vm, array.data.array, x); - ParserPop(p); - ParserTopAppend(p, array); + GstValue x, array; + x.type = GST_STRING; + x.data.string = gst_buffer_to_string(p->vm, top->buf.string.buffer); + array.type = GST_ARRAY; + array.data.array = gst_array(p->vm, 2); + gst_array_push(p->vm, array.data.array, gst_load_cstring(p->vm, "quote")); + gst_array_push(p->vm, array.data.array, x); + parser_pop(p); + parser_append(p, array); } else { - BufferPush(p->vm, top->buf.string.buffer, c); + gst_buffer_push(p->vm, top->buf.string.buffer, c); } break; case STRING_STATE_ESCAPE: @@ -278,10 +283,10 @@ static int ParserStringState(Parser * p, uint8_t c) { case '\'': next = '\''; break; case 'z': next = '\0'; break; default: - PError(p, "Unknown string escape sequence."); + p_error(p, "Unknown string escape sequence."); return 1; } - BufferPush(p->vm, top->buf.string.buffer, next); + gst_buffer_push(p->vm, top->buf.string.buffer, next); top->buf.string.state = STRING_STATE_BASE; } break; @@ -294,60 +299,60 @@ static int ParserStringState(Parser * p, uint8_t c) { } /* Root state of the parser */ -static int ParserRootState(Parser * p, uint8_t c) { +static int root_state(GstParser *p, uint8_t c) { if (c == ']' || c == ')' || c == '}') { - PError(p, UNEXPECTED_CLOSING_DELIM); + p_error(p, UNEXPECTED_CLOSING_DELIM); return 1; } if (c == '(' || c == '[' || c == '{') { - ParserPush(p, PTYPE_FORM, c); + parser_push(p, PTYPE_FORM, c); return 1; } if (c == '"') { - ParserPush(p, PTYPE_STRING, c); + parser_push(p, PTYPE_STRING, c); return 1; } - if (isWhitespace(c)) return 1; - if (isSymbolChar(c)) { - ParserPush(p, PTYPE_TOKEN, c); + if (is_whitespace(c)) return 1; + if (is_symbol_char(c)) { + parser_push(p, PTYPE_TOKEN, c); return 0; } - PError(p, "Unexpected character."); + p_error(p, "Unexpected character."); return 1; } /* Handle parsing a form */ -static int ParserFormState(Parser * p, uint8_t c) { - ParseState * top = ParserPeek(p); +static int form_state(GstParser *p, uint8_t c) { + GstParseState *top = parser_peek(p); if (c == top->buf.form.endDelimiter) { - Array * array = top->buf.form.array; - Value x; - x.type = TYPE_ARRAY; + GstArray *array = top->buf.form.array; + GstValue x; + x.type = GST_ARRAY; x.data.array = array; - ParserPop(p); - ParserTopAppend(p, x); + parser_pop(p); + parser_append(p, x); return 1; } - return ParserRootState(p, c); + return root_state(p, c); } /* Handle a character */ -static int ParserDispatchChar(Parser * p, uint8_t c) { +static int dispatch_char(GstParser *p, uint8_t c) { int done = 0; - while (!done && p->status == PARSER_PENDING) { - ParseState * top = ParserPeek(p); + while (!done && p->status == GST_PARSER_PENDING) { + GstParseState *top = parser_peek(p); switch (top->type) { case PTYPE_ROOT: - done = ParserRootState(p, c); + done = root_state(p, c); break; case PTYPE_TOKEN: - done = ParserTokenState(p, c); + done = token_state(p, c); break; case PTYPE_FORM: - done = ParserFormState(p, c); + done = form_state(p, c); break; case PTYPE_STRING: - done = ParserStringState(p, c); + done = string_state(p, c); break; } } @@ -360,25 +365,25 @@ static int ParserDispatchChar(Parser * p, uint8_t c) { * was not read. Returns 1 if any values were read, otherwise returns 0. * Returns the number of bytes read. */ -int ParserParseCString(Parser * p, const char * string) { +int gst_parse_cstring(GstParser *p, const char *string) { int bytesRead = 0; - p->status = PARSER_PENDING; - while ((p->status == PARSER_PENDING) && (string[bytesRead] != '\0')) { - ParserDispatchChar(p, string[bytesRead++]); + p->status = GST_PARSER_PENDING; + while ((p->status == GST_PARSER_PENDING) && (string[bytesRead] != '\0')) { + dispatch_char(p, string[bytesRead++]); } return bytesRead; } /* Parser initialization (memory allocation) */ -void ParserInit(Parser * p, VM * vm) { +void gst_parser(GstParser *p, Gst *vm) { p->vm = vm; - ParseState * data = VMAlloc(vm, sizeof(ParseState) * 10); + GstParseState *data = gst_alloc(vm, sizeof(GstParseState) * 10); p->data = data; p->count = 0; p->cap = 10; p->index = 0; p->error = NULL; - p->status = PARSER_PENDING; - p->value.type = TYPE_NIL; - ParserPush(p, PTYPE_ROOT, ' '); + p->status = GST_PARSER_PENDING; + p->value.type = GST_NIL; + parser_push(p, PTYPE_ROOT, ' '); } diff --git a/parse.h b/parse.h index 80a4cee1..1ec80c1f 100644 --- a/parse.h +++ b/parse.h @@ -3,12 +3,10 @@ #include "datatypes.h" -#define PARSE_ERROR -1 -#define PARSE_VALUE_READ 1 -#define PARSE_VALUE_PENDING 0 +/* Initialize a parser */ +void gst_parser(GstParser *p, Gst *vm); -void ParserInit(Parser * p, VM * vm); - -int ParserParseCString(Parser * p, const char * string); +/* Parse a c style string. Returns true if successful */ +int gst_parse_cstring(GstParser *p, const char *string); #endif /* end of include guard: PARSE_H_ONYWMADW */ diff --git a/value.c b/value.c index 2dcb1799..037e0c86 100644 --- a/value.c +++ b/value.c @@ -5,44 +5,44 @@ #include "ds.h" #include "vm.h" -static uint8_t * LoadCString(VM * vm, const char * string, uint32_t len) { - uint8_t * data = VMAlloc(vm, len + 2 * sizeof(uint32_t)); +static uint8_t * load_cstring(Gst *vm, const char *string, uint32_t len) { + uint8_t *data = gst_alloc(vm, len + 2 * sizeof(uint32_t)); data += 2 * sizeof(uint32_t); - VStringHash(data) = 0; - VStringSize(data) = len; + gst_string_hash(data) = 0; + gst_string_length(data) = len; memcpy(data, string, len); return data; } -Value ValueLoadCString(VM * vm, const char * string) { - Value ret; - ret.type = TYPE_STRING; - ret.data.string = LoadCString(vm, string, strlen(string)); +GstValue gst_load_cstring(Gst *vm, const char *string) { + GstValue ret; + ret.type = GST_STRING; + ret.data.string = load_cstring(vm, string, strlen(string)); return ret; } -static uint8_t * NumberToString(VM * vm, Number x) { +static uint8_t * number_to_string(Gst *vm, GstNumber x) { static const uint32_t SIZE = 20; - uint8_t * data = VMAlloc(vm, SIZE + 2 * sizeof(uint32_t)); + uint8_t *data = gst_alloc(vm, SIZE + 2 * sizeof(uint32_t)); data += 2 * sizeof(uint32_t); snprintf((char *) data, SIZE, "%.17g", x); - VStringHash(data) = 0; - VStringSize(data) = strlen((char *) data); + gst_string_hash(data) = 0; + gst_string_length(data) = strlen((char *) data); return data; } -static const char * HEX_CHARACTERS = "0123456789abcdef"; +static const char *HEX_CHARACTERS = "0123456789abcdef"; #define HEX(i) (((uint8_t *) HEX_CHARACTERS)[(i)]) /* Returns a string description for a pointer */ -static uint8_t * StringDescription(VM * vm, const char * title, uint32_t titlelen, void * pointer) { +static uint8_t *string_description(Gst *vm, const char *title, uint32_t titlelen, void *pointer) { uint32_t len = 5 + titlelen + sizeof(void *) * 2; uint32_t i; - uint8_t * data = VMAlloc(vm, len + 2 * sizeof(uint32_t)); - uint8_t * c; + uint8_t *data = gst_alloc(vm, len + 2 * sizeof(uint32_t)); + uint8_t *c; union { uint8_t bytes[sizeof(void *)]; - void * p; + void *p; } buf; buf.p = pointer; data += 2 * sizeof(uint32_t); @@ -61,58 +61,57 @@ static uint8_t * StringDescription(VM * vm, const char * title, uint32_t titlele *c++ = HEX(byte & 0xF); } *c++ = '>'; - VStringHash(data) = 0; - VStringSize(data) = c - data; + gst_string_hash(data) = 0; + gst_string_length(data) = c - data; return data; } /* Returns a string pointer or NULL if could not allocate memory. */ -uint8_t * ValueToString(VM * vm, Value x) { +uint8_t *gst_to_string(Gst *vm, GstValue x) { switch (x.type) { - case TYPE_NIL: - return LoadCString(vm, "nil", 3); - case TYPE_BOOLEAN: + case GST_NIL: + return load_cstring(vm, "nil", 3); + case GST_BOOLEAN: if (x.data.boolean) { - return LoadCString(vm, "true", 4); + return load_cstring(vm, "true", 4); } else { - return LoadCString(vm, "false", 5); + return load_cstring(vm, "false", 5); } - case TYPE_NUMBER: - return NumberToString(vm, x.data.number); - case TYPE_ARRAY: + case GST_NUMBER: + return number_to_string(vm, x.data.number); + case GST_ARRAY: { uint32_t i; - Buffer * b = BufferNew(vm, 40); - BufferPush(vm, b, '('); + GstBuffer * b = gst_buffer(vm, 40); + gst_buffer_push(vm, b, '('); for (i = 0; i < x.data.array->count; ++i) { - uint8_t * substr = ValueToString(vm, x.data.array->data[i]); - BufferAppendData(vm, b, substr, VStringSize(substr)); + uint8_t * substr = gst_to_string(vm, x.data.array->data[i]); + gst_buffer_append(vm, b, substr, gst_string_length(substr)); if (i < x.data.array->count - 1) - BufferPush(vm, b, ' '); + gst_buffer_push(vm, b, ' '); } - BufferPush(vm, b, ')'); - return BufferToString(vm, b); + gst_buffer_push(vm, b, ')'); + return gst_buffer_to_string(vm, b); } - return StringDescription(vm, "array", 5, x.data.pointer); - case TYPE_STRING: + case GST_STRING: return x.data.string; - case TYPE_BYTEBUFFER: - return StringDescription(vm, "buffer", 6, x.data.pointer); - case TYPE_CFUNCTION: - return StringDescription(vm, "cfunction", 9, x.data.pointer); - case TYPE_FUNCTION: - return StringDescription(vm, "function", 8, x.data.pointer); - case TYPE_DICTIONARY: - return StringDescription(vm, "dictionary", 10, x.data.pointer); - case TYPE_THREAD: - return StringDescription(vm, "thread", 6, x.data.pointer); + case GST_BYTEBUFFER: + return string_description(vm, "buffer", 6, x.data.pointer); + case GST_CFUNCTION: + return string_description(vm, "cfunction", 9, x.data.pointer); + case GST_FUNCTION: + return string_description(vm, "function", 8, x.data.pointer); + case GST_OBJECT: + return string_description(vm, "object", 6, x.data.pointer); + case GST_THREAD: + return string_description(vm, "thread", 6, x.data.pointer); } return NULL; } /* Simple hash function */ uint32_t djb2(const uint8_t * str) { - const uint8_t * end = str + VStringSize(str); + const uint8_t * end = str + gst_string_length(str); uint32_t hash = 5381; while (str < end) hash = (hash << 5) + hash + *str++; @@ -120,45 +119,45 @@ uint32_t djb2(const uint8_t * str) { } /* Check if two values are equal. This is strict equality with no conversion. */ -int ValueEqual(Value x, Value y) { +int gst_equals(GstValue x, GstValue y) { int result = 0; if (x.type != y.type) { result = 0; } else { switch (x.type) { - case TYPE_NIL: + case GST_NIL: result = 1; break; - case TYPE_BOOLEAN: + case GST_BOOLEAN: result = (x.data.boolean == y.data.boolean); break; - case TYPE_NUMBER: + case GST_NUMBER: result = (x.data.number == y.data.number); break; /* Assume that when strings are created, equal strings * are set to the same string */ - case TYPE_STRING: + case GST_STRING: if (x.data.string == y.data.string) { result = 1; break; } - if (ValueHash(x) != ValueHash(y) || - VStringSize(x.data.string) != VStringSize(y.data.string)) { + if (gst_hash(x) != gst_hash(y) || + gst_string_length(x.data.string) != gst_string_length(y.data.string)) { result = 0; break; } - if (!strncmp((char *) x.data.string, (char *) y.data.string, VStringSize(x.data.string))) { + if (!strncmp((char *) x.data.string, (char *) y.data.string, gst_string_length(x.data.string))) { result = 1; break; } result = 0; break; - case TYPE_ARRAY: - case TYPE_BYTEBUFFER: - case TYPE_CFUNCTION: - case TYPE_DICTIONARY: - case TYPE_FUNCTION: - case TYPE_THREAD: + case GST_ARRAY: + case GST_BYTEBUFFER: + case GST_CFUNCTION: + case GST_OBJECT: + case GST_FUNCTION: + case GST_THREAD: /* compare pointers */ result = (x.data.array == y.data.array); break; @@ -168,39 +167,39 @@ int ValueEqual(Value x, Value y) { } /* Computes a hash value for a function */ -uint32_t ValueHash(Value x) { +uint32_t gst_hash(GstValue x) { uint32_t hash = 0; switch (x.type) { - case TYPE_NIL: + case GST_NIL: hash = 0; break; - case TYPE_BOOLEAN: + case GST_BOOLEAN: hash = x.data.boolean; break; - case TYPE_NUMBER: + case GST_NUMBER: { union { uint32_t hash; - Number number; + GstNumber number; } u; u.number = x.data.number; hash = u.hash; } break; /* String hashes */ - case TYPE_STRING: + case GST_STRING: /* Assume 0 is not hashed. */ - if (VStringHash(x.data.string)) - hash = VStringHash(x.data.string); + if (gst_string_hash(x.data.string)) + hash = gst_string_hash(x.data.string); else - hash = VStringHash(x.data.string) = djb2(x.data.string); + hash = gst_string_hash(x.data.string) = djb2(x.data.string); break; - case TYPE_ARRAY: - case TYPE_BYTEBUFFER: - case TYPE_CFUNCTION: - case TYPE_DICTIONARY: - case TYPE_FUNCTION: - case TYPE_THREAD: + case GST_ARRAY: + case GST_BYTEBUFFER: + case GST_CFUNCTION: + case GST_OBJECT: + case GST_FUNCTION: + case GST_THREAD: /* Cast the pointer */ { union { @@ -218,30 +217,30 @@ uint32_t ValueHash(Value x) { /* Compares x to y. If they are equal retuns 0. If x is less, returns -1. * If y is less, returns 1. All types are comparable * and should have strict ordering. */ -int ValueCompare(Value x, Value y) { +int gst_compare(GstValue x, GstValue y) { if (x.type == y.type) { switch (x.type) { - case TYPE_NIL: + case GST_NIL: return 0; - case TYPE_BOOLEAN: + case GST_BOOLEAN: if (x.data.boolean == y.data.boolean) { return 0; } else { return x.data.boolean ? 1 : -1; } - case TYPE_NUMBER: + case GST_NUMBER: /* TODO: define behavior for NaN and infinties. */ if (x.data.number == y.data.number) { return 0; } else { return x.data.number > y.data.number ? 1 : -1; } - case TYPE_STRING: + case GST_STRING: if (x.data.string == y.data.string) { return 0; } else { - uint32_t xlen = VStringSize(x.data.string); - uint32_t ylen = VStringSize(y.data.string); + uint32_t xlen = gst_string_length(x.data.string); + uint32_t ylen = gst_string_length(y.data.string); uint32_t len = xlen > ylen ? ylen : xlen; uint32_t i; for (i = 0; i < len; ++i) { @@ -259,12 +258,12 @@ int ValueCompare(Value x, Value y) { return xlen < ylen ? -1 : 1; } } - case TYPE_ARRAY: - case TYPE_BYTEBUFFER: - case TYPE_CFUNCTION: - case TYPE_FUNCTION: - case TYPE_DICTIONARY: - case TYPE_THREAD: + case GST_ARRAY: + case GST_BYTEBUFFER: + case GST_CFUNCTION: + case GST_FUNCTION: + case GST_OBJECT: + case GST_THREAD: if (x.data.string == y.data.string) { return 0; } else { @@ -280,9 +279,9 @@ int ValueCompare(Value x, Value y) { /* Allow negative indexing to get from end of array like structure */ /* This probably isn't very fast - look at Lua conversion function. * I would like to keep this standard C for as long as possible, though. */ -static int32_t ToIndex(Number raw, int64_t len) { +static int32_t to_index(GstNumber raw, int64_t len) { int32_t toInt = raw; - if ((Number) toInt == raw) { + if ((GstNumber) toInt == raw) { /* We were able to convert */ if (toInt < 0) { /* Index from end */ @@ -299,65 +298,65 @@ static int32_t ToIndex(Number raw, int64_t len) { } /* Convert a number into a byte. */ -static uint8_t NumberToByte(Number raw) { +static uint8_t to_byte(GstNumber raw) { if (raw > 255) return 255; if (raw < 0) return 0; return (uint8_t) raw; } /* Get a value out af an associated data structure. Can throw VM error. */ -Value ValueGet(VM * vm, Value ds, Value key) { +GstValue gst_get(Gst *vm, GstValue ds, GstValue key) { int32_t index; - Value ret; + GstValue ret; switch (ds.type) { - case TYPE_ARRAY: - VMAssertType(vm, key, TYPE_NUMBER); - index = ToIndex(key.data.number, ds.data.array->count); - if (index == -1) VMError(vm, "Invalid array access"); + case GST_ARRAY: + gst_assert_type(vm, key, GST_NUMBER); + index = to_index(key.data.number, ds.data.array->count); + if (index == -1) gst_error(vm, "Invalid array access"); return ds.data.array->data[index]; - case TYPE_BYTEBUFFER: - VMAssertType(vm, key, TYPE_NUMBER); - index = ToIndex(key.data.number, ds.data.buffer->count); - if (index == -1) VMError(vm, "Invalid buffer access"); - ret.type = TYPE_NUMBER; + case GST_BYTEBUFFER: + gst_assert_type(vm, key, GST_NUMBER); + index = to_index(key.data.number, ds.data.buffer->count); + if (index == -1) gst_error(vm, "Invalid buffer access"); + ret.type = GST_NUMBER; ret.data.number = ds.data.buffer->data[index]; break; - case TYPE_STRING: - VMAssertType(vm, key, TYPE_NUMBER); - index = ToIndex(key.data.number, VStringSize(ds.data.string)); - if (index == -1) VMError(vm, "Invalid string access"); - ret.type = TYPE_NUMBER; + case GST_STRING: + gst_assert_type(vm, key, GST_NUMBER); + index = to_index(key.data.number, gst_string_length(ds.data.string)); + if (index == -1) gst_error(vm, "Invalid string access"); + ret.type = GST_NUMBER; ret.data.number = ds.data.string[index]; break; - case TYPE_DICTIONARY: - return DictGet(ds.data.dict, key); + case GST_OBJECT: + return gst_object_get(ds.data.object, key); default: - VMError(vm, "Cannot get."); + gst_error(vm, "Cannot get."); } return ret; } /* Set a value in an associative data structure. Can throw VM error. */ -void ValueSet(VM * vm, Value ds, Value key, Value value) { +void gst_set(Gst *vm, GstValue ds, GstValue key, GstValue value) { int32_t index; switch (ds.type) { - case TYPE_ARRAY: - VMAssertType(vm, key, TYPE_NUMBER); - index = ToIndex(key.data.number, ds.data.array->count); - if (index == -1) VMError(vm, "Invalid array access"); + case GST_ARRAY: + gst_assert_type(vm, key, GST_NUMBER); + index = to_index(key.data.number, ds.data.array->count); + if (index == -1) gst_error(vm, "Invalid array access"); ds.data.array->data[index] = value; break; - case TYPE_BYTEBUFFER: - VMAssertType(vm, key, TYPE_NUMBER); - VMAssertType(vm, value, TYPE_NUMBER); - index = ToIndex(key.data.number, ds.data.buffer->count); - if (index == -1) VMError(vm, "Invalid buffer access"); - ds.data.buffer->data[index] = NumberToByte(value.data.number); + case GST_BYTEBUFFER: + gst_assert_type(vm, key, GST_NUMBER); + gst_assert_type(vm, value, GST_NUMBER); + index = to_index(key.data.number, ds.data.buffer->count); + if (index == -1) gst_error(vm, "Invalid buffer access"); + ds.data.buffer->data[index] = to_byte(value.data.number); break; - case TYPE_DICTIONARY: - DictPut(vm, ds.data.dict, key, value); + case GST_OBJECT: + gst_object_put(vm, ds.data.object, key, value); break; default: - VMError(vm, "Cannot set."); + gst_error(vm, "Cannot set."); } } diff --git a/value.h b/value.h index 8b13b3b7..8314f7ee 100644 --- a/value.h +++ b/value.h @@ -3,18 +3,27 @@ #include "datatypes.h" -int ValueCompare(Value x, Value y); +/* Compare two gst values. All gst values are comparable and strictly + * ordered by default. Return 0 if equal, -1 if x is less than y, and + * 1 and x is greater than y. */ +int gst_compare(GstValue x, GstValue y); -int ValueEqual(Value x, Value y); +/* Returns if two values are equal. */ +int gst_equals(GstValue x, GstValue y); -Value ValueGet(VM * vm, Value ds, Value key); +/* Get a value from an associative gst object. Can throw errors. */ +GstValue gst_get(Gst *vm, GstValue ds, GstValue key); -void ValueSet(VM * vm, Value ds, Value key, Value value); +/* Set a value in an associative gst object. Can throw errors. */ +void gst_set(Gst *vm, GstValue ds, GstValue key, GstValue value); -Value ValueLoadCString(VM * vm, const char * string); +/* Load a c style string into a gst value (copies data) */ +GstValue gst_load_cstring(Gst *vm, const char *string); -uint8_t * ValueToString(VM * vm, Value x); +/* Convert any gst value into a string */ +uint8_t *gst_to_string(Gst *vm, GstValue x); -uint32_t ValueHash(Value x); +/* Generate a hash value for a gst object */ +uint32_t gst_hash(GstValue x); #endif /* end of include guard: VALUE_H_1RJPQKFM */ diff --git a/vm.c b/vm.c index 8a155fc3..88e7a66c 100644 --- a/vm.c +++ b/vm.c @@ -12,15 +12,85 @@ static const char VMS_EXPECTED_NUMBER_ROP[] = "Expected right operand to be numb static const char VMS_EXPECTED_NUMBER_LOP[] = "Expected left operand to be number"; /* The size of a StackFrame in units of Values. */ -#define FRAME_SIZE ((sizeof(StackFrame) + sizeof(Value) - 1) / sizeof(Value)) +#define FRAME_SIZE ((sizeof(GstStackFrame) + sizeof(GstValue) - 1) / sizeof(GstValue)) /* Get the stack frame pointer for a thread */ -static StackFrame * ThreadFrame(Thread * thread) { - return (StackFrame *)(thread->data + thread->count - FRAME_SIZE); +static GstStackFrame *thread_frame(GstThread * thread) { + return (GstStackFrame *)(thread->data + thread->count - FRAME_SIZE); } +/* Ensure that a thread has enough space in it */ +static void thread_ensure(Gst *vm, GstThread *thread, uint32_t size) { + if (size > thread->capacity) { + uint32_t newCap = size * 2; + GstValue *newData = gst_alloc(vm, sizeof(GstValue) * newCap); + memcpy(newData, thread->data, thread->capacity * sizeof(GstValue)); + thread->data = newData; + thread->capacity = newCap; + } +} + +/* Push a stack frame onto a thread */ +static void thread_push(Gst *vm, GstThread *thread, GstValue callee, uint32_t size) { + uint16_t oldSize; + uint32_t nextCount, i; + GstStackFrame *frame; + if (thread->count) { + frame = thread_frame(thread); + oldSize = frame->size; + } else { + oldSize = 0; + } + nextCount = thread->count + oldSize + FRAME_SIZE; + thread_ensure(vm, thread, nextCount + size); + thread->count = nextCount; + /* Ensure values start out as nil so as to not confuse + * the garabage collector */ + for (i = nextCount; i < nextCount + size; ++i) + thread->data[i].type = GST_NIL; + vm->base = thread->data + thread->count; + vm->frame = frame = (GstStackFrame *)(vm->base - FRAME_SIZE); + /* Set up the new stack frame */ + frame->prevSize = oldSize; + frame->size = size; + frame->env = NULL; + frame->callee = callee; +} + +/* Copy the current function stack to the current closure + environment. Call when exiting function with closures. */ +static void thread_split_env(Gst *vm) { + GstStackFrame *frame = vm->frame; + GstFuncEnv *env = frame->env; + /* Check for closures */ + if (env) { + GstThread *thread = vm->thread; + uint32_t size = frame->size; + env->thread = NULL; + env->stackOffset = size; + env->values = gst_alloc(vm, sizeof(GstValue) * size); + memcpy(env->values, thread->data + thread->count, size * sizeof(GstValue)); + } +} + +/* Pop the top-most stack frame from stack */ +static void thread_pop(Gst *vm) { + GstThread *thread = vm->thread; + GstStackFrame *frame = vm->frame; + uint32_t delta = FRAME_SIZE + frame->prevSize; + if (thread->count) { + thread_split_env(vm); + } else { + gst_error(vm, "Nothing to pop from stack."); + } + thread->count -= delta; + vm->base -= delta; + vm->frame = (GstStackFrame *)(vm->base - FRAME_SIZE); +} + + /* The metadata header associated with an allocated block of memory */ -#define GCHeader(mem) ((GCMemoryHeader *)(mem) - 1) +#define gc_header(mem) ((GCMemoryHeader *)(mem) - 1) /* Memory header struct. Node of a linked list of memory blocks. */ typedef struct GCMemoryHeader GCMemoryHeader; @@ -30,44 +100,44 @@ struct GCMemoryHeader { }; /* Forward declaration */ -static void VMMark(VM * vm, Value * x); +static void gst_mark(Gst *vm, GstValue *x); /* Helper to mark function environments */ -static void VMMarkFuncEnv(VM * vm, FuncEnv * env) { - if (GCHeader(env)->color != vm->black) { - Value temp; - GCHeader(env)->color = vm->black; +static void gst_mark_funcenv(Gst *vm, GstFuncEnv *env) { + if (gc_header(env)->color != vm->black) { + GstValue temp; + gc_header(env)->color = vm->black; if (env->thread) { - temp.type = TYPE_THREAD; + temp.type = GST_THREAD; temp.data.thread = env->thread; - VMMark(vm, &temp); + gst_mark(vm, &temp); } if (env->values) { uint32_t count = env->stackOffset; uint32_t i; - GCHeader(env->values)->color = vm->black; + gc_header(env->values)->color = vm->black; for (i = 0; i < count; ++i) - VMMark(vm, env->values + i); + gst_mark(vm, env->values + i); } } } /* GC helper to mark a FuncDef */ -static void VMMarkFuncDef(VM * vm, FuncDef * def) { - if (GCHeader(def)->color != vm->black) { - GCHeader(def)->color = vm->black; - GCHeader(def->byteCode)->color = vm->black; +static void gst_mark_funcdef(Gst *vm, GstFuncDef *def) { + if (gc_header(def)->color != vm->black) { + gc_header(def)->color = vm->black; + gc_header(def->byteCode)->color = vm->black; uint32_t count, i; if (def->literals) { count = def->literalsLen; - GCHeader(def->literals)->color = vm->black; + gc_header(def->literals)->color = vm->black; for (i = 0; i < count; ++i) { /* If the literal is a NIL type, it actually * contains a FuncDef */ - if (def->literals[i].type == TYPE_NIL) { - VMMarkFuncDef(vm, (FuncDef *) def->literals[i].data.pointer); + if (def->literals[i].type == GST_NIL) { + gst_mark_funcdef(vm, (GstFuncDef *) def->literals[i].data.pointer); } else { - VMMark(vm, def->literals + i); + gst_mark(vm, def->literals + i); } } } @@ -75,86 +145,88 @@ static void VMMarkFuncDef(VM * vm, FuncDef * def) { } /* Helper to mark a stack frame. Returns the next frame. */ -static StackFrame * VMMarkStackFrame(VM * vm, StackFrame * frame) { +static GstStackFrame *gst_mark_stackframe(Gst *vm, GstStackFrame *frame) { uint32_t i; - Value * stack = (Value *)frame + FRAME_SIZE; - VMMark(vm, &frame->callee); + GstValue *stack = (GstValue *)frame + FRAME_SIZE; + gst_mark(vm, &frame->callee); if (frame->env) - VMMarkFuncEnv(vm, frame->env); + gst_mark_funcenv(vm, frame->env); for (i = 0; i < frame->size; ++i) - VMMark(vm, stack + i); - return (StackFrame *)(stack + frame->size); + gst_mark(vm, stack + i); + return (GstStackFrame *)(stack + frame->size); } /* Mark allocated memory associated with a value. This is * the main function for doing the garbage collection mark phase. */ -static void VMMark(VM * vm, Value * x) { +static void gst_mark(Gst *vm, GstValue *x) { switch (x->type) { - case TYPE_NIL: - case TYPE_BOOLEAN: - case TYPE_NUMBER: - case TYPE_CFUNCTION: + case GST_NIL: + case GST_BOOLEAN: + case GST_NUMBER: + case GST_CFUNCTION: break; - case TYPE_STRING: - GCHeader(VStringRaw(x->data.string))->color = vm->black; + case GST_STRING: + gc_header(gst_string_raw(x->data.string))->color = vm->black; break; - case TYPE_BYTEBUFFER: - GCHeader(x->data.buffer)->color = vm->black; - GCHeader(x->data.buffer->data)->color = vm->black; + case GST_BYTEBUFFER: + gc_header(x->data.buffer)->color = vm->black; + gc_header(x->data.buffer->data)->color = vm->black; break; - case TYPE_ARRAY: - if (GCHeader(x->data.array)->color != vm->black) { + case GST_ARRAY: + if (gc_header(x->data.array)->color != vm->black) { uint32_t i, count; count = x->data.array->count; - GCHeader(x->data.array)->color = vm->black; - GCHeader(x->data.array->data)->color = vm->black; + gc_header(x->data.array)->color = vm->black; + gc_header(x->data.array->data)->color = vm->black; for (i = 0; i < count; ++i) - VMMark(vm, x->data.array->data + i); + gst_mark(vm, x->data.array->data + i); } break; - case TYPE_THREAD: - if (GCHeader(x->data.thread)->color != vm->black) { - Thread * thread = x->data.thread; - StackFrame * frame = (StackFrame *)thread->data; - StackFrame * end = ThreadFrame(thread); - GCHeader(thread)->color = vm->black; - GCHeader(thread->data)->color = vm->black; + case GST_THREAD: + if (gc_header(x->data.thread)->color != vm->black) { + GstThread *thread = x->data.thread; + GstStackFrame *frame = (GstStackFrame *)thread->data; + GstStackFrame *end = thread_frame(thread); + gc_header(thread)->color = vm->black; + gc_header(thread->data)->color = vm->black; while (frame <= end) - frame = VMMarkStackFrame(vm, frame); + frame = gst_mark_stackframe(vm, frame); } break; - case TYPE_FUNCTION: - if (GCHeader(x->data.func)->color != vm->black) { - Func * f = x->data.func; - GCHeader(f)->color = vm->black; - VMMarkFuncDef(vm, f->def); + case GST_FUNCTION: + if (gc_header(x->data.function)->color != vm->black) { + GstFunction *f = x->data.function; + gc_header(f)->color = vm->black; + gst_mark_funcdef(vm, f->def); if (f->env) - VMMarkFuncEnv(vm, f->env); + gst_mark_funcenv(vm, f->env); if (f->parent) { - Value temp; - temp.type = TYPE_FUNCTION; - temp.data.func = f->parent; - VMMark(vm, &temp); + GstValue temp; + temp.type = GST_FUNCTION; + temp.data.function = f->parent; + gst_mark(vm, &temp); } } break; - case TYPE_DICTIONARY: - if (GCHeader(x->data.dict)->color != vm->black) { - DictionaryIterator iter; - DictBucket * bucket; - GCHeader(x->data.dict)->color = vm->black; - GCHeader(x->data.dict->buckets)->color = vm->black; - DictIterate(x->data.dict, &iter); - while (DictIterateNext(&iter, &bucket)) { - GCHeader(bucket)->color = vm->black; - VMMark(vm, &bucket->key); - VMMark(vm, &bucket->value); + case GST_OBJECT: + if (gc_header(x->data.object)->color != vm->black) { + uint32_t i; + GstBucket *bucket; + gc_header(x->data.object)->color = vm->black; + gc_header(x->data.object->buckets)->color = vm->black; + for (i = 0; i < x->data.object->capacity; ++i) { + bucket = x->data.object->buckets[i]; + while (bucket) { + gst_mark(vm, &bucket->key); + gst_mark(vm, &bucket->value); + bucket = bucket->next; + } } } break; @@ -165,10 +237,10 @@ static void VMMark(VM * vm, Value * x) { /* Iterate over all allocated memory, and free memory that is not * marked as reachable. Flip the gc color flag for next sweep. */ -static void VMSweep(VM * vm) { - GCMemoryHeader * previous = NULL; - GCMemoryHeader * current = vm->blocks; - GCMemoryHeader * next; +static void gst_sweep(Gst *vm) { + GCMemoryHeader *previous = NULL; + GCMemoryHeader *current = vm->blocks; + GCMemoryHeader *next; while (current) { next = current->next; if (current->color != vm->black) { @@ -188,13 +260,13 @@ static void VMSweep(VM * vm) { } /* Prepare a memory block */ -static void * VMAllocPrepare(VM * vm, char * rawBlock, uint32_t size) { - GCMemoryHeader * mdata; +static void *gst_alloc_prepare(Gst *vm, char *rawBlock, uint32_t size) { + GCMemoryHeader *mdata; if (rawBlock == NULL) { - VMCrash(vm, OOM); + gst_crash(vm, OOM); } vm->nextCollection += size; - mdata = (GCMemoryHeader *) rawBlock; + mdata = (GCMemoryHeader *)rawBlock; mdata->next = vm->blocks; vm->blocks = mdata; mdata->color = !vm->black; @@ -202,117 +274,47 @@ static void * VMAllocPrepare(VM * vm, char * rawBlock, uint32_t size) { } /* Allocate some memory that is tracked for garbage collection */ -void * VMAlloc(VM * vm, uint32_t size) { +void *gst_alloc(Gst *vm, uint32_t size) { uint32_t totalSize = size + sizeof(GCMemoryHeader); - return VMAllocPrepare(vm, malloc(totalSize), totalSize); + return gst_alloc_prepare(vm, malloc(totalSize), totalSize); } /* Allocate some zeroed memory that is tracked for garbage collection */ -void * VMZalloc(VM * vm, uint32_t size) { +void *gst_zalloc(Gst *vm, uint32_t size) { uint32_t totalSize = size + sizeof(GCMemoryHeader); - return VMAllocPrepare(vm, calloc(1, totalSize), totalSize); + return gst_alloc_prepare(vm, calloc(1, totalSize), totalSize); } /* Run garbage collection */ -void VMCollect(VM * vm) { +void gst_collect(Gst *vm) { if (vm->lock > 0) return; /* Thread can be null */ if (vm->thread) { - Value thread; - thread.type = TYPE_THREAD; + GstValue thread; + thread.type = GST_THREAD; thread.data.thread = vm->thread; - VMMark(vm, &thread); + gst_mark(vm, &thread); } - VMMark(vm, &vm->ret); - VMSweep(vm); + gst_mark(vm, &vm->ret); + gst_sweep(vm); vm->nextCollection = 0; } /* Run garbage collection if needed */ -void VMMaybeCollect(VM * vm) { +void gst_maybe_collect(Gst *vm) { if (vm->nextCollection >= vm->memoryInterval) - VMCollect(vm); -} - -/* Ensure that a thread has enough space in it */ -static void ThreadEnsure(VM * vm, Thread * thread, uint32_t size) { - if (size > thread->capacity) { - uint32_t newCap = size * 2; - Value * newData = VMAlloc(vm, sizeof(Value) * newCap); - memcpy(newData, thread->data, thread->capacity * sizeof(Value)); - thread->data = newData; - thread->capacity = newCap; - } -} - -/* Push a stack frame onto a thread */ -static void VMThreadPush(VM * vm, Thread * thread, Value callee, uint32_t size) { - uint16_t oldSize; - uint32_t nextCount, i; - StackFrame * frame; - if (thread->count) { - frame = ThreadFrame(thread); - oldSize = frame->size; - } else { - oldSize = 0; - } - nextCount = thread->count + oldSize + FRAME_SIZE; - ThreadEnsure(vm, thread, nextCount + size); - thread->count = nextCount; - /* Ensure values start out as nil so as to not confuse - * the garabage collector */ - for (i = nextCount; i < nextCount + size; ++i) - thread->data[i].type = TYPE_NIL; - vm->base = thread->data + thread->count; - vm->frame = frame = (StackFrame *)(vm->base - FRAME_SIZE); - /* Set up the new stack frame */ - frame->prevSize = oldSize; - frame->size = size; - frame->env = NULL; - frame->callee = callee; -} - -/* Copy the current function stack to the current closure - environment */ -static void VMThreadSplitStack(VM * vm) { - StackFrame * frame = vm->frame; - FuncEnv * env = frame->env; - /* Check for closures */ - if (env) { - Thread * thread = vm->thread; - uint32_t size = frame->size; - env->thread = NULL; - env->stackOffset = size; - env->values = VMAlloc(vm, sizeof(Value) * size); - memcpy(env->values, thread->data + thread->count, size * sizeof(Value)); - } -} - -/* Pop the top-most stack frame from stack */ -static void VMThreadPop(VM * vm) { - Thread * thread = vm->thread; - StackFrame * frame = vm->frame; - uint32_t delta = FRAME_SIZE + frame->prevSize; - if (thread->count) { - VMThreadSplitStack(vm); - } else { - VMError(vm, "Nothing to pop from stack."); - } - thread->count -= delta; - vm->base -= delta; - vm->frame = (StackFrame *)(vm->base - FRAME_SIZE); + gst_collect(vm); } /* Get an upvalue */ -static Value * GetUpValue(VM * vm, Func * fn, uint16_t level, uint16_t index) { - FuncEnv * env; - Value * stack; - if (!level) { +static GstValue *gst_vm_upvalue_location(Gst *vm, GstFunction *fn, uint16_t level, uint16_t index) { + GstFuncEnv *env; + GstValue *stack; + if (!level) return vm->base + index; - } while (fn && --level) fn = fn->parent; - VMAssert(vm, fn, NO_UPVALUE); + gst_assert(vm, fn, NO_UPVALUE); env = fn->env; if (env->thread) stack = env->thread->data + env->stackOffset; @@ -321,143 +323,141 @@ static Value * GetUpValue(VM * vm, Func * fn, uint16_t level, uint16_t index) { return stack + index; } -/* Get a constant */ -static Value LoadConstant(VM * vm, Func * fn, uint16_t index) { +/* Get a literal */ +static GstValue gst_vm_literal(Gst *vm, GstFunction *fn, uint16_t index) { if (index > fn->def->literalsLen) { - VMError(vm, NO_UPVALUE); + gst_error(vm, NO_UPVALUE); } return fn->def->literals[index]; } /* Boolean truth definition */ -static int truthy(Value v) { - return v.type != TYPE_NIL && !(v.type == TYPE_BOOLEAN && !v.data.boolean); +static int truthy(GstValue v) { + return v.type != GST_NIL && !(v.type == GST_BOOLEAN && !v.data.boolean); } /* Return from the vm */ -static void VMReturn(VM * vm, Value ret) { - VMThreadPop(vm); +static void gst_vm_return(Gst *vm, GstValue ret) { + thread_pop(vm); if (vm->thread->count == 0) { - VMExit(vm, ret); + gst_exit(vm, ret); } vm->pc = vm->frame->pc; vm->base[vm->frame->ret] = ret; } /* Implementation of the opcode for function calls */ -static void VMCallOp(VM * vm) { - Thread * thread = vm->thread; - Value callee = vm->base[vm->pc[1]]; +static void gst_vm_call(Gst *vm) { + GstThread *thread = vm->thread; + GstValue callee = vm->base[vm->pc[1]]; uint32_t arity = vm->pc[3]; uint32_t oldCount = thread->count; uint32_t i; - Value * oldBase; + GstValue *oldBase; vm->frame->pc = vm->pc + 4 + arity; vm->frame->ret = vm->pc[2]; - if (callee.type == TYPE_FUNCTION) { - Func * fn = callee.data.func; - VMThreadPush(vm, thread, callee, fn->def->locals); - } else if (callee.type == TYPE_CFUNCTION) { - VMThreadPush(vm, thread, callee, arity); + if (callee.type == GST_FUNCTION) { + GstFunction *fn = callee.data.function; + thread_push(vm, thread, callee, fn->def->locals); + } else if (callee.type == GST_CFUNCTION) { + thread_push(vm, thread, callee, arity); } else { - VMError(vm, EXPECTED_FUNCTION); + gst_error(vm, EXPECTED_FUNCTION); } oldBase = thread->data + oldCount; - if (callee.type == TYPE_CFUNCTION) { + if (callee.type == GST_CFUNCTION) { for (i = 0; i < arity; ++i) vm->base[i] = oldBase[vm->pc[4 + i]]; ++vm->lock; - VMReturn(vm, callee.data.cfunction(vm)); + gst_vm_return(vm, callee.data.cfunction(vm)); --vm->lock; } else { - Func * f = callee.data.func; + GstFunction *f = callee.data.function; uint32_t locals = f->def->locals; for (i = 0; i < arity; ++i) vm->base[i] = oldBase[vm->pc[4 + i]]; for (; i < locals; ++i) - vm->base[i].type = TYPE_NIL; + vm->base[i].type = GST_NIL; vm->pc = f->def->byteCode; } } /* Implementation of the opcode for tail calls */ -static void VMTailCallOp(VM * vm) { - Thread * thread = vm->thread; - Value callee = vm->base[vm->pc[1]]; +static void gst_vm_tailcall(Gst *vm) { + GstThread *thread = vm->thread; + GstValue callee = vm->base[vm->pc[1]]; uint32_t arity = vm->pc[2]; uint16_t newFrameSize, currentFrameSize; uint32_t i; /* Check for closures */ - VMThreadSplitStack(vm); - if (callee.type == TYPE_CFUNCTION) { + thread_split_env(vm); + if (callee.type == GST_CFUNCTION) { newFrameSize = arity; - } else if (callee.type == TYPE_FUNCTION) { - Func * f = callee.data.func; + } else if (callee.type == GST_FUNCTION) { + GstFunction * f = callee.data.function; newFrameSize = f->def->locals; } else { - VMError(vm, EXPECTED_FUNCTION); + gst_error(vm, EXPECTED_FUNCTION); } /* Ensure stack has enough space for copies of arguments */ currentFrameSize = vm->frame->size; - ThreadEnsure(vm, thread, thread->count + currentFrameSize + arity); + thread_ensure(vm, thread, thread->count + currentFrameSize + arity); vm->base = thread->data + thread->count; /* Copy the arguments into the extra space */ - for (i = 0; i < arity; ++i) { + for (i = 0; i < arity; ++i) vm->base[currentFrameSize + i] = vm->base[vm->pc[3 + i]]; - } /* Copy the end of the stack to the parameter position */ - memcpy(vm->base, vm->base + currentFrameSize, arity * sizeof(Value)); + memcpy(vm->base, vm->base + currentFrameSize, arity * sizeof(GstValue)); /* nil the non argument part of the stack for gc */ - for (i = arity; i < newFrameSize; ++i) { - vm->base[i].type = TYPE_NIL; - } + for (i = arity; i < newFrameSize; ++i) + vm->base[i].type = GST_NIL; /* Update the stack frame */ vm->frame->size = newFrameSize; vm->frame->callee = callee; vm->frame->env = NULL; - if (callee.type == TYPE_CFUNCTION) { + if (callee.type == GST_CFUNCTION) { ++vm->lock; - VMReturn(vm, callee.data.cfunction(vm)); + gst_vm_return(vm, callee.data.cfunction(vm)); --vm->lock; } else { - Func * f = callee.data.func; + GstFunction *f = callee.data.function; vm->pc = f->def->byteCode; } } /* Instantiate a closure */ -static Value VMMakeClosure(VM * vm, uint16_t literal) { - Thread * thread = vm->thread; - if (vm->frame->callee.type != TYPE_FUNCTION) { - VMError(vm, EXPECTED_FUNCTION); +static GstValue gst_vm_closure(Gst *vm, uint16_t literal) { + GstThread *thread = vm->thread; + if (vm->frame->callee.type != GST_FUNCTION) { + gst_error(vm, EXPECTED_FUNCTION); } else { - Value constant, ret; - Func * fn, * current; - FuncEnv * env = vm->frame->env; + GstValue constant, ret; + GstFunction *fn, *current; + GstFuncEnv *env = vm->frame->env; if (!env) { - env = VMAlloc(vm, sizeof(FuncEnv)); + env = gst_alloc(vm, sizeof(GstFuncEnv)); env->thread = thread; env->stackOffset = thread->count; env->values = NULL; vm->frame->env = env; } - current = vm->frame->callee.data.func; - constant = LoadConstant(vm, current, literal); - if (constant.type != TYPE_NIL) { - VMError(vm, "Error trying to create closure"); + current = vm->frame->callee.data.function; + constant = gst_vm_literal(vm, current, literal); + if (constant.type != GST_NIL) { + gst_error(vm, "Error trying to create closure"); } - fn = VMAlloc(vm, sizeof(Func)); - fn->def = (FuncDef *) constant.data.pointer; + fn = gst_alloc(vm, sizeof(GstFunction)); + fn->def = (GstFuncDef *) constant.data.pointer; fn->parent = current; fn->env = env; - ret.type = TYPE_FUNCTION; - ret.data.func = fn; + ret.type = GST_FUNCTION; + ret.data.function = fn; return ret; } } /* Start running the VM */ -int VMStart(VM * vm) { +int gst_start(Gst *vm) { /* Set jmp_buf to jump back to for return. */ { @@ -475,7 +475,7 @@ int VMStart(VM * vm) { } for (;;) { - Value temp, v1, v2; + GstValue temp, v1, v2; uint16_t opcode = *vm->pc; switch (opcode) { @@ -483,84 +483,84 @@ int VMStart(VM * vm) { #define DO_BINARY_MATH(op) \ v1 = vm->base[vm->pc[2]]; \ v2 = vm->base[vm->pc[3]]; \ - VMAssert(vm, v1.type == TYPE_NUMBER, VMS_EXPECTED_NUMBER_LOP); \ - VMAssert(vm, v2.type == TYPE_NUMBER, VMS_EXPECTED_NUMBER_ROP); \ - temp.type = TYPE_NUMBER; \ + gst_assert(vm, v1.type == GST_NUMBER, VMS_EXPECTED_NUMBER_LOP); \ + gst_assert(vm, v2.type == GST_NUMBER, VMS_EXPECTED_NUMBER_ROP); \ + temp.type = GST_NUMBER; \ temp.data.number = v1.data.number op v2.data.number; \ vm->base[vm->pc[1]] = temp; \ vm->pc += 4; \ break; - case VM_OP_ADD: /* Addition */ + case GST_OP_ADD: /* Addition */ DO_BINARY_MATH(+) - case VM_OP_SUB: /* Subtraction */ + case GST_OP_SUB: /* Subtraction */ DO_BINARY_MATH(-) - case VM_OP_MUL: /* Multiplication */ + case GST_OP_MUL: /* Multiplication */ DO_BINARY_MATH(*) - case VM_OP_DIV: /* Division */ + case GST_OP_DIV: /* Division */ DO_BINARY_MATH(/) #undef DO_BINARY_MATH - case VM_OP_NOT: /* Boolean unary (Boolean not) */ - temp.type = TYPE_BOOLEAN; + case GST_OP_NOT: /* Boolean unary (Boolean not) */ + temp.type = GST_BOOLEAN; temp.data.boolean = !truthy(vm->base[vm->pc[2]]); vm->base[vm->pc[1]] = temp; vm->pc += 3; break; - case VM_OP_LD0: /* Load 0 */ - temp.type = TYPE_NUMBER; + case GST_OP_LD0: /* Load 0 */ + temp.type = GST_NUMBER; temp.data.number = 0; vm->base[vm->pc[1]] = temp; vm->pc += 2; break; - case VM_OP_LD1: /* Load 1 */ - temp.type = TYPE_NUMBER; + case GST_OP_LD1: /* Load 1 */ + temp.type = GST_NUMBER; temp.data.number = 1; vm->base[vm->pc[1]] = temp; vm->pc += 2; break; - case VM_OP_FLS: /* Load False */ - temp.type = TYPE_BOOLEAN; + case GST_OP_FLS: /* Load False */ + temp.type = GST_BOOLEAN; temp.data.boolean = 0; vm->base[vm->pc[1]] = temp; vm->pc += 2; break; - case VM_OP_TRU: /* Load True */ - temp.type = TYPE_BOOLEAN; + case GST_OP_TRU: /* Load True */ + temp.type = GST_BOOLEAN; temp.data.boolean = 1; vm->base[vm->pc[1]] = temp; vm->pc += 2; break; - case VM_OP_NIL: /* Load Nil */ - temp.type = TYPE_NIL; + case GST_OP_NIL: /* Load Nil */ + temp.type = GST_NIL; vm->base[vm->pc[1]] = temp; vm->pc += 2; break; - case VM_OP_I16: /* Load Small Integer */ - temp.type = TYPE_NUMBER; + case GST_OP_I16: /* Load Small Integer */ + temp.type = GST_NUMBER; temp.data.number = ((int16_t *)(vm->pc))[2]; vm->base[vm->pc[1]] = temp; vm->pc += 3; break; - case VM_OP_UPV: /* Load Up Value */ + case GST_OP_UPV: /* Load Up Value */ temp = vm->frame->callee; - VMAssert(vm, temp.type == TYPE_FUNCTION, EXPECTED_FUNCTION); - vm->base[vm->pc[1]] = *GetUpValue(vm, temp.data.func, vm->pc[2], vm->pc[3]); + gst_assert(vm, temp.type == GST_FUNCTION, EXPECTED_FUNCTION); + vm->base[vm->pc[1]] = *gst_vm_upvalue_location(vm, temp.data.function, vm->pc[2], vm->pc[3]); vm->pc += 4; break; - case VM_OP_JIF: /* Jump If */ + case GST_OP_JIF: /* Jump If */ if (truthy(vm->base[vm->pc[1]])) { vm->pc += 4; } else { @@ -568,125 +568,125 @@ int VMStart(VM * vm) { } break; - case VM_OP_JMP: /* Jump */ + case GST_OP_JMP: /* Jump */ vm->pc += *((int32_t *)(vm->pc + 1)); break; - case VM_OP_CAL: /* Call */ - VMCallOp(vm); + case GST_OP_CAL: /* Call */ + gst_vm_call(vm); break; - case VM_OP_RET: /* Return */ - VMReturn(vm, vm->base[vm->pc[1]]); + case GST_OP_RET: /* Return */ + gst_vm_return(vm, vm->base[vm->pc[1]]); break; - case VM_OP_SUV: /* Set Up Value */ + case GST_OP_SUV: /* Set Up Value */ temp = vm->frame->callee; - VMAssert(vm, temp.type == TYPE_FUNCTION, EXPECTED_FUNCTION); - *GetUpValue(vm, temp.data.func, vm->pc[2], vm->pc[3]) = vm->base[vm->pc[1]]; + gst_assert(vm, temp.type == GST_FUNCTION, EXPECTED_FUNCTION); + *gst_vm_upvalue_location(vm, temp.data.function, vm->pc[2], vm->pc[3]) = vm->base[vm->pc[1]]; vm->pc += 4; break; - case VM_OP_CST: /* Load constant value */ + case GST_OP_CST: /* Load constant value */ temp = vm->frame->callee; - VMAssert(vm, temp.type == TYPE_FUNCTION, EXPECTED_FUNCTION); - vm->base[vm->pc[1]] = LoadConstant(vm, temp.data.func, vm->pc[2]); + gst_assert(vm, temp.type == GST_FUNCTION, EXPECTED_FUNCTION); + vm->base[vm->pc[1]] = gst_vm_literal(vm, temp.data.function, vm->pc[2]); vm->pc += 3; break; - case VM_OP_I32: /* Load 32 bit integer */ - temp.type = TYPE_NUMBER; + case GST_OP_I32: /* Load 32 bit integer */ + temp.type = GST_NUMBER; temp.data.number = *((int32_t *)(vm->pc + 2)); vm->base[vm->pc[1]] = temp; vm->pc += 4; break; - case VM_OP_F64: /* Load 64 bit float */ - temp.type = TYPE_NUMBER; - temp.data.number = (Number) *((double *)(vm->pc + 2)); + case GST_OP_F64: /* Load 64 bit float */ + temp.type = GST_NUMBER; + temp.data.number = (GstNumber) *((double *)(vm->pc + 2)); vm->base[vm->pc[1]] = temp; vm->pc += 6; break; - case VM_OP_MOV: /* Move Values */ + case GST_OP_MOV: /* Move Values */ vm->base[vm->pc[1]] = vm->base[vm->pc[2]]; vm->pc += 3; break; - case VM_OP_CLN: /* Create closure from constant FuncDef */ - vm->base[vm->pc[1]] = VMMakeClosure(vm, vm->pc[2]); + case GST_OP_CLN: /* Create closure from constant FuncDef */ + vm->base[vm->pc[1]] = gst_vm_closure(vm, vm->pc[2]); vm->pc += 3; break; - case VM_OP_EQL: /* Equality */ - temp.type = TYPE_BOOLEAN; - temp.data.boolean = ValueEqual(vm->base[vm->pc[2]], vm->base[vm->pc[3]]); + case GST_OP_EQL: /* Equality */ + temp.type = GST_BOOLEAN; + temp.data.boolean = gst_equals(vm->base[vm->pc[2]], vm->base[vm->pc[3]]); vm->base[vm->pc[1]] = temp; vm->pc += 4; break; - case VM_OP_LTN: /* Less Than */ - temp.type = TYPE_BOOLEAN; - temp.data.boolean = (ValueCompare(vm->base[vm->pc[2]], vm->base[vm->pc[3]]) == -1); + case GST_OP_LTN: /* Less Than */ + temp.type = GST_BOOLEAN; + temp.data.boolean = (gst_compare(vm->base[vm->pc[2]], vm->base[vm->pc[3]]) == -1); vm->base[vm->pc[1]] = temp; vm->pc += 4; break; - case VM_OP_LTE: /* Less Than or Equal to */ - temp.type = TYPE_BOOLEAN; - temp.data.boolean = (ValueEqual(vm->base[vm->pc[2]], vm->base[vm->pc[3]]) != 1); + case GST_OP_LTE: /* Less Than or Equal to */ + temp.type = GST_BOOLEAN; + temp.data.boolean = (gst_compare(vm->base[vm->pc[2]], vm->base[vm->pc[3]]) != 1); vm->base[vm->pc[1]] = temp; vm->pc += 4; break; - case VM_OP_ARR: /* Array literal */ + case GST_OP_ARR: /* Array literal */ { uint32_t i; uint32_t arrayLen = vm->pc[2]; - Array * array = ArrayNew(vm, arrayLen); + GstArray *array = gst_array(vm, arrayLen); array->count = arrayLen; for (i = 0; i < arrayLen; ++i) array->data[i] = vm->base[vm->pc[3 + i]]; - temp.type = TYPE_ARRAY; + temp.type = GST_ARRAY; temp.data.array = array; vm->base[vm->pc[1]] = temp; vm->pc += 3 + arrayLen; } break; - case VM_OP_DIC: /* Dictionary literal */ + case GST_OP_DIC: /* Object literal */ { uint32_t i = 3; uint32_t kvs = vm->pc[2]; - Dictionary * dict = DictNew(vm, kvs + 2); + GstObject *o = gst_object(vm, kvs + 2); kvs = kvs + 3; while (i < kvs) { v1 = vm->base[vm->pc[i++]]; v2 = vm->base[vm->pc[i++]]; - DictPut(vm, dict, v1, v2); + gst_object_put(vm, o, v1, v2); } - temp.type = TYPE_DICTIONARY; - temp.data.dict = dict; + temp.type = GST_OBJECT; + temp.data.object = o; vm->base[vm->pc[1]] = temp; vm->pc += kvs; } break; - case VM_OP_TCL: /* Tail call */ - VMTailCallOp(vm); + case GST_OP_TCL: /* Tail call */ + gst_vm_tailcall(vm); break; /* Macro for generating some math operators */ #define DO_MULTI_MATH(op, start) { \ uint16_t count = vm->pc[2]; \ uint16_t i; \ - Number accum = start; \ + GstNumber accum = start; \ for (i = 0; i < count; ++i) { \ v1 = vm->base[vm->pc[3 + i]]; \ - VMAssert(vm, v1.type == TYPE_NUMBER, "Expected number"); \ + gst_assert(vm, v1.type == GST_NUMBER, "Expected number"); \ accum = accum op v1.data.number; \ } \ - temp.type = TYPE_NUMBER; \ + temp.type = GST_NUMBER; \ temp.data.number = accum; \ vm->base[vm->pc[1]] = temp; \ vm->pc += 3 + count; \ @@ -694,69 +694,69 @@ int VMStart(VM * vm) { } /* Vectorized math */ - case VM_OP_ADM: + case GST_OP_ADM: DO_MULTI_MATH(+, 0) - case VM_OP_SBM: + case GST_OP_SBM: DO_MULTI_MATH(-, 0) - case VM_OP_MUM: + case GST_OP_MUM: DO_MULTI_MATH(*, 1) - case VM_OP_DVM: + case GST_OP_DVM: DO_MULTI_MATH(/, 1) #undef DO_MULTI_MATH - case VM_OP_RTN: /* Return nil */ - temp.type = TYPE_NIL; - VMReturn(vm, temp); + case GST_OP_RTN: /* Return nil */ + temp.type = GST_NIL; + gst_vm_return(vm, temp); break; - case VM_OP_GET: - temp = ValueGet(vm, vm->base[vm->pc[2]], vm->base[vm->pc[3]]); + case GST_OP_GET: + temp = gst_get(vm, vm->base[vm->pc[2]], vm->base[vm->pc[3]]); vm->base[vm->pc[1]] = temp; vm->pc += 4; break; - case VM_OP_SET: - ValueSet(vm, vm->base[vm->pc[1]], vm->base[vm->pc[2]], vm->base[vm->pc[3]]); + case GST_OP_SET: + gst_set(vm, vm->base[vm->pc[1]], vm->base[vm->pc[2]], vm->base[vm->pc[3]]); vm->pc += 4; break; default: - VMError(vm, "Unknown opcode"); + gst_error(vm, "Unknown opcode"); break; } /* Move collection only to places that allocate memory */ /* This, however, is good for testing */ - VMMaybeCollect(vm); + gst_maybe_collect(vm); } } /* Get an argument from the stack */ -Value VMGetArg(VM * vm, uint16_t index) { +GstValue gst_arg(Gst *vm, uint16_t index) { uint16_t frameSize = vm->frame->size; - VMAssert(vm, frameSize > index, "Cannot get arg out of stack bounds"); + gst_assert(vm, frameSize > index, "Cannot get arg out of stack bounds"); return vm->base[index]; } /* Put a value on the stack */ -void VMSetArg(VM * vm, uint16_t index, Value x) { +void gst_set_arg(Gst* vm, uint16_t index, GstValue x) { uint16_t frameSize = vm->frame->size; - VMAssert(vm, frameSize > index, "Cannot set arg out of stack bounds"); + gst_assert(vm, frameSize > index, "Cannot set arg out of stack bounds"); vm->base[index] = x; } /* Get the size of the VMStack */ -uint16_t VMCountArgs(VM * vm) { +uint16_t gst_count_args(Gst *vm) { return vm->frame->size; } /* Initialize the VM */ -void VMInit(VM * vm) { - vm->ret.type = TYPE_NIL; +void gst_init(Gst *vm) { + vm->ret.type = GST_NIL; vm->base = NULL; vm->frame = NULL; vm->pc = NULL; @@ -777,19 +777,19 @@ void VMInit(VM * vm) { /* Load a function into the VM. The function will be called with * no arguments when run */ -void VMLoad(VM * vm, Value func) { +void gst_load(Gst *vm, GstValue callee) { uint32_t startCapacity = 100; - Thread * thread = VMAlloc(vm, sizeof(Thread)); - thread->data = VMAlloc(vm, sizeof(Value) * startCapacity); + GstThread *thread = gst_alloc(vm, sizeof(GstThread)); + thread->data = gst_alloc(vm, sizeof(GstValue) * startCapacity); thread->capacity = startCapacity; thread->count = 0; vm->thread = thread; - if (func.type == TYPE_FUNCTION) { - Func * fn = func.data.func; - VMThreadPush(vm, thread, func, fn->def->locals); + if (callee.type == GST_FUNCTION) { + GstFunction *fn = callee.data.function; + thread_push(vm, thread, callee, fn->def->locals); vm->pc = fn->def->byteCode; - } else if (func.type == TYPE_CFUNCTION) { - VMThreadPush(vm, thread, func, 0); + } else if (callee.type == GST_CFUNCTION) { + thread_push(vm, thread, callee, 0); vm->pc = NULL; } else { return; @@ -797,10 +797,10 @@ void VMLoad(VM * vm, Value func) { } /* Clear all memory associated with the VM */ -void VMDeinit(VM * vm) { - GCMemoryHeader * current = vm->blocks; +void gst_deinit(Gst *vm) { + GCMemoryHeader *current = vm->blocks; while (current) { - GCMemoryHeader * next = current->next; + GCMemoryHeader *next = current->next; free(current); current = next; } diff --git a/vm.h b/vm.h index 4afab3d5..ad8b8b5c 100644 --- a/vm.h +++ b/vm.h @@ -4,54 +4,54 @@ #include "datatypes.h" /* Exit from the VM normally */ -#define VMExit(vm, r) ((vm)->ret = (r), longjmp((vm)->jump, 1)) +#define gst_exit(vm, r) ((vm)->ret = (r), longjmp((vm)->jump, 1)) /* Bail from the VM with an error. */ -#define VMError(vm, e) ((vm)->error = (e), longjmp((vm)->jump, 2)) +#define gst_error(vm, e) ((vm)->error = (e), longjmp((vm)->jump, 2)) /* Crash. Not catchable, unlike error. */ -#define VMCrash(vm, e) ((vm)->error = (e), longjmp((vm)->jump, 3)) +#define gst_crash(vm, e) ((vm)->error = (e), longjmp((vm)->jump, 3)) /* Error if the condition is false */ -#define VMAssert(vm, cond, e) do \ - { if (!(cond)) { VMError((vm), (e)); } } while (0) +#define gst_assert(vm, cond, e) do \ + { if (!(cond)) { gst_error((vm), (e)); } } while (0) /* Type assertion */ -#define VMAssertType(vm, f, t) \ - VMAssert((vm), (f).type == (t), "Expected type,") +#define gst_assert_type(vm, f, t) \ + gst_assert((vm), (f).type == (t), "Expected a different type.") /* Initialize the VM */ -void VMInit(VM * vm); +void gst_init(Gst * vm); /* Deinitialize the VM */ -void VMDeinit(VM * vm); +void gst_deinit(Gst * vm); /* Load a function to be run on the VM */ -void VMLoad(VM * vm, Value func); +void gst_load(Gst * vm, GstValue func); /* Start running the VM */ -int VMStart(VM * vm); +int gst_start(Gst * vm); /* Run garbage collection */ -void VMCollect(VM * vm); +void gst_collect(Gst * vm); /* Collect garbage if enough memory has been allocated since * the previous collection */ -void VMMaybeCollect(VM * vm); +void gst_maybe_collect(Gst * vm); /* Allocate memory */ -void * VMAlloc(VM * vm, uint32_t amount); +void * gst_alloc(Gst * vm, uint32_t amount); /* Allocate zeroed memory */ -void * VMZalloc(VM * vm, uint32_t amount); +void * gst_zalloc(Gst * vm, uint32_t amount); /* Get an argument from the stack */ -Value VMGetArg(VM * vm, uint16_t index); +GstValue gst_arg(Gst * vm, uint16_t index); /* Put a value on the stack */ -void VMSetArg(VM * vm, uint16_t index, Value x); +void gst_set_arg(Gst * vm, uint16_t index, GstValue x); /* Get the number of arguments on the stack */ -uint16_t VMCountArgs(VM * vm); +uint16_t gst_count_args(Gst * vm); #endif /* end of include guard: VM_H_C4OZU8CQ */