add load primitive and (minimal) stdlib

This commit is contained in:
Lobo 2026-01-15 12:17:43 -03:00
parent 9ef27f90e1
commit d6c89d0e6d
7 changed files with 75 additions and 2 deletions

View file

@ -1,2 +1,5 @@
# wolflisp # 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. :^)

View file

@ -290,6 +290,8 @@ O list_assoc(In *in, O key, O alist);
O list_reverse(In *in, O list); O list_reverse(In *in, O list);
O list_next(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 compile(Cm *co, O expr, I toplevel);
V disassemble(Cm *co); V disassemble(Cm *co);
O vm_run(Cm *c); O vm_run(Cm *c);

View file

@ -42,6 +42,7 @@ V interp_init(In *in) {
PRIM(">", prim_gt, 2, 2); PRIM(">", prim_gt, 2, 2);
PRIM("=", prim_equal, 0, -1); // variadic PRIM("=", prim_equal, 0, -1); // variadic
PRIM("gc", prim_gc, 0, 0); PRIM("gc", prim_gc, 0, 0);
PRIM("load", prim_load, 1, 1);
#undef PRIM #undef PRIM
} }

View file

@ -1,5 +1,6 @@
#include <prim.h> #include <prim.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <wolflisp.h> #include <wolflisp.h>
#define BOOL(x) ((x) ? in->t : NIL) #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); gc_collect(&in->gc);
return NIL; 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;
}

View file

@ -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_nil_p(In *in, O *args, int argc, O env);
O prim_env(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_gc(In *in, O *args, int argc, O env);
O prim_load(In *in, O *args, int argc, O env);

View file

@ -26,7 +26,6 @@ void repl(void) {
if (setjmp(in.err.handler) == 0) { if (setjmp(in.err.handler) == 0) {
in.err.active = 1; in.err.active = 1;
compile(&compiler, expr, 1); compile(&compiler, expr, 1);
disassemble(&compiler);
result = vm_run(&compiler); result = vm_run(&compiler);
println(result); println(result);
} else { } else {

24
src/std.scm Normal file
View 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)))
'()