diff --git a/examples/cmp.fk b/examples/cmp.fk new file mode 100644 index 0000000..a7129a6 --- /dev/null +++ b/examples/cmp.fk @@ -0,0 +1,35 @@ +(assert= true (> 5 2)) +(assert= false (> 5 5)) +(assert= false (> 5 8)) +(assert= true (>= 5 2)) +(assert= true (>= 5 5)) +(assert= false (>= 5 8)) +(assert= true (< 1 2)) +(assert= false (< 3 3)) +(assert= false (< 5 2)) +(assert= true (<= 1 2)) +(assert= true (<= 3 3)) +(assert= false (<= 5 2)) + +(assert= true (> 5. 2.)) +(assert= false (> 5. 5.)) +(assert= false (> 5. 8.)) +(assert= true (>= 5. 2.)) +(assert= true (>= 5. 5.)) +(assert= false (>= 5. 8.)) +(assert= true (< 1. 2.)) +(assert= false (< 3. 3.)) +(assert= false (< 5. 2.)) +(assert= true (<= 1. 2.)) +(assert= true (<= 3. 3.)) +(assert= false (<= 5. 2.)) + +(assert= true (= 12 12)) +(assert= false (= 1 3)) +(assert= false (<> 16 16)) +(assert= true (<> 19 7)) + +(assert= true (= 12. 12.)) +(assert= false (= 1. 3.)) +(assert= false (<> 1.6 1.6)) +(assert= true (<> 19. 7.)) \ No newline at end of file diff --git a/examples/if.fk b/examples/if.fk new file mode 100644 index 0000000..e993c43 --- /dev/null +++ b/examples/if.fk @@ -0,0 +1,5 @@ +($ a (if true 12 78)) +($ b (if false 46 966)) + +(assert= 12 a) +(assert= 966 b) \ No newline at end of file diff --git a/libstd/fun.cpp b/libstd/fun.cpp index 8401339..07ab202 100644 --- a/libstd/fun.cpp +++ b/libstd/fun.cpp @@ -1,5 +1,23 @@ #include "fun.hpp" +#define NUM_BINOP(OP)\ + auto lhs = args[0]; \ + auto rhs = args[1]; \ + bool res = false; \ + \ + if (lhs->type() == TYPE_INT) \ + { \ + res = std::get(lhs->value()) OP std::get(rhs->value()); \ + } \ + \ + if (lhs->type() == TYPE_FLOAT) \ + { \ + res = std::get(lhs->value()) OP std::get(rhs->value()); \ + } \ + \ + return std::make_shared(TYPE_BOOL, res, loc) + + namespace fkstd { STDRET assert_eq(Loc loc, STDARGS args) @@ -147,4 +165,34 @@ namespace fkstd return std::make_shared(TYPE_INT, result, loc); } + + STDRET lt(Loc loc, STDARGS args) + { + NUM_BINOP(<); + } + + STDRET le(Loc loc, STDARGS args) + { + NUM_BINOP(<=); + } + + STDRET gt(Loc loc, STDARGS args) + { + NUM_BINOP(>); + } + + STDRET ge(Loc loc, STDARGS args) + { + NUM_BINOP(>=); + } + + STDRET eq(Loc loc, STDARGS args) + { + NUM_BINOP(==); + } + + STDRET ne(Loc loc, STDARGS args) + { + NUM_BINOP(!=); + } } diff --git a/libstd/fun.hpp b/libstd/fun.hpp index 642d776..8d3ecca 100644 --- a/libstd/fun.hpp +++ b/libstd/fun.hpp @@ -13,6 +13,13 @@ namespace fkstd STDRET div_int(Loc loc, STDARGS args); STDRET mod_int(Loc loc, STDARGS args); STDRET pow_int(Loc loc, STDARGS args); + + STDRET lt(Loc loc, STDARGS args); + STDRET le(Loc loc, STDARGS args); + STDRET gt(Loc loc, STDARGS args); + STDRET ge(Loc loc, STDARGS args); + STDRET eq(Loc loc, STDARGS args); + STDRET ne(Loc loc, STDARGS args); } #endif diff --git a/libstd/lib.cpp b/libstd/lib.cpp index 6ad98af..ae5ca5d 100644 --- a/libstd/lib.cpp +++ b/libstd/lib.cpp @@ -12,8 +12,15 @@ extern "C" void lib(Module& mod) mod.register_function("/", fkstd::div_int); mod.register_function("%", fkstd::mod_int); mod.register_function("^", fkstd::pow_int); + mod.register_function("<", fkstd::lt); + mod.register_function("<=", fkstd::le); + mod.register_function(">", fkstd::gt); + mod.register_function(">=", fkstd::ge); + mod.register_function("=", fkstd::eq); + mod.register_function("<>", fkstd::ne); mod.register_macro("assert-static-fail", fkstd::assert_static_fail); mod.register_macro(":", fkstd::block); mod.register_macro("$", fkstd::decl); + mod.register_macro("if", fkstd::if_macro); } diff --git a/libstd/macro.cpp b/libstd/macro.cpp index 223aa57..1d22d90 100644 --- a/libstd/macro.cpp +++ b/libstd/macro.cpp @@ -62,4 +62,23 @@ namespace fkstd compiler.sym()->leave_scope(); } + + void if_macro(Compiler& compiler, + std::shared_ptr node, + std::shared_ptr program) + { + auto if_expr = node->child(1); + auto then_expr = node->child(2); + auto else_expr = node->child(3); + + compiler.compile_prog(if_expr, program); + size_t to_else = program->add(OP_BNE, 0 /*else*/); + + compiler.compile_prog(then_expr, program); + size_t to_end = program->add(OP_BR, 0 /* end */); + + program->set_param(to_else, program->size()); + compiler.compile_prog(else_expr, program); + program->set_param(to_end, program->size()); + } } diff --git a/libstd/macro.hpp b/libstd/macro.hpp index 9edb4da..0076488 100644 --- a/libstd/macro.hpp +++ b/libstd/macro.hpp @@ -15,6 +15,10 @@ namespace fkstd void block(Compiler& compiler, std::shared_ptr node, std::shared_ptr program); + + void if_macro(Compiler& compiler, + std::shared_ptr node, + std::shared_ptr program); } #endif diff --git a/src/Compiler.cpp b/src/Compiler.cpp index 023e20d..fdd5a24 100644 --- a/src/Compiler.cpp +++ b/src/Compiler.cpp @@ -83,6 +83,7 @@ namespace fk case NODE_CALL: { std::string ident = node->child(0)->repr(); + if (auto itr=m_macros.find(ident); itr != std::end(m_macros)) { diff --git a/src/Program.cpp b/src/Program.cpp index d8b5c5b..4824b14 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -16,6 +16,12 @@ namespace fk return m_instrs.size() - 1; } + void Program::set_param(size_t index, addr_t param) + { + assert(index < m_instrs.size()); + m_instrs[index].param = param; + } + Instr Program::instr(size_t index) const { assert(index < size()); diff --git a/src/Program.hpp b/src/Program.hpp index e1b7cce..4427fdc 100644 --- a/src/Program.hpp +++ b/src/Program.hpp @@ -24,6 +24,8 @@ namespace fk size_t const_size() const { return m_consts.size(); } size_t add(Opcode opcode, addr_t param=NO_PARAM); + void set_param(size_t index, addr_t param); + Instr instr(size_t index) const; std::shared_ptr get_const(addr_t addr) const; diff --git a/src/VM.cpp b/src/VM.cpp index 113d653..e4f3868 100644 --- a/src/VM.cpp +++ b/src/VM.cpp @@ -27,6 +27,25 @@ namespace fk switch (instr.opcode) { + case OP_BR: { + m_pc = instr.param; + } break; + + case OP_BNE: { + auto cond_val = frame().program->get_const(pop()); + bool cond = std::get(cond_val->value()); + + if (!cond) + { + m_pc = instr.param; + } + else + { + m_pc++; + } + + } break; + case OP_MAKE_FUNCTION: { auto p = frame().program->get_const(pop()); auto prog = std::get>(p->value()); diff --git a/src/opcodes.hpp b/src/opcodes.hpp index 4fca9fd..9513dcb 100644 --- a/src/opcodes.hpp +++ b/src/opcodes.hpp @@ -3,7 +3,8 @@ #define OPCODES(G) G(OP_LOAD_CONST), G(OP_POP), G(OP_CALL_NATIVE), \ 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_MAKE_FUNCTION), G(OP_CALL_REF), G(OP_RET), G(OP_BNE), \ + G(OP_BR) #include "commons.hpp"