diff --git a/examples/bool.fk b/examples/bool.fk new file mode 100644 index 0000000..4f8a5d3 --- /dev/null +++ b/examples/bool.fk @@ -0,0 +1,18 @@ +(assert= true true) +(assert= false false) + +(assert= false (not true)) +(assert= true (not false)) + +(assert= true (and true true)) +(assert= false (and true false)) +(assert= false (and false true)) +(assert= false (and false false)) + +(assert= true (or true true)) +(assert= true (or true false)) +(assert= true (or false true)) +(assert= false (or false false)) + +(and false (: (assert= 0 1) false)) +(or true (: (assert= 0 1) false)) \ No newline at end of file diff --git a/libstd/fun.cpp b/libstd/fun.cpp index 756fe6f..695c10d 100644 --- a/libstd/fun.cpp +++ b/libstd/fun.cpp @@ -196,7 +196,13 @@ namespace fkstd NUM_BINOP(!=); } - STDRET array_ref(Loc loc, Module& mod, STDARGS args) + STDRET bool_not(Loc loc, Module&, STDARGS args) + { + bool val = std::get(args[0]->value()); + return std::make_shared(TYPE_BOOL, !val, loc); + } + + STDRET array_ref(Loc, Module& mod, STDARGS args) { auto ref_val = args[0]->value(); size_t ref = std::get(ref_val); diff --git a/libstd/fun.hpp b/libstd/fun.hpp index 433f1d1..d01de93 100644 --- a/libstd/fun.hpp +++ b/libstd/fun.hpp @@ -21,6 +21,7 @@ namespace fkstd STDRET eq(Loc loc, Module& mod, STDARGS args); STDRET ne(Loc loc, Module& mod, STDARGS args); + STDRET bool_not(Loc loc, Module& mod, STDARGS args); STDRET array_ref(Loc loc, Module& mod, STDARGS args); } diff --git a/libstd/lib.cpp b/libstd/lib.cpp index 7c91963..68a0fdc 100644 --- a/libstd/lib.cpp +++ b/libstd/lib.cpp @@ -18,10 +18,14 @@ extern "C" void lib(Module& mod) mod.register_function(">=", fkstd::ge); mod.register_function("=", fkstd::eq); mod.register_function("<>", fkstd::ne); + + mod.register_function("not", fkstd::bool_not); mod.register_function("ref", fkstd::array_ref); mod.register_macro("!", fkstd::set_addr); mod.register_macro("assert-static-fail", fkstd::assert_static_fail); mod.register_macro(":", fkstd::block); mod.register_macro("if", fkstd::if_macro); + mod.register_macro("and", fkstd::and_macro); + mod.register_macro("or", fkstd::or_macro); } diff --git a/libstd/macro.cpp b/libstd/macro.cpp index 671296a..1b71ee8 100644 --- a/libstd/macro.cpp +++ b/libstd/macro.cpp @@ -103,4 +103,67 @@ namespace fkstd compiler.compile_prog(else_expr, program); program->set_param(to_end, program->size()); } + + void and_macro(Compiler& compiler, + std::shared_ptr node, + std::shared_ptr program) + { + std::vector to_false; + + for (size_t i=1; isize(); i++) + { + compiler.compile_prog(node->child(i), program); + size_t addr = program->add(OP_BNE, 0 /* to end*/); + to_false.push_back(addr); + } + + program->load_const(std::make_shared(TYPE_BOOL, + true, + node->loc())); + + size_t out_addr = program->add(OP_BR, 0 /* to end*/); + + for (auto addr: to_false) + { + program->set_param(addr, program->size()); + } + + program->load_const(std::make_shared(TYPE_BOOL, + false, + node->loc())); + + program->set_param(out_addr, program->size()); + } + + void or_macro(Compiler& compiler, + std::shared_ptr node, + std::shared_ptr program) + { + std::vector to_true; + + for (size_t i=1; isize(); i++) + { + compiler.compile_prog(node->child(i), program); + program->add(OP_NOT); + size_t addr = program->add(OP_BNE, 0 /* to end*/); + to_true.push_back(addr); + } + + program->load_const(std::make_shared(TYPE_BOOL, + false, + node->loc())); + + size_t out_addr = program->add(OP_BR, 0 /* to end*/); + + for (auto addr: to_true) + { + program->set_param(addr, program->size()); + } + + program->load_const(std::make_shared(TYPE_BOOL, + true, + node->loc())); + + program->set_param(out_addr, program->size()); + } } diff --git a/libstd/macro.hpp b/libstd/macro.hpp index 79b27a8..3a29762 100644 --- a/libstd/macro.hpp +++ b/libstd/macro.hpp @@ -23,6 +23,14 @@ namespace fkstd void if_macro(Compiler& compiler, std::shared_ptr node, std::shared_ptr program); + + void and_macro(Compiler& compiler, + std::shared_ptr node, + std::shared_ptr program); + + void or_macro(Compiler& compiler, + std::shared_ptr node, + std::shared_ptr program); } #endif diff --git a/src/Compiler.cpp b/src/Compiler.cpp index 55baf2d..a6bcefb 100644 --- a/src/Compiler.cpp +++ b/src/Compiler.cpp @@ -198,6 +198,7 @@ namespace fk { auto macro = itr->second; macro->call(*this, node, prog); + break; } else if (node->child(0)->type() == NODE_NS && has_macro(node->child(0)->child(1)->repr())) diff --git a/src/VM.cpp b/src/VM.cpp index 29dc1fe..8afeb5a 100644 --- a/src/VM.cpp +++ b/src/VM.cpp @@ -212,6 +212,16 @@ namespace fk m_pc++; } break; + case OP_NOT: { + auto c_val = frame().program->get_const(pop()); + bool val = std::get(c_val->value()); + push(frame(). + program->add(std::make_shared(TYPE_BOOL, + !val, + c_val->loc()))); + m_pc++; + } break; + case OP_BR: { m_pc = instr.param; } break; diff --git a/src/opcodes.hpp b/src/opcodes.hpp index 30238f0..a746a15 100644 --- a/src/opcodes.hpp +++ b/src/opcodes.hpp @@ -5,7 +5,8 @@ G(OP_LOAD_GLOBAL), G(OP_LOAD_LOCAL), G(OP_STORE_LOCAL), \ G(OP_MAKE_FUNCTION), G(OP_CALL_REF), G(OP_RET), G(OP_BNE), \ G(OP_BR), G(OP_LOAD_CLOSURE), G(OP_STORE_CLOSURE), \ - G(OP_LOAD_MOD), G(OP_IMPORT), G(OP_IMPORT_SYS), G(OP_MAKE_ARRAY) + G(OP_LOAD_MOD), G(OP_IMPORT), G(OP_IMPORT_SYS), G(OP_MAKE_ARRAY), \ + G(OP_NOT) #include "commons.hpp"