diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/builtins.c | 76 | ||||
| -rw-r--r-- | src/builtins.h | 20 | ||||
| -rw-r--r-- | src/interp.c | 61 | ||||
| -rw-r--r-- | src/prelude.c | 2 | ||||
| -rw-r--r-- | src/prelude.lisp | 1 |
5 files changed, 137 insertions, 23 deletions
diff --git a/src/builtins.c b/src/builtins.c index fbf5855..b8040ef 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -4,6 +4,78 @@ #include <algds/str.h> #include <stdint.h> #include <float.h> +#include <math.h> + +SExpRef builtin_float(Interp *interp, SExpRef args) { + if (LENGTH(args) != 1) return new_error(interp, "float: expect 1 arg.\n"); + SExpRef x = CAR(args); + if (VALTYPE(x) != kIntegerSExp) return new_error(interp, "float: wrong type.\n"); + return new_real(interp, REF(x)->integer); +} + +SExpRef builtin_abs(Interp *interp, SExpRef args) { + if (LENGTH(args) != 1) return new_error(interp, "abs: expect 1 arg.\n"); + SExpRef x = CAR(args); + if (VALTYPE(x) != kIntegerSExp && VALTYPE(x) != kRealSExp) { + return new_error(interp, "abs: wrong type.\n"); + } + if (VALTYPE(x) == kIntegerSExp) { + int64_t val = REF(x)->integer; + if (val < 0) val = -val; + return new_integer(interp, val); + } else { + double val = REF(x)->real; + if (val < 0) val = -val; + return new_real(interp, val); + } +} + +static double real_value(Interp *interp, SExpRef x) { + if (VALTYPE(x) == kIntegerSExp) { + return REF(x)->integer; + } else { + return REF(x)->real; + } +} + +SExpRef builtin_pow(Interp *interp, SExpRef args) { + if (LENGTH(args) != 2) return new_error(interp, "pow: expect 2 args.\n"); + SExpRef x = CAR(args), y = CADR(args); + if (VALTYPE(x) != kIntegerSExp && VALTYPE(x) != kRealSExp) { + return new_error(interp, "pow: wrong type.\n"); + } + if (VALTYPE(y) != kIntegerSExp && VALTYPE(y) != kRealSExp) { + return new_error(interp, "pow: wrong type.\n"); + } + return new_real(interp, pow(real_value(interp, x), real_value(interp, y))); +} + +#define GEN_MATH_FUNC(name, cfunc) \ +SExpRef builtin_##name(Interp *interp, SExpRef args) { \ + if (LENGTH(args) != 1) return new_error(interp, #name": expect 1 args.\n"); \ + SExpRef x = CAR(args); \ + if (VALTYPE(x) != kIntegerSExp && VALTYPE(x) != kRealSExp) { \ + return new_error(interp, #name": wrong type.\n"); \ + } \ + return new_real(interp, cfunc(real_value(interp, x))); \ +} + +GEN_MATH_FUNC(sqrt, sqrt); +GEN_MATH_FUNC(cbrt, cbrt); +GEN_MATH_FUNC(floor, floor); +GEN_MATH_FUNC(truncate, trunc); +GEN_MATH_FUNC(ceiling, ceil); +GEN_MATH_FUNC(round, round); +GEN_MATH_FUNC(sin, sin); +GEN_MATH_FUNC(cos, cos); +GEN_MATH_FUNC(tan, tan); +GEN_MATH_FUNC(asin, asin); +GEN_MATH_FUNC(acos, acos); +GEN_MATH_FUNC(atan, atan); +GEN_MATH_FUNC(ln, log); +GEN_MATH_FUNC(log10, log10); +GEN_MATH_FUNC(log2, log2); +GEN_MATH_FUNC(exp, exp); SExpRef builtin_min(Interp *interp, SExpRef args) { if (LENGTH(args) < 1) return new_error(interp, "min: wrong arg number.\n"); @@ -294,9 +366,9 @@ static SExp raw_add(SExp a, SExp b) { static SExp raw_mul(SExp a, SExp b) { if (a.type == kRealSExp || b.type == kRealSExp) { double result = 1.0; - if (a.type == kRealSExp) result += a.real; + if (a.type == kRealSExp) result *= a.real; else result *= a.integer; - if (b.type == kRealSExp) result += b.real; + if (b.type == kRealSExp) result *= b.real; else result *= b.integer; return (SExp){ .type = kRealSExp, .real = result }; } else { diff --git a/src/builtins.h b/src/builtins.h index abcd7a0..3c54bdc 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -3,6 +3,26 @@ #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); diff --git a/src/interp.c b/src/interp.c index 8813d37..a8c9ad7 100644 --- a/src/interp.c +++ b/src/interp.c @@ -86,33 +86,54 @@ 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, "min", builtin_min); - Interp_add_userfunc(self, "max", builtin_max); + 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, "asin", builtin_asin); + 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, "eq", builtin_eq); - Interp_add_userfunc(self, "equal", builtin_equal); - Interp_add_userfunc(self, "format", builtin_format); + Interp_add_userfunc(self, "ln", builtin_ln); + Interp_add_userfunc(self, "=", builtin_num_equal); + Interp_add_userfunc(self, "/=", builtin_num_neq); Interp_add_userfunc(self, "concat", builtin_concat); - Interp_add_userfunc(self, "error", builtin_error); Interp_add_userfunc(self, "print", builtin_print); - Interp_add_userfunc(self, "princ", builtin_princ); - Interp_add_userfunc(self, "car", builtin_car); - Interp_add_userfunc(self, "list", builtin_list); - Interp_add_userfunc(self, "cdr", builtin_cdr); - Interp_add_userfunc(self, "cons", builtin_cons); - Interp_add_userfunc(self, "+", builtin_add); + 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_sub); + Interp_add_userfunc(self, "abs", builtin_abs); Interp_add_userfunc(self, "*", builtin_mul); - Interp_add_userfunc(self, "/", builtin_div); - Interp_add_userfunc(self, "i/", builtin_idiv); - Interp_add_userfunc(self, "mod", builtin_mod); - Interp_add_userfunc(self, "=", builtin_num_equal); - Interp_add_userfunc(self, "/=", builtin_num_neq); - Interp_add_userfunc(self, "<", builtin_lt); + 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, "list", builtin_list); + Interp_add_userfunc(self, "car", builtin_car); + Interp_add_userfunc(self, "sin", builtin_sin); + Interp_add_userfunc(self, "max", builtin_max); + 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, "min", builtin_min); + Interp_add_userfunc(self, "error", builtin_error); Interp_add_userfunc(self, ">=", builtin_ge); - Interp_add_userfunc(self, "<=", builtin_le); - Interp_add_userfunc(self, "not", builtin_not); - Interp_add_userfunc(self, "exit", builtin_exit); + 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); SExpRef ret = Interp_eval_string(self, bamboo_lisp_prelude); diff --git a/src/prelude.c b/src/prelude.c index 3d1a971..ca9109d 100644 --- a/src/prelude.c +++ b/src/prelude.c @@ -1,6 +1,6 @@ #include "prelude.h" -const char *bamboo_lisp_prelude = "(defvar nil \'())\n\n(defvar pi 3.1415926)\n\n(defmacro incq (i)\n `(setq ,i (+ ,i 1)))\n\n(defmacro decq (i)\n `(setq ,i (- ,i 1)))\n\n(defun zerop (x) (= x 0))\n(defun plusp (x) (> x 0))\n(defun minusp (x) (< x 0))\n\n(defmacro when (pred . body)\n `(if ,pred\n (progn ,@body)\n nil))\n\n(defmacro unless (pred . body)\n `(if ,pred\n nil\n (progn ,@body)))\n"; +const char *bamboo_lisp_prelude = "(defvar nil \'())\n\n(defvar pi 3.1415926)\n(defvar e 2.718281828)\n\n(defmacro incq (i)\n `(setq ,i (+ ,i 1)))\n\n(defmacro decq (i)\n `(setq ,i (- ,i 1)))\n\n(defun zerop (x) (= x 0))\n(defun plusp (x) (> x 0))\n(defun minusp (x) (< x 0))\n\n(defmacro when (pred . body)\n `(if ,pred\n (progn ,@body)\n nil))\n\n(defmacro unless (pred . body)\n `(if ,pred\n nil\n (progn ,@body)))\n"; diff --git a/src/prelude.lisp b/src/prelude.lisp index df85a9b..7e9992b 100644 --- a/src/prelude.lisp +++ b/src/prelude.lisp @@ -1,6 +1,7 @@ (defvar nil '()) (defvar pi 3.1415926) +(defvar e 2.718281828) (defmacro incq (i) `(setq ,i (+ ,i 1))) |
