Skip to content

Commit

Permalink
Fix nits and support unamed primitive type
Browse files Browse the repository at this point in the history
  • Loading branch information
leewei05 committed Jun 4, 2024
1 parent d34f0f6 commit 0a5e11a
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 58 deletions.
12 changes: 6 additions & 6 deletions include/type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,9 @@ class FuncType : public Type {

class StructType : public Type {
public:
/// @param id The identifier of a struct type.
explicit StructType(std::string id,
std::vector<std::unique_ptr<Type>> field_types)
/// @param id The identifier of the struct type. May be empty ("") for unnamed
/// structs.
StructType(std::string id, std::vector<std::unique_ptr<Type>> field_types)
: id_{std::move(id)}, field_types_{std::move(field_types)} {}

bool IsStruct() const noexcept override {
Expand All @@ -197,9 +197,9 @@ class StructType : public Type {

class UnionType : public Type {
public:
/// @param id The identifier of a union type.
explicit UnionType(std::string id,
std::vector<std::unique_ptr<Type>> field_types)
/// @param id The identifier of the union type. May be empty ("") for unnamed
/// unions.
UnionType(std::string id, std::vector<std::unique_ptr<Type>> field_types)
: id_{std::move(id)}, field_types_{std::move(field_types)} {}

bool IsUnion() const noexcept override {
Expand Down
2 changes: 1 addition & 1 deletion lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ integer [0-9]+
":" { return yy::parser::make_COLON(yylloc); }

"," { return yy::parser::make_COMMA(yylloc); }
"." { return yy::parser::make_PERIOD(yylloc); }
"." { return yy::parser::make_DOT(yylloc); }

/* operators */
"-" { return yy::parser::make_MINUS(yylloc); }
Expand Down
38 changes: 16 additions & 22 deletions parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ std::unique_ptr<Type> ResolveType(std::unique_ptr<Type> resolved_type,

%token MINUS PLUS STAR DIV MOD ASSIGN
%token EXCLAMATION TILDE AMPERSAND QUESTION
%token COMMA PERIOD SEMICOLON COLON
%token COMMA DOT SEMICOLON COLON
// (), {}, []
%token LEFT_PAREN RIGHT_PAREN LEFT_CURLY RIGHT_CURLY LEFT_SQUARE RIGHT_SQUARE

Expand Down Expand Up @@ -388,25 +388,24 @@ arg: expr {
/* 6.7 Declarations */
/* Declaration specifiers can be either a 'type' or a 'declaration of type'. */
/* TODO: init declarator list */
/* TODO: If the init declarator doesn't present, e.g., `int;`, the declaration is still valid. */
decl: declaration_specifiers init_declarator_opt SEMICOLON {
auto decl_specifers = $1;
auto init_decl = $2;
if (std::holds_alternative<std::unique_ptr<Type>>(decl_specifers)) {
auto type = std::move(std::get<std::unique_ptr<Type>>(decl_specifers));
init_decl->type = ResolveType(std::move(type), std::move(init_decl->type));
if (init_decl) {
init_decl->type = ResolveType(std::move(type), std::move(init_decl->type));
} else { // unnamed primitive type
init_decl = std::make_unique<VarDeclNode>(Loc(@1), "", std::move(type));
}

$$ = std::move(init_decl);
} else {
auto decl = std::move(std::get<std::unique_ptr<DeclNode>>(decl_specifers));
auto rec_decl = dynamic_cast<RecordDeclNode*>(decl.get());
auto* rec_decl = dynamic_cast<RecordDeclNode*>(decl.get());
assert(rec_decl);
if (auto* rec_var_decl = dynamic_cast<RecordVarDeclNode*>(init_decl.get())) {
// A struct or union variable.
rec_var_decl->type = ResolveType(std::move(rec_decl->type), std::move(rec_var_decl->type));
decl = std::move(init_decl);
} else if (auto* arr_decl = dynamic_cast<ArrDeclNode*>(init_decl.get())) {
// An array with struct or union elements.
arr_decl->type = ResolveType(std::move(rec_decl->type), std::move(arr_decl->type));
if (init_decl) {
init_decl->type = ResolveType(std::move(rec_decl->type), std::move(init_decl->type));
decl = std::move(init_decl);
}

Expand Down Expand Up @@ -446,11 +445,10 @@ init_declarator: declarator { $$ = $1; }
arr_decl->init_list = std::move(init_expr_list);
} else if (auto* var_decl = dynamic_cast<VarDeclNode*>(decl.get())) {
// Declares a struct or union variable.
auto rec_decl = std::make_unique<RecordVarDeclNode>(Loc(@1),
decl = std::make_unique<RecordVarDeclNode>(Loc(@1),
std::move(var_decl->id),
std::move(var_decl->type),
std::move(init_expr_list));
decl = std::move(rec_decl);
}
}
$$ = std::move(decl);
Expand Down Expand Up @@ -483,19 +481,18 @@ struct_or_union_specifier: struct_or_union id_opt LEFT_CURLY struct_declaration_
type = std::make_unique<UnionType>(std::move(type_id), std::move(field_types));
}

$$ = std::make_unique<RecordDeclNode>(Loc(@2), decl_id ? std::move(decl_id->id) : "", std::move(type), std::move(field_list));
$$ = std::make_unique<RecordDeclNode>(Loc(@2), std::move(type_id), std::move(type), std::move(field_list));
}
| struct_or_union ID {
auto type = $1;
auto decl_id = $2;
auto field_list = std::vector<std::unique_ptr<FieldNode>>{};
auto field_types = std::vector<std::unique_ptr<Type>>{};

auto type_id = decl_id;
if (type->IsStruct()) {
type = std::make_unique<StructType>(std::move(type_id), std::move(field_types));
type = std::make_unique<StructType>(std::move(decl_id), std::move(field_types));
} else {
type = std::make_unique<UnionType>(std::move(type_id), std::move(field_types));
type = std::make_unique<UnionType>(std::move(decl_id), std::move(field_types));
}

$$ = std::make_unique<RecordDeclNode>(Loc(@2), std::move(decl_id), std::move(type), std::move(field_list));
Expand Down Expand Up @@ -589,7 +586,7 @@ direct_declarator: ID {
auto type = std::make_unique<ArrType>(std::move(declarator->type), $3);
if (!dynamic_cast<ArrDeclNode*>(declarator.get())) {
// If the declarator is not yet a array declarator, we need to construct one.
$$ = std::make_unique<ArrDeclNode>(Loc(@1), declarator->id, std::move(type), /* init list */ std::vector<std::unique_ptr<InitExprNode>>{});
$$ = std::make_unique<ArrDeclNode>(Loc(@1), declarator->id, std::move(type), std::vector<std::unique_ptr<InitExprNode>>{});
} else {
declarator->type = std::move(type);
$$ = std::move(declarator);
Expand Down Expand Up @@ -709,7 +706,6 @@ direct_abstract_declarator_opt: direct_abstract_declarator { $$ = $1; }
;

/* 6.7.8 Initialization */
/* The current object shall have array type and the expression shall be an integer constant expression. */
initializer: LEFT_CURLY initializer_list comma_opt RIGHT_CURLY { $$ = $2; }
| assign_expr { $$ = std::make_unique<InitExprNode>(Loc(@1), std::vector<std::unique_ptr<DesNode>>{}, $1); }
;
Expand Down Expand Up @@ -743,10 +739,8 @@ designator_list: designator {
}
;

/* The current object shall have array type and the expression shall be an integer constant expression. */
designator: LEFT_SQUARE const_expr RIGHT_SQUARE { $$ = std::make_unique<ArrDesNode>(Loc(@2), $2); }
/* The current object shall have structure or union type and the identifier shall be the name of a member of that type. */
| PERIOD ID { $$ = std::make_unique<IdDesNode>(Loc(@2), $2); }
| DOT ID { $$ = std::make_unique<IdDesNode>(Loc(@2), $2); }
;

comma_opt: COMMA
Expand Down
5 changes: 4 additions & 1 deletion src/type_checker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,11 +356,14 @@ void TypeChecker::Visit(InitExprNode& init_expr) {
}

void TypeChecker::Visit(ArrDesNode& arr_des) {
/* ArrDesNode shall have array type and the expression shall be an integer
* constant expression. */
arr_des.index->Accept(*this);
}

void TypeChecker::Visit(IdDesNode& id_des) {
/* do nothing */
/* IdDesNode does nothing and shall have structure or union type and the
* identifier shall be the name of a member of that type. */
}

void TypeChecker::Visit(NullExprNode&) {
Expand Down
1 change: 1 addition & 0 deletions test/typecheck/decl.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
int main() {
int i = 0;
int j;
int;
}
1 change: 1 addition & 0 deletions test/typecheck/decl.exp
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ ProgramNode <1:1>
VarDeclNode <2:7> i: int
IntConstExprNode <2:11> 0: int
VarDeclNode <3:7> j: int
VarDeclNode <4:3> : int
2 changes: 1 addition & 1 deletion test/typecheck/struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ int main() {

struct birth bd2 = {3, 3, 1998};

struct birth bd3[3] = { [0].date = 4, [1].year = 1999};
struct birth bd3[3] = {[0].date = 4, [1].year = 1999};

return 0;
}
20 changes: 10 additions & 10 deletions test/typecheck/struct.exp
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ ProgramNode <1:1>
InitExprNode <22:23>
IntConstExprNode <22:29> 1998: int
ArrDeclNode <24:16> bd3: struct birth[3]
InitExprNode <24:27>
ArrDesNode <24:28>
IntConstExprNode <24:28> 0: int
IdDesNode <24:31> date
IntConstExprNode <24:38> 4: int
InitExprNode <24:27>
ArrDesNode <24:42>
IntConstExprNode <24:42> 1: int
IdDesNode <24:45> year
IntConstExprNode <24:52> 1999: int
InitExprNode <24:26>
ArrDesNode <24:27>
IntConstExprNode <24:27> 0: int
IdDesNode <24:30> date
IntConstExprNode <24:37> 4: int
InitExprNode <24:26>
ArrDesNode <24:41>
IntConstExprNode <24:41> 1: int
IdDesNode <24:44> year
IntConstExprNode <24:51> 1999: int
ReturnStmtNode <26:3>
IntConstExprNode <26:10> 0: int
4 changes: 2 additions & 2 deletions test/typecheck/union.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ int main() {
int e;
};

// It's a legal case, but compiler will show warning of excessing elements.
// It's a legal case, but compilers like GCC may show warning of excessing elements.
// The value of the members is 3.
union shape s = {3, 4, 5};
// Three members in circle variable share the same memory location, so every member is 1.
union shape circle = {.circle = 1};
union shape puzzles[3] = { [0].circle = 1, [1].triangle = 2, [2].square = 4};
union shape puzzles[3] = {[0].circle = 1, [1].triangle = 2, [2].square = 4};

return 0;
}
30 changes: 15 additions & 15 deletions test/typecheck/union.exp
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,20 @@ ProgramNode <1:1>
IdDesNode <22:26> circle
IntConstExprNode <22:35> 1: int
ArrDeclNode <23:15> puzzles: union shape[3]
InitExprNode <23:30>
ArrDesNode <23:31>
IntConstExprNode <23:31> 0: int
IdDesNode <23:34> circle
IntConstExprNode <23:43> 1: int
InitExprNode <23:30>
ArrDesNode <23:47>
IntConstExprNode <23:47> 1: int
IdDesNode <23:50> triangle
IntConstExprNode <23:61> 2: int
InitExprNode <23:30>
ArrDesNode <23:65>
IntConstExprNode <23:65> 2: int
IdDesNode <23:68> square
IntConstExprNode <23:77> 4: int
InitExprNode <23:29>
ArrDesNode <23:30>
IntConstExprNode <23:30> 0: int
IdDesNode <23:33> circle
IntConstExprNode <23:42> 1: int
InitExprNode <23:29>
ArrDesNode <23:46>
IntConstExprNode <23:46> 1: int
IdDesNode <23:49> triangle
IntConstExprNode <23:60> 2: int
InitExprNode <23:29>
ArrDesNode <23:64>
IntConstExprNode <23:64> 2: int
IdDesNode <23:67> square
IntConstExprNode <23:76> 4: int
ReturnStmtNode <25:3>
IntConstExprNode <25:10> 0: int

0 comments on commit 0a5e11a

Please sign in to comment.