Compare commits

...

5 Commits

14 changed files with 355 additions and 40 deletions

View File

@ -1,13 +1,13 @@
(assert= 8 ([2 6 2 8 9] 3)) (assert= 8 (ref [2 6 2 8 9] 3))
(assert= 9 ([[3 6] [9 2]] 1 0)) (assert= 9 (ref [[3 6] [9 2]] 1 0))
($ a ['a' [[2 true] 2.3]]) ($ a ['a' [[2 true] 2.3]])
(assert= 'a' (a 0)) (assert= 'a' (ref a 0))
(assert= 2 (a 1 0 0)) (assert= 2 (ref a 1 0 0))
($ (second arr) ($ (second arr)
(arr 1)) (ref arr 1))
(assert= 6 (second [2 6])) (assert= 6 (second [2 6]))
@ -15,3 +15,6 @@
[2 4 6]) [2 4 6])
(assert= 4 (second (produce))) (assert= 4 (second (produce)))
($ arr [2 'bim' produce false])
(assert= 6 (ref ((ref arr 2)) 2))

18
examples/bool.fk Normal file
View File

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

20
examples/float.fk Normal file
View File

@ -0,0 +1,20 @@
(assert= 7.2 7.20)
(assert= 4.7 (+. 3.2 1.5))
(assert= 3.2 (+. 3.2))
(assert= 0.0 (+.))
(assert= 1.7 (-. 3.2 1.5))
(assert= -1.5 (-. 1.5))
(assert= 0.0 (-.))
(assert= 77.4 (*. 21.5 3.6))
(assert= 3.0 (*. 3.0))
(assert= 1.0 (*.))
(assert= 0.57 (/. 1.14 2.0))
(assert= .25 (/. 4.0))
(assert= 1.0 (/.))
(assert= 1.5 (%. 75. 3.5))
(assert= 15.625 (^. 2.5 3.))

3
examples/string.fk Normal file
View File

@ -0,0 +1,3 @@
(assert= 'hello world' (cat 'hello' ' world'))
(assert= 'yoyoyo' (dup 'yo' 3))
(assert= 'e' (char-at 'hello' 1))

View File

@ -166,6 +166,118 @@ namespace fkstd
return std::make_shared<Constant>(TYPE_INT, result, loc); return std::make_shared<Constant>(TYPE_INT, result, loc);
} }
STDRET add_float(Loc loc, Module&, STDARGS args)
{
if (args.empty())
{
return std::make_shared<Constant>(TYPE_FLOAT, 0.0f, loc);
}
float result = std::get<float>(args[0]->value());
for (size_t i=1; i<args.size(); i++)
{
result = result + std::get<float>(args[i]->value());
}
return std::make_shared<Constant>(TYPE_FLOAT, result, loc);
}
STDRET sub_float(Loc loc, Module&, STDARGS args)
{
if (args.empty())
{
return std::make_shared<Constant>(TYPE_FLOAT, 0.0f, loc);
}
float result = std::get<float>(args[0]->value());
for (size_t i=1; i<args.size(); i++)
{
result = result - std::get<float>(args[i]->value());
}
if (args.size() == 1)
{
return std::make_shared<Constant>(TYPE_FLOAT, -result, loc);
}
return std::make_shared<Constant>(TYPE_FLOAT, result, loc);
}
STDRET mul_float(Loc loc, Module&, STDARGS args)
{
if (args.empty())
{
return std::make_shared<Constant>(TYPE_FLOAT, 1.0f, loc);
}
float result = std::get<float>(args[0]->value());
for (size_t i=1; i<args.size(); i++)
{
result = result * std::get<float>(args[i]->value());
}
return std::make_shared<Constant>(TYPE_FLOAT, result, loc);
}
STDRET div_float(Loc loc, Module&, STDARGS args)
{
if (args.empty())
{
return std::make_shared<Constant>(TYPE_FLOAT, 1.0f, loc);
}
float result = std::get<float>(args[0]->value());
for (size_t i=1; i<args.size(); i++)
{
result = result / std::get<float>(args[i]->value());
}
if (args.size() == 1)
{
return std::make_shared<Constant>(TYPE_FLOAT, 1.0f/result, loc);
}
return std::make_shared<Constant>(TYPE_FLOAT, result, loc);
}
STDRET mod_float(Loc loc, Module&, STDARGS args)
{
if (args.empty())
{
return std::make_shared<Constant>(TYPE_FLOAT, 1.0f, loc);
}
float result = std::get<float>(args[0]->value());
for (size_t i=1; i<args.size(); i++)
{
result = std::fmod(result, std::get<float>(args[i]->value()));
}
return std::make_shared<Constant>(TYPE_FLOAT, result, loc);
}
STDRET pow_float(Loc loc, Module&, STDARGS args)
{
if (args.empty())
{
return std::make_shared<Constant>(TYPE_FLOAT, 1.0f, loc);
}
float result = std::get<float>(args[0]->value());
for (size_t i=1; i<args.size(); i++)
{
result = std::pow(result, std::get<float>(args[i]->value()));
}
return std::make_shared<Constant>(TYPE_FLOAT, result, loc);
}
STDRET lt(Loc loc, Module&, STDARGS args) STDRET lt(Loc loc, Module&, STDARGS args)
{ {
NUM_BINOP(<); NUM_BINOP(<);
@ -195,4 +307,76 @@ namespace fkstd
{ {
NUM_BINOP(!=); NUM_BINOP(!=);
} }
STDRET bool_not(Loc loc, Module&, STDARGS args)
{
bool val = std::get<bool>(args[0]->value());
return std::make_shared<Constant>(TYPE_BOOL, !val, loc);
}
STDRET array_ref(Loc, Module& mod, STDARGS args)
{
auto ref_val = args[0]->value();
size_t ref = std::get<size_t>(ref_val);
std::shared_ptr<Array> val =
std::get<std::shared_ptr<Array>>(mod.vm()->load_global(ref));
for (size_t i=1; i<args.size() - 1; i++)
{
int k = std::get<int>(args[i]->value());
auto ref_val = val->at(k)->value();
size_t ref = std::get<size_t>(ref_val);
auto arr =
std::get<std::shared_ptr<Array>>(mod.vm()->load_global(ref));
val = arr;
}
return val->at(std::get<int>(args.back()->value()));
}
STDRET string_cat(Loc loc, Module&, STDARGS args)
{
if (args.empty())
{
return std::make_shared<Constant>(TYPE_STRING, "", loc);
}
std::string value = std::get<std::string>(args[0]->value());
for (size_t i=1; i<args.size(); i++)
{
value += std::get<std::string>(args[i]->value());
}
return std::make_shared<Constant>(TYPE_STRING, value, loc);
}
STDRET string_dup(Loc loc, Module&, STDARGS args)
{
std::string str = std::get<std::string>(args[0]->value());
int n = std::get<int>(args[1]->value());
std::string res;
for (int i=0; i<n; i++)
{
res += str;
}
return std::make_shared<Constant>(TYPE_STRING, res, loc);
}
STDRET char_at(Loc loc, Module&, STDARGS args)
{
std::string str = std::get<std::string>(args[0]->value());
int n = std::get<int>(args[1]->value());
return std::make_shared<Constant>(TYPE_STRING,
std::string(1, str[n]),
loc);
}
} }

View File

@ -14,12 +14,26 @@ namespace fkstd
STDRET mod_int(Loc loc, Module& mod, STDARGS args); STDRET mod_int(Loc loc, Module& mod, STDARGS args);
STDRET pow_int(Loc loc, Module& mod, STDARGS args); STDRET pow_int(Loc loc, Module& mod, STDARGS args);
STDRET add_float(Loc loc, Module& mod, STDARGS args);
STDRET sub_float(Loc loc, Module& mod, STDARGS args);
STDRET mul_float(Loc loc, Module& mod, STDARGS args);
STDRET div_float(Loc loc, Module& mod, STDARGS args);
STDRET mod_float(Loc loc, Module& mod, STDARGS args);
STDRET pow_float(Loc loc, Module& mod, STDARGS args);
STDRET lt(Loc loc, Module& mod, STDARGS args); STDRET lt(Loc loc, Module& mod, STDARGS args);
STDRET le(Loc loc, Module& mod, STDARGS args); STDRET le(Loc loc, Module& mod, STDARGS args);
STDRET gt(Loc loc, Module& mod, STDARGS args); STDRET gt(Loc loc, Module& mod, STDARGS args);
STDRET ge(Loc loc, Module& mod, STDARGS args); STDRET ge(Loc loc, Module& mod, STDARGS args);
STDRET eq(Loc loc, Module& mod, STDARGS args); STDRET eq(Loc loc, Module& mod, STDARGS args);
STDRET ne(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);
STDRET string_cat(Loc loc, Module& mod, STDARGS args);
STDRET string_dup(Loc loc, Module& mod, STDARGS args);
STDRET char_at(Loc loc, Module& mod, STDARGS args);
} }
#endif #endif

View File

@ -12,6 +12,14 @@ extern "C" void lib(Module& mod)
mod.register_function("/", fkstd::div_int); mod.register_function("/", fkstd::div_int);
mod.register_function("%", fkstd::mod_int); mod.register_function("%", fkstd::mod_int);
mod.register_function("^", fkstd::pow_int); mod.register_function("^", fkstd::pow_int);
mod.register_function("+.", fkstd::add_float);
mod.register_function("-.", fkstd::sub_float);
mod.register_function("*.", fkstd::mul_float);
mod.register_function("/.", fkstd::div_float);
mod.register_function("%.", fkstd::mod_float);
mod.register_function("^.", fkstd::pow_float);
mod.register_function("<", fkstd::lt); mod.register_function("<", fkstd::lt);
mod.register_function("<=", fkstd::le); mod.register_function("<=", fkstd::le);
mod.register_function(">", fkstd::gt); mod.register_function(">", fkstd::gt);
@ -19,8 +27,16 @@ extern "C" void lib(Module& mod)
mod.register_function("=", fkstd::eq); mod.register_function("=", fkstd::eq);
mod.register_function("<>", fkstd::ne); mod.register_function("<>", fkstd::ne);
mod.register_function("not", fkstd::bool_not);
mod.register_function("ref", fkstd::array_ref);
mod.register_function("cat", fkstd::string_cat);
mod.register_function("dup", fkstd::string_dup);
mod.register_function("char-at", fkstd::char_at);
mod.register_macro("!", fkstd::set_addr); mod.register_macro("!", fkstd::set_addr);
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("if", fkstd::if_macro); mod.register_macro("if", fkstd::if_macro);
mod.register_macro("and", fkstd::and_macro);
mod.register_macro("or", fkstd::or_macro);
} }

View File

@ -103,4 +103,67 @@ namespace fkstd
compiler.compile_prog(else_expr, program); compiler.compile_prog(else_expr, program);
program->set_param(to_end, program->size()); program->set_param(to_end, program->size());
} }
void and_macro(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program)
{
std::vector<size_t> to_false;
for (size_t i=1; i<node->size(); 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<Constant>(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<Constant>(TYPE_BOOL,
false,
node->loc()));
program->set_param(out_addr, program->size());
}
void or_macro(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program)
{
std::vector<size_t> to_true;
for (size_t i=1; i<node->size(); 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<Constant>(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<Constant>(TYPE_BOOL,
true,
node->loc()));
program->set_param(out_addr, program->size());
}
} }

View File

@ -23,6 +23,14 @@ namespace fkstd
void if_macro(Compiler& compiler, void if_macro(Compiler& compiler,
std::shared_ptr<Node> node, std::shared_ptr<Node> node,
std::shared_ptr<Program> program); std::shared_ptr<Program> program);
void and_macro(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program);
void or_macro(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program);
} }
#endif #endif

View File

@ -198,6 +198,7 @@ namespace fk
{ {
auto macro = itr->second; auto macro = itr->second;
macro->call(*this, node, prog); macro->call(*this, node, prog);
break;
} }
else if (node->child(0)->type() == NODE_NS else if (node->child(0)->type() == NODE_NS
&& has_macro(node->child(0)->child(1)->repr())) && has_macro(node->child(0)->child(1)->repr()))
@ -218,12 +219,7 @@ namespace fk
compile_prog(node->child(i), prog); compile_prog(node->child(i), prog);
} }
if (node->child(0)->type() == NODE_ARRAY) if (node->child(0)->type() == NODE_LAMBDA
{
prog->add(OP_CALL_REF, node->size() - 1);
break;
}
else if (node->child(0)->type() == NODE_LAMBDA
|| node->child(0)->type() == NODE_CALL || node->child(0)->type() == NODE_CALL
|| node->child(0)->type() == NODE_NS) || node->child(0)->type() == NODE_NS)
{ {
@ -236,7 +232,8 @@ namespace fk
entry && entry->is_global() == false) entry && entry->is_global() == false)
{ {
if (entry->node() if (entry->node()
&& entry->node()->child(1)->type() != NODE_ARRAY) && entry->node()
&& entry->node()->type() == NODE_LAMBDA)
{ {
size_t arity = entry->node()->child(0)->size(); size_t arity = entry->node()->child(0)->size();
if (arity != node->size() - 1) if (arity != node->size() - 1)
@ -262,6 +259,7 @@ namespace fk
break; break;
} }
} }
std::cerr << "cannot call node '" std::cerr << "cannot call node '"
<< node->string() << "'" << std::endl; << node->string() << "'" << std::endl;
abort(); abort();

View File

@ -196,7 +196,7 @@ namespace fk
cursor++; cursor++;
} }
if (repr.empty() || repr.back() == '-' || repr == ".") if (repr.empty() || repr.back() == '-' || repr == "." || repr == "-.")
{ {
return std::nullopt; return std::nullopt;
} }

View File

@ -212,6 +212,16 @@ namespace fk
m_pc++; m_pc++;
} break; } break;
case OP_NOT: {
auto c_val = frame().program->get_const(pop());
bool val = std::get<bool>(c_val->value());
push(frame().
program->add(std::make_shared<Constant>(TYPE_BOOL,
!val,
c_val->loc())));
m_pc++;
} break;
case OP_BR: { case OP_BR: {
m_pc = instr.param; m_pc = instr.param;
} break; } break;
@ -310,31 +320,6 @@ namespace fk
m_pc++; m_pc++;
break; break;
} }
else if (std::get_if<std::shared_ptr<Array>>(&val))
{
std::shared_ptr<Array> val =
std::get<std::shared_ptr<Array>>(load_global(ref));
for (size_t i=0; i<args.size() - 1; i++)
{
int k = std::get<int>(args[i]->value());
auto ref_val = val->at(k)->value();
size_t ref = std::get<size_t>(ref_val);
auto arr =
std::get<std::shared_ptr<Array>>(load_global(ref));
val = arr;
}
push(frame().program->add
(val->at(std::get<int>(args.back()->value()))));
m_pc++;
break;
}
auto lambda = std::get<std::shared_ptr<Lambda>>(load_global(ref)); auto lambda = std::get<std::shared_ptr<Lambda>>(load_global(ref));

View File

@ -23,6 +23,8 @@ namespace fk
}; };
class Module; class Module;
FK_ERROR(execution_error);
class VM class VM
{ {
public: public:

View File

@ -5,7 +5,8 @@
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_BNE), \ 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_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" #include "commons.hpp"