From 7563e4e5c3c346b8b11f7e66cdb11c81bcf58fa9 Mon Sep 17 00:00:00 2001 From: Mistivia Date: Sun, 22 Jun 2025 23:32:56 +0800 Subject: add symbol functions --- Makefile | 3 ++ src/builtins.c | 22 +++++++++++++ src/builtins.h | 98 ++++++++++++++++++++++++++++--------------------------- src/interp.c | 49 +++++++++++++++------------- src/interp.h | 1 + tests/lambda.lisp | 7 ++++ tests/symbol.lisp | 4 +++ tests/test.lisp | 34 ++++++++++--------- 8 files changed, 132 insertions(+), 86 deletions(-) create mode 100644 tests/symbol.lisp diff --git a/Makefile b/Makefile index ac30fc3..b3ebc74 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,9 @@ tests_bin=$(tests:.c=.bin) all: bamboo-lisp +install: bamboo-lisp + sudo cp bamboo-lisp /usr/local/bin/bamboo + src/prelude.c: src/prelude.lisp cat src/prelude.lisp | python scripts/genprelude.py > src/prelude.c diff --git a/src/builtins.c b/src/builtins.c index b8040ef..98252f8 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -6,6 +6,28 @@ #include #include +SExpRef builtin_symbol2string(Interp *interp, SExpRef args) { + if (LENGTH(args) != 1) return new_error(interp, "symbol->string: arg num error.\n"); + SExpRef arg = CAR(args); + if (VALTYPE(arg) != kSymbolSExp) return new_error(interp, "symbol->string: type error.\n"); + return new_string(interp, REF(arg)->str); +} + +SExpRef builtin_intern(Interp *interp, SExpRef args) { + if (LENGTH(args) != 1) return new_error(interp, "intern: arg num error.\n"); + SExpRef arg = CAR(args); + if (VALTYPE(arg) != kStringSExp) return new_error(interp, "intern: type error.\n"); + return new_symbol(interp, REF(arg)->str); +} + +SExpRef builtin_gensym(Interp *interp, SExpRef args) { + if (LENGTH(args) != 0) return new_error(interp, "gensym: no arg.\n"); + char buf[16]; + snprintf(buf, 16, "sYyYm%d", interp->gensym_cnt); + interp->gensym_cnt++; + return new_symbol(interp, buf); +} + SExpRef builtin_float(Interp *interp, SExpRef args) { if (LENGTH(args) != 1) return new_error(interp, "float: expect 1 arg.\n"); SExpRef x = CAR(args); diff --git a/src/builtins.h b/src/builtins.h index 3c54bdc..5b6b763 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -3,53 +3,55 @@ #include "interp.h" - -SExpRef builtin_sqrt(Interp *interp, SExpRef sexp); -SExpRef builtin_cbrt(Interp *interp, SExpRef sexp); -SExpRef builtin_float(Interp *interp, SExpRef sexp); -SExpRef builtin_abs(Interp *interp, SExpRef sexp); -SExpRef builtin_pow(Interp *interp, SExpRef sexp); -SExpRef builtin_floor(Interp *interp, SExpRef sexp); -SExpRef builtin_truncate(Interp *interp, SExpRef sexp); -SExpRef builtin_ceiling(Interp *interp, SExpRef sexp); -SExpRef builtin_round(Interp *interp, SExpRef sexp); -SExpRef builtin_sin(Interp *interp, SExpRef sexp); -SExpRef builtin_cos(Interp *interp, SExpRef sexp); -SExpRef builtin_tan(Interp *interp, SExpRef sexp); -SExpRef builtin_asin(Interp *interp, SExpRef sexp); -SExpRef builtin_acos(Interp *interp, SExpRef sexp); -SExpRef builtin_atan(Interp *interp, SExpRef sexp); -SExpRef builtin_ln(Interp *interp, SExpRef sexp); -SExpRef builtin_log10(Interp *interp, SExpRef sexp); -SExpRef builtin_log2(Interp *interp, SExpRef sexp); -SExpRef builtin_exp(Interp *interp, SExpRef sexp); -SExpRef builtin_min(Interp *interp, SExpRef sexp); -SExpRef builtin_max(Interp *interp, SExpRef sexp); -SExpRef builtin_equal(Interp *interp, SExpRef sexp); -SExpRef builtin_eq(Interp *interp, SExpRef sexp); -SExpRef builtin_format(Interp *interp, SExpRef sexp); -SExpRef builtin_concat(Interp *interp, SExpRef sexp); -SExpRef builtin_print(Interp *interp, SExpRef sexp); -SExpRef builtin_exit(Interp *interp, SExpRef sexp); -SExpRef builtin_error(Interp *interp, SExpRef sexp); -SExpRef builtin_list(Interp *interp, SExpRef sexp); -SExpRef builtin_car(Interp *interp, SExpRef sexp); -SExpRef builtin_cdr(Interp *interp, SExpRef sexp); -SExpRef builtin_cons(Interp *interp, SExpRef sexp); -SExpRef builtin_not(Interp *interp, SExpRef sexp); -SExpRef builtin_add(Interp *interp, SExpRef sexp); -SExpRef builtin_sub(Interp *interp, SExpRef sexp); -SExpRef builtin_mul(Interp *interp, SExpRef sexp); -SExpRef builtin_div(Interp *interp, SExpRef sexp); -SExpRef builtin_idiv(Interp *interp, SExpRef sexp); -SExpRef builtin_mod(Interp *interp, SExpRef sexp); -SExpRef builtin_num_equal(Interp *interp, SExpRef sexp); -SExpRef builtin_num_neq(Interp *interp, SExpRef sexp); -SExpRef builtin_gt(Interp *interp, SExpRef sexp); -SExpRef builtin_lt(Interp *interp, SExpRef sexp); -SExpRef builtin_ge(Interp *interp, SExpRef sexp); -SExpRef builtin_le(Interp *interp, SExpRef sexp); -SExpRef builtin_princ(Interp *interp, SExpRef sexp); -SExpRef builtin_gcstat(Interp *interp, SExpRef sexp); +SExpRef builtin_symbol2string(Interp *interp, SExpRef args); +SExpRef builtin_intern(Interp *interp, SExpRef args); +SExpRef builtin_gensym(Interp *interp, SExpRef args); +SExpRef builtin_sqrt(Interp *interp, SExpRef args); +SExpRef builtin_cbrt(Interp *interp, SExpRef args); +SExpRef builtin_float(Interp *interp, SExpRef args); +SExpRef builtin_abs(Interp *interp, SExpRef args); +SExpRef builtin_pow(Interp *interp, SExpRef args); +SExpRef builtin_floor(Interp *interp, SExpRef args); +SExpRef builtin_truncate(Interp *interp, SExpRef args); +SExpRef builtin_ceiling(Interp *interp, SExpRef args); +SExpRef builtin_round(Interp *interp, SExpRef args); +SExpRef builtin_sin(Interp *interp, SExpRef args); +SExpRef builtin_cos(Interp *interp, SExpRef args); +SExpRef builtin_tan(Interp *interp, SExpRef args); +SExpRef builtin_asin(Interp *interp, SExpRef args); +SExpRef builtin_acos(Interp *interp, SExpRef args); +SExpRef builtin_atan(Interp *interp, SExpRef args); +SExpRef builtin_ln(Interp *interp, SExpRef args); +SExpRef builtin_log10(Interp *interp, SExpRef args); +SExpRef builtin_log2(Interp *interp, SExpRef args); +SExpRef builtin_exp(Interp *interp, SExpRef args); +SExpRef builtin_min(Interp *interp, SExpRef args); +SExpRef builtin_max(Interp *interp, SExpRef args); +SExpRef builtin_equal(Interp *interp, SExpRef args); +SExpRef builtin_eq(Interp *interp, SExpRef args); +SExpRef builtin_format(Interp *interp, SExpRef args); +SExpRef builtin_concat(Interp *interp, SExpRef args); +SExpRef builtin_print(Interp *interp, SExpRef args); +SExpRef builtin_exit(Interp *interp, SExpRef args); +SExpRef builtin_error(Interp *interp, SExpRef args); +SExpRef builtin_list(Interp *interp, SExpRef args); +SExpRef builtin_car(Interp *interp, SExpRef args); +SExpRef builtin_cdr(Interp *interp, SExpRef args); +SExpRef builtin_cons(Interp *interp, SExpRef args); +SExpRef builtin_not(Interp *interp, SExpRef args); +SExpRef builtin_add(Interp *interp, SExpRef args); +SExpRef builtin_sub(Interp *interp, SExpRef args); +SExpRef builtin_mul(Interp *interp, SExpRef args); +SExpRef builtin_div(Interp *interp, SExpRef args); +SExpRef builtin_idiv(Interp *interp, SExpRef args); +SExpRef builtin_mod(Interp *interp, SExpRef args); +SExpRef builtin_num_equal(Interp *interp, SExpRef args); +SExpRef builtin_num_neq(Interp *interp, SExpRef args); +SExpRef builtin_gt(Interp *interp, SExpRef args); +SExpRef builtin_lt(Interp *interp, SExpRef args); +SExpRef builtin_ge(Interp *interp, SExpRef args); +SExpRef builtin_le(Interp *interp, SExpRef args); +SExpRef builtin_princ(Interp *interp, SExpRef args); +SExpRef builtin_gcstat(Interp *interp, SExpRef args); #endif diff --git a/src/interp.c b/src/interp.c index 615a922..983ba8e 100644 --- a/src/interp.c +++ b/src/interp.c @@ -20,6 +20,7 @@ VECTOR_IMPL(TopBinding); #define UNBOUND ((SExpRef){-1}) void Interp_init(Interp *self) { + self->gensym_cnt = 42; self->parser = malloc(sizeof(Parser)); Parser_init(self->parser); self->parser->ctx = self; @@ -61,24 +62,24 @@ void Interp_init(Interp *self) { self->reg = self->nil; Interp_add_primitive(self, "eval", primitive_eval); + Interp_add_primitive(self, "apply", primitive_apply); Interp_add_primitive(self, "if", primitive_if); Interp_add_primitive(self, "cond", primitive_cond); + Interp_add_primitive(self, "while", primitive_while); Interp_add_primitive(self, "progn", primitive_progn); - Interp_add_primitive(self, "setq", primitive_setq); + Interp_add_primitive(self, "and", primitive_and); + Interp_add_primitive(self, "or", primitive_or); Interp_add_primitive(self, "let", primitive_let); - Interp_add_primitive(self, "while", primitive_while); + Interp_add_primitive(self, "setq", primitive_setq); Interp_add_primitive(self, "lambda", primitive_lambda); Interp_add_primitive(self, "function", primitive_function); Interp_add_primitive(self, "defun", primitive_defun); Interp_add_primitive(self, "defvar", primitive_defvar); Interp_add_primitive(self, "defmacro", primitive_defmacro); Interp_add_primitive(self, "funcall", primitive_funcall); - Interp_add_primitive(self, "apply", primitive_apply); Interp_add_primitive(self, "quote", primitive_quote); Interp_add_primitive(self, "quasiquote", primitive_quasi); Interp_add_primitive(self, "macroexpand-1", primitive_macroexpand1); - Interp_add_primitive(self, "and", primitive_and); - Interp_add_primitive(self, "or", primitive_or); Interp_add_primitive(self, "return", primitive_return); Interp_add_primitive(self, "break", primitive_break); Interp_add_primitive(self, "continue", primitive_continue); @@ -86,13 +87,20 @@ void Interp_init(Interp *self) { Interp_add_primitive(self, "assert-error", primitive_assert_error); Interp_add_primitive(self, "load", primitive_load); - Interp_add_userfunc(self, "round", builtin_round); - Interp_add_userfunc(self, "acos", builtin_acos); - Interp_add_userfunc(self, "floor", builtin_floor); + Interp_add_userfunc(self, "symbol->string", builtin_symbol2string); + Interp_add_userfunc(self, "intern", builtin_intern); + Interp_add_userfunc(self, "gensym", builtin_gensym); + Interp_add_userfunc(self, "float", builtin_float); + Interp_add_userfunc(self, "tan", builtin_tan); Interp_add_userfunc(self, "asin", builtin_asin); + Interp_add_userfunc(self, "acos", builtin_acos); Interp_add_userfunc(self, "log2", builtin_log2); Interp_add_userfunc(self, "pow", builtin_pow); - Interp_add_userfunc(self, "float", builtin_float); + Interp_add_userfunc(self, "expt", builtin_pow); + Interp_add_userfunc(self, "exp", builtin_exp); + Interp_add_userfunc(self, "sqrt", builtin_sqrt); + Interp_add_userfunc(self, "cbrt", builtin_cbrt); + Interp_add_userfunc(self, "log10", builtin_log10); Interp_add_userfunc(self, "eq", builtin_eq); Interp_add_userfunc(self, "ln", builtin_ln); Interp_add_userfunc(self, "=", builtin_num_equal); @@ -102,13 +110,16 @@ void Interp_init(Interp *self) { Interp_add_userfunc(self, "format", builtin_format); Interp_add_userfunc(self, "truncate", builtin_truncate); Interp_add_userfunc(self, "mod", builtin_mod); - Interp_add_userfunc(self, "i/", builtin_idiv); + Interp_add_userfunc(self, "+", builtin_add); Interp_add_userfunc(self, "-", builtin_sub); - Interp_add_userfunc(self, "abs", builtin_abs); Interp_add_userfunc(self, "*", builtin_mul); - Interp_add_userfunc(self, "tan", builtin_tan); - Interp_add_userfunc(self, "exp", builtin_exp); - Interp_add_userfunc(self, "log10", builtin_log10); + Interp_add_userfunc(self, "/", builtin_div); + Interp_add_userfunc(self, "i/", builtin_idiv); + Interp_add_userfunc(self, ">", builtin_gt); + Interp_add_userfunc(self, "<", builtin_lt); + Interp_add_userfunc(self, ">=", builtin_ge); + Interp_add_userfunc(self, "<=", builtin_le); + Interp_add_userfunc(self, "abs", builtin_abs); Interp_add_userfunc(self, "list", builtin_list); Interp_add_userfunc(self, "car", builtin_car); Interp_add_userfunc(self, "sin", builtin_sin); @@ -116,22 +127,16 @@ void Interp_init(Interp *self) { Interp_add_userfunc(self, "exit", builtin_exit); Interp_add_userfunc(self, "not", builtin_not); Interp_add_userfunc(self, "cos", builtin_cos); - Interp_add_userfunc(self, "<=", builtin_le); Interp_add_userfunc(self, "princ", builtin_princ); - Interp_add_userfunc(self, ">", builtin_gt); - Interp_add_userfunc(self, "+", builtin_add); Interp_add_userfunc(self, "equal", builtin_equal); - Interp_add_userfunc(self, "/", builtin_div); Interp_add_userfunc(self, "atan", builtin_atan); Interp_add_userfunc(self, "cons", builtin_cons); Interp_add_userfunc(self, "cdr", builtin_cdr); Interp_add_userfunc(self, "ceiling", builtin_ceiling); + Interp_add_userfunc(self, "round", builtin_round); + Interp_add_userfunc(self, "floor", builtin_floor); Interp_add_userfunc(self, "min", builtin_min); Interp_add_userfunc(self, "error", builtin_error); - Interp_add_userfunc(self, ">=", builtin_ge); - Interp_add_userfunc(self, "<", builtin_lt); - Interp_add_userfunc(self, "sqrt", builtin_sqrt); - Interp_add_userfunc(self, "cbrt", builtin_cbrt); Interp_add_userfunc(self, "_gcstat", builtin_gcstat); diff --git a/src/interp.h b/src/interp.h index d4940e0..1989ab3 100644 --- a/src/interp.h +++ b/src/interp.h @@ -34,6 +34,7 @@ struct interp { SExpRef nil; char *errmsg_buf; Parser *parser; + int gensym_cnt; }; void Interp_init(Interp *self); diff --git a/tests/lambda.lisp b/tests/lambda.lisp index 18bbd8b..0a1ad1c 100644 --- a/tests/lambda.lisp +++ b/tests/lambda.lisp @@ -24,3 +24,10 @@ (assert (= 1 (funcall c))) (assert (= 2 (funcall c))) (assert (= 3 (funcall c)))) + +(let ((x 1) + (fn nil)) + (setq fn + (lambda (x) (setq x 2))) + (funcall fn x) + (assert (= x 1))) diff --git a/tests/symbol.lisp b/tests/symbol.lisp new file mode 100644 index 0000000..f771272 --- /dev/null +++ b/tests/symbol.lisp @@ -0,0 +1,4 @@ +(assert (eq 'a (intern "a"))) +(assert (eq (intern "ab") (intern (concat "a" "b")))) +(assert (equal "abc" (symbol->string 'abc))) +(assert (not (eq (gensym) (gensym)))) diff --git a/tests/test.lisp b/tests/test.lisp index 9b0f888..ca8195c 100644 --- a/tests/test.lisp +++ b/tests/test.lisp @@ -1,19 +1,21 @@ -(defmacro test-module (name) - `(progn - (princ (format "[TEST] %s\n" ,name)) - (load (format "%s.lisp" ,name)) - (princ (format "[PASS] %s\n" ,name)))) +(defmacro test-module (module) + (let ((name (symbol->string module))) + `(progn + (princ (format "[TEST] %s\n" ,name)) + (load (format "%s.lisp" ,name)) + (princ (format "[PASS] %s\n" ,name))))) -(test-module "math") -(test-module "eq") -(test-module "arithmetic") -(test-module "error") -(test-module "logic") -(test-module "tailcall") -(test-module "control-flow") -(test-module "lambda") -(test-module "comment") -(test-module "macro") -(test-module "let-binding") +(test-module math) +(test-module symbol) +(test-module eq) +(test-module arithmetic) +(test-module error) +(test-module logic) +(test-module tailcall) +(test-module control-flow) +(test-module lambda) +(test-module comment) +(test-module macro) +(test-module let-binding) (exit) -- cgit v1.0