diff --git a/client/main.c b/client/main.c index f64cda0d..011c9080 100644 --- a/client/main.c +++ b/client/main.c @@ -45,8 +45,8 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) { gst_compiler_globals(&c, gst_wrap_table(vm->registry)); func = gst_wrap_function(gst_compiler_compile(&c, ast)); /* Check for compilation errors */ - if (c.error) { - printf("Compiler error: %s\n", c.error); + if (c.error.type != GST_NIL) { + printf("Compiler error: %s\n", (const char *)gst_to_string(vm, c.error)); return 1; } /* Execute function */ @@ -54,7 +54,7 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) { if (vm->crash) { printf("VM crash: %s\n", vm->crash); } else { - printf("VM error: %s\n", (char *)gst_to_string(vm, vm->ret)); + printf("VM error: %s\n", (const char *)gst_to_string(vm, vm->ret)); } return 1; } @@ -63,35 +63,43 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) { /* Parse a file and execute it */ int debug_run(Gst *vm, FILE *in) { - char buffer[1024] = {0}; + char buffer[2048] = {0}; const char *reader = buffer; - GstValue ast; GstParser p; - /* Init parser */ - gst_parser(&p, vm); - /* 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)) { - /* Check that parser is complete */ - if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) { - printf("Unexpected end of source\n"); - return 1; + for (;;) { + /* Init parser */ + gst_parser(&p, vm); + while (p.status != GST_PARSER_ERROR && p.status != GST_PARSER_FULL) { + if (*reader == '\0') { + if (!fgets(buffer, sizeof(buffer), in)) { + /* Add possible end of line */ + if (p.status == GST_PARSER_PENDING) + gst_parse_cstring(&p, "\n"); + /* Check that parser is complete */ + if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) { + printf("Unexpected end of source\n"); + return 1; + } + /* Otherwise we finished the file with no problems*/ + return 0; } - return 0; + reader = buffer; } - reader = buffer; - } - if (p.status != GST_PARSER_FULL) reader += gst_parse_cstring(&p, reader); - if (gst_parse_hasvalue(&p)) { - ast = gst_parse_consume(&p); - debug_compile_and_run(vm, ast, gst_wrap_nil()); } - } - /* Check if file read in correctly */ - if (p.error) { - printf("Parse error: %s\n", p.error); + /* Check if file read in correctly */ + if (p.error) { + printf("Parse error: %s\n", p.error); + break; + } + /* Check that parser is complete */ + if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) { + printf("Unexpected end of source\n"); + break; + } + if (debug_compile_and_run(vm, gst_parse_consume(&p), vm->ret)) { + break; + } } return 1; } diff --git a/core/compile.c b/core/compile.c index 10354a6d..e2051a04 100644 --- a/core/compile.c +++ b/core/compile.c @@ -117,6 +117,11 @@ BUFFER_DEFINE(i16, int16_t) /* If there is an error during compilation, * jump back to start */ static void c_error(GstCompiler *c, const char *e) { + c->error = gst_string_cv(c->vm, e); + longjmp(c->onError, 1); +} + +static void c_error1(GstCompiler *c, GstValue e) { c->error = e; longjmp(c->onError, 1); } @@ -183,7 +188,11 @@ static uint16_t compiler_get_local(GstCompiler *c, GstScope *scope) { if (scope->nextLocal + 1 == 0) { c_error(c, "too many local variables"); } - return scope->nextLocal++; + ++scope->nextLocal; + if (scope->nextLocal > scope->frameSize) { + scope->frameSize = scope->nextLocal; + } + return scope->nextLocal - 1; } else { return scope->freeHeap[--scope->heapSize]; } @@ -471,7 +480,7 @@ static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) { Slot ret; int status = symbol_resolve(c, sym, &level, &index, &lit); if (!status) { - c_error(c, "undefined symbol"); + c_error1(c, sym); } if (opts.resultUnused) return nil_slot(); if (status == 2) { @@ -626,7 +635,7 @@ static Slot compile_function(GstCompiler *c, FormOptions opts, const GstValue *f GstArray *params; FormOptions subOpts = form_options_default(); Slot ret; - int varargs; + int varargs = 0; uint32_t arity; if (opts.resultUnused) return nil_slot(); ret = compiler_get_target(c, opts); @@ -1092,7 +1101,7 @@ void gst_compiler(GstCompiler *c, Gst *vm) { c->vm = vm; c->buffer = gst_buffer(vm, 128); c->tail = NULL; - c->error = NULL; + c->error.type = GST_NIL; c->trackers = NULL; compiler_push_scope(c, 0); } @@ -1135,8 +1144,8 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) { c->trackers = NULL; if (c->tail) c->tail->parent = NULL; - if (c->error == NULL) - c->error = "unknown error"; + if (c->error.type == GST_NIL) + c->error = gst_string_cv(c->vm, "unknown error"); return NULL; } /* Create a scope */ @@ -1169,6 +1178,7 @@ static void gst_compiler_mark(Gst *vm, void *data, uint32_t len) { return; /* Mark compiler */ gst_mark_value(vm, gst_wrap_buffer(c->buffer)); + gst_mark_value(vm, c->error); /* Mark trackers - the trackers themselves are all on the stack. */ st = (SlotTracker *) c->trackers; while (st) { @@ -1232,7 +1242,7 @@ static int gst_stl_compiler_compile(Gst *vm) { gst_c_throwc(vm, "expected compiler"); ret = gst_compiler_compile(c, gst_arg(vm, 1)); if (ret == NULL) - gst_c_throwc(vm, c->error); + gst_c_throw(vm, c->error); gst_c_return(vm, gst_wrap_function(ret)); } diff --git a/core/parse.c b/core/parse.c index 4544bd30..3611c80e 100644 --- a/core/parse.c +++ b/core/parse.c @@ -153,7 +153,7 @@ static int is_symbol_char(uint8_t c) { if (c >= '0' && c <= ':') return 1; if (c >= '<' && c <= '@') return 1; if (c >= '*' && c <= '/') return 1; - if (c >= '$' && c == '&') return 1; + if (c >= '#' && c <= '&') return 1; if (c == '_') return 1; if (c == '^') return 1; if (c == '!') return 1; @@ -444,22 +444,6 @@ static int form_state(GstParser *p, uint8_t c) { static void dispatch_char(GstParser *p, uint8_t c) { int done = 0; ++p->index; - /* Handle comments */ - if (p->flags & GST_PARSER_FLAG_INCOMMENT) { - if (c == '\n') { - p->flags = GST_PARSER_FLAG_EXPECTING_COMMENT; - } - return; - } else if (p->flags & GST_PARSER_FLAG_EXPECTING_COMMENT) { - if (c == '#') { - p->flags = GST_PARSER_FLAG_INCOMMENT; - return; - } else if (!is_whitespace(c)) { - p->flags = 0; - } else { - return; - } - } /* Dispatch character to state */ while (!done) { GstParseState *top = parser_peek(p); @@ -504,6 +488,11 @@ int gst_parse_string(GstParser *p, const uint8_t *string) { return i; } +/* Parse a single byte */ +void gst_parse_byte(GstParser *p, uint8_t byte) { + dispatch_char(p, byte); +} + /* 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. */ @@ -529,7 +518,6 @@ void gst_parser(GstParser *p, Gst *vm) { p->error = NULL; p->status = GST_PARSER_ROOT; p->value.type = GST_NIL; - p->flags = GST_PARSER_FLAG_EXPECTING_COMMENT; parser_push(p, PTYPE_ROOT, ' '); } diff --git a/core/thread.c b/core/thread.c index 9cc4422f..3659dd23 100644 --- a/core/thread.c +++ b/core/thread.c @@ -85,11 +85,13 @@ void gst_thread_pushnil(Gst *vm, GstThread *thread, uint32_t n) { void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n) { GstValue *stack = thread->data + thread->count; uint32_t size = gst_frame_size(stack); - if (n >= size) { + if (n > size) { + /* Push one extra nil to ensure space for tuple */ gst_thread_pushnil(vm, thread, n - size + 1); stack = thread->data + thread->count; stack[n].type = GST_TUPLE; stack[n].data.tuple = gst_tuple_end(vm, gst_tuple_begin(vm, 0)); + gst_frame_size(stack) = n + 1; } else { uint32_t i; GstValue *tuple = gst_tuple_begin(vm, size - n); @@ -97,7 +99,6 @@ void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n) { tuple[i - n] = stack[i]; stack[n].type = GST_TUPLE; stack[n].data.tuple = gst_tuple_end(vm, tuple); - gst_frame_size(stack) = n + 1; } } diff --git a/core/vm.c b/core/vm.c index 1432c4f8..b263272f 100644 --- a/core/vm.c +++ b/core/vm.c @@ -242,6 +242,7 @@ int gst_continue(Gst *vm) { stack = gst_thread_stack(vm->thread); for (i = 0; i < count; ++i) stack[oldsize + i] = data[i]; + /*gst_frame_size(stack) += count;*/ pc += 2; } break; diff --git a/include/gst/compile.h b/include/gst/compile.h index 829958ed..a4378773 100644 --- a/include/gst/compile.h +++ b/include/gst/compile.h @@ -32,7 +32,7 @@ typedef struct GstScope GstScope; /* Compilation state */ struct GstCompiler { Gst *vm; - const char *error; + GstValue error; jmp_buf onError; GstScope *tail; GstBuffer *buffer; diff --git a/include/gst/parse.h b/include/gst/parse.h index 17aa5158..6f8b04ef 100644 --- a/include/gst/parse.h +++ b/include/gst/parse.h @@ -37,7 +37,6 @@ struct GstParser { uint32_t count; uint32_t cap; uint32_t index; - uint32_t flags; uint32_t quoteCount; enum { GST_PARSER_PENDING = 0, @@ -47,10 +46,6 @@ struct GstParser { } status; }; -/* Some parser flags */ -#define GST_PARSER_FLAG_INCOMMENT 1 -#define GST_PARSER_FLAG_EXPECTING_COMMENT 2 - /* Initialize a parser */ void gst_parser(GstParser *p, Gst *vm); @@ -60,6 +55,9 @@ int gst_parse_cstring(GstParser *p, const char *string); /* Parse a gst string. Returns number of bytes read */ int gst_parse_string(GstParser *p, const uint8_t *string); +/* Parse a single byte */ +void gst_parse_byte(GstParser *p, uint8_t byte); + /* 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. */ diff --git a/libs/compile.gst b/libs/compile.gst deleted file mode 100644 index e743757d..00000000 --- a/libs/compile.gst +++ /dev/null @@ -1,27 +0,0 @@ -# Real compiler - -# Make compiler -(: make-compiler (fn [] { - 'scopes [] - 'env [] - 'labels {} -})) - -# Make default form options -(: make-formopts (fn [] { - 'target nil - 'resultUnused false - 'canChoose true - 'isTail false -})) - -# Make scope -(: make-scope (fn [] { - 'level 0 - 'nextSlot 0 - 'frameSize 0 - 'freeSlots [] - 'literals {} - 'literalsArray [] - 'slotMap [] -})) diff --git a/libs/hello.gst b/libs/hello.gst new file mode 100644 index 00000000..298f057e --- /dev/null +++ b/libs/hello.gst @@ -0,0 +1,13 @@ +(print "Hello, World!") + +(do (+ 1 2 3)) + +(print _ ) + +"Comment" +(do + (: i 0) + (while (< i 1000) + (print i) + (: i (+ i 1))) +) diff --git a/libs/parse.gst b/libs/parse.gst deleted file mode 100644 index e6e9478c..00000000 --- a/libs/parse.gst +++ /dev/null @@ -1,8 +0,0 @@ -# Make parser - -(: parser (fn [in] { - 'in in - 'line 0 - 'index 0 - 'states [] -})) diff --git a/libs/pp.gst b/libs/pp.gst index 734b15e3..8474ce54 100644 --- a/libs/pp.gst +++ b/libs/pp.gst @@ -1,9 +1,8 @@ (do -# Declare pretty print (: pp nil) -# Pretty print an array or tuple +"Pretty print an array or tuple" (: print-seq (fn [start end a seen] (: seen (if seen seen {})) (if (get seen a) (get seen a) @@ -21,7 +20,7 @@ (set! seen a ret) ret)))) -# Pretty print an object or struct +"Pretty print an object or struct" (: print-struct (fn [start end s seen] (: seen (if seen seen {})) (if (get seen s) (get seen s) @@ -40,7 +39,7 @@ (set! seen s ret) ret)))) -# Type handlers +"Type handlers" (: handlers { "array" (fn [a seen] (print-seq "[" "]" a seen)) "tuple" (fn [a seen] (print-seq "(" ")" a seen)) @@ -48,13 +47,13 @@ "struct" (fn [s seen] (print-struct "#{" "}" s seen)) }) -# Define pretty print +"Define pretty print" (: pp (fn [x seen] (: handler (get handlers (type x))) (: handler (if handler handler tostring)) (handler x seen))) -# Export pretty print +"Export pretty print" (export! 'pp pp) ) diff --git a/libs/stl.gst b/libs/stl.gst deleted file mode 100644 index 4180ef7d..00000000 --- a/libs/stl.gst +++ /dev/null @@ -1,4 +0,0 @@ -(print 1) - -(: counter 0) -(while (< counter 100) (print counter) (: counter (+ 1 counter)))