mirror of
https://github.com/janet-lang/janet
synced 2024-06-25 22:53:16 +00:00
Allow parser to parse files rather than just a repl. I think
there are some memory leak issues (problems with gc).
This commit is contained in:
parent
f456de5fac
commit
f52e290206
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@
|
||||||
######################################################
|
######################################################
|
||||||
##### Set global variables for all gst Makefiles #####
|
##### Set global variables for all gst Makefiles #####
|
||||||
######################################################
|
######################################################
|
||||||
CFLAGS=-std=c99 -Wall -Wextra -Wpedantic -g -I./include
|
CFLAGS=-std=c99 -Wall -Wextra -Wpedantic -I./include -g
|
||||||
PREFIX=/usr/local
|
PREFIX=/usr/local
|
||||||
GST_TARGET=client/gst
|
GST_TARGET=client/gst
|
||||||
GST_CORELIB=core/libgst.a
|
GST_CORELIB=core/libgst.a
|
||||||
|
|
159
client/main.c
159
client/main.c
|
@ -6,96 +6,95 @@
|
||||||
#include <gst/stl.h>
|
#include <gst/stl.h>
|
||||||
#include <gst/disasm.h>
|
#include <gst/disasm.h>
|
||||||
|
|
||||||
/* A simple repl for debugging */
|
/* Parse a file and execute it */
|
||||||
void debug_repl(FILE *in, FILE *out) {
|
int debug_run(Gst *vm, FILE *in) {
|
||||||
char buffer[1024] = {0};
|
char buffer[1024] = {0};
|
||||||
const char * reader = buffer;
|
const char *reader = buffer;
|
||||||
GstValue func;
|
GstValue func;
|
||||||
Gst vm;
|
|
||||||
GstParser p;
|
GstParser p;
|
||||||
GstCompiler c;
|
GstCompiler c;
|
||||||
|
|
||||||
|
gst_parser(&p, vm);
|
||||||
|
|
||||||
|
/* Create do struct */
|
||||||
|
GstArray *arr = gst_array(vm, 10);
|
||||||
|
gst_array_push(vm, arr, gst_string_cv(vm, "do"));
|
||||||
|
|
||||||
|
/* Get and parse input until we have a full form */
|
||||||
|
while (p.status != GST_PARSER_ERROR) {
|
||||||
|
if (*reader == '\0') {
|
||||||
|
if (!fgets(buffer, sizeof(buffer), in)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader = buffer;
|
||||||
|
}
|
||||||
|
reader += gst_parse_cstring(&p, reader);
|
||||||
|
if (gst_parse_hasvalue(&p))
|
||||||
|
gst_array_push(vm, arr, gst_parse_consume(&p));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Turn array into tuple */
|
||||||
|
GstValue *tup = gst_tuple_begin(vm, arr->count);
|
||||||
|
gst_memcpy(tup, arr->data, arr->count * sizeof(GstValue));
|
||||||
|
vm->ret.type = GST_TUPLE;
|
||||||
|
vm->ret.data.tuple = gst_tuple_end(vm, tup);
|
||||||
|
|
||||||
|
/* Check if file read in correctly */
|
||||||
|
if (p.error) {
|
||||||
|
printf("Parse error: %s\n", p.error);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that parser is complete */
|
||||||
|
if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) {
|
||||||
|
printf("Unexpected end of source\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to compile generated AST */
|
||||||
|
gst_compiler(&c, vm);
|
||||||
|
func.type = GST_NIL;
|
||||||
|
gst_compiler_usemodule(&c, "std");
|
||||||
|
func.type = GST_FUNCTION;
|
||||||
|
func.data.function = gst_compiler_compile(&c, vm->ret);
|
||||||
|
|
||||||
|
/* Check for compilation errors */
|
||||||
|
if (c.error) {
|
||||||
|
printf("Compiler error: %s\n", c.error);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Execute function */
|
||||||
|
if (gst_run(vm, func)) {
|
||||||
|
if (vm->crash) {
|
||||||
|
printf("VM crash: %s\n", vm->crash);
|
||||||
|
} else {
|
||||||
|
printf("VM error: %s\n", (char *)gst_to_string(vm, vm->ret));
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv) {
|
||||||
|
|
||||||
|
Gst vm;
|
||||||
|
int status = 0;
|
||||||
gst_init(&vm);
|
gst_init(&vm);
|
||||||
gst_stl_load(&vm);
|
gst_stl_load(&vm);
|
||||||
|
|
||||||
for (;;) {
|
const char *filename;
|
||||||
|
|
||||||
/* Reset state */
|
// if (argc > 1) {
|
||||||
gst_parser(&p, &vm);
|
// filename = argv[1];
|
||||||
|
//} else {
|
||||||
|
filename = "libs/stl.gst";
|
||||||
|
//}
|
||||||
|
|
||||||
/* Get and parse input until we have a full form */
|
FILE *f = fopen(filename, "rb");
|
||||||
while (p.status == GST_PARSER_PENDING) {
|
status = debug_run(&vm, f);
|
||||||
/* Get some input if we are done */
|
|
||||||
if (*reader == '\0') {
|
|
||||||
if (out)
|
|
||||||
fprintf(out, ">> ");
|
|
||||||
if (!fgets(buffer, sizeof(buffer), in)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
p.index = 0;
|
|
||||||
reader = buffer;
|
|
||||||
}
|
|
||||||
reader += gst_parse_cstring(&p, reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for parsing errors */
|
gst_deinit(&vm);
|
||||||
if (p.error) {
|
|
||||||
unsigned i;
|
|
||||||
if (out) {
|
|
||||||
fprintf(out, "\n");
|
|
||||||
fprintf(out, "%s\n", buffer);
|
|
||||||
for (i = 1; i < p.index; ++i) {
|
|
||||||
fprintf(out, " ");
|
|
||||||
}
|
|
||||||
fprintf(out, "^\n");
|
|
||||||
fprintf(out, "\nParse error: %s\n", p.error);
|
|
||||||
}
|
|
||||||
reader = buffer; /* Flush the input buffer */
|
|
||||||
buffer[0] = '\0';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to compile generated AST */
|
|
||||||
gst_compiler(&c, &vm);
|
|
||||||
func.type = GST_NIL;
|
|
||||||
gst_compiler_usemodule(&c, "std");
|
|
||||||
gst_compiler_global(&c, "ans", gst_object_get(vm.rootenv, gst_string_cv(&vm, "ans")));
|
|
||||||
func.type = GST_FUNCTION;
|
|
||||||
func.data.function = gst_compiler_compile(&c, p.value);
|
|
||||||
|
|
||||||
/* Check for compilation errors */
|
|
||||||
if (c.error) {
|
|
||||||
if (out) {
|
|
||||||
fprintf(out, "Compiler error: %s\n", c.error);
|
|
||||||
}
|
|
||||||
reader = buffer;
|
|
||||||
buffer[0] = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Execute function */
|
|
||||||
if (gst_run(&vm, func)) {
|
|
||||||
if (out) {
|
|
||||||
if (vm.crash) {
|
|
||||||
fprintf(out, "VM crash: %s\n", vm.crash);
|
|
||||||
} else {
|
|
||||||
fprintf(out, "VM error: ");
|
|
||||||
fprintf(out, "%s\n", (char *)gst_to_string(&vm, vm.ret));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader = buffer;
|
|
||||||
buffer[0] = 0;
|
|
||||||
continue;
|
|
||||||
} else if (out) {
|
|
||||||
fprintf(out, "%s\n", (char *)gst_to_string(&vm, vm.ret));
|
|
||||||
gst_object_put(&vm, vm.rootenv, gst_string_cv(&vm, "ans"), vm.ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
return status;
|
||||||
|
|
||||||
int main() {
|
|
||||||
printf("GST v0.0 repl\nCopyright 2017 Calvin Rose\n");
|
|
||||||
debug_repl(stdin, stdout);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -555,9 +555,6 @@ static Slot compile_function(GstCompiler *c, FormOptions opts, const GstValue *f
|
||||||
if (opts.resultUnused) return nil_slot();
|
if (opts.resultUnused) return nil_slot();
|
||||||
ret = compiler_get_target(c, opts);
|
ret = compiler_get_target(c, opts);
|
||||||
subGstScope = compiler_push_scope(c, 0);
|
subGstScope = compiler_push_scope(c, 0);
|
||||||
/* Check for function documentation - for now just ignore. */
|
|
||||||
if (form[current].type == GST_STRING)
|
|
||||||
++current;
|
|
||||||
/* Define the function parameters */
|
/* Define the function parameters */
|
||||||
if (form[current].type != GST_ARRAY)
|
if (form[current].type != GST_ARRAY)
|
||||||
c_error(c, "expected function arguments array");
|
c_error(c, "expected function arguments array");
|
||||||
|
@ -672,6 +669,7 @@ static Slot compile_try(GstCompiler *c, FormOptions opts, const GstValue *form)
|
||||||
Slot body;
|
Slot body;
|
||||||
uint16_t errorIndex;
|
uint16_t errorIndex;
|
||||||
uint32_t countAtTry, countTemp, countAtJump;
|
uint32_t countAtTry, countTemp, countAtJump;
|
||||||
|
countAtJump = 0;
|
||||||
/* Check argument count */
|
/* Check argument count */
|
||||||
if (gst_tuple_length(form) < 3 || gst_tuple_length(form) > 4)
|
if (gst_tuple_length(form) < 3 || gst_tuple_length(form) > 4)
|
||||||
c_error(c, "try takes either 2 or 3 arguments");
|
c_error(c, "try takes either 2 or 3 arguments");
|
||||||
|
|
|
@ -145,10 +145,8 @@ void gst_mark(Gst *vm, GstValueUnion x, GstType type) {
|
||||||
gc_header(x.object)->color = vm->black;
|
gc_header(x.object)->color = vm->black;
|
||||||
gc_header(x.object->data)->color = vm->black;
|
gc_header(x.object->data)->color = vm->black;
|
||||||
for (i = 0; i < x.object->capacity; i += 2) {
|
for (i = 0; i < x.object->capacity; i += 2) {
|
||||||
if (x.object->data[i].type != GST_NIL) {
|
gst_mark_value(vm, x.object->data[i]);
|
||||||
gst_mark_value(vm, x.object->data[i]);
|
gst_mark_value(vm, x.object->data[i + 1]);
|
||||||
gst_mark_value(vm, x.object->data[i + 1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (x.object->parent != NULL) {
|
if (x.object->parent != NULL) {
|
||||||
GstValueUnion temp;
|
GstValueUnion temp;
|
||||||
|
@ -254,6 +252,9 @@ void gst_collect(Gst *vm) {
|
||||||
renv.object = vm->rootenv;
|
renv.object = vm->rootenv;
|
||||||
gst_mark(vm, renv, GST_OBJECT);
|
gst_mark(vm, renv, GST_OBJECT);
|
||||||
gst_mark_value(vm, vm->ret);
|
gst_mark_value(vm, vm->ret);
|
||||||
|
if (vm->scratch) {
|
||||||
|
gc_header(vm->scratch)->color = vm->black;
|
||||||
|
}
|
||||||
gst_sweep(vm);
|
gst_sweep(vm);
|
||||||
vm->nextCollection = 0;
|
vm->nextCollection = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,7 +254,7 @@ const GstValue *gst_struct_end(Gst *vm, GstValue *st) {
|
||||||
|
|
||||||
/* Get an item from a struct */
|
/* Get an item from a struct */
|
||||||
GstValue gst_struct_get(const GstValue *st, GstValue key) {
|
GstValue gst_struct_get(const GstValue *st, GstValue key) {
|
||||||
GstValue *bucket = gst_struct_find(st, key);
|
const GstValue *bucket = gst_struct_find(st, key);
|
||||||
if (!bucket || bucket[0].type == GST_NIL) {
|
if (!bucket || bucket[0].type == GST_NIL) {
|
||||||
GstValue ret;
|
GstValue ret;
|
||||||
ret.type = GST_NIL;
|
ret.type = GST_NIL;
|
||||||
|
|
27
core/parse.c
27
core/parse.c
|
@ -341,6 +341,8 @@ static int string_state(GstParser *p, uint8_t c) {
|
||||||
|
|
||||||
/* Root state of the parser */
|
/* Root state of the parser */
|
||||||
static int root_state(GstParser *p, uint8_t c) {
|
static int root_state(GstParser *p, uint8_t c) {
|
||||||
|
if (is_whitespace(c)) return 1;
|
||||||
|
p->status = GST_PARSER_PENDING;
|
||||||
if (c == ']' || c == ')' || c == '}') {
|
if (c == ']' || c == ')' || c == '}') {
|
||||||
p_error(p, UNEXPECTED_CLOSING_DELIM);
|
p_error(p, UNEXPECTED_CLOSING_DELIM);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -357,7 +359,6 @@ static int root_state(GstParser *p, uint8_t c) {
|
||||||
p->quoteCount++;
|
p->quoteCount++;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (is_whitespace(c)) return 1;
|
|
||||||
if (is_symbol_char(c)) {
|
if (is_symbol_char(c)) {
|
||||||
parser_push(p, PTYPE_TOKEN, c);
|
parser_push(p, PTYPE_TOKEN, c);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -421,7 +422,7 @@ static void dispatch_char(GstParser *p, uint8_t c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Dispatch character to state */
|
/* Dispatch character to state */
|
||||||
while (!done && p->status == GST_PARSER_PENDING) {
|
while (!done && (p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT)) {
|
||||||
GstParseState *top = parser_peek(p);
|
GstParseState *top = parser_peek(p);
|
||||||
switch (top->type) {
|
switch (top->type) {
|
||||||
case PTYPE_ROOT:
|
case PTYPE_ROOT:
|
||||||
|
@ -447,8 +448,8 @@ static void dispatch_char(GstParser *p, uint8_t c) {
|
||||||
*/
|
*/
|
||||||
int gst_parse_cstring(GstParser *p, const char *string) {
|
int gst_parse_cstring(GstParser *p, const char *string) {
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
p->status = GST_PARSER_PENDING;
|
while ((p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT)
|
||||||
while ((p->status == GST_PARSER_PENDING) && (string[bytesRead] != '\0')) {
|
&& (string[bytesRead] != '\0')) {
|
||||||
dispatch_char(p, string[bytesRead++]);
|
dispatch_char(p, string[bytesRead++]);
|
||||||
}
|
}
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
|
@ -457,14 +458,26 @@ int gst_parse_cstring(GstParser *p, const char *string) {
|
||||||
/* Parse a gst string */
|
/* Parse a gst string */
|
||||||
int gst_parse_string(GstParser *p, const uint8_t *string) {
|
int gst_parse_string(GstParser *p, const uint8_t *string) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
p->status = GST_PARSER_PENDING;
|
|
||||||
for (i = 0; i < gst_string_length(string); ++i) {
|
for (i = 0; i < gst_string_length(string); ++i) {
|
||||||
if (p->status != GST_PARSER_PENDING) break;
|
if (p->status != GST_PARSER_PENDING && p->status != GST_PARSER_ROOT) break;
|
||||||
dispatch_char(p, string[i]);
|
dispatch_char(p, string[i]);
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if a parser has a value that needs to be handled. If
|
||||||
|
* so, the parser will not parse any more input until that value
|
||||||
|
* is consumed. */
|
||||||
|
int gst_parse_hasvalue(GstParser *p) {
|
||||||
|
return p->status == GST_PARSER_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gets a value from the parser */
|
||||||
|
GstValue gst_parse_consume(GstParser *p) {
|
||||||
|
p->status = GST_PARSER_ROOT;
|
||||||
|
return p->value;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parser initialization (memory allocation) */
|
/* Parser initialization (memory allocation) */
|
||||||
void gst_parser(GstParser *p, Gst *vm) {
|
void gst_parser(GstParser *p, Gst *vm) {
|
||||||
p->vm = vm;
|
p->vm = vm;
|
||||||
|
@ -475,7 +488,7 @@ void gst_parser(GstParser *p, Gst *vm) {
|
||||||
p->index = 0;
|
p->index = 0;
|
||||||
p->quoteCount = 0;
|
p->quoteCount = 0;
|
||||||
p->error = NULL;
|
p->error = NULL;
|
||||||
p->status = GST_PARSER_PENDING;
|
p->status = GST_PARSER_ROOT;
|
||||||
p->value.type = GST_NIL;
|
p->value.type = GST_NIL;
|
||||||
p->flags = GST_PARSER_FLAG_EXPECTING_COMMENT;
|
p->flags = GST_PARSER_FLAG_EXPECTING_COMMENT;
|
||||||
parser_push(p, PTYPE_ROOT, ' ');
|
parser_push(p, PTYPE_ROOT, ' ');
|
||||||
|
|
|
@ -88,7 +88,7 @@ static const char *gst_deserialize_impl(
|
||||||
#define deser_assert(c, e) do{if(!(c))deser_error(e);}while(0)
|
#define deser_assert(c, e) do{if(!(c))deser_error(e);}while(0)
|
||||||
|
|
||||||
/* Assert enough buffer */
|
/* Assert enough buffer */
|
||||||
#define deser_datacheck(len) do{if (end - data < (len)) deser_error(UEB);}while(0)
|
#define deser_datacheck(len) do{if (end < (data + len)) deser_error(UEB);}while(0)
|
||||||
|
|
||||||
/* Check for enough space to read uint32_t */
|
/* Check for enough space to read uint32_t */
|
||||||
#define read_u32(out) do{deser_datacheck(4); (out)=bytes2u32(data); data += 4; }while(0)
|
#define read_u32(out) do{deser_datacheck(4); (out)=bytes2u32(data); data += 4; }while(0)
|
||||||
|
@ -485,6 +485,19 @@ const char *gst_serialize_impl(
|
||||||
write_byte(x.data.string[i]);
|
write_byte(x.data.string[i]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case GST_STRUCT:
|
||||||
|
write_byte(206);
|
||||||
|
count = gst_struct_length(x.data.st);
|
||||||
|
write_u32(count);
|
||||||
|
for (i = 0; i < gst_struct_capacity(x.data.st); i += 2) {
|
||||||
|
if (x.data.st[i].type != GST_NIL) {
|
||||||
|
err = gst_serialize_impl(vm, buffer, visited, nextId, x.data.st[i]);
|
||||||
|
if (err != NULL) return err;
|
||||||
|
err = gst_serialize_impl(vm, buffer, visited, nextId, x.data.st[i + 1]);
|
||||||
|
if (err != NULL) return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case GST_BYTEBUFFER:
|
case GST_BYTEBUFFER:
|
||||||
write_byte(207);
|
write_byte(207);
|
||||||
count = x.data.buffer->count;
|
count = x.data.buffer->count;
|
||||||
|
|
|
@ -363,8 +363,10 @@ int gst_stl_print(Gst *vm) {
|
||||||
uint32_t len = gst_string_length(string);
|
uint32_t len = gst_string_length(string);
|
||||||
for (i = 0; i < len; ++i)
|
for (i = 0; i < len; ++i)
|
||||||
fputc(string[i], stdout);
|
fputc(string[i], stdout);
|
||||||
fputc('\n', stdout);
|
if (j < count - 1)
|
||||||
|
fputc(' ', stdout);
|
||||||
}
|
}
|
||||||
|
fputc('\n', stdout);
|
||||||
return GST_RETURN_OK;
|
return GST_RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
66
core/vm.c
66
core/vm.c
|
@ -19,28 +19,16 @@ static const char GST_EXPECTED_FUNCTION[] = "expected function";
|
||||||
static const char GST_EXPECTED_NUMBER_ROP[] = "expected right operand to be number";
|
static const char GST_EXPECTED_NUMBER_ROP[] = "expected right operand to be number";
|
||||||
static const char GST_EXPECTED_NUMBER_LOP[] = "expected left operand to be number";
|
static const char GST_EXPECTED_NUMBER_LOP[] = "expected left operand to be number";
|
||||||
|
|
||||||
/* Contextual macro to state in function with VM */
|
|
||||||
#define GST_STATE_SYNC() do { \
|
|
||||||
thread = *vm->thread; \
|
|
||||||
stack = thread.data + thread.count; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Write local state back to VM */
|
|
||||||
#define GST_STATE_WRITE() do { \
|
|
||||||
*vm->thread = thread; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Start running the VM from where it left off. Continue running
|
/* Start running the VM from where it left off. Continue running
|
||||||
* until the stack size is smaller than minStackSize. */
|
* until the stack size is smaller than minStackSize. */
|
||||||
static int gst_continue_size(Gst *vm, uint32_t stackBase) {
|
static int gst_continue_size(Gst *vm, uint32_t stackBase) {
|
||||||
/* VM state */
|
/* VM state */
|
||||||
GstThread thread;
|
|
||||||
GstValue *stack;
|
GstValue *stack;
|
||||||
GstValue temp, v1, v2;
|
GstValue temp, v1, v2;
|
||||||
uint16_t *pc;
|
uint16_t *pc;
|
||||||
|
|
||||||
/* Intialize local state */
|
/* Intialize local state */
|
||||||
GST_STATE_SYNC();
|
stack = vm->thread->data + vm->thread->count;
|
||||||
pc = gst_frame_pc(stack);
|
pc = gst_frame_pc(stack);
|
||||||
|
|
||||||
/* Main interpreter loop */
|
/* Main interpreter loop */
|
||||||
|
@ -158,9 +146,8 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) {
|
||||||
gst_error(vm, GST_EXPECTED_FUNCTION);
|
gst_error(vm, GST_EXPECTED_FUNCTION);
|
||||||
if (gst_frame_env(stack) == NULL) {
|
if (gst_frame_env(stack) == NULL) {
|
||||||
gst_frame_env(stack) = gst_alloc(vm, sizeof(GstFuncEnv));
|
gst_frame_env(stack) = gst_alloc(vm, sizeof(GstFuncEnv));
|
||||||
*vm->thread = thread;
|
|
||||||
gst_frame_env(stack)->thread = vm->thread;
|
gst_frame_env(stack)->thread = vm->thread;
|
||||||
gst_frame_env(stack)->stackOffset = thread.count;
|
gst_frame_env(stack)->stackOffset = vm->thread->count;
|
||||||
gst_frame_env(stack)->values = NULL;
|
gst_frame_env(stack)->values = NULL;
|
||||||
}
|
}
|
||||||
if (pc[2] > v1.data.function->def->literalsLen)
|
if (pc[2] > v1.data.function->def->literalsLen)
|
||||||
|
@ -179,10 +166,6 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GST_OP_ERR: /* Throw error */
|
|
||||||
vm->ret = stack[pc[1]];
|
|
||||||
goto vm_error;
|
|
||||||
|
|
||||||
case GST_OP_TRY: /* Begin try block */
|
case GST_OP_TRY: /* Begin try block */
|
||||||
gst_frame_errloc(stack) = pc[1];
|
gst_frame_errloc(stack) = pc[1];
|
||||||
gst_frame_errjmp(stack) = pc + *(uint32_t *)(pc + 2);
|
gst_frame_errjmp(stack) = pc + *(uint32_t *)(pc + 2);
|
||||||
|
@ -195,10 +178,9 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case GST_OP_RTN: /* Return nil */
|
case GST_OP_RTN: /* Return nil */
|
||||||
stack = gst_thread_popframe(vm, &thread);
|
stack = gst_thread_popframe(vm, vm->thread);
|
||||||
if (thread.count < stackBase) {
|
if (vm->thread->count < stackBase) {
|
||||||
vm->ret.type = GST_NIL;
|
vm->ret.type = GST_NIL;
|
||||||
GST_STATE_WRITE();
|
|
||||||
return GST_RETURN_OK;
|
return GST_RETURN_OK;
|
||||||
}
|
}
|
||||||
pc = gst_frame_pc(stack);
|
pc = gst_frame_pc(stack);
|
||||||
|
@ -207,10 +189,9 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) {
|
||||||
|
|
||||||
case GST_OP_RET: /* Return */
|
case GST_OP_RET: /* Return */
|
||||||
temp = stack[pc[1]];
|
temp = stack[pc[1]];
|
||||||
stack = gst_thread_popframe(vm, &thread);
|
stack = gst_thread_popframe(vm, vm->thread);
|
||||||
if (thread.count < stackBase) {
|
if (vm->thread->count < stackBase) {
|
||||||
vm->ret = temp;
|
vm->ret = temp;
|
||||||
GST_STATE_WRITE();
|
|
||||||
return GST_RETURN_OK;
|
return GST_RETURN_OK;
|
||||||
}
|
}
|
||||||
pc = gst_frame_pc(stack);
|
pc = gst_frame_pc(stack);
|
||||||
|
@ -230,17 +211,17 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) {
|
||||||
/* Push new frame */
|
/* Push new frame */
|
||||||
if (temp.type != GST_FUNCTION && temp.type != GST_CFUNCTION)
|
if (temp.type != GST_FUNCTION && temp.type != GST_CFUNCTION)
|
||||||
gst_error(vm, GST_EXPECTED_FUNCTION);
|
gst_error(vm, GST_EXPECTED_FUNCTION);
|
||||||
stack = gst_thread_beginframe(vm, &thread, temp, arity);
|
stack = gst_thread_beginframe(vm, vm->thread, temp, arity);
|
||||||
oldStack = stack - GST_FRAME_SIZE - gst_frame_prevsize(stack);
|
oldStack = stack - GST_FRAME_SIZE - gst_frame_prevsize(stack);
|
||||||
/* Write arguments */
|
/* Write arguments */
|
||||||
size = gst_frame_size(stack);
|
size = gst_frame_size(stack);
|
||||||
for (i = 0; i < arity; ++i)
|
for (i = 0; i < arity; ++i)
|
||||||
stack[i + size - arity] = oldStack[pc[offset + i]];
|
stack[i + size - arity] = oldStack[pc[offset + i]];
|
||||||
/* Finish new frame */
|
/* Finish new frame */
|
||||||
gst_thread_endframe(vm, &thread);
|
gst_thread_endframe(vm, vm->thread);
|
||||||
/* Check tail call - if so, replace frame. */
|
/* Check tail call - if so, replace frame. */
|
||||||
if (isTCall) {
|
if (isTCall) {
|
||||||
stack = gst_thread_tail(vm, &thread);
|
stack = gst_thread_tail(vm, vm->thread);
|
||||||
} else {
|
} else {
|
||||||
gst_frame_ret(oldStack) = ret;
|
gst_frame_ret(oldStack) = ret;
|
||||||
}
|
}
|
||||||
|
@ -254,14 +235,11 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) {
|
||||||
} else {
|
} else {
|
||||||
int status;
|
int status;
|
||||||
gst_frame_pc(stack) = pc;
|
gst_frame_pc(stack) = pc;
|
||||||
GST_STATE_WRITE();
|
|
||||||
vm->ret.type = GST_NIL;
|
vm->ret.type = GST_NIL;
|
||||||
status = temp.data.cfunction(vm);
|
status = temp.data.cfunction(vm);
|
||||||
GST_STATE_SYNC();
|
stack = gst_thread_popframe(vm, vm->thread);
|
||||||
stack = gst_thread_popframe(vm, &thread);
|
|
||||||
if (status == GST_RETURN_OK) {
|
if (status == GST_RETURN_OK) {
|
||||||
if (thread.count < stackBase) {
|
if (vm->thread->count < stackBase) {
|
||||||
GST_STATE_WRITE();
|
|
||||||
return status;
|
return status;
|
||||||
} else {
|
} else {
|
||||||
stack[gst_frame_ret(stack)] = vm->ret;
|
stack[gst_frame_ret(stack)] = vm->ret;
|
||||||
|
@ -281,6 +259,10 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) {
|
||||||
* These opcodes are nto strictlyre required and can
|
* These opcodes are nto strictlyre required and can
|
||||||
* be reimplemented with stanard library functions */
|
* be reimplemented with stanard library functions */
|
||||||
|
|
||||||
|
case GST_OP_ERR: /* Throw error */
|
||||||
|
vm->ret = stack[pc[1]];
|
||||||
|
goto vm_error;
|
||||||
|
|
||||||
#define OP_BINARY_MATH(op) \
|
#define OP_BINARY_MATH(op) \
|
||||||
v1 = stack[pc[2]]; \
|
v1 = stack[pc[2]]; \
|
||||||
v2 = stack[pc[3]]; \
|
v2 = stack[pc[3]]; \
|
||||||
|
@ -401,15 +383,13 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) {
|
||||||
|
|
||||||
case GST_OP_YLD: /* Yield from function */
|
case GST_OP_YLD: /* Yield from function */
|
||||||
temp = stack[pc[1]];
|
temp = stack[pc[1]];
|
||||||
if (thread.parent == NULL) {
|
if (vm->thread->parent == NULL) {
|
||||||
vm->ret = temp;
|
vm->ret = temp;
|
||||||
return GST_RETURN_OK;
|
return GST_RETURN_OK;
|
||||||
}
|
}
|
||||||
gst_frame_pc(stack) = pc + 2;
|
gst_frame_pc(stack) = pc + 2;
|
||||||
GST_STATE_WRITE();
|
vm->thread = vm->thread->parent;
|
||||||
vm->thread = thread.parent;
|
stack = vm->thread->data + vm->thread->count;
|
||||||
thread = *vm->thread;
|
|
||||||
stack = thread.data + thread.count;
|
|
||||||
pc = gst_frame_pc(stack);
|
pc = gst_frame_pc(stack);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -418,8 +398,8 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) {
|
||||||
if (stack == NULL)
|
if (stack == NULL)
|
||||||
return GST_RETURN_ERROR;
|
return GST_RETURN_ERROR;
|
||||||
while (gst_frame_errjmp(stack) == NULL) {
|
while (gst_frame_errjmp(stack) == NULL) {
|
||||||
stack = gst_thread_popframe(vm, &thread);
|
stack = gst_thread_popframe(vm, vm->thread);
|
||||||
if (thread.count < stackBase)
|
if (vm->thread->count < stackBase)
|
||||||
return GST_RETURN_ERROR;
|
return GST_RETURN_ERROR;
|
||||||
}
|
}
|
||||||
pc = gst_frame_errjmp(stack);
|
pc = gst_frame_errjmp(stack);
|
||||||
|
@ -428,9 +408,9 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) {
|
||||||
|
|
||||||
} /* end switch */
|
} /* end switch */
|
||||||
|
|
||||||
/* TODO: Move collection only to places that allocate memory */
|
/* Check for collection every cycle. If the instruction definitely does
|
||||||
/* This, however, is good for testing to ensure no memory leaks */
|
* not allocate memory, it can use continue instead of break to
|
||||||
*vm->thread = thread;
|
* skip this check */
|
||||||
gst_maybe_collect(vm);
|
gst_maybe_collect(vm);
|
||||||
|
|
||||||
} /* end for */
|
} /* end for */
|
||||||
|
|
|
@ -20,7 +20,8 @@ struct GstParser {
|
||||||
enum {
|
enum {
|
||||||
GST_PARSER_PENDING = 0,
|
GST_PARSER_PENDING = 0,
|
||||||
GST_PARSER_FULL,
|
GST_PARSER_FULL,
|
||||||
GST_PARSER_ERROR
|
GST_PARSER_ERROR,
|
||||||
|
GST_PARSER_ROOT
|
||||||
} status;
|
} status;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,4 +38,12 @@ int gst_parse_cstring(GstParser *p, const char *string);
|
||||||
/* Parse a gst string. Returns number of bytes read */
|
/* Parse a gst string. Returns number of bytes read */
|
||||||
int gst_parse_string(GstParser *p, const uint8_t *string);
|
int gst_parse_string(GstParser *p, const uint8_t *string);
|
||||||
|
|
||||||
|
/* Check if a parser has a value that needs to be handled. If
|
||||||
|
* so, the parser will not parse any more input until that value
|
||||||
|
* is consumed. */
|
||||||
|
int gst_parse_hasvalue(GstParser *p);
|
||||||
|
|
||||||
|
/* Gets a value from the parser */
|
||||||
|
GstValue gst_parse_consume(GstParser *p);
|
||||||
|
|
||||||
#endif /* end of include guard: PARSE_H_ONYWMADW */
|
#endif /* end of include guard: PARSE_H_ONYWMADW */
|
||||||
|
|
|
@ -1 +1,6 @@
|
||||||
|
(: f (fn [x] (strcat (tostring x) "-abumba")))
|
||||||
|
|
||||||
|
(: i 100)
|
||||||
|
(while (> i 0) (print i) (: i (- i 1)))
|
||||||
|
|
||||||
|
(print (strcat (tostring (+ 1 2 3)) 'a 'b (f 'c)))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user