Skip to content
Snippets Groups Projects
Select Git revision
1 result Searching

CS_CodeGen.jrag

Blame
  • CS_CodeGen.jrag 26.16 KiB
    import java.io.*;
    import java.util.*;
    
    aspect CS_CodeGenEnv {
    
      // Environment wrapper for CS-code generation
      // handles indentation, file writing, 
    
      public class CS_env {
    
        public final int version;
        public final String verStr;
        private int indent;
        private int depth;
        private CS_printer printer;
        private HashMap unique = new HashMap();
    
        final private static class CS_printer {
          
          private boolean newline = true;
          private File file;
          private PrintStream out;
          private IOException exception;
          
    
          public CS_printer(File f) {
      	file = f;
            File parentFile = f.getParentFile();
            if(parentFile != null) {
                parentFile.mkdirs();
            }
          }
    
         public CS_printer(PrintStream out) {
            this.out = out;
          }
    
          public void close() throws IOException {
    	if (out != null) {
      	  out.close();
            }
    	if (exception != null) {
    	  throw exception;
            }
          }
    
          public PrintStream getPrintStream() {
    	return(out);
          }
    
          public void checkOpen() {
    	if (out == null && exception == null) {
              try {
        	    out = new PrintStream(new FileOutputStream(file));
              } catch (IOException e) {
    	    exception = e;
              }
            }
          }
    
          public void print(CS_env env, String s) {
    	checkOpen();
            if (newline) {
              newline = false;
              for (int i = 0 ; i < env.indent ; i++) {
                out.print("  ");
              }
            }
            out.print(s);
          }
    
          public void println(CS_env env, String s) {
    	checkOpen();
            print(env, s);
            out.println();
            newline = true;
          }
        }
    
        private CS_env(int indent, CS_printer printer, int version) {
          this.version = version;
          this.indent = indent;
          this.printer = printer;
          this.verStr = LabCommVersion.versionString(version);
        }
    
        public CS_env(File f, int version) {
          this(0, new CS_printer(f), version);
        }
    
        public CS_env(PrintStream out, int version) {
          this(0, new CS_printer(out), version);
        }
    
        public void close() throws IOException {
          printer.close();
        }
    
        public PrintStream getPrintStream() {
          return printer.getPrintStream();
        }
        public void indent(int amount) {
          indent += amount;
        }
    
        public void indent() {
          indent(1);
        }
    
        public void unindent(int amount) {
          indent -= amount;
          if (indent < 0) {
            throw new Error("Negative indent level");
          }
        }
    
        public void unindent() {
          unindent(1);
        }
    
        public void print(String s) {
          printer.print(this, s);
        }
    
        public void println(String s) {
          printer.println(this, s);
        }
    
        public void println() {
          printer.println(this, "");
        }
    
        public int getDepth() {
          return depth;
        }
    
        public String print_for_begin(String limit) {
          print("for (int i_" + depth + " = 0 ; ");
          print("i_" + depth + " < " + limit + " ; ");
          println("i_" + depth + "++) {");
          indent();
          depth++;
          return "i_" + (depth - 1);
        }
    
        public void print_for_end() {
          depth--;
          unindent();
          println("}");
        }
    
        public void print_block_begin() {
          println("{");
          indent();
        }
    
        public void print_block_end() {
          unindent();
          println("}");
        }
    
        public String getUnique(Object o) {
          String result = (String)unique.get(o);
          if (result == null) {
       	result = "_" + (unique.size() + 1) + "_";
          }
          unique.put(o, result);
          return result;
        }
    
      }
    
    }
    
    aspect CS_StructName {
    
      inh int Decl.CS_Depth();
      inh int Type.CS_Depth();
      eq Program.getDecl(int i).CS_Depth() = 0;
      eq StructType.getField(int i).CS_Depth() = CS_Depth() + 1;
    
      inh String Type.CS_structName();
      eq Program.getDecl(int i).CS_structName() = getDecl(i).getName();
      eq StructType.getField(int i).CS_structName() {
        if (CS_Depth() == 0) {
          return "struct_" + getField(i).getName();
        } else {
          return CS_structName() + "_" + getField(i).getName();
        }
      }
    }
    
    aspect CS_Void {
    
      syn boolean Decl.CS_isVoid() = getType().CS_isVoid();
      syn boolean UserType.CS_isVoid() = decl().CS_isVoid();
      syn boolean Type.CS_isVoid() = false;
      syn boolean VoidType.CS_isVoid() = true;
    
    }
    
    aspect CS_CodeGen {
    
      public void Program.CS_gen(String file, 
    			     String namespace, int version) throws IOException {
        // Registration class
        CS_env env = new CS_env(new File(file), version);
        if (namespace != null && namespace.length() > 0) {
          env.println("namespace " + namespace + "{");
          env.indent();
        }
        env.println("using System;");
        env.println("using se.lth.control.labcomm;");
        for (int i = 0; i < getNumDecl(); i++) {
          Decl d = getDecl(i);
          try {
            d.CS_emitClass(env);
          } catch (Error e) {
    	System.err.println(d.getName());
    	throw e;
          }
        }
        if (namespace != null && namespace.length() > 0) {
          env.unindent();
          env.println("}");
        }
      }
    
    }
    
    aspect CS_Register {
    
      public void Program.CS_emitTypeRegister(CS_env env) {
      }
    
      public void Decl.CS_emitTypeRegister(CS_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".CS_emitTypeRegister(CS_env env)" + 
    		    " not declared");
      }
    
      public void SampleDecl.CS_emitTypeRegister(CS_env env) {
        env.println(getName() + ".register(c);");
      }
    
      public void TypeDecl.CS_emitTypeRegister(CS_env env) {
        // TODO
      }
    
    }
    
    aspect CS_Class {
    
      public void Decl.CS_emitClass(CS_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".CS_emitClass(CS_env env)" + 
    		    " not declared");
      }
    
      public void Decl.CS_emitDeclPP(CS_env env){
    	env.println("/* ");
    	pp(env.getPrintStream());
    	
    	CS_emitUserTypeDeps(env,null,false);
    	CS_emitUserTypeRefs(env,null,false);
    	env.println("*/");
      
      }
      
      public void Decl.CS_emitUserTypeDeps(CS_env env, String via, boolean outputCode){
    	Iterator<Decl> it = type_dependencies().iterator();
    	while(it.hasNext()) {
    	    Decl t = it.next();
    
    	    t.CS_emitUserTypeDeps(env, t.getName(), outputCode);
    	    if( outputCode && t.getType().isUserType() ) {
    	       env.println(t.getName()+".register(e);");
    	    } else {  // Just output a comment
    		String refpath = (via == null) ? "directly" : "indirectly via "+via;
    	       env.println(" //Depends ("+refpath+") on "+t.getName() );
    	    }
    	}
      }
      
      public void Decl.CS_emitUserTypeRefs(CS_env env, String via, boolean outputCode){
         if( isReferenced() ) {
            Iterator<Decl> it = type_references().iterator();
            while(it.hasNext()) {
                Decl t = it.next();
    
                t.CS_emitUserTypeRefs(env, t.getName(), outputCode);
                if(outputCode) {
                   env.println(t.getName()+".register(e);");
                } else {  // Just output a comment
    	        String refpath = (via == null) ? "directly" : "indirectly via "+via;
    	       env.println(" //Is referenced ("+refpath+")  by "+t.getName() );
                }
            }
        }
      }
      
      public void Decl.CS_emitRegisterEncoder(CS_env env) {
        env.println("public static void register(Encoder e){");
        env.indent();
        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, 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();
      }
        
      public void TypeDecl.CS_emitClass(CS_env env) {
        if (getType().CS_needInstance()) {
          // Hackish prettyprint preamble
          env.println("/* ");
          pp(env.getPrintStream());
          env.println("*/");
          env.println();
          env.println("public class " + getName() + " : SampleType {");
          env.println();
          env.indent();
          getType().CS_emitInstance(env);
          if( isReferenced()) {
            CS_emitRegisterEncoder(env);
    	CS_emitDispatcher(env,false);
          }
          CS_emitSignature(env);
          CS_emitEncoder(env);
          CS_emitDecoder(env);
          env.unindent();
          env.println("}");
        }
      }
    
      public void SampleDecl.CS_emitClass(CS_env env) {
        env.println("/* ");
        pp(env.getPrintStream());
        env.println("*/");
        env.println();
        env.println("public class " + getName() + " : Sample {");
        env.println();
        env.indent();
        getType().CS_emitInstance(env);
        env.println("public interface Handler : SampleHandler {");
        env.print("  void handle(");
        if (!isVoid()) {
          getType().CS_emitType(env);
          env.print(" value");
        }
        env.println(");");
        env.println("}");
        env.println();
        CS_emitDispatcher(env,true);
        CS_emitRegisterEncoder(env);
        CS_emitRegisterDecoder(env);
        CS_emitEncoder(env);
        CS_emitDecoder(env);
        CS_emitSignature(env);
    
        env.println("}");
      }
    
      public void Decl.CS_emitSignature(CS_env env) {
        CS_emitFlatSignature(env);
    //    if(isReferenced() || isSampleDecl()){
    //      Signature signature = getSignature();
    //      signature.CS_emitSignature(env, !isSampleDecl());
    //    }
      }
    
      public void Decl.CS_emitFlatSignature(CS_env env){
        env.println("private static byte[] signature = new byte[] {");
        env.indent();
        SignatureList signature = flatSignature(env.version);
        for (int i = 0 ; i < signature.size() ; i++) {
          String comment = signature.getComment(i);
          if (comment != null) {
            env.println(signature.getIndent(i) + "// " + comment);
          }
          byte[] data = signature.getData(i, env.version);
          if (data != null) {
            env.print(signature.getIndent(i));
            for (int j = 0 ; j < data.length ; j++) {
              //env.print(data[j] + ", ");
              env.print(String.format("0x%02X, ", data[j])) ;
            }
            env.println();
          }
        }
        env.unindent();
        env.println("};");
        env.println();
      }
    
      //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 static Dispatcher dispatcher = new Dispatcher();");
        env.println();
        env.println("public SampleDispatcher getDispatcher() {");
        env.indent();
        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() + ");");
        env.unindent();
        env.println("}");
        env.println();
        env.println("public String getName() {");
        env.indent();
        env.println("return \"" + getName() + "\";");
        env.unindent();
        env.println("}");
        env.println();
        env.println("public byte getTypeDeclTag() {");
        env.indent();
        if(isSample) {
          env.println("return Constant.SAMPLE_DEF;");
        } else {
          env.println("return Constant.TYPE_DEF;");
        }
        env.unindent();
        env.println("}");
        env.println();
        env.println("public bool isSample() {");
        env.indent();
        env.println("return "+isSample+";");
        env.unindent();
        env.println("}");
        env.println("/** return the flat signature. */");
        env.println("public byte[] getSignature() {");
        env.indent();
        env.println("return signature;");
        env.unindent();
        env.println("}");
        env.println();
    //    env.println("public void encodeSignature(Encoder e) throws IOException{");
    //    env.indent();
    //    env.println("emitSignature(e);");
    //    env.unindent();
    //    env.println("}");
    //    env.println();
    //  env.println("public void encodeSignatureMetadata(Encoder e, int index){");
    //  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 bool canDecodeAndHandle() {");
        env.indent();
        env.println("return "+isSample+";");
        env.unindent();
        env.println("}");
        env.println();
        env.println("public void decodeAndHandle(Decoder d,");
        env.println("                            SampleHandler h) {");
        env.indent();
        if( isSample) {
            if (isVoid()) {
              env.println(getName() + ".decode(d);");
              env.println("((Handler)h).handle();");
            } else {
              env.println("((Handler)h).handle(" + getName() + ".decode(d));");
            }
        } else {
            env.println("throw new Exception(\"A typedef has no handler, the corresponding method on the sample class should be called.\");");
        }
        env.unindent();
        env.println("}");
        env.println("");
        env.unindent();
        env.println("}");
        env.println("");
    
     } //TODO, fix above method
      
      public void TypeDecl.CS_emitEncoder(CS_env env) {
        env.print("public static void encode(Encoder e");
        if (!isVoid()) {
          env.print(", ");
          getType().CS_emitType(env);
          env.print(" value");
        }
        env.println(") {");
        env.indent();
        getType().CS_emitEncoder(env, "value");
        env.unindent();
        env.println("}");
        env.println();
      }
    
      public void SampleDecl.CS_emitEncoder(CS_env env) {
        env.print("public static void encode(Encoder e");
        if (!isVoid()) {
          env.print(", ");
          getType().CS_emitType(env);
          env.print(" value");
        }
        env.println(") {");
        env.indent();
        env.println("e.begin(typeof(" + getName() + "));");
        getType().CS_emitEncoder(env, "value");
        env.println("e.end(typeof(" + getName() + "));");
        env.unindent();
        env.println("}");
        env.println();
      }
    
      public void Type.CS_emitEncoder(CS_env env, String name) {
        throw new Error(this.getClass().getName() + 
    		    ".CS_emitEncoder(CS_env env, String name)" + 
    		    " not declared");
      }
    
      public void VoidType.CS_emitEncoder(CS_env env, String name) {
      }
    
      public void PrimType.CS_emitEncoder(CS_env env, String name) {
        switch (getToken()) {
          case LABCOMM_BOOLEAN: { env.print("e.encodeBoolean"); } break;
          case LABCOMM_BYTE: { env.print("e.encodeByte"); } break;
          case LABCOMM_SHORT: { env.print("e.encodeShort"); } break;
          case LABCOMM_INT: { env.print("e.encodeInt"); } break;
          case LABCOMM_LONG: { env.print("e.encodeLong"); } break;
          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.print("e.encodeSampleRef"); } break;
        }
        env.println("(" + name + ");");
      }
    
      public void ArrayType.CS_emitEncoder(CS_env env, String name) {
        env.print_block_begin();
        int baseDepth = env.getDepth();
        for (int i = 0 ; i < getNumExp() ; i++) {
          String limit = getExp(i).CS_emitEncoder(env, 
    					      name + ".GetLength(" + i + ")");
          env.println("int i_" + (baseDepth + i) + "_max = " + limit + ";");
        }
        String index = null;
        for (int i = 0 ; i < getNumExp() ; i++) {
          String limit = "i_" + (baseDepth + i) + "_max";
          if (i == 0) {
            index = env.print_for_begin(limit);
          } else {
            index = index + ", " + env.print_for_begin(limit);
          }
        }
        getType().CS_emitEncoder(env, name + "[" + index + "]");
        for (int i = 0 ; i < getNumExp() ; i++) {
          env.print_for_end();
        }
        env.print_block_end();
      }
      
      public String Exp.CS_emitEncoder(CS_env env, String name) {
        throw new Error(this.getClass().getName() + 
    		    ".CS_emitEncoder(CS_env env, String name)" + 
    		    " not declared");
      }
    
      public String IntegerLiteral.CS_emitEncoder(CS_env env, String name) {
        return getValue();
      }
    
      public String VariableSize.CS_emitEncoder(CS_env env, String name) {
        env.println("e.encodePacked32(" + name + ");");
        return name;
      }
    
      public void StructType.CS_emitEncoder(CS_env env, String name) {
        for (int i = 0 ; i < getNumField() ; i++) {
          Field f = getField(i);
          f.getType().CS_emitEncoder(env, name + "." + f.getName());
        }
      }
    
      public void UserType.CS_emitEncoder(CS_env env, String name) {
        if (CS_needInstance()) {
          env.println(getName() + ".encode(e, " + name + ");");
        } else {
          decl().getType().CS_emitEncoder(env, name);
        }
      }
    
      public void Decl.CS_emitDecoder(CS_env env) {
        env.print("public static ");
        getType().CS_emitType(env);
        env.println(" decode(Decoder d) {");
        env.indent();
        if (!isVoid()) {
          getType().CS_emitType(env);
          env.println(" result;");
          getType().CS_emitDecoder(env, "result");
          env.println("return result;");
        }
        env.unindent();
        env.println("}");
        env.println();
      }
    
      public void Type.CS_emitDecoder(CS_env env, String name) {
        throw new Error(this.getClass().getName() + 
    		    ".CS_emitDecoder(CS_env env, String name)" + 
    		    " not declared");
      }
    
      public void VoidType.CS_emitDecoder(CS_env env, String name) {
      }
    
      public void PrimType.CS_emitDecoder(CS_env env, String name) {
        env.print(name + " = ");
        switch (getToken()) {
          case LABCOMM_BOOLEAN: { env.println("d.decodeBoolean();"); } break;
          case LABCOMM_BYTE: { env.println("d.decodeByte();"); } break;
          case LABCOMM_SHORT: { env.println("d.decodeShort();"); } break;
          case LABCOMM_INT: { env.println("d.decodeInt();"); } break;
          case LABCOMM_LONG: { env.println("d.decodeLong();"); } break;
          case LABCOMM_FLOAT: { env.println("d.decodeFloat();"); } break;
          case LABCOMM_DOUBLE: { env.println("d.decodeDouble();"); } break;
          case LABCOMM_STRING: { env.println("d.decodeString();"); } break;
          case LABCOMM_SAMPLE: { env.println("d.decodeSampleRef();"); } break;
          default: {
            throw new Error("PrimType.CS_emitDecoder(CS_env env, String name)" + 
                            " unknown token type");
          }
        }
      }
    
      public void ArrayType.CS_emitDecoder(CS_env env, String name) {
        env.println("{");
        env.indent();
        int baseDepth = env.getDepth();
        for (int i = 0 ; i < getNumExp() ; i++) {
          env.print("int i_" + (baseDepth + i) + "_max = ");
          getExp(i).CS_emitDecoder(env);
          env.println(";");
        }
        env.print(name + " = new "); 
        getType().CS_emitTypePrefix(env);
        env.print("[");
        for (int i = 0 ; i < getNumExp() ; i++) {
          if (i > 0) {
    	env.print(", ");
          }
          env.print("i_" + (baseDepth + i) + "_max");
        }
        env.print("]");
        getType().CS_emitTypeSuffix(env);
        env.println(";");
        
        String index = null;
        for (int i = 0 ; i < getNumExp() ; i++) {
          String limit = "i_" + (baseDepth + i) + "_max";
          if (i == 0) {
            index = env.print_for_begin(limit);
          } else {
            index = index + ", " + env.print_for_begin(limit);
          }
        }
        getType().CS_emitDecoder(env, name + "[" + index + "]");
        for (int i = 0 ; i < getNumExp() ; i++) {
          env.print_for_end();
        }
        env.unindent();
        env.println("}");
      }
    
      public void Exp.CS_emitDecoder(CS_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".CS_emitDecoder(CS_env env)" + 
    		    " not declared");
      }
    
      public void IntegerLiteral.CS_emitDecoder(CS_env env) {
        env.print(getValue());
      }
    
      public void VariableSize.CS_emitDecoder(CS_env env) {
        env.print("d.decodePacked32()");
      }
    
      public void StructType.CS_emitDecoder(CS_env env, String name) {
        env.print(name + " = new ");
        CS_emitType(env);
        env.println("();");
        for (int i = 0 ; i < getNumField() ; i++) {
          Field f = getField(i);
          f.getType().CS_emitDecoder(env, name + "." + f.getName());
        }
      }
    
      public void UserType.CS_emitDecoder(CS_env env, String name) {
        if (CS_needInstance()) {
          env.println(name + " = " + getName() + ".decode(d);");
        } else {
          decl().getType().CS_emitDecoder(env, name);
        }
      }
    
      public void Type.CS_emitTypePrefix(CS_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".CS_emitTypePrefix(CS_env env)" + 
    		    " not declared");
      }
    
      public void PrimType.CS_emitTypePrefix(CS_env env) {
        switch (getToken()) {
          case LABCOMM_STRING: { env.print("String"); } break;
          case LABCOMM_SAMPLE: { env.print("Type"); } break;
          default: { env.print(getName()); } break;
        }
      }
    
      public void UserType.CS_emitTypePrefix(CS_env env) {
        if (CS_needInstance()) {
          env.print(getName());
        } else {
          decl().getType().CS_emitTypePrefix(env);
        } 
      }
    
      public void ArrayType.CS_emitTypePrefix(CS_env env){
        getType().CS_emitTypePrefix(env);
      }
    
      public void StructType.CS_emitTypePrefix(CS_env env){
        env.print(CS_structName());
      }
    
      public void Type.CS_emitTypeSuffix(CS_env env) {
      }
    
      public void UserType.CS_emitTypeSuffix(CS_env env) {
        if (! CS_needInstance()) {
          decl().getType().CS_emitTypeSuffix(env);
        } 
      }
    
      public void ArrayType.CS_emitTypeSuffix(CS_env env){
        env.print("[");
        for (int i = 1 ; i < getNumExp() ; i++) {
          env.print(",");
        }
        env.print("]");
        getType().CS_emitTypeSuffix(env);
      }
    
      public boolean Type.CS_needInstance() {
        throw new Error(this.getClass().getName() + 
    		    ".CS_needInstance()" + 
    		    " not declared");
      }
    
      public boolean VoidType.CS_needInstance() {
        return false;
      }
    
      public boolean PrimType.CS_needInstance() {
        return false;
      }
    
      public boolean UserType.CS_needInstance() {
        return decl().getType().CS_needInstance();
      }
    
      public boolean StructType.CS_needInstance() {
        return true;
      }
    
      public boolean ArrayType.CS_needInstance() {
        return getType().CS_needInstance();
      }
    
      public boolean Type.CS_isPrimitive() {
        return false;
      }
    
      public boolean PrimType.CS_isPrimitive() {
        return true;
      }
    
      public void Type.CS_emitInstance(CS_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".CS_emitInstance(CS_env env)" + 
    		    " not declared");
      }
    
      public void VoidType.CS_emitInstance(CS_env env) {
      }
    
      public void PrimType.CS_emitInstance(CS_env env) {
      }
    
      public void ArrayType.CS_emitInstance(CS_env env) {
        getType().CS_emitInstance(env);
      }
    
      public void StructType.CS_emitInstance(CS_env env) {
        if (CS_Depth() > 0) {
          env.println("public class " + CS_structName() + " {");
          env.indent();
        }
        for (int i = 0 ; i < getNumField() ; i++) {
          getField(i).getType().CS_emitInstance(env);
        }
        for (int i = 0 ; i < getNumField() ; i++) {
          getField(i).CS_emitField(env);
        }
        if (CS_Depth() > 0) {
          env.unindent();
          env.println("}");
        }
        env.println();
      }
    
      public void UserType.CS_emitInstance(CS_env env) {
      }
    
      public void Field.CS_emitField(CS_env env) {
        env.print("public ");
        getType().CS_emitType(env);
        env.println(" " + getName() + ";");    
      }
    
      public void Type.CS_emitType(CS_env env) {
        throw new Error(this.getClass().getName() + 
    		    ".CS_emitType(CS_env env)" + 
    		    " not declared");
      }
    
      public void VoidType.CS_emitType(CS_env env) {
        env.print("void");
      }
    
      public void PrimType.CS_emitType(CS_env env) {
        switch (getToken()) {
          case LABCOMM_STRING: { env.print("String"); } break;
          case LABCOMM_BOOLEAN: { env.print("bool"); } break;
          case LABCOMM_SAMPLE: { env.print("Type"); } break;
          default: { env.print(getName()); } break;
        }
      }
    
      public void UserType.CS_emitType(CS_env env) {
        decl().getType().CS_emitType(env);
      }
    
      public void ArrayType.CS_emitType(CS_env env){
        getType().CS_emitTypePrefix(env);
        env.print("[");
        for (int i = 1 ; i < getNumExp() ; i++) {
          env.print(",");
        }
        env.print("]");
        getType().CS_emitTypeSuffix(env);
      }
    
      public void StructType.CS_emitType(CS_env env){
        env.print(CS_structName());
      }
    
    }
    
    aspect CS_Signature {
        public void Signature.CS_emitSignature(CS_env env, boolean decl){
     
          SignatureList sl = getSignatureList();
          sl.CS_emitSignature(env, decl);
        }
    
        public abstract void SignatureLine.CS_emitSignature(CS_env env, boolean decl);
    
        public void TypeRefSignatureLine.CS_emitSignature(CS_env env, boolean isDecl){
          env.print(getIndentString());
          env.println("e.encodePacked32(e.getTypeId( typeof("+decl.getName()+")));");
        }
    
        public void DataSignatureLine.CS_emitSignature(CS_env env, boolean decl){
            byte[] data = getData(env.version);
              if (data != null) {
                  env.print(getIndentString());
                  for (int j = 0 ; j < data.length ; j++) {
                      //env.print("e.encodeByte((byte)"+data[j]+");");
                      env.print("e.encodeByte((byte)"+ String.format("0x%02X ", data[j]) +"); ");
                  }
                  env.println();
              }
      }
        public void SignatureList.CS_emitSignature(CS_env env, boolean decl) {
          env.println("private static void emitSignature(Encoder e){");
          env.indent();
          for (int i = 0 ; i < size() ; i++) {
            String comment = getComment(i);
            if (comment != null && comment.length() > 0) {
                env.println(getIndent(i) + "// " + comment);
            }
            SignatureLine l = getSignatureLine(i);
            l.CS_emitSignature(env, decl);
          }
          env.println("}");
          env.unindent();
      }
    
    }
    
    aspect CS_Info {
    
      public void Program.CS_info(PrintStream out, String namespace, int version) {
        CS_env env = new CS_env(out, version);
        if (namespace == null) {
          namespace = ""; 
        } else {
          namespace = namespace + "."; 
        }
        for (int i = 0; i < getNumDecl(); i++) {
          getDecl(i).CS_info(env, namespace);
        }
      }
    
      public void Decl.CS_info(CS_env env, String namespace) {
        throw new Error(this.getClass().getName() + 
    		    ".CS_info(CS_env env)" + 
    		    " not declared");
      }
    
      public void TypeDecl.CS_info(CS_env env, String namespace) {
        env.print(";C#;typedef;" + namespace + getName() + ";");
        getType().CS_emitType(env) ;
        env.print(";not_applicable_for_C#");
        env.println();
      }
    
      public void SampleDecl.CS_info(CS_env env, String namespace) {
        env.print(";C#;sample;" + namespace + getName() + ";");
        getType().CS_emitType(env);
        env.print(";not_applicable_for_C#");
        env.println();
      }
    
    }