ADD: if macro and comparison functions.

main
bog 2023-09-21 23:30:51 +02:00
parent 11a7f6a9da
commit 4d91c05aea
12 changed files with 155 additions and 1 deletions

35
examples/cmp.fk Normal file
View File

@ -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.))

5
examples/if.fk Normal file
View File

@ -0,0 +1,5 @@
($ a (if true 12 78))
($ b (if false 46 966))
(assert= 12 a)
(assert= 966 b)

View File

@ -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<int>(lhs->value()) OP std::get<int>(rhs->value()); \
} \
\
if (lhs->type() == TYPE_FLOAT) \
{ \
res = std::get<float>(lhs->value()) OP std::get<float>(rhs->value()); \
} \
\
return std::make_shared<Constant>(TYPE_BOOL, res, loc)
namespace fkstd
{
STDRET assert_eq(Loc loc, STDARGS args)
@ -147,4 +165,34 @@ namespace fkstd
return std::make_shared<Constant>(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(!=);
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -62,4 +62,23 @@ namespace fkstd
compiler.sym()->leave_scope();
}
void if_macro(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> 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());
}
}

View File

@ -15,6 +15,10 @@ namespace fkstd
void block(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program);
void if_macro(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program);
}
#endif

View File

@ -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))
{

View File

@ -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());

View File

@ -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<Constant> get_const(addr_t addr) const;

View File

@ -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<bool>(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<std::shared_ptr<Program>>(p->value());

View File

@ -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"