diff --git a/src/main/jastadd/Analysis.jrag b/src/main/jastadd/Analysis.jrag index 0524c6175805427457e5918b5eb6e1b330608768..27f3a7d89731f351b8a21043e9b2a816cd3d3548 100644 --- a/src/main/jastadd/Analysis.jrag +++ b/src/main/jastadd/Analysis.jrag @@ -4,95 +4,105 @@ import java.util.*; aspect TypeAnalysis { public abstract TypeUse Component.getTypeUse(); + //--- lookupType --- syn TypeDecl TypeUse.decl() = lookupType(getID()); inh TypeDecl TypeUse.lookupType(String name); + inh TypeDecl TypeDecl.lookupType(String name); eq Program.getChild().lookupType(String name) { - for (TypeDecl td: getTypeDecls()) { + for (TypeDecl td : getTypeDecls()) { if (td.getID().equals(name)) { return td; } } return null; } - syn boolean TypeDecl.isAlreadyDeclared() - = lookupType(getID()) != this; - inh TypeDecl TypeDecl.lookupType(String name); - syn TypeDecl TypeDecl.mostGeneralSuperType() { - if (!hasSuper()) { - return this; - } else { - return getSuper().decl().mostGeneralSuperType(); - } - } + //--- isAlreadyDeclared --- + syn boolean TypeDecl.isAlreadyDeclared() = lookupType(getID()) != this; } aspect ComponentAnalysis { - syn boolean Component.isTargetOfDirectedRelation() = false; - eq RelationComponent.isTargetOfDirectedRelation() = isTargetOfRightDirection() | isTargetOfLeftDirection(); - inh boolean RelationComponent.isTargetOfRightDirection(); - eq Relation.getRight().isTargetOfRightDirection() - = getDirection() instanceof RightDirection; - eq Program.getChild().isTargetOfRightDirection() = false; - inh boolean RelationComponent.isTargetOfLeftDirection(); - eq Relation.getLeft().isTargetOfLeftDirection() - = getDirection() instanceof LeftDirection; - eq Program.getChild().isTargetOfLeftDirection() = false; + //--- isTargetOfDirectedRelation --- + inh boolean Component.isTargetOfDirectedRelation(); + eq Relation.getRight().isTargetOfDirectedRelation() = getDirection() instanceof RightDirection; + eq Program.getChild().isTargetOfDirectedRelation() = false; + //--- name --- syn String Component.name() = getID(); - syn TypeDecl Component.toTypeDecl() = enclosingTypeDecl(); - eq RelationComponent.toTypeDecl() = getTypeUse().decl(); + //--- enclosingTypeDecl --- inh TypeDecl Component.enclosingTypeDecl(); eq TypeDecl.getChild().enclosingTypeDecl() = this; eq Program.getChild().enclosingTypeDecl() = null; + //--- otherSide --- inh RelationComponent RelationComponent.otherSide(); eq Relation.getLeft().otherSide() = getRight(); eq Relation.getRight().otherSide() = getLeft(); eq Program.getChild().otherSide() = null; - syn TypeDecl RelationComponent.ofTypeDecl() = otherSide().toTypeDecl(); + //--- ofTypeDecl --- + syn TypeDecl RelationComponent.ofTypeDecl() = otherSide().getTypeUse().decl(); - syn boolean Component.isAlreadyDeclared() - = !isTargetOfDirectedRelation() - && toTypeDecl() != null - && lookupComponent(toTypeDecl(), name()) != this; - inh Component Component.lookupComponent(TypeDecl td, String name); - eq Program.getChild().lookupComponent(TypeDecl td, String name) - = lookupComponentSyn(td, name); - syn Component Program.lookupComponentSyn(TypeDecl td, String name) { + //--- 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 */ + && getTypeUse().decl() != null /* nonterminal type of role is defined */ + && findComponent(getTypeUse().decl(), 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) { for (Component c: td.getComponents()) { if (c.name().equals(name)) { return c; } } - for (Relation r: getRelations()) { - Component c = r.getLeft().lookup(td, name); - if (c != null) return c; - c = r.getRight().lookup(td, name); - if (c != null) return c; + for (Relation r : getRelations()) { + if (r.getLeft().matches(td, name)) + return r.getLeft(); + if (r.getRight().matches(td, name)) + return r.getRight(); } return null; } - syn boolean Component.isInvalidRedefinition() { - if (toTypeDecl() == null) return false; + //--- isInvalidRedefinition --- + /** + * Check, if a component with the same name is already declared in some supertype + */ + syn boolean Component.isInvalidRedefinition() = invalidRedefinition() != null; - TypeDecl td = toTypeDecl(); + /** + * 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; while (td.hasSuper() && td.getSuper().decl() != null) { td = td.getSuper().decl(); - Component c = lookupComponent(td, getID()); - if (c != null && isTargetOfDirectedRelation()) return true; + // find a matching component on the RHS of the (current) super type + Component c = findComponent(td, getID()); - if (c != null && !this.isEqual(c)) return true; + if (c != null && !this.isEqual(c)) return c; } - return false; + return null; } + //--- isEqual --- syn boolean Component.isEqual(Component c) = this.getClass() == c.getClass() && getTypeUse().isEqual(c.getTypeUse()); syn boolean TypeUse.isEqual(TypeUse u); @@ -108,20 +118,23 @@ aspect ComponentAnalysis { return true; } - syn RelationComponent RelationComponent.lookup(TypeDecl td, String name) - = !isTargetOfDirectedRelation() && toTypeDecl() == td && name().equals(name) - ? this - : null; - + //--- 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() && getTypeUse().decl() == td && name().equals(name); + //--- relationComponents --- coll Set<RelationComponent> TypeDecl.relationComponents() [new HashSet<RelationComponent>()] root Program; RelationComponent contributes this - when !isTargetOfDirectedRelation() && toTypeDecl() != null + when !isTargetOfDirectedRelation() && getTypeUse().decl() != null to TypeDecl.relationComponents() - for toTypeDecl(); + for getTypeUse().decl(); + //--- relationComponentsTransitive --- syn Collection<RelationComponent> TypeDecl.relationComponentsTransitive() { ArrayList<RelationComponent> list = new ArrayList<>(); if (hasSuper() && getSuper().decl() != null) { @@ -131,6 +144,7 @@ aspect ComponentAnalysis { return list; } + //--- oneRelationComponents --- syn Set<OneRelationComponent> TypeDecl.oneRelationComponents() { Set<OneRelationComponent> set = new HashSet<>(); for (RelationComponent rc: relationComponents()) { @@ -141,27 +155,33 @@ aspect ComponentAnalysis { return set; } + //--- needUnresolvedClass --- syn boolean TypeDecl.needUnresolvedClass() { // a TypeDecl needs an unresolved class, if it can appear in a relation // TODO return true; } + //--- isList --- syn boolean Component.isList() = false; eq ListComponent.isList() = true; + //--- isOpt --- syn boolean Component.isOpt() = false; eq OptComponent.isOpt() = true; + //--- isNullable --- syn boolean Component.isNullable() = false; eq TokenComponent.isNullable() = !"float double int short long char byte boolean".contains(getTypeUse().getID()); } aspect InstanceSupplier { + //--- program --- inh Program TypeDecl.program(); eq Program.getTypeDecl(int i).program() = this; + //--- subTypeDecls --- syn Collection<TypeDecl> TypeDecl.subTypeDecls() { java.util.List<TypeDecl> subDecls = new ArrayList(); for (TypeDecl decl : program().getTypeDeclList()) { @@ -172,6 +192,7 @@ aspect InstanceSupplier { return subDecls; } + //--- instantiableSubType --- syn TypeDecl TypeDecl.instantiableSubType() { if (getAbstract() == false) { return this; @@ -192,6 +213,7 @@ aspect InstanceSupplier { } aspect Constructors { + //--- componentsTransitive --- syn Collection<Component> TypeDecl.componentsTransitive() { ArrayList<Component> list = new ArrayList<>(); if (hasSuper() && getSuper().decl() != null) { @@ -205,6 +227,7 @@ aspect Constructors { return list; } + //--- needsConstructor --- syn boolean TypeDecl.needsConstructor() { if (componentsTransitive().isEmpty()) { return false; @@ -217,30 +240,37 @@ aspect Constructors { && getSuper().decl().needsConstructor(); } + //--- inConstructor --- /** * @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; + eq NTAOptComponent.inConstructor() = false; + eq NTAListComponent.inConstructor() = false; } aspect Utils { + //--- isMany --- syn boolean RelationComponent.isMany() = false; eq ManyRelationComponent.isMany() = true; + //--- toString --- public String SimpleTypeUse.toString() { return getID(); } public String ParameterizedTypeUse.toString() { StringBuilder sb = new StringBuilder(); sb.append(getID()).append("<"); - int i = 0; + boolean first = true; for (TypeUse u: getTypeUses()) { - sb.append(u.toString()); - if (++i < getNumTypeUse()) { + if (first) { + first = false; + } else { sb.append(", "); } + sb.append(u.toString()); } sb.append(">"); return sb.toString(); diff --git a/src/main/jastadd/Backend.jadd b/src/main/jastadd/Backend.jadd index f5d69d3facd57a19d3d5630d339455b928ddcc68..a3711d389ad5f5d1423fd8a1df97e900588306a8 100644 --- a/src/main/jastadd/Backend.jadd +++ b/src/main/jastadd/Backend.jadd @@ -240,7 +240,7 @@ aspect BackendDirectedAPI { generateGetOne(sb); // Set - sb.append(ind(1) + "public " + toTypeDecl() + " " + toTypeDecl()); + sb.append(ind(1) + "public " + getTypeUse().decl() + " " + getTypeUse().decl()); sb.append(".set" + nameCapitalized() + "(" + ofTypeDecl() + " o) {\n"); if (!optional) { sb.append(ind(2) + "assertNotNull(o);\n"); @@ -252,7 +252,7 @@ aspect BackendDirectedAPI { public void ManyRelationComponent.generateDirectedAPI(StringBuilder sb) { // Get - sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl() + "."); + sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + getTypeUse().decl() + "."); if (useJastAddNames) { // getXs sb.append("get" + nameCapitalized() + "s() {\n"); @@ -260,7 +260,7 @@ aspect BackendDirectedAPI { sb.append(ind(1) + "}\n"); // getXList - sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl()); + sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + getTypeUse().decl()); sb.append(".get" + nameCapitalized() + "List() {\n"); } else { sb.append(name() + "() {\n"); @@ -287,7 +287,7 @@ aspect BackendDirectedAPI { sb.append(ind(1) + "}\n"); // Add - sb.append(ind(1) + "public void " + toTypeDecl() + ".add"); + sb.append(ind(1) + "public void " + getTypeUse().decl() + ".add"); if (!useJastAddNames) { sb.append("To"); } @@ -302,7 +302,7 @@ aspect BackendDirectedAPI { sb.append(ind(1) + "}\n"); // Insert / add at specific position - sb.append(ind(1) + "public void " + toTypeDecl() + ".add"); + sb.append(ind(1) + "public void " + getTypeUse().decl() + ".add"); if (!useJastAddNames) { sb.append("To"); } @@ -317,7 +317,7 @@ aspect BackendDirectedAPI { sb.append(ind(1) + "}\n"); // Remove - sb.append(ind(1) + "public void " + toTypeDecl() + ".remove"); + sb.append(ind(1) + "public void " + getTypeUse().decl() + ".remove"); if (!useJastAddNames) { sb.append("From"); } @@ -331,7 +331,7 @@ aspect BackendDirectedAPI { } public void RelationComponent.generateGetOne(StringBuilder sb) { - sb.append(ind(1) + "public " + ofTypeDecl() + " " + toTypeDecl() + "."); + sb.append(ind(1) + "public " + ofTypeDecl() + " " + getTypeUse().decl() + "."); if (useJastAddNames) { sb.append("get" + nameCapitalized()); } else { @@ -353,7 +353,7 @@ aspect BackendDirectedAPI { public void RelationComponent.generateExtraOptAPI(StringBuilder sb) { // has - sb.append(ind(1) + "public boolean " + toTypeDecl()); + sb.append(ind(1) + "public boolean " + getTypeUse().decl()); sb.append(".has" + nameCapitalized() + "() {\n"); sb.append(ind(2) + "return "); if (useJastAddNames) { @@ -365,7 +365,7 @@ aspect BackendDirectedAPI { sb.append(ind(1) + "}\n"); // clear - sb.append(ind(1) + "public void " + toTypeDecl()); + sb.append(ind(1) + "public void " + getTypeUse().decl()); sb.append(".clear" + nameCapitalized() + "() {\n"); sb.append(ind(2) + "set" + nameCapitalized() + "(null);\n"); sb.append(ind(1) + "}\n"); @@ -418,7 +418,7 @@ aspect BackendBidirectionalAPI { generateGetOne(sb); // Set - sb.append(ind(1) + "public " + toTypeDecl() + " " + toTypeDecl()); + sb.append(ind(1) + "public " + getTypeUse().decl() + " " + getTypeUse().decl()); sb.append(".set" + nameCapitalized() + "(" + ofTypeDecl() + " o) {\n"); if (!isOpt) { sb.append(ind(2) + "assertNotNull(o);\n"); @@ -465,7 +465,7 @@ aspect BackendBidirectionalAPI { public void RelationComponent.generateBiManyMany(StringBuilder sb, RelationComponent opposite) { // Get - sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl() + "."); + sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + getTypeUse().decl() + "."); if (useJastAddNames) { // getXs sb.append("get" + nameCapitalized() + "s() {\n"); @@ -473,7 +473,7 @@ aspect BackendBidirectionalAPI { sb.append(ind(1) + "}\n"); // getXList - sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl()); + sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + getTypeUse().decl()); sb.append(".get" + nameCapitalized() + "List() {\n"); } else { sb.append(name() + "() {\n"); @@ -489,7 +489,7 @@ aspect BackendBidirectionalAPI { sb.append(ind(5) + "changed = true;\n"); sb.append(ind(5) + ofTypeDecl() + " resolvedElement = resolve" + nameCapitalized() + "ByToken(element.as$Unresolved().getUnresolved$Token(), i);\n"); sb.append(ind(5) + "if (resolvedElement != null && element.as$Unresolved().getUnresolved$ResolveOpposite()) {\n"); - sb.append(ind(6) + ASTNode.listClass + "<" + toTypeDecl() + "> otherList = resolvedElement." + opposite.getImplAttributeField() + ";\n"); + sb.append(ind(6) + ASTNode.listClass + "<" + getTypeUse().decl() + "> otherList = resolvedElement." + opposite.getImplAttributeField() + ";\n"); sb.append(ind(6) + "if (otherList == null) {\n"); sb.append(ind(7) + "otherList = new " + listClass + "<>();\n"); sb.append(ind(6) + "}\n"); @@ -508,7 +508,7 @@ aspect BackendBidirectionalAPI { sb.append(ind(1) + "}\n"); // Add - sb.append(ind(1) + "public void " + toTypeDecl() + ".add"); + sb.append(ind(1) + "public void " + getTypeUse().decl() + ".add"); if (!useJastAddNames) { sb.append("To"); } @@ -529,7 +529,7 @@ aspect BackendBidirectionalAPI { sb.append(ind(1) + "}\n"); // Insert / add at specific position - sb.append(ind(1) + "public void " + toTypeDecl() + ".add"); + sb.append(ind(1) + "public void " + getTypeUse().decl() + ".add"); if (!useJastAddNames) { sb.append("To"); } @@ -551,7 +551,7 @@ aspect BackendBidirectionalAPI { sb.append(ind(1) + "}\n"); // Remove - sb.append(ind(1) + "public void " + toTypeDecl() + ".remove"); + sb.append(ind(1) + "public void " + getTypeUse().decl() + ".remove"); if (!useJastAddNames) { sb.append("From"); } @@ -571,7 +571,7 @@ aspect BackendBidirectionalAPI { public void RelationComponent.generateBiManyOne(StringBuilder sb, RelationComponent opposite) { // Get - sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl() + "."); + sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + getTypeUse().decl() + "."); if (useJastAddNames) { // getXs sb.append("get" + nameCapitalized() + "s() {\n"); @@ -579,7 +579,7 @@ aspect BackendBidirectionalAPI { sb.append(ind(1) + "}\n"); // getXList - sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl()); + sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + getTypeUse().decl()); sb.append(".get" + nameCapitalized() + "List() {\n"); } else { sb.append(name() + "() {\n"); @@ -595,7 +595,7 @@ aspect BackendBidirectionalAPI { sb.append(ind(5) + "changed = true;\n"); sb.append(ind(5) + ofTypeDecl() + " resolvedElement = resolve" + nameCapitalized() + "ByToken(element.as$Unresolved().getUnresolved$Token(), i);\n"); sb.append(ind(5) + "if (element.as$Unresolved().getUnresolved$ResolveOpposite()) {\n"); - sb.append(ind(6) + toTypeDecl() + " oldTarget = resolvedElement." + opposite.getImplAttributeField() + ";\n"); + sb.append(ind(6) + getTypeUse().decl() + " oldTarget = resolvedElement." + opposite.getImplAttributeField() + ";\n"); sb.append(ind(6) + "if (oldTarget != null && oldTarget != this) {\n"); sb.append(ind(7) + "oldTarget." + getImplAttributeField() + ".remove(resolvedElement);\n"); sb.append(ind(6) + "}\n"); @@ -620,7 +620,7 @@ aspect BackendBidirectionalAPI { sb.append(ind(1) + "}\n"); // Add - sb.append(ind(1) + "public void " + toTypeDecl() + ".add"); + sb.append(ind(1) + "public void " + getTypeUse().decl() + ".add"); if (!useJastAddNames) { sb.append("To"); } @@ -643,7 +643,7 @@ aspect BackendBidirectionalAPI { sb.append(ind(1) + "}\n"); // Insert / add at specific position - sb.append(ind(1) + "public void " + toTypeDecl() + ".add"); + sb.append(ind(1) + "public void " + getTypeUse().decl() + ".add"); if (!useJastAddNames) { sb.append("To"); } @@ -664,7 +664,7 @@ aspect BackendBidirectionalAPI { sb.append(ind(1) + "}\n"); // Remove - sb.append(ind(1) + "public void " + toTypeDecl() + ".remove"); + sb.append(ind(1) + "public void " + getTypeUse().decl() + ".remove"); if (!useJastAddNames) { sb.append("From"); } @@ -685,13 +685,13 @@ aspect BackendBidirectionalAPI { generateGetOne(sb); // Set - sb.append(ind(1) + "public " + toTypeDecl() + " " + toTypeDecl() + ".set" + nameCapitalized() + sb.append(ind(1) + "public " + getTypeUse().decl() + " " + getTypeUse().decl() + ".set" + nameCapitalized() + "(" + ofTypeDecl() + " o) {\n"); if (!isOpt) { sb.append(ind(2) + "assertNotNull(o);\n"); } sb.append(ind(2) + "if (" + getImplAttributeField() + " != null) {\n"); - sb.append(ind(3) + ASTNode.listClass + "<" + toTypeDecl() + "> list2 = " + getImplAttributeField() + sb.append(ind(3) + ASTNode.listClass + "<" + getTypeUse().decl() + "> list2 = " + getImplAttributeField() + "." + otherSide().getImplAttributeField() + ";\n"); sb.append(ind(3) + "list2.remove(this);\n"); sb.append(ind(3) + getImplAttributeField() + "." + "set" @@ -703,7 +703,7 @@ aspect BackendBidirectionalAPI { if (isOpt) { sb.append(ind(2) + "if (o != null) {\n"); } - sb.append(ind(ind) + ASTNode.listClass + "<" + toTypeDecl() + "> list = o." + sb.append(ind(ind) + ASTNode.listClass + "<" + getTypeUse().decl() + "> list = o." + otherSide().getImplAttributeField() + ";\n"); sb.append(ind(ind) + "if (list == null) {\n"); sb.append(ind(ind+1) + "list = new " + ASTNode.listClass + "<>();\n"); @@ -933,13 +933,13 @@ aspect NameResolutionHelper { public void ManyRelationComponent.generateContextDependentNameResolution(StringBuilder sb) { if (serializer && !resolverHelper) { - sb.append(ind(1) + ofTypeDecl() + " " + toTypeDecl() + ".resolve" + nameCapitalized() + "ByToken(String id, int position) {\n"); + sb.append(ind(1) + ofTypeDecl() + " " + getTypeUse().decl() + ".resolve" + nameCapitalized() + "ByToken(String id, int position) {\n"); sb.append(ind(2) + "return (" + ofTypeDecl() + ") globallyResolveASTNodeByUID(id);\n"); sb.append(ind(1) + "}\n"); } else { sb.append(ind(1) + "// context-dependent name resolution\n"); - sb.append(ind(1) + "uncache " + toTypeDecl() + ".resolve" + nameCapitalized() + "ByToken(String id, int position);\n"); - sb.append(ind(1) + "syn " + ofTypeDecl() + " " + toTypeDecl() + ".resolve" + nameCapitalized() + "ByToken(String id, int position) {\n"); + sb.append(ind(1) + "uncache " + getTypeUse().decl() + ".resolve" + nameCapitalized() + "ByToken(String id, int position);\n"); + sb.append(ind(1) + "syn " + ofTypeDecl() + " " + getTypeUse().decl() + ".resolve" + nameCapitalized() + "ByToken(String id, int position) {\n"); sb.append(ind(2) + "// default to context-independent name resolution\n"); sb.append(ind(2) + "return globallyResolve" + ofTypeDecl() + "ByToken(id);\n"); sb.append(ind(1) + "}\n"); @@ -948,13 +948,13 @@ aspect NameResolutionHelper { public void RelationComponent.generateDirectedContextDependentNameResolution(StringBuilder sb) { if (serializer && !resolverHelper) { - sb.append(ind(1) + ofTypeDecl() + " " + toTypeDecl() + ".resolve" + nameCapitalized() + "ByToken(String id) {\n"); + sb.append(ind(1) + ofTypeDecl() + " " + getTypeUse().decl() + ".resolve" + nameCapitalized() + "ByToken(String id) {\n"); sb.append(ind(2) + "return (" + ofTypeDecl() + ") globallyResolveASTNodeByUID(id);\n"); sb.append(ind(1) + "}\n"); } else { sb.append(ind(1) + "// context-dependent name resolution\n"); - sb.append(ind(1) + "uncache " + toTypeDecl() + ".resolve" + nameCapitalized() + "ByToken(String id);\n"); - sb.append(ind(1) + "syn " + ofTypeDecl() + " " + toTypeDecl() + ".resolve" + nameCapitalized() + "ByToken(String id) {\n"); + sb.append(ind(1) + "uncache " + getTypeUse().decl() + ".resolve" + nameCapitalized() + "ByToken(String id);\n"); + sb.append(ind(1) + "syn " + ofTypeDecl() + " " + getTypeUse().decl() + ".resolve" + nameCapitalized() + "ByToken(String id) {\n"); sb.append(ind(2) + "// default to context-independent name resolution\n"); sb.append(ind(2) + "return globallyResolve" + ofTypeDecl() + "ByToken(id);\n"); sb.append(ind(1) + "}\n"); diff --git a/src/main/jastadd/Errors.jrag b/src/main/jastadd/Errors.jrag index 9d9f75505aa01df342dd6b9e365c091b4a7ce6c7..b1ec073575e4ea6c15e924c1f6c6b95eeaba2cba 100644 --- a/src/main/jastadd/Errors.jrag +++ b/src/main/jastadd/Errors.jrag @@ -15,18 +15,25 @@ aspect Errors { when isAlreadyDeclared() to Program.errors(); - Component contributes error("Component '" + name() - + "' is already declared for type '" + toTypeDecl() + "'") + RelationComponent contributes error("Role '" + name() + + "' is already declared for type '" + getTypeUse().decl() + "'") when isAlreadyDeclared() to Program.errors(); - Component contributes error("Component '" + name() - + "' is an invalid redefition for type '" + toTypeDecl() + "'") + RelationComponent contributes error("Role '" + name() + + "' is an invalid redefinition for type '" + getTypeUse().decl() + "', conflicts with supertype '" + + invalidRedefinition().enclosingTypeDecl() + "'") + when isInvalidRedefinition() + to Program.errors(); + + TokenComponent contributes error("Token '" + name() + + "' is an invalid redefinition for type '" + enclosingTypeDecl() + "', conflicts with supertype '" + + invalidRedefinition().enclosingTypeDecl() + "'") when isInvalidRedefinition() to Program.errors(); RelationComponent contributes - error("Role name missing for type '" + toTypeDecl() + "'") + error("Role name missing for type '" + getTypeUse().decl() + "'") when !isTargetOfDirectedRelation() && name().isEmpty() to Program.errors(); diff --git a/src/main/jastadd/RelAst.parser b/src/main/jastadd/RelAst.parser index 303dcb6dd727df10b4037d110e234213fdc90b36..6b138b97d35b76583a3226b376613b8316a95a36 100644 --- a/src/main/jastadd/RelAst.parser +++ b/src/main/jastadd/RelAst.parser @@ -86,9 +86,15 @@ Relation relation = RELATION relation_comp.l direction relation_comp.r SCOL {: Relation result = new Relation(); - result.setLeft(l); - result.setDirection(direction); - result.setRight(r); + if (direction instanceof LeftDirection) { + result.setLeft(r); + result.setDirection(new RightDirection()); + result.setRight(l); + } else { + result.setLeft(l); + result.setDirection(direction); + result.setRight(r); + } return result; :} ; diff --git a/src/test/jastadd/errors/Errors.expected b/src/test/jastadd/errors/Errors.expected index 01049a4a3ae266a25ed024698f93ad49b129aab2..be149e0fda289a2a4d5203d5bb6317b0a0a73434 100644 --- a/src/test/jastadd/errors/Errors.expected +++ b/src/test/jastadd/errors/Errors.expected @@ -3,3 +3,4 @@ $FILENAME Line 5, column 5: Role name missing for type 'A' $FILENAME Line 6, column 15: Role name missing for type 'B' $FILENAME Line 7, column 12: The target of a directed relation cannot have a role name $FILENAME Line 8, column 13: The target of a directed relation may only have multiplicity 1 +$FILENAME Line 9, column 5: Role 'b2' is already declared for type 'A' diff --git a/src/test/jastadd/errors/Errors.relast b/src/test/jastadd/errors/Errors.relast index c5bfd75f87b2ff697a558f0491211025d23e4ddc..1d63f5705ecc09ac2e431dbbfbb26a850a466825 100644 --- a/src/test/jastadd/errors/Errors.relast +++ b/src/test/jastadd/errors/Errors.relast @@ -6,3 +6,4 @@ rel A -> B; rel A.bs* <-> B*; rel A.b -> B.b; rel A.b2 -> B*; +rel A.b2 -> A; diff --git a/src/test/jastadd/errors/ErrorsLeft.expected b/src/test/jastadd/errors/ErrorsLeft.expected index 155d0ec5110a4f6156e71033e92137a6aebb0492..191db3e226f8e5cb2cf64059954fdeee57f2d94b 100644 --- a/src/test/jastadd/errors/ErrorsLeft.expected +++ b/src/test/jastadd/errors/ErrorsLeft.expected @@ -3,3 +3,4 @@ $FILENAME Line 5, column 10: Role name missing for type 'A' $FILENAME Line 6, column 15: Role name missing for type 'B' $FILENAME Line 7, column 5: The target of a directed relation cannot have a role name $FILENAME Line 8, column 5: The target of a directed relation may only have multiplicity 1 +$FILENAME Line 9, column 10: Role 'b2' is already declared for type 'A' diff --git a/src/test/jastadd/errors/ErrorsLeft.relast b/src/test/jastadd/errors/ErrorsLeft.relast index e381449c06b7f0223b36b8b0936f417c5811bb7b..5c4c35abe374c258b732989d9ef7dfacca051ce9 100644 --- a/src/test/jastadd/errors/ErrorsLeft.relast +++ b/src/test/jastadd/errors/ErrorsLeft.relast @@ -6,3 +6,4 @@ rel B <- A; rel A.bs* <-> B*; rel B.b <- A.b; rel B* <- A.b2; +rel A <- A.b2; diff --git a/src/test/jastadd/errors/Inheritance.expected b/src/test/jastadd/errors/Inheritance.expected index 717389a4052a506dbe52c3734c9880b7f5c709fe..b3382e004ae6e15ca9bbd1ed6695ece0e3110fbe 100644 --- a/src/test/jastadd/errors/Inheritance.expected +++ b/src/test/jastadd/errors/Inheritance.expected @@ -1,3 +1,3 @@ Errors: -$FILENAME Line 4, column 12: Component 'X' is an invalid redefition for type 'B3' -$FILENAME Line 7, column 5: Component 'X' is an invalid redefition for type 'B2' +$FILENAME Line 4, column 12: Token 'X' is an invalid redefinition for type 'B3', conflicts with supertype 'A' +$FILENAME Line 7, column 5: Role 'X' is an invalid redefinition for type 'B2', conflicts with supertype 'A' diff --git a/src/test/jastadd/errors/InheritanceLeft.expected b/src/test/jastadd/errors/InheritanceLeft.expected index 2cb8024867b5c38771a337330d2e87a8035be653..a897e473946be908e3cac5f6b6d59628720d3376 100644 --- a/src/test/jastadd/errors/InheritanceLeft.expected +++ b/src/test/jastadd/errors/InheritanceLeft.expected @@ -1,3 +1,3 @@ Errors: -$FILENAME Line 4, column 12: Component 'X' is an invalid redefition for type 'B3' -$FILENAME Line 7, column 10: Component 'X' is an invalid redefition for type 'B2' +$FILENAME Line 4, column 12: Token 'X' is an invalid redefinition for type 'B3', conflicts with supertype 'A' +$FILENAME Line 7, column 10: Role 'X' is an invalid redefinition for type 'B2', conflicts with supertype 'A'