-
Notifications
You must be signed in to change notification settings - Fork 1
/
scope.hpp
201 lines (163 loc) · 4.51 KB
/
scope.hpp
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#pragma once
#include <map>
#include <vector>
#include <string>
#include <typeinfo>
#include <memory>
#include <iostream>
#include <cassert>
using namespace std;
struct ScopeValue{
virtual bool is_func() const { return false; }
virtual bool is_int() const { return false; }
};
struct ScopeFunc : public ScopeValue {
bool returns;
int no_params;
int no_var;
ScopeFunc(bool returns = false, int no_params = 0, int no_var = 0)
: returns(returns), no_params(no_params), no_var(no_var){}
bool returns_int() const { return returns; }
bool returns_void() const { return !returns; }
bool compatible_with(int x) const { return x == no_params; }
bool is_func() const override{
return true;
}
int count_declarations(){ return no_var; } const
void set_declarations(int x) { no_var = x; }
};
struct ScopeInt : public ScopeValue {
int val;
bool global;
ScopeInt(bool global = false) : global(global){}
operator int() const { return val; }
ScopeInt & operator=(int x){ val = x; return *this; }
int offset() const { return int(*this); }
bool is_global() const { return global; }
bool is_int() const override{
return true;
}
};
struct Scope{
bool inside_int;
void * inside_loop;
map<string, shared_ptr<ScopeInt>> table_int;
map<string, shared_ptr<ScopeFunc>> table_func;
Scope(){
inside_int = false;
inside_loop = 0;
}
bool check_int(string s) { return table_int.count(s); }
bool check_func(string s) { return table_func.count(s); }
shared_ptr<ScopeInt> & get_int(string s) { return table_int[s]; }
shared_ptr<ScopeFunc> & get_func(string s) { return table_func[s]; }
};
struct ScopeStack{
int loop_cnt = 0, if_cnt = 0;
vector<Scope> st;
shared_ptr<ScopeInt> & _declare_int(string var){
if(st.back().check_int(var))
throw runtime_error("variable " + var + " was declared before");
return st.back().get_int(var);
}
shared_ptr<ScopeFunc> & _declare_func(string var){
if(st.back().check_func(var))
throw runtime_error("function " + var + " was declared before");
return st.back().get_func(var);
}
ScopeFunc & declare_func(string var, bool returns_int = false, int no_params = 0, int no_var = 0){
return *(this->_declare_func(var) = make_shared<ScopeFunc>(returns_int, no_params, no_var));
}
ScopeInt & declare_int(string var, bool is_global = false){
return *(this->_declare_int(var) = make_shared<ScopeInt>(is_global));
}
shared_ptr<ScopeInt> _get_int(string var){
for(int i = (int)st.size()-1; i >= 0; i--){
if(st[i].check_int(var))
return st[i].get_int(var);
}
throw runtime_error("variable " + var + " not declared in this scope");
}
shared_ptr<ScopeFunc> _get_func(string var){
for(int i = (int)st.size()-1; i >= 0; i--){
if(st[i].check_func(var))
return st[i].get_func(var);
}
throw runtime_error("function " + var + " not declared in this scope");
}
ScopeFunc & get_func(string var){
shared_ptr<ScopeFunc> res = 0;
try{
res = this->_get_func(var);
} catch(std::exception & e){
throw runtime_error("name " + var + " not declared in this scope");
}
if(res == 0)
throw runtime_error("name " + var + " was declared before but is not a function");
return *res;
}
ScopeInt & get_int(string var){
shared_ptr<ScopeInt> res = 0;
try{
res = this->_get_int(var);
} catch(std::exception & e){
throw runtime_error("name " + var + " not declared in this scope");
}
if(res == 0)
throw runtime_error("name " + var + " was declared before but is not an int");
return *res;
}
void push(){
st.emplace_back();
}
void push_int(){
push();
st.back().inside_int = true;
}
void push_void(){
push();
}
int push_if(){
push();
if_cnt++;
return if_cnt;
}
int push_else(){
push();
return if_cnt;
}
int push_loop(void * no){
push();
loop_cnt++;
st.back().inside_loop = no;
return loop_cnt;
}
void pop(){
st.pop_back();
}
void * last_loop() const {
for(int i = (int)st.size()-1; i >= 0; i--)
if(st[i].inside_loop)
return st[i].inside_loop;
return 0;
}
bool is_int() const {
for(const auto & p : st)
if(p.inside_int)
return true;
return false;
}
bool is_loop() const {
for(const auto & p : st){
if(p.inside_loop)
return true;
}
return false;
}
void * loop_block() const {
return st.back().inside_loop;
}
bool is_global() const {
return st.size() == 1;
}
};