Skip to content

Commit

Permalink
Add prefix for record type to avoid name collision in type table
Browse files Browse the repository at this point in the history
  • Loading branch information
leewei05 authored and Lai-YT committed Jun 19, 2024
1 parent 8ac0acf commit 1cf2769
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 16 deletions.
12 changes: 6 additions & 6 deletions include/type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -203,8 +203,8 @@ class StructType : public RecordType {
StructType(std::string id, std::vector<std::unique_ptr<Field>> 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<Type> MemberType(
const std::string& id) const noexcept override;
Expand All @@ -230,8 +230,8 @@ class UnionType : public RecordType {
UnionType(std::string id, std::vector<std::unique_ptr<Field>> 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<Type> MemberType(
const std::string& id) const noexcept override;
Expand Down
35 changes: 25 additions & 10 deletions src/type_checker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
const std::unique_ptr<Type>& 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) {
Expand Down Expand Up @@ -94,8 +108,9 @@ 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);
auto decl_type =
std::make_unique<TypeEntry>(record_decl.id, record_decl.type->Clone());
std::make_unique<TypeEntry>(type_id, record_decl.type->Clone());

// TODO: May be file scope once we support global variables.
env_.AddType(std::move(decl_type), ScopeKind::kBlock);
Expand All @@ -118,9 +133,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.
auto record_type = env_.LookUpType(
dynamic_cast<RecordType*>(record_decl.type.get())->id());
// record_type_id is "struct_birth" in the above example.
auto record_type_id =
dynamic_cast<RecordType*>(record_decl.type.get())->id();
auto record_type =
env_.LookUpType(MangleRecordTypeId(record_type_id, record_decl.type));
assert(record_type);
auto symbol = std::make_unique<SymbolEntry>(record_decl.id,
record_type->type->Clone());

Expand Down Expand Up @@ -488,13 +506,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<IdExprNode*>((mem_expr.expr).get());
assert(id_expr);
auto symbol = env_.LookUpSymbol(id_expr->id);
if (auto* record_type = dynamic_cast<RecordType*>((symbol->type).get())) {
if (auto* record_type =
dynamic_cast<RecordType*>((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.
Expand Down

0 comments on commit 1cf2769

Please sign in to comment.