Skip to content

Commit 1cb0d4b

Browse files
committed
[parser] Refactor semantic checks: Move diagnostics handling to Semantic pass and implement designator index checks
1 parent f6caa07 commit 1cb0d4b

8 files changed

Lines changed: 548 additions & 81 deletions

File tree

src/exec/main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,8 @@ int main(int argc, char** argv) {
198198
}
199199

200200
// Not dumping AST: run semantic checks and continue compiler passes
201-
wvmcc::parser::Semantic sem(false);
202-
sem.run(main_translation_unit, parser.getDiagnosticsRef());
201+
wvmcc::parser::Semantic sem(main_translation_unit, false);
202+
sem.run(parser.getDiagnosticsRef());
203203

204204
WasmVM::WasmModule module;
205205
const std::string target = args.outPath.empty() ? std::string("a.wasm") : args.outPath;

src/parser/ASTVisitor.cpp

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
#include "ASTVisitor.hpp"
2+
#include <memory>
3+
#include <variant>
4+
5+
namespace wvmcc::parser {
6+
7+
void ASTVisitor::traverseTranslationUnit(const TranslationUnitPtr &tu) {
8+
if (!tu) return;
9+
for (auto &ext : tu->externals) traverseExternalDecl(ext);
10+
}
11+
12+
void ASTVisitor::traverseExternalDecl(const ExternalDeclPtr &ext) {
13+
if (!ext) return;
14+
if (std::holds_alternative<FunctionDefPtr>(ext->decl)) {
15+
auto f = std::get<FunctionDefPtr>(ext->decl);
16+
onFunctionDef(f);
17+
traverseFunction(f);
18+
} else if (std::holds_alternative<DeclarationPtr>(ext->decl)) {
19+
auto d = std::get<DeclarationPtr>(ext->decl);
20+
onDeclaration(d);
21+
traverseDeclaration(d);
22+
}
23+
}
24+
25+
void ASTVisitor::traverseFunction(const FunctionDefPtr &f) {
26+
if (!f) return;
27+
onEnterFunction(f);
28+
// params
29+
for (const auto &p : f->params) {
30+
if (p.defaultValue) traverseExpr(p.defaultValue.value());
31+
}
32+
// body
33+
for (const auto &bi : f->body) {
34+
if (std::holds_alternative<DeclarationPtr>(bi->item)) {
35+
traverseDeclaration(std::get<DeclarationPtr>(bi->item));
36+
} else {
37+
traverseStmt(std::get<StmtPtr>(bi->item));
38+
}
39+
}
40+
onExitFunction(f);
41+
}
42+
43+
void ASTVisitor::traverseDeclaration(const DeclarationPtr &d) {
44+
if (!d) return;
45+
if (d->initializer) traverseInit(d->initializer.value());
46+
}
47+
48+
void ASTVisitor::traverseInit(const InitializerPtr &in) {
49+
if (!in) return;
50+
if (in->kind == Initializer::Kind::Expr) traverseExpr(in->expr);
51+
else {
52+
for (const auto &c : in->clauses) {
53+
for (const auto &des : c.designators) {
54+
if (des.kind == Designator::Kind::Index && des.index) traverseExpr(des.index.value());
55+
}
56+
traverseInit(c.init);
57+
}
58+
}
59+
}
60+
61+
void ASTVisitor::traverseStmt(const StmtPtr &s) {
62+
if (!s) return;
63+
switch (s->kind) {
64+
case Stmt::Kind::Expr: {
65+
auto es = std::dynamic_pointer_cast<ExprStmt>(s);
66+
if (es && es->expr) traverseExpr(es->expr);
67+
break;
68+
}
69+
case Stmt::Kind::Compound: {
70+
auto cs = std::dynamic_pointer_cast<CompoundStmt>(s);
71+
if (cs) {
72+
for (const auto &bi : cs->items) {
73+
if (std::holds_alternative<DeclarationPtr>(bi->item)) traverseDeclaration(std::get<DeclarationPtr>(bi->item));
74+
else traverseStmt(std::get<StmtPtr>(bi->item));
75+
}
76+
}
77+
break;
78+
}
79+
case Stmt::Kind::If: {
80+
auto ifs = std::dynamic_pointer_cast<IfStmt>(s);
81+
if (ifs) {
82+
traverseExpr(ifs->cond);
83+
traverseStmt(ifs->thenStmt);
84+
if (ifs->elseStmt) traverseStmt(ifs->elseStmt.value());
85+
}
86+
break;
87+
}
88+
case Stmt::Kind::While: {
89+
auto ws = std::dynamic_pointer_cast<WhileStmt>(s);
90+
if (ws) {
91+
traverseExpr(ws->cond);
92+
traverseStmt(ws->body);
93+
}
94+
break;
95+
}
96+
case Stmt::Kind::For: {
97+
auto fs = std::dynamic_pointer_cast<ForStmt>(s);
98+
if (fs) {
99+
if (fs->init) {
100+
auto bi = fs->init.value();
101+
if (std::holds_alternative<DeclarationPtr>(bi->item)) traverseDeclaration(std::get<DeclarationPtr>(bi->item));
102+
else traverseStmt(std::get<StmtPtr>(bi->item));
103+
}
104+
if (fs->cond) traverseExpr(fs->cond.value());
105+
if (fs->step) traverseExpr(fs->step.value());
106+
traverseStmt(fs->body);
107+
}
108+
break;
109+
}
110+
case Stmt::Kind::Return: {
111+
auto rs = std::dynamic_pointer_cast<ReturnStmt>(s);
112+
if (rs && rs->value) traverseExpr(rs->value.value());
113+
break;
114+
}
115+
case Stmt::Kind::DoWhile: {
116+
auto dws = std::dynamic_pointer_cast<DoWhileStmt>(s);
117+
if (dws) {
118+
traverseStmt(dws->body);
119+
traverseExpr(dws->cond);
120+
}
121+
break;
122+
}
123+
case Stmt::Kind::Switch: {
124+
auto ss = std::dynamic_pointer_cast<SwitchStmt>(s);
125+
if (ss) {
126+
traverseExpr(ss->cond);
127+
traverseStmt(ss->body);
128+
}
129+
break;
130+
}
131+
case Stmt::Kind::Case: {
132+
auto cs = std::dynamic_pointer_cast<CaseStmt>(s);
133+
if (cs) {
134+
traverseExpr(cs->value);
135+
traverseStmt(cs->stmt);
136+
}
137+
break;
138+
}
139+
case Stmt::Kind::Default: {
140+
auto ds = std::dynamic_pointer_cast<DefaultStmt>(s);
141+
if (ds) traverseStmt(ds->stmt);
142+
break;
143+
}
144+
case Stmt::Kind::Label: {
145+
auto ls = std::dynamic_pointer_cast<LabelStmt>(s);
146+
if (ls) traverseStmt(ls->stmt);
147+
break;
148+
}
149+
case Stmt::Kind::Goto:
150+
case Stmt::Kind::Break:
151+
case Stmt::Kind::Continue:
152+
case Stmt::Kind::Empty:
153+
break;
154+
}
155+
}
156+
157+
void ASTVisitor::traverseExpr(const ExprPtr &e) {
158+
if (!e) return;
159+
switch (e->kind) {
160+
case Expr::Kind::Ident: onIdent(std::static_pointer_cast<IdentifierExpr>(e)); break;
161+
case Expr::Kind::Unary: traverseExpr(std::static_pointer_cast<UnaryExpr>(e)->rhs); break;
162+
case Expr::Kind::PostfixUnary: traverseExpr(std::static_pointer_cast<PostfixUnaryExpr>(e)->base); break;
163+
case Expr::Kind::Cast: traverseExpr(std::static_pointer_cast<CastExpr>(e)->expr); break;
164+
case Expr::Kind::Sizeof: {
165+
auto s = std::static_pointer_cast<SizeofExpr>(e);
166+
if (s->expr) traverseExpr(s->expr);
167+
break;
168+
}
169+
case Expr::Kind::AlignOf: break;
170+
case Expr::Kind::CompoundLiteral: traverseInit(std::static_pointer_cast<CompoundLiteral>(e)->init); break;
171+
case Expr::Kind::GenericSelection: {
172+
auto g = std::static_pointer_cast<GenericSelectionExpr>(e);
173+
traverseExpr(g->controlling);
174+
for (const auto &a : g->assocs) traverseExpr(a.expr);
175+
break;
176+
}
177+
case Expr::Kind::Binary: {
178+
auto b = std::static_pointer_cast<BinaryExpr>(e);
179+
traverseExpr(b->lhs);
180+
traverseExpr(b->rhs);
181+
break;
182+
}
183+
case Expr::Kind::Ternary: {
184+
auto t = std::static_pointer_cast<TernaryExpr>(e);
185+
traverseExpr(t->cond);
186+
traverseExpr(t->thenExpr);
187+
traverseExpr(t->elseExpr);
188+
break;
189+
}
190+
case Expr::Kind::Call: {
191+
auto c = std::static_pointer_cast<CallExpr>(e);
192+
traverseExpr(c->callee);
193+
for (const auto &a : c->args) traverseExpr(a);
194+
break;
195+
}
196+
case Expr::Kind::Member: traverseExpr(std::static_pointer_cast<MemberExpr>(e)->base); break;
197+
case Expr::Kind::Index: {
198+
auto ix = std::static_pointer_cast<IndexExpr>(e);
199+
traverseExpr(ix->base);
200+
traverseExpr(ix->index);
201+
break;
202+
}
203+
case Expr::Kind::Integer:
204+
case Expr::Kind::Float:
205+
case Expr::Kind::Char:
206+
case Expr::Kind::String:
207+
break;
208+
}
209+
}
210+
211+
} // namespace wvmcc::parser

src/parser/ASTVisitor.hpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#pragma once
2+
3+
#include "AST.hpp"
4+
5+
namespace wvmcc::parser {
6+
7+
class ASTVisitor {
8+
public:
9+
virtual ~ASTVisitor() = default;
10+
// convenience aliases for node pointer types
11+
using IdentifierExprPtr = std::shared_ptr<IdentifierExpr>;
12+
13+
// Entry point
14+
void traverseTranslationUnit(const TranslationUnitPtr &tu);
15+
16+
void traverseExternalDecl(const ExternalDeclPtr &ext);
17+
18+
void traverseFunction(const FunctionDefPtr &f);
19+
20+
void traverseDeclaration(const DeclarationPtr &d);
21+
22+
void traverseInit(const InitializerPtr &in);
23+
24+
void traverseStmt(const StmtPtr &s);
25+
26+
void traverseExpr(const ExprPtr &e);
27+
28+
protected:
29+
// callback hooks
30+
virtual void onIdent(const IdentifierExprPtr &/*id*/) {}
31+
virtual void onFunctionDef(const FunctionDefPtr &/*f*/) {}
32+
// called when entering/exiting a function body
33+
virtual void onEnterFunction(const FunctionDefPtr &/*f*/) {}
34+
virtual void onExitFunction(const FunctionDefPtr &/*f*/) {}
35+
virtual void onDeclaration(const DeclarationPtr &/*d*/) {}
36+
};
37+
38+
} // namespace wvmcc::parser

0 commit comments

Comments
 (0)