aboutsummaryrefslogtreecommitdiffstats
path: root/c_compiler/src/expression.cpp
blob: 31595b13a303f81d215afa05d6090b16aa13d311 (plain)
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;
}