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
|
package st;
import java.util.*;
import misc.*;
/**
* Class which provides methods for interacting with and managing
* the symbol table. Maintains context-awareness to keep the state
* of each symbol consistent.
*/
public class SymbolTable {
private HashMap<TokenKey,AbstractInstance> symt; // the mapping of ids to Instances
private HashMap<TypeEnum,AbstractInstance> active; // the current scope of the visitor (class, method)
public SymbolTable() {
MinimalLogger.info("Creating a new SymbolTable...");
this.symt = new HashMap<>();
this.active = new HashMap<>();
}
@Override public String toString() {
StringBuilder mapAsString = new StringBuilder("{");
for (TokenKey key : this.symt.keySet()) {
mapAsString.append(key.toString() + ":" + this.symt.get(key).getType() + ", ");
}
mapAsString.delete(mapAsString.length()-2, mapAsString.length()).append("}");
return mapAsString.toString();
}
/**
* Methods intended to be used during the first pass
*/
public void put(TokenKey id, AbstractInstance symbol) {
MinimalLogger.info(String.format("Inserting %s -> %s",
id,
symbol.getType()));
this.symt.put(id, symbol);
}
/**
* Methods intended to be used during the second pass
*/
public void setExtend(String arg) {
ClassInstance cls = (ClassInstance) this.active.get(TypeEnum.classname);
ClassInstance ext = this.getClass(arg);
MinimalLogger.info(String.format("%s found to extend %s",
cls.getName(),
ext.getName()));
cls.setExtend(ext);
for (TypeInstance t : ext.getLocals()) {
MinimalLogger.info(String.format("Added %s (%s) as a local var of %s (%s)",
t.getName(), t.getType(),
cls.getName(), cls.getType()));
cls.addLocal(t);
}
for (MethodInstance m : ext.getMethods()) {
MinimalLogger.info(String.format("Added %s (%s) as a method of %s (%s)",
m.getName(), m.getType(),
cls.getName(), cls.getType()));
cls.addMethod(m);
}
}
public void addLocal(String lvar) {
TypeInstance var = this.getType(lvar);
AbstractInstance par;
if (this.active.get(TypeEnum.method) != null) { // we are in a method
MethodInstance par1 = (MethodInstance) this.active.get(TypeEnum.method);
par1.addLocal(var);
par = par1;
} else {
ClassInstance par1 = (ClassInstance) this.active.get(TypeEnum.classname);
par1.addLocal(var);
par = par1;
}
MinimalLogger.info(String.format("Added %s (%s) as a local var of %s (%s)",
var.getName(), var.getType(),
par.getName(), par.getType()));
}
public void addMethod(String mtd) {
ClassInstance cls = (ClassInstance) this.active.get(TypeEnum.classname);
MethodInstance lmtd = this.getMethod(mtd);
cls.addMethod(lmtd);
MinimalLogger.info(String.format("Added %s as a method of %s",
lmtd.getName(), cls.getName()));
}
public void addParameter(String arg) {
MethodInstance mtd = (MethodInstance) this.active.get(TypeEnum.method);
TypeInstance para = this.getType(arg);
mtd.addArgument(para); // also adds to local vars
MinimalLogger.info(String.format("Added %s as a parameter of %s",
para.getName(), mtd.getName()));
MinimalLogger.info(String.format("Added %s as a localvar of %s",
para.getName(), mtd.getName()));
}
public void addClassInstance(TypeInstance t, String c) {
ClassInstance cls = (c != null) ?
this.getClass(c) :
null;
t.addClassInstance(cls);
}
/**
* Methods to safely retrieve differentiable types
* in `typecheck', `vaporize' libraries
*/
public void setActive(TypeEnum type, AbstractInstance id) {
MinimalLogger.info(String.format("%s is now the active %s.",
id.getName(),
type));
this.active.put(type, id);
}
public void removeActive(TypeEnum type) {
AbstractInstance id = this.getActive(type);
MinimalLogger.info(String.format("%s is no longer the active %s.",
id.getName(),
type));
this.active.remove(type);
}
public TypeInstance getType(String name) {
TokenKey id = new TokenKey(name,
(ClassInstance) this.getActive(TypeEnum.classname),
(MethodInstance) this.getActive(TypeEnum.method));
AbstractInstance symbol;
TypeInstance ret = ((symbol = this.symt.get(id)) !=
null && symbol instanceof TypeInstance) ?
(TypeInstance) symbol : null;
if (ret == null)
MinimalLogger.severe(String.format("getType returning null for missing alias %s!",
id));
return ret;
}
public MethodInstance getMethod(String name) {
TokenKey id = new TokenKey(name,
(ClassInstance) this.getActive(TypeEnum.classname),
null);
AbstractInstance symbol;
MethodInstance ret = ((symbol = this.symt.get(id)) !=
null && symbol instanceof MethodInstance) ?
(MethodInstance) symbol : null;
if (ret == null)
MinimalLogger.severe(String.format("getMethod returning null for missing alias %s!",
id));
return ret;
}
public ClassInstance getClass(String name) {
TokenKey id = new TokenKey(name,
null,
null);
AbstractInstance symbol;
ClassInstance ret = ((symbol = this.symt.get(id)) !=
null && symbol instanceof ClassInstance) ?
(ClassInstance) symbol : null;
if (ret == null)
MinimalLogger.severe(String.format("getClass returning null for missing alias %s!",
id));
return ret;
}
public AbstractInstance getActive(TypeEnum type) {
return this.active.get(type);
}
}
|