-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsem.H
375 lines (349 loc) · 12.3 KB
/
sem.H
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
#ifndef __SEM_H
#define __SEM_H
#include "ast.H"
#include <list>
#include <vector>
#include <map>
#include <stack>
#include <assert.h>
namespace llvm {
class Type;
}
namespace IR {
class Vtbl;
class Code;
}
namespace SEM {
class Type;;
}
void printMe(SEM::Type* t);
namespace SEM {
using namespace AST;
class Type {
public:
Type() {}
virtual ~Type() {}
virtual std::ostream& print(ostream& os) const { return os;}
virtual bool accept(Type* t) const { return false;}
virtual bool isInt() const { return false;}
virtual bool isBool() const { return false;}
virtual bool isVoid() const { return false;}
virtual bool isError() const { return false;}
virtual bool isInstance() const { return false;}
virtual bool isClass() const { return false;}
virtual bool isArray() const { return false;}
virtual bool isMethod() const { return false;}
virtual bool isEqual(Type* t) const { return this==t;}
virtual llvm::Type* getLLVMType(IR::Code&) { return 0;}
virtual std::string getName() const { return "";}
friend std::ostream& operator<<(ostream& os,const Type& t) {
return t.print(os);
}
};
class TypeInt : public Type {
public:
TypeInt() {}
~TypeInt(){}
std::ostream& print(ostream& os) const { return os << "int";}
std::string getName() const { return "int";}
bool accept(Type* t) const { return t->isInt() || t->isBool();}
bool isInt() const { return true;}
bool isBool() const { return false;}
bool isEqual(Type* t) const { return t->isInt();}
llvm::Type* getLLVMType(IR::Code&);
};
class TypeBool : public Type {
public:
TypeBool() {}
~TypeBool() {}
std::ostream& print(ostream& os) const { return os << "bool";}
std::string getName() const { return "bool";}
bool accept(Type* t) const { return t->isBool();}
bool isBool() const { return true;}
bool isEqual(Type* t) const { return t->isBool();}
llvm::Type* getLLVMType(IR::Code&);
};
class TypeVoid : public Type {
public:
TypeVoid() {}
~TypeVoid() {}
std::ostream& print(ostream& os) const { return os << "void";}
std::string getName() const { return "void";}
bool accept(Type* t) const { return t->isVoid();}
bool isVoid() const { return true;}
bool isEqual(Type* t) const { return t->isVoid();}
llvm::Type* getLLVMType(IR::Code&);
};
class TypeError : public Type {
public:
TypeError() {}
~TypeError() {}
std::ostream& print(ostream& os) const { return os << "error";}
std::string getName() const { return "error";}
bool accept(Type* t) const { return t->isError();}
bool isError() const { return true;}
bool isEqual(Type* t) const { return t->isError();}
};
class TypeClass : public Type {
std::string _name;
TypeClass* _parent;
Scope* _scope;
llvm::Type* _llty;
public:
TypeClass(std::string n,TypeClass* p) : _name(n),_parent(p),_scope(0),_llty(0) {}
~TypeClass() {}
void setScope(Scope* s) { _scope = s;}
Scope* getScope() { return _scope;}
SEM::Descriptor* getSymbol(const std::string& key);
std::ostream& print(ostream& os) const;
bool isClass() const { return true;}
bool isSuperOf(TypeClass* t2);
TypeClass* getParent() { return _parent;}
std::string getName() const { return _name;}
llvm::Type* getLLVMType(IR::Code&);
void emitAttributes(IR::Code&,std::vector<llvm::Type*>& att);
bool hasMethod(string name,TypeMethod* mty);
MethodDescriptor* getMethod(string name,TypeMethod* mty);
bool isEqual(Type* t) const;
};
class TypeArray : public Type {
Type* _base;
public:
TypeArray(Type* b) : _base(b) {}
~TypeArray() {}
std::ostream& print(ostream& os) const {
return os << "[" << *_base << "]";
}
Type* getType() const { return _base;}
bool isArray() const { return true;}
bool accept(Type* t) const {
return t->isArray() && _base->accept(dynamic_cast<TypeArray*>(t)->getType());
}
llvm::Type* getLLVMType(IR::Code&);
bool isEqual(Type* t) const {
if (t->isArray()) {
TypeArray* t2 = dynamic_cast<TypeArray*>(t);
if (this == t2) return true;
else {
return _base->isEqual(t2->getType());
}
} else return false;
}
};
class TypeInstance : public Type {
TypeClass* _of;
public:
TypeInstance(TypeClass* of) : _of(of) {}
~TypeInstance() {}
TypeClass* getType() { return _of;}
std::ostream& print(ostream& os) const {
return os << "instance(" << *_of << ")";
}
bool isInstance() const { return true;}
bool accept(Type* t) const {
return t->isInstance() && _of->isSuperOf(dynamic_cast<TypeInstance*>(t)->getType());
}
llvm::Type* getLLVMType(IR::Code&);
std::string getName() const { return _of->getName();}
bool isEqual(Type* t) const {
if (t->isInstance()) {
TypeInstance* t2 = dynamic_cast<TypeInstance*>(t);
return _of->isEqual(t2->getType());
} else return false;
}
};
class TypeMethod : public Type {
TypeClass* _receiver;
Type* _rt;
std::vector<Type*> _fTypes;
std::vector<std::string> _fNames;
public:
TypeMethod(TypeClass* rcv,Type* r) : _receiver(rcv),_rt(r) {}
void addFormal(std::string n,Type* t) {
_fTypes.push_back(t);
_fNames.push_back(n);
}
bool isMethod() const { return true;}
unsigned long nbExpectedArgs() { return _fNames.size();}
SEM::Type* acceptCall(std::vector<SEM::Type*>& aty);
std::string getName() const { return "method!!!";}
bool canOverride(TypeMethod* t);
bool isEqual(Type* t) const;
bool returnsVoid() {
return _rt->isVoid();
}
std::ostream& print(ostream& os) const {
if (_rt)
os << *_rt << "(";
else os << "constructor(";
std::vector<Type*>::const_iterator ti = _fTypes.begin();
std::vector<std::string>::const_iterator ni = _fNames.begin();
while (ti != _fTypes.end()) {
os << (*ti)->getName() << " " << *ni;
++ti;
++ni;
if (ti != _fTypes.end())
os << ",";
}
os << ")";
return os;
}
void setFormalNames(llvm::Function* f);
llvm::Type* getLLVMType(IR::Code&);
};
class Descriptor {
protected:
Type* _type;
public:
Descriptor(Type* t) : _type(t) {}
Descriptor(const Descriptor& d) : _type(d._type) {}
Type* getType() { return _type;}
virtual llvm::Value* get() { return 0;}
virtual std::ostream& print(std::ostream& os) const {
return os << *_type;
}
friend std::ostream& operator<<(std::ostream& os,const Descriptor& d) {
return d.print(os);
}
virtual bool isField() { return false;}
virtual bool isMethod() { return false;}
virtual llvm::Value* genExpr(IR::Code&) { return 0;}
virtual llvm::Value* genAddress(IR::Code&) { return 0;}
};
class ClassDescriptor : public Descriptor {
ClassDescriptor* _pClass;
IR::Vtbl* _vtbl;
int _nbM;
llvm::Type* _cType;
public:
ClassDescriptor(Type* t,ClassDescriptor* pCD=0)
: Descriptor(t),_pClass(pCD),_nbM(-1),_cType(0)
{}
ClassDescriptor* getParent() { return _pClass;}
int nbMethods() { return _nbM;}
int labelMethods();
void makeVTBL(IR::Code&);
void updateVTBL(int k,llvm::Function* mk);
void emitVTBL(IR::Code& code);
IR::Vtbl* patchVTBL();
void setLLVMType(llvm::Type* ct) { _cType = ct;}
llvm::Type* getLLVMType() { return _cType;}
llvm::Value* getVTBLAddress();
int requiredSize(IR::Code&);
std::ostream& print(std::ostream& os) const {
os << "ClassDesc(#M:" << _nbM << ',';
if (_pClass) os << *_pClass;
os << ")";
return Descriptor::print(os);
}
};
class MethodDescriptor : public Descriptor {
ClassDescriptor* _cd;
FormalDescriptor* _rec;
vector<FormalDescriptor*> _args;
int _offset; // offset within VTBL
public:
MethodDescriptor(ClassDescriptor* cd,FormalDescriptor* rec,Type* t)
: Descriptor(t),_cd(cd),_rec(rec),_offset(-1) {}
ClassDescriptor* getClass() { return _cd;}
std::ostream& print(std::ostream& os) const {
os << "MethodDesc:";
return Descriptor::print(os);
}
vector<llvm::Type*> getLLVMType(IR::Code&);
void addFormal(std::string key,FormalDescriptor* fd);
void setFormalNames(llvm::Function* f);
void bindFormals(llvm::Function* f);
void setOffset(int o) { _offset = o;}
int getOffset() const { return _offset;}
virtual bool isMethod() { return true;}
bool returnsVoid() {
return dynamic_cast<TypeMethod*>(_type)->returnsVoid();
}
};
class FieldDescriptor: public Descriptor {
int _num;
public:
FieldDescriptor(Type* t) : Descriptor(t),_num(0) {}
std::ostream& print(std::ostream& os) const {
os << "FieldDesc:";
return Descriptor::print(os);
}
void setFieldNumber(int n) { _num = n;}
int getFieldNumber() { return _num;}
virtual bool isField() { return true;}
};
class FormalDescriptor : public Descriptor {
llvm::Value* _val;
public:
FormalDescriptor(Type* t) : Descriptor(t),_val(0) {}
void bindTo(llvm::Value* v) { _val = v;}
llvm::Value* get() { return _val;}
std::ostream& print(std::ostream& os) const {
os << "FormalDesc:";
return Descriptor::print(os);
}
llvm::Value* genExpr(IR::Code&);
llvm::Value* genAddress(IR::Code&);
};
class LocalDescriptor : public Descriptor {
llvm::Value* _val;
public:
LocalDescriptor(Type* t) : Descriptor(t) { _val = 0;}
void bindTo(llvm::Value* v) { _val = v;}
llvm::Value* get() { return _val;}
std::ostream& print(std::ostream& os) const {
os << "LocalDesc:";
return Descriptor::print(os);
}
llvm::Value* genExpr(IR::Code&);
llvm::Value* genAddress(IR::Code&);
};
class Scope {
std::map<std::string,Descriptor*> _map;
Scope* _parent;
public:
Scope(Scope* p = 0) : _parent(p) {}
Descriptor* addSymbol(std::string key,Descriptor* d);
Descriptor* getSymbol(std::string key,bool rec=false);
friend std::ostream& operator<<(ostream& os,const Scope& s) {
os << "scope[";
std::map<std::string,Descriptor*>::const_iterator i = s._map.begin();
while (i != s._map.end()) {
os << '\t' << setw(20) << i->first << " --> " << *(i->second) << endl;
++i;
}
return os << ']' << endl;
}
int scanMethods(int lastM,TypeClass* toCheck);
void scanAttributes(IR::Code& code,std::vector<llvm::Type*>& att);
};
class Env {
stack<Scope*> _env;
Type *_tint,*_tbool,*_tvoid,*_terror;
TypeClass* _currentClass;
ClassDescriptor* _currentDesc;
Type* _returnType;
public:
Env();
~Env();
Scope* openScope();
void pushScope(Scope* s);
Scope* popScope();
Descriptor* addSymbol(std::string key,Descriptor* d);
Descriptor* addMethod(std::string key,MethodDescriptor* d);
Descriptor* getSymbol(std::string key,bool rec=false);
void analyze(AST::Node* root);
void reportError(std::string s);
void setCurrentClass(TypeClass* cl,ClassDescriptor* cd) { _currentClass = cl;_currentDesc = cd;}
void setReturnType(Type* rt) { _returnType = rt;}
TypeClass* getCurrentClass() { return _currentClass;}
ClassDescriptor* getCurrentClassDesc() { return _currentDesc;}
Type* getReturnType() { return _returnType;}
Type* getTypeInt() { return _tint;}
Type* getTypeBool() { return _tbool;}
Type* getTypeVoid() { return _tvoid;}
Type* getTypeError() { return _terror;}
};
};
#endif