From b8709e5afc7e4e66989c815bf5ea958bf800e152 Mon Sep 17 00:00:00 2001
From: Johannes Mey <johannes.mey@tu-dresden.de>
Date: Mon, 11 Mar 2019 09:17:19 +0100
Subject: [PATCH] fix name resolution for serializer

---
 .gitignore                                    |  1 +
 build.gradle                                  |  5 ++-
 src/main/jastadd/Backend.jadd                 | 40 +++++++++++++++----
 .../org/jastadd/relast/compiler/Compiler.java |  2 +-
 4 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/.gitignore b/.gitignore
index d84ffee..febce23 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,3 +28,4 @@ src/test/jastadd/serializer/Serializer.ast
 src/test/jastadd/serializer/Serializer.jadd
 src/test/jastadd/serializer/SerializerSerializer.jadd
 src/test/jastadd/serializer/SerializerRefResolver.jadd
+src/test/jastadd/serializer/SerializerResolverStubs.jrag
diff --git a/build.gradle b/build.gradle
index be8ffde..020c175 100644
--- a/build.gradle
+++ b/build.gradle
@@ -294,7 +294,9 @@ task preprocessSerializerTest(type: JavaExec, group: 'verification') {
         delete 'src/test/jastadd/serializer/Serializer.ast',
                 'src/test/jastadd/serializer/Serializer.jadd',
                 'src/test/jastadd/serializer/SerializerRefResolver.jadd',
-                'src/test/jastadd/serializer/SerializerSerializer.jadd'
+                'src/test/jastadd/serializer/SerializerSerializer.jadd',
+                'src/test/jastadd/serializer/SerializerRefResolver.jadd',
+                'src/test/jastadd/serializer/SerializerResolverStubs.jrag'
     }
 
     classpath = sourceSets.main.runtimeClasspath
@@ -317,6 +319,7 @@ task compileSerializerTest(type: JavaExec, group: 'verification') {
             'src/test/jastadd/serializer/Serializer.jadd',
             'src/test/jastadd/serializer/SerializerRefResolver.jadd',
             'src/test/jastadd/serializer/SerializerSerializer.jadd',
+            'src/test/jastadd/serializer/SerializerResolverStubs.jrag',
             'src/test/jastadd/Utils.jadd'
 }
 
diff --git a/src/main/jastadd/Backend.jadd b/src/main/jastadd/Backend.jadd
index c33893c..9b0fce8 100644
--- a/src/main/jastadd/Backend.jadd
+++ b/src/main/jastadd/Backend.jadd
@@ -200,7 +200,7 @@ aspect BackendDirectedAPI {
     sb.append(".get" + nameCapitalized() + "List() {\n");
     sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> l = get" + getImplAttributeName() + "();\n");
     // resolve the entire list
-    if (resolverHelper) {
+    if (resolverHelper | serializer) {
       sb.append(ind(2) + "if (l != null) {\n");
         sb.append(ind(3) + "boolean changed = false;\n");
         sb.append(ind(3) + "for (int i = 0; i < l.size(); i++) {\n");
@@ -256,7 +256,7 @@ aspect BackendDirectedAPI {
   public void RelationComponent.generateGetOne(StringBuilder sb) {
     sb.append(ind(1) + "public " + ofTypeDecl() + " " + toTypeDecl());
     sb.append(".get" + nameCapitalized() + "() {\n");
-    if (resolverHelper) {
+    if (resolverHelper | serializer) {
       sb.append(ind(2) + "if (get" + getImplAttributeName() + "() != null && get" + getImplAttributeName() + "().unresolved()) {\n");
         sb.append(ind(3) + "if (get" + getImplAttributeName() + "().asUnresolved().get__resolve_opposite()) {\n");
           sb.append(ind(4) + "set" + nameCapitalized() + "(resolve" + nameCapitalized() + "ByToken(get" + getImplAttributeName() + "().asUnresolved().get__token()));\n");
@@ -339,7 +339,7 @@ aspect BackendBidirectionalAPI {
     sb.append(ind(2) + "if (get" + getImplAttributeName() + "() != null) {\n");
     sb.append(ind(3) + "get" + getImplAttributeName() + "().set" + otherSide().getImplAttributeName() + "(null);\n");
     sb.append(ind(2) + "}\n");
-    if (resolverHelper) {
+    if (resolverHelper | serializer) {
       sb.append(ind(2) + "if (!o.unresolved() && o != null && o.get" + otherSide().getImplAttributeName() + "() != null) {\n");
     } else {
       sb.append(ind(2) + "if (o != null && o.get" + otherSide().getImplAttributeName() + "() != null) {\n");
@@ -347,7 +347,7 @@ aspect BackendBidirectionalAPI {
     sb.append(ind(3) + "o.get" + otherSide().getImplAttributeName() + "().set" + getImplAttributeName() + "(null);\n");
     sb.append(ind(2) + "}\n");
     sb.append(ind(2) + "set" + getImplAttributeName() + "(o);\n");
-    if (resolverHelper) {
+    if (resolverHelper | serializer) {
       sb.append(ind(2) + "if (!o.unresolved()) {\n");
       if (isOpt) {
         sb.append(ind(3) + "if (o != null) {\n");
@@ -388,7 +388,7 @@ aspect BackendBidirectionalAPI {
     sb.append(".get" + nameCapitalized() + "List() {\n");
     sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> l = get" + getImplAttributeName() + "();\n");
     // resolve the entire list
-    if (resolverHelper) {
+    if (resolverHelper | serializer) {
       sb.append(ind(2) + "if (l != null) {\n");
         sb.append(ind(3) + "boolean changed = false;\n");
         sb.append(ind(3) + "for (int i = 0; i < l.size(); i++) {\n");
@@ -481,7 +481,7 @@ aspect BackendBidirectionalAPI {
     sb.append(".get" + nameCapitalized() + "List() {\n");
     sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> l = get" + getImplAttributeName() + "();\n");
     // resolve the entire list
-    if (resolverHelper) {
+    if (resolverHelper | serializer) {
       sb.append(ind(2) + "if (l != null) {\n");
         sb.append(ind(3) + "boolean changed = false;\n");
         sb.append(ind(3) + "for (int i = 0; i < l.size(); i++) {\n");
@@ -801,8 +801,12 @@ aspect NameResolutionHelper {
 
     sb.append(ind(1) + "// context-independent name resolution\n");
     sb.append(ind(1) + "syn " + superType + " ASTNode.globallyResolve" + superType + "ByToken(String id) {\n");
+    if (serializer) {
+      sb.append(ind(2) + "return (" + superType + ") globallyResolveASTNodeByUID(id);\n");
+    } 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 "+ superType + " not implemented.\");\n");
+      sb.append(ind(2) + "throw new RuntimeException(\"Context-independent name resolution for " + superType + " not implemented.\");\n");
+    }
     sb.append(ind(1) + "}\n");
   }
 
@@ -1236,6 +1240,28 @@ aspect Serializer {
     sb.append(ind(1) + "protected String ASTNode.serializationID() {\n");
     sb.append(ind(2) + "return null;\n");
     sb.append(ind(1) + "}\n");
+
+    sb.append(ind(1) + "syn ASTNode ASTNode.globallyResolveASTNodeByUID(String uid) {\n");
+    sb.append(ind(2) + "if (getParent() == null) {\n");
+    sb.append(ind(3) + "return __uidMap().get(uid);\n");
+    sb.append(ind(2) + "} else {\n");
+    sb.append(ind(3) + "return getParent().globallyResolveASTNodeByUID(uid);\n");
+    sb.append(ind(2) + "}\n");
+    sb.append(ind(1) + "}\n");
+
+    sb.append(ind(1) + "syn java.util.Map<String, ASTNode> ASTNode.__uidMap() {\n");
+    sb.append(ind(2) + "return(__uidMap(new java.util.HashMap()));\n");
+    sb.append(ind(1) + "}\n");
+
+    sb.append(ind(1) + "protected java.util.Map<String, ASTNode> ASTNode.__uidMap(java.util.Map<String, ASTNode> map) {\n");
+    sb.append(ind(2) + "map.put(this.__uid, this);\n");
+    sb.append(ind(2) + "for (ASTNode child : astChildren()) {\n");
+    sb.append(ind(3) + "child.__uidMap(map);\n");
+    sb.append(ind(2) + "}\n");
+    sb.append(ind(2) + "return map;\n");
+    sb.append(ind(1) + "}\n");
+
+
     sb.append("}\n");
   }
 
diff --git a/src/main/java/org/jastadd/relast/compiler/Compiler.java b/src/main/java/org/jastadd/relast/compiler/Compiler.java
index 9c6c23b..533b30d 100644
--- a/src/main/java/org/jastadd/relast/compiler/Compiler.java
+++ b/src/main/java/org/jastadd/relast/compiler/Compiler.java
@@ -96,7 +96,7 @@ public class Compiler {
           }
         }
 
-        if (optionResolverHelper.isSet()) {
+        if (optionResolverHelper.isSet() || optionSerializer.isSet()) {
           ASTNode.resolverHelper = true;
           writeToFile(grammarName + "ResolverStubs.jrag", p.generateResolverStubs());
         }
-- 
GitLab