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:
parent
7b83247c07
commit
96a605fbc0
@ -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;
|
||||||
|
for (;;) {
|
||||||
/* Init parser */
|
/* Init parser */
|
||||||
gst_parser(&p, vm);
|
gst_parser(&p, vm);
|
||||||
/* Get and parse input until we have a full form */
|
while (p.status != GST_PARSER_ERROR && p.status != GST_PARSER_FULL) {
|
||||||
while (p.status != GST_PARSER_ERROR) {
|
|
||||||
if (*reader == '\0') {
|
if (*reader == '\0') {
|
||||||
if (!fgets(buffer, sizeof(buffer), in)) {
|
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 */
|
/* Check that parser is complete */
|
||||||
if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) {
|
if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) {
|
||||||
printf("Unexpected end of source\n");
|
printf("Unexpected end of source\n");
|
||||||
return 1;
|
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;
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
core/parse.c
24
core/parse.c
@ -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, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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. */
|
||||||
|
@ -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
13
libs/hello.gst
Normal 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)))
|
||||||
|
)
|
@ -1,8 +0,0 @@
|
|||||||
# Make parser
|
|
||||||
|
|
||||||
(: parser (fn [in] {
|
|
||||||
'in in
|
|
||||||
'line 0
|
|
||||||
'index 0
|
|
||||||
'states []
|
|
||||||
}))
|
|
11
libs/pp.gst
11
libs/pp.gst
@ -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)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
(print 1)
|
|
||||||
|
|
||||||
(: counter 0)
|
|
||||||
(while (< counter 100) (print counter) (: counter (+ 1 counter)))
|
|
Loading…
Reference in New Issue
Block a user