1
0
mirror of https://github.com/janet-lang/janet synced 2024-12-25 07:50: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;
}
}
/* 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. */
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 */

View File

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

11
main.c
View File

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

52
vm.c
View File

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

11
vm.h
View File

@ -4,7 +4,7 @@
#include "datatypes.h"
/* 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. */
#define VMError(vm, e) ((vm)->error = (e), longjmp((vm)->jump, 2))
@ -16,6 +16,10 @@
#define VMAssert(vm, cond, e) do \
{ 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 */
void VMInit(VM * vm);
@ -23,14 +27,11 @@ void VMInit(VM * vm);
void VMDeinit(VM * 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 */
int VMStart(VM * vm);
/* Get the result after VMStart returns */
#define VMResult(vm) ((vm)->tempRoot)
/* Run garbage collection */
void VMCollect(VM * vm);