• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rieske / trans / 29902648358

22 Jul 2026 08:04AM UTC coverage: 91.671% (+0.5%) from 91.142%
29902648358

Pull #53

github

rieske
Fuzz-test and fix the backend
Pull Request #53: Fuzz-test and fix the backend

128 of 134 new or added lines in 10 files covered. (95.52%)

5514 of 6015 relevant lines covered (91.67%)

379841.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.3
/src/codegen/CodeGeneratingVisitor.cpp
1
#include "CodeGeneratingVisitor.h"
2

3
#include <stdexcept>
4

5
#include "semantic_analyzer/ValueEntry.h"
6
#include "semantic_analyzer/LabelEntry.h"
7

8
#include "quadruples/Assign.h"
9
#include "quadruples/Argument.h"
10
#include "quadruples/Call.h"
11
#include "quadruples/Retrieve.h"
12
#include "quadruples/AssignConstant.h"
13
#include "quadruples/Inc.h"
14
#include "quadruples/Dec.h"
15
#include "quadruples/AddressOf.h"
16
#include "quadruples/Dereference.h"
17
#include "quadruples/UnaryMinus.h"
18
#include "quadruples/UnaryNot.h"
19
#include "quadruples/ValueCompare.h"
20
#include "quadruples/ZeroCompare.h"
21
#include "quadruples/Jump.h"
22
#include "quadruples/Label.h"
23
#include "quadruples/Add.h"
24
#include "quadruples/Sub.h"
25
#include "quadruples/Mul.h"
26
#include "quadruples/Div.h"
27
#include "quadruples/Mod.h"
28
#include "quadruples/And.h"
29
#include "quadruples/Or.h"
30
#include "quadruples/Xor.h"
31
#include "quadruples/Return.h"
32
#include "quadruples/VoidReturn.h"
33
#include "quadruples/LvalueAssign.h"
34
#include "quadruples/StartProcedure.h"
35
#include "quadruples/EndProcedure.h"
36
#include "quadruples/Shl.h"
37
#include "quadruples/Shr.h"
38

39
namespace codegen {
40

41
CodeGeneratingVisitor::CodeGeneratingVisitor() {
416✔
42
}
416✔
43

44
CodeGeneratingVisitor::~CodeGeneratingVisitor() {
416✔
45
}
416✔
46

47
void CodeGeneratingVisitor::visit(ast::DeclarationSpecifiers&) {
520✔
48
}
520✔
49

50
void CodeGeneratingVisitor::visit(ast::Declaration& declaration) {
520✔
51
    declaration.visitChildren(*this);
520✔
52
}
520✔
53

54
void CodeGeneratingVisitor::visit(ast::Declarator& declarator) {
1,328✔
55
    declarator.visitChildren(*this);
1,328✔
56
}
1,328✔
57

58
void CodeGeneratingVisitor::visit(ast::InitializedDeclarator& declarator) {
642✔
59
    // File-scope variables are initialized in .data; skip children (would emit assigns with no procedure).
60
    if (declarator.hasInitializer() && declarator.getHolder()->isGlobal()) {
642✔
61
        return;
28✔
62
    }
63
    declarator.visitChildren(*this);
614✔
64
    if (declarator.hasInitializer()) {
614✔
65
        instructions.push_back(std::make_unique<Assign>(
38✔
66
                declarator.getInitializerHolder()->getName(), declarator.getHolder()->getName()));
76✔
67
    }
68
}
69

70
void CodeGeneratingVisitor::visit(ast::ArrayAccess& arrayAccess) {
×
71
    arrayAccess.visitLeftOperand(*this);
×
72
    arrayAccess.visitRightOperand(*this);
×
73

74
    // TODO: not implemented yet
75
    //auto offset = arrayAccess.rightOperandSymbol();
76
    //quadruples.push_back( { code_generator::INDEX, arrayAccess.leftOperandSymbol(), offset, arrayAccess.getResultSymbol() });
77
    //quadruples.push_back( { code_generator::INDEX_ADDR, arrayAccess.leftOperandSymbol(), offset, arrayAccess.getLvalue() });
78
}
×
79

80
void CodeGeneratingVisitor::visit(ast::FunctionCall& functionCall) {
982✔
81
    functionCall.visitOperand(*this);
982✔
82
    functionCall.visitArguments(*this);
982✔
83

84
    for (auto& expression : functionCall.getArgumentList()) {
3,096✔
85
        instructions.push_back(std::make_unique<Argument>(expression->getResultSymbol()->getName()));
2,114✔
86
    }
87

88
    instructions.push_back(std::make_unique<Call>(functionCall.getSymbol()->getName()));
982✔
89
    if (!functionCall.getType().isVoid()) {
982✔
90
        instructions.push_back(std::make_unique<Retrieve>(functionCall.getResultSymbol()->getName()));
982✔
91
    }
92
}
982✔
93

94
void CodeGeneratingVisitor::visit(ast::IdentifierExpression&) {
2,886✔
95
}
2,886✔
96

97
void CodeGeneratingVisitor::visit(ast::ConstantExpression& constant) {
1,360✔
98
    instructions.push_back(std::make_unique<AssignConstant>(constant.getValue(), constant.getResultSymbol()->getName()));
1,360✔
99
}
1,360✔
100

101
void CodeGeneratingVisitor::visit(ast::StringLiteralExpression& stringLiteral) {
856✔
102
    instructions.push_back(
856✔
103
        std::make_unique<AssignConstant>(stringLiteral.getConstantSymbol(), stringLiteral.getResultSymbol()->getName())
1,712✔
104
    );
105
}
856✔
106

107
void CodeGeneratingVisitor::visit(ast::PostfixExpression& expression) {
30✔
108
    expression.visitOperand(*this);
30✔
109

110
    auto resultSymbolName = expression.getResultSymbol()->getName();
30✔
111
    auto preOperationSymbol = expression.getPreOperationSymbol()->getName();
30✔
112
    instructions.push_back(std::make_unique<Assign>(resultSymbolName, preOperationSymbol));
30✔
113

114
    if (expression.getOperator()->getLexeme() == "++") {
30✔
115
        instructions.push_back(std::make_unique<Inc>(resultSymbolName));
24✔
116
    } else if (expression.getOperator()->getLexeme() == "--") {
6✔
117
        instructions.push_back(std::make_unique<Dec>(resultSymbolName));
6✔
118
    }
119

120
    // Dereference (and similar) lvalues: value lives in a temp; store new value through the pointer.
121
    if (auto* lvalue = expression.operandLvalueSymbol()) {
30✔
122
        instructions.push_back(std::make_unique<LvalueAssign>(resultSymbolName, lvalue->getName()));
8✔
123
    }
124

125
    expression.setResultSymbol(*expression.getPreOperationSymbol());
30✔
126
}
30✔
127

128
void CodeGeneratingVisitor::visit(ast::PrefixExpression& expression) {
28✔
129
    expression.visitOperand(*this);
28✔
130

131
    auto resultSymbolName = expression.getResultSymbol()->getName();
28✔
132
    if (expression.getOperator()->getLexeme() == "++") {
28✔
133
        instructions.push_back(std::make_unique<Inc>(resultSymbolName));
22✔
134
    } else if (expression.getOperator()->getLexeme() == "--") {
6✔
135
        instructions.push_back(std::make_unique<Dec>(resultSymbolName));
6✔
136
    }
137

138
    if (auto* lvalue = expression.operandLvalueSymbol()) {
28✔
139
        instructions.push_back(std::make_unique<LvalueAssign>(resultSymbolName, lvalue->getName()));
20✔
140
    }
141
}
28✔
142

143
void CodeGeneratingVisitor::visit(ast::UnaryExpression& expression) {
564✔
144
    expression.visitOperand(*this);
564✔
145

146
    switch (expression.getOperator()->getLexeme().front()) {
564✔
147
    case '&':
328✔
148
        instructions.push_back(std::make_unique<AddressOf>(expression.operandSymbol()->getName(), expression.getResultSymbol()->getName()));
328✔
149
        break;
328✔
150
    case '*':
92✔
151
        instructions.push_back(std::make_unique<Dereference>(expression.operandSymbol()->getName(), expression.getLvalueSymbol()->getName(),
92✔
152
                                                             expression.getResultSymbol()->getName()));
184✔
153
        break;
92✔
154
    case '+':
2✔
155
        break;
2✔
156
    case '-':
94✔
157
        instructions.push_back(std::make_unique<UnaryMinus>(expression.operandSymbol()->getName(), expression.getResultSymbol()->getName()));
94✔
158
        break;
94✔
159
    case '~':
18✔
160
        instructions.push_back(std::make_unique<UnaryNot>(expression.operandSymbol()->getName(), expression.getResultSymbol()->getName()));
18✔
161
        break;
18✔
162
    case '!':
30✔
163
        instructions.push_back(std::make_unique<ZeroCompare>(expression.operandSymbol()->getName()));
30✔
164
        instructions.push_back(std::make_unique<Jump>(expression.getTruthyLabel()->getName(), JumpCondition::IF_EQUAL));
30✔
165
        instructions.push_back(std::make_unique<AssignConstant>("0", expression.getResultSymbol()->getName()));
30✔
166
        instructions.push_back(std::make_unique<Jump>(expression.getFalsyLabel()->getName()));
30✔
167
        instructions.push_back(std::make_unique<Label>(expression.getTruthyLabel()->getName()));
30✔
168
        instructions.push_back(std::make_unique<AssignConstant>("1", expression.getResultSymbol()->getName()));
30✔
169
        instructions.push_back(std::make_unique<Label>(expression.getFalsyLabel()->getName()));
30✔
170
        break;
30✔
171
    default:
×
172
        throw std::runtime_error { "Unidentified unary operator: " + expression.getOperator()->getLexeme() };
×
173
    }
174
}
564✔
175

176
void CodeGeneratingVisitor::visit(ast::TypeCast& expression) {
×
177
    expression.visitOperand(*this);
×
178
    instructions.push_back(std::make_unique<Assign>(expression.operandSymbol()->getName(), expression.getResultSymbol()->getName()));
×
179
}
×
180

181
void CodeGeneratingVisitor::visit(ast::ArithmeticExpression& expression) {
126✔
182
    expression.visitLeftOperand(*this);
126✔
183
    expression.visitRightOperand(*this);
126✔
184

185
    switch (expression.getOperator()->getLexeme().front()) {
126✔
186
    case '+':
94✔
187
        instructions.push_back(std::make_unique<Add>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
94✔
188
                                                     expression.getResultSymbol()->getName()));
188✔
189
        break;
94✔
190
    case '-':
16✔
191
        instructions.push_back(std::make_unique<Sub>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
16✔
192
                                                     expression.getResultSymbol()->getName()));
32✔
193
        break;
16✔
194
    case '*':
8✔
195
        instructions.push_back(std::make_unique<Mul>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
8✔
196
                                                     expression.getResultSymbol()->getName()));
16✔
197
        break;
8✔
198
    case '/':
4✔
199
        instructions.push_back(std::make_unique<Div>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
4✔
200
                                                     expression.getResultSymbol()->getName()));
8✔
201
        break;
4✔
202
    case '%':
4✔
203
        instructions.push_back(std::make_unique<Mod>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
4✔
204
                                                     expression.getResultSymbol()->getName()));
8✔
205
        break;
4✔
206
    default:
×
207
        throw std::runtime_error { "unidentified arithmetic operator: " + expression.getOperator()->getLexeme() };
×
208
    }
209
}
126✔
210

211
void CodeGeneratingVisitor::visit(ast::ShiftExpression& expression) {
28✔
212
    expression.visitLeftOperand(*this);
28✔
213
    expression.visitRightOperand(*this);
28✔
214

215
    switch (expression.getOperator()->getLexeme().front()) {
28✔
216
    case '<':   // <<
10✔
217
        instructions.push_back(std::make_unique<Shl>(
10✔
218
                    expression.leftOperandSymbol()->getName(),
20✔
219
                    expression.rightOperandSymbol()->getName(),
20✔
220
                    expression.getResultSymbol()->getName()));
20✔
221
        break;
10✔
222
    case '>':   // >>
18✔
223
        instructions.push_back(std::make_unique<Shr>(
18✔
224
                    expression.leftOperandSymbol()->getName(),
36✔
225
                    expression.rightOperandSymbol()->getName(),
36✔
226
                    expression.getResultSymbol()->getName()));
36✔
227
        break;
18✔
228
    default:
×
229
        throw std::runtime_error { "unidentified shift operator!" };
×
230
    }
231
}
28✔
232

233
void CodeGeneratingVisitor::visit(ast::ComparisonExpression& expression) {
196✔
234
    expression.visitLeftOperand(*this);
196✔
235
    expression.visitRightOperand(*this);
196✔
236

237
    instructions.push_back(std::make_unique<ValueCompare>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName()));
196✔
238

239
    auto truthyLabel = expression.getTruthyLabel()->getName();
196✔
240
    if (expression.getOperator()->getLexeme() == ">") {
196✔
241
        instructions.push_back(std::make_unique<Jump>(truthyLabel, JumpCondition::IF_ABOVE));
40✔
242
    } else if (expression.getOperator()->getLexeme() == "<") {
156✔
243
        instructions.push_back(std::make_unique<Jump>(truthyLabel, JumpCondition::IF_BELOW));
66✔
244
    } else if (expression.getOperator()->getLexeme() == "<=") {
90✔
245
        instructions.push_back(std::make_unique<Jump>(truthyLabel, JumpCondition::IF_BELOW_OR_EQUAL));
28✔
246
    } else if (expression.getOperator()->getLexeme() == ">=") {
62✔
247
        instructions.push_back(std::make_unique<Jump>(truthyLabel, JumpCondition::IF_ABOVE_OR_EQUAL));
24✔
248
    } else if (expression.getOperator()->getLexeme() == "==") {
38✔
249
        instructions.push_back(std::make_unique<Jump>(truthyLabel, JumpCondition::IF_EQUAL));
32✔
250
    } else if (expression.getOperator()->getLexeme() == "!=") {
6✔
251
        instructions.push_back(std::make_unique<Jump>(truthyLabel, JumpCondition::IF_NOT_EQUAL));
6✔
252
    } else {
253
        throw std::runtime_error { "unidentified ml_op operator!\n" };
×
254
    }
255

256
    instructions.push_back(std::make_unique<AssignConstant>("0", expression.getResultSymbol()->getName()));
196✔
257
    instructions.push_back(std::make_unique<Jump>(expression.getFalsyLabel()->getName()));
196✔
258
    instructions.push_back(std::make_unique<Label>(truthyLabel));
196✔
259
    instructions.push_back(std::make_unique<AssignConstant>("1", expression.getResultSymbol()->getName()));
196✔
260
    instructions.push_back(std::make_unique<Label>(expression.getFalsyLabel()->getName()));
196✔
261
}
196✔
262

263
void CodeGeneratingVisitor::visit(ast::BitwiseExpression& expression) {
12✔
264
    expression.visitLeftOperand(*this);
12✔
265
    expression.visitRightOperand(*this);
12✔
266

267
    switch (expression.getOperator()->getLexeme().front()) {
12✔
268
    case '&':
4✔
269
        instructions.push_back(std::make_unique<And>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
4✔
270
                                                     expression.getResultSymbol()->getName()));
8✔
271
        break;
4✔
272
    case '|':
4✔
273
        instructions.push_back(std::make_unique<Or>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
4✔
274
                                                    expression.getResultSymbol()->getName()));
8✔
275
        break;
4✔
276
    case '^':
4✔
277
        instructions.push_back(std::make_unique<Xor>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
4✔
278
                                                     expression.getResultSymbol()->getName()));
8✔
279
        break;
4✔
280
    default:
×
281
        throw std::runtime_error { "no semantic actions defined for bitwise operator: " + expression.getOperator()->getLexeme() };
×
282
    }
283
}
12✔
284

285
void CodeGeneratingVisitor::visit(ast::LogicalAndExpression& expression) {
8✔
286
    expression.visitLeftOperand(*this);
8✔
287

288
    instructions.push_back(std::make_unique<AssignConstant>("0", expression.getResultSymbol()->getName()));
8✔
289
    instructions.push_back(std::make_unique<ZeroCompare>(expression.leftOperandSymbol()->getName()));
8✔
290
    instructions.push_back(std::make_unique<Jump>(expression.getExitLabel()->getName(), JumpCondition::IF_EQUAL));
8✔
291

292
    expression.visitRightOperand(*this);
8✔
293

294
    instructions.push_back(std::make_unique<ZeroCompare>(expression.rightOperandSymbol()->getName()));
8✔
295
    instructions.push_back(std::make_unique<Jump>(expression.getExitLabel()->getName(), JumpCondition::IF_EQUAL));
8✔
296
    instructions.push_back(std::make_unique<AssignConstant>("1", expression.getResultSymbol()->getName()));
8✔
297

298
    instructions.push_back(std::make_unique<Label>(expression.getExitLabel()->getName()));
8✔
299
}
8✔
300

301
void CodeGeneratingVisitor::visit(ast::LogicalOrExpression& expression) {
8✔
302
    expression.visitLeftOperand(*this);
8✔
303

304
    instructions.push_back(std::make_unique<AssignConstant>("1", expression.getResultSymbol()->getName()));
8✔
305
    instructions.push_back(std::make_unique<ZeroCompare>(expression.leftOperandSymbol()->getName()));
8✔
306
    instructions.push_back(std::make_unique<Jump>(expression.getExitLabel()->getName(), JumpCondition::IF_NOT_EQUAL));
8✔
307

308
    expression.visitRightOperand(*this);
8✔
309

310
    instructions.push_back(std::make_unique<ZeroCompare>(expression.rightOperandSymbol()->getName()));
8✔
311
    instructions.push_back(std::make_unique<Jump>(expression.getExitLabel()->getName(), JumpCondition::IF_NOT_EQUAL));
8✔
312
    instructions.push_back(std::make_unique<AssignConstant>("0", expression.getResultSymbol()->getName()));
8✔
313

314
    instructions.push_back(std::make_unique<Label>(expression.getExitLabel()->getName()));
8✔
315
}
8✔
316

317
void CodeGeneratingVisitor::visit(ast::AssignmentExpression& expression) {
504✔
318
    expression.visitLeftOperand(*this);
504✔
319
    expression.visitRightOperand(*this);
504✔
320

321
    auto assignmentOperator = expression.getOperator();
504✔
322
    auto resultName = expression.getResultSymbol()->getName();
504✔
323
    if (assignmentOperator->getLexeme() == "+=")
504✔
324
        instructions.push_back(std::make_unique<Add>(
10✔
325
                    resultName,
326
                    expression.rightOperandSymbol()->getName(),
20✔
327
                    resultName
328
        ));
329
    else if (assignmentOperator->getLexeme() == "-=")
494✔
330
        instructions.push_back(std::make_unique<Sub>(
6✔
331
                    resultName,
332
                    expression.rightOperandSymbol()->getName(),
12✔
333
                    resultName
334
        ));
335
    else if (assignmentOperator->getLexeme() == "*=")
488✔
336
        instructions.push_back(std::make_unique<Mul>(
8✔
337
                    resultName,
338
                    expression.rightOperandSymbol()->getName(),
16✔
339
                    resultName
340
        ));
341
    else if (assignmentOperator->getLexeme() == "/=")
480✔
342
        instructions.push_back(std::make_unique<Div>(
6✔
343
                    resultName,
344
                    expression.rightOperandSymbol()->getName(),
12✔
345
                    resultName
346
        ));
347
    else if (assignmentOperator->getLexeme() == "%=")
474✔
348
        instructions.push_back(std::make_unique<Mod>(
6✔
349
                    resultName,
350
                    expression.rightOperandSymbol()->getName(),
12✔
351
                    resultName
352
        ));
353
    else if (assignmentOperator->getLexeme() == "&=")
468✔
354
        instructions.push_back(std::make_unique<And>(
6✔
355
                    resultName,
356
                    expression.rightOperandSymbol()->getName(),
12✔
357
                    resultName
358
        ));
359
    else if (assignmentOperator->getLexeme() == "^=")
462✔
360
        instructions.push_back(std::make_unique<Xor>(
6✔
361
                    resultName,
362
                    expression.rightOperandSymbol()->getName(),
12✔
363
                    resultName
364
        ));
365
    else if (assignmentOperator->getLexeme() == "|=")
456✔
366
        instructions.push_back(std::make_unique<Or>(
6✔
367
                    resultName,
368
                    expression.rightOperandSymbol()->getName(),
12✔
369
                    resultName
370
        ));
371
    else if (assignmentOperator->getLexeme() == "<<=") {
450✔
372
        instructions.push_back(std::make_unique<Shl>(
10✔
373
                    resultName,
374
                    expression.rightOperandSymbol()->getName(),
20✔
375
                    resultName
376
        ));
377
    } else if (assignmentOperator->getLexeme() == ">>=") {
440✔
378
        instructions.push_back(std::make_unique<Shr>(
10✔
379
                    resultName,
380
                    expression.rightOperandSymbol()->getName(),
20✔
381
                    resultName
382
        ));
383
    } else if (assignmentOperator->getLexeme() == "=") {
430✔
384
        if (expression.leftOperandLvalueSymbol()) {
430✔
385
            instructions.push_back(std::make_unique<LvalueAssign>(
14✔
386
                        expression.rightOperandSymbol()->getName(),
28✔
387
                        expression.leftOperandLvalueSymbol()->getName()
28✔
388
            ));
389
        } else {
390
            instructions.push_back(std::make_unique<Assign>(
416✔
391
                        expression.rightOperandSymbol()->getName(),
832✔
392
                        resultName
393
            ));
394
        }
395
        return;
430✔
396
    } else {
397
        throw std::runtime_error { "unidentified assignment operator: " + assignmentOperator->getLexeme() };
×
398
    }
399

400
    // Compound assign updated the value temp; write back through pointer lvalues (e.g. *p += 1).
401
    if (auto* lvalue = expression.leftOperandLvalueSymbol()) {
74✔
402
        instructions.push_back(std::make_unique<LvalueAssign>(resultName, lvalue->getName()));
20✔
403
    }
404
}
504✔
405

406
void CodeGeneratingVisitor::visit(ast::ExpressionList& expression) {
2✔
407
    expression.visitLeftOperand(*this);
2✔
408
    expression.visitRightOperand(*this);
2✔
409
}
2✔
410

411
void CodeGeneratingVisitor::visit(ast::Operator&) {
×
412
}
×
413

414
void CodeGeneratingVisitor::visit(ast::JumpStatement& statement) {
8✔
415
    if (!statement.getJumpTo()) {
8✔
NEW
416
        throw std::runtime_error { "JumpStatement has no target label" };
×
417
    }
418
    instructions.push_back(std::make_unique<Jump>(statement.getJumpTo()->getName()));
8✔
419
}
8✔
420

421
void CodeGeneratingVisitor::visit(ast::ReturnStatement& statement) {
506✔
422
    statement.returnExpression->accept(*this);
506✔
423
    instructions.push_back(std::make_unique<Return>(statement.returnExpression->getResultSymbol()->getName()));
506✔
424
}
506✔
425

426
void CodeGeneratingVisitor::visit(ast::VoidReturnStatement &statement) { instructions.push_back(std::make_unique<VoidReturn>()); }
22✔
427

428
void CodeGeneratingVisitor::visit(ast::IfStatement& statement) {
38✔
429
    statement.testExpression->accept(*this);
38✔
430

431
    instructions.push_back(std::make_unique<ZeroCompare>(statement.testExpression->getResultSymbol()->getName()));
38✔
432
    instructions.push_back(std::make_unique<Jump>(statement.getFalsyLabel()->getName(), JumpCondition::IF_EQUAL));
38✔
433

434
    statement.body->accept(*this);
38✔
435

436
    instructions.push_back(std::make_unique<Label>(statement.getFalsyLabel()->getName()));
38✔
437
}
38✔
438

439
void CodeGeneratingVisitor::visit(ast::IfElseStatement& statement) {
16✔
440
    statement.testExpression->accept(*this);
16✔
441

442
    instructions.push_back(std::make_unique<ZeroCompare>(statement.testExpression->getResultSymbol()->getName()));
16✔
443
    instructions.push_back(std::make_unique<Jump>(statement.getFalsyLabel()->getName(), JumpCondition::IF_EQUAL));
16✔
444

445
    statement.truthyBody->accept(*this);
16✔
446
    instructions.push_back(std::make_unique<Jump>(statement.getExitLabel()->getName()));
16✔
447
    instructions.push_back(std::make_unique<Label>(statement.getFalsyLabel()->getName()));
16✔
448

449
    statement.falsyBody->accept(*this);
16✔
450
    instructions.push_back(std::make_unique<Label>(statement.getExitLabel()->getName()));
16✔
451
}
16✔
452

453
void CodeGeneratingVisitor::visit(ast::LoopStatement& loop) {
66✔
454
    loop.header->accept(*this);
66✔
455
    loop.body->accept(*this);
66✔
456
    // continue target: for-loops place a label before the increment; while reuses entry.
457
    if (loop.header->getLoopContinue()
66✔
458
            && loop.header->getLoopContinue()->getName() != loop.header->getLoopEntry()->getName()) {
132✔
459
        instructions.push_back(std::make_unique<Label>(loop.header->getLoopContinue()->getName()));
28✔
460
    }
461
    if (loop.header->increment) {
66✔
462
        loop.header->increment->accept(*this);
28✔
463
    }
464

465
    instructions.push_back(std::make_unique<Jump>(loop.header->getLoopEntry()->getName()));
66✔
466
    instructions.push_back(std::make_unique<Label>(loop.header->getLoopExit()->getName()));
66✔
467
}
66✔
468

469
void CodeGeneratingVisitor::visit(ast::ForLoopHeader& loopHeader) {
40✔
470
    if (loopHeader.initialization) {
40✔
471
        loopHeader.initialization->accept(*this);
26✔
472
    }
473

474
    instructions.push_back(std::make_unique<Label>(loopHeader.getLoopEntry()->getName()));
40✔
475
    if (loopHeader.clause) {
40✔
476
        loopHeader.clause->accept(*this);
30✔
477
        instructions.push_back(std::make_unique<ZeroCompare>(loopHeader.clause->getResultSymbol()->getName()));
30✔
478
        instructions.push_back(std::make_unique<Jump>(loopHeader.getLoopExit()->getName(), JumpCondition::IF_EQUAL));
30✔
479
    }
480
}
40✔
481

482
void CodeGeneratingVisitor::visit(ast::WhileLoopHeader& loopHeader) {
26✔
483
    instructions.push_back(std::make_unique<Label>(loopHeader.getLoopEntry()->getName()));
26✔
484
    loopHeader.clause->accept(*this);
26✔
485
    instructions.push_back(std::make_unique<ZeroCompare>(loopHeader.clause->getResultSymbol()->getName()));
26✔
486
    instructions.push_back(std::make_unique<Jump>(loopHeader.getLoopExit()->getName(), JumpCondition::IF_EQUAL));
26✔
487
}
26✔
488

489
void CodeGeneratingVisitor::visit(ast::Pointer&) {
70✔
490
}
70✔
491

492
void CodeGeneratingVisitor::visit(ast::Identifier&) {
798✔
493
}
798✔
494

495
void CodeGeneratingVisitor::visit(ast::FunctionDeclarator& declarator) {
522✔
496
    declarator.visitFormalArguments(*this);
522✔
497
}
522✔
498

499
void CodeGeneratingVisitor::visit(ast::ArrayDeclarator& declaration) {
×
500
    declaration.subscriptExpression->accept(*this);
×
501
    throw std::runtime_error { "not implemented" };
×
502
}
503

504
void CodeGeneratingVisitor::visit(ast::FormalArgument& parameter) {
192✔
505
    parameter.visitDeclarator(*this);
192✔
506
}
192✔
507

508
void CodeGeneratingVisitor::visit(ast::FunctionDefinition& function) {
520✔
509
    // Semantic analysis skips setSymbol when the definition is invalid (e.g. name conflicts).
510
    if (!function.hasSymbol()) {
520✔
NEW
511
        return;
×
512
    }
513

514
    function.visitDeclarator(*this);
520✔
515

516
    std::vector<Value> values;
520✔
517
    for (auto& valueSymbol : function.getLocalVariables()) {
5,310✔
518
        values.push_back( {
9,580✔
519
                valueSymbol.second.getName(),
9,580✔
520
                valueSymbol.second.getIndex(),
521
                // FIXME:
522
                Type::INTEGRAL,
523
                valueSymbol.second.getType().getSize()
9,580✔
524
        });
525
    }
520✔
526
    std::vector<Value> arguments;
520✔
527
    for (auto& argumentSymbol : function.getArguments()) {
712✔
528
        arguments.push_back( {
384✔
529
                argumentSymbol.getName(),
384✔
530
                argumentSymbol.getIndex(),
531
                // FIXME:
532
                Type::INTEGRAL,
533
                argumentSymbol.getType().getSize()
384✔
534
        });
535
    }
520✔
536
    instructions.push_back(std::make_unique<StartProcedure>(function.getSymbol()->getName(), std::move(values), std::move(arguments)));
520✔
537

538
    auto instructionsBak = std::move(instructions);
520✔
539
    function.visitBody(*this);
520✔
540
    auto functionBody = toBasicBlocks(std::move(instructions));
520✔
541
    for (auto& bb : functionBody) {
2,098✔
542
        if (!bb->terminates()) {
1,578✔
543
            bb->appendInstruction(std::make_unique<VoidReturn>());
18✔
544
        }
545
        instructionsBak.push_back(std::move(bb));
1,578✔
546
    }
547
    instructions = std::move(instructionsBak);
520✔
548

549
    instructions.push_back(std::make_unique<EndProcedure>(function.getSymbol()->getName()));
520✔
550
}
520✔
551

552
void CodeGeneratingVisitor::visit(ast::Block& block) {
674✔
553
    block.visitChildren(*this);
674✔
554
}
674✔
555

556
std::vector<std::unique_ptr<Quadruple>> CodeGeneratingVisitor::getQuadruples() {
416✔
557
    return std::move(instructions);
416✔
558
}
559

560
std::vector<std::unique_ptr<BasicBlock>> toBasicBlocks(std::vector<std::unique_ptr<Quadruple>> instructions) {
526✔
561
    std::vector<std::unique_ptr<BasicBlock>> basicBlocks {};
526✔
562

563
    std::unique_ptr<BasicBlock> bb = std::make_unique<BasicBlock>();
526✔
564

565
    std::vector<std::unique_ptr<Quadruple>> bbInstructions;
526✔
566
    for (auto& instruction : instructions) {
10,988✔
567
        if (bb->terminates() || instruction->isLabel()) {
10,462✔
568
            basicBlocks.push_back(std::move(bb));
1,066✔
569
            bb = std::make_unique<BasicBlock>();
1,066✔
570
            basicBlocks.back()->setSuccessor(bb.get());
1,066✔
571
        }
572
        bb->appendInstruction(std::move(instruction));
10,462✔
573
    }
574
    basicBlocks.push_back(std::move(bb));
526✔
575

576
    return basicBlocks;
1,052✔
577
}
526✔
578

579
} // namespace codegen
580

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc