-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathtype_checker_implementation.cc
More file actions
112 lines (96 loc) · 2.9 KB
/
type_checker_implementation.cc
File metadata and controls
112 lines (96 loc) · 2.9 KB
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
#include "implementation.hh"
#include <iostream>
#include <sstream>
std::map<std::string, symbol> symbol_table;
type number_expression::get_type() const {
return natural;
}
type boolean_expression::get_type() const {
return boolean;
}
void symbol::declare() {
if(symbol_table.count(name) > 0) {
error(line, std::string("Re-declared variable: ") + name);
}
symbol_table[name] = *this;
}
type id_expression::get_type() const {
if(symbol_table.count(name) == 0) {
error(line, std::string("Undefined variable: ") + name);
}
return symbol_table[name].symbol_type;
}
type operand_type(std::string op) {
if(op == "+" || op == "-" || op == "*" || op == "/" || op == "%" ||
op == "<" || op == ">" || op == "<=" || op == ">=") {
return natural;
} else {
return boolean;
}
}
type return_type(std::string op) {
if(op == "+" || op == "-" || op == "*" || op == "/" || op == "%") {
return natural;
} else {
return boolean;
}
}
type binop_expression::get_type() const {
if(op == "=") {
if(left->get_type() != right->get_type()) {
error(line, "Left and right operands of '=' have different types.");
}
} else {
if(left->get_type() != operand_type(op)) {
error(line, std::string("Left operand of '") + op + "' has unexpected type.");
}
if(right->get_type() != operand_type(op)) {
error(line, std::string("Right operand of '") + op + "' has unexpected type.");
}
}
return return_type(op);
}
type not_expression::get_type() const {
if(operand->get_type() != boolean) {
error(line, "Operand of 'not' is not boolean.");
}
return boolean;
}
void assign_instruction::type_check() {
if(symbol_table.count(left) == 0) {
error(line, std::string("Undefined variable: ") + left);
}
if(symbol_table[left].symbol_type != right->get_type()) {
error(line, "Left and right hand sides of assignment are of different types.");
}
}
void read_instruction::type_check() {
if(symbol_table.count(id) == 0) {
error(line, std::string("Undefined variable: ") + id);
}
}
void write_instruction::type_check() {
exp_type = exp->get_type();
}
void if_instruction::type_check() {
if(condition->get_type() != boolean) {
error(line, "Condition of 'if' instruction is not boolean.");
}
type_check_commands(true_branch);
type_check_commands(false_branch);
}
void while_instruction::type_check() {
if(condition->get_type() != boolean) {
error(line, "Condition of 'while' instruction is not boolean.");
}
type_check_commands(body);
}
void type_check_commands(std::list<instruction*>* commands) {
if(!commands) {
return;
}
std::list<instruction*>::iterator it;
for(it = commands->begin(); it != commands->end(); ++it) {
(*it)->type_check();
}
}