ADD: import local modules.
parent
25bd1f28f6
commit
078877aa26
|
@ -11,6 +11,9 @@ EXPR ::=
|
||||||
| LAMBDA
|
| LAMBDA
|
||||||
| BLOCK
|
| BLOCK
|
||||||
| ARRAY
|
| ARRAY
|
||||||
|
| IMPORT
|
||||||
|
| SHORT_IMPORT
|
||||||
|
| NS
|
||||||
VARDECL ::= opar decl ident EXPR cpar
|
VARDECL ::= opar decl ident EXPR cpar
|
||||||
FUNDECL ::= opar decl opar ident* cpar BODY cpar
|
FUNDECL ::= opar decl opar ident* cpar BODY cpar
|
||||||
FUNCALL ::= opar EXPR EXPR* cpar
|
FUNCALL ::= opar EXPR EXPR* cpar
|
||||||
|
@ -19,3 +22,6 @@ PARAMS ::= ident*
|
||||||
BODY ::= EXPR*
|
BODY ::= EXPR*
|
||||||
BLOCK ::= opar colon EXPR* cpar
|
BLOCK ::= opar colon EXPR* cpar
|
||||||
ARRAY ::= osquare EXPR* csquare
|
ARRAY ::= osquare EXPR* csquare
|
||||||
|
IMPORT ::= opar import string cpar
|
||||||
|
SHORT_IMPORT ::= opar decl import ident string cpar
|
||||||
|
NS ::= ident ns ident
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
($ @m './mod2.gri')
|
||||||
|
|
||||||
|
(assert= 32 (m::twice 16))
|
||||||
|
(assert= 3.14159 m::pi)
|
|
@ -0,0 +1,2 @@
|
||||||
|
($ (twice n) (* n 2))
|
||||||
|
($ pi 3.14159)
|
|
@ -32,6 +32,7 @@ grino_src = static_library('grino',
|
||||||
'src/SymTable.cpp',
|
'src/SymTable.cpp',
|
||||||
'src/Loader.cpp',
|
'src/Loader.cpp',
|
||||||
'src/Addr.cpp',
|
'src/Addr.cpp',
|
||||||
|
'src/Module.cpp',
|
||||||
])
|
])
|
||||||
|
|
||||||
grino_dep = declare_dependency(link_with: grino_src)
|
grino_dep = declare_dependency(link_with: grino_src)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "Compiler.hpp"
|
#include "Compiler.hpp"
|
||||||
#include "Program.hpp"
|
#include "Program.hpp"
|
||||||
|
#include "Module.hpp"
|
||||||
#include "SymTable.hpp"
|
#include "SymTable.hpp"
|
||||||
#include "src/opcodes.hpp"
|
#include "src/opcodes.hpp"
|
||||||
#include "StaticFunction.hpp"
|
#include "StaticFunction.hpp"
|
||||||
|
@ -31,6 +32,25 @@ namespace grino
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case NODE_IMPORT: {
|
||||||
|
std::string name = node->child(0).lock()->repr();
|
||||||
|
name = name.substr(1, name.size() - 2);
|
||||||
|
|
||||||
|
program.push_value(Value::make_string(node->loc(), name));
|
||||||
|
program.push_instr(OPCODE_MK_MOD);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_NS: {
|
||||||
|
auto mod = node->child(0).lock();
|
||||||
|
auto var = node->child(1).lock()->repr();
|
||||||
|
|
||||||
|
compile(mod, program, sym);
|
||||||
|
|
||||||
|
program.push_value(Value::make_string(node->loc(), var));
|
||||||
|
|
||||||
|
program.push_instr(OPCODE_LOAD_NS);
|
||||||
|
} break;
|
||||||
|
|
||||||
case NODE_BODY: {
|
case NODE_BODY: {
|
||||||
for (size_t i=0; i<node->size(); i++)
|
for (size_t i=0; i<node->size(); i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,8 @@ namespace grino
|
||||||
: m_logger { logger }
|
: m_logger { logger }
|
||||||
, m_loc {source_path, 1}
|
, m_loc {source_path, 1}
|
||||||
{
|
{
|
||||||
|
add_text(NODE_NS, "::", false);
|
||||||
|
add_text(NODE_IMPORT, "@", false);
|
||||||
add_text(NODE_COLON, ":", false);
|
add_text(NODE_COLON, ":", false);
|
||||||
add_text(NODE_OSQUARE, "[", false);
|
add_text(NODE_OSQUARE, "[", false);
|
||||||
add_text(NODE_CSQUARE, "]", false);
|
add_text(NODE_CSQUARE, "]", false);
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include "Function.hpp"
|
#include "Function.hpp"
|
||||||
#include "src/config.in.hpp"
|
#include "src/config.in.hpp"
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include "Lexer.hpp"
|
||||||
|
#include "Parser.hpp"
|
||||||
|
|
||||||
namespace grino
|
namespace grino
|
||||||
{
|
{
|
||||||
|
@ -16,6 +18,51 @@ namespace grino
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::filesystem::path>
|
||||||
|
Loader::dependencies(std::shared_ptr<Node> node)
|
||||||
|
{
|
||||||
|
std::vector<std::filesystem::path> deps;
|
||||||
|
|
||||||
|
std::function<void(std::shared_ptr<Node>)>
|
||||||
|
f = [&](std::shared_ptr<Node> n){
|
||||||
|
if (n->type() == NODE_IMPORT)
|
||||||
|
{
|
||||||
|
std::string str = n->child(0).lock()->repr();
|
||||||
|
deps.push_back(str.substr(1, str.size() - 2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (size_t i=0; i<n->size(); i++)
|
||||||
|
{
|
||||||
|
f(n->child(i).lock());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
f(node);
|
||||||
|
return deps;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Node>
|
||||||
|
Loader::user_module(std::filesystem::path path)
|
||||||
|
{
|
||||||
|
std::string source;
|
||||||
|
{
|
||||||
|
std::ifstream file { path };
|
||||||
|
assert(file);
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
while (std::getline(file, line))
|
||||||
|
{ source += line + (file.eof() ? "" : "\n"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger logger;
|
||||||
|
Lexer lexer {logger, path};
|
||||||
|
Parser parser {logger, lexer};
|
||||||
|
|
||||||
|
return parser.parse(source);
|
||||||
|
}
|
||||||
|
|
||||||
void Loader::load_libraries()
|
void Loader::load_libraries()
|
||||||
{
|
{
|
||||||
for (auto entry: std::filesystem::directory_iterator(GRINO_LIBDIR))
|
for (auto entry: std::filesystem::directory_iterator(GRINO_LIBDIR))
|
||||||
|
|
|
@ -17,6 +17,11 @@ namespace grino
|
||||||
|
|
||||||
VM& vm() const { return m_vm; }
|
VM& vm() const { return m_vm; }
|
||||||
|
|
||||||
|
std::vector<std::filesystem::path>
|
||||||
|
dependencies(std::shared_ptr<Node> node);
|
||||||
|
|
||||||
|
std::shared_ptr<Node> user_module(std::filesystem::path path);
|
||||||
|
|
||||||
void load_libraries();
|
void load_libraries();
|
||||||
void load_library(std::filesystem::path path);
|
void load_library(std::filesystem::path path);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
#include "Module.hpp"
|
||||||
|
#include "Loader.hpp"
|
||||||
|
#include "Lexer.hpp"
|
||||||
|
#include "Parser.hpp"
|
||||||
|
#include "Compiler.hpp"
|
||||||
|
|
||||||
|
namespace grino
|
||||||
|
{
|
||||||
|
/*explicit*/ Module::Module(std::filesystem::path path,
|
||||||
|
std::string const& name /*= "" */)
|
||||||
|
: m_path { path }
|
||||||
|
, m_name { name == "" ? m_path.filename().stem().string() : name }
|
||||||
|
, m_program { std::make_shared<Program>()}
|
||||||
|
, m_sym_table { std::make_shared<SymTable>(m_logger)}
|
||||||
|
, m_vm { std::make_shared<VM>(m_logger, *m_program)}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Module::~Module()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::load()
|
||||||
|
{
|
||||||
|
std::string source;
|
||||||
|
{
|
||||||
|
std::ifstream file { m_path };
|
||||||
|
assert(file);
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
while (std::getline(file, line))
|
||||||
|
{ source += line + (file.eof() ? "" : "\n"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
Lexer lexer {m_logger, m_path};
|
||||||
|
Parser parser {m_logger, lexer};
|
||||||
|
|
||||||
|
auto ast = parser.parse(source);
|
||||||
|
Addr addr;
|
||||||
|
Compiler compiler {m_logger, addr};
|
||||||
|
m_vm = std::make_shared<VM>(m_logger, *m_program);
|
||||||
|
|
||||||
|
Loader loader {*m_vm, compiler, *m_sym_table};
|
||||||
|
loader.load_libraries();
|
||||||
|
|
||||||
|
compiler.compile(ast, *m_program, *m_sym_table);
|
||||||
|
|
||||||
|
m_vm->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Value> Module::find(std::string const& name)
|
||||||
|
{
|
||||||
|
auto entry = m_sym_table->find_no_scope(name);
|
||||||
|
assert(entry);
|
||||||
|
assert(entry->is_object == false);
|
||||||
|
|
||||||
|
return m_vm->local(entry->addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Value> Module::from_heap(size_t addr)
|
||||||
|
{
|
||||||
|
return m_vm->heap(addr);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef grino_MODULE_HPP
|
||||||
|
#define grino_MODULE_HPP
|
||||||
|
|
||||||
|
#include "commons.hpp"
|
||||||
|
#include "Program.hpp"
|
||||||
|
#include "SymTable.hpp"
|
||||||
|
#include "VM.hpp"
|
||||||
|
|
||||||
|
namespace grino
|
||||||
|
{
|
||||||
|
class Module
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Module(std::filesystem::path path, std::string const& name="");
|
||||||
|
virtual ~Module();
|
||||||
|
|
||||||
|
std::string name() const { return m_name; }
|
||||||
|
void load();
|
||||||
|
|
||||||
|
std::shared_ptr<Value> find(std::string const& name);
|
||||||
|
std::shared_ptr<Value> from_heap(size_t addr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::filesystem::path m_path;
|
||||||
|
std::string m_name;
|
||||||
|
Logger m_logger;
|
||||||
|
std::shared_ptr<Program> m_program;
|
||||||
|
std::shared_ptr<SymTable> m_sym_table;
|
||||||
|
std::shared_ptr<VM> m_vm;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -23,7 +23,9 @@
|
||||||
G(NODE_BLOCK), \
|
G(NODE_BLOCK), \
|
||||||
G(NODE_ARRAY), \
|
G(NODE_ARRAY), \
|
||||||
G(NODE_FLOAT), \
|
G(NODE_FLOAT), \
|
||||||
G(NODE_STRING)
|
G(NODE_STRING), \
|
||||||
|
G(NODE_IMPORT), \
|
||||||
|
G(NODE_NS)
|
||||||
|
|
||||||
namespace grino
|
namespace grino
|
||||||
{
|
{
|
||||||
|
|
|
@ -118,11 +118,27 @@ namespace grino
|
||||||
|
|
||||||
std::shared_ptr<Node> Parser::parse_expr()
|
std::shared_ptr<Node> Parser::parse_expr()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (type_is({NODE_IDENT, NODE_NS}))
|
||||||
|
{
|
||||||
|
return parse_ns();
|
||||||
|
}
|
||||||
|
|
||||||
if (type_is(NODE_OSQUARE))
|
if (type_is(NODE_OSQUARE))
|
||||||
{
|
{
|
||||||
return parse_array();
|
return parse_array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type_is({NODE_OPAR, NODE_DECL, NODE_IMPORT}))
|
||||||
|
{
|
||||||
|
return parse_short_import();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type_is({NODE_OPAR, NODE_IMPORT}))
|
||||||
|
{
|
||||||
|
return parse_import();
|
||||||
|
}
|
||||||
|
|
||||||
if (type_is({NODE_OPAR, NODE_COLON}))
|
if (type_is({NODE_OPAR, NODE_COLON}))
|
||||||
{
|
{
|
||||||
return parse_block();
|
return parse_block();
|
||||||
|
@ -294,4 +310,42 @@ namespace grino
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Node> Parser::parse_import()
|
||||||
|
{
|
||||||
|
consume(NODE_OPAR);
|
||||||
|
auto node = consume(NODE_IMPORT);
|
||||||
|
node->add_child(consume(NODE_STRING));
|
||||||
|
consume(NODE_CPAR);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Node> Parser::parse_ns()
|
||||||
|
{
|
||||||
|
auto node = make_node(NODE_NS);
|
||||||
|
node->add_child(consume(NODE_IDENT));
|
||||||
|
consume(NODE_NS);
|
||||||
|
node->add_child(consume(NODE_IDENT));
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Node> Parser::parse_short_import()
|
||||||
|
{
|
||||||
|
consume(NODE_OPAR);
|
||||||
|
consume(NODE_DECL);
|
||||||
|
consume(NODE_IMPORT);
|
||||||
|
auto ident = consume(NODE_IDENT);
|
||||||
|
auto val = consume(NODE_STRING);
|
||||||
|
consume(NODE_CPAR);
|
||||||
|
|
||||||
|
auto node = make_node(NODE_VARDECL);
|
||||||
|
node->add_child(ident);
|
||||||
|
|
||||||
|
auto imp = make_node(NODE_IMPORT);
|
||||||
|
imp->add_child(val);
|
||||||
|
node->add_child(imp);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,9 @@ namespace grino
|
||||||
std::shared_ptr<Node> parse_body();
|
std::shared_ptr<Node> parse_body();
|
||||||
std::shared_ptr<Node> parse_block();
|
std::shared_ptr<Node> parse_block();
|
||||||
std::shared_ptr<Node> parse_array();
|
std::shared_ptr<Node> parse_array();
|
||||||
|
std::shared_ptr<Node> parse_import();
|
||||||
|
std::shared_ptr<Node> parse_short_import();
|
||||||
|
std::shared_ptr<Node> parse_ns();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,22 @@ namespace grino
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<SymEntry>
|
||||||
|
SymTable::find_no_scope(std::string const& name)
|
||||||
|
{
|
||||||
|
std::optional<SymEntry> entry;
|
||||||
|
|
||||||
|
for (size_t i=0; i<m_entries.size(); i++)
|
||||||
|
{
|
||||||
|
if (m_entries[i].name == name)
|
||||||
|
{
|
||||||
|
entry = m_entries[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
void SymTable::purge(size_t scope)
|
void SymTable::purge(size_t scope)
|
||||||
{
|
{
|
||||||
auto itr = std::remove_if(std::begin(m_entries),
|
auto itr = std::remove_if(std::begin(m_entries),
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace grino
|
||||||
size_t scope);
|
size_t scope);
|
||||||
|
|
||||||
std::optional<SymEntry> find(std::string const& name, size_t scope);
|
std::optional<SymEntry> find(std::string const& name, size_t scope);
|
||||||
|
std::optional<SymEntry> find_no_scope(std::string const& name);
|
||||||
|
|
||||||
void purge(size_t scope);
|
void purge(size_t scope);
|
||||||
|
|
||||||
|
|
40
src/VM.cpp
40
src/VM.cpp
|
@ -1,5 +1,6 @@
|
||||||
#include "VM.hpp"
|
#include "VM.hpp"
|
||||||
#include "src/Value.hpp"
|
#include "src/Value.hpp"
|
||||||
|
#include "Module.hpp"
|
||||||
#include "src/opcodes.hpp"
|
#include "src/opcodes.hpp"
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
@ -32,6 +33,45 @@ namespace grino
|
||||||
|
|
||||||
switch (instr.opcode)
|
switch (instr.opcode)
|
||||||
{
|
{
|
||||||
|
case OPCODE_MK_MOD: {
|
||||||
|
auto path = std::filesystem::path(program()
|
||||||
|
.constant(pop())
|
||||||
|
->as_string());
|
||||||
|
|
||||||
|
auto mod = std::make_shared<Module>(path);
|
||||||
|
mod->load();
|
||||||
|
size_t addr = heap_size();
|
||||||
|
|
||||||
|
Loc loc {"???", 0};
|
||||||
|
set_heap(addr, Value::make_module(loc, mod));
|
||||||
|
|
||||||
|
auto ref = Value::make_ref(loc, addr);
|
||||||
|
push(program().push_constant(ref));
|
||||||
|
|
||||||
|
m_pc++;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case OPCODE_LOAD_NS: {
|
||||||
|
std::string var = program().constant(pop())->as_string();
|
||||||
|
size_t ref_val = program().constant(pop())->as_ref();
|
||||||
|
auto mod = heap(ref_val);
|
||||||
|
|
||||||
|
auto val = mod->as_module()->find(var);
|
||||||
|
|
||||||
|
if (val->type() == TYPE_REF)
|
||||||
|
{
|
||||||
|
size_t heap_addr = val->as_ref();
|
||||||
|
auto heap_val = mod->as_module()->from_heap(heap_addr);
|
||||||
|
size_t addr = heap_size();
|
||||||
|
set_heap(addr, heap_val);
|
||||||
|
val = Value::make_ref(heap_val->loc(), addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
push(program().push_constant(val));
|
||||||
|
|
||||||
|
m_pc++;
|
||||||
|
} break;
|
||||||
|
|
||||||
case OPCODE_MK_ARRAY: {
|
case OPCODE_MK_ARRAY: {
|
||||||
size_t const N = *instr.param;
|
size_t const N = *instr.param;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "Value.hpp"
|
#include "Value.hpp"
|
||||||
#include "Program.hpp"
|
#include "Program.hpp"
|
||||||
#include "src/types.hpp"
|
#include "src/types.hpp"
|
||||||
|
#include "Module.hpp"
|
||||||
|
|
||||||
namespace grino
|
namespace grino
|
||||||
{
|
{
|
||||||
|
@ -84,6 +85,10 @@ namespace grino
|
||||||
return Value::make_int(loc, val->as_int());
|
return Value::make_int(loc, val->as_int());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case TYPE_STRING: {
|
||||||
|
return Value::make_string(loc, val->as_string());
|
||||||
|
} break;
|
||||||
|
|
||||||
case TYPE_REF: {
|
case TYPE_REF: {
|
||||||
return Value::make_ref(loc, val->as_ref());
|
return Value::make_ref(loc, val->as_ref());
|
||||||
} break;
|
} break;
|
||||||
|
@ -115,11 +120,26 @@ namespace grino
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*static*/
|
||||||
|
std::shared_ptr<Value> Value::make_module(Loc const& loc,
|
||||||
|
std::shared_ptr<Module> val)
|
||||||
|
{
|
||||||
|
auto value = std::make_shared<Value>(loc);
|
||||||
|
value->m_type = TYPE_MODULE;
|
||||||
|
value->m_module_val = val;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<Program> Value::as_program() const
|
std::shared_ptr<Program> Value::as_program() const
|
||||||
{
|
{
|
||||||
return m_program_val;
|
return m_program_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Module> Value::as_module() const
|
||||||
|
{
|
||||||
|
return m_module_val;
|
||||||
|
}
|
||||||
|
|
||||||
std::string Value::string() const
|
std::string Value::string() const
|
||||||
{
|
{
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
|
@ -132,6 +152,7 @@ namespace grino
|
||||||
case TYPE_FUNCTION: return "<function>";
|
case TYPE_FUNCTION: return "<function>";
|
||||||
case TYPE_REF: return "&" + std::to_string(*m_ref_val);
|
case TYPE_REF: return "&" + std::to_string(*m_ref_val);
|
||||||
case TYPE_PROGRAM: return "<program>";
|
case TYPE_PROGRAM: return "<program>";
|
||||||
|
case TYPE_MODULE: return "<module " + m_module_val->name() + ">";
|
||||||
case TYPE_ARRAY: {
|
case TYPE_ARRAY: {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "[";
|
ss << "[";
|
||||||
|
@ -166,6 +187,7 @@ namespace grino
|
||||||
return std::fabs(*m_float_val - *other.m_float_val) < FLOAT_APPROX;
|
return std::fabs(*m_float_val - *other.m_float_val) < FLOAT_APPROX;
|
||||||
case TYPE_REF: return *m_ref_val == *other.m_ref_val;
|
case TYPE_REF: return *m_ref_val == *other.m_ref_val;
|
||||||
case TYPE_PROGRAM: return false;
|
case TYPE_PROGRAM: return false;
|
||||||
|
case TYPE_MODULE: return false;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
std::cerr << "cannot compare equality with value "
|
std::cerr << "cannot compare equality with value "
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
namespace grino
|
namespace grino
|
||||||
{
|
{
|
||||||
class Program;
|
class Program;
|
||||||
|
class Module;
|
||||||
|
|
||||||
using val_array_t = std::vector<std::shared_ptr<Value>>;
|
using val_array_t = std::vector<std::shared_ptr<Value>>;
|
||||||
|
|
||||||
|
@ -40,6 +41,9 @@ namespace grino
|
||||||
static std::shared_ptr<Value> make_string(Loc const& loc,
|
static std::shared_ptr<Value> make_string(Loc const& loc,
|
||||||
std::string const& val);
|
std::string const& val);
|
||||||
|
|
||||||
|
static std::shared_ptr<Value> make_module(Loc const& loc,
|
||||||
|
std::shared_ptr<Module> val);
|
||||||
|
|
||||||
explicit Value(Loc const& loc);
|
explicit Value(Loc const& loc);
|
||||||
virtual ~Value() = default;
|
virtual ~Value() = default;
|
||||||
|
|
||||||
|
@ -54,6 +58,7 @@ namespace grino
|
||||||
val_array_t& as_array() { return *m_array_val; }
|
val_array_t& as_array() { return *m_array_val; }
|
||||||
val_array_t const& as_array() const { return *m_array_val; }
|
val_array_t const& as_array() const { return *m_array_val; }
|
||||||
std::string const& as_string() const { return *m_string_val; }
|
std::string const& as_string() const { return *m_string_val; }
|
||||||
|
std::shared_ptr<Module> as_module() const;
|
||||||
|
|
||||||
std::string string() const;
|
std::string string() const;
|
||||||
bool equals(Value const& other) const;
|
bool equals(Value const& other) const;
|
||||||
|
@ -69,6 +74,7 @@ namespace grino
|
||||||
std::optional<size_t> m_ref_val;
|
std::optional<size_t> m_ref_val;
|
||||||
std::optional<val_array_t> m_array_val;
|
std::optional<val_array_t> m_array_val;
|
||||||
std::optional<std::string> m_string_val;
|
std::optional<std::string> m_string_val;
|
||||||
|
std::shared_ptr<Module> m_module_val;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
22
src/main.cpp
22
src/main.cpp
|
@ -12,11 +12,18 @@
|
||||||
#include "Loader.hpp"
|
#include "Loader.hpp"
|
||||||
#include "Addr.hpp"
|
#include "Addr.hpp"
|
||||||
|
|
||||||
void run(char** argv, bool debug_mode)
|
|
||||||
|
void run(char* const source_name, bool debug_mode)
|
||||||
{
|
{
|
||||||
std::string source;
|
std::string source;
|
||||||
{
|
{
|
||||||
std::ifstream file { argv[optind] };
|
if (!std::filesystem::exists(source_name))
|
||||||
|
{
|
||||||
|
std::cerr << "file " << source_name << " doesnt exists" << std::endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream file { source_name };
|
||||||
assert(file);
|
assert(file);
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
|
@ -25,7 +32,7 @@ void run(char** argv, bool debug_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
grino::Logger logger;
|
grino::Logger logger;
|
||||||
grino::Lexer lexer {logger, argv[optind]};
|
grino::Lexer lexer {logger, source_name};
|
||||||
grino::Parser parser {logger, lexer};
|
grino::Parser parser {logger, lexer};
|
||||||
|
|
||||||
auto ast = parser.parse(source);
|
auto ast = parser.parse(source);
|
||||||
|
@ -46,6 +53,11 @@ void run(char** argv, bool debug_mode)
|
||||||
grino::Loader loader {vm, compiler, sym_table};
|
grino::Loader loader {vm, compiler, sym_table};
|
||||||
loader.load_libraries();
|
loader.load_libraries();
|
||||||
|
|
||||||
|
for (auto dep: loader.dependencies(ast))
|
||||||
|
{
|
||||||
|
// TODO: import them
|
||||||
|
}
|
||||||
|
|
||||||
compiler.compile(ast, program, sym_table);
|
compiler.compile(ast, program, sym_table);
|
||||||
|
|
||||||
if (debug_mode)
|
if (debug_mode)
|
||||||
|
@ -108,13 +120,13 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
if (debug_mode)
|
if (debug_mode)
|
||||||
{
|
{
|
||||||
run(argv, debug_mode);
|
run(argv[optind], debug_mode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
run(argv, debug_mode);
|
run(argv[optind], debug_mode);
|
||||||
}
|
}
|
||||||
catch(std::exception const& err)
|
catch(std::exception const& err)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
G(OPCODE_NOT), \
|
G(OPCODE_NOT), \
|
||||||
G(OPCODE_RET), \
|
G(OPCODE_RET), \
|
||||||
G(OPCODE_MK_FUN), \
|
G(OPCODE_MK_FUN), \
|
||||||
G(OPCODE_MK_ARRAY),
|
G(OPCODE_MK_ARRAY), \
|
||||||
|
G(OPCODE_MK_MOD), \
|
||||||
|
G(OPCODE_LOAD_NS),
|
||||||
|
|
||||||
namespace grino
|
namespace grino
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
G(TYPE_PROGRAM), \
|
G(TYPE_PROGRAM), \
|
||||||
G(TYPE_FLOAT), \
|
G(TYPE_FLOAT), \
|
||||||
G(TYPE_ARRAY), \
|
G(TYPE_ARRAY), \
|
||||||
G(TYPE_STRING)
|
G(TYPE_STRING), \
|
||||||
|
G(TYPE_MODULE)
|
||||||
|
|
||||||
|
|
||||||
namespace grino
|
namespace grino
|
||||||
|
|
|
@ -129,3 +129,13 @@ TEST_CASE_METHOD(LexerTest, "Lexer_strings")
|
||||||
test_next(lexer, "STRING[''bim'']");
|
test_next(lexer, "STRING[''bim'']");
|
||||||
test_end(lexer);
|
test_end(lexer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(LexerTest, "Lexer_import")
|
||||||
|
{
|
||||||
|
grino::Lexer lexer {m_logger, "tests/lexer"};
|
||||||
|
|
||||||
|
lexer.scan(" @ :: ");
|
||||||
|
test_next(lexer, "IMPORT");
|
||||||
|
test_next(lexer, "NS");
|
||||||
|
test_end(lexer);
|
||||||
|
}
|
||||||
|
|
|
@ -105,3 +105,15 @@ TEST_CASE_METHOD(ParserTest, "Parser_string")
|
||||||
test_parse("MODULE(BLOCK(ARRAY(STRING['bim !'],FLOAT[28.5],IDENT[salut])))",
|
test_parse("MODULE(BLOCK(ARRAY(STRING['bim !'],FLOAT[28.5],IDENT[salut])))",
|
||||||
"(: ['bim !' 28.5 salut] )");
|
"(: ['bim !' 28.5 salut] )");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(ParserTest, "Parser_import")
|
||||||
|
{
|
||||||
|
test_parse("MODULE(IMPORT(STRING['./salut']))",
|
||||||
|
"(@ './salut')");
|
||||||
|
|
||||||
|
test_parse("MODULE(NS(IDENT[hello],IDENT[world]))",
|
||||||
|
" hello::world ");
|
||||||
|
|
||||||
|
test_parse("MODULE(VARDECL(IDENT[bim],IMPORT(STRING['hello'])))",
|
||||||
|
"($ @bim 'hello')");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue