grino/tests/StaticPass.cpp

380 lines
10 KiB
C++

#include <catch2/catch.hpp>
#include <memory>
#include "../src/StaticPass.hpp"
#include "../src/Logger.hpp"
#include "../src/Lexer.hpp"
#include "../src/Parser.hpp"
#include "src/Prototype.hpp"
#include "src/SymTable.hpp"
#include "src/Loader.hpp"
#include "src/types.hpp"
class StaticPassTest
{
public:
explicit StaticPassTest() {}
virtual ~StaticPassTest() {}
void test_ok(std::string const& source,
std::function<void(grino::Loader&)> init)
{
grino::Logger logger;
grino::Lexer lexer {logger, "tests/parser"};
grino::Parser parser {logger, lexer};
grino::SymTable sym {logger};
grino::Addr addr;
grino::Compiler compiler {logger, addr};
grino::StaticPass pass {logger, compiler, sym};
grino::Program prog;
grino::VM vm {logger, prog};
grino::Loader loader {vm, compiler, sym};
init(loader);
auto root = parser.parse(source);
INFO("source: " << source);
REQUIRE_NOTHROW(pass.check(root));
}
void test_ko(std::string const& source,
std::function<void(grino::Loader&)> init)
{
grino::Logger logger;
grino::Lexer lexer {logger, "tests/parser"};
grino::Parser parser {logger, lexer};
grino::SymTable sym {logger};
grino::Addr addr;
grino::Compiler compiler {logger, addr};
grino::StaticPass pass {logger, compiler, sym};
grino::Program prog;
grino::VM vm {logger, prog};
grino::Loader loader {vm, compiler, sym};
init(loader);
auto root = parser.parse(source);
INFO("source: " << source);
REQUIRE_THROWS_AS(pass.check(root), grino::static_error);
}
protected:
};
TEST_CASE_METHOD(StaticPassTest, "StaticPass_normal")
{
grino::TypeSlot ty_int_param {
grino::HintCatType::HINT_CAT_PARAM,
grino::TYPE_INT
};
grino::TypeSlot ty_int_ret {
grino::HintCatType::HINT_CAT_RETURN,
grino::TYPE_INT
};
auto slots = std::vector<grino::TypeSlot> {ty_int_param,
ty_int_param,
ty_int_ret};
auto proto = std::make_shared<grino::Prototype>(slots);
test_ok("(+ 45 1)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ko("(+ 45.2 1)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ko("(+ (+ 45.2 1) 3)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
}
TEST_CASE_METHOD(StaticPassTest, "StaticPass_hint_any")
{
grino::TypeSlot ty_int_param {
grino::HintCatType::HINT_CAT_PARAM,
grino::TYPE_INT
};
grino::TypeSlot ty_any_param {
grino::HintCatType::HINT_CAT_PARAM,
grino::TYPE_INT,
grino::HINT_ANY
};
grino::TypeSlot ty_int_ret {
grino::HintCatType::HINT_CAT_RETURN,
grino::TYPE_INT
};
auto slots = std::vector<grino::TypeSlot> {ty_int_param,
ty_any_param,
ty_int_ret};
auto proto = std::make_shared<grino::Prototype>(slots);
test_ok("(+ 45 1)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ko("(+ 45.2 1)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ok("(+ 45 1.3)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ok("(+ (+ 2 1) 3)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ok("(+ (+ 2 1) 3.2)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ko("(+ 7.14 (+ 2 1))", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
}
TEST_CASE_METHOD(StaticPassTest, "StaticPass_hint_same")
{
grino::TypeSlot ty_any_param {
grino::HintCatType::HINT_CAT_PARAM,
grino::TYPE_NIL,
grino::HINT_ANY
};
grino::TypeSlot ty_same_param {
grino::HintCatType::HINT_CAT_PARAM,
grino::TYPE_NIL,
grino::HINT_SAME
};
grino::TypeSlot ty_int_ret {
grino::HintCatType::HINT_CAT_RETURN,
grino::TYPE_INT
};
auto slots = std::vector<grino::TypeSlot> {ty_any_param,
ty_same_param,
ty_int_ret};
auto proto = std::make_shared<grino::Prototype>(slots);
test_ok("(+ 45 1)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ok("(+ 45.2 1.3)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ok("(+ false true)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ko("(+ false 3.2)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ko("(+ 3.7 9)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
}
TEST_CASE_METHOD(StaticPassTest, "StaticPass_int_variadic")
{
grino::TypeSlot ty_same_param {
grino::HintCatType::HINT_CAT_PARAM,
grino::TYPE_NIL,
grino::HINT_SAME
};
grino::TypeSlot ty_var_param {
grino::HintCatType::HINT_CAT_VARIADIC_PARAM,
grino::TYPE_INT
};
grino::TypeSlot ty_int_ret {
grino::HintCatType::HINT_CAT_RETURN,
grino::TYPE_INT
};
auto slots = std::vector<grino::TypeSlot> {
ty_same_param,
ty_var_param,
ty_int_ret
};
auto proto = std::make_shared<grino::Prototype>(slots);
test_ok("(+ 45 1 3 2 1 7)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ok("(+ 45 1 7)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ko("(+ 45 3.12 1 7)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
}
TEST_CASE_METHOD(StaticPassTest, "StaticPass_any_variadic")
{
grino::TypeSlot ty_same_param {
grino::HintCatType::HINT_CAT_PARAM,
grino::TYPE_NIL,
grino::HINT_SAME
};
grino::TypeSlot ty_var_param {
grino::HintCatType::HINT_CAT_VARIADIC_PARAM,
grino::TYPE_INT,
grino::HINT_ANY
};
grino::TypeSlot ty_int_ret {
grino::HintCatType::HINT_CAT_RETURN,
grino::TYPE_INT
};
auto slots = std::vector<grino::TypeSlot> {
ty_same_param,
ty_var_param,
ty_int_ret
};
auto proto = std::make_shared<grino::Prototype>(slots);
test_ok("(+ 45 1 3 2 1 7)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ok("(+ 45 1 7)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ok("(+ 45 3.12 1 7)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
test_ok("(+ 45 3.12 true 'salut' 7)", [&proto](auto& loader){
grino::Loc loc {"tests/static_pass"};
loader.add_native("+", [loader, loc](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_int(loc, lhs->as_int() + rhs->as_int());
}, proto);
});
}