From f393d6d7f7f7ee1da75d9c2aaa39c05e4a22a74c Mon Sep 17 00:00:00 2001 From: bog Date: Fri, 15 Sep 2023 20:36:16 +0200 Subject: [PATCH] FIX: type checking and modules. FIX: closure capture on non copyable objects. --- src/Loader.cpp | 12 ++++++++++- src/Loader.hpp | 4 ++++ src/Module.hpp | 1 + src/Program.hpp | 1 + src/StaticPass.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++-- src/StaticPass.hpp | 1 + src/SymTable.cpp | 8 +++++++ src/SymTable.hpp | 6 ++++++ src/VM.cpp | 29 ++++++++++++++++++-------- src/Value.cpp | 8 +++++-- src/Value.hpp | 4 ++-- src/main.cpp | 1 - 12 files changed, 110 insertions(+), 17 deletions(-) diff --git a/src/Loader.cpp b/src/Loader.cpp index b34d80f..306fbd7 100644 --- a/src/Loader.cpp +++ b/src/Loader.cpp @@ -88,11 +88,21 @@ namespace grino size_t addr = m_vm.heap_size(); m_vm.set_heap(addr, val); - m_sym_table.declare_object(loc, name, addr, 0); + m_sym_table.declare_module(loc, name, addr, 0, mod->sym_table()); return mod; } + void Loader::add_var(std::string const& name, + std::shared_ptr val) + { + size_t addr = m_vm.heap_size(); + grino::Loc loc {"natives/" + name, 0}; + m_vm.set_heap(addr, val); + + m_sym_table.declare_object(loc, name, addr, 0); + } + void Loader::add_native(std::string const& name, native_t native, std::shared_ptr prototype) diff --git a/src/Loader.hpp b/src/Loader.hpp index d5793e1..f9194e8 100644 --- a/src/Loader.hpp +++ b/src/Loader.hpp @@ -26,6 +26,10 @@ namespace grino void load_library(std::filesystem::path path); std::shared_ptr add_module(std::string const& name); + + void add_var(std::string const& name, + std::shared_ptr val); + void add_native(std::string const& name, native_t native, std::shared_ptr prototype); diff --git a/src/Module.hpp b/src/Module.hpp index a433b6b..420a136 100644 --- a/src/Module.hpp +++ b/src/Module.hpp @@ -18,6 +18,7 @@ namespace grino std::string name() const { return m_name; } void load(); void load_native(); + std::shared_ptr sym_table() const { return m_sym_table; } std::shared_ptr loader() const { return m_loader; } std::shared_ptr find(std::string const& name); std::shared_ptr from_heap(size_t addr); diff --git a/src/Program.hpp b/src/Program.hpp index 2c8bb22..62e21cf 100644 --- a/src/Program.hpp +++ b/src/Program.hpp @@ -20,6 +20,7 @@ namespace grino size_t size() const { return m_instrs.size(); } + size_t constant_size() const { return m_constants.size(); } Instr get(size_t index) const; diff --git a/src/StaticPass.cpp b/src/StaticPass.cpp index f0142b9..46feb93 100644 --- a/src/StaticPass.cpp +++ b/src/StaticPass.cpp @@ -1,7 +1,9 @@ #include "StaticPass.hpp" #include "src/Prototype.hpp" #include "StaticFunction.hpp" +#include "Module.hpp" #include "src/types.hpp" +#include namespace grino { @@ -83,6 +85,13 @@ namespace grino std::string ident = node->child(0).lock()->repr(); auto res = check(node->child(1).lock()); m_types[ident] = res; + + if (node->child(1).lock()->type() == NODE_IMPORT) + { + auto name = node->child(1).lock()->child(0).lock()->repr(); + name = name.substr(1, name.size() - 2); + m_mod_names[ident] = name; + } return res; } break; @@ -99,6 +108,43 @@ namespace grino { proto = m_compiler.static_func(ident)->prototype(); } + else if (node->child(0).lock()->type() == NODE_NS) + { + std::string mod_name + = node->child(0).lock()->child(0).lock()->repr(); + + std::string var_name + = node->child(0).lock()->child(1).lock()->repr(); + + auto mod_entry = m_sym.find_no_scope(mod_name); + std::shared_ptr mod_sym; + + if (!mod_entry) + { + std::filesystem::path name = mod_name; + + auto full_name = std::filesystem::path(m_mod_names[mod_name]); + + if (!full_name.has_extension()) + { + full_name += ".gri"; + } + + auto mod = std::make_shared(full_name); + mod->load(); + + auto entry = mod->sym_table()->find_no_scope(var_name); + assert(entry); + proto = entry->prototype; + } + else + { + mod_sym = mod_entry->mod; + + auto entry = mod_sym->find_no_scope(var_name); + proto = entry->prototype; + } + } if (proto) { @@ -139,7 +185,7 @@ namespace grino << "' got '" << (node->size() - 1) << "'"; - std::cout << node->string() << std::endl; + m_logger .log(LOG_ERROR, node->loc(), ss.str()); } @@ -158,7 +204,9 @@ namespace grino } bool same_err = (i > 1 && proto->hint(i - 1) == HINT_SAME) - && ty.back().type != ty.at(ty.size() - 2).type; + && ty.back().type != ty.at(ty.size() - 2).type + && ty.back().hint != HINT_ANY + && ty.at(ty.size() - 2).hint != HINT_ANY; if (same_err) { diff --git a/src/StaticPass.hpp b/src/StaticPass.hpp index e98a760..6c202f9 100644 --- a/src/StaticPass.hpp +++ b/src/StaticPass.hpp @@ -23,6 +23,7 @@ namespace grino Logger& m_logger; Compiler& m_compiler; SymTable& m_sym; + std::unordered_map m_mod_names; std::unordered_map m_types; void error(TypeType lhs, TypeType rhs, std::shared_ptr node); diff --git a/src/SymTable.cpp b/src/SymTable.cpp index f875983..6e68ade 100644 --- a/src/SymTable.cpp +++ b/src/SymTable.cpp @@ -49,6 +49,14 @@ namespace grino m_entries.back().prototype = prototype; } + void SymTable::declare_module(Loc const& loc, std::string const& name, + size_t addr, + size_t scope, std::shared_ptr sym) + { + declare_object(loc, name, addr, scope); + m_entries.back().mod = sym; + } + std::optional SymTable::find(std::string const& name, size_t scope) { std::optional entry; diff --git a/src/SymTable.hpp b/src/SymTable.hpp index dadb067..2c32481 100644 --- a/src/SymTable.hpp +++ b/src/SymTable.hpp @@ -8,12 +8,15 @@ namespace grino { + class SymTable; + struct SymEntry { std::string name; 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; /* only used by functions */ + std::shared_ptr mod; /* only used by modules */ }; GRINO_ERROR(symbolic_error); @@ -33,6 +36,9 @@ namespace grino void declare_function(Loc const& loc, std::string const& name, size_t addr, size_t scope, std::shared_ptr prototype); + void declare_module(Loc const& loc, std::string const& name, size_t addr, + size_t scope, std::shared_ptr sym); + std::optional find(std::string const& name, size_t scope); std::optional find_no_scope(std::string const& name); diff --git a/src/VM.cpp b/src/VM.cpp index b0a4108..f3c7aef 100644 --- a/src/VM.cpp +++ b/src/VM.cpp @@ -130,9 +130,13 @@ namespace grino { for (auto const& entry: m_frames.at(m_frames.size() - 1).locals) { - fun_val->as_function() - ->set_env(entry.first, - Value::make_copy(fun_val->loc(), entry.second)); + auto cpy = Value::try_copy(fun_val->loc(), entry.second); + + if (cpy) + { + fun_val->as_function() + ->set_env(entry.first, cpy); + } } } @@ -198,8 +202,12 @@ namespace grino if (fun && fun->has_env(addr)) { - fun->set_env(addr, Value::make_copy(value->loc(), value)); - found = true; + auto cpy = Value::try_copy(value->loc(), value); + if (cpy) + { + fun->set_env(addr, cpy); + found = true; + } } else { @@ -212,9 +220,12 @@ namespace grino { if (fun) { - fun->set_env(itr->first, - Value::make_copy(itr->second->loc(), - itr->second)); + auto cpy = Value::try_copy(itr->second->loc(), + itr->second); + if (cpy) + { + fun->set_env(itr->first, cpy); + } } found = true; @@ -265,7 +276,7 @@ namespace grino if (fun) { fun->set_env(itr2->first, - Value::make_copy(itr2->second->loc(), + Value::try_copy(itr2->second->loc(), itr2->second)); } diff --git a/src/Value.cpp b/src/Value.cpp index 736e7c4..8b31730 100644 --- a/src/Value.cpp +++ b/src/Value.cpp @@ -81,8 +81,8 @@ namespace grino } /*static*/ - std::shared_ptr Value::make_copy(Loc const& loc, - std::shared_ptr val) + std::shared_ptr Value::try_copy(Loc const& loc, + std::shared_ptr val) { switch (val->type()) { @@ -98,6 +98,10 @@ namespace grino return Value::make_ref(loc, val->as_ref()); } break; + case TYPE_PROGRAM: { + return nullptr; + } break; + default: std::cerr << "cannot copy unknown value " << TypeTypeStr[val->type()] << std::endl; diff --git a/src/Value.hpp b/src/Value.hpp index d34ae0c..1bd6172 100644 --- a/src/Value.hpp +++ b/src/Value.hpp @@ -38,8 +38,8 @@ namespace grino static std::shared_ptr make_program(Loc const& loc, std::shared_ptr val); - static std::shared_ptr make_copy(Loc const& loc, - std::shared_ptr val); + static std::shared_ptr try_copy(Loc const& loc, + std::shared_ptr val); static std::shared_ptr make_array(Loc const& loc, val_array_t val); diff --git a/src/main.cpp b/src/main.cpp index 88d3873..33399ef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,7 +60,6 @@ void run(char* const source_name, } loader.load_libraries(); - grino::StaticPass static_pass {logger, compiler, sym_table}; static_pass.check(ast);