From 0a5c322f2081b25c5aa4368dd25c4fdb18f41ac9 Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Tue, 18 Nov 2014 17:19:41 +0100
Subject: [PATCH] C# sample references implemented.

---
 compiler/CS_CodeGen.jrag                      | 39 +++++++++++--------
 compiler/Java_CodeGen.jrag                    | 17 ++++----
 lib/csharp/se/lth/control/labcomm/Constant.cs |  5 ++-
 lib/csharp/se/lth/control/labcomm/Decoder.cs  |  3 +-
 .../se/lth/control/labcomm/DecoderChannel.cs  | 31 ++++++++++++---
 lib/csharp/se/lth/control/labcomm/Encoder.cs  |  3 +-
 .../se/lth/control/labcomm/EncoderChannel.cs  | 30 +++++++++++---
 lib/csharp/se/lth/control/labcomm/Sample.cs   |  8 +++-
 lib/java/se/lth/control/labcomm/Encoder.java  |  1 +
 .../lth/control/labcomm/EncoderChannel.java   |  3 ++
 lib/java/se/lth/control/labcomm/Sample.java   |  4 +-
 lib/python/labcomm/LabComm.py                 | 14 ++++++-
 test/ref.lc                                   |  6 +--
 test/relay_gen_cs.py                          | 22 ++++++++---
 14 files changed, 133 insertions(+), 53 deletions(-)

diff --git a/compiler/CS_CodeGen.jrag b/compiler/CS_CodeGen.jrag
index adcb0c6..e1da497 100644
--- a/compiler/CS_CodeGen.jrag
+++ b/compiler/CS_CodeGen.jrag
@@ -302,15 +302,27 @@ aspect CS_Class {
   public void Decl.CS_emitRegisterEncoder(CS_env env) {
     env.println("public static void register(Encoder e){");
     env.indent();
-    env.println("e.register(Dispatcher.singleton());");
+    env.println("e.register(dispatcher);");
     env.unindent();
     env.println("}");
+    env.println("public static void registerSampleRef(Encoder e) {");
+    env.indent();
+    env.println("e.registerSampleRef(dispatcher);");
+    env.unindent();
+    env.println("}");
+    env.println();
   }
   
   public void Decl.CS_emitRegisterDecoder(CS_env env) {
     env.println("public static void register(Decoder d, Handler h) {");
     env.indent();
-    env.println("d.register(Dispatcher.singleton(), h);");
+    env.println("d.register(dispatcher, h);");
+    env.unindent();
+    env.println("}");
+    env.println();
+    env.println("public static void registerSampleRef(Decoder d) {");
+    env.indent();
+    env.println("d.registerSampleRef(dispatcher);");
     env.unindent();
     env.println("}");
     env.println();
@@ -402,22 +414,17 @@ aspect CS_Class {
   //XXX TODO: refactor: split into a static class ("TypeDefSingleton"?)and a (smaller) dispatcher
   public void Decl.CS_emitDispatcher(CS_env env, boolean isSample) {
     String genericStr = ""; //env.versionHasMetaData()?"<"+getName()+">":""; 
-    env.println("private class Dispatcher : SampleDispatcher{");
-    env.indent();
-    env.println();
-    env.println("private static Dispatcher single;");
+    env.println("private static Dispatcher dispatcher = new Dispatcher();");
     env.println();
-    env.println("public static Dispatcher singleton() {");
+    env.println("public SampleDispatcher getDispatcher() {");
     env.indent();
-    env.println("lock(typeof(Dispatcher)) {");
-    env.indent();
-    env.println("if( single == null ) single = new Dispatcher();");
-    env.println("return single;");
-    env.unindent();
-    env.println("}");
+    env.println("return dispatcher;");
     env.unindent();
     env.println("}");
     env.println();
+    env.println("private class Dispatcher : SampleDispatcher{");
+    env.indent();
+    env.println();
     env.println("public Type getSampleClass() {");
     env.indent();
     env.println("return typeof(" + getName() + ");");
@@ -546,7 +553,7 @@ aspect CS_Class {
       case LABCOMM_FLOAT: { env.print("e.encodeFloat"); } break;
       case LABCOMM_DOUBLE: { env.print("e.encodeDouble"); } break;
       case LABCOMM_STRING: { env.print("e.encodeString"); } break;
-      case LABCOMM_SAMPLE: { env.println("e.encodeSampleRef"); } break;
+      case LABCOMM_SAMPLE: { env.print("e.encodeSampleRef"); } break;
     }
     env.println("(" + name + ");");
   }
@@ -729,7 +736,7 @@ aspect CS_Class {
   public void PrimType.CS_emitTypePrefix(CS_env env) {
     switch (getToken()) {
       case LABCOMM_STRING: { env.print("String"); } break;
-      case LABCOMM_SAMPLE: { env.print("Sample"); } break;
+      case LABCOMM_SAMPLE: { env.print("Type"); } break;
       default: { env.print(getName()); } break;
     }
   }
@@ -859,7 +866,7 @@ aspect CS_Class {
     switch (getToken()) {
       case LABCOMM_STRING: { env.print("String"); } break;
       case LABCOMM_BOOLEAN: { env.print("bool"); } break;
-      case LABCOMM_SAMPLE: { env.print("Sample"); } break;
+      case LABCOMM_SAMPLE: { env.print("Type"); } break;
       default: { env.print(getName()); } break;
     }
   }
diff --git a/compiler/Java_CodeGen.jrag b/compiler/Java_CodeGen.jrag
index db2d562..7c00bc3 100644
--- a/compiler/Java_CodeGen.jrag
+++ b/compiler/Java_CodeGen.jrag
@@ -338,7 +338,7 @@ aspect Java_Class {
     env.indent();
 
     Java_emitUserTypeDeps(env, null, true);
-    env.println("e.register(Dispatcher.singleton());");
+    env.println("e.register(dispatcher);");
     env.unindent();
     env.println("}");
     env.println();
@@ -429,7 +429,7 @@ aspect Java_Class {
     env.println();
     env.println("public static void register(Decoder d, Handler h) throws IOException {");
     env.indent();
-    env.println("d.register(Dispatcher.singleton(), h);");
+    env.println("d.register(dispatcher, h);");
     env.unindent();
     env.println("}");
     env.println();
@@ -490,18 +490,17 @@ 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()+">":""; 
-    env.println("private static class Dispatcher implements SampleDispatcher "+genericStr+"{");
-    env.indent();
-    env.println();
-    env.println("private static Dispatcher singleton;");
+    env.println("private static Dispatcher dispatcher = new Dispatcher();");
     env.println();
-    env.println("public synchronized static Dispatcher singleton() {");
+    env.println("public SampleDispatcher getDispatcher() {");
     env.indent();
-    env.println("if(singleton==null) singleton=new Dispatcher();");
-    env.println("return singleton;");
+    env.println("return dispatcher;");
     env.unindent();
     env.println("}");
     env.println();
+    env.println("private static class Dispatcher implements SampleDispatcher "+genericStr+"{");
+    env.indent();
+    env.println();
     env.println("public Class"+genericStr+" getSampleClass() {");
     env.indent();
     env.println("return " + getName() + ".class;");
diff --git a/lib/csharp/se/lth/control/labcomm/Constant.cs b/lib/csharp/se/lth/control/labcomm/Constant.cs
index cc7deac..5b247f6 100644
--- a/lib/csharp/se/lth/control/labcomm/Constant.cs
+++ b/lib/csharp/se/lth/control/labcomm/Constant.cs
@@ -9,8 +9,8 @@ namespace se.lth.control.labcomm {
      */
     public const int VERSION          = 0x01;
     public const int SAMPLE_DEF       = 0x02;
-    public const int TYPE_DEF         = 0x03;
-    public const int TYPE_BINDING     = 0x04;
+    public const int SAMPLE_REF       = 0x03;
+    public const int TYPE_DEF         = 0x04;
     public const int PRAGMA           = 0x3f;
     public const int FIRST_USER_INDEX = 0x40; /* ..0xffffffff */
 
@@ -31,6 +31,7 @@ namespace se.lth.control.labcomm {
     public const int FLOAT            = 0x25;
     public const int DOUBLE           = 0x26;
     public const int STRING           = 0x27;
+    public const int SAMPLE           = 0x28;
     
   }
 
diff --git a/lib/csharp/se/lth/control/labcomm/Decoder.cs b/lib/csharp/se/lth/control/labcomm/Decoder.cs
index 9bdbaa3..4e8868f 100644
--- a/lib/csharp/se/lth/control/labcomm/Decoder.cs
+++ b/lib/csharp/se/lth/control/labcomm/Decoder.cs
@@ -6,6 +6,7 @@ namespace se.lth.control.labcomm {
 
     void register(SampleDispatcher dispatcher, 
 		  SampleHandler handler);
+    void registerSampleRef(SampleDispatcher dispatcher);
 
     bool decodeBoolean();
     byte decodeByte();
@@ -16,7 +17,7 @@ namespace se.lth.control.labcomm {
     double decodeDouble();
     String decodeString();
     int decodePacked32();
-    Sample decodeSampleRef();
+    Type decodeSampleRef();
 
   }
 
diff --git a/lib/csharp/se/lth/control/labcomm/DecoderChannel.cs b/lib/csharp/se/lth/control/labcomm/DecoderChannel.cs
index 26a3e65..1185e28 100644
--- a/lib/csharp/se/lth/control/labcomm/DecoderChannel.cs
+++ b/lib/csharp/se/lth/control/labcomm/DecoderChannel.cs
@@ -8,7 +8,8 @@ namespace se.lth.control.labcomm {
   public class DecoderChannel : Decoder {
 
     private Stream stream;
-    private DecoderRegistry registry = new DecoderRegistry();
+    private DecoderRegistry def_registry = new DecoderRegistry();
+    private DecoderRegistry ref_registry = new DecoderRegistry();
     byte[] buf = new byte[8];
 
     public DecoderChannel(Stream stream) {
@@ -34,10 +35,18 @@ namespace se.lth.control.labcomm {
           int signature_length = decodePacked32();
           byte[] signature = new byte[signature_length];
           ReadBytes(signature, signature_length);
-	  registry.add(index, name, signature);
+	  def_registry.add(index, name, signature);
+        } break;
+        case Constant.SAMPLE_REF: {
+          int index = decodePacked32();
+          String name = decodeString();
+          int signature_length = decodePacked32();
+          byte[] signature = new byte[signature_length];
+          ReadBytes(signature, signature_length);
+	  ref_registry.add(index, name, signature);
         } break;
         default: {
-          DecoderRegistry.Entry e = registry.get(tag);
+          DecoderRegistry.Entry e = def_registry.get(tag);
           if (e == null) {
             throw new IOException("Unhandled tag " + tag);
           }
@@ -64,7 +73,11 @@ namespace se.lth.control.labcomm {
 
     public void register(SampleDispatcher dispatcher, 
 			 SampleHandler handler) {
-      registry.add(dispatcher, handler);
+      def_registry.add(dispatcher, handler);
+    }
+
+    public void registerSampleRef(SampleDispatcher dispatcher) {
+      ref_registry.add(dispatcher, null);
     }
 
     private void ReadBytes(byte[] result, int length) {
@@ -147,8 +160,14 @@ namespace se.lth.control.labcomm {
       return (int) (res & 0xffffffff);
     }
 
-    public Sample decodeSampleRef() {
-      return null;
+    public Type decodeSampleRef() {
+      int index = (int)ReadInt(4);
+      DecoderRegistry.Entry e = ref_registry.get(index);
+      if (e != null) {
+        return e.getSampleDispatcher().getSampleClass();
+      } else {
+        return null;
+      }
     }
   }
 } 
diff --git a/lib/csharp/se/lth/control/labcomm/Encoder.cs b/lib/csharp/se/lth/control/labcomm/Encoder.cs
index 0badded..1deb1b7 100644
--- a/lib/csharp/se/lth/control/labcomm/Encoder.cs
+++ b/lib/csharp/se/lth/control/labcomm/Encoder.cs
@@ -5,6 +5,7 @@ namespace se.lth.control.labcomm {
   public interface Encoder {
     
     void register(SampleDispatcher dispatcher);
+    void registerSampleRef(SampleDispatcher dispatcher);
     void begin(Type c);
     void end(Type c);
 
@@ -17,7 +18,7 @@ namespace se.lth.control.labcomm {
     void encodeDouble(double value);
     void encodeString(String value);
     void encodePacked32(Int64 value);
-    void encodeSampleRef(Sample value);
+    void encodeSampleRef(Type value);
     
   }
 
diff --git a/lib/csharp/se/lth/control/labcomm/EncoderChannel.cs b/lib/csharp/se/lth/control/labcomm/EncoderChannel.cs
index 90c0ac8..2f3da1c 100644
--- a/lib/csharp/se/lth/control/labcomm/EncoderChannel.cs
+++ b/lib/csharp/se/lth/control/labcomm/EncoderChannel.cs
@@ -9,7 +9,8 @@ namespace se.lth.control.labcomm {
 
     private Stream writer;
     private MemoryStream bytes = new MemoryStream();
-    private EncoderRegistry registry = new EncoderRegistry();
+    private EncoderRegistry def_registry = new EncoderRegistry();
+    private EncoderRegistry ref_registry = new EncoderRegistry();
     byte[] buf = new byte[8];
     private int current_tag; 
 
@@ -22,7 +23,7 @@ namespace se.lth.control.labcomm {
     }
 
     public void register(SampleDispatcher dispatcher) {
-      int index = registry.add(dispatcher);
+      int index = def_registry.add(dispatcher);
       begin(Constant.SAMPLE_DEF);
       encodePacked32(index);
       encodeString(dispatcher.getName());
@@ -34,13 +35,26 @@ namespace se.lth.control.labcomm {
       end(null);
     }
 
+    public void registerSampleRef(SampleDispatcher dispatcher) {
+      int index = ref_registry.add(dispatcher);
+      begin(Constant.SAMPLE_REF);
+      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);
+    }
+
     private void begin(int tag) {
       current_tag = tag;
       bytes.SetLength(0);
     }
 
     public void begin(Type c) {
-      begin(registry.getTag(c));
+      begin(def_registry.getTag(c));
     }
 
     public void end(Type c) {
@@ -118,9 +132,13 @@ namespace se.lth.control.labcomm {
       WritePacked32(bytes, value);
     }
 
-    public void encodeSampleRef(Sample value) {
-      WriteInt(0, 4);
-      throw new Exception("IMPLEMENT");
+    public void encodeSampleRef(Type value) {
+      int index = 0;
+      try {
+        index = ref_registry.getTag(value);
+      } catch (NullReferenceException) {
+      }
+      WriteInt(index, 4);
     }
 
   }
diff --git a/lib/csharp/se/lth/control/labcomm/Sample.cs b/lib/csharp/se/lth/control/labcomm/Sample.cs
index ac56229..c9ea7fd 100644
--- a/lib/csharp/se/lth/control/labcomm/Sample.cs
+++ b/lib/csharp/se/lth/control/labcomm/Sample.cs
@@ -1,3 +1,9 @@
-public interface Sample {
+namespace se.lth.control.labcomm {
+
+  public interface Sample {
+
+    SampleDispatcher getDispatcher();
+
+  }
 
 }
diff --git a/lib/java/se/lth/control/labcomm/Encoder.java b/lib/java/se/lth/control/labcomm/Encoder.java
index 1d0f452..957447e 100644
--- a/lib/java/se/lth/control/labcomm/Encoder.java
+++ b/lib/java/se/lth/control/labcomm/Encoder.java
@@ -5,6 +5,7 @@ import java.io.IOException;
 public interface Encoder {
 
   public void register(SampleDispatcher dispatcher) throws IOException;
+  public void registerSampleRef(Sample sample) throws IOException;
   public void begin(Class<? extends Sample> c) throws IOException;
   public void end(Class<? extends Sample> c) throws IOException;
   public void encodeBoolean(boolean value) throws IOException;
diff --git a/lib/java/se/lth/control/labcomm/EncoderChannel.java b/lib/java/se/lth/control/labcomm/EncoderChannel.java
index 91dade4..aeeee47 100644
--- a/lib/java/se/lth/control/labcomm/EncoderChannel.java
+++ b/lib/java/se/lth/control/labcomm/EncoderChannel.java
@@ -41,6 +41,9 @@ public class EncoderChannel implements Encoder {
     end(null);
   }
 
+  public void registerSampleRef(Sample sample) throws IOException {
+  }
+
   private void begin(int tag) {
     current_tag = tag;
     bytes.reset();
diff --git a/lib/java/se/lth/control/labcomm/Sample.java b/lib/java/se/lth/control/labcomm/Sample.java
index 8210e3a..f86f486 100644
--- a/lib/java/se/lth/control/labcomm/Sample.java
+++ b/lib/java/se/lth/control/labcomm/Sample.java
@@ -2,4 +2,6 @@ package se.lth.control.labcomm;
 
 public interface Sample {
 
-}
\ No newline at end of file
+  public SampleDispatcher getDispatcher();
+
+}
diff --git a/lib/python/labcomm/LabComm.py b/lib/python/labcomm/LabComm.py
index f22707b..c45e705 100644
--- a/lib/python/labcomm/LabComm.py
+++ b/lib/python/labcomm/LabComm.py
@@ -559,7 +559,17 @@ class array(object):
     
 class struct:
     def __init__(self, field):
-        self.field = field
+        self.field = tuple(field)
+
+    def __eq__(self, other):
+        return (type(self) == type(other) and 
+                self.field == other.field)
+        
+    def __ne__(self, other):
+        return not self == other
+
+    def __hash__(self):
+        return hash(self.field)
 
     def encode_decl(self, encoder):
         encoder.encode_type(i_STRUCT)
@@ -612,7 +622,7 @@ SAMPLE_DEF = sample_def()
 SAMPLE_REF = sample_ref()
 
 ARRAY = array(None, None)
-STRUCT = struct({})
+STRUCT = struct([])
 
 class anonymous_object(dict):
     def __setattr__(self, name, value):
diff --git a/test/ref.lc b/test/ref.lc
index 955d9a7..6fa041e 100644
--- a/test/ref.lc
+++ b/test/ref.lc
@@ -1,4 +1,4 @@
-sample sample usedBoth;
-sample sample unusedEncoder;
-sample sample unusedDecoder;
+sample sample s1;
+sample sample s2;
+sample sample s3;
 sample sample sample_list[4];
diff --git a/test/relay_gen_cs.py b/test/relay_gen_cs.py
index 669f5f5..8cd9043 100755
--- a/test/relay_gen_cs.py
+++ b/test/relay_gen_cs.py
@@ -2,6 +2,7 @@
 
 import re
 import sys
+import random
 
 def split_match(pattern, multiline):
     def match(s):
@@ -11,6 +12,10 @@ def split_match(pattern, multiline):
         pass
     return filter(lambda s: s != None, map(match, multiline.split('\n')))
    
+def shuffle(l):
+    result = list(l)
+    random.shuffle(result)
+    return result
 
 if __name__ == '__main__':
     f = open(sys.argv[1])
@@ -58,22 +63,29 @@ if __name__ == '__main__':
       |    FileStream InFile = new FileStream(InName,
       |                                       FileMode.Open,
       |                                       FileAccess.Read);
-      |    DecoderChannel d = new DecoderChannel(InFile);
+      |    DecoderChannel decoder = new DecoderChannel(InFile);
       |    FileStream OutFile = new FileStream(OutName,
       |                                        FileMode.OpenOrCreate,
       |                                        FileAccess.Write);
       |    encoder = new EncoderChannel(OutFile);
       |
     """))
-    for func,arg in sample:
-        result.append('    %s.register(d, this);' % func)
+    for func,arg in shuffle(sample):
+        result.append('    %s.register(decoder, this);' % func)
         pass
-    for func,arg in sample:
+    for func,arg in shuffle(sample):
+        result.append('    %s.registerSampleRef(decoder);' % func)
+        pass
+    for func,arg in shuffle(sample):
         result.append('    %s.register(encoder);' % func)
         pass
+    for func,arg in shuffle(sample):
+        result.append('    %s.registerSampleRef(encoder);' % func)
+        pass
+    
     result.extend(split_match('^[^|]*\|(.*)$', """
       |    try {
-      |      d.run();
+      |      decoder.run();
       |    } catch (EndOfStreamException) {
       |    }
       |  }
-- 
GitLab