Compare commits

...

2 Commits

Author SHA1 Message Date
bog 4d91c05aea ADD: if macro and comparison functions. 2023-09-21 23:30:51 +02:00
bog 11a7f6a9da ADD: int arithmetic. 2023-09-21 22:26:13 +02:00
17 changed files with 324 additions and 18 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)

25
examples/int.fk Normal file
View File

@ -0,0 +1,25 @@
(assert= 3 (+ 3))
(assert= 6 (+ 1 2 3))
(assert= 0 (+))
(assert= -3 (- 3))
(assert= 4 (- 7 3))
(assert= -4 (- 1 2 3))
(assert= 0 (-))
(assert= 1 (*))
(assert= 2 (* 2))
(assert= 14 (* 2 7))
(assert= 1 (/))
(assert= 0 (/ 5))
(assert= 2 (/ 5 2))
(assert= 6 (/ 18 3))
(assert= 1 (%))
(assert= 3 (% 7 4))
(assert= 1 (^))
(assert= 128 (^ 2 7))
(assert= 8 (* 2 (+ 1 3)))

View File

@ -1,6 +1,7 @@
#ifndef fkstd_COMMONS_HPP #ifndef fkstd_COMMONS_HPP
#define fkstd_COMMONS_HPP #define fkstd_COMMONS_HPP
#include <cmath>
#include "../src/Module.hpp" #include "../src/Module.hpp"
#include "../src/Constant.hpp" #include "../src/Constant.hpp"

View File

@ -1,8 +1,26 @@
#include "fun.hpp" #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 namespace fkstd
{ {
STDRET assert_eq(STDARGS args) STDRET assert_eq(Loc loc, STDARGS args)
{ {
auto oracle = args[0]; auto oracle = args[0];
auto expr = args[1]; auto expr = args[1];
@ -16,13 +34,13 @@ namespace fkstd
<< expr->string() << expr->string()
<< "'"; << "'";
oracle->loc().error<assert_error>(LOG_ERROR, ss.str()); loc.error<assert_error>(LOG_ERROR, ss.str());
} }
return std::make_shared<Constant>(TYPE_BOOL, true, oracle->loc()); return std::make_shared<Constant>(TYPE_BOOL, true, loc);
} }
STDRET println(STDARGS args) STDRET println(Loc loc, STDARGS args)
{ {
std::string sep; std::string sep;
@ -32,8 +50,6 @@ namespace fkstd
sep = " "; sep = " ";
} }
Loc loc {"???"};
if (args.size() > 0) if (args.size() > 0)
{ {
loc = args.front()->loc(); loc = args.front()->loc();
@ -43,4 +59,140 @@ namespace fkstd
return std::make_shared<Constant>(TYPE_INT, 0, loc); return std::make_shared<Constant>(TYPE_INT, 0, loc);
} }
STDRET add_int(Loc loc, STDARGS args)
{
int result = 0;
for (auto arg: args)
{
result += std::get<int>(arg->value());
}
return std::make_shared<Constant>(TYPE_INT, result, loc);
}
STDRET sub_int(Loc loc, STDARGS args)
{
if (args.empty())
{
return std::make_shared<Constant>(TYPE_INT, 0, loc);
}
if (args.size() == 1)
{
return std::make_shared<Constant>(TYPE_INT,
-std::get<int>(args[0]->value()),
loc);
}
int result = std::get<int>(args[0]->value());
for (size_t i=1; i<args.size(); i++)
{
result -= std::get<int>(args[i]->value());
}
return std::make_shared<Constant>(TYPE_INT, result, loc);
}
STDRET mul_int(Loc loc, STDARGS args)
{
int result = 1;
for (auto arg: args)
{
result *= std::get<int>(arg->value());
}
return std::make_shared<Constant>(TYPE_INT, result, loc);
}
STDRET div_int(Loc loc, STDARGS args)
{
if (args.empty())
{
return std::make_shared<Constant>(TYPE_INT, 1, loc);
}
if (args.size() == 1)
{
return std::make_shared<Constant>(TYPE_INT,
1/std::get<int>(args[0]->value()),
loc);
}
int result = std::get<int>(args[0]->value());
for (size_t i=1; i<args.size(); i++)
{
result /= std::get<int>(args[i]->value());
}
return std::make_shared<Constant>(TYPE_INT, result, loc);
}
STDRET mod_int(Loc loc, STDARGS args)
{
if (args.empty())
{
return std::make_shared<Constant>(TYPE_INT, 1, loc);
}
int result = std::get<int>(args[0]->value());
for (size_t i=1; i<args.size(); i++)
{
result %= std::get<int>(args[i]->value());
}
return std::make_shared<Constant>(TYPE_INT, result, loc);
}
STDRET pow_int(Loc loc, STDARGS args)
{
if (args.empty())
{
return std::make_shared<Constant>(TYPE_INT, 1, loc);
}
int result = std::get<int>(args[0]->value());
for (size_t i=1; i<args.size(); i++)
{
result = std::pow(result, std::get<int>(args[i]->value()));
}
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

@ -4,8 +4,22 @@
namespace fkstd namespace fkstd
{ {
STDRET assert_eq(STDARGS args); STDRET assert_eq(Loc loc, STDARGS args);
STDRET println(STDARGS args); STDRET println(Loc loc, STDARGS args);
STDRET add_int(Loc loc, STDARGS args);
STDRET sub_int(Loc loc, STDARGS args);
STDRET mul_int(Loc loc, STDARGS args);
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 #endif

View File

@ -6,8 +6,21 @@ extern "C" void lib(Module& mod)
{ {
mod.register_function("assert=", fkstd::assert_eq); mod.register_function("assert=", fkstd::assert_eq);
mod.register_function("println", fkstd::println); mod.register_function("println", fkstd::println);
mod.register_function("+", fkstd::add_int);
mod.register_function("-", fkstd::sub_int);
mod.register_function("*", fkstd::mul_int);
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("assert-static-fail", fkstd::assert_static_fail);
mod.register_macro(":", fkstd::block); mod.register_macro(":", fkstd::block);
mod.register_macro("$", fkstd::decl); mod.register_macro("$", fkstd::decl);
mod.register_macro("if", fkstd::if_macro);
} }

View File

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

View File

@ -83,6 +83,7 @@ namespace fk
case NODE_CALL: { case NODE_CALL: {
std::string ident = node->child(0)->repr(); std::string ident = node->child(0)->repr();
if (auto itr=m_macros.find(ident); if (auto itr=m_macros.find(ident);
itr != std::end(m_macros)) itr != std::end(m_macros))
{ {

View File

@ -29,7 +29,7 @@ namespace fk
private: private:
std::filesystem::path m_source_path; std::filesystem::path m_source_path;
std::string m_source; std::string m_source;
Loc m_loc {m_source_path}; Loc m_loc {m_source_path, 1};
std::shared_ptr<Lexer> m_lexer = std::make_shared<Lexer>(m_loc); std::shared_ptr<Lexer> m_lexer = std::make_shared<Lexer>(m_loc);
std::shared_ptr<Parser> m_parser = std::make_shared<Parser>(*m_lexer); std::shared_ptr<Parser> m_parser = std::make_shared<Parser>(*m_lexer);
std::shared_ptr<SymTable> m_sym = std::make_shared<SymTable>(); std::shared_ptr<SymTable> m_sym = std::make_shared<SymTable>();

View File

@ -12,8 +12,9 @@ namespace fk
} }
std::shared_ptr<Constant> std::shared_ptr<Constant>
NativeFunction::call(std::vector<std::shared_ptr<Constant>> args) NativeFunction::call(Loc const& loc,
std::vector<std::shared_ptr<Constant>> args)
{ {
return m_native(args); return m_native(loc, args);
} }
} }

View File

@ -7,7 +7,7 @@
namespace fk namespace fk
{ {
using native_t = std::function using native_t = std::function
<std::shared_ptr<Constant>(std::vector<std::shared_ptr<Constant>>)>; <std::shared_ptr<Constant>(Loc, std::vector<std::shared_ptr<Constant>>)>;
class NativeFunction class NativeFunction
{ {
@ -16,7 +16,7 @@ namespace fk
virtual ~NativeFunction(); virtual ~NativeFunction();
std::shared_ptr<Constant> std::shared_ptr<Constant>
call(std::vector<std::shared_ptr<Constant>> args); call(Loc const& loc, std::vector<std::shared_ptr<Constant>> args);
private: private:
native_t m_native; native_t m_native;

View File

@ -16,6 +16,12 @@ namespace fk
return m_instrs.size() - 1; 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 Instr Program::instr(size_t index) const
{ {
assert(index < size()); assert(index < size());
@ -32,7 +38,9 @@ namespace fk
{ {
for (size_t i=0; i<m_consts.size(); i++) for (size_t i=0; i<m_consts.size(); i++)
{ {
if (m_consts[i]->equals(*constant)) if (m_consts[i]->equals(*constant)
&& m_consts[i]->loc().line() == constant->loc().line()
&& m_consts[i]->loc().path() == constant->loc().path())
{ {
return i; return i;
} }

View File

@ -24,6 +24,8 @@ namespace fk
size_t const_size() const { return m_consts.size(); } size_t const_size() const { return m_consts.size(); }
size_t add(Opcode opcode, addr_t param=NO_PARAM); 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; Instr instr(size_t index) const;
std::shared_ptr<Constant> get_const(addr_t addr) const; std::shared_ptr<Constant> get_const(addr_t addr) const;

View File

@ -27,6 +27,25 @@ namespace fk
switch (instr.opcode) 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: { case OP_MAKE_FUNCTION: {
auto p = frame().program->get_const(pop()); auto p = frame().program->get_const(pop());
auto prog = std::get<std::shared_ptr<Program>>(p->value()); auto prog = std::get<std::shared_ptr<Program>>(p->value());
@ -101,13 +120,19 @@ namespace fk
args.insert(std::begin(args), args.insert(std::begin(args),
frame().program->get_const(addr)); frame().program->get_const(addr));
} }
auto ref_val = frame().program->get_const(pop());
Loc loc = ref_val->loc();
auto ref = std::get<size_t>(frame().program if (instr.param > 0)
->get_const(pop())->value()); {
loc = args.front()->loc();
}
auto ref = std::get<size_t>(ref_val->value());
auto fun = std::get<std::shared_ptr<NativeFunction>> auto fun = std::get<std::shared_ptr<NativeFunction>>
(load_global(ref)); (load_global(ref));
push(frame().program->add(fun->call(args))); push(frame().program->add(fun->call(loc, args)));
m_pc++; m_pc++;
} break; } break;

View File

@ -3,7 +3,8 @@
#define OPCODES(G) G(OP_LOAD_CONST), G(OP_POP), G(OP_CALL_NATIVE), \ #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_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" #include "commons.hpp"