diff --git a/include/lang/common.hh b/include/lang/common.hh index 6d193c8..b60780c 100644 --- a/include/lang/common.hh +++ b/include/lang/common.hh @@ -1,5 +1,41 @@ #pragma once +#include + +namespace ppc::lang { + struct namespace_name_t : public std::vector { + using base = std::vector; + + int compare(const namespace_name_t &other) const; + + bool operator==(const namespace_name_t &other) const { return compare(other) == 0; } + bool operator!=(const namespace_name_t &other) const { return compare(other) != 0; } + bool operator<(const namespace_name_t &other) const { return compare(other) < 0; } + bool operator<=(const namespace_name_t &other) const { return compare(other) <= 0; } + bool operator>(const namespace_name_t &other) const { return compare(other) > 0; } + bool operator>=(const namespace_name_t &other) const { return compare(other) >= 0; } + + operator std::string() const { return to_string(); } + std::string to_string() const; + + namespace_name_t() { } + namespace_name_t(std::initializer_list segments): base(segments.begin(), segments.end()) { } + }; +} + +template <> +struct std::hash { + std::size_t operator()(const ppc::lang::namespace_name_t& k) const { + size_t res = 0; + + for (auto &el : k) { + res ^= std::hash()(el); + } + + return res; + } +}; + #include "utils/message.hh" #include "utils/location.hh" @@ -29,25 +65,6 @@ namespace ppc::lang { slocated_t() { } }; - struct namespace_name_t : public std::vector { - using base = std::vector; - - int compare(const namespace_name_t &other) const; - - bool operator==(const namespace_name_t &other) const { return compare(other) == 0; } - bool operator!=(const namespace_name_t &other) const { return compare(other) != 0; } - bool operator<(const namespace_name_t &other) const { return compare(other) < 0; } - bool operator<=(const namespace_name_t &other) const { return compare(other) <= 0; } - bool operator>(const namespace_name_t &other) const { return compare(other) > 0; } - bool operator>=(const namespace_name_t &other) const { return compare(other) >= 0; } - - operator std::string() const { return to_string(); } - std::string to_string() const; - - namespace_name_t() { } - namespace_name_t(std::initializer_list segments): base(segments.begin(), segments.end()) { } - }; - struct loc_namespace_name_t : public std::vector> { using base = std::vector>; @@ -74,4 +91,4 @@ namespace ppc::lang { messages::msg_stack_t ms; return is_identifier_valid(ms, { }, name); } -} +} \ No newline at end of file diff --git a/include/lang/module.hh b/include/lang/module.hh new file mode 100644 index 0000000..8205604 --- /dev/null +++ b/include/lang/module.hh @@ -0,0 +1,162 @@ +#include +#include +#include "lang/common.hh" + +namespace ppc::lang { + struct type_t { + namespace_name_t name; + size_t ptr_n; + }; + + struct statement_t { + private: + enum kind_t { + CALL, + STACK, + RETURN, + } kind; + union val_t { + namespace_name_t *call; + int64_t stack; + } val; + + ~statement_t(); + + statement_t(kind_t kind, val_t val) { + this->kind = kind; + this->val = val; + } + statement_t(kind_t kind) { + this->kind = kind; + } + + public: + bool is_call() const { return kind == CALL; } + bool is_stack() const { return kind == STACK; } + bool is_return() const { return kind == RETURN; } + + auto &call() const { + if (!is_call()) throw (std::string)"Statement is not a call."; + return val.call; + } + auto stack() const { + if (!is_call()) throw (std::string)"Statement is not a stack."; + return val.stack; + } + + static statement_t call(const namespace_name_t &func); + static statement_t stack(int64_t stack); + static statement_t ret(); + }; + + struct field_t { + type_t type; + }; + struct struct_t { + std::unordered_map fields; + }; + struct function_t { + std::unordered_map args; + type_t type; + + std::string get_signature(); + }; + + struct definition_t { + private: + enum { + FUNCTION, + STRUCT, + FIELD, + } kind; + union { + field_t *field; + struct_t *str; + function_t *func; + } val; + + public: + ~definition_t(); + definition_t(field_t val); + definition_t(struct_t val); + definition_t(function_t val); + definition_t(const definition_t &other); + + bool is_func() const { return kind == FUNCTION; } + bool is_struct() const { return kind == STRUCT; } + bool is_field() const { return kind == FIELD; } + + function_t &get_func(); + struct_t &get_struct(); + field_t &get_field(); + + const function_t &get_func() const { return ((definition_t&)*this).get_func(); } + const struct_t &get_struct() const { return ((definition_t&)*this).get_struct(); } + const field_t &get_field() const { return ((definition_t&)*this).get_field(); } + }; + + struct module_t { + private: + using fields_t = std::unordered_map; + using structs_t = std::unordered_map; + using funcs_t = std::unordered_map; + struct resolve_res_t { + namespace_name_t name; + definition_t def; + }; + public: + fields_t fields; + structs_t structs; + funcs_t funcs; + + const definition_t &def(namespace_name_t name); + void add_def(namespace_name_t name, const definition_t &def) { + if (def.is_field()) fields.emplace(name, def.get_field()); + if (def.is_func()) funcs.emplace(name, def.get_func()); + if (def.is_struct()) structs.emplace(name, def.get_struct()); + } + bool exists(namespace_name_t name) { + return + fields.find(name) != fields.end() || + structs.find(name) != structs.end() || + funcs.find(name) != funcs.end(); + } + }; + + template + struct resolve_res_t { + namespace_name_t name; + T value; + }; + + + bool resolve_name( + const std::vector &names, const std::set &imports, + const namespace_name_t &name, namespace_name_t &res + ); + + template + bool resolve_name_map( + const MapT &defs, const std::set &imports, + const namespace_name_t &name, namespace_name_t &res + ) { + std::vector names; + for (auto &it : defs) { + const namespace_name_t &val = it.first; + names.push_back(val); + } + return resolve_name(names, imports, name, res); + } + + template + bool resolve( + const MapT &defs, const std::set &imports, + const namespace_name_t &name, typename MapT::iterator &res + ) { + if (resolve_name_map(defs, imports, name, res.name)) { + res.value = defs.find(res.name)->second; + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/compiler/treeifier/ast/parsers/group.cc b/src/compiler/treeifier/ast/parsers/group.cc index 4cad173..bbe0f75 100644 --- a/src/compiler/treeifier/ast/parsers/group.cc +++ b/src/compiler/treeifier/ast/parsers/group.cc @@ -1,3 +1,4 @@ +#include "lang/module.hh" #include "compiler/treeifier/ast.hh" #include "compiler/treeifier/tokenizer.hh" #include "compiler/treeifier/ast/helper.hh" @@ -18,28 +19,7 @@ static bool read_nmsp(ast_ctx_t &ctx, size_t &i, lang::loc_namespace_name_t &nam name = conv::map_to_nmsp(res); return h.submit(false); } -template -static bool resolve_nmsp(ast_ctx_t &ctx, const lang::namespace_name_t &name, T begin, T end, lang::namespace_name_t &actual_name) { - for (auto it = begin; it != end; it++) { - const namespace_name_t &curr = it->first; - if (curr == name) { - actual_name = name; - return true; - } - } - for (const auto &import : ctx.imports) { - auto new_name = name; - new_name.insert(new_name.begin(), import.begin(), import.end()); - for (auto it = begin; it != end; it++) { - const namespace_name_t &curr = it->first; - if (curr == new_name) { - actual_name = name; - return true; - } - } - } - return false; -} + group_t &group_t::insert(const std::string &name, parser_t parser, const std::string &relative_to, bool after) { if (parsers.find(name) != parsers.end()) { @@ -94,10 +74,18 @@ bool group_t::operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const { if (h.ended()) return false; + std::set names; + + for (auto &import : ctx.imports) names.insert(import.strip_location()); + loc_namespace_name_t name; if (read_nmsp(ctx, h.i, name)) { namespace_name_t actual; - if (resolve_nmsp(ctx, name.strip_location(), named_parsers.begin(), named_parsers.end(), actual)) { + + if (resolve_name_map( + named_parsers, names, + name.strip_location(), actual + )) { auto parser = parsers.find(this->named_parsers.find(actual)->second); out["$_name"] = parser->first; if (h.parse(parser->second, out)) return h.submit(false); diff --git a/src/lang/module.cc b/src/lang/module.cc new file mode 100644 index 0000000..b14c4b1 --- /dev/null +++ b/src/lang/module.cc @@ -0,0 +1,88 @@ +#include "lang/module.hh" + +using namespace std::string_literals; +using namespace ppc::lang; + +definition_t::definition_t(function_t val) { + this->kind = FUNCTION; + this->val.func = new auto(val); +} +definition_t::definition_t(struct_t val) { + this->kind = STRUCT; + this->val.str = new auto(val); +} +definition_t::definition_t(field_t val) { + this->kind = FIELD; + this->val.field = new auto(val); +} +definition_t::definition_t(const definition_t &val) { + this->kind = val.kind; + switch (val.kind) { + case STRUCT: + this->val.str = new auto(*val.val.str); + break; + case FUNCTION: + this->val.func = new auto(*val.val.func); + break; + case FIELD: + this->val.field = new auto(*val.val.field); + break; + } +} + +definition_t::~definition_t() { + switch (this->kind) { + case FUNCTION: delete this->val.func; break; + case FIELD: delete this->val.field; break; + case STRUCT: delete this->val.str; break; + } +} + + +function_t &definition_t::get_func() { + if (!this->is_func()) throw "Definition is not a function."s; + return *this->val.func; +} +struct_t &definition_t::get_struct() { + if (!this->is_struct()) throw "Definition is not a struct."s; + return *this->val.str; +} +field_t &definition_t::get_field() { + if (!this->is_field()) throw "Definition is not a field."s; + return *this->val.field; +} + + + +statement_t statement_t::call(const namespace_name_t &func) { + return { CALL, { .call = new auto(func) }}; +} +statement_t statement_t::stack(int64_t stack) { + return { STACK, { .stack = stack }}; +} +statement_t statement_t::ret() { + return { RETURN }; +} + +bool ppc::lang::resolve_name( + const std::vector &names, const std::set &imports, + const namespace_name_t &name, namespace_name_t &res +) { + for (auto &curr : names) { + if (curr == name) { + res = curr; + return true; + } + } + for (auto &import : imports) { + auto new_name = name; + new_name.insert(new_name.begin(), import.begin(), import.end()); + for (auto &curr : names) { + if (curr == new_name) { + res = curr; + return true; + } + } + } + return false; +} \ No newline at end of file