Browse Source

fix lambda env, add fib, add more bi op

Signed-off-by: Rain Mark <rain.by.zhou@gmail.com>
main
Rain Mark 4 years ago
parent
commit
09320b781d
  1. 19
      example/bi.lisp
  2. 5
      example/fib.lisp
  3. 84
      src/core.h
  4. 6
      src/lispoo.h

19
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))
)

5
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))
)

84
src/core.h

@ -4,23 +4,46 @@
namespace lispoo {
inline std::shared_ptr<Expr> sum(const std::shared_ptr<Expr>& a,
const std::shared_ptr<Expr>& b) {
if (a->type() == Type::Float && b->type() == Type::Float) {
return std::make_shared<Float>(get_value<Float>(a) + get_value<Float>(b));
#define BI_OP(fn, op) \
inline std::shared_ptr<Expr> fn(const std::shared_ptr<Expr>& a, \
const std::shared_ptr<Expr>& b) { \
if (a->type() == Type::Float && b->type() == Type::Float) { \
return std::make_shared<Float>(get_value<Float>(a) \
op get_value<Float>(b)); \
} \
if (a->type() == Type::Integer && b->type() == Type::Integer) { \
return std::make_shared<Integer>(get_value<Integer>(a) \
op get_value<Integer>(b)); \
} \
if (a->type() == Type::Float) { \
return std::make_shared<Float>(get_value<Float>(a) \
op get_value<Integer>(b)); \
} \
if (b->type() == Type::Float) { \
return std::make_shared<Float>(get_value<Integer>(a) \
op get_value<Float>(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<Integer>(get_value<Integer>(a) +
get_value<Integer>(b));
}
if (a->type() == Type::Float) {
return std::make_shared<Float>(get_value<Float>(a) + get_value<Integer>(b));
}
if (b->type() == Type::Float) {
return std::make_shared<Float>(get_value<Integer>(a) + get_value<Float>(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<Expr> message(const std::shared_ptr<Expr>& 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<List>(expr);
auto symbols = get_value<List>(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<List>(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<List>(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<List>(expr);
for (auto i = 1; i < value.size(); ++i) {

6
src/lispoo.h

@ -143,7 +143,8 @@ inline bool is_symbol(const std::shared_ptr<Expr>& expr) {
}
inline bool is_true(const std::shared_ptr<Expr>& expr) {
if (!is_number(expr)) {
return false;
oops("is_true() failed, not number type: " +
std::to_string((int)expr->type()));
}
if (is_type<Type::Integer>(expr)) {
return get_value<Integer>(expr);
@ -192,7 +193,7 @@ inline std::shared_ptr<Expr> parse_atom(const std::vector<std::string>& 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<Expr> eval(const std::shared_ptr<Expr>& expr,
const std::shared_ptr<Env>& env) {
if (!expr) {
oops("syntax error");
return nil;
}
if (is_number(expr)) {
return expr;

Loading…
Cancel
Save