From 3d74e0ce14ec685e32b3712496c1b8bbad30fd2c Mon Sep 17 00:00:00 2001
From: Sven Gestegard Robertz <sven.robertz@cs.lth.se>
Date: Fri, 23 Jan 2015 16:16:43 +0100
Subject: [PATCH] reimplemented hierarchical typedefs in Java

---
 compiler/2014/Java_CodeGen.jrag               | 44 +++++----
 lib/java/se/lth/control/labcomm/Encoder.java  |  7 +-
 .../lth/control/labcomm/EncoderChannel.java   | 95 ++++++++++++-------
 .../lth/control/labcomm/EncoderRegistry.java  | 10 +-
 lib/java/se/lth/control/labcomm/Sample.java   |  2 +-
 .../lth/control/labcomm/SampleDispatcher.java |  8 +-
 6 files changed, 108 insertions(+), 58 deletions(-)

diff --git a/compiler/2014/Java_CodeGen.jrag b/compiler/2014/Java_CodeGen.jrag
index 478a0ac..c17cdb2 100644
--- a/compiler/2014/Java_CodeGen.jrag
+++ b/compiler/2014/Java_CodeGen.jrag
@@ -454,10 +454,10 @@ aspect Java_Class {
     env.println();
   }
 
-  //public void TypeDecl.Java_emitSignature(Java_env env) {
-  //  Signature signature = getSignature();
-  //  signature.Java_emitSignature(env, true);
-  //}
+  public void TypeDecl.Java_emitSignature(Java_env env) {
+    Signature signature = getSignature();
+    signature.Java_emitSignature(env, true);
+  }
 
   public void Decl.Java_emitSignature(Java_env env) {
     //always emit the flat signature, as it is needed
@@ -465,10 +465,10 @@ aspect Java_Class {
     //the type_ids of dependent types. Therefore, flat sigs
     //are used for matching
     Java_emitFlatSignature(env);
-    //if(isReferenced() || isSampleDecl()){
-    //  Signature signature = getSignature();
-    //  signature.Java_emitSignature(env, !isSampleDecl());
-    //}
+    if(isReferenced() || isSampleDecl()){
+      Signature signature = getSignature();
+      signature.Java_emitSignature(env, !isSampleDecl());
+    }
   }
 
   public void Decl.Java_emitFlatSignature(Java_env env){
@@ -497,7 +497,8 @@ aspect Java_Class {
 
   //XXX TODO: refactor: split into a static class ("TypeDefSingleton"?)and a (smaller) dispatcher
   public void Decl.Java_emitDispatcher(Java_env env, boolean isSample) {
-    String genericStr = ""; //env.versionHasMetaData()?"<"+getName()+">":""; 
+    // String genericStr = ""; //env.versionHasMetaData()?"<"+getName()+">":""; 
+    String genericStr = "<"+getName()+">"; 
     env.println("private static Dispatcher dispatcher = new Dispatcher();");
     env.println();
     env.println("public SampleDispatcher getDispatcher() {");
@@ -553,7 +554,11 @@ aspect Java_Class {
     env.println("/** return the flat signature. */");
     env.println("public byte[] getSignature() {");
     env.indent();
-    env.println("return signature;");
+    if(isSample) {
+        env.println("return signature;");
+    } else {
+        env.println("throw new Error(\"a TYPE_DEF has no flat signature\");");
+    }
     env.unindent();
     env.println("}");
     env.println();
@@ -563,15 +568,16 @@ aspect Java_Class {
 //    env.unindent();
 //    env.println("}");
 //    env.println();
-//    env.println("public void encodeSignatureMetadata(Encoder e, int index) throws IOException{");
-//    env.indent();
-//    env.println("e.encodePacked32(Constant.TYPE_DEF);");
-//    env.println("e.encodePacked32(index);");
-//    env.println("e.encodeString(getName());");
-//    env.println("emitSignature(e);");
-//    env.unindent();
-//    env.println("}");
-//    env.println();
+    env.println("public void encodeTypeDef(Encoder e, int index) throws IOException{");
+    env.indent();
+    env.println("e.begin(Constant.TYPE_DEF);");
+    env.println("e.encodePacked32(index);");
+    env.println("e.encodeString(getName());");
+    env.println("emitSignature(e);");
+    env.println("e.end(null);");
+    env.unindent();
+    env.println("}");
+    env.println();
     env.println("public boolean canDecodeAndHandle() {");
     env.indent();
     env.println("return "+isSample+";");
diff --git a/lib/java/se/lth/control/labcomm/Encoder.java b/lib/java/se/lth/control/labcomm/Encoder.java
index 203366e..4190115 100644
--- a/lib/java/se/lth/control/labcomm/Encoder.java
+++ b/lib/java/se/lth/control/labcomm/Encoder.java
@@ -6,8 +6,11 @@ public interface Encoder {
 
   public void register(SampleDispatcher dispatcher) throws IOException;
   public void registerSampleRef(SampleDispatcher dispatcher) throws IOException;
-  public void begin(Class<? extends Sample> c) throws IOException;
-  public void end(Class<? extends Sample> c) throws IOException;
+  public void begin(Class<? extends SampleType> c) throws IOException;
+  public void end(Class<? extends SampleType> c) throws IOException;
+
+  public void begin(int t) throws IOException;
+  public int getTypeId(Class<? extends SampleType> c) throws IOException;
 
   public void encodeBoolean(boolean value) throws IOException;
   public void encodeByte(byte value) throws IOException;
diff --git a/lib/java/se/lth/control/labcomm/EncoderChannel.java b/lib/java/se/lth/control/labcomm/EncoderChannel.java
index 01330fe..0872414 100644
--- a/lib/java/se/lth/control/labcomm/EncoderChannel.java
+++ b/lib/java/se/lth/control/labcomm/EncoderChannel.java
@@ -10,9 +10,10 @@ public class EncoderChannel implements Encoder {
   private Writer writer;
   private ByteArrayOutputStream bytes = new ByteArrayOutputStream();
   private DataOutputStream data = new DataOutputStream(bytes);
-  private EncoderRegistry def_registry = new EncoderRegistry();
-  private EncoderRegistry ref_registry = new EncoderRegistry();
-  private int current_tag; 
+  private EncoderRegistry sample_def_registry = new EncoderRegistry();
+  private EncoderRegistry sample_ref_registry = new EncoderRegistry();
+  private EncoderRegistry type_def_registry = new EncoderRegistry();
+  private int current_tag;
 
   public EncoderChannel(Writer writer) throws IOException {
     this.writer = writer;
@@ -26,42 +27,63 @@ public class EncoderChannel implements Encoder {
     this(new WriterWrapper(writer));
   }
 
-  public void register(SampleDispatcher dispatcher) throws IOException {
-    switch (dispatcher.getTypeDeclTag())  {
-        case Constant.SAMPLE_DEF: {
-            int index = def_registry.add(dispatcher);
+  private void bindType(int sampleId, int typeId) throws IOException {
+        begin(Constant.TYPE_BINDING);
+        encodePacked32(sampleId);
+        encodePacked32(typeId);
+        end(null);
+  }
+
+  private void registerSample(SampleDispatcher dispatcher) throws IOException {
+        int index = sample_def_registry.add(dispatcher);
+        begin(dispatcher.getTypeDeclTag());
+        encodePacked32(index);
+        encodeString(dispatcher.getName());
+        byte[] signature = dispatcher.getSignature();
+        encodePacked32(signature.length);
+        for (int i = 0 ; i < signature.length ; i++) {
+            encodeByte(signature[i]);
+        }
+        end(null);
+        int tindex = registerTypeDef(dispatcher);
+        bindType(index, tindex);
+
+  }
+
+  private int registerTypeDef(SampleDispatcher dispatcher) throws IOException {
+      //XXX A bit crude; maybe add boolean registry.contains(...) and check
+      //    if already registered
+        try {
+            return type_def_registry.getTag(dispatcher);
+        } catch (IOException e) {
+            int index = type_def_registry.add(dispatcher);
             begin(dispatcher.getTypeDeclTag());
             encodePacked32(index);
             encodeString(dispatcher.getName());
-            byte[] signature = dispatcher.getSignature();
-            encodePacked32(signature.length);
-            for (int i = 0 ; i < signature.length ; i++) {
-                encodeByte(signature[i]);
-            }
+            dispatcher.encodeTypeDef(this, index);
             end(null);
+            return index;
+        }
+  }
+
+  public void register(SampleDispatcher dispatcher) throws IOException {
+    switch (dispatcher.getTypeDeclTag())  {
+        case Constant.SAMPLE_DEF: {
+            registerSample(dispatcher);
             break;
         }
         case Constant.TYPE_DEF: {
-            int index = def_registry.add(dispatcher);
-            begin(dispatcher.getTypeDeclTag());
-            encodePacked32(index);
-            encodeString(dispatcher.getName());
-            byte[] signature = dispatcher.getSignature();
-            encodePacked32(8);
-            for (int i = 0 ; i < 8; i++) {
-                encodeByte((byte) 0xff);
-            }
-            end(null);
+            registerTypeDef(dispatcher);
             break;
         }
         default:
-            throw new Error("Unknown typeDeclTag: "+dispatcher.getTypeDeclTag());    
-    } 
+            throw new Error("Unknown typeDeclTag: "+dispatcher.getTypeDeclTag());
+    }
   }
 
   public void registerSampleRef(SampleDispatcher dispatcher) throws IOException {
     System.err.println(dispatcher);
-    int index = ref_registry.add(dispatcher);
+    int index = sample_ref_registry.add(dispatcher);
     begin(Constant.SAMPLE_REF);
     encodePacked32(index);
     encodeString(dispatcher.getName());
@@ -73,16 +95,16 @@ public class EncoderChannel implements Encoder {
     end(null);
   }
 
-  private void begin(int tag) {
+  public void begin(int tag) {
     current_tag = tag;
     bytes.reset();
   }
 
-  public void begin(Class<? extends Sample> c) throws IOException {
-    begin(def_registry.getTag(c));
+  public void begin(Class<? extends SampleType> c) throws IOException {
+    begin(sample_def_registry.getTag(c));
   }
 
-  public void end(Class<? extends Sample> c) throws IOException {
+  public void end(Class<? extends SampleType> c) throws IOException {
     data.flush();
     WritePacked32(writer, current_tag);
     WritePacked32(writer, bytes.size());
@@ -90,19 +112,26 @@ public class EncoderChannel implements Encoder {
     bytes.reset();
   }
 
+  /** 
+   * @return the id of a TYPE_DEF 
+   */
+  public int getTypeId(Class<? extends SampleType> c) throws IOException {
+    return type_def_registry.getTag(c);
+  }
+
   private void WritePacked32(Writer s, long value) throws IOException {
     byte[] tmp1 = new byte[5];
     byte[] tmp2 = new byte[1];
     long v = value & 0xffffffff;
     int i;
-    
+
     for (i = 0 ; i == 0 || v != 0 ; i++, v = (v >> 7)) {
       tmp1[i] = (byte)(v & 0x7f | (i!=0?0x80:0x00));
     }
     for (i = i - 1 ; i >= 0 ; i--) {
       tmp2[0] = tmp1[i];
       writer.write(tmp2);
-    }      
+    }
   }
 
   public void encodeBoolean(boolean value) throws IOException{
@@ -144,7 +173,7 @@ public class EncoderChannel implements Encoder {
     tmps.writeUTF(value);
     tmps.flush();
     byte[] tmp = tmpb.toByteArray();
-  
+
     encodePacked32(tmp.length-2);
     for (int i = 2 ; i < tmp.length ; i++) {
       encodeByte(tmp[i]);
@@ -167,7 +196,7 @@ public class EncoderChannel implements Encoder {
   public void encodeSampleRef(Class value) throws IOException {
     int index = 0;
     try {
-      index = ref_registry.getTag(value);
+      index = sample_ref_registry.getTag(value);
     } catch (NullPointerException e) {
     }
     data.writeInt(index);
diff --git a/lib/java/se/lth/control/labcomm/EncoderRegistry.java b/lib/java/se/lth/control/labcomm/EncoderRegistry.java
index cd0cf72..f990d18 100644
--- a/lib/java/se/lth/control/labcomm/EncoderRegistry.java
+++ b/lib/java/se/lth/control/labcomm/EncoderRegistry.java
@@ -42,7 +42,11 @@ public class EncoderRegistry {
     return e.getIndex();
   }
   
-  public int getTag(Class<? extends Sample> sample) throws IOException {
+  public int getTag(SampleDispatcher d) throws IOException {
+      return getTag(d.getSampleClass());
+  }
+
+  public int getTag(Class<? extends SampleType> sample) throws IOException {
     Entry e = byClass.get(sample);
     if (e == null) {
       throw new IOException("'" + 
@@ -52,4 +56,8 @@ public class EncoderRegistry {
     return e.index;
   }
 
+  public boolean contains(Class<? extends SampleType> sample) {
+    return byClass.containsKey(sample);
+  }
+
 }
diff --git a/lib/java/se/lth/control/labcomm/Sample.java b/lib/java/se/lth/control/labcomm/Sample.java
index f86f486..2dd432b 100644
--- a/lib/java/se/lth/control/labcomm/Sample.java
+++ b/lib/java/se/lth/control/labcomm/Sample.java
@@ -1,6 +1,6 @@
 package se.lth.control.labcomm;
 
-public interface Sample {
+public interface Sample extends SampleType {
 
   public SampleDispatcher getDispatcher();
 
diff --git a/lib/java/se/lth/control/labcomm/SampleDispatcher.java b/lib/java/se/lth/control/labcomm/SampleDispatcher.java
index 58e3d1d..aeef84e 100644
--- a/lib/java/se/lth/control/labcomm/SampleDispatcher.java
+++ b/lib/java/se/lth/control/labcomm/SampleDispatcher.java
@@ -1,8 +1,10 @@
 package se.lth.control.labcomm;
 
-public interface SampleDispatcher {
+import java.io.IOException;
+
+public interface SampleDispatcher <T extends SampleType>{
     
-  public Class getSampleClass();
+  public Class<T> getSampleClass();
     
   public String getName();
 
@@ -11,6 +13,8 @@ public interface SampleDispatcher {
   public void decodeAndHandle(Decoder decoder,
 			      SampleHandler handler) throws Exception;
 
+  public void encodeTypeDef(Encoder e, int index) throws IOException;
+
   /** return the tag SAMPLE_DEF or TYPE_DEF, for use
    *  by encoder.register.
    *  TODO: refactor types, moving this to a super-interface
-- 
GitLab