aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--src/builtins.c22
-rw-r--r--src/builtins.h98
-rw-r--r--src/interp.c49
-rw-r--r--src/interp.h1
-rw-r--r--tests/lambda.lisp7
-rw-r--r--tests/symbol.lisp4
-rw-r--r--tests/test.lisp34
8 files changed, 132 insertions, 86 deletions
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 <float.h>
#include <math.h>
+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)