diff --git a/include/type.hpp b/include/type.hpp index b0e6b04d..91782684 100644 --- a/include/type.hpp +++ b/include/type.hpp @@ -186,8 +186,8 @@ struct Field { class RecordType : public Type { public: /// @return The type id. - virtual std::string id() - const noexcept = 0; // // NOLINT(readability-identifier-naming) + virtual std::string id() // NOLINT(readability-identifier-naming) + const noexcept = 0; /// @brief Checks if `id` is a member of the record type. virtual bool IsMember(const std::string& id) const noexcept = 0; /// @return The type of a member in struct or union. The unknown type if the @@ -203,8 +203,8 @@ class StructType : public RecordType { StructType(std::string id, std::vector> fields) : id_{std::move(id)}, fields_{std::move(fields)} {} - std::string id() - const noexcept override; // NOLINT(readability-identifier-naming) + std::string id() // NOLINT(readability-identifier-naming) + const noexcept override; bool IsMember(const std::string& id) const noexcept override; std::unique_ptr MemberType( const std::string& id) const noexcept override; @@ -230,8 +230,8 @@ class UnionType : public RecordType { UnionType(std::string id, std::vector> fields) : id_{std::move(id)}, fields_{std::move(fields)} {} - std::string id() - const noexcept override; // NOLINT(readability-identifier-naming) + std::string id() // NOLINT(readability-identifier-naming) + const noexcept override; bool IsMember(const std::string& id) const noexcept override; std::unique_ptr MemberType( const std::string& id) const noexcept override; diff --git a/src/type_checker.cpp b/src/type_checker.cpp index 57c6aba1..765c00ec 100644 --- a/src/type_checker.cpp +++ b/src/type_checker.cpp @@ -38,6 +38,20 @@ bool IsInBodyOf(BodyType type) { [type](auto&& t) { return t == type; }); } +/// @note Struct and union type id should be mangled when adding/looking up from +/// the type table to avoid same name but different types. +std::string MangleRecordTypeId(const std::string& id, + std::unique_ptr type) { + // We simply prefix them with their record kind. + if (type->IsStruct()) { + return "struct_" + id; + } else if (type->IsUnion()) { + return "union_" + id; + } else { + throw "unknown record type"; + } +} + } // namespace void TypeChecker::Visit(DeclStmtNode& decl_stmt) { @@ -94,8 +108,10 @@ void TypeChecker::Visit(RecordDeclNode& record_decl) { // }; // If no, then it is the redefinition of 'id'. } else { + auto type_id = + MangleRecordTypeId(record_decl.id, record_decl.type->Clone()); auto decl_type = - std::make_unique(record_decl.id, record_decl.type->Clone()); + std::make_unique(type_id, record_decl.type->Clone()); // TODO: May be file scope once we support global variables. env_.AddType(std::move(decl_type), ScopeKind::kBlock); @@ -118,9 +134,12 @@ void TypeChecker::Visit(RecordVarDeclNode& record_decl) { // // struct birth bd1 { .date = 1 }; // RecordVarDeclNode -> search type entry // to update its type. - // record_type->id() is "birth" in the above example. + // record_type_id is "struct_birth" in the above example. + auto record_type_id = + dynamic_cast(record_decl.type.get())->id(); auto record_type = env_.LookUpType( - dynamic_cast(record_decl.type.get())->id()); + MangleRecordTypeId(record_type_id, record_decl.type->Clone())); + assert(record_type); auto symbol = std::make_unique(record_decl.id, record_type->type->Clone()); @@ -488,13 +507,10 @@ void TypeChecker::Visit(PostfixArithExprNode& postfix_expr) { void TypeChecker::Visit(RecordMemExprNode& mem_expr) { mem_expr.expr->Accept(*this); - // id_expr->id is a record variable id. - const auto* id_expr = dynamic_cast((mem_expr.expr).get()); - assert(id_expr); - auto symbol = env_.LookUpSymbol(id_expr->id); - if (auto* record_type = dynamic_cast((symbol->type).get())) { + if (auto* record_type = + dynamic_cast((mem_expr.expr->type).get())) { if (record_type->IsMember(mem_expr.id)) { - mem_expr.type = record_type->MemberType(mem_expr.id)->Clone(); + mem_expr.type = record_type->MemberType(mem_expr.id); } else { assert(false); // TODO: Throw error if mem_expr.id is not a symbol's member.