grino/lib/core.cpp

341 lines
7.5 KiB
C++
Raw Normal View History

2023-09-11 10:14:01 +00:00
#include "../src/Loader.hpp"
2023-09-11 11:46:41 +00:00
#include "src/Logger.hpp"
#include "src/Value.hpp"
2023-09-11 11:46:41 +00:00
GRINO_ERROR(assertion_error);
2023-09-11 10:14:01 +00:00
2023-09-11 13:59:37 +00:00
extern "C" void lib_int(grino::Loader& loader)
{
loader.add_native("+", [](auto args){
int result = 0;
for (auto value: args)
{
result += value->as_int();
}
grino::Loc loc {"???", 0};
if (args.empty() == false)
{
loc = args.front()->loc();
}
return grino::Value::make_int(loc, result);
});
loader.add_native("*", [](auto args){
int result = 1;
for (auto value: args)
{
result *= value->as_int();
}
grino::Loc loc {"???", 0};
if (args.empty() == false)
{
loc = args.front()->loc();
}
return grino::Value::make_int(loc, result);
});
loader.add_native("-", [](auto args){
grino::Loc loc {"???", 0};
if (args.empty() == false)
{
loc = args.front()->loc();
}
else
{
return grino::Value::make_int(loc, 0);
}
int result = args[0]->as_int();
if (args.size() == 1)
{
return grino::Value::make_int(loc, -result);
}
for (size_t i=1; i<args.size(); i++)
{
result -= args[i]->as_int();
}
return grino::Value::make_int(loc, result);
});
loader.add_native("/", [](auto args){
grino::Loc loc {"???", 0};
if (args.empty() == false)
{
loc = args.front()->loc();
}
else
{
return grino::Value::make_int(loc, 1);
}
int result = args[0]->as_int();
if (args.size() == 1)
{
return grino::Value::make_int(loc, result);
}
for (size_t i=1; i<args.size(); i++)
{
result /= args[i]->as_int();
}
return grino::Value::make_int(loc, result);
});
loader.add_native("%", [](auto args){
grino::Loc loc {"???", 0};
if (args.empty() == false)
{
loc = args.front()->loc();
}
else
{
return grino::Value::make_int(loc, 1);
}
int result = args[0]->as_int();
if (args.size() == 1)
{
return grino::Value::make_int(loc, result);
}
for (size_t i=1; i<args.size(); i++)
{
result %= args[i]->as_int();
}
return grino::Value::make_int(loc, result);
});
loader.add_native("^", [](auto args){
grino::Loc loc {"???", 0};
if (args.empty() == false)
{
loc = args.front()->loc();
}
else
{
return grino::Value::make_int(loc, 1);
}
int result = args[0]->as_int();
if (args.size() == 1)
{
return grino::Value::make_int(loc, result);
}
for (size_t i=1; i<args.size(); i++)
{
result = std::pow(result, args[i]->as_int());
}
return grino::Value::make_int(loc, result);
});
}
extern "C" void lib_cmp(grino::Loader& loader)
{
loader.add_native("<", [](auto args){
int lhs = args[0]->as_int();
int rhs = args[1]->as_int();
return grino::Value::make_bool(args[0]->loc(), lhs < rhs);
});
loader.add_native("<=", [](auto args){
int lhs = args[0]->as_int();
int rhs = args[1]->as_int();
return grino::Value::make_bool(args[0]->loc(), lhs <= rhs);
});
loader.add_native(">", [](auto args){
int lhs = args[0]->as_int();
int rhs = args[1]->as_int();
return grino::Value::make_bool(args[0]->loc(), lhs > rhs);
});
loader.add_native(">=", [](auto args){
int lhs = args[0]->as_int();
int rhs = args[1]->as_int();
return grino::Value::make_bool(args[0]->loc(), lhs >= rhs);
});
loader.add_native("ne?", [](auto args){
int lhs = args[0]->as_int();
int rhs = args[1]->as_int();
return grino::Value::make_bool(args[0]->loc(), lhs != rhs);
});
}
extern "C" void lib_bool(grino::Loader& loader)
{
loader.add_native("not", [](auto args){
return grino::Value::make_bool(args[0]->loc(), !args[0]->as_bool());
});
2023-09-11 18:59:54 +00:00
loader.add_static("and", [](auto& compiler, auto node,
auto& program,
auto& sym){
std::vector<size_t> to_false;
for (size_t i=1; i<node->size(); i++)
{
2023-09-11 18:59:54 +00:00
compiler.compile(node->child(i).lock(), program, sym);
to_false.push_back(program.size());
program.push_instr(grino::OPCODE_BRF, 0 /* to false */);
}
size_t addr = program
.push_constant(grino::Value::make_bool(node->loc(), true));
program.push_instr(grino::OPCODE_LOAD_CONST, addr);
size_t to_end = program.size();
program.push_instr(grino::OPCODE_BR, 0 /* to end */);
for (auto a: to_false)
{
program.set_param(a, program.size());
}
addr = program
.push_constant(grino::Value::make_bool(node->loc(), false));
program.push_instr(grino::OPCODE_LOAD_CONST, addr);
program.set_param(to_end, program.size());
});
2023-09-11 18:59:54 +00:00
loader.add_static("or", [](auto& compiler, auto node,
auto& program, auto& sym){
std::vector<size_t> to_true;
for (size_t i=1; i<node->size(); i++)
{
2023-09-11 18:59:54 +00:00
compiler.compile(node->child(i).lock(), program, sym);
program.push_instr(grino::OPCODE_NOT);
to_true.push_back(program.size());
program.push_instr(grino::OPCODE_BRF, 0 /* to true */);
}
size_t addr = program
.push_constant(grino::Value::make_bool(node->loc(), false));
program.push_instr(grino::OPCODE_LOAD_CONST, addr);
size_t to_end = program.size();
program.push_instr(grino::OPCODE_BR, 0 /* to end */);
for (auto a: to_true)
{
program.set_param(a, program.size());
}
addr = program
.push_constant(grino::Value::make_bool(node->loc(), true));
program.push_instr(grino::OPCODE_LOAD_CONST, addr);
program.set_param(to_end, program.size());
});
}
extern "C" void lib_assert(grino::Loader& loader)
{
2023-09-11 13:59:37 +00:00
loader.add_native("assert", [](auto args){
for (auto value: args)
{
if (!value->as_bool())
{
grino::Logger logger;
logger.log<assertion_error>(grino::LOG_ASSERT,
value->loc(),
"assertion failed");
}
}
return grino::Value::make_bool(args.front()->loc(), true);
});
2023-09-11 13:59:37 +00:00
loader.add_native("assert-eq?", [](auto args){
auto lhs = args.front();
for (size_t i=1; i<args.size(); i++)
{
auto rhs = args[i];
if (!lhs->equals(*rhs))
{
grino::Logger logger;
std::stringstream ss;
ss << "'" << lhs->string() << "' is not equals to '"
<< rhs->string() << "'";
logger.log<assertion_error>(grino::LOG_ASSERT,
lhs->loc(),
ss.str());
}
}
return grino::Value::make_bool(args.front()->loc(), true);
});
}
2023-09-11 10:14:01 +00:00
extern "C" void lib(grino::Loader& loader)
{
lib_assert(loader);
2023-09-11 13:59:37 +00:00
lib_int(loader);
lib_cmp(loader);
lib_bool(loader);
2023-09-11 10:14:01 +00:00
loader.add_native("dump", [](auto args){
std::string sep;
std::stringstream ss;
for (auto arg: args)
{
ss << sep << arg->string();
sep = " ";
}
std::cout << ss.str() << std::endl;
2023-09-11 11:46:41 +00:00
return grino::Value::make_nil(args.back()->loc());
});
loader.add_native("eq?", [](auto args){
auto lhs = args.front();
2023-09-11 11:46:41 +00:00
for (size_t i=1; i<args.size(); i++)
2023-09-11 11:46:41 +00:00
{
auto rhs = args[i];
if (!lhs->equals(*rhs))
2023-09-11 11:46:41 +00:00
{
return grino::Value::make_bool(rhs->loc(), false);
2023-09-11 11:46:41 +00:00
}
}
return grino::Value::make_bool(args.front()->loc(), true);
2023-09-11 10:14:01 +00:00
});
}