add load primitive and (minimal) stdlib
This commit is contained in:
parent
9ef27f90e1
commit
d6c89d0e6d
7 changed files with 75 additions and 2 deletions
|
|
@ -1,2 +1,5 @@
|
|||
# wolflisp
|
||||
a lisp but wolfy. right now it's very minimal... :^)
|
||||
|
||||
A toy Lisp started as a learning project.
|
||||
I might work on making it less toy-ish and more useful-ish, but for now expect
|
||||
bites and nibbles from it if you do things wrong. :^)
|
||||
|
|
|
|||
|
|
@ -290,6 +290,8 @@ O list_assoc(In *in, O key, O alist);
|
|||
O list_reverse(In *in, O list);
|
||||
O list_next(In *in, O *list);
|
||||
|
||||
int read_expr(In *in, Lx *lex, O *result);
|
||||
|
||||
V compile(Cm *co, O expr, I toplevel);
|
||||
V disassemble(Cm *co);
|
||||
O vm_run(Cm *c);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ V interp_init(In *in) {
|
|||
PRIM(">", prim_gt, 2, 2);
|
||||
PRIM("=", prim_equal, 0, -1); // variadic
|
||||
PRIM("gc", prim_gc, 0, 0);
|
||||
PRIM("load", prim_load, 1, 1);
|
||||
#undef PRIM
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <prim.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wolflisp.h>
|
||||
|
||||
#define BOOL(x) ((x) ? in->t : NIL)
|
||||
|
|
@ -207,3 +208,45 @@ O prim_gc(In *in, O *args, int argc, O env) {
|
|||
gc_collect(&in->gc);
|
||||
return NIL;
|
||||
}
|
||||
|
||||
O prim_load(In *in, O *args, int argc, O env) {
|
||||
(void)env;
|
||||
if (argc != 1)
|
||||
error_throw(in, "load: expected 1 argument, got %d", argc);
|
||||
if (type(args[0]) != TYPE_STR)
|
||||
error_throw(in, "load: expected string argument, got %s",
|
||||
typename(type(args[0])));
|
||||
Ss *s = (Ss *)(UNBOX(args[0]) + 1);
|
||||
FILE *fp = fopen(s->data, "r");
|
||||
if (!fp)
|
||||
error_throw(in, "load: could not open file '%s'", s->data);
|
||||
Lx lex = {0, 0, fp, {0}};
|
||||
nexttoken(&lex);
|
||||
O result = NIL;
|
||||
I mark = gc_rootmark(&in->gc);
|
||||
gc_addroot(&in->gc, &result);
|
||||
while (lex.kind != TOK_EOF) {
|
||||
O expr = NIL;
|
||||
if (read_expr(in, &lex, &expr) == -1)
|
||||
break;
|
||||
|
||||
Cm compiler;
|
||||
memset(&compiler, 0, sizeof(Cm));
|
||||
compiler.in = in;
|
||||
|
||||
compile(&compiler, expr, 1);
|
||||
result = vm_run(&compiler);
|
||||
|
||||
free(compiler.code);
|
||||
if (compiler.locals.data)
|
||||
free(compiler.locals.data);
|
||||
if (compiler.constants.data)
|
||||
free(compiler.constants.data);
|
||||
|
||||
nexttoken(&lex);
|
||||
}
|
||||
|
||||
gc_rootreset(&in->gc, mark);
|
||||
fclose(fp);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,3 +18,4 @@ O prim_gt(In *in, O *args, int argc, O env);
|
|||
O prim_nil_p(In *in, O *args, int argc, O env);
|
||||
O prim_env(In *in, O *args, int argc, O env);
|
||||
O prim_gc(In *in, O *args, int argc, O env);
|
||||
O prim_load(In *in, O *args, int argc, O env);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ void repl(void) {
|
|||
if (setjmp(in.err.handler) == 0) {
|
||||
in.err.active = 1;
|
||||
compile(&compiler, expr, 1);
|
||||
disassemble(&compiler);
|
||||
result = vm_run(&compiler);
|
||||
println(result);
|
||||
} else {
|
||||
|
|
|
|||
24
src/std.scm
Normal file
24
src/std.scm
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
(def defmacro
|
||||
(mac (name args . body)
|
||||
(list 'def name (cons 'mac (cons args body)))))
|
||||
|
||||
(defmacro defn (name args . body)
|
||||
(list 'def name (cons 'fn (cons args body))))
|
||||
|
||||
(defn map-aux (f acc l)
|
||||
(if (nil? l)
|
||||
(acc f '())
|
||||
(map-aux
|
||||
f
|
||||
(fn (f ys)
|
||||
(acc f (cons (f (head l)) ys)))
|
||||
(tail l))))
|
||||
(defn map (f l)
|
||||
(map-aux f (fn (f x) x) l))
|
||||
|
||||
(defmacro let (bindings . body)
|
||||
(cons
|
||||
(cons 'fn (cons (map head bindings) body))
|
||||
(map (fn (x) (head (tail x))) bindings)))
|
||||
|
||||
'()
|
||||
Loading…
Add table
Add a link
Reference in a new issue