Analysis.jrag 8.46 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
34
  //--- toTypeDecl ---
  /** @return enclosing type */
Johannes Mey's avatar
Johannes Mey committed
35
  syn TypeDecl Component.toTypeDecl() = enclosingTypeDecl();
36
  /** @return type of nonterminal relation role is defined for */
Johannes Mey's avatar
Johannes Mey committed
37
  eq RelationComponent.toTypeDecl() = getTypeUse().decl();
38
39

  //--- enclosingTypeDecl ---
Johannes Mey's avatar
Johannes Mey committed
40
41
42
43
  inh TypeDecl Component.enclosingTypeDecl();
  eq TypeDecl.getChild().enclosingTypeDecl() = this;
  eq Program.getChild().enclosingTypeDecl() = null;

44
  //--- otherSide ---
Johannes Mey's avatar
Johannes Mey committed
45
46
47
48
49
  inh RelationComponent RelationComponent.otherSide();
  eq Relation.getLeft().otherSide() = getRight();
  eq Relation.getRight().otherSide() = getLeft();
  eq Program.getChild().otherSide() = null;

50
  //--- ofTypeDecl ---
Johannes Mey's avatar
Johannes Mey committed
51
52
  syn TypeDecl RelationComponent.ofTypeDecl() = otherSide().toTypeDecl();

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  //--- 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 */
      && toTypeDecl() != null                           /* nonterminal type of role is defined */
      && findComponent(toTypeDecl(), name()) != this;   /* there is another role defined previously with the same name */

  //--- 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
69
70
71
72
73
74
    for (Component c: td.getComponents()) {
      if (c.name().equals(name)) {
        return c;
      }
    }

75
76
77
78
79
    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
80
81
82
83
84
    }

    return null;
  }

85
86
87
88
  //--- isInvalidRedefinition ---
  /**
   * Check, if a component with the same name is already declared in some supertype
   */
89
90
  syn boolean Component.isInvalidRedefinition() {
    TypeDecl td = toTypeDecl();
91
    if (td == null) return false;
92
93
94

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

      if (c != null && !this.isEqual(c)) return true;
    }
    return false;
  }

103
  //--- isEqual ---
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  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;
  }

119
120
121
122
123
124
  //--- 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)
    = !isTargetOfDirectedRelation() && toTypeDecl() == td && name().equals(name);
Johannes Mey's avatar
Johannes Mey committed
125

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

135
  //--- relationComponentsTransitive ---
136
137
138
139
140
141
142
143
144
  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;
  }

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

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

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

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

171
  //--- isNullable ---
172
173
  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
174
175
}

176
177
aspect InstanceSupplier {

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

182
  //--- subTypeDecls ---
183
184
185
186
187
188
189
190
191
192
  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;
  }

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

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

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

241
  //--- inConstructor ---
242
243
244
245
246
  /**
   * @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;
247
248
  eq NTAOptComponent.inConstructor() = false;
  eq NTAListComponent.inConstructor() = false;
249
250
}

Niklas Fors's avatar
Niklas Fors committed
251
aspect Utils {
252

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

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