Analysis.jrag 8.67 KB
Newer Older
Niklas Fors's avatar
Niklas Fors committed
1
2
3
import java.util.*;


Niklas Fors's avatar
Niklas Fors committed
4
aspect TypeAnalysis {
Johannes Mey's avatar
Johannes Mey committed
5
6
  public abstract TypeUse Component.getTypeUse();

7
  //--- lookupType ---
Johannes Mey's avatar
Johannes Mey committed
8
9
  syn TypeDecl TypeUse.decl() = lookupType(getID());
  inh TypeDecl TypeUse.lookupType(String name);
10
  inh TypeDecl TypeDecl.lookupType(String name);
Johannes Mey's avatar
Johannes Mey committed
11
  eq Program.getChild().lookupType(String name) {
12
    for (TypeDecl td : getTypeDecls()) {
Johannes Mey's avatar
Johannes Mey committed
13
14
15
16
17
18
      if (td.getID().equals(name)) {
        return td;
      }
    }
    return null;
  }
19

20
21
  //--- isAlreadyDeclared ---
  syn boolean TypeDecl.isAlreadyDeclared() = lookupType(getID()) != this;
Niklas Fors's avatar
Niklas Fors committed
22
}
Niklas Fors's avatar
Niklas Fors committed
23

Niklas Fors's avatar
Niklas Fors committed
24
aspect ComponentAnalysis {
25
26
27
28
  //--- isTargetOfDirectedRelation ---
  inh boolean Component.isTargetOfDirectedRelation();
  eq Relation.getRight().isTargetOfDirectedRelation() = getDirection() instanceof RightDirection;
  eq Program.getChild().isTargetOfDirectedRelation() = false;
Johannes Mey's avatar
Johannes Mey committed
29

30
  //--- name ---
Johannes Mey's avatar
Johannes Mey committed
31
32
  syn String Component.name() = getID();

33
  //--- enclosingTypeDecl ---
Johannes Mey's avatar
Johannes Mey committed
34
35
36
37
  inh TypeDecl Component.enclosingTypeDecl();
  eq TypeDecl.getChild().enclosingTypeDecl() = this;
  eq Program.getChild().enclosingTypeDecl() = null;

38
  //--- otherSide ---
Johannes Mey's avatar
Johannes Mey committed
39
40
41
42
43
  inh RelationComponent RelationComponent.otherSide();
  eq Relation.getLeft().otherSide() = getRight();
  eq Relation.getRight().otherSide() = getLeft();
  eq Program.getChild().otherSide() = null;

44
  //--- ofTypeDecl ---
45
  syn TypeDecl RelationComponent.ofTypeDecl() = otherSide().getTypeUse().decl();
Johannes Mey's avatar
Johannes Mey committed
46

47
48
49
50
51
52
  //--- isAlreadyDeclared ---
  /**
   * Check, if role with the same name is already declared on the same nonterminal
   */
  syn boolean RelationComponent.isAlreadyDeclared()
    = !isTargetOfDirectedRelation()                     /* if unnamed in relation, there is no role name, so no error */
53
54
      && getTypeUse().decl() != null                           /* nonterminal type of role is defined */
      && findComponent(getTypeUse().decl(), name()) != this;   /* there is another role defined previously with the same name */
55
56
57
58
59
60
61
62

  //--- findComponent ---
  /** Search for either a component on the RHS of the given type with the given name,
   *   or a relation part for the given type and a role with the given name */
  inh Component Component.findComponent(TypeDecl td, String name);
  eq Program.getChild().findComponent(TypeDecl td, String name)
    = findComponentSyn(td, name);
  syn Component Program.findComponentSyn(TypeDecl td, String name) {
Johannes Mey's avatar
Johannes Mey committed
63
64
65
66
67
68
    for (Component c: td.getComponents()) {
      if (c.name().equals(name)) {
        return c;
      }
    }

69
70
71
72
73
    for (Relation r : getRelations()) {
      if (r.getLeft().matches(td, name))
        return r.getLeft();
      if (r.getRight().matches(td, name))
        return r.getRight();
Johannes Mey's avatar
Johannes Mey committed
74
75
76
77
78
    }

    return null;
  }

79
80
81
82
  //--- isInvalidRedefinition ---
  /**
   * Check, if a component with the same name is already declared in some supertype
   */
83
  syn boolean Component.isInvalidRedefinition() = invalidRedefinition() != null;
84

85
86
87
88
89
90
91
92
93
  /**
   * Check, if a component with the same name is already declared in some supertype, and return it, if any
   */
  syn Component Component.invalidRedefinition() = null;
  eq TokenComponent.invalidRedefinition() = invalidRedefinitionOn(enclosingTypeDecl());
  eq RelationComponent.invalidRedefinition() = invalidRedefinitionOn(getTypeUse().decl());

  syn Component Component.invalidRedefinitionOn(TypeDecl td) {
    if (td == null) return null;
94
95
96

    while (td.hasSuper() && td.getSuper().decl() != null) {
      td = td.getSuper().decl();
97
98
      // find a matching component on the RHS of the (current) super type
      Component c = findComponent(td, getID());
99

100
      if (c != null && !this.isEqual(c)) return c;
101
    }
102
    return null;
103
104
  }

105
  //--- isEqual ---
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
  syn boolean Component.isEqual(Component c) = this.getClass() == c.getClass() && getTypeUse().isEqual(c.getTypeUse());

  syn boolean TypeUse.isEqual(TypeUse u);
  eq SimpleTypeUse.isEqual(TypeUse u) = u instanceof SimpleTypeUse && getID().equals(u.getID());
  eq ParameterizedTypeUse.isEqual(TypeUse u) {
    if (!getID().equals(u.getID())) return false;
    if (!(u instanceof ParameterizedTypeUse)) return false;
    ParameterizedTypeUse pu = (ParameterizedTypeUse) u;
    if (getNumTypeUse() != pu.getNumTypeUse()) return false;
    for (int i = 0; i < getNumTypeUse(); i++) {
      if (!getTypeUse(i).isEqual(pu.getTypeUse(i))) return false;
    }
    return true;
  }

121
122
123
124
125
  //--- matches ---
  /**
   * @return true, if the component has both type and role, its type matches the given typeDecl and its name matches the given name
   */
  syn boolean RelationComponent.matches(TypeDecl td, String name)
126
    = !isTargetOfDirectedRelation() && getTypeUse().decl() == td && name().equals(name);
Johannes Mey's avatar
Johannes Mey committed
127

128
  //--- relationComponents ---
Johannes Mey's avatar
Johannes Mey committed
129
130
131
132
  coll Set<RelationComponent> TypeDecl.relationComponents()
    [new HashSet<RelationComponent>()]
    root Program;
  RelationComponent contributes this
133
    when !isTargetOfDirectedRelation() && getTypeUse().decl() != null
Johannes Mey's avatar
Johannes Mey committed
134
    to TypeDecl.relationComponents()
135
    for getTypeUse().decl();
Johannes Mey's avatar
Johannes Mey committed
136

137
  //--- relationComponentsTransitive ---
138
139
140
141
142
143
144
145
146
  syn Collection<RelationComponent> TypeDecl.relationComponentsTransitive() {
    ArrayList<RelationComponent> list = new ArrayList<>();
    if (hasSuper() && getSuper().decl() != null) {
      list.addAll(getSuper().decl().relationComponentsTransitive());
    }
    list.addAll(relationComponents());
    return list;
  }

147
  //--- oneRelationComponents ---
Johannes Mey's avatar
Johannes Mey committed
148
149
150
151
152
153
154
155
156
  syn Set<OneRelationComponent> TypeDecl.oneRelationComponents() {
    Set<OneRelationComponent> set = new HashSet<>();
    for (RelationComponent rc: relationComponents()) {
      if (rc instanceof OneRelationComponent) {
        set.add((OneRelationComponent) rc);
      }
    }
    return set;
  }
157

158
  //--- needUnresolvedClass ---
159
160
161
162
163
  syn boolean TypeDecl.needUnresolvedClass() {
    // a TypeDecl needs an unresolved class, if it can appear in a relation
    // TODO
    return true;
  }
164

165
  //--- isList ---
166
167
168
  syn boolean Component.isList() = false;
  eq ListComponent.isList() = true;

169
  //--- isOpt ---
170
171
172
  syn boolean Component.isOpt() = false;
  eq OptComponent.isOpt() = true;

173
  //--- isNullable ---
174
175
  syn boolean Component.isNullable() = false;
  eq TokenComponent.isNullable() = !"float double int short long char byte boolean".contains(getTypeUse().getID());
Niklas Fors's avatar
Niklas Fors committed
176
177
}

178
179
aspect InstanceSupplier {

180
  //--- program ---
181
182
183
  inh Program TypeDecl.program();
  eq Program.getTypeDecl(int i).program() = this;

184
  //--- subTypeDecls ---
185
186
187
188
189
190
191
192
193
194
  syn Collection<TypeDecl> TypeDecl.subTypeDecls() {
    java.util.List<TypeDecl> subDecls = new ArrayList();
    for (TypeDecl decl : program().getTypeDeclList()) {
      if (decl.hasSuper() && decl.getSuper().getID().equals(getID())) {
        subDecls.add(decl);
      }
    }
    return subDecls;
  }

195
  //--- instantiableSubType ---
196
  syn TypeDecl TypeDecl.instantiableSubType() {
197
    if (getAbstract() == false) {
198
      return this;
199
200
201
    } else {
      for (TypeDecl sub : subTypeDecls()) {
        if (sub.getAbstract() == false) {
202
          return sub;
203
        } else {
204
          TypeDecl subInstance = sub.instantiableSubType();
205
          if (subInstance != null) {
206
            return subInstance;
207
208
209
210
211
212
213
214
          }
        }
      }
    }
    return null;
  }
}

215
aspect Constructors {
216
  //--- componentsTransitive ---
Johannes Mey's avatar
Johannes Mey committed
217
218
219
220
221
222
  syn Collection<Component> TypeDecl.componentsTransitive() {
    ArrayList<Component> list = new ArrayList<>();
    if (hasSuper() && getSuper().decl() != null) {
      list.addAll(getSuper().decl().componentsTransitive());
    }
    for (Component c: getComponents()) {
223
224
225
      if (c.inConstructor()) {
        list.add(c);
      }
Johannes Mey's avatar
Johannes Mey committed
226
227
228
229
    }
    return list;
  }

230
  //--- needsConstructor ---
Johannes Mey's avatar
Johannes Mey committed
231
232
233
234
235
236
237
238
239
240
241
  syn boolean TypeDecl.needsConstructor() {
    if (componentsTransitive().isEmpty()) {
      return false;
    }
    if (!relationComponents().isEmpty()) {
      return true;
    }
    return hasSuper()
      && getSuper().decl() != null
      && getSuper().decl().needsConstructor();
  }
242

243
  //--- inConstructor ---
244
245
246
247
248
  /**
   * @return true, if the component should be added to the constructor (i.e., is not an NTA)
   */
  syn boolean Component.inConstructor() = true;
  eq NTAComponent.inConstructor() = false;
249
250
  eq NTAOptComponent.inConstructor() = false;
  eq NTAListComponent.inConstructor() = false;
251
252
}

Niklas Fors's avatar
Niklas Fors committed
253
aspect Utils {
254

255
  //--- isMany ---
256
257
258
  syn boolean RelationComponent.isMany() = false;
  eq ManyRelationComponent.isMany() = true;

259
  //--- toString ---
Johannes Mey's avatar
Johannes Mey committed
260
261
262
263
264
265
  public String SimpleTypeUse.toString() {
    return getID();
  }
  public String ParameterizedTypeUse.toString() {
    StringBuilder sb = new StringBuilder();
    sb.append(getID()).append("<");
266
    boolean first = true;
Johannes Mey's avatar
Johannes Mey committed
267
    for (TypeUse u: getTypeUses()) {
268
269
270
      if (first) {
        first = false;
      } else {
Johannes Mey's avatar
Johannes Mey committed
271
272
        sb.append(", ");
      }
273
      sb.append(u.toString());
Johannes Mey's avatar
Johannes Mey committed
274
275
276
277
278
279
280
    }
    sb.append(">");
    return sb.toString();
  }
  public String TypeDecl.toString() {
    return getID();
  }
Niklas Fors's avatar
Niklas Fors committed
281
}