aboutsummaryrefslogtreecommitdiffstats
path: root/c_compiler/src/expression.cpp
blob: 7c0bd8bd6612922c262bbf541a728d502a55fbee (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
#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
    // the lhs is forced to have a stack position due to it being a function, array or other type of variable
    // unsigned current_stack = bindings.currentRegister();
    // std::cout << "Current Register: " << current_reg << std::endl;
    // bindings.increaseRegister();
    
    int store_stack_position = lhs_->postfixStackPosition(bindings);
    
    rhs_->printAsm(bindings);

    // 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
{
    lhs_->printAsm(bindings);

    // move the rhs out of the way to be able to evaluate the lhs
    std::cout << "\tmove\t$3,$2" << std::endl;

    rhs_->printAsm(bindings);

    // then perform the right operation
    
    // 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,$3,$2" << std::endl;
    else if(operation_ == "-")
	std::cout << "\tsub\t$2,$3,$2" << std::endl;
    else
	std::cerr << "Don't recognize symbol: '" << operation_ << "'" << 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
{
    lhs_->printAsm(bindings);

    std::cout << "\tmove\t$3,$2" << std::endl;

    rhs_->printAsm(bindings);

    // then perform the right operation
    if(operation_ == "*")
	std::cout << "\tmul\t$2,$3,$2" << std::endl;
    else if(operation_ == "/" || operation_ == "%") {
	std::cout << "\tdiv\t$3,$2" << 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;

    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;
	
    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;

    return bindings;
}