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