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

rieske / trans / 28294438679

27 Jun 2026 04:05PM UTC coverage: 89.399% (+0.009%) from 89.39%
28294438679

push

github

web-flow
Merge pull request #33 from rieske/fix/unary-operand-double-visit

Fix unary codegen double-evaluating operands

4832 of 5405 relevant lines covered (89.4%)

186702.52 hits per line

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

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

3
#include <iostream>
4
#include <stdexcept>
5

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

9
#include "quadruples/Assign.h"
10
#include "quadruples/Argument.h"
11
#include "quadruples/Call.h"
12
#include "quadruples/Retrieve.h"
13
#include "quadruples/AssignConstant.h"
14
#include "quadruples/Inc.h"
15
#include "quadruples/Dec.h"
16
#include "quadruples/AddressOf.h"
17
#include "quadruples/Dereference.h"
18
#include "quadruples/UnaryMinus.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() {
162✔
42
}
162✔
43

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

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

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

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

58
void CodeGeneratingVisitor::visit(ast::InitializedDeclarator& declarator) {
282✔
59
    declarator.visitChildren(*this);
282✔
60

61
    if (declarator.hasInitializer()) {
282✔
62
        instructions.push_back(std::make_unique<Assign>(declarator.getInitializerHolder()->getName(), declarator.getHolder()->getName()));
30✔
63
    }
64
}
282✔
65

66
void CodeGeneratingVisitor::visit(ast::ArrayAccess& arrayAccess) {
×
67
    arrayAccess.visitLeftOperand(*this);
×
68
    arrayAccess.visitRightOperand(*this);
×
69

70
    // TODO: not implemented yet
71
    //auto offset = arrayAccess.rightOperandSymbol();
72
    //quadruples.push_back( { code_generator::INDEX, arrayAccess.leftOperandSymbol(), offset, arrayAccess.getResultSymbol() });
73
    //quadruples.push_back( { code_generator::INDEX_ADDR, arrayAccess.leftOperandSymbol(), offset, arrayAccess.getLvalue() });
74
}
×
75

76
void CodeGeneratingVisitor::visit(ast::FunctionCall& functionCall) {
574✔
77
    functionCall.visitOperand(*this);
574✔
78
    functionCall.visitArguments(*this);
574✔
79

80
    for (auto& expression : functionCall.getArgumentList()) {
1,858✔
81
        instructions.push_back(std::make_unique<Argument>(expression->getResultSymbol()->getName()));
1,284✔
82
    }
83

84
    instructions.push_back(std::make_unique<Call>(functionCall.getSymbol()->getName()));
574✔
85
    if (!functionCall.getType().isVoid()) {
574✔
86
        instructions.push_back(std::make_unique<Retrieve>(functionCall.getResultSymbol()->getName()));
574✔
87
    }
88
}
574✔
89

90
void CodeGeneratingVisitor::visit(ast::IdentifierExpression&) {
1,448✔
91
}
1,448✔
92

93
void CodeGeneratingVisitor::visit(ast::ConstantExpression& constant) {
506✔
94
    instructions.push_back(std::make_unique<AssignConstant>(constant.getValue(), constant.getResultSymbol()->getName()));
506✔
95
}
506✔
96

97
void CodeGeneratingVisitor::visit(ast::StringLiteralExpression& stringLiteral) {
528✔
98
    instructions.push_back(
528✔
99
        std::make_unique<AssignConstant>(stringLiteral.getConstantSymbol(), stringLiteral.getResultSymbol()->getName())
1,056✔
100
    );
101
}
528✔
102

103
void CodeGeneratingVisitor::visit(ast::PostfixExpression& expression) {
16✔
104
    expression.visitOperand(*this);
16✔
105

106
    auto resultSymbolName = expression.getResultSymbol()->getName();
16✔
107
    auto preOperationSymbol = expression.getPreOperationSymbol()->getName();
16✔
108
    instructions.push_back(std::make_unique<Assign>(resultSymbolName, preOperationSymbol));
16✔
109

110
    if (expression.getOperator()->getLexeme() == "++") {
16✔
111
        instructions.push_back(std::make_unique<Inc>(resultSymbolName));
12✔
112
    } else if (expression.getOperator()->getLexeme() == "--") {
4✔
113
        instructions.push_back(std::make_unique<Dec>(resultSymbolName));
4✔
114
    }
115

116
    expression.setResultSymbol(*expression.getPreOperationSymbol());
16✔
117
}
16✔
118

119
void CodeGeneratingVisitor::visit(ast::PrefixExpression& expression) {
8✔
120
    expression.visitOperand(*this);
8✔
121

122
    if (expression.getOperator()->getLexeme() == "++") {
8✔
123
        instructions.push_back(std::make_unique<Inc>(expression.getResultSymbol()->getName()));
4✔
124
    } else if (expression.getOperator()->getLexeme() == "--") {
4✔
125
        instructions.push_back(std::make_unique<Dec>(expression.getResultSymbol()->getName()));
4✔
126
    }
127
}
8✔
128

129
void CodeGeneratingVisitor::visit(ast::UnaryExpression& expression) {
370✔
130
    expression.visitOperand(*this);
370✔
131

132
    switch (expression.getOperator()->getLexeme().front()) {
370✔
133
    case '&':
240✔
134
        instructions.push_back(std::make_unique<AddressOf>(expression.operandSymbol()->getName(), expression.getResultSymbol()->getName()));
240✔
135
        break;
240✔
136
    case '*':
28✔
137
        instructions.push_back(std::make_unique<Dereference>(expression.operandSymbol()->getName(), expression.getLvalueSymbol()->getName(),
28✔
138
                                                             expression.getResultSymbol()->getName()));
56✔
139
        break;
28✔
140
    case '+':
×
141
        break;
×
142
    case '-':
84✔
143
        instructions.push_back(std::make_unique<UnaryMinus>(expression.operandSymbol()->getName(), expression.getResultSymbol()->getName()));
84✔
144
        break;
84✔
145
    case '!':
18✔
146
        instructions.push_back(std::make_unique<ZeroCompare>(expression.operandSymbol()->getName()));
18✔
147
        instructions.push_back(std::make_unique<Jump>(expression.getTruthyLabel()->getName(), JumpCondition::IF_EQUAL));
18✔
148
        instructions.push_back(std::make_unique<AssignConstant>("0", expression.getResultSymbol()->getName()));
18✔
149
        instructions.push_back(std::make_unique<Jump>(expression.getFalsyLabel()->getName()));
18✔
150
        instructions.push_back(std::make_unique<Label>(expression.getTruthyLabel()->getName()));
18✔
151
        instructions.push_back(std::make_unique<AssignConstant>("1", expression.getResultSymbol()->getName()));
18✔
152
        instructions.push_back(std::make_unique<Label>(expression.getFalsyLabel()->getName()));
18✔
153
        break;
18✔
154
    default:
×
155
        throw std::runtime_error { "Unidentified unary operator: " + expression.getOperator()->getLexeme() };
×
156
    }
157
}
370✔
158

159
void CodeGeneratingVisitor::visit(ast::TypeCast& expression) {
×
160
    expression.visitOperand(*this);
×
161
    instructions.push_back(std::make_unique<Assign>(expression.operandSymbol()->getName(), expression.getResultSymbol()->getName()));
×
162
}
×
163

164
void CodeGeneratingVisitor::visit(ast::ArithmeticExpression& expression) {
36✔
165
    expression.visitLeftOperand(*this);
36✔
166
    expression.visitRightOperand(*this);
36✔
167

168
    switch (expression.getOperator()->getLexeme().front()) {
36✔
169
    case '+':
12✔
170
        instructions.push_back(std::make_unique<Add>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
12✔
171
                                                     expression.getResultSymbol()->getName()));
24✔
172
        break;
12✔
173
    case '-':
14✔
174
        instructions.push_back(std::make_unique<Sub>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
14✔
175
                                                     expression.getResultSymbol()->getName()));
28✔
176
        break;
14✔
177
    case '*':
6✔
178
        instructions.push_back(std::make_unique<Mul>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
6✔
179
                                                     expression.getResultSymbol()->getName()));
12✔
180
        break;
6✔
181
    case '/':
2✔
182
        instructions.push_back(std::make_unique<Div>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
2✔
183
                                                     expression.getResultSymbol()->getName()));
4✔
184
        break;
2✔
185
    case '%':
2✔
186
        instructions.push_back(std::make_unique<Mod>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
2✔
187
                                                     expression.getResultSymbol()->getName()));
4✔
188
        break;
2✔
189
    default:
×
190
        throw std::runtime_error { "unidentified arithmetic operator: " + expression.getOperator()->getLexeme() };
×
191
    }
192
}
36✔
193

194
void CodeGeneratingVisitor::visit(ast::ShiftExpression& expression) {
12✔
195
    expression.visitLeftOperand(*this);
12✔
196
    expression.visitRightOperand(*this);
12✔
197

198
    switch (expression.getOperator()->getLexeme().front()) {
12✔
199
    case '<':   // <<
6✔
200
        instructions.push_back(std::make_unique<Shl>(
6✔
201
                    expression.leftOperandSymbol()->getName(),
12✔
202
                    expression.rightOperandSymbol()->getName(),
12✔
203
                    expression.getResultSymbol()->getName()));
12✔
204
        break;
6✔
205
    case '>':   // >>
6✔
206
        instructions.push_back(std::make_unique<Shr>(
6✔
207
                    expression.leftOperandSymbol()->getName(),
12✔
208
                    expression.rightOperandSymbol()->getName(),
12✔
209
                    expression.getResultSymbol()->getName()));
12✔
210
        break;
6✔
211
    default:
×
212
        throw std::runtime_error { "unidentified shift operator!" };
×
213
    }
214
}
12✔
215

216
void CodeGeneratingVisitor::visit(ast::ComparisonExpression& expression) {
140✔
217
    expression.visitLeftOperand(*this);
140✔
218
    expression.visitRightOperand(*this);
140✔
219

220
    instructions.push_back(std::make_unique<ValueCompare>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName()));
140✔
221

222
    auto truthyLabel = expression.getTruthyLabel()->getName();
140✔
223
    if (expression.getOperator()->getLexeme() == ">") {
140✔
224
        instructions.push_back(std::make_unique<Jump>(truthyLabel, JumpCondition::IF_ABOVE));
36✔
225
    } else if (expression.getOperator()->getLexeme() == "<") {
104✔
226
        instructions.push_back(std::make_unique<Jump>(truthyLabel, JumpCondition::IF_BELOW));
32✔
227
    } else if (expression.getOperator()->getLexeme() == "<=") {
72✔
228
        instructions.push_back(std::make_unique<Jump>(truthyLabel, JumpCondition::IF_BELOW_OR_EQUAL));
28✔
229
    } else if (expression.getOperator()->getLexeme() == ">=") {
44✔
230
        instructions.push_back(std::make_unique<Jump>(truthyLabel, JumpCondition::IF_ABOVE_OR_EQUAL));
24✔
231
    } else if (expression.getOperator()->getLexeme() == "==") {
20✔
232
        instructions.push_back(std::make_unique<Jump>(truthyLabel, JumpCondition::IF_EQUAL));
14✔
233
    } else if (expression.getOperator()->getLexeme() == "!=") {
6✔
234
        instructions.push_back(std::make_unique<Jump>(truthyLabel, JumpCondition::IF_NOT_EQUAL));
6✔
235
    } else {
236
        throw std::runtime_error { "unidentified ml_op operator!\n" };
×
237
    }
238

239
    instructions.push_back(std::make_unique<AssignConstant>("0", expression.getResultSymbol()->getName()));
140✔
240
    instructions.push_back(std::make_unique<Jump>(expression.getFalsyLabel()->getName()));
140✔
241
    instructions.push_back(std::make_unique<Label>(truthyLabel));
140✔
242
    instructions.push_back(std::make_unique<AssignConstant>("1", expression.getResultSymbol()->getName()));
140✔
243
    instructions.push_back(std::make_unique<Label>(expression.getFalsyLabel()->getName()));
140✔
244
}
140✔
245

246
void CodeGeneratingVisitor::visit(ast::BitwiseExpression& expression) {
6✔
247
    expression.visitLeftOperand(*this);
6✔
248
    expression.visitRightOperand(*this);
6✔
249

250
    switch (expression.getOperator()->getLexeme().front()) {
6✔
251
    case '&':
2✔
252
        instructions.push_back(std::make_unique<And>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
2✔
253
                                                     expression.getResultSymbol()->getName()));
4✔
254
        break;
2✔
255
    case '|':
2✔
256
        instructions.push_back(std::make_unique<Or>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
2✔
257
                                                    expression.getResultSymbol()->getName()));
4✔
258
        break;
2✔
259
    case '^':
2✔
260
        instructions.push_back(std::make_unique<Xor>(expression.leftOperandSymbol()->getName(), expression.rightOperandSymbol()->getName(),
2✔
261
                                                     expression.getResultSymbol()->getName()));
4✔
262
        break;
2✔
263
    default:
×
264
        throw std::runtime_error { "no semantic actions defined for bitwise operator: " + expression.getOperator()->getLexeme() };
×
265
    }
266
}
6✔
267

268
void CodeGeneratingVisitor::visit(ast::LogicalAndExpression& expression) {
4✔
269
    expression.visitLeftOperand(*this);
4✔
270

271
    instructions.push_back(std::make_unique<AssignConstant>("0", expression.getResultSymbol()->getName()));
4✔
272
    instructions.push_back(std::make_unique<ZeroCompare>(expression.leftOperandSymbol()->getName()));
4✔
273
    instructions.push_back(std::make_unique<Jump>(expression.getExitLabel()->getName(), JumpCondition::IF_EQUAL));
4✔
274

275
    expression.visitRightOperand(*this);
4✔
276

277
    instructions.push_back(std::make_unique<ZeroCompare>(expression.rightOperandSymbol()->getName()));
4✔
278
    instructions.push_back(std::make_unique<Jump>(expression.getExitLabel()->getName(), JumpCondition::IF_EQUAL));
4✔
279
    instructions.push_back(std::make_unique<AssignConstant>("1", expression.getResultSymbol()->getName()));
4✔
280

281
    instructions.push_back(std::make_unique<Label>(expression.getExitLabel()->getName()));
4✔
282
}
4✔
283

284
void CodeGeneratingVisitor::visit(ast::LogicalOrExpression& expression) {
4✔
285
    expression.visitLeftOperand(*this);
4✔
286

287
    instructions.push_back(std::make_unique<AssignConstant>("1", expression.getResultSymbol()->getName()));
4✔
288
    instructions.push_back(std::make_unique<ZeroCompare>(expression.leftOperandSymbol()->getName()));
4✔
289
    instructions.push_back(std::make_unique<Jump>(expression.getExitLabel()->getName(), JumpCondition::IF_NOT_EQUAL));
4✔
290

291
    expression.visitRightOperand(*this);
4✔
292

293
    instructions.push_back(std::make_unique<ZeroCompare>(expression.rightOperandSymbol()->getName()));
4✔
294
    instructions.push_back(std::make_unique<Jump>(expression.getExitLabel()->getName(), JumpCondition::IF_NOT_EQUAL));
4✔
295
    instructions.push_back(std::make_unique<AssignConstant>("0", expression.getResultSymbol()->getName()));
4✔
296

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

300
void CodeGeneratingVisitor::visit(ast::AssignmentExpression& expression) {
90✔
301
    expression.visitLeftOperand(*this);
90✔
302
    expression.visitRightOperand(*this);
90✔
303

304
    auto assignmentOperator = expression.getOperator();
90✔
305
    if (assignmentOperator->getLexeme() == "+=")
90✔
306
        instructions.push_back(std::make_unique<Add>(
2✔
307
                    expression.getResultSymbol()->getName(),
4✔
308
                    expression.rightOperandSymbol()->getName(),
4✔
309
                    expression.getResultSymbol()->getName()
4✔
310
        ));
311
    else if (assignmentOperator->getLexeme() == "-=")
88✔
312
        instructions.push_back(std::make_unique<Sub>(
2✔
313
                    expression.getResultSymbol()->getName(),
4✔
314
                    expression.rightOperandSymbol()->getName(),
4✔
315
                    expression.getResultSymbol()->getName()
4✔
316
        ));
317
    else if (assignmentOperator->getLexeme() == "*=")
86✔
318
        instructions.push_back(std::make_unique<Mul>(
4✔
319
                    expression.getResultSymbol()->getName(),
8✔
320
                    expression.rightOperandSymbol()->getName(),
8✔
321
                    expression.getResultSymbol()->getName()
8✔
322
        ));
323
    else if (assignmentOperator->getLexeme() == "/=")
82✔
324
        instructions.push_back(std::make_unique<Div>(
2✔
325
                    expression.getResultSymbol()->getName(),
4✔
326
                    expression.rightOperandSymbol()->getName(),
4✔
327
                    expression.getResultSymbol()->getName()
4✔
328
        ));
329
    else if (assignmentOperator->getLexeme() == "%=")
80✔
330
        instructions.push_back(std::make_unique<Mod>(
2✔
331
                    expression.getResultSymbol()->getName(),
4✔
332
                    expression.rightOperandSymbol()->getName(),
4✔
333
                    expression.getResultSymbol()->getName()
4✔
334
        ));
335
    else if (assignmentOperator->getLexeme() == "&=")
78✔
336
        instructions.push_back(std::make_unique<And>(
2✔
337
                    expression.getResultSymbol()->getName(),
4✔
338
                    expression.rightOperandSymbol()->getName(),
4✔
339
                    expression.getResultSymbol()->getName()
4✔
340
        ));
341
    else if (assignmentOperator->getLexeme() == "^=")
76✔
342
        instructions.push_back(std::make_unique<Xor>(
2✔
343
                    expression.getResultSymbol()->getName(),
4✔
344
                    expression.rightOperandSymbol()->getName(),
4✔
345
                    expression.getResultSymbol()->getName()
4✔
346
        ));
347
    else if (assignmentOperator->getLexeme() == "|=")
74✔
348
        instructions.push_back(std::make_unique<Or>(
2✔
349
                    expression.getResultSymbol()->getName(),
4✔
350
                    expression.rightOperandSymbol()->getName(),
4✔
351
                    expression.getResultSymbol()->getName()
4✔
352
        ));
353
    else if (assignmentOperator->getLexeme() == "<<=") {
72✔
354
        instructions.push_back(std::make_unique<Shl>(
6✔
355
                    expression.getResultSymbol()->getName(),
12✔
356
                    expression.rightOperandSymbol()->getName(),
12✔
357
                    expression.getResultSymbol()->getName()
12✔
358
        ));
359
    } else if (assignmentOperator->getLexeme() == ">>=") {
66✔
360
        instructions.push_back(std::make_unique<Shr>(
6✔
361
                    expression.getResultSymbol()->getName(),
12✔
362
                    expression.rightOperandSymbol()->getName(),
12✔
363
                    expression.getResultSymbol()->getName()
12✔
364
        ));
365
    } else if (assignmentOperator->getLexeme() == "=") {
60✔
366
        if (expression.leftOperandLvalueSymbol()) {
60✔
367
            instructions.push_back(std::make_unique<LvalueAssign>(
8✔
368
                        expression.rightOperandSymbol()->getName(),
16✔
369
                        expression.leftOperandLvalueSymbol()->getName()
16✔
370
            ));
371
        } else {
372
            instructions.push_back(std::make_unique<Assign>(
52✔
373
                        expression.rightOperandSymbol()->getName(),
104✔
374
                        expression.getResultSymbol()->getName()
104✔
375
            ));
376
        }
377
    } else {
378
        throw std::runtime_error { "unidentified assignment operator: " + assignmentOperator->getLexeme() };
×
379
    }
380
}
90✔
381

382
void CodeGeneratingVisitor::visit(ast::ExpressionList& expression) {
×
383
    expression.visitLeftOperand(*this);
×
384
    expression.visitRightOperand(*this);
×
385
}
×
386

387
void CodeGeneratingVisitor::visit(ast::Operator&) {
×
388
}
×
389

390
void CodeGeneratingVisitor::visit(ast::JumpStatement& statement) {
×
391
    throw std::runtime_error { "not implemented" };
×
392
}
393

394
void CodeGeneratingVisitor::visit(ast::ReturnStatement& statement) {
194✔
395
    statement.returnExpression->accept(*this);
194✔
396
    instructions.push_back(std::make_unique<Return>(statement.returnExpression->getResultSymbol()->getName()));
194✔
397
}
194✔
398

399
void CodeGeneratingVisitor::visit(ast::VoidReturnStatement &statement) { instructions.push_back(std::make_unique<VoidReturn>()); }
6✔
400

401
void CodeGeneratingVisitor::visit(ast::IfStatement& statement) {
8✔
402
    statement.testExpression->accept(*this);
8✔
403

404
    instructions.push_back(std::make_unique<ZeroCompare>(statement.testExpression->getResultSymbol()->getName()));
8✔
405
    instructions.push_back(std::make_unique<Jump>(statement.getFalsyLabel()->getName(), JumpCondition::IF_EQUAL));
8✔
406

407
    statement.body->accept(*this);
8✔
408

409
    instructions.push_back(std::make_unique<Label>(statement.getFalsyLabel()->getName()));
8✔
410
}
8✔
411

412
void CodeGeneratingVisitor::visit(ast::IfElseStatement& statement) {
6✔
413
    statement.testExpression->accept(*this);
6✔
414

415
    instructions.push_back(std::make_unique<ZeroCompare>(statement.testExpression->getResultSymbol()->getName()));
6✔
416
    instructions.push_back(std::make_unique<Jump>(statement.getFalsyLabel()->getName(), JumpCondition::IF_EQUAL));
6✔
417

418
    statement.truthyBody->accept(*this);
6✔
419
    instructions.push_back(std::make_unique<Jump>(statement.getExitLabel()->getName()));
6✔
420
    instructions.push_back(std::make_unique<Label>(statement.getFalsyLabel()->getName()));
6✔
421

422
    statement.falsyBody->accept(*this);
6✔
423
    instructions.push_back(std::make_unique<Label>(statement.getExitLabel()->getName()));
6✔
424
}
6✔
425

426
void CodeGeneratingVisitor::visit(ast::LoopStatement& loop) {
16✔
427
    loop.header->accept(*this);
16✔
428
    loop.body->accept(*this);
16✔
429
    // FIXME:
430
    if (loop.header->increment) {
16✔
431
        loop.header->increment->accept(*this);
8✔
432
    }
433

434
    instructions.push_back(std::make_unique<Jump>(loop.header->getLoopEntry()->getName()));
16✔
435
    instructions.push_back(std::make_unique<Label>(loop.header->getLoopExit()->getName()));
16✔
436
}
16✔
437

438
void CodeGeneratingVisitor::visit(ast::ForLoopHeader& loopHeader) {
8✔
439
    loopHeader.initialization->accept(*this);
8✔
440

441
    instructions.push_back(std::make_unique<Label>(loopHeader.getLoopEntry()->getName()));
8✔
442
    loopHeader.clause->accept(*this);
8✔
443
    instructions.push_back(std::make_unique<ZeroCompare>(loopHeader.clause->getResultSymbol()->getName()));
8✔
444
    instructions.push_back(std::make_unique<Jump>(loopHeader.getLoopExit()->getName(), JumpCondition::IF_EQUAL));
8✔
445
}
8✔
446

447
void CodeGeneratingVisitor::visit(ast::WhileLoopHeader& loopHeader) {
8✔
448
    instructions.push_back(std::make_unique<Label>(loopHeader.getLoopEntry()->getName()));
8✔
449
    loopHeader.clause->accept(*this);
8✔
450
    instructions.push_back(std::make_unique<ZeroCompare>(loopHeader.clause->getResultSymbol()->getName()));
8✔
451
    instructions.push_back(std::make_unique<Jump>(loopHeader.getLoopExit()->getName(), JumpCondition::IF_EQUAL));
8✔
452
}
8✔
453

454
void CodeGeneratingVisitor::visit(ast::Pointer&) {
10✔
455
}
10✔
456

457
void CodeGeneratingVisitor::visit(ast::Identifier&) {
384✔
458
}
384✔
459

460
void CodeGeneratingVisitor::visit(ast::FunctionDeclarator& declarator) {
206✔
461
    declarator.visitFormalArguments(*this);
206✔
462
}
206✔
463

464
void CodeGeneratingVisitor::visit(ast::ArrayDeclarator& declaration) {
×
465
    declaration.subscriptExpression->accept(*this);
×
466
    throw std::runtime_error { "not implemented" };
×
467
}
468

469
void CodeGeneratingVisitor::visit(ast::FormalArgument& parameter) {
102✔
470
    parameter.visitDeclarator(*this);
102✔
471
}
102✔
472

473
void CodeGeneratingVisitor::visit(ast::FunctionDefinition& function) {
206✔
474
    function.visitDeclarator(*this);
206✔
475

476
    std::vector<Value> values;
206✔
477
    for (auto& valueSymbol : function.getLocalVariables()) {
2,712✔
478
        values.push_back( {
5,012✔
479
                valueSymbol.second.getName(),
5,012✔
480
                valueSymbol.second.getIndex(),
481
                // FIXME:
482
                Type::INTEGRAL,
483
                valueSymbol.second.getType().getSize(),
5,012✔
484
                false
485
        });
486
    }
206✔
487
    std::vector<Value> arguments;
206✔
488
    for (auto& argumentSymbol : function.getArguments()) {
308✔
489
        arguments.push_back( {
204✔
490
                argumentSymbol.getName(),
204✔
491
                argumentSymbol.getIndex(),
492
                // FIXME:
493
                Type::INTEGRAL,
494
                argumentSymbol.getType().getSize(),
204✔
495
                true
496
        });
497
    }
206✔
498
    instructions.push_back(std::make_unique<StartProcedure>(function.getSymbol()->getName(), std::move(values), std::move(arguments)));
206✔
499

500
    auto instructionsBak = std::move(instructions);
206✔
501
    function.visitBody(*this);
206✔
502
    auto functionBody = toBasicBlocks(std::move(instructions));
206✔
503
    for (auto& bb : functionBody) {
996✔
504
        if (!bb->terminates()) {
790✔
505
            bb->appendInstruction(std::make_unique<VoidReturn>());
14✔
506
        }
507
        instructionsBak.push_back(std::move(bb));
790✔
508
    }
509
    instructions = std::move(instructionsBak);
206✔
510

511
    instructions.push_back(std::make_unique<EndProcedure>(function.getSymbol()->getName()));
206✔
512
}
206✔
513

514
void CodeGeneratingVisitor::visit(ast::Block& block) {
238✔
515
    block.visitChildren(*this);
238✔
516
}
238✔
517

518
std::vector<std::unique_ptr<Quadruple>> CodeGeneratingVisitor::getQuadruples() {
162✔
519
    return std::move(instructions);
162✔
520
}
521

522
std::vector<std::unique_ptr<BasicBlock>> toBasicBlocks(std::vector<std::unique_ptr<Quadruple>> instructions) {
212✔
523
    std::vector<std::unique_ptr<BasicBlock>> basicBlocks {};
212✔
524

525
    std::unique_ptr<BasicBlock> bb = std::make_unique<BasicBlock>();
212✔
526

527
    std::vector<std::unique_ptr<Quadruple>> bbInstructions;
212✔
528
    for (auto& instruction : instructions) {
5,770✔
529
        if (bb->terminates() || instruction->isLabel()) {
5,558✔
530
            basicBlocks.push_back(std::move(bb));
592✔
531
            bb = std::make_unique<BasicBlock>();
592✔
532
            basicBlocks.back()->setSuccessor(bb.get());
592✔
533
        }
534
        bb->appendInstruction(std::move(instruction));
5,558✔
535
    }
536
    basicBlocks.push_back(std::move(bb));
212✔
537

538
    return basicBlocks;
424✔
539
}
212✔
540

541
} // namespace codegen
542

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

© 2026 Coveralls, Inc