AALanguage
The best language for those who have nothing to do
Loading...
Searching...
No Matches
Semantic.cpp
Go to the documentation of this file.
1#include "Semantic.h"
2
4 if (str == "double") return ExprType::Double;
5 if (str == "udouble") return ExprType::UDouble;
6 if (str == "long") return ExprType::Long;
7 if (str == "ulong") return ExprType::ULong;
8 if (str == "float") return ExprType::Float;
9 if (str == "ufloat") return ExprType::UFloat;
10 if (str == "int") return ExprType::Int;
11 if (str == "uint") return ExprType::UInt;
12 if (str == "short") return ExprType::Short;
13 if (str == "ushort") return ExprType::UShort;
14 if (str == "byte") return ExprType::Byte;
15 if (str == "char") return ExprType::Char;
16 if (str == "string") return ExprType::String;
17 if (str == "bool") return ExprType::Bool;
18 if (str == "void") return ExprType::Void;
19 if (str == "large") return ExprType::Large;
20 return ExprType::Unknown;
21}
22
23bool Semantic::is_convertible(Type first, Type second, bool is_func) {
24 if (first.is_array != second.is_array || !is_func && first.array_size != second.array_size) return false;
25 if (first == second) return true;
26 switch (first.expr_type) {
27 case Bool:
28 return second.expr_type == ExprType::Bool;
29 case Char:
30 case Double:
31 case UDouble:
32 case Float:
33 case UFloat:
34 case Int:
35 case UInt:
36 case Long:
37 case ULong:
38 case Short:
39 case UShort:
40 case Byte:
41 case Large:
42 return second.expr_type != ExprType::Bool && second.expr_type != ExprType::String && second.expr_type != ExprType::Void && second.expr_type != ExprType::Unknown;
43 case String:
44 return second.expr_type == ExprType::String;
45 case Void:
46 case Unknown:
47 return second.expr_type == ExprType::Unknown;
48 default:
49 break;
50 }
51}
52
54 if (!is_convertible(first, second)) return Type();
55 if (type_prior[first.expr_type] >= type_prior[second.expr_type])
56 return first;
57 else
58 return second;
59}
60
61std::string Semantic::type_to_string(Type type) {
62 switch (type.expr_type) {
63 case Bool:
64 return (std::string)"bool" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
65 case Char:
66 return (std::string)"char" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
67 case Double:
68 return (std::string)"double" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
69 case UDouble:
70 return (std::string)"udouble" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
71 case Float:
72 return (std::string)"float" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
73 case UFloat:
74 return (std::string)"ufloat" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
75 case Int:
76 return (std::string)"int" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
77 case UInt:
78 return (std::string)"uint" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
79 case Long:
80 return (std::string)"long" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
81 case ULong:
82 return (std::string)"ulong" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
83 case Short:
84 return (std::string)"short" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
85 case UShort:
86 return (std::string)"ushort" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
87 case Byte:
88 return (std::string)"byte" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
89 case String:
90 return (std::string)"string" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
91 case Large:
92 return (std::string)"large" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
93 case Void:
94 return (std::string)"void" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
95 case Unknown:
96 default:
97 return (std::string)"unknown" + (type.is_array ? "[" + std::to_string(type.array_size) + "]" : "");
98 }
99}
100
101void Semantic::add_identifier(Identifier* ident, bool is_global) {
102 if (!is_global) {
103 if (tid->identifiers.count(ident->name) != 0) throw std::exception(("Identifier '" + ident->name + "' was already declared in the current scope").c_str());
104 tid->identifiers[ident->name] = ident;
105 params_ptrs.push_back(ident);
106 } else {
107 if (global_tid->identifiers.count(ident->name) != 0) throw std::exception(("Identifier '" + ident->name + "' was already declared in the current scope").c_str());
108 global_tid->identifiers[ident->name] = ident;
109 }
110}
111
113 TableIdentifiers* ptr = tid;
114 while (ptr != nullptr) {
115 if (ptr->identifiers.count(name) != 0) {
116 return ptr->identifiers[name];
117 }
118 ptr = ptr->parent;
119 }
120 if (global_tid->identifiers.count(name) == 0) {
121 throw std::exception(("Identifier '" + name + "' was not declared in the current scope").c_str());
122 return nullptr;
123 }
124 return global_tid->identifiers[name];
125}
126
128 auto next = tid->parent;
129 delete tid;
130 tid = next;
131 if (tid == nullptr)
132 tid = new TableIdentifiers();
133}
134
135void Semantic::create_table(bool new_func) {
136 auto next = new TableIdentifiers();
137 if (!new_func)
138 next->parent = tid;
139 tid = next;
140}
141
142void Semantic::create_function(std::string name, Type type, int pref, std::vector<int> inits, std::vector<Identifier*> ptrs, int ptr) {
143 std::vector<Type> idents;
144 for (auto& u : tid->identifiers) {
145 idents.push_back(u.second->type);
146 }
147 Function f = Function(name, type, tid, idents, inits, ptrs, ptr, pref);
148 if (funcs.count(f) != 0)
149 throw std::exception(("Function '" + f.name + "' was already declared in the current scope").c_str());
150 funcs[f] = tid;
151 current_function = type;
152}
153
154Function Semantic::get_function(std::string name, std::vector<Type> params) {
155 std::vector<std::pair<int, Function>> functions;
156 for (auto& u : funcs) {
157 int curr_level = 0;
158 if (u.first.name != name) continue;
159 if (params.size() < u.first.not_default_pref) continue;
160 if (params.size() > u.first.identifiers.size()) continue;
161 bool flag = true;
162 for (int i = 0; i < params.size(); ++i) {
163 if (params[i].expr_type != u.first.identifiers[i].expr_type) {
164 if (!is_convertible(params[i], u.first.identifiers[i], true)) {
165 flag = false;
166 break;
167 } else {
168 curr_level = 1;
169 }
170 }
171 if (params[i].is_array != u.first.identifiers[i].is_array) {
172 flag = false;
173 break;
174 }
175 }
176
177 if (flag) {
178 functions.push_back({ curr_level, u.first });
179 }
180 }
181 if (functions.empty()) {
182 throw std::exception(("Function '" + name + "' was not declared in the current scope").c_str());
183 }
184 std::sort(functions.begin(), functions.end(), [&](std::pair<int, Function> f, std::pair<int, Function> s) {
185 return f.first < s.first;
186 });
187 if (functions.size() == 1 || functions[1].first > functions[0].first)
188 return functions[0].second;
189 throw std::exception((name + " function call is ambiguous").c_str());
190}
191
192void Semantic::init_array(ExprType type, int size, void*& value, std::string name) {
193 if (size > 5e5) throw std::exception("Array size cannot be bigger than 5e5");
194 if (size <= 0) throw std::exception("Array size cannot be less than 1");
195 std::vector<Identifier*>* arr = new std::vector<Identifier*>();
196 for (int i = 0; i < size; ++i) {
197 arr->push_back(new Identifier(name + "[" + std::to_string(i) + "]", Type(type, false, false), nullptr));
198 }
199 value = arr;
200}
201
202bool Semantic::check_operation(Type f, Type s, std::string operation) {
203 auto first = f.expr_type, second = s.expr_type;
204 if (operation == ">>" || operation == "<<" || operation == "~" || operation == "|" || operation == "&" || operation == "^" || operation == "->")
205 if (first == ExprType::Double || first == ExprType::Float || second == ExprType::Double || second == ExprType::Float || second == ExprType::Large)
206 return false;
207 if (operation == "+")
208 return first != ExprType::Bool && is_convertible(f, s);
209 if (operation == "-" || operation == "*" || operation == "/" || operation == ">>" || operation == "<<" || operation == "<" || operation == "<=" ||
210 operation == ">" || operation == ">=")
211 return first != ExprType::Bool && first != ExprType::String && is_convertible(f, s);
212 if (operation == "%")
213 return first != ExprType::Bool && first != ExprType::String && first != ExprType::Float && first != ExprType::UFloat &&
214 first != ExprType::Double && first != ExprType::UDouble && second != ExprType::Float && second != ExprType::UFloat &&
215 second != ExprType::Double && second != ExprType::UDouble && is_convertible(f, s);
216 if (operation == "&" || operation == "^" || operation == "|" || operation == "->" || operation == "~")
217 return first != ExprType::String && is_convertible(f, s);
218 if (operation == "=" || operation == "==" || operation == "!=")
219 return is_convertible(f, s);
220 if (operation == "||" || operation == "&&")
221 return first == ExprType::Bool && is_convertible(f, s);
222 return false;
223}
224
226 switch (lex.is_literal(current_token.value)) {
228 return Type(ExprType::Bool, false, false);
230 if (current_token.value.find("ul") != current_token.value.npos || current_token.value.find("UL") != current_token.value.npos)
231 return Type(ExprType::ULong, false, false);
232 if (current_token.value.find("l") != current_token.value.npos || current_token.value.find("L") != current_token.value.npos)
233 return Type(ExprType::Long, false, false);
234 if (current_token.value.find("i") != current_token.value.npos || current_token.value.find("I") != current_token.value.npos)
235 return Type(ExprType::Int, false, false);
236 if (current_token.value.find("u") != current_token.value.npos || current_token.value.find("U") != current_token.value.npos ||
237 current_token.value.find("ui") != current_token.value.npos || current_token.value.find("UI") != current_token.value.npos)
238 return Type(ExprType::UInt, false, false);
239 if (current_token.value.find("s") != current_token.value.npos || current_token.value.find("S") != current_token.value.npos)
240 return Type(ExprType::Short, false, false);
241 if (current_token.value.find("us") != current_token.value.npos || current_token.value.find("US") != current_token.value.npos)
242 return Type(ExprType::UShort, false, false);
243 if (current_token.value.find("b") != current_token.value.npos || current_token.value.find("B") != current_token.value.npos)
244 return Type(ExprType::Byte, false, false);
245 return Type(ExprType::Int, false, false);
247 if (current_token.value.find("d") != current_token.value.npos || current_token.value.find("D") != current_token.value.npos)
248 return Type(ExprType::Double, false, false);
249 if (current_token.value.find("ud") != current_token.value.npos || current_token.value.find("UD") != current_token.value.npos)
250 return Type(ExprType::UDouble, false, false);
251 if (current_token.value.find("f") != current_token.value.npos || current_token.value.find("F") != current_token.value.npos)
252 return Type(ExprType::Float, false, false);
253 if (current_token.value.find("uf") != current_token.value.npos || current_token.value.find("UF") != current_token.value.npos)
254 return Type(ExprType::UFloat, false, false);
255 return Type(ExprType::Float, false, false);
257 return Type(ExprType::Char, false, false);
259 return Type(ExprType::String, false, false);
260 default:
261 return Type(ExprType::Unknown, false, false);
262 }
263}