aboutsummaryrefslogtreecommitdiffstats
path: root/c_compiler/src/expression.cpp
blob: cd20e24bb2b1326995069ff04bbbb5852dee503c (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
#include "expression.hpp"
#include "bindings.hpp"

#include <iostream>

// Expression definition

// There are no values to delete so it is just empty
Expression::~Expression()
{}

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
}

int32_t Expression::getPostfixStackPosition(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)
{}

// deletes the two member variables that have been initialized
OperationExpression::~OperationExpression()
{
    delete lhs;
    delete rhs;
}


// Assignment Expression definition

AssignmentExpression::AssignmentExpression(Expression* _lhs, Expression* _rhs)
    : OperationExpression(_lhs, _rhs)
{}

VariableStackBindings AssignmentExpression::printasm(VariableStackBindings bindings) const
{
    // the lhs is forced to have a stack position due to it being a function, array or other type of variable
    int32_t store_stack_position = lhs->getPostfixStackPosition(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,$2,$3" << 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;
}


// Identifier definition

Identifier::Identifier(const std::string& id)
    : m_id(id)
{}

VariableStackBindings Identifier::printasm(VariableStackBindings bindings) const
{
    if(bindings.bindingExists(m_id)) {
	int32_t stack_position = bindings.getStackPosition(m_id);

	std::cout << "\tlw\t$2," << stack_position << "($fp)" << std::endl;
    } else
	std::cerr << "Can't find identifier '" << m_id << "' in current scope binding" << std::endl;
	
    return bindings;
}

int32_t Identifier::getPostfixStackPosition(VariableStackBindings bindings) const
{
    if(bindings.bindingExists(m_id)) {
	return bindings.getStackPosition(m_id);
    }

    return -1;
}


// Constant definition

Constant::Constant(const int32_t& constant)
    : m_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," << m_constant << std::endl;

    return bindings;
}