From 09320b781dc690ebc71c3408599e1afcc16c9108 Mon Sep 17 00:00:00 2001 From: Rain Mark Date: Fri, 4 Mar 2022 22:47:16 +0800 Subject: [PATCH] fix lambda env, add fib, add more bi op Signed-off-by: Rain Mark --- example/bi.lisp | 19 +++++++++++ example/fib.lisp | 5 +++ src/core.h | 84 +++++++++++++++++++++++++++++++++++------------- src/lispoo.h | 6 ++-- 4 files changed, 89 insertions(+), 25 deletions(-) create mode 100644 example/bi.lisp create mode 100644 example/fib.lisp diff --git a/example/bi.lisp b/example/bi.lisp new file mode 100644 index 0000000..a7d3e79 --- /dev/null +++ b/example/bi.lisp @@ -0,0 +1,19 @@ +(progn + (message (+ 1 1)) + (message (- 1 1)) + (message (* 2 2)) + (message (/ 8 2)) + + (message (> 8 2)) + (message (< 8 2)) + (message (<= 2 2)) + (message (>= 2 2)) + (message (== 2 2)) + + (message (&& 1 0)) + (message (|| 1 0)) + (message (&& 1 1)) + (message (|| 1 1)) + (message (&& 0 0)) + (message (|| 0 0)) + ) diff --git a/example/fib.lisp b/example/fib.lisp new file mode 100644 index 0000000..25aac78 --- /dev/null +++ b/example/fib.lisp @@ -0,0 +1,5 @@ +(progn + (define fib (lambda (n) (if (<= n 2) 1 (+ (fib (- n 1)) (fib (- n 2)))))) + (message (fib 4)) + (message (fib 8)) + ) diff --git a/src/core.h b/src/core.h index a3e2e63..234c003 100644 --- a/src/core.h +++ b/src/core.h @@ -4,23 +4,46 @@ namespace lispoo { -inline std::shared_ptr sum(const std::shared_ptr& a, - const std::shared_ptr& b) { - if (a->type() == Type::Float && b->type() == Type::Float) { - return std::make_shared(get_value(a) + get_value(b)); +#define BI_OP(fn, op) \ + inline std::shared_ptr fn(const std::shared_ptr& a, \ + const std::shared_ptr& b) { \ + if (a->type() == Type::Float && b->type() == Type::Float) { \ + return std::make_shared(get_value(a) \ + op get_value(b)); \ + } \ + if (a->type() == Type::Integer && b->type() == Type::Integer) { \ + return std::make_shared(get_value(a) \ + op get_value(b)); \ + } \ + if (a->type() == Type::Float) { \ + return std::make_shared(get_value(a) \ + op get_value(b)); \ + } \ + if (b->type() == Type::Float) { \ + return std::make_shared(get_value(a) \ + op get_value(b)); \ + } \ + oops(std::string(#op) + \ + " failed, type: " + std::to_string((int)a->type()) + " " + \ + std::to_string((int)b->type())); \ + return nil; \ } - if (a->type() == Type::Integer && b->type() == Type::Integer) { - return std::make_shared(get_value(a) + - get_value(b)); - } - if (a->type() == Type::Float) { - return std::make_shared(get_value(a) + get_value(b)); - } - if (b->type() == Type::Float) { - return std::make_shared(get_value(a) + get_value(b)); - } - return nil; -} + +BI_OP(sum, +) +BI_OP(sub, -) +BI_OP(mul, *) +BI_OP(div, /) + +BI_OP(eq, ==) +BI_OP(gt, >) +BI_OP(lt, <) +BI_OP(gte, >=) +BI_OP(lte, <=) + +BI_OP(_and, &&) +BI_OP(_or, ||) + +#undef BI_OP inline std::shared_ptr message(const std::shared_ptr& expr) { auto type = expr->type(); @@ -118,7 +141,7 @@ inline void init() { putenv("lambda", [](auto expr, auto env) { // (lambda (args) (body)) assert_len(expr, 3); - auto lambda = [expr, parent = env](auto args, auto) { + auto lambda = [expr](auto args, auto parent) { auto value = get_value(expr); auto symbols = get_value(value[1]); // arguments bind @@ -138,11 +161,28 @@ inline void init() { }); // normal builtin function - putenv("+", [](auto expr, auto env) { - assert_len(expr, 3); - auto value = get_value(expr); - return sum(eval(value[1], env), eval(value[2], env)); - }); +#define PUT_BI_OP(fn, op) \ + putenv(#op, [](auto expr, auto env) { \ + assert_len(expr, 3); \ + auto value = get_value(expr); \ + return fn(eval(value[1], env), eval(value[2], env)); \ + }) + PUT_BI_OP(sum, +); + PUT_BI_OP(sub, -); + PUT_BI_OP(mul, *); + PUT_BI_OP(div, /); + + PUT_BI_OP(eq, ==); + PUT_BI_OP(gt, >); + PUT_BI_OP(lt, <); + PUT_BI_OP(gte, >=); + PUT_BI_OP(lte, <=); + + PUT_BI_OP(_and, &&); + PUT_BI_OP(_or, ||); + +#undef PUT_BI_OP + putenv("message", [](auto expr, auto env) { auto value = get_value(expr); for (auto i = 1; i < value.size(); ++i) { diff --git a/src/lispoo.h b/src/lispoo.h index 7069b3e..0f234e5 100644 --- a/src/lispoo.h +++ b/src/lispoo.h @@ -143,7 +143,8 @@ inline bool is_symbol(const std::shared_ptr& expr) { } inline bool is_true(const std::shared_ptr& expr) { if (!is_number(expr)) { - return false; + oops("is_true() failed, not number type: " + + std::to_string((int)expr->type())); } if (is_type(expr)) { return get_value(expr); @@ -192,7 +193,7 @@ inline std::shared_ptr parse_atom(const std::vector& tokens, long& cursor) { auto token = tokens[cursor]; auto type = Type::Symbol; - if (std::isdigit(token[0]) || token[0] == '-') { + if (std::isdigit(token[0]) || (token[0] == '-' && token.size() > 1)) { type = Type::Integer; for (auto i = 1; i < token.size(); ++i) { if (token[i] == '.') { @@ -239,7 +240,6 @@ inline std::shared_ptr eval(const std::shared_ptr& expr, const std::shared_ptr& env) { if (!expr) { oops("syntax error"); - return nil; } if (is_number(expr)) { return expr;