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

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)
{}


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