NameResolution.jadd 14.5 KB
Newer Older
1
2
aspect NameResolutionHelper {

3
4
5
  protected static final String ASTNode.unresolvedPrefix = "Unresolved$";
  protected static final String ASTNode.isUnresolvedMethod = "is$Unresolved";
  protected static final String ASTNode.asUnresolvedMethod = "as$Unresolved";
6
7
  protected static final String ASTNode.unresolvedTokenMethod = unresolvedPrefix + "Token";
  protected static final String ASTNode.unresolvedResolveOppositeMethod = unresolvedPrefix + "ResolveOpposite";
8
9
10
  protected static final String ASTNode.createReferenceMethod = "createReference";
  protected static final String ASTNode.createRefMethod = "createRef";
  protected static final String ASTNode.createRefDirectionMethod = "createRefDirection";
11
  protected static final String ASTNode.resolvePrefix = "resolve";
12
  protected static final String ASTNode.globallyResolvePrefix = "globallyResolve";
13
  protected static final String ASTNode.resolvePostfix = "ByToken";
14
15
  protected static final String ASTNode.resolveAllMethod = "resolveAll";
  protected static final String ASTNode.treeResolveAllMethod = "treeResolveAll";
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
  protected static final String ASTNode.unresolvedNodeInterface = unresolvedPrefix + "Node$Interface";

  public void TypeDecl.generateUnresolvedClass(StringBuilder sb) {
    if (getAbstract()) {
      sb.append(ind(1) + "abstract ");
    } else {
      sb.append(ind(1));
    }
    sb.append("class " + unresolvedPrefix + getID() + " extends " + getID() + "  implements " + unresolvedNodeInterface + " {\n");

    sb.append(ind(2) + "private String unresolved$Token;\n");
    sb.append(ind(2) + "public String get" + unresolvedTokenMethod + "() {\n");
    sb.append(ind(3) + "return unresolved$Token;\n");
    sb.append(ind(2) + "}\n");
    sb.append(ind(2) + "void set" + unresolvedTokenMethod + "(String token) {\n");
    sb.append(ind(3) + "this.unresolved$Token = token;\n");
    sb.append(ind(2) + "}\n");

    sb.append(ind(2) + "private boolean unresolved$ResolveOpposite;\n");
    sb.append(ind(2) + "public boolean get" + unresolvedResolveOppositeMethod + "() {\n");
    sb.append(ind(3) + "return unresolved$ResolveOpposite;\n");
    sb.append(ind(2) + "}\n");
    sb.append(ind(2) + "void set" + unresolvedResolveOppositeMethod + "(boolean resolveOpposite) {\n");
    sb.append(ind(3) + "this.unresolved$ResolveOpposite = resolveOpposite;\n");
    sb.append(ind(2) + "}\n");

    sb.append(ind(1) + "}\n");

    sb.append(ind(1) + unresolvedNodeInterface + " " + getID() + "." + asUnresolvedMethod + "() {\n");
    sb.append(ind(2) + "return null;\n");
    sb.append(ind(1) + "}\n");
    sb.append(ind(1) + unresolvedNodeInterface + " " + unresolvedPrefix + getID() + "." + asUnresolvedMethod + "() {\n");
    sb.append(ind(2) + "return this;\n");
    sb.append(ind(1) + "}\n");

    sb.append(ind(1) + "boolean " + getID() + "." + isUnresolvedMethod + "() {\n");
    sb.append(ind(2) + "return false;\n");
    sb.append(ind(1) + "}\n");
    sb.append(ind(1) + "boolean " + unresolvedPrefix + getID() + "." + isUnresolvedMethod + "() {\n");
    sb.append(ind(2) + "return true;\n");
    sb.append(ind(1) + "}\n");
  }
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
  public String Program.generateRewriteToSuperTypeStub() {
    StringBuilder sb = new StringBuilder();
    generateRewriteToSuperTypeStub(sb);
    return sb.toString();
  }

  public String Program.generateResolverStubs() {
    StringBuilder sb = new StringBuilder();
    generateResolverStubs(sb);
    return sb.toString();
  }

  public void Program.generateResolverStubs(StringBuilder sb) {
    sb.append("aspect RefResolverStubs {\n\n");

    for (Relation r: getRelations()) {
      r.generateContextDependentNameResolution(sb);
    }

    if (resolverHelper || ASTNode.jsonPointer || ASTNode.manualReferences) {
      for (TypeDecl decl : getTypeDeclList()) {
        decl.generateContextIndependentNameResolution(sb);
        sb.append("\n");
      }
    }
    sb.append("}\n\n");

    if (ASTNode.manualReferences) {
      sb.append("aspect RefCreatorStubs {\n\n");

      for (Relation r: getRelations()) {
        r.generateContextDependentRefCreation(sb);
      }

      generateGenericRefCreation(sb);
      sb.append("\n");

      for (TypeDecl decl : getTypeDeclList()) {
        decl.generateContextIndependentRefCreation(sb);
        sb.append("\n");
      }

      sb.append("}\n\n");
    }
  }

  public void Program.generateGenericRefCreation(StringBuilder sb) {
    sb.append(ind(1) + "// generic reference creation\n");
107
108
    sb.append(ind(1) + "syn String ASTNode." + createReferenceMethod + "();\n");
    sb.append(ind(1) + "eq ASTNode." + createReferenceMethod + "() {\n");
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
    sb.append(ind(2) + "throw new RuntimeException(\"Generic reference creation not implemented.\");\n");
    sb.append(ind(1) + "}\n");
  }

  public void Relation.generateContextDependentRefCreation(StringBuilder sb) {
    sb.append(ind(1) + "// " + prettyPrint() + "\n");
    getDirection().generateContextDependentRefCreation(sb);
    sb.append("\n");
  }

  public abstract void Direction.generateContextDependentRefCreation(StringBuilder sb);
  public void RightDirection.generateContextDependentRefCreation(StringBuilder sb) {
    relation().getLeft().generateContextDependentRefCreation(sb);
  }
  public void LeftDirection.generateContextDependentRefCreation(StringBuilder sb) {
    relation().getRight().generateContextDependentRefCreation(sb);
  }
  public void Bidirectional.generateContextDependentRefCreation(StringBuilder sb) {
    relation().getLeft().generateContextDependentRefCreation(sb);
    relation().getRight().generateContextDependentRefCreation(sb);
  }

  public void RelationComponent.generateContextDependentRefCreation(StringBuilder sb) {
    sb.append(ind(1) + "// context-dependent reference creation\n");
133
    sb.append(ind(1) + "syn String " + getTypeUse().decl() + "." + createRefMethod + "To" + nameCapitalized() + "(" + ofTypeDecl() + " target) {\n");
134
    sb.append(ind(2) + "// default to context-independent reference creation\n");
135
    sb.append(ind(2) + "return target." + createReferenceMethod + "();\n");
136
137
138
139
140
    sb.append(ind(1) + "}\n");
  }

  public void TypeDecl.generateContextIndependentRefCreation(StringBuilder sb) {
    sb.append(ind(1) + "// context-independent reference creation\n");
141
    sb.append(ind(1) + "eq " + getID() + "." + createReferenceMethod + "() {\n");
142
    sb.append(ind(2) + "// default to generic reference creation\n");
143
    sb.append(ind(2) + "return super." + createReferenceMethod + "();\n");
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
    sb.append(ind(1) + "}\n");
  }

  public void Program.generateRewriteToSuperTypeStub(StringBuilder sb) {

    sb.append("aspect ReferenceCreation {\n\n");

    for (TypeDecl decl : getTypeDeclList()) {
      decl.createReferenceCreator(sb);
    }

    sb.append("}\n\n");

    sb.append("aspect ResolverTrigger {\n\n");

    resolveAll(sb);

    for (TypeDecl decl : getTypeDeclList()) {
      decl.resolveAll(sb);
    }

    sb.append("}\n\n");

    sb.append("aspect RefResolverHelpers {\n\n");

169
170
171
    sb.append(ind(1) + "interface " + unresolvedNodeInterface + " {\n");
    sb.append(ind(2) + "String get" + unresolvedTokenMethod + "();\n");
    sb.append(ind(2) + "boolean get" + unresolvedResolveOppositeMethod + "();\n");
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
    sb.append(ind(1) + "}\n\n");

    for (TypeDecl td: getTypeDecls()) {
      if (td.needUnresolvedClass()) {
        td.generateUnresolvedClass(sb);
      }
    }

    sb.append("\n}\n");
  }

  public void TypeDecl.createReferenceCreator(StringBuilder sb) {

    TypeDecl instantiableSubType = instantiableSubType();
    if (instantiableSubType == null) {
      throw new RuntimeException("unable to find instantiable subtype for " + getID());
    }

190
191
192
193
    sb.append(ind(1) + "public static " + getID() + " " + getID() + "." + createRefMethod + "(String ref) {\n");
      sb.append(ind(2) + unresolvedPrefix + instantiableSubType.getID() + " unresolvedNode = new " + unresolvedPrefix + instantiableSubType.getID() + "();\n");
      sb.append(ind(2) + "unresolvedNode.set" + unresolvedPrefix + "Token(ref);\n");
      sb.append(ind(2) + "unresolvedNode.set" + unresolvedPrefix + "ResolveOpposite(true);\n");
194
195
196
      sb.append(ind(2) + "return unresolvedNode;\n");
    sb.append(ind(1) + "}\n");

197
198
199
200
    sb.append(ind(1) + "public static " + getID() + " " + getID() + "." + createRefDirectionMethod + "(String ref) {\n");
      sb.append(ind(2) + unresolvedPrefix + instantiableSubType.getID() + " unresolvedNode = new " + unresolvedPrefix + instantiableSubType.getID() + "();\n");
      sb.append(ind(2) + "unresolvedNode.set" + unresolvedPrefix + "Token(ref);\n");
      sb.append(ind(2) + "unresolvedNode.set" + unresolvedPrefix + "ResolveOpposite(false);\n");
201
202
203
204
205
206
      sb.append(ind(2) + "return unresolvedNode;\n");
    sb.append(ind(1) + "}\n");
  }

  public void TypeDecl.generateContextIndependentNameResolution(StringBuilder sb) {
    sb.append(ind(1) + "// context-independent name resolution\n");
207
208
    sb.append(ind(1) + "uncache ASTNode." + globallyResolvePrefix + getID() + resolvePostfix + "(String id);\n");
    sb.append(ind(1) + "syn " + getID() + " ASTNode." + globallyResolvePrefix + getID() + resolvePostfix + "(String id) {\n");
209
210
211
212
    if (serializer && !manualReferences) {
      if (jsonPointer) {
        sb.append(ind(2) + "return (" + getID() + ") resolveJsonPointer(id);\n");
      } else {
213
        sb.append(ind(2) + "return (" + getID() + ") " + globallyResolvePrefix + "ASTNodeByUID(id);\n");
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
      }
    } else {
      sb.append(ind(2) + "// perform context independent name resolution here using the id\n");
      sb.append(ind(2) + "throw new RuntimeException(\"Context-independent name resolution for " + getID() + " not implemented.\");\n");
    }
    sb.append(ind(1) + "}\n");
  }

  public void Relation.generateContextDependentNameResolution(StringBuilder sb) {
    sb.append(ind(1) + "// " + prettyPrint() + "\n");
    getDirection().generateContextDependentNameResolution(sb);
    sb.append("\n");
  }

  public abstract void Direction.generateContextDependentNameResolution(StringBuilder sb);
  public void RightDirection.generateContextDependentNameResolution(StringBuilder sb) {
    relation().getLeft().generateContextDependentNameResolution(sb);
  }
  public void LeftDirection.generateContextDependentNameResolution(StringBuilder sb) {
    relation().getRight().generateContextDependentNameResolution(sb);
  }
  public void Bidirectional.generateContextDependentNameResolution(StringBuilder sb) {
    relation().getLeft().generateContextDependentNameResolution(sb);
    relation().getRight().generateContextDependentNameResolution(sb);
  }

  public abstract void RelationComponent.generateContextDependentNameResolution(StringBuilder sb);
  public void OneRelationComponent.generateContextDependentNameResolution(StringBuilder sb) {
    generateDirectedContextDependentNameResolution(sb);
  }
  public void OptionalRelationComponent.generateContextDependentNameResolution(StringBuilder sb) {
    // optional relations are resolved in the same way as mandatory relations
    // TODO maybe, there should be a check if the id to be solved is empty or null
    generateDirectedContextDependentNameResolution(sb);
  }
  public void ManyRelationComponent.generateContextDependentNameResolution(StringBuilder sb) {

    if (serializer && !resolverHelper) {
252
      sb.append(ind(1) + ofTypeDecl() + " " + getTypeUse().decl() + ".resolve" + nameCapitalized() + resolvePostfix + "(String id, int position) {\n");
253
        sb.append(ind(2) + "return (" + ofTypeDecl() + ") " + globallyResolvePrefix + "ASTNodeByUID(id);\n");
254
255
256
      sb.append(ind(1) + "}\n");
    } else {
      sb.append(ind(1) + "// context-dependent name resolution\n");
257
258
      sb.append(ind(1) + "uncache " + getTypeUse().decl() + ".resolve" + nameCapitalized() + resolvePostfix + "(String id, int position);\n");
      sb.append(ind(1) + "syn " + ofTypeDecl() + " " + getTypeUse().decl() + ".resolve" + nameCapitalized() + resolvePostfix + "(String id, int position) {\n");
259
        sb.append(ind(2) + "// default to context-independent name resolution\n");
260
        sb.append(ind(2) + "return " + globallyResolvePrefix + ofTypeDecl() + resolvePostfix + "(id);\n");
261
262
263
264
265
266
      sb.append(ind(1) + "}\n");
    }
  }

  public void RelationComponent.generateDirectedContextDependentNameResolution(StringBuilder sb) {
    if (serializer && !resolverHelper) {
267
      sb.append(ind(1) + ofTypeDecl() + " " + getTypeUse().decl() + ".resolve" + nameCapitalized() + resolvePostfix + "(String id) {\n");
268
        sb.append(ind(2) + "return (" + ofTypeDecl() + ") " + globallyResolvePrefix + "ASTNodeByUID(id);\n");
269
270
271
      sb.append(ind(1) + "}\n");
    } else {
      sb.append(ind(1) + "// context-dependent name resolution\n");
272
273
      sb.append(ind(1) + "uncache " + getTypeUse().decl() + ".resolve" + nameCapitalized() + resolvePostfix + "(String id);\n");
      sb.append(ind(1) + "syn " + ofTypeDecl() + " " + getTypeUse().decl() + ".resolve" + nameCapitalized() + resolvePostfix + "(String id) {\n");
274
        sb.append(ind(2) + "// default to context-independent name resolution\n");
275
        sb.append(ind(2) + "return " + globallyResolvePrefix + ofTypeDecl() + resolvePostfix + "(id);\n");
276
277
278
279
280
281
      sb.append(ind(1) + "}\n");
    }
  }

  public void Program.resolveAll(StringBuilder sb) {
    sb.append(ind(1) + "// enforce resolving of all non-containment relations of the current non-terminal\n");
282
    sb.append(ind(1) + "public void ASTNode." + resolveAllMethod + "() {\n");
283
284
285
    sb.append(ind(1) + "}\n\n");

    sb.append(ind(1) + "// enforce resolving in the entire subtree\n");
286
    sb.append(ind(1) + "public void ASTNode." + treeResolveAllMethod + "() {\n");
287
288
289
290
      sb.append(ind(2) + "if (children != null) {\n");
        sb.append(ind(3) + "for (int i = 0; i < numChildren; ++i) {\n");
          sb.append(ind(4) + "ASTNode child = children[i];\n");
          sb.append(ind(4) + "if (child != null) {\n");
291
            sb.append(ind(5) + "child." + treeResolveAllMethod + "();\n");
292
293
294
          sb.append(ind(4) + "}\n");
        sb.append(ind(3) + "}\n");
      sb.append(ind(2) + "}\n");
295
      sb.append(ind(2) + resolveAllMethod + "();\n");
296
297
298
299
300
    sb.append(ind(1) + "}\n");
  }

  public void TypeDecl.resolveAll(StringBuilder sb) {
    sb.append(ind(1) + "// enforce resolving of all non-containment relations of the current non-terminal\n");
301
    sb.append(ind(1) + "public void " + getID() + "." + resolveAllMethod + "() {\n");
302
303
304
305
306
307
308
    for (RelationComponent relationComponent : relationComponents()) {
      sb.append(ind(2));
      if (useJastAddNames) {
        sb.append("get" + relationComponent.nameCapitalized());
      } else {
        sb.append(relationComponent.name());
      }
309
      sb.append(relationComponent.isList() && useJastAddNames ? "List" : "").append("();\n");
310
    }
311
      sb.append(ind(2) + "super." + resolveAllMethod + "();\n");
312
313
314
    sb.append(ind(1) + "}\n");
  }
}