1
0
mirror of https://github.com/janet-lang/janet synced 2024-12-26 00:10:27 +00:00

Fix variadic functions.

This commit is contained in:
Calvin Rose 2017-05-07 16:48:35 -04:00
parent 7b83247c07
commit 96a605fbc0
12 changed files with 83 additions and 104 deletions

View File

@ -45,8 +45,8 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) {
gst_compiler_globals(&c, gst_wrap_table(vm->registry)); gst_compiler_globals(&c, gst_wrap_table(vm->registry));
func = gst_wrap_function(gst_compiler_compile(&c, ast)); func = gst_wrap_function(gst_compiler_compile(&c, ast));
/* Check for compilation errors */ /* Check for compilation errors */
if (c.error) { if (c.error.type != GST_NIL) {
printf("Compiler error: %s\n", c.error); printf("Compiler error: %s\n", (const char *)gst_to_string(vm, c.error));
return 1; return 1;
} }
/* Execute function */ /* Execute function */
@ -54,7 +54,7 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) {
if (vm->crash) { if (vm->crash) {
printf("VM crash: %s\n", vm->crash); printf("VM crash: %s\n", vm->crash);
} else { } 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; return 1;
} }
@ -63,35 +63,43 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) {
/* Parse a file and execute it */ /* Parse a file and execute it */
int debug_run(Gst *vm, FILE *in) { int debug_run(Gst *vm, FILE *in) {
char buffer[1024] = {0}; char buffer[2048] = {0};
const char *reader = buffer; const char *reader = buffer;
GstValue ast;
GstParser p; GstParser p;
/* Init parser */ for (;;) {
gst_parser(&p, vm); /* Init parser */
/* Get and parse input until we have a full form */ gst_parser(&p, vm);
while (p.status != GST_PARSER_ERROR) { while (p.status != GST_PARSER_ERROR && p.status != GST_PARSER_FULL) {
if (*reader == '\0') { if (*reader == '\0') {
if (!fgets(buffer, sizeof(buffer), in)) { if (!fgets(buffer, sizeof(buffer), in)) {
/* Check that parser is complete */ /* Add possible end of line */
if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) { if (p.status == GST_PARSER_PENDING)
printf("Unexpected end of source\n"); gst_parse_cstring(&p, "\n");
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;
}
/* 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); 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 */
/* Check if file read in correctly */ if (p.error) {
if (p.error) { printf("Parse error: %s\n", 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; return 1;
} }

View File

@ -117,6 +117,11 @@ BUFFER_DEFINE(i16, int16_t)
/* If there is an error during compilation, /* If there is an error during compilation,
* jump back to start */ * jump back to start */
static void c_error(GstCompiler *c, const char *e) { 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; c->error = e;
longjmp(c->onError, 1); longjmp(c->onError, 1);
} }
@ -183,7 +188,11 @@ static uint16_t compiler_get_local(GstCompiler *c, GstScope *scope) {
if (scope->nextLocal + 1 == 0) { if (scope->nextLocal + 1 == 0) {
c_error(c, "too many local variables"); 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 { } else {
return scope->freeHeap[--scope->heapSize]; return scope->freeHeap[--scope->heapSize];
} }
@ -471,7 +480,7 @@ static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) {
Slot ret; Slot ret;
int status = symbol_resolve(c, sym, &level, &index, &lit); int status = symbol_resolve(c, sym, &level, &index, &lit);
if (!status) { if (!status) {
c_error(c, "undefined symbol"); c_error1(c, sym);
} }
if (opts.resultUnused) return nil_slot(); if (opts.resultUnused) return nil_slot();
if (status == 2) { if (status == 2) {
@ -626,7 +635,7 @@ static Slot compile_function(GstCompiler *c, FormOptions opts, const GstValue *f
GstArray *params; GstArray *params;
FormOptions subOpts = form_options_default(); FormOptions subOpts = form_options_default();
Slot ret; Slot ret;
int varargs; int varargs = 0;
uint32_t arity; uint32_t arity;
if (opts.resultUnused) return nil_slot(); if (opts.resultUnused) return nil_slot();
ret = compiler_get_target(c, opts); ret = compiler_get_target(c, opts);
@ -1092,7 +1101,7 @@ void gst_compiler(GstCompiler *c, Gst *vm) {
c->vm = vm; c->vm = vm;
c->buffer = gst_buffer(vm, 128); c->buffer = gst_buffer(vm, 128);
c->tail = NULL; c->tail = NULL;
c->error = NULL; c->error.type = GST_NIL;
c->trackers = NULL; c->trackers = NULL;
compiler_push_scope(c, 0); compiler_push_scope(c, 0);
} }
@ -1135,8 +1144,8 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) {
c->trackers = NULL; c->trackers = NULL;
if (c->tail) if (c->tail)
c->tail->parent = NULL; c->tail->parent = NULL;
if (c->error == NULL) if (c->error.type == GST_NIL)
c->error = "unknown error"; c->error = gst_string_cv(c->vm, "unknown error");
return NULL; return NULL;
} }
/* Create a scope */ /* Create a scope */
@ -1169,6 +1178,7 @@ static void gst_compiler_mark(Gst *vm, void *data, uint32_t len) {
return; return;
/* Mark compiler */ /* Mark compiler */
gst_mark_value(vm, gst_wrap_buffer(c->buffer)); 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. */ /* Mark trackers - the trackers themselves are all on the stack. */
st = (SlotTracker *) c->trackers; st = (SlotTracker *) c->trackers;
while (st) { while (st) {
@ -1232,7 +1242,7 @@ static int gst_stl_compiler_compile(Gst *vm) {
gst_c_throwc(vm, "expected compiler"); gst_c_throwc(vm, "expected compiler");
ret = gst_compiler_compile(c, gst_arg(vm, 1)); ret = gst_compiler_compile(c, gst_arg(vm, 1));
if (ret == NULL) if (ret == NULL)
gst_c_throwc(vm, c->error); gst_c_throw(vm, c->error);
gst_c_return(vm, gst_wrap_function(ret)); gst_c_return(vm, gst_wrap_function(ret));
} }

View File

@ -153,7 +153,7 @@ static int is_symbol_char(uint8_t c) {
if (c >= '0' && c <= ':') return 1; 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 >= '$' && c == '&') return 1; if (c >= '#' && c <= '&') return 1;
if (c == '_') return 1; if (c == '_') return 1;
if (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) { static void dispatch_char(GstParser *p, uint8_t c) {
int done = 0; int done = 0;
++p->index; ++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 */ /* Dispatch character to state */
while (!done) { while (!done) {
GstParseState *top = parser_peek(p); GstParseState *top = parser_peek(p);
@ -504,6 +488,11 @@ int gst_parse_string(GstParser *p, const uint8_t *string) {
return i; 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 /* 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 * so, the parser will not parse any more input until that value
* is consumed. */ * is consumed. */
@ -529,7 +518,6 @@ void gst_parser(GstParser *p, Gst *vm) {
p->error = NULL; p->error = NULL;
p->status = GST_PARSER_ROOT; p->status = GST_PARSER_ROOT;
p->value.type = GST_NIL; p->value.type = GST_NIL;
p->flags = GST_PARSER_FLAG_EXPECTING_COMMENT;
parser_push(p, PTYPE_ROOT, ' '); parser_push(p, PTYPE_ROOT, ' ');
} }

View File

@ -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) { void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n) {
GstValue *stack = thread->data + thread->count; GstValue *stack = thread->data + thread->count;
uint32_t size = gst_frame_size(stack); 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); gst_thread_pushnil(vm, thread, n - size + 1);
stack = thread->data + thread->count; stack = thread->data + thread->count;
stack[n].type = GST_TUPLE; stack[n].type = GST_TUPLE;
stack[n].data.tuple = gst_tuple_end(vm, gst_tuple_begin(vm, 0)); stack[n].data.tuple = gst_tuple_end(vm, gst_tuple_begin(vm, 0));
gst_frame_size(stack) = n + 1;
} else { } else {
uint32_t i; uint32_t i;
GstValue *tuple = gst_tuple_begin(vm, size - n); 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]; tuple[i - n] = stack[i];
stack[n].type = GST_TUPLE; stack[n].type = GST_TUPLE;
stack[n].data.tuple = gst_tuple_end(vm, tuple); stack[n].data.tuple = gst_tuple_end(vm, tuple);
gst_frame_size(stack) = n + 1;
} }
} }

View File

@ -242,6 +242,7 @@ int gst_continue(Gst *vm) {
stack = gst_thread_stack(vm->thread); stack = gst_thread_stack(vm->thread);
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
stack[oldsize + i] = data[i]; stack[oldsize + i] = data[i];
/*gst_frame_size(stack) += count;*/
pc += 2; pc += 2;
} }
break; break;

View File

@ -32,7 +32,7 @@ typedef struct GstScope GstScope;
/* Compilation state */ /* Compilation state */
struct GstCompiler { struct GstCompiler {
Gst *vm; Gst *vm;
const char *error; GstValue error;
jmp_buf onError; jmp_buf onError;
GstScope *tail; GstScope *tail;
GstBuffer *buffer; GstBuffer *buffer;

View File

@ -37,7 +37,6 @@ struct GstParser {
uint32_t count; uint32_t count;
uint32_t cap; uint32_t cap;
uint32_t index; uint32_t index;
uint32_t flags;
uint32_t quoteCount; uint32_t quoteCount;
enum { enum {
GST_PARSER_PENDING = 0, GST_PARSER_PENDING = 0,
@ -47,10 +46,6 @@ struct GstParser {
} status; } status;
}; };
/* Some parser flags */
#define GST_PARSER_FLAG_INCOMMENT 1
#define GST_PARSER_FLAG_EXPECTING_COMMENT 2
/* Initialize a parser */ /* Initialize a parser */
void gst_parser(GstParser *p, Gst *vm); 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 */ /* 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);
/* 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 /* 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 * so, the parser will not parse any more input until that value
* is consumed. */ * is consumed. */

View File

@ -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 []
}))

13
libs/hello.gst Normal file
View File

@ -0,0 +1,13 @@
(print "Hello, World!")
(do (+ 1 2 3))
(print _ )
"Comment"
(do
(: i 0)
(while (< i 1000)
(print i)
(: i (+ i 1)))
)

View File

@ -1,8 +0,0 @@
# Make parser
(: parser (fn [in] {
'in in
'line 0
'index 0
'states []
}))

View File

@ -1,9 +1,8 @@
(do (do
# Declare pretty print
(: pp nil) (: pp nil)
# Pretty print an array or tuple "Pretty print an array or tuple"
(: print-seq (fn [start end a seen] (: print-seq (fn [start end a seen]
(: seen (if seen seen {})) (: seen (if seen seen {}))
(if (get seen a) (get seen a) (if (get seen a) (get seen a)
@ -21,7 +20,7 @@
(set! seen a ret) (set! seen a ret)
ret)))) ret))))
# Pretty print an object or struct "Pretty print an object or struct"
(: print-struct (fn [start end s seen] (: print-struct (fn [start end s seen]
(: seen (if seen seen {})) (: seen (if seen seen {}))
(if (get seen s) (get seen s) (if (get seen s) (get seen s)
@ -40,7 +39,7 @@
(set! seen s ret) (set! seen s ret)
ret)))) ret))))
# Type handlers "Type handlers"
(: handlers { (: handlers {
"array" (fn [a seen] (print-seq "[" "]" a seen)) "array" (fn [a seen] (print-seq "[" "]" a seen))
"tuple" (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)) "struct" (fn [s seen] (print-struct "#{" "}" s seen))
}) })
# Define pretty print "Define pretty print"
(: pp (fn [x seen] (: pp (fn [x seen]
(: handler (get handlers (type x))) (: handler (get handlers (type x)))
(: handler (if handler handler tostring)) (: handler (if handler handler tostring))
(handler x seen))) (handler x seen)))
# Export pretty print "Export pretty print"
(export! 'pp pp) (export! 'pp pp)
) )

View File

@ -1,4 +0,0 @@
(print 1)
(: counter 0)
(while (< counter 100) (print counter) (: counter (+ 1 counter)))