-
Notifications
You must be signed in to change notification settings - Fork 1
/
statements.cpp
166 lines (129 loc) · 4.72 KB
/
statements.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include "statements.h"
#include "object.h"
#include "case.h"
#include "gen.h"
// ReadStmt
ReadStmt::ReadStmt(IdNode* id, int line) : Stmt(), id(id), line(line) {}
void ReadStmt::genStmt()
{
myType idtype = id->getType();
if (idtype == _INT)
emit("iread %s\n", id->getName());
else
emit("fread %s\n", id->getName());
}
// AssignStmt
AssignStmt::AssignStmt(IdNode* lhs, Exp* rhs, int line) : Stmt(), lhs(lhs), rhs(rhs), line(line) {}
void AssignStmt::genStmt()
{
Object result = rhs->genExp();
myType idtype = lhs->getType();
if (idtype == rhs->getType())
emit("%s = %s\n", lhs->getName(), result.getString());
else {
if (idtype == _INT) {
emit("%s = (int) %s\n", lhs->getName(), result.getString());
errorMsg(WARNING, "line %d: WARNING - float value assigned to int variable\n", line);
}
else {
emit("%s = (float) %s\n", lhs->getName(), result.getString());
}
}
}
// RepeatStmt
RepeatStmt::RepeatStmt(Exp* expression, Stmt* repeatStmt, int line): Stmt(), expression(expression), repeatStmt(repeatStmt), line(line)
{
if (expression->getType() != _INT) // expression should be int, because it is the number of times wanted for repeating the statement
errorMsg(ERR, "line %d: expresion for repeat statement should be an int\n", line);
}
void RepeatStmt::genStmt()
{
int condlabel = newlabel();
int exitlabel = newlabel();
Object numIters = expression->genExp(); // get num iterantions from expression
emitlabel(condlabel);
emit("if %s <= 0 goto label%d\n", numIters.getString(), exitlabel); // check condition before continuing to true statement, alse goto exitlabe
repeatStmt->genStmt(); // generate statement to be repeated
emit("%s = %s - 1\n", numIters.getString(), numIters.getString()); // after iteration decrease number of iterations to be done
emit("goto label%d\n", condlabel); // jump back to check condition
emitlabel(exitlabel);
}
// IfStmt
IfStmt::IfStmt(BoolExp* condition, Stmt* thenStmt, Stmt* elseStmt) : Stmt(), condition(condition), thenStmt(thenStmt), elseStmt(elseStmt) {}
void IfStmt::genStmt()
{
int elseStmtlabel = newlabel();
int exitlabel = newlabel();
condition->genBoolExp(FALL_THROUGH, elseStmtlabel);
thenStmt->genStmt();
emit("goto label%d\n", exitlabel);
emitlabel(elseStmtlabel);
elseStmt->genStmt();
emitlabel(exitlabel);
}
// WhileStmt
WhileStmt::WhileStmt(BoolExp* condition, Stmt* body) : Stmt(), condition(condition), body(body) {}
void WhileStmt::genStmt()
{
int condlabel = newlabel();
int exitlabel = newlabel();
continuelabels.push(condlabel);
emitlabel(condlabel);
condition->genBoolExp(FALL_THROUGH, exitlabel);
body->genStmt();
emit("goto label%d\n", condlabel);
emitlabel(exitlabel);
continuelabels.pop(); // after done with current while, pop it's continuelabel from stack
}
// Block
Block::Block(Stmt* stmtlist) : stmtlist(stmtlist) {}
void Block::genStmt()
{
for (Stmt* stmt = stmtlist; stmt != NULL; stmt = stmt->getNext())
stmt->genStmt();
}
// BreakStmt
BreakStmt::BreakStmt(int line) : line(line) {}
void BreakStmt::genStmt()
{
emit("break statements not implemented yet\n");
}
// ContinueStmt
ContinueStmt::ContinueStmt(int line) : line(line) {}
void ContinueStmt::genStmt()
{
// if continuelabels is empty, continue statement is not inside while loop
if (continuelabels.empty()) {
errorMsg(ERR, "line %d: continue statement should be inside while loop\n", line);
}
else {
emit("goto label%d\n", continuelabels.top()); // get label of current while loop (which is on top of continuelabels)
}
}
// SwitchStmt
SwitchStmt::SwitchStmt(Exp* exp, Case* caselist, Stmt* default_stmt, int line): exp(exp), caselist(caselist), default_stmt(default_stmt), line(line)
{
if (exp->getType() != _INT)
errorMsg(ERR, "line %d: switch expression should be int\n", line);
}
void SwitchStmt::genStmt()
{
Object exp = this->exp->genExp(); // generate switch expression
for (Case* c = caselist; c != NULL; c = c->getNext()) // for each case add new label and emit goto that label if switch expression matches switch number
{
c->setLabel(newlabel());
emit("if %s == %d goto label%d\n", exp.getString(), c->getNumber(), c->getLabel());
}
int defaultlabel = newlabel(); // for default statement
int exitlabel = newlabel(); // for exit switch (break)
emit("goto label%d\n", defaultlabel); // if no case matched, goto default
for (Case* c = caselist; c != NULL; c = c->getNext()) // for each case emit it's label, it's statement and break (goto exitlabel)
{
emitlabel(c->getLabel());
c->getStmt()->genStmt();
emit("goto label%d\n", exitlabel); // assume cases have break at the end
}
emitlabel(defaultlabel); // after all cases emit default label and default statement
default_stmt->genStmt();
emitlabel(exitlabel); // emit exitlabel after all cases to break from switch
}