Repository navigation
Expand file tree
/
Copy pathScope.cpp
More file actions
110 lines (94 loc) · 4.26 KB
/
Copy pathScope.cpp
File metadata and controls
110 lines (94 loc) · 4.26 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
#include "CompilationContext.hpp"
void CompilationContext::pushFrame(bool isFunction) {
if (this->createToGlobal) {
globals.isFunction = isFunction;
} else {
auto sc = Scope();
sc.isFunction = isFunction;
scopes.push_back(sc);
}
}
// add frame
void CompilationContext::pushFrame(Scope &frame) {
scopes.push_back(frame);
}
void CompilationContext::popFrame() {
scopes.pop_back();
}
// variable handling
VariableScope CompilationContext::createVarName(string varName, VariableScope var) {
// eventually expand to full list of keywords later
if (varName == "this") throw invalid_argument("Cannot name keyword.");
if (this->createToGlobal) {
if (globals.varNames.count(varName) > 0) throw invalid_argument("Variable already exists in scope.");
globals.varNames[varName] = var;
} else {
if (scopes.back().varNames.count(varName) > 0) throw invalid_argument("Variable already exists in scope.");
scopes.back().varNames[varName] = var;
}
return var;
}
variant<VariableScope, ClassScope> CompilationContext::findVarName(string varName) {
auto fullScopes = scopes; fullScopes.push_back(globals);
for(vector<Scope>::reverse_iterator i = fullScopes.rbegin(); i != fullScopes.rend(); ++i) {
if(i->varNames.count(varName) != 0) return i->varNames[varName];
if (i->isFunction && runningClass == "") break;
}
// if we are comiling class it might be a class scope thing
if (runningClass != "")
return this->classesDefined[runningClass];
throw invalid_argument("No variable by the name of '" + varName + "'");
}
// function type
string CompilationContext::createFunctionName (optional<string> returnType, string funcName, vector<string> types, bool isPrivate) {
string n = funcName;
bool isDiffParams = false;
auto fullScopes = scopes; fullScopes.push_back(globals);
for(vector<Scope>::reverse_iterator i = fullScopes.rbegin(); i != fullScopes.rend(); ++i) {
for (auto func : i->functions) {
// if func has same name but different params
if (func.prefixName == funcName && func.params != types) isDiffParams = true;
// same name same param types, then throw error
else if (func.prefixName == funcName && func.params == types)
throw invalid_argument("Function with same params already declared");
}
}
if (isDiffParams)
n = names.use(funcName);
string newRet = "";
if (returnType) newRet = *returnType;
else newRet = "void";
auto fscope = FunctionScope {funcName, n, types, newRet, isPrivate};
if (this->createToGlobal)
globals.functions.push_back(fscope);
else
scopes.back().functions.push_back(fscope);
return n;
}
FunctionScope CompilationContext::findFuncName (string funcName, vector<string> types) {
auto fullScopes = scopes; fullScopes.push_back(globals);
for (vector<Scope>::reverse_iterator i = fullScopes.rbegin(); i != fullScopes.rend(); ++i) {
for (auto func : i->functions) {
if (func.prefixName == "printf" && funcName == "printf") return func; // I don't support varadic types yet okay
if (func.prefixName == funcName && types == func.params) return func;
}
}
throw invalid_argument("Invalid function call: no function found: " + funcName);
}
// classes
ClassScope CompilationContext::createClass (string name, StructType* type, Type* pointerType, vector<VarTemplate> variables) {
// assert thats in global scope
if (scopes.size() != 2) throw invalid_argument("Class must be declared in global scope.");
// check whether we didn't declare any of the classes before
if (this->classesDefined.find(name) != this->classesDefined.end()) throw invalid_argument("Class already defined.");
// if not any of these conditions, then we can push scope
ClassScope c = {name, type, pointerType, variables, {}};
this->classesDefined[name] = c;
return c;
}
// really this function is only used when defining functions within in the class
ClassScope CompilationContext::findClass (string name) {
if (this->classesDefined.find(name) != this->classesDefined.end())
return this->classesDefined[name];
throw invalid_argument("Invalid class name.");
}