1
0
mirror of https://github.com/janet-lang/janet synced 2024-12-26 00:10:27 +00:00

Merge branch 'master' of git+ssh://eng-grid.bu.edu/home/calsrose/code/interp

This commit is contained in:
Calvin Rose 2017-02-12 15:55:45 -05:00
commit f2d6b979f0
8 changed files with 400 additions and 363 deletions

View File

@ -1185,3 +1185,27 @@ Func * CompilerCompile(Compiler * c, Value form) {
return func; return func;
} }
} }
/* 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) {
while (x.type == TYPE_FORM) {
Array * form = x.data.array;
Value 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)) {
/* We encountered an error during parsing */
return 1;;
} else {
x = vm->ret;
}
}
*out = x;
return 0;
}

View File

@ -15,4 +15,10 @@ void CompilerAddGlobalCFunc(Compiler * c, const char * name, CFunction f);
/* Compile a function that evaluates the given form. */ /* Compile a function that evaluates the given form. */
Func * CompilerCompile(Compiler * c, Value form); Func * CompilerCompile(Compiler * c, Value 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);
#endif /* end of include guard: COMPILE_H_9VXF71HY */ #endif /* end of include guard: COMPILE_H_9VXF71HY */

View File

@ -127,10 +127,11 @@ struct VM {
uint16_t * pc; uint16_t * pc;
Array * thread; Array * thread;
Value * base; Value * base;
Value root; /* Global state - prevents GC cleanup */
/* Return state */ /* Return state */
const char * error; const char * error;
jmp_buf jump; jmp_buf jump;
Value tempRoot; /* Temporary GC root */ Value ret; /* Returned value from VMStart */
}; };
/* Parsing */ /* Parsing */

11
main.c
View File

@ -1,7 +1,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include "datatypes.h" #include "datatypes.h"
#include "gc.h"
#include "vm.h" #include "vm.h"
#include "parse.h" #include "parse.h"
#include "compile.h" #include "compile.h"
@ -28,7 +27,7 @@ Value print(VM * vm) {
void debugRepl() { void debugRepl() {
char buffer[128] = {0}; char buffer[128] = {0};
const char * reader = buffer; const char * reader = buffer;
Func * func; Value func;
VM vm; VM vm;
Parser p; Parser p;
Compiler c; Compiler c;
@ -75,7 +74,8 @@ void debugRepl() {
/* Try to compile generated AST */ /* Try to compile generated AST */
CompilerInit(&c, &vm); CompilerInit(&c, &vm);
CompilerAddGlobalCFunc(&c, "print", print); CompilerAddGlobalCFunc(&c, "print", print);
func = CompilerCompile(&c, p.value); func.type = TYPE_FUNCTION;
func.data.func = CompilerCompile(&c, p.value);
/* Check for compilation errors */ /* Check for compilation errors */
if (c.error) { if (c.error) {
@ -85,9 +85,6 @@ void debugRepl() {
continue; continue;
} }
/* Print the function that will be executed */
//dasmFunc(stdout, func);
/* Execute function */ /* Execute function */
VMLoad(&vm, func); VMLoad(&vm, func);
if (VMStart(&vm)) { if (VMStart(&vm)) {
@ -96,7 +93,7 @@ void debugRepl() {
buffer[0] = 0; buffer[0] = 0;
continue; continue;
} else { } else {
ValuePrint(vm.tempRoot, 0); ValuePrint(vm.ret, 0);
printf("\n"); printf("\n");
} }
} }

52
vm.c
View File

@ -23,13 +23,11 @@ struct StackFrame {
}; };
/* The size of a StackFrame in units of Values. */ /* The size of a StackFrame in units of Values. */
static size_t FRAME_SIZE() { #define FRAME_SIZE ((sizeof(StackFrame) + sizeof(Value) - 1) / sizeof(Value))
return ((sizeof(StackFrame) + sizeof(Value) - 1) / sizeof(Value));
}
/* Get the stack frame pointer for a thread */ /* Get the stack frame pointer for a thread */
static StackFrame * ThreadFrame(Array * thread) { static StackFrame * ThreadFrame(Array * thread) {
return (StackFrame *)(thread->data + thread->count - FRAME_SIZE()); return (StackFrame *)(thread->data + thread->count - FRAME_SIZE);
} }
/* The metadata header associated with an allocated block of memory */ /* The metadata header associated with an allocated block of memory */
@ -102,11 +100,11 @@ static void VMMark(VM * vm, Value * x) {
uint32_t i; uint32_t i;
Array * thread = x->data.array; Array * thread = x->data.array;
StackFrame * frame = (StackFrame *)thread->data; StackFrame * frame = (StackFrame *)thread->data;
StackFrame * end = (StackFrame *)(thread->data + thread->count - FRAME_SIZE()); StackFrame * end = (StackFrame *)(thread->data + thread->count - FRAME_SIZE);
GCHeader(thread)->color = vm->black; GCHeader(thread)->color = vm->black;
GCHeader(thread->data)->color = vm->black; GCHeader(thread->data)->color = vm->black;
while (frame <= end) { while (frame <= end) {
Value * stack = (Value *)frame + FRAME_SIZE(); Value * stack = (Value *)frame + FRAME_SIZE;
VMMark(vm, &frame->callee); VMMark(vm, &frame->callee);
if (frame->env) if (frame->env)
VMMarkFuncEnv(vm, frame->env); VMMarkFuncEnv(vm, frame->env);
@ -224,21 +222,24 @@ void * VMZalloc(VM * vm, uint32_t size) {
/* Run garbage collection */ /* Run garbage collection */
void VMCollect(VM * vm) { void VMCollect(VM * vm) {
if (vm->lock > 0) return; if (vm->lock > 0) return;
/* Thread can be null */
if (vm->thread) {
Value thread; Value thread;
thread.type = TYPE_THREAD; thread.type = TYPE_THREAD;
thread.data.array = vm->thread; thread.data.array = vm->thread;
VMMark(vm, &thread); VMMark(vm, &thread);
VMMark(vm, &vm->tempRoot); }
VMMark(vm, &vm->ret);
VMMark(vm, &vm->root);
VMSweep(vm); VMSweep(vm);
vm->nextCollection = 0; vm->nextCollection = 0;
} }
/* Run garbage collection if needed */ /* Run garbage collection if needed */
void VMMaybeCollect(VM * vm) { void VMMaybeCollect(VM * vm) {
if (vm->nextCollection >= vm->memoryInterval) { if (vm->nextCollection >= vm->memoryInterval)
VMCollect(vm); VMCollect(vm);
} }
}
/* Push a stack frame onto a thread */ /* Push a stack frame onto a thread */
static void VMThreadPush(VM * vm, Array * thread, Value callee, uint32_t size) { static void VMThreadPush(VM * vm, Array * thread, Value callee, uint32_t size) {
@ -251,7 +252,7 @@ static void VMThreadPush(VM * vm, Array * thread, Value callee, uint32_t size) {
} else { } else {
oldSize = 0; oldSize = 0;
} }
nextCount = thread->count + oldSize + FRAME_SIZE(); nextCount = thread->count + oldSize + FRAME_SIZE;
ArrayEnsure(vm, thread, nextCount + size); ArrayEnsure(vm, thread, nextCount + size);
thread->count = nextCount; thread->count = nextCount;
/* Ensure values start out as nil so as to not confuse /* Ensure values start out as nil so as to not confuse
@ -285,7 +286,7 @@ static void VMThreadSplitStack(VM * vm, Array * thread) {
/* Pop the top-most stack frame from stack */ /* Pop the top-most stack frame from stack */
static void VMThreadPop(VM * vm, Array * thread) { static void VMThreadPop(VM * vm, Array * thread) {
StackFrame * frame = ThreadFrame(thread); StackFrame * frame = ThreadFrame(thread);
uint32_t delta = FRAME_SIZE() + frame->prevSize; uint32_t delta = FRAME_SIZE + frame->prevSize;
if (thread->count) { if (thread->count) {
VMThreadSplitStack(vm, thread); VMThreadSplitStack(vm, thread);
} else { } else {
@ -748,29 +749,36 @@ uint16_t VMCountArgs(VM * vm) {
/* Initialize the VM */ /* Initialize the VM */
void VMInit(VM * vm) { void VMInit(VM * vm) {
vm->tempRoot.type = TYPE_NIL; vm->ret.type = TYPE_NIL;
vm->root.type = TYPE_NIL;
vm->base = NULL; vm->base = NULL;
vm->pc = NULL; vm->pc = NULL;
vm->error = NULL; vm->error = NULL;
/* Garbage collection */ /* Garbage collection */
vm->blocks = NULL; vm->blocks = NULL;
vm->nextCollection = 0; vm->nextCollection = 0;
vm->memoryInterval = 1024 * 256; vm->memoryInterval = 0;
vm->black = 0; vm->black = 0;
vm->lock = 0; vm->lock = 0;
/* Create new thread */ /* Set to empty thread */
vm->thread = ArrayNew(vm, 32); vm->thread = NULL;
} }
/* Load a function into the VM. The function will be called with /* Load a function into the VM. The function will be called with
* no arguments when run */ * no arguments when run */
void VMLoad(VM * vm, Func * func) { void VMLoad(VM * vm, Value func) {
Value callee; Array * thread = ArrayNew(vm, 100);
callee.type = TYPE_FUNCTION; vm->thread = thread;
callee.data.func = func; if (func.type == TYPE_FUNCTION) {
vm->thread = ArrayNew(vm, 32); Func * fn = func.data.func;
VMThreadPush(vm, vm->thread, callee, func->def->locals); VMThreadPush(vm, thread, func, fn->def->locals);
vm->pc = func->def->byteCode; vm->pc = fn->def->byteCode;
} else if (func.type == TYPE_CFUNCTION) {
VMThreadPush(vm, thread, func, 0);
vm->pc = NULL;
} else {
return;
}
} }
/* Clear all memory associated with the VM */ /* Clear all memory associated with the VM */

11
vm.h
View File

@ -4,7 +4,7 @@
#include "datatypes.h" #include "datatypes.h"
/* Exit from the VM normally */ /* Exit from the VM normally */
#define VMExit(vm, r) ((vm)->tempRoot = (r), longjmp((vm)->jump, 1)) #define VMExit(vm, r) ((vm)->ret = (r), longjmp((vm)->jump, 1))
/* Bail from the VM with an error. */ /* Bail from the VM with an error. */
#define VMError(vm, e) ((vm)->error = (e), longjmp((vm)->jump, 2)) #define VMError(vm, e) ((vm)->error = (e), longjmp((vm)->jump, 2))
@ -16,6 +16,10 @@
#define VMAssert(vm, cond, e) do \ #define VMAssert(vm, cond, e) do \
{ if (!(cond)) { VMError((vm), (e)); } } while (0) { if (!(cond)) { VMError((vm), (e)); } } while (0)
/* Type assertion */
#define VMAssertType(vm, f, type) \
VMAssert(vm, (f).type == (type), "Expected type " type)
/* Initialize the VM */ /* Initialize the VM */
void VMInit(VM * vm); void VMInit(VM * vm);
@ -23,14 +27,11 @@ void VMInit(VM * vm);
void VMDeinit(VM * vm); void VMDeinit(VM * vm);
/* Load a function to be run on the VM */ /* Load a function to be run on the VM */
void VMLoad(VM * vm, Func * func); void VMLoad(VM * vm, Value func);
/* Start running the VM */ /* Start running the VM */
int VMStart(VM * vm); int VMStart(VM * vm);
/* Get the result after VMStart returns */
#define VMResult(vm) ((vm)->tempRoot)
/* Run garbage collection */ /* Run garbage collection */
void VMCollect(VM * vm); void VMCollect(VM * vm);