From 904361b5a00c6cb46845c135d8eff0f8d7653ffd Mon Sep 17 00:00:00 2001 From: harrand Date: Sun, 12 May 2024 02:28:56 +0100 Subject: [PATCH] [cpp] implement semal::output::combine --- cpp/src/error.hpp | 4 +++- cpp/src/semal.cpp | 23 +++++++++++++++++++++++ cpp/src/semal.hpp | 12 +++++++++--- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/cpp/src/error.hpp b/cpp/src/error.hpp index 831eefb..6b39675 100644 --- a/cpp/src/error.hpp +++ b/cpp/src/error.hpp @@ -10,6 +10,7 @@ enum class error_code lex, parse, type, + semal, _count }; @@ -20,7 +21,8 @@ constexpr std::array error_names "badargs", "lex", "parse", - "type" + "type", + "semantic analysis" }; #endif // PSYC_ERROR_HPP \ No newline at end of file diff --git a/cpp/src/semal.cpp b/cpp/src/semal.cpp index 7b2cd71..f0297d3 100644 --- a/cpp/src/semal.cpp +++ b/cpp/src/semal.cpp @@ -1,10 +1,33 @@ #include "semal.hpp" +#include "diag.hpp" namespace semal { + const srcloc& context::location() const + { + return tree->get(this->path).meta; + } + void output::combine(const output& rhs) { // add functions, global variables, structs etc... to *this + for(const auto& [name, fn] : rhs.functions) + { + diag::assert_that(!this->functions.contains(name), error_code::semal, "at: {}: duplicate definition of function \"{}\" (previously defined at: {})", this->functions.at(name).ctx.location().to_string(), fn.name, fn.ctx.location().to_string()); + this->functions[name] = fn; + } + + for(const auto& [name, gvar] : rhs.global_variables) + { + diag::assert_that(!this->global_variables.contains(name), error_code::semal, "at: {}: duplicate definition of global variable \"{}\" (previously defined at: {})", this->functions.at(name).ctx.location().to_string(), gvar.name, gvar.ctx.location().to_string()); + this->global_variables[name] = gvar; + } + + for(const auto& [name, structdata] : rhs.struct_decls) + { + diag::assert_that(!this->struct_decls.contains(name), error_code::semal, "at: {}: duplicate definition of struct \"{}\" (previously defined at: {})", this->functions.at(name).ctx.location().to_string(), structdata.ty.name, structdata.ctx.location().to_string()); + this->struct_decls[name] = structdata; + } } output analyse_predecl(const ast& tree) diff --git a/cpp/src/semal.hpp b/cpp/src/semal.hpp index 8d4e092..84fc97c 100644 --- a/cpp/src/semal.hpp +++ b/cpp/src/semal.hpp @@ -7,11 +7,17 @@ namespace semal { + struct context + { + const ast* tree; + ast::path_t path; + const srcloc& location() const; + }; struct local_variable_t { type ty; std::string name; - ast::path_t context; + context ctx; // codegen may want to track extra data. however, semal doesnt care about any of this. mutable void* userdata = nullptr; }; @@ -21,7 +27,7 @@ namespace semal type return_ty; std::string name; std::vector params = {}; - ast::path_t context; + context ctx; bool is_method = false; // codegen may want to track extra data. however, semal doesnt care about any of this. mutable void* userdata = nullptr; @@ -30,7 +36,7 @@ namespace semal struct struct_t { struct_type ty; - ast::path_t context; + context ctx; std::unordered_map methods = {}; // codegen may want to track extra data. however, semal doesnt care about any of this. mutable void* userdata = nullptr;