Compare commits

..

No commits in common. "e12ff9694332fbc1d6a48042f4f99e85cfb351f0" and "47b44d3439c28d97ad895f7be5a3c9a1ac629f91" have entirely different histories.

37 changed files with 98 additions and 1164 deletions

View File

@ -24,5 +24,4 @@ BLOCK ::= opar colon EXPR* cpar
ARRAY ::= osquare EXPR* csquare
IMPORT ::= opar import string cpar
SHORT_IMPORT ::= opar decl import ident string cpar
SHORTER_IMPORT ::= opar decl import ident cpar
NS ::= ident ns ident

View File

@ -1,26 +0,0 @@
#include "commons.hpp"
extern "C" void lib_cast(grino::Loader& loader)
{
grino::Loc loc {"core/casts"};
loader.add_native("stoi", [loc](auto args){
std::string value = args[0]->as_string();
return grino::Value::make_int(loc, std::stoi(value));
});
loader.add_native("itos", [loc](auto args){
int value = args[0]->as_int();
return grino::Value::make_string(loc, std::to_string(value));
});
loader.add_native("stof", [loc](auto args){
std::string value = args[0]->as_string();
return grino::Value::make_int(loc, std::stof(value));
});
loader.add_native("ftos", [loc](auto args){
float value = args[0]->as_float();
return grino::Value::make_string(loc, std::to_string(value));
});
}

View File

@ -1,5 +0,0 @@
#include "../src/Loader.hpp"
#include "../src/Logger.hpp"
#include "../src/Value.hpp"
#include "../src/opcodes.hpp"
#include "../src/Module.hpp"

View File

@ -1,11 +1,8 @@
#include "../src/Loader.hpp"
#include "src/Logger.hpp"
#include "src/Prototype.hpp"
#include "src/Value.hpp"
#include "src/opcodes.hpp"
#include "../src/Module.hpp"
#include "cast.hpp"
#include "src/types.hpp"
GRINO_ERROR(assertion_error);
@ -44,11 +41,7 @@ extern "C" void lib_collection(grino::Loader& loader)
};
return f(args[0], idxs);
}, std::make_shared<grino::Prototype>(std::vector<grino::TypeSlot>{
grino::TypeSlot {grino::HINT_CAT_PARAM, grino::TYPE_INT},
grino::TypeSlot {grino::HINT_CAT_PARAM, grino::TYPE_NIL, grino::HINT_ANY},
grino::TypeSlot {grino::HINT_CAT_RETURN, grino::TYPE_NIL, grino::HINT_ANY},
}));
});
loader.add_native("empty?", [&loader](auto args){
auto val = args[0];
@ -146,21 +139,11 @@ extern "C" void lib_flow_control(grino::Loader& loader)
compiler.compile(else_node, prog, sym);
prog.set_param(br, prog.size());
}, std::make_shared<grino::Prototype>(std::vector<grino::TypeSlot> {{
grino::TypeSlot {grino::HINT_CAT_RETURN,
grino::TYPE_NIL,
grino::HINT_NONE},
}}));
});
}
extern "C" void lib_int(grino::Loader& loader)
{
auto var_proto =
std::make_shared<grino::Prototype>(std::vector<grino::TypeSlot>{
grino::TypeSlot {grino::HINT_CAT_VARIADIC_PARAM, grino::TYPE_INT},
grino::TypeSlot {grino::HINT_CAT_RETURN, grino::TYPE_INT},
});
loader.add_native("+", [](auto args){
int result = 0;
@ -177,7 +160,7 @@ extern "C" void lib_int(grino::Loader& loader)
}
return grino::Value::make_int(loc, result);
}, var_proto);
});
loader.add_native("*", [](auto args){
int result = 1;
@ -195,7 +178,7 @@ extern "C" void lib_int(grino::Loader& loader)
}
return grino::Value::make_int(loc, result);
}, var_proto);
});
loader.add_native("-", [](auto args){
grino::Loc loc {"???", 0};
@ -222,7 +205,7 @@ extern "C" void lib_int(grino::Loader& loader)
}
return grino::Value::make_int(loc, result);
}, var_proto);
});
loader.add_native("/", [](auto args){
grino::Loc loc {"???", 0};
@ -249,7 +232,7 @@ extern "C" void lib_int(grino::Loader& loader)
}
return grino::Value::make_int(loc, result);
}, var_proto);
});
loader.add_native("%", [](auto args){
grino::Loc loc {"???", 0};
@ -276,7 +259,7 @@ extern "C" void lib_int(grino::Loader& loader)
}
return grino::Value::make_int(loc, result);
}, var_proto);
});
loader.add_native("^", [](auto args){
grino::Loc loc {"???", 0};
@ -303,17 +286,11 @@ extern "C" void lib_int(grino::Loader& loader)
}
return grino::Value::make_int(loc, result);
}, var_proto);
});
}
extern "C" void lib_float(grino::Loader& loader)
{
auto var_proto =
std::make_shared<grino::Prototype>(std::vector<grino::TypeSlot>{
grino::TypeSlot {grino::HINT_CAT_VARIADIC_PARAM, grino::TYPE_FLOAT},
grino::TypeSlot {grino::HINT_CAT_RETURN, grino::TYPE_INT},
});
loader.add_native("+.", [](auto args){
float result = 0;
@ -330,7 +307,7 @@ extern "C" void lib_float(grino::Loader& loader)
}
return grino::Value::make_float(loc, result);
}, var_proto);
});
loader.add_native("*.", [](auto args){
float result = 1;
@ -348,7 +325,7 @@ extern "C" void lib_float(grino::Loader& loader)
}
return grino::Value::make_float(loc, result);
}, var_proto);
});
loader.add_native("-.", [](auto args){
grino::Loc loc {"???", 0};
@ -375,7 +352,7 @@ extern "C" void lib_float(grino::Loader& loader)
}
return grino::Value::make_float(loc, result);
}, var_proto);
});
loader.add_native("/.", [](auto args){
grino::Loc loc {"???", 0};
@ -402,7 +379,7 @@ extern "C" void lib_float(grino::Loader& loader)
}
return grino::Value::make_float(loc, result);
}, var_proto);
});
loader.add_native("%.", [](auto args){
grino::Loc loc {"???", 0};
@ -429,7 +406,7 @@ extern "C" void lib_float(grino::Loader& loader)
}
return grino::Value::make_float(loc, result);
}, var_proto);
});
loader.add_native("^.", [](auto args){
grino::Loc loc {"???", 0};
@ -456,18 +433,11 @@ extern "C" void lib_float(grino::Loader& loader)
}
return grino::Value::make_float(loc, result);
}, var_proto);
});
}
extern "C" void lib_cmp(grino::Loader& loader)
{
auto var_proto =
std::make_shared<grino::Prototype>(std::vector<grino::TypeSlot>{
grino::TypeSlot {grino::HINT_CAT_PARAM, grino::TYPE_INT},
grino::TypeSlot {grino::HINT_CAT_PARAM, grino::TYPE_INT},
grino::TypeSlot {grino::HINT_CAT_RETURN, grino::TYPE_BOOL},
});
loader.add_native("<", [](auto args){
if (args[0]->type() == grino::TYPE_INT)
{
@ -485,7 +455,7 @@ extern "C" void lib_cmp(grino::Loader& loader)
}
assert(0);
}, var_proto);
});
loader.add_native("<=", [](auto args){
if (args[0]->type() == grino::TYPE_INT)
@ -504,7 +474,7 @@ extern "C" void lib_cmp(grino::Loader& loader)
}
assert(0);
}, var_proto);
});
loader.add_native(">", [](auto args){
if (args[0]->type() == grino::TYPE_INT)
@ -523,7 +493,7 @@ extern "C" void lib_cmp(grino::Loader& loader)
}
assert(0);
}, var_proto);
});
loader.add_native(">=", [](auto args){
if (args[0]->type() == grino::TYPE_INT)
@ -542,33 +512,21 @@ extern "C" void lib_cmp(grino::Loader& loader)
}
assert(0);
}, var_proto);
});
loader.add_native("ne?", [](auto args){
auto lhs = args[0];
auto rhs = args[1];
return grino::Value::make_bool(args[0]->loc(), !lhs->equals(*rhs));
}, std::make_shared<grino::Prototype>(std::vector<grino::TypeSlot> {{
grino::TypeSlot {grino::HINT_CAT_PARAM,
grino::TYPE_NIL,
grino::HINT_ANY},
grino::TypeSlot {grino::HINT_CAT_PARAM,
grino::TYPE_NIL,
grino::HINT_SAME},
grino::TypeSlot {grino::HINT_CAT_RETURN,
grino::TYPE_BOOL}
}}));
});
}
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());
}, std::make_shared<grino::Prototype>(std::vector<grino::TypeSlot> {{
grino::TypeSlot {grino::HINT_CAT_PARAM, grino::TYPE_BOOL},
grino::TypeSlot {grino::HINT_CAT_RETURN, grino::TYPE_BOOL}
}}));
});
loader.add_static("and", [](auto& compiler, auto node,
auto& program,
@ -598,14 +556,7 @@ extern "C" void lib_bool(grino::Loader& loader)
program.push_instr(grino::OPCODE_LOAD_CONST, addr);
program.set_param(to_end, program.size());
}, std::make_shared<grino::Prototype>(std::vector<grino::TypeSlot> {{
grino::TypeSlot {grino::HINT_CAT_VARIADIC_PARAM,
grino::TYPE_BOOL,
grino::HINT_NONE},
grino::TypeSlot {grino::HINT_CAT_RETURN,
grino::TYPE_BOOL,
grino::HINT_NONE},
}}));
});
loader.add_static("or", [](auto& compiler, auto node,
auto& program, auto& sym){
@ -635,14 +586,7 @@ extern "C" void lib_bool(grino::Loader& loader)
program.push_instr(grino::OPCODE_LOAD_CONST, addr);
program.set_param(to_end, program.size());
}, std::make_shared<grino::Prototype>(std::vector<grino::TypeSlot> {{
grino::TypeSlot {grino::HINT_CAT_VARIADIC_PARAM,
grino::TYPE_BOOL,
grino::HINT_NONE},
grino::TypeSlot {grino::HINT_CAT_RETURN,
grino::TYPE_BOOL,
grino::HINT_NONE},
}}));
});
}
extern "C" void lib_assert(grino::Loader& loader)
@ -661,10 +605,7 @@ extern "C" void lib_assert(grino::Loader& loader)
}
return grino::Value::make_bool(args.front()->loc(), true);
}, std::make_shared<grino::Prototype>(std::vector<grino::TypeSlot> {{
grino::TypeSlot {grino::HINT_CAT_PARAM, grino::TYPE_BOOL},
grino::TypeSlot {grino::HINT_CAT_RETURN, grino::TYPE_NIL}
}}));
});
loader.add_native("assert=", [](auto args){
auto lhs = args.front();
@ -730,7 +671,6 @@ extern "C" void lib(grino::Loader& loader)
lib_collection(loader);
lib_array(loader);
lib_string(loader);
lib_cast(loader);
loader.add_native("dump", [](auto args){
std::string sep;
@ -763,17 +703,7 @@ extern "C" void lib(grino::Loader& loader)
}
program.push_value(grino::Value::make_nil(node->loc()));
}, std::make_shared<grino::Prototype>(std::vector<grino::TypeSlot> {{
grino::TypeSlot {grino::HINT_CAT_PARAM,
grino::TYPE_NIL,
grino::HINT_ANY},
grino::TypeSlot {grino::HINT_CAT_PARAM,
grino::TYPE_NIL,
grino::HINT_SAME},
grino::TypeSlot {grino::HINT_CAT_RETURN,
grino::TYPE_NIL,
grino::HINT_NONE}
}}));
});
loader.add_native("eq?", [](auto args){
auto lhs = args.front();
@ -789,14 +719,5 @@ extern "C" void lib(grino::Loader& loader)
}
return grino::Value::make_bool(args.front()->loc(), true);
}, std::make_shared<grino::Prototype>(std::vector<grino::TypeSlot> {{
grino::TypeSlot {grino::HINT_CAT_PARAM,
grino::TYPE_NIL,
grino::HINT_ANY},
grino::TypeSlot {grino::HINT_CAT_PARAM,
grino::TYPE_NIL,
grino::HINT_SAME},
grino::TypeSlot {grino::HINT_CAT_RETURN,
grino::TYPE_BOOL}
}}));
});
}

View File

@ -1,31 +0,0 @@
#include "src/Loader.hpp"
#include "src/Module.hpp"
extern "C" void lib_io(grino::Loader& loader)
{
auto mod = loader.add_module("io");
mod->loader()->add_native("print", [](auto args){
for (auto arg: args)
{
std::cout << arg->string();
}
return grino::Value::make_nil(grino::Loc {"io"});
});
mod->loader()->add_native("println", [](auto args){
for (auto arg: args)
{
std::cout << arg->string();
}
std::cout << std::endl;
return grino::Value::make_nil(grino::Loc {"io"});
});
mod->loader()->add_native("read", [](auto args){
std::string value;
std::cin >> value;
return grino::Value::make_string(grino::Loc {"io"}, value);
});
}

View File

@ -1,33 +0,0 @@
#include <random>
#include <chrono>
#include "src/Loader.hpp"
#include "src/Module.hpp"
extern "C" void lib_rand(grino::Loader& loader)
{
grino::Loc loc {"core/rand"};
auto mod = loader.add_module("rand");
mod->loader()->add_native("randf", [loc](auto args){
std::mt19937 r;
r.seed(std::chrono::steady_clock::now().time_since_epoch().count());
std::uniform_real_distribution<float> urd(0.0f, 1.0f);
return grino::Value::make_float(loc, urd(r));
});
mod->loader()->add_native("range", [loc](auto args){
std::mt19937 r;
r.seed(std::chrono::steady_clock::now().time_since_epoch().count());
int from = args[0]->as_int();
int to = args[1]->as_int();
std::uniform_int_distribution<int> dist(from, to);
return grino::Value::make_int(loc, dist(r));
});
}

View File

@ -1,10 +0,0 @@
#include "src/Loader.hpp"
#include "io.hpp"
#include "rand.hpp"
extern "C" void lib(grino::Loader& loader)
{
lib_io(loader);
lib_rand(loader);
}

View File

@ -35,8 +35,6 @@ grino_src = shared_library('grino',
'src/Loader.cpp',
'src/Addr.cpp',
'src/Module.cpp',
'src/StaticPass.cpp',
'src/Prototype.cpp',
],
install: true)
pkg = import('pkgconfig')
@ -64,8 +62,6 @@ install_headers(
'src/Loader.hpp',
'src/Addr.hpp',
'src/Module.hpp',
'src/StaticPass.hpp',
'src/Prototype.hpp',
], subdir: 'grino'
)
@ -81,16 +77,6 @@ shared_library('grino_core',
install: true,
install_dir: grino_libdir)
shared_library('grino_std',
sources: [
'lib/std/std.cpp'
],
dependencies: [
grino_dep
],
install: true,
install_dir: grino_libdir)
executable('grino',
sources: [
'src/main.cpp'
@ -105,7 +91,6 @@ executable('grino-tests',
'tests/main.cpp',
'tests/Lexer.cpp',
'tests/Parser.cpp',
'tests/StaticPass.cpp',
],
dependencies: [
grino_dep,

View File

@ -2,7 +2,7 @@
#include "Program.hpp"
#include "Module.hpp"
#include "SymTable.hpp"
#include "opcodes.hpp"
#include "src/opcodes.hpp"
#include "StaticFunction.hpp"
namespace grino
@ -246,11 +246,6 @@ namespace grino
}
}
bool Compiler::has_static_func(std::string name) const
{
return m_statics.find(name) != std::end(m_statics);
}
void Compiler::add_static_func(std::string const& name,
std::shared_ptr<StaticFunction> fun)
{

View File

@ -4,7 +4,7 @@
#include "commons.hpp"
#include "Logger.hpp"
#include "Node.hpp"
#include "mutils.hpp"
#include "src/mutils.hpp"
#include "Addr.hpp"
namespace grino
@ -27,14 +27,6 @@ namespace grino
Program& program,
SymTable& sym);
std::shared_ptr<StaticFunction>
static_func(std::string name) const {
return m_statics.at(name);
}
bool has_static_func(std::string name) const;
void add_static_func(std::string const& name,
std::shared_ptr<StaticFunction> fun);

View File

@ -51,8 +51,4 @@ namespace grino
m_env[addr] = value;
}
void Function::set_prototype(std::shared_ptr<Prototype> prototype)
{
m_prototype = prototype;
}
}

View File

@ -2,7 +2,6 @@
#define grino_FUNCTION_HPP
#include "commons.hpp"
#include "Prototype.hpp"
namespace grino
{
@ -20,7 +19,6 @@ namespace grino
explicit Function(std::shared_ptr<Program> prog, size_t base_addr);
virtual ~Function();
std::shared_ptr<Prototype> prototype() const { return m_prototype; }
size_t base_addr() const { return m_base_addr; }
bool is_native() const;
@ -31,14 +29,11 @@ namespace grino
std::shared_ptr<Value> env(size_t addr) const;
void set_env(size_t addr, std::shared_ptr<Value> value);
void set_prototype(std::shared_ptr<Prototype> prototype);
private:
native_t m_native;
std::shared_ptr<Program> m_prog;
std::unordered_map<size_t, std::shared_ptr<Value>> m_env;
size_t m_base_addr = 0;
std::shared_ptr<Prototype> m_prototype;
};
}

View File

@ -1,5 +1,5 @@
#include "Lexer.hpp"
#include "Node.hpp"
#include "src/Node.hpp"
namespace grino
{

View File

@ -1,5 +1,6 @@
#include "Loader.hpp"
#include "Function.hpp"
#include "src/config.in.hpp"
#include <dlfcn.h>
#include "Lexer.hpp"
#include "Parser.hpp"
@ -43,11 +44,6 @@ namespace grino
return deps;
}
void Loader::add_lib(std::filesystem::path path)
{
m_libs.push_back(path);
}
void Loader::load_libraries()
{
for (auto entry: std::filesystem::directory_iterator(GRINO_LIBDIR))
@ -58,15 +54,6 @@ namespace grino
load_library(entry.path());
}
}
for (auto path: m_libs)
{
if (path.has_extension()
&& path.extension() == ".so")
{
load_library(path);
}
}
}
void Loader::load_library(std::filesystem::path path)
@ -74,7 +61,6 @@ namespace grino
void* handle = dlopen(path.string().c_str(), RTLD_NOW);
typedef void(*libfun)(Loader&);
libfun f = (libfun) dlsym(handle, "lib");
assert(f);
f(*this);
}
@ -102,23 +88,8 @@ namespace grino
m_sym_table.declare_object(loc, name, addr, 0);
}
void Loader::add_native(std::string const& name,
native_t native,
std::shared_ptr<Prototype> prototype)
void Loader::add_static(std::string const& name, static_fun_t fun)
{
size_t addr = m_vm.heap_size();
grino::Loc loc {"natives/" + name, 0};
auto val = grino::Value::make_native_function(loc, native);
val->as_function()->set_prototype(prototype);
m_vm.set_heap(addr, val);
m_sym_table.declare_function(loc, name, addr, 0, prototype);
}
void Loader::add_static(std::string const& name,
static_fun_t fun,
std::shared_ptr<Prototype> prototype)
{
auto fn = std::make_shared<StaticFunction>(fun, prototype);
m_compiler.add_static_func(name, fn);
m_compiler.add_static_func(name, std::make_shared<StaticFunction>(fun));
}
}

View File

@ -20,27 +20,17 @@ namespace grino
std::vector<std::filesystem::path>
dependencies(std::shared_ptr<Node> node);
void add_lib(std::filesystem::path path);
void load_libraries();
void load_library(std::filesystem::path path);
std::shared_ptr<Module> add_module(std::string const& name);
void add_native(std::string const& name, native_t native);
void add_native(std::string const& name,
native_t native,
std::shared_ptr<Prototype> prototype);
void add_static(std::string const& name,
static_fun_t fun,
std::shared_ptr<Prototype> prototype);
void add_static(std::string const& name, static_fun_t fun);
private:
VM& m_vm;
Compiler& m_compiler;
SymTable& m_sym_table;
std::vector<std::filesystem::path> m_libs;
};
}

View File

@ -8,7 +8,7 @@ namespace grino
class Loc
{
public:
explicit Loc(std::filesystem::path path, int line=0);
explicit Loc(std::filesystem::path path, int line);
virtual ~Loc();
std::filesystem::path path() const { return m_path; }

View File

@ -2,7 +2,7 @@
#define grino_LOGGER_HPP
#include "commons.hpp"
#include "mutils.hpp"
#include "src/mutils.hpp"
#include "Loc.hpp"
#define LOG_TYPE(G) \

View File

@ -3,7 +3,6 @@
#include "Lexer.hpp"
#include "Parser.hpp"
#include "Compiler.hpp"
#include "StaticPass.hpp"
namespace grino
{
@ -45,9 +44,6 @@ namespace grino
m_loader = std::make_shared<Loader>(*m_vm, *m_compiler, *m_sym_table);
m_loader->load_libraries();
StaticPass static_pass {m_logger, *m_compiler, *m_sym_table};
static_pass.check(ast);
m_compiler->compile(ast, *m_program, *m_sym_table);
m_vm->run();

View File

@ -1,6 +1,6 @@
#include "Parser.hpp"
#include "Node.hpp"
#include "mutils.hpp"
#include "src/Node.hpp"
#include "src/mutils.hpp"
namespace grino
{
@ -118,6 +118,7 @@ namespace grino
std::shared_ptr<Node> Parser::parse_expr()
{
if (type_is({NODE_IDENT, NODE_NS}))
{
return parse_ns();
@ -334,17 +335,7 @@ namespace grino
consume(NODE_DECL);
consume(NODE_IMPORT);
auto ident = consume(NODE_IDENT);
std::shared_ptr<Node> val;
if (type_is(NODE_STRING))
{
val = consume(NODE_STRING);
}
else
{
val = make_node(NODE_STRING, "'" + ident->repr() + "'");
}
auto val = consume(NODE_STRING);
consume(NODE_CPAR);
auto node = make_node(NODE_VARDECL);
@ -356,4 +347,5 @@ namespace grino
return node;
}
}

View File

@ -3,7 +3,7 @@
#include "commons.hpp"
#include "Lexer.hpp"
#include "mutils.hpp"
#include "src/mutils.hpp"
namespace grino
{

View File

@ -1,5 +1,5 @@
#include "Program.hpp"
#include "opcodes.hpp"
#include "src/opcodes.hpp"
namespace grino
{

View File

@ -1,65 +0,0 @@
#include "Prototype.hpp"
namespace grino
{
/*explicit*/ Prototype::Prototype(std::vector<TypeSlot> const& types)
: m_types { types }
{
}
/*explicit*/ Prototype::Prototype(std::vector<TypeType> const& params,
TypeType ret)
{
for (auto ty: params)
{
m_types.push_back(TypeSlot {
HINT_CAT_PARAM,
ty,
HINT_NONE
});
}
m_types.push_back(TypeSlot {
HINT_CAT_RETURN,
ret,
HINT_NONE
});
}
/*virtual*/ Prototype::~Prototype()
{
}
TypeType Prototype::type(size_t index) const
{
assert(index < size());
return m_types[index].type;
}
HintType Prototype::hint(size_t index) const
{
assert(index < size());
return m_types[index].hint;
}
HintCatType Prototype::category(size_t index) const
{
assert(index < size());
return m_types[index].category;
}
std::vector<TypeSlot> Prototype::filter(HintCatType category) const
{
std::vector<TypeSlot> result;
for (size_t i=0; i<size(); i++)
{
if (m_types[i].category == category)
{
result.push_back(m_types[i]);
}
}
return result;
}
}

View File

@ -1,48 +0,0 @@
#ifndef grino_PROTOTYPE_HPP
#define grino_PROTOTYPE_HPP
#include "commons.hpp"
#include "types.hpp"
#define HINTS(G) \
G(HINT_NONE), \
G(HINT_ANY), \
G(HINT_SAME),
#define HINTS_CATEGORY(G) \
G(HINT_CAT_PARAM), \
G(HINT_CAT_VARIADIC_PARAM), \
G(HINT_CAT_RETURN)
namespace grino
{
GRINO_ENUM(Hint, HINTS);
GRINO_ENUM(HintCat, HINTS_CATEGORY);
struct TypeSlot {
HintCatType category;
TypeType type;
HintType hint = HINT_NONE;
};
class Prototype
{
public:
explicit Prototype(std::vector<TypeSlot> const& types);
explicit Prototype(std::vector<TypeType> const& params, TypeType ret);
virtual ~Prototype();
size_t size() const { return m_types.size(); }
TypeType type(size_t index) const;
HintType hint(size_t index) const;
HintCatType category(size_t index) const;
std::vector<TypeSlot> filter(HintCatType category) const;
private:
std::vector<TypeSlot> m_types;
};
}
#endif

View File

@ -3,10 +3,8 @@
namespace grino
{
/*explicit*/ StaticFunction::StaticFunction(static_fun_t fun,
std::shared_ptr<Prototype> proto)
/*explicit*/ StaticFunction::StaticFunction(static_fun_t fun)
: m_fun { fun }
, m_prototype { proto }
{
}

View File

@ -6,7 +6,6 @@
#include "Node.hpp"
#include "Program.hpp"
#include "SymTable.hpp"
#include "Prototype.hpp"
namespace grino
{
@ -19,16 +18,13 @@ namespace grino
class StaticFunction
{
public:
explicit StaticFunction(static_fun_t fun, std::shared_ptr<Prototype> proto);
explicit StaticFunction(static_fun_t fun);
virtual ~StaticFunction();
std::shared_ptr<Prototype> prototype() const { return m_prototype; }
void call(Compiler& compiler, node_t node, prog_t prog, sym_t sym);
private:
static_fun_t m_fun;
std::shared_ptr<Prototype> m_prototype;
};
}

View File

@ -1,183 +0,0 @@
#include "StaticPass.hpp"
#include "src/Prototype.hpp"
#include "StaticFunction.hpp"
namespace grino
{
/*explicit*/ StaticPass::StaticPass(Logger& logger,
Compiler& compiler,
SymTable& sym)
: m_logger { logger }
, m_compiler { compiler }
, m_sym { sym }
{
}
/*virtual*/ StaticPass::~StaticPass()
{
}
TypeType StaticPass::check(std::shared_ptr<Node> node)
{
switch (node->type())
{
case NODE_ARRAY:
case NODE_BLOCK: {
for (size_t i=0; i<node->size(); i++)
{
check(node->child(i).lock());
}
return TYPE_NIL;
} break;
case NODE_MODULE: {
for (size_t i=0; i<node->size(); i++)
{
check(node->child(i).lock());
}
return TYPE_MODULE;
} break;
case NODE_INT: {
return TYPE_INT;
} break;
case NODE_FLOAT: {
return TYPE_FLOAT;
} break;
case NODE_BOOL: {
return TYPE_BOOL;
} break;
case NODE_STRING: {
return TYPE_STRING;
} break;
case NODE_IDENT: {
std::string ident = node->repr();
return m_types[ident];
} break;
case NODE_LAMBDA: {
return TYPE_FUNCTION;
} break;
case NODE_IMPORT: {
return TYPE_MODULE;
} break;
case NODE_VARDECL: {
std::string ident = node->child(0).lock()->repr();
auto res = check(node->child(1).lock());
m_types[ident] = res;
return res;
} break;
case NODE_FUNCALL: {
std::string ident = node->child(0).lock()->repr();
std::shared_ptr<Prototype> proto;
auto entry = m_sym.find_no_scope(ident);
if (entry && entry->prototype)
{
proto = entry->prototype;
}
else if (m_compiler.has_static_func(ident))
{
proto = m_compiler.static_func(ident)->prototype();
}
if (proto)
{
auto params = proto->filter(HINT_CAT_PARAM);
auto rets = proto->filter(HINT_CAT_RETURN);
auto var_params = proto->filter(HINT_CAT_VARIADIC_PARAM);
if (!var_params.empty())
{
TypeType ty = var_params.back().type;
for (size_t i=1; i<node->size(); i++)
{
auto param_ty = check(node->child(i).lock());
if (param_ty != ty
&& var_params.back().hint != HINT_ANY)
{
error(ty, param_ty, node->loc());
}
}
return rets[0].type;
}
if (params.size() != node->size() - 1)
{
std::stringstream ss;
ss << "arity mismatch, expected '"
<< params.size()
<< "' got '"
<< (node->size() - 1)
<< "'";
std::cout << node->string() << std::endl;
m_logger
.log<static_error>(LOG_ERROR, node->loc(), ss.str());
}
std::vector<TypeType> ty;
for (size_t i=1; i<node->size(); i++)
{
TypeType param_ty = check(node->child(i).lock());
ty.push_back(param_ty);
if (proto->hint(i - 1) == HINT_ANY)
{
continue;
}
bool same_err = (i > 1 && proto->hint(i - 1) == HINT_SAME)
&& ty.back() != ty.at(ty.size() - 2);
bool normal_err = proto->hint(i - 1) == HINT_NONE
&& param_ty != proto->type(i - 1);
if (same_err || normal_err)
{
error(proto->type(i - 1), param_ty, node->loc());
}
}
assert(rets.size() > 0);
return rets[0].type;
}
return TYPE_NIL;
} break;
default:
break;
}
std::cerr << "cannot check node "
<< NodeTypeStr[node->type()] << std::endl;
abort();
}
void StaticPass::error(TypeType lhs, TypeType rhs, Loc const& loc)
{
std::stringstream ss;
ss << "type mismatch, expected '"
<< GRINO_TRIM(TypeTypeStr[lhs], "TYPE_")
<< "', got '"
<< GRINO_TRIM(TypeTypeStr[rhs], "TYPE_")
<< "'";
m_logger
.log<static_error>(LOG_ERROR, loc, ss.str());
}
}

View File

@ -1,32 +0,0 @@
#ifndef grino_STATICPASS_HPP
#define grino_STATICPASS_HPP
#include "commons.hpp"
#include "Node.hpp"
#include "Logger.hpp"
#include "SymTable.hpp"
#include "Compiler.hpp"
namespace grino
{
GRINO_ERROR(static_error);
class StaticPass
{
public:
explicit StaticPass(Logger& logger, Compiler& compiler, SymTable& sym);
virtual ~StaticPass();
TypeType check(std::shared_ptr<Node> node);
private:
Logger& m_logger;
Compiler& m_compiler;
SymTable& m_sym;
std::unordered_map<std::string, TypeType> m_types;
void error(TypeType lhs, TypeType rhs, Loc const& loc);
};
}
#endif

View File

@ -27,6 +27,7 @@ namespace grino
entry.name = name;
entry.is_object = false;
entry.scope = scope;
m_entries.push_back(entry);
}
@ -39,16 +40,6 @@ namespace grino
m_entries.back().is_object = true;
}
void SymTable::declare_function(Loc const& loc,
std::string const& name,
size_t addr,
size_t scope,
std::shared_ptr<Prototype> prototype)
{
declare_object(loc, name, addr, scope);
m_entries.back().prototype = prototype;
}
std::optional<SymEntry> SymTable::find(std::string const& name, size_t scope)
{
std::optional<SymEntry> entry;

View File

@ -3,8 +3,6 @@
#include "commons.hpp"
#include "Logger.hpp"
#include "types.hpp"
#include "Prototype.hpp"
namespace grino
{
@ -13,7 +11,6 @@ namespace grino
bool is_object; /* object are on the heap instead of the stack */
size_t addr; /* address on the heap if object, local address otherwise */
size_t scope;
std::shared_ptr<Prototype> prototype; /* only used by functions */
};
GRINO_ERROR(symbolic_error);
@ -30,9 +27,6 @@ namespace grino
void declare_object(Loc const& loc, std::string const& name, size_t addr,
size_t scope);
void declare_function(Loc const& loc, std::string const& name, size_t addr,
size_t scope, std::shared_ptr<Prototype> prototype);
std::optional<SymEntry> find(std::string const& name, size_t scope);
std::optional<SymEntry> find_no_scope(std::string const& name);

View File

@ -1,7 +1,7 @@
#include "VM.hpp"
#include "Value.hpp"
#include "src/Value.hpp"
#include "Module.hpp"
#include "opcodes.hpp"
#include "src/opcodes.hpp"
#include <optional>
namespace grino
@ -212,6 +212,7 @@ namespace grino
{
if (fun)
{
std::cout << "store INIT" << std::endl;
fun->set_env(itr->first,
Value::make_copy(itr->second->loc(),
itr->second));

View File

@ -1,6 +1,6 @@
#include "Value.hpp"
#include "Program.hpp"
#include "types.hpp"
#include "src/types.hpp"
#include "Module.hpp"
namespace grino
@ -37,28 +37,23 @@ namespace grino
}
/*static*/
std::shared_ptr<Value>
Value::make_native_function(Loc const& loc,
native_t val,
std::shared_ptr<Prototype> prototype)
std::shared_ptr<Value> Value::make_native_function(Loc const& loc,
native_t val)
{
auto value = std::make_shared<Value>(loc);
value->m_type = TYPE_FUNCTION;
value->m_function_val = std::make_shared<Function>(val);
value->m_function_val->set_prototype(prototype);
return value;
}
/*static*/ std::shared_ptr<Value>
Value::make_function(Loc const& loc,
std::shared_ptr<Program> val,
size_t base_addr,
std::shared_ptr<Prototype> prototype)
size_t base_addr)
{
auto value = std::make_shared<Value>(loc);
value->m_type = TYPE_FUNCTION;
value->m_function_val = std::make_shared<Function>(val, base_addr);
value->m_function_val->set_prototype(prototype);
return value;
}
@ -135,16 +130,6 @@ namespace grino
return value;
}
/*static*/
std::shared_ptr<Value> Value::make_user_data(Loc const& loc,
void* val)
{
auto value = std::make_shared<Value>(loc);
value->m_type = TYPE_PROGRAM;
value->m_user_data_val = val;
return value;
}
std::shared_ptr<Program> Value::as_program() const
{
return m_program_val;
@ -167,7 +152,6 @@ namespace grino
case TYPE_FUNCTION: return "<function>";
case TYPE_REF: return "&" + std::to_string(*m_ref_val);
case TYPE_PROGRAM: return "<program>";
case TYPE_USER_DATA: return "<user data>";
case TYPE_MODULE: return "<module " + m_module_val->name() + ">";
case TYPE_ARRAY: {
std::stringstream ss;
@ -204,7 +188,6 @@ namespace grino
case TYPE_REF: return *m_ref_val == *other.m_ref_val;
case TYPE_PROGRAM: return false;
case TYPE_MODULE: return false;
case TYPE_USER_DATA: return m_user_data_val == other.m_user_data_val;
default:
std::cerr << "cannot compare equality with value "

View File

@ -20,17 +20,11 @@ namespace grino
static std::shared_ptr<Value> make_bool(Loc const& loc, bool val);
static std::shared_ptr<Value> make_int(Loc const& loc, int val);
static std::shared_ptr<Value> make_float(Loc const& loc, float val);
static std::shared_ptr<Value>
make_native_function(Loc const& loc,
native_t val,
std::shared_ptr<Prototype> prototype=nullptr);
static std::shared_ptr<Value>
make_function(Loc const& loc,
std::shared_ptr<Program> val,
size_t base_addr,
std::shared_ptr<Prototype> prototype=nullptr);
static std::shared_ptr<Value> make_native_function(Loc const& loc,
native_t val);
static std::shared_ptr<Value> make_function(Loc const& loc,
std::shared_ptr<Program> val,
size_t base_addr);
static std::shared_ptr<Value> make_ref(Loc const& loc,
size_t val);
@ -50,9 +44,6 @@ namespace grino
static std::shared_ptr<Value> make_module(Loc const& loc,
std::shared_ptr<Module> val);
static std::shared_ptr<Value> make_user_data(Loc const& loc,
void* val);
explicit Value(Loc const& loc);
virtual ~Value() = default;
@ -68,7 +59,6 @@ namespace grino
val_array_t const& as_array() const { return *m_array_val; }
std::string const& as_string() const { return *m_string_val; }
std::shared_ptr<Module> as_module() const;
void* as_user_data() const { return m_user_data_val; }
std::string string() const;
bool equals(Value const& other) const;
@ -85,7 +75,6 @@ namespace grino
std::optional<val_array_t> m_array_val;
std::optional<std::string> m_string_val;
std::shared_ptr<Module> m_module_val;
void* m_user_data_val = nullptr;
};
}

View File

@ -8,14 +8,12 @@
#include "Program.hpp"
#include "VM.hpp"
#include "Logger.hpp"
#include "SymTable.hpp"
#include "src/SymTable.hpp"
#include "Loader.hpp"
#include "Addr.hpp"
#include "StaticPass.hpp"
void run(char* const source_name,
std::vector<std::filesystem::path> const& libs,
bool debug_mode)
void run(char* const source_name, bool debug_mode)
{
std::string source;
{
@ -53,16 +51,12 @@ void run(char* const source_name,
grino::Compiler compiler {logger, addr};
grino::Loader loader {vm, compiler, sym_table};
for (auto p: libs)
{
loader.add_lib(p);
}
loader.load_libraries();
grino::StaticPass static_pass {logger, compiler, sym_table};
static_pass.check(ast);
for (auto dep: loader.dependencies(ast))
{
// TODO: import them
}
compiler.compile(ast, program, sym_table);
@ -84,80 +78,55 @@ void run(char* const source_name,
int main(int argc, char** argv)
{
bool debug_mode = false;
std::vector<std::filesystem::path> libs;
while (true)
static struct option options[] = {
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'v'},
{"debug", no_argument, 0, 'd'},
{0, 0, 0, 0}
};
int option_index = 0;
int c = getopt_long(argc, argv, "hvd", options, &option_index);
switch (c)
{
static struct option options[] = {
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'v'},
{"debug", no_argument, 0, 'd'},
{"lib", no_argument, 0, 'l'},
{0, 0, 0, 0}
};
case 'h': {
std::cout << "Usage: grino [OPTION]... source" << std::endl;
std::cout << "OPTIONS:" << std::endl;
std::cout << "\t" << "-d, --debug, "
<< "activate debug mode" << std::endl;
int option_index = 0;
std::cout << "\t" << "-h, --help, "
<< "show this message" << std::endl;
std::cout << "\t" << "-v, --version, "
<< "show grino version" << std::endl;
exit(0);
} break;
int c = getopt_long(argc, argv, "hvdl:", options, &option_index);
case 'v': {
std::cout << "grino version: " << GRINO_VERSION << std::endl;
std::cout << "License: " << "GPLv3 or later (see LICENSE)"<< std::endl;
exit(0);
} break;
if (c == -1)
{
break;
}
switch (c)
{
case 'h': {
std::cout << "Usage: grino [OPTION]... source" << std::endl;
std::cout << "OPTIONS:" << std::endl;
std::cout << "\t" << "-d, --debug, "
<< "activate debug mode" << std::endl;
std::cout << "\t" << "-h, --help, "
<< "show this message" << std::endl;
std::cout << "\t" << "-v, --version, "
<< "show grino version" << std::endl;
exit(0);
} break;
case 'v': {
std::cout << "grino version: " << GRINO_VERSION << std::endl;
std::cout << "License: " << "GPLv3 or later (see LICENSE)"<< std::endl;
exit(0);
} break;
case 'd': {
debug_mode = true;
} break;
case 'l': {
auto path = std::filesystem::path("/usr/lib")
/ std::filesystem::path("lib" + std::string(optarg) + ".so");
if (std::filesystem::is_regular_file(path))
{
libs.push_back(path);
}
else
{
std::cerr << "W: cannot find lib " << path << std::endl;
}
} break;
}
case 'd': {
debug_mode = true;
} break;
}
if (optind < argc)
{
if (debug_mode)
{
run(argv[optind], libs, debug_mode);
run(argv[optind], debug_mode);
}
else
{
try
{
run(argv[optind], libs, debug_mode);
run(argv[optind], debug_mode);
}
catch(std::exception const& err)
{

View File

@ -2,7 +2,7 @@
#define grino_OPCODES_HPP
#include "commons.hpp"
#include "mutils.hpp"
#include "src/mutils.hpp"
#define OPCODES(G) \
G(OPCODE_LOAD_CONST), \

View File

@ -13,8 +13,7 @@
G(TYPE_FLOAT), \
G(TYPE_ARRAY), \
G(TYPE_STRING), \
G(TYPE_MODULE), \
G(TYPE_USER_DATA)
G(TYPE_MODULE)
namespace grino

View File

@ -116,10 +116,4 @@ TEST_CASE_METHOD(ParserTest, "Parser_import")
test_parse("MODULE(VARDECL(IDENT[bim],IMPORT(STRING['hello'])))",
"($ @bim 'hello')");
test_parse("MODULE(VARDECL(IDENT[bim],IMPORT(STRING['bim'])))",
"($ @ bim )");
test_parse("MODULE(VARDECL(IDENT[hello_world],IMPORT(STRING['hello_world'])))",
" ( $ @ hello_world )");
}

View File

@ -1,379 +0,0 @@
#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);
});
}