diff --git a/compile.c b/compile.c index e6c1ddc4..f99d546b 100644 --- a/compile.c +++ b/compile.c @@ -70,8 +70,7 @@ struct Scope { Dictionary * literals; Array * literalsArray; Dictionary * locals; - Scope * nextScope; - Scope * previousScope; + Scope * parent; }; /* Provides default FormOptions */ @@ -110,11 +109,9 @@ static Scope * CompilerPushScope(Compiler * c, int sameFunction) { scope->freeHeap = VMAlloc(c->vm, 10 * sizeof(uint16_t)); scope->heapSize = 0; scope->heapCapacity = 10; - scope->nextScope = NULL; - scope->previousScope = c->tail; + scope->parent = c->tail; scope->frameSize = 0; if (c->tail) { - c->tail->nextScope = scope; scope->level = c->tail->level + (sameFunction ? 0 : 1); } else { scope->level = 0; @@ -132,8 +129,6 @@ static Scope * CompilerPushScope(Compiler * c, int sameFunction) { scope->literalsArray = ArrayNew(c->vm, 10); } c->tail = scope; - if (!c->root) - c->root = scope; return scope; } @@ -146,15 +141,11 @@ static void CompilerPopScope(Compiler * c) { if (last->nextLocal > last->frameSize) { last->frameSize = last->nextLocal; } - c->tail = last->previousScope; + c->tail = last->parent; if (c->tail) { if (last->frameSize > c->tail->frameSize) { c->tail->frameSize = last->frameSize; } - c->tail->nextScope = NULL; - } else { - /* We deleted the last scope */ - c->root = NULL; } } } @@ -350,7 +341,7 @@ static int ScopeSymbolResolve(Scope * scope, Value x, *index = (uint16_t) check.data.number; return 1; } - scope = scope->previousScope; + scope = scope->parent; } return 0; } @@ -1183,7 +1174,7 @@ void CompilerInit(Compiler * c, VM * vm) { c->vm = vm; c->buffer = BufferNew(vm, 128); c->env = ArrayNew(vm, 10); - c->tail = c->root = NULL; + c->tail = NULL; c->error = NULL; CompilerPushScope(c, 0); } @@ -1192,7 +1183,7 @@ void CompilerInit(Compiler * c, VM * vm) { void CompilerAddGlobal(Compiler * c, const char * name, Value x) { Value sym = ValueLoadCString(c->vm, name); sym.type = TYPE_SYMBOL; - CompilerDeclareSymbol(c, c->root, sym); + CompilerDeclareSymbol(c, c->tail, sym); ArrayPush(c->vm, c->env, x); } @@ -1211,8 +1202,8 @@ Func * CompilerCompile(Compiler * c, Value form) { FuncDef * def; if (setjmp(c->onError)) { /* Clear all but root scope */ - c->tail = c->root; - c->root->nextScope = NULL; + if (c->tail) + c->tail->parent = NULL; return NULL; } /* Create a scope */ diff --git a/datatypes.h b/datatypes.h index b8d19613..f2bac657 100644 --- a/datatypes.h +++ b/datatypes.h @@ -167,7 +167,6 @@ struct Compiler { VM * vm; const char * error; jmp_buf onError; - Scope * root; Scope * tail; Array * env; Buffer * buffer; diff --git a/main.c b/main.c index 6e227506..f1c3d9ac 100644 --- a/main.c +++ b/main.c @@ -9,104 +9,104 @@ /* Test c function */ Value print(VM * vm) { - uint32_t i, j, count; - Value nil; - count = VMCountArgs(vm); - for (j = 0; j < count; ++j) { - uint8_t * string = ValueToString(vm, VMGetArg(vm, j)); - uint32_t len = VStringSize(string); - for (i = 0; i < len; ++i) - fputc(string[i], stdout); - fputc('\n', stdout); - } - nil.type = TYPE_NIL; - return nil; + uint32_t i, j, count; + Value nil; + count = VMCountArgs(vm); + for (j = 0; j < count; ++j) { + uint8_t * string = ValueToString(vm, VMGetArg(vm, j)); + uint32_t len = VStringSize(string); + for (i = 0; i < len; ++i) + fputc(string[i], stdout); + fputc('\n', stdout); + } + nil.type = TYPE_NIL; + return nil; } /* A simple repl for debugging */ void debugRepl() { - char buffer[128] = {0}; - const char * reader = buffer; - Value func; - VM vm; - Parser p; - Compiler c; + char buffer[128] = {0}; + const char * reader = buffer; + Value func; + VM vm; + Parser p; + Compiler c; - VMInit(&vm); + VMInit(&vm); - for (;;) { + for (;;) { - /* Run garbage collection */ -/* VMMaybeCollect(&vm);*/ + /* Run garbage collection */ + VMMaybeCollect(&vm); - /* Reset state */ - ParserInit(&p, &vm); + /* Reset state */ + ParserInit(&p, &vm); - /* Get and parse input until we have a full form */ - while (p.status == PARSER_PENDING) { - /* Get some input if we are done */ - if (*reader == '\0') { - printf("> "); - if (!fgets(buffer, sizeof(buffer), stdin)) { - return; + /* Get and parse input until we have a full form */ + while (p.status == PARSER_PENDING) { + /* Get some input if we are done */ + if (*reader == '\0') { + printf("> "); + if (!fgets(buffer, sizeof(buffer), stdin)) { + return; + } + p.index = 0; + reader = buffer; + } + reader += ParserParseCString(&p, reader); + } + + /* Check for parsing errors */ + if (p.error) { + unsigned i; + printf("\n"); + printf("%s\n", buffer); + for (i = 0; i < p.index; ++i) { + printf(" "); + } + printf("^\n"); + printf("\nParse error: %s\n", p.error); + reader = buffer; /* Flush the input buffer */ + buffer[0] = '\0'; + continue; + } + + /* Try to compile generated AST */ + CompilerInit(&c, &vm); + CompilerAddGlobalCFunc(&c, "print", print); + func.type = TYPE_FUNCTION; + func.data.func = CompilerCompile(&c, p.value); + + /* Check for compilation errors */ + if (c.error) { + printf("Compiler error: %s\n", c.error); + reader = buffer; + buffer[0] = 0; + continue; + } + + /* Print asm */ + printf("\n"); + dasmFunc(stdout, func.data.func); + printf("\n"); + + /* Execute function */ + VMLoad(&vm, func); + if (VMStart(&vm)) { + printf("VM error: %s\n", vm.error); + reader = buffer; + buffer[0] = 0; + continue; + } else { + ValuePrint(vm.ret, 0); + printf("\n"); } - p.index = 0; - reader = buffer; - } - reader += ParserParseCString(&p, reader); } - /* Check for parsing errors */ - if (p.error) { - unsigned i; - printf("\n"); - printf("%s\n", buffer); - for (i = 0; i < p.index; ++i) { - printf(" "); - } - printf("^\n"); - printf("\nParse error: %s\n", p.error); - reader = buffer; /* Flush the input buffer */ - buffer[0] = '\0'; - continue; - } - - /* Try to compile generated AST */ - CompilerInit(&c, &vm); - CompilerAddGlobalCFunc(&c, "print", print); - func.type = TYPE_FUNCTION; - func.data.func = CompilerCompile(&c, p.value); - - /* Check for compilation errors */ - if (c.error) { - printf("Compiler error: %s\n", c.error); - reader = buffer; - buffer[0] = 0; - continue; - } - - /* Print asm */ - printf("\n"); - dasmFunc(stdout, func.data.func); - printf("\n"); - - /* Execute function */ - VMLoad(&vm, func); - if (VMStart(&vm)) { - printf("VM error: %s\n", vm.error); - reader = buffer; - buffer[0] = 0; - continue; - } else { - ValuePrint(vm.ret, 0); - printf("\n"); - } - } - } int main() { - printf("Super cool interpreter v0.0\n"); - debugRepl(); - return 0; + printf("Super cool interpreter v0.0\n"); + debugRepl(); + return 0; } diff --git a/vm.c b/vm.c index 8b757813..7ddb4eae 100644 --- a/vm.c +++ b/vm.c @@ -41,7 +41,8 @@ static void VMMarkFuncEnv(VM * vm, FuncEnv * env) { temp.type = TYPE_THREAD; temp.data.array = env->thread; VMMark(vm, &temp); - } else if (env->values) { + } + if (env->values) { uint32_t count = env->stackOffset; uint32_t i; GCHeader(env->values)->color = vm->black; @@ -126,8 +127,9 @@ static void VMMark(VM * vm, Value * x) { if (GCHeader(x->data.func)->color != vm->black) { Func * f = x->data.func; GCHeader(f)->color = vm->black; - VMMarkFuncEnv(vm, f->env); VMMarkFuncDef(vm, f->def); + if (f->env) + VMMarkFuncEnv(vm, f->env); if (f->parent) { Value temp; temp.type = TYPE_FUNCTION; @@ -169,18 +171,20 @@ static void VMMark(VM * vm, Value * x) { static void VMSweep(VM * vm) { GCMemoryHeader * previous = NULL; GCMemoryHeader * current = vm->blocks; + GCMemoryHeader * next; while (current) { + next = current->next; if (current->color != vm->black) { if (previous) { - previous->next = current->next; + previous->next = next; } else { - vm->blocks = current->next; + vm->blocks = next; } free(current); } else { previous = current; } - current = current->next; + current = next; } /* Rotate flag */ vm->black = !vm->black; @@ -216,10 +220,12 @@ void * VMZalloc(VM * vm, uint32_t size) { void VMCollect(VM * vm) { if (vm->lock > 0) return; /* Thread can be null */ - Value thread; - thread.type = TYPE_THREAD; - thread.data.array = vm->thread; - VMMark(vm, &thread); + if (vm->thread) { + Value thread; + thread.type = TYPE_THREAD; + thread.data.array = vm->thread; + VMMark(vm, &thread); + } VMMark(vm, &vm->ret); VMSweep(vm); vm->nextCollection = 0; @@ -271,7 +277,7 @@ static void VMThreadSplitStack(VM * vm) { 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 */