From d6c9f0ce66fa9c90303f9b53fcdfa721803e7283 Mon Sep 17 00:00:00 2001
From: Johannes Mey <johannes.mey@tu-dresden.de>
Date: Wed, 9 Oct 2019 11:47:37 +0200
Subject: [PATCH] reordering of components is allowed

---
 src/main/jastadd/Analysis.jrag                | 36 +++++++++++++++----
 src/main/jastadd/Errors.jrag                  |  5 +++
 src/test/jastadd/errors/Inheritance.expected  |  4 +--
 src/test/jastadd/errors/Inheritance.relast    |  1 +
 .../jastadd/errors/InheritanceLeft.expected   |  4 +--
 .../jastadd/errors/InheritanceLeft.relast     |  1 +
 6 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/src/main/jastadd/Analysis.jrag b/src/main/jastadd/Analysis.jrag
index 8959b7b..0524c61 100644
--- a/src/main/jastadd/Analysis.jrag
+++ b/src/main/jastadd/Analysis.jrag
@@ -62,12 +62,6 @@ aspect ComponentAnalysis {
   eq Program.getChild().lookupComponent(TypeDecl td, String name)
     = lookupComponentSyn(td, name);
   syn Component Program.lookupComponentSyn(TypeDecl td, String name) {
-    // Check super type first to find duplicates (shadowing is not allowed)
-    if (td.hasSuper() && td.getSuper().decl() != null) {
-      Component c = lookupComponentSyn(td.getSuper().decl(), name);
-      if (c != null) return c;
-    }
-
     for (Component c: td.getComponents()) {
       if (c.name().equals(name)) {
         return c;
@@ -84,6 +78,36 @@ aspect ComponentAnalysis {
     return null;
   }
 
+  syn boolean Component.isInvalidRedefinition() {
+    if (toTypeDecl() == null) return false;
+
+    TypeDecl td = toTypeDecl();
+
+    while (td.hasSuper() && td.getSuper().decl() != null) {
+      td = td.getSuper().decl();
+      Component c = lookupComponent(td, getID());
+      if (c != null && isTargetOfDirectedRelation()) return true;
+
+      if (c != null && !this.isEqual(c)) return true;
+    }
+    return false;
+  }
+
+  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;
+  }
+
   syn RelationComponent RelationComponent.lookup(TypeDecl td, String name)
     = !isTargetOfDirectedRelation() && toTypeDecl() == td && name().equals(name)
     ? this
diff --git a/src/main/jastadd/Errors.jrag b/src/main/jastadd/Errors.jrag
index 39a1bfd..9d9f755 100644
--- a/src/main/jastadd/Errors.jrag
+++ b/src/main/jastadd/Errors.jrag
@@ -20,6 +20,11 @@ aspect Errors {
     when isAlreadyDeclared()
     to Program.errors();
 
+  Component contributes error("Component '" + name()
+    + "' is an invalid redefition for type '" + toTypeDecl() + "'")
+    when isInvalidRedefinition()
+    to Program.errors();
+
   RelationComponent contributes
     error("Role name missing for type '" + toTypeDecl() + "'")
     when !isTargetOfDirectedRelation() && name().isEmpty()
diff --git a/src/test/jastadd/errors/Inheritance.expected b/src/test/jastadd/errors/Inheritance.expected
index 048fc97..717389a 100644
--- a/src/test/jastadd/errors/Inheritance.expected
+++ b/src/test/jastadd/errors/Inheritance.expected
@@ -1,3 +1,3 @@
 Errors:
-$FILENAME Line 2, column 12: Component 'X' is already declared for type 'B1'
-$FILENAME Line 6, column 5: Component 'X' is already declared for type 'B2'
+$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'
diff --git a/src/test/jastadd/errors/Inheritance.relast b/src/test/jastadd/errors/Inheritance.relast
index 9f012a9..db746eb 100644
--- a/src/test/jastadd/errors/Inheritance.relast
+++ b/src/test/jastadd/errors/Inheritance.relast
@@ -1,6 +1,7 @@
 A ::= X;
 B1 : A ::= X;
 B2 : A;
+B3 : A ::= <X:String>;
 X;
 
 rel B2.X -> X;
diff --git a/src/test/jastadd/errors/InheritanceLeft.expected b/src/test/jastadd/errors/InheritanceLeft.expected
index ef568b5..2cb8024 100644
--- a/src/test/jastadd/errors/InheritanceLeft.expected
+++ b/src/test/jastadd/errors/InheritanceLeft.expected
@@ -1,3 +1,3 @@
 Errors:
-$FILENAME Line 2, column 12: Component 'X' is already declared for type 'B1'
-$FILENAME Line 6, column 10: Component 'X' is already declared for type 'B2'
+$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'
diff --git a/src/test/jastadd/errors/InheritanceLeft.relast b/src/test/jastadd/errors/InheritanceLeft.relast
index a63c266..710cc86 100644
--- a/src/test/jastadd/errors/InheritanceLeft.relast
+++ b/src/test/jastadd/errors/InheritanceLeft.relast
@@ -1,6 +1,7 @@
 A ::= X;
 B1 : A ::= X;
 B2 : A;
+B3 : A ::= <X:String>;
 X;
 
 rel X <- B2.X;
-- 
GitLab