From f2eb940821c1b97859d1956a9011b7cac37a786e Mon Sep 17 00:00:00 2001 From: Lee Date: Mon, 27 Nov 2023 19:54:23 +0800 Subject: [PATCH] Implement if statement ast_dumper and type_checker --- include/ast.hpp | 12 ++++++++++++ include/ast_dumper.hpp | 1 + include/qbe_ir_generator.hpp | 1 + include/type_checker.hpp | 1 + include/visitor.hpp | 2 ++ parser.y | 2 +- src/ast.cpp | 8 ++++++++ src/ast_dumper.cpp | 9 +++++++++ src/qbe_ir_generator.cpp | 2 ++ src/type_checker.cpp | 9 +++++++-- 10 files changed, 44 insertions(+), 3 deletions(-) diff --git a/include/ast.hpp b/include/ast.hpp index 8c2872f6..ede92a82 100644 --- a/include/ast.hpp +++ b/include/ast.hpp @@ -93,6 +93,18 @@ struct NullStmtNode : public StmtNode { virtual void Accept(ModifyingVisitor&) override; }; +struct IfStmtNode : public StmtNode { + IfStmtNode(std::unique_ptr expr, + std::unique_ptr block) + : predicate{std::move(expr)}, body{std::move(block)} {} + + virtual void Accept(NonModifyingVisitor&) const override; + virtual void Accept(ModifyingVisitor&) override; + + std::unique_ptr predicate; + std::unique_ptr body; +}; + struct ReturnStmtNode : public StmtNode { ReturnStmtNode(std::unique_ptr expr) : expr{std::move(expr)} {} diff --git a/include/ast_dumper.hpp b/include/ast_dumper.hpp index cbb4875b..74e3a12e 100644 --- a/include/ast_dumper.hpp +++ b/include/ast_dumper.hpp @@ -10,6 +10,7 @@ class AstDumper : public NonModifyingVisitor { void Visit(const BlockStmtNode&) override; void Visit(const ProgramNode&) override; void Visit(const NullStmtNode&) override; + void Visit(const IfStmtNode&) override; void Visit(const ReturnStmtNode&) override; void Visit(const ExprStmtNode&) override; void Visit(const IdExprNode&) override; diff --git a/include/qbe_ir_generator.hpp b/include/qbe_ir_generator.hpp index 461d2ed9..67aa0988 100644 --- a/include/qbe_ir_generator.hpp +++ b/include/qbe_ir_generator.hpp @@ -9,6 +9,7 @@ class QbeIrGenerator : public NonModifyingVisitor { void Visit(const BlockStmtNode&) override; void Visit(const ProgramNode&) override; void Visit(const NullStmtNode&) override; + void Visit(const IfStmtNode&) override; void Visit(const ReturnStmtNode&) override; void Visit(const ExprStmtNode&) override; void Visit(const IdExprNode&) override; diff --git a/include/type_checker.hpp b/include/type_checker.hpp index 05381d2a..82b97d14 100644 --- a/include/type_checker.hpp +++ b/include/type_checker.hpp @@ -13,6 +13,7 @@ class TypeChecker : public ModifyingVisitor { void Visit(BlockStmtNode&) override; void Visit(ProgramNode&) override; void Visit(NullStmtNode&) override; + void Visit(IfStmtNode&) override; void Visit(ReturnStmtNode&) override; void Visit(ExprStmtNode&) override; void Visit(IdExprNode&) override; diff --git a/include/visitor.hpp b/include/visitor.hpp index 86656a89..0d7b57ec 100644 --- a/include/visitor.hpp +++ b/include/visitor.hpp @@ -13,6 +13,7 @@ struct DeclNode; struct BlockStmtNode; struct ProgramNode; struct NullStmtNode; +struct IfStmtNode; struct ReturnStmtNode; struct ExprStmtNode; struct IdExprNode; @@ -55,6 +56,7 @@ class Visitor { virtual void Visit(CondMut&){}; virtual void Visit(CondMut&){}; virtual void Visit(CondMut&){}; + virtual void Visit(CondMut&){}; virtual void Visit(CondMut&){}; virtual void Visit(CondMut&){}; virtual void Visit(CondMut&){}; diff --git a/parser.y b/parser.y index 188856c9..f690af40 100644 --- a/parser.y +++ b/parser.y @@ -109,7 +109,7 @@ stmts: stmts stmt { stmt: ';' { $$ = std::make_unique(); } | RETURN expr ';' { $$ = std::make_unique($2); } | expr ';' { $$ = std::make_unique($1); } - | IF '(' expr ')' block {} + | IF '(' expr ')' block { $$ = std::make_unique($3, $5); } ; expr: ID { $$ = std::make_unique($1); } diff --git a/src/ast.cpp b/src/ast.cpp index 797b1543..8a4531fa 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -64,6 +64,14 @@ void NullStmtNode::Accept(ModifyingVisitor& v) { v.Visit(*this); } +void IfStmtNode::Accept(NonModifyingVisitor& v) const { + v.Visit(*this); +} + +void IfStmtNode::Accept(ModifyingVisitor& v) { + v.Visit(*this); +} + void ReturnStmtNode::Accept(NonModifyingVisitor& v) const { v.Visit(*this); } diff --git a/src/ast_dumper.cpp b/src/ast_dumper.cpp index cfa013fd..8f83765c 100644 --- a/src/ast_dumper.cpp +++ b/src/ast_dumper.cpp @@ -57,6 +57,15 @@ void AstDumper::Visit(const NullStmtNode& stmt) { std::cout << indenter_.Indent() << "()" << std::endl; } +void AstDumper::Visit(const IfStmtNode& if_stmt) { + std::cout << indenter_.Indent() << "(if" << std::endl; + indenter_.IncreaseLevel(); + if_stmt.predicate->Accept(*this); + if_stmt.body->Accept(*this); + indenter_.DecreaseLevel(); + std::cout << indenter_.Indent() << ')' << std::endl; +} + void AstDumper::Visit(const ReturnStmtNode& ret_stmt) { std::cout << indenter_.Indent() << "(ret" << std::endl; indenter_.IncreaseLevel(); diff --git a/src/qbe_ir_generator.cpp b/src/qbe_ir_generator.cpp index f5949d75..94b83863 100644 --- a/src/qbe_ir_generator.cpp +++ b/src/qbe_ir_generator.cpp @@ -106,6 +106,8 @@ void QbeIrGenerator::Visit(const NullStmtNode&) { /* do nothing */ } +void QbeIrGenerator::Visit(const IfStmtNode& if_stmt) {} + void QbeIrGenerator::Visit(const ReturnStmtNode& ret_stmt) { ret_stmt.expr->Accept(*this); int ret_num = num_recorder.NumOfPrevExpr(); diff --git a/src/type_checker.cpp b/src/type_checker.cpp index d61c7e73..74c309c6 100644 --- a/src/type_checker.cpp +++ b/src/type_checker.cpp @@ -39,6 +39,11 @@ void TypeChecker::Visit(NullStmtNode&) { /* do nothing */ } +void TypeChecker::Visit(IfStmtNode& if_stmt) { + if_stmt.predicate->Accept(*this); + if_stmt.body->Accept(*this); +} + void TypeChecker::Visit(ReturnStmtNode& ret_stmt) { ret_stmt.expr->Accept(*this); if (ret_stmt.expr->type != ExprType::kInt) { @@ -100,8 +105,8 @@ void TypeChecker::Visit(SimpleAssignmentExprNode& assign_expr) { if (assign_expr.expr->type == symbol->expr_type) { // 6.5.16 Assignment operators // The type of an assignment expression is the type of the left - // operand unless the left operand has qualified type, in which case it is - // the unqualified version of the type of the left operand. + // operand unless the left operand has qualified type, in which case it + // is the unqualified version of the type of the left operand. assign_expr.type = symbol->expr_type; } else { // TODO: assigning to 'symbol->expr_type' from incompatible type