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:
commit
f2d6b979f0
24
compile.c
24
compile.c
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
11
main.c
@ -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
52
vm.c
@ -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
11
vm.h
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user