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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
#include "expression.hpp"
#include <iostream>
// Expression definition
void Expression::print() const
{
std::cerr << "This expression has not been implemented yet" << std::endl;
}
void Expression::printXml() const
{
// Does nothing as I do not want it to appear in the xml output
}
int Expression::postfixStackPosition(VariableStackBindings bindings) const
{
std::cerr << "Error : Can't call 'getPostfixStackPosition(VariableStackBindings " <<
"bindings)' on this type of expression" << std::endl;
(void)bindings;
return -1;
}
// OperationExpression definition
OperationExpression::OperationExpression(Expression* lhs, Expression* rhs)
: lhs_(lhs), rhs_(rhs)
{}
// Assignment Expression definition
AssignmentExpression::AssignmentExpression(Expression* lhs, Expression* rhs)
: OperationExpression(lhs, rhs)
{}
VariableStackBindings AssignmentExpression::printAsm(VariableStackBindings bindings) const
{
// TODO add stack and store results in there, also for addition and multiplication.
// get the current location of lhs in the stack so that I can store result there
int store_stack_position = lhs_->postfixStackPosition(bindings);
// get the current available stack position
int expression_stack_position = bindings.currentExpressionStackPosition();
// evaluate rhs and get the result back at the stack position I assigned
// don't have to change the stack position as there is no lhs to evaluate
rhs_->printAsm(bindings);
// now the result of the rhs will be in that stack position, so we can load it into $2
std::cout << "\tlw\t$2," << expression_stack_position << "($fp)" << std::endl;
// we are assigning so we don't have to evaluate the lhs as it will be overwritten anyways
std::cout << "\tsw\t$2," << store_stack_position << "($fp)" << std::endl;
return bindings;
}
// Additive Expression definition
AdditiveExpression::AdditiveExpression(Expression* lhs, const std::string& operation, Expression* rhs)
: OperationExpression(lhs, rhs), operation_(operation)
{}
VariableStackBindings AdditiveExpression::printAsm(VariableStackBindings bindings) const
{
// I can just evaluate the lhs with the same entry stack position
lhs_->printAsm(bindings);
// store this stack position
int lhs_stack_position = bindings.currentExpressionStackPosition();
// now have to increase the expression stack position for the rhs
bindings.nextExpressionStackPosition();
rhs_->printAsm(bindings);
// now I have them evaluated at two positions in the stack and can load both into registers
// $2 and $3
std::cout << "\tlw\t$2," << lhs_stack_position << "($fp)" << std::endl;
std::cout << "\tlw\t$3," << bindings.currentExpressionStackPosition() << "($fp)" << std::endl;
// TODO currently using signed and sub because I only have signed numbers implemented
// must update this as I add more types
if(operation_ == "+")
std::cout << "\tadd\t$2,$2,$3" << std::endl;
else if(operation_ == "-")
std::cout << "\tsub\t$2,$2,$3" << std::endl;
else
std::cerr << "Don't recognize symbol: '" << operation_ << "'" << std::endl;
// now I have to store it back into the original stack position
std::cout << "\tsw\t$2," << lhs_stack_position << "($fp)" << std::endl;
return bindings;
}
// Multiplicative Expression definition
MultiplicativeExpression::MultiplicativeExpression(Expression* lhs, const std::string& operation, Expression* rhs)
: OperationExpression(lhs, rhs), operation_(operation)
{}
VariableStackBindings MultiplicativeExpression::printAsm(VariableStackBindings bindings) const
{
// I can just evaluate lhs without increasing stack count
lhs_->printAsm(bindings);
// store current stack position
int lhs_stack_position = bindings.currentExpressionStackPosition();
// increase stack position to store next result in
bindings.nextExpressionStackPosition();
rhs_->printAsm(bindings);
std::cout << "\tlw\t$2," << lhs_stack_position << "($fp)" << std::endl;
std::cout << "\tlw\t$3," << bindings.currentExpressionStackPosition() << "($fp)" << std::endl;
// then perform the right operation
if(operation_ == "*")
std::cout << "\tmul\t$2,$2,$3" << std::endl;
else if(operation_ == "/" || operation_ == "%") {
std::cout << "\tdiv\t$2,$3" << std::endl;
if(operation_ == "/")
std::cout << "\tmflo\t$2" << std::endl;
else
std::cout << "\tmfhi\t$2" << std::endl;
} else
std::cerr << "Don't recognize symbol '" << operation_ << "'" << std::endl;
// finally store result back into the stack position
std::cout << "\tsw\t$2," << lhs_stack_position << "($fp)" << std::endl;
return bindings;
}
// Identifier definition
Identifier::Identifier(const std::string& id)
: id_(id)
{}
VariableStackBindings Identifier::printAsm(VariableStackBindings bindings) const
{
if(bindings.bindingExists(id_))
std::cout << "\tlw\t$2," << bindings.stackPosition(id_) << "($fp)" << std::endl;
else
std::cerr << "Can't find identifier '" << id_ << "' in current scope binding" << std::endl;
std::cout << "\tsw\t$2," << bindings.currentExpressionStackPosition() << "($fp)" << std::endl;
return bindings;
}
int Identifier::postfixStackPosition(VariableStackBindings bindings) const
{
if(bindings.bindingExists(id_)) {
return bindings.stackPosition(id_);
}
return -1;
}
// Constant definition
Constant::Constant(const int32_t& constant)
: constant_(constant)
{}
VariableStackBindings Constant::printAsm(VariableStackBindings bindings) const
{
// constant only has to load to $2 because the other expression will take care of the rest
std::cout << "\tli\t$2," << constant_ << std::endl;
std::cout << "\tsw\t$2," << bindings.currentExpressionStackPosition() << "($fp)" << std::endl;
return bindings;
}
|