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
|
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(TokenKey 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(TokenKey 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(TokenKey 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(TokenKey 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()));
}
public void addClassInstance(AbstractInstance t, String c) {
ClassInstance cls = (c != null) ?
this.getClass(new TokenKey(c, 0)) :
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(TokenKey id) {
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(TokenKey id) {
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(TokenKey id) {
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);
}
}
|