Skip to content
Snippets Groups Projects
Select Git revision
  • 59a4985519ce3100226928f163b7d5e3497a3591
  • master default
  • labcomm2006
  • typedefs
  • anders.blomdell
  • typeref
  • pragma
  • compiler-refactoring
  • labcomm2013
  • v2014.4
  • v2006.0
  • v2014.3
  • v2014.2
  • v2014.1
  • v2014.0
  • v2013.0
16 results

Java_CodeGen.jrag

Blame
  • Forked from Anders Blomdell / LabComm
    Loading
    Java_CodeGen.jrag 30.65 KiB
    import java.io.*;
    import java.util.*;
    
    aspect Java_CodeGenEnv {
    
      // Environment wrapper for Java-code generation
      // handles indentation, file writing,
    
      public class Java_env {
    
        public final int version;  //labcomm version to generate code for
        public final String verStr;
        private int indent;
        private int depth;
        private Java_printer printer;
        private HashMap unique = new HashMap();
    
        public boolean versionHasMetaData() {
          return version != 2006;
        }
    
        final private class Java_printer {
    
          private boolean newline = true;
          private File file;
          private PrintStream out;
          private IOException exception;
    
    
          public Java_printer(File f) {
      	file = f;
            File parentFile = f.getParentFile();
            if(parentFile != null) {
                parentFile.mkdirs();
            }
          }
    
         public Java_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(Java_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(Java_env env, String s) {
    	checkOpen();
            print(env, s);
            out.println();
            newline = true;
          }
        }
    
        private Java_env(int version, int indent) {
          this.version = version;
          this.verStr = (version == 2006) ? "2006" : "";
          this.indent = indent;
        }
    
        private Java_env(int version, Java_printer printer) {
          this(version, 0);
          this.printer = printer;
        }
    
        public Java_env(int version, File f) {
          this(version, 0);
          this.printer = new Java_printer(f);
        }
    
        public Java_env(int version, PrintStream out) {
          this(version, 0);
          this.printer = new Java_printer(out);
        }
    
        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;
        }
    
        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 Java_StructName {
    
      inh int Decl.Java_Depth();
      inh int Type.Java_Depth();
      eq Program.getDecl(int i).Java_Depth() = 0;
      eq StructType.getField(int i).Java_Depth() = Java_Depth() + 1;
    
      inh String Type.Java_structName();
      eq Program.getDecl(int i).Java_structName() = getDecl(i).getName();
      eq StructType.getField(int i).Java_structName() {
        if (Java_Depth() == 0) {
          return "struct_" + getField(i).getName();
        } else {
          return Java_structName() + "_" + getField(i).getName();
        }
      }
    }
    
    aspect Java_Void {
    
      syn boolean Decl.isVoid() = getType().isVoid();
      syn boolean UserType.isVoid() = decl().isVoid();
      syn boolean Type.isVoid() = false;
      syn boolean VoidType.isVoid() = true;
    
    }
    
    aspect Java_CodeGen {
    
      public void Program.J_gen(PrintStream ps, String pack, int version) throws IOException {
        Java_env env;
        env = new Java_env(version, ps);
        for (int i = 0; i < getNumDecl(); i++) {
          Decl d = getDecl(i);
          try {
            d.Java_emitClass(env, pack);
          } catch (Error e) {
    	System.err.println(d.getName());
    	throw e;
          }
        }
        env.close();
      }
    
      public void Program.J_gen(String dir, String pack, int version) throws IOException {
        Java_env env;
        for (int i = 0; i < getNumDecl(); i++) {
          Decl d = getDecl(i);
          try {
            env = new Java_env(version, new File(dir, d.getName() + ".java"));
            d.Java_emitClass(env, pack);
            env.close();
          } catch (Error e) {
    	System.err.println(d.getName());
    	throw e;
          }
        }
      }
    
      /** Experimental method for generating code to a map <classname, source>
        */
      public void Program.J_gen(Map<String,String> src, String pack, int version) throws IOException {
        Java_env env;
        for (int i = 0; i < getNumDecl(); i++) {
          Decl d = getDecl(i);
          try {
            ByteArrayOutputStream bs = new ByteArrayOutputStream();
            PrintStream out = new PrintStream(bs);
            env = new Java_env(version, out);
            d.Java_emitClass(env, pack);
            env.close();
            src.put(d.getName(), bs.toString());
          } catch (Error e) {
    	System.err.println(d.getName());
    	throw e;
          }
        }
      }
    
    }
    
    aspect Java_Class {
    
      public void Decl.Java_emitClass(Java_env env, String pack) {
        throw new Error(this.getClass().getName() +
    		    ".Java_emitClass(Java_env env, String pack)" +
    		    " not declared");
      }
    
      public void Decl.Java_emitDeclPP(Java_env env) {
          // Hackish prettyprint preamble
          env.println("/* ");
          pp(env.getPrintStream());
    
          Java_emitUserTypeDeps(env, null, false);
          Java_emitUserTypeRefs(env, null, false);
          env.println("*/");
    
      }
    
      public void Decl.Java_emitUserTypeDeps(Java_env env, String via, boolean outputCode) {
      // XXX TODO will generate unnecessary recursion for types. fix this per commented out code
      // XXX      but ensure that types with references actually register themselves.. (i.e., add "nested" argument)
      //public abstract void Decl.Java_emitUserTypeDeps(Java_env env, String via, boolean outputCode);
    
      //public void TypeDecl.Java_emitUserTypeDeps(Java_env env, String via, boolean outputCode) {
      //  // do nothing for type decls; sampledecl iterates over all dependencies and outputs
      //  // all type decls
      //}
      //public void SampleDecl.Java_emitUserTypeDeps(Java_env env, String via, boolean outputCode) {
        if(env.versionHasMetaData() && hasDependencies() || isReferenced() ) {
            if(env.versionHasMetaData() && isSampleDecl() && outputCode) {
               env.println("if(sendMetaData){");
               env.indent();
            }
            Iterator<Decl> it = type_dependencies().iterator();
            while(it.hasNext()) {
                Decl t = it.next();
    
                t.Java_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() + " (" + t +") " );
    	       //env.println(" //Depends ("+refpath+") on "+t.getName() );
    	       env.println(" //Depends ("+refpath+") on "+t.getName()+" -- "+t.getType() );
                }
            }
            if(env.versionHasMetaData() && isSampleDecl() && outputCode) {
               env.unindent();
               env.println("}");
            }
        }
      }
      public void Decl.Java_emitUserTypeRefs(Java_env env, String via, boolean outputCode) {
        if( isReferenced() ) {
            Iterator<Decl> it = type_references().iterator();
            while(it.hasNext()) {
                Decl t = it.next();
    
                t.Java_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.Java_emitRegisterEncoder(Java_env env) {
        env.println("public static void register(Encoder e) throws IOException {");
        env.indent();
        env.println("register(e, true);");
        env.unindent();
        env.println("}");
    
        env.println();
        env.println("public static void register(Encoder e, boolean sendMetaData) throws IOException {");
        env.indent();
    
        Java_emitUserTypeDeps(env, null, true);
        if(env.versionHasMetaData()) {
            env.println("e.register(Dispatcher.singleton());");
        } else {
            env.println("e.register(Dispatcher.singleton());");
        }
        env.unindent();
        env.println("}");
        env.println();
      }
    
      public void TypeDecl.Java_emitClass(Java_env env, String pack) {
          Java_emitDeclPP(env);
          if (pack != null && pack.length() > 0) {
              env.println("package " + pack + ";");
          }
    
          env.println("import se.lth.control.labcomm"+env.verStr+".Constant;");
          env.println("import se.lth.control.labcomm"+env.verStr+".SampleType;");
    
          if (getType().Java_needInstance() || hasDependencies() || isReferenced()) {
              env.println("import se.lth.control.labcomm"+env.verStr+".Encoder;");
              env.println("import se.lth.control.labcomm"+env.verStr+".SampleDispatcher;");
              env.println("import se.lth.control.labcomm"+env.verStr+".SampleHandler;");
    //          env.println();
    //      }
    //
    //      if (getType().Java_needInstance()) {
              env.println("import java.io.IOException;");
              env.println("import se.lth.control.labcomm"+env.verStr+".Decoder;");
          }
          // For types without type_dependencies and not needing an instance,
          // currently just an empty class is generated
    
          env.println("public class " + getName() + " implements SampleType {");
          env.println();
    
          env.indent();
          if (getType().Java_needInstance()) {
            getType().Java_emitInstance(env);
            Java_emitEncoder(env);
            Java_emitDecoder(env);
          }
    
          //if(hasDependencies() || isReferenced()) {
          //if( getType().isUserType() && isReferenced()) {
          if( isReferenced()) {
            Java_emitRegisterEncoder(env);
            Java_emitDispatcher(env, false);
          }
          Java_emitSignature(env);
    
          env.println("}");
          env.unindent();
          env.println();
      }
    
    
      public void SampleDecl.Java_emitClass(Java_env env, String pack) {
        Java_emitDeclPP(env);
    
        if (pack != null && pack.length() > 0) {
          env.println("package " + pack + ";");
        }
    
        env.println("import java.io.IOException;");
        env.println("import se.lth.control.labcomm"+env.verStr+".Constant;");
        env.println("import se.lth.control.labcomm"+env.verStr+".Decoder;");
        env.println("import se.lth.control.labcomm"+env.verStr+".SampleDispatcher;");
        env.println("import se.lth.control.labcomm"+env.verStr+".Encoder;");
        env.println("import se.lth.control.labcomm"+env.verStr+".SampleHandler;");
        env.println("import se.lth.control.labcomm"+env.verStr+".Sample;");
        env.println();
        env.print("public class " + getName());
    //  TODO: ?
    //  Code for making samples of user types extend their type
    //  currently commented out. Is this a good idea or not?
    //
    //    if(getType().isUserType()) {
    //        env.print(" extends "+getType().getTypeName());
    //    }
        env.println(" implements Sample {");
        env.println();
        env.indent();
        getType().Java_emitInstance(env);
        env.println("public interface Handler extends SampleHandler {");
        env.print("  public void handle_" + getName() + "(");
        if (!isVoid()) {
          getType().Java_emitType(env);
          env.print(" value");
        }
        env.println(") throws Exception;");
        env.println("}");
        env.println();
        env.println("public static void register(Decoder d, Handler h) throws IOException {");
        env.indent();
        env.println("d.register(Dispatcher.singleton(), h);");
        env.unindent();
        env.println("}");
        env.println();
    
    
        Java_emitRegisterEncoder(env);
        Java_emitDispatcher(env, true);
        Java_emitEncoder(env);
        Java_emitDecoder(env);
    
        Java_emitSignature(env);
        env.unindent();
        env.println("}");
        env.println();
      }
    
      //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
        //for matching at the decoder side (which cannot know
        //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());
        //}
      }
    
      public void Decl.Java_emitFlatSignature(Java_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.println();
          }
        }
        env.unindent();
        env.println("};");
        env.unindent();
        env.println();
      }
    
      //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();
        env.println("public synchronized static Dispatcher singleton() {");
        env.indent();
        env.println("if(singleton==null) singleton=new Dispatcher();");
        env.println("return singleton;");
        env.unindent();
        env.println("}");
        env.println();
        env.println("public Class"+genericStr+" getSampleClass() {");
        env.indent();
        env.println("return " + getName() + ".class;");
        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(env.version == 2006) {
          if(isSample) {
            env.println("return Constant.SAMPLE;");
          } else {
            env.println("return Constant.TYPEDEF;");
          }
        } else {
          if(isSample) {
            env.println("return Constant.SAMPLE_DEF;");
          } else {
            env.println("return Constant.TYPE_DEF;");
          }
        }
        env.unindent();
        env.println("}");
        env.println();
        env.println("public boolean isSample() {");
        env.indent();
        env.println("return "+isSample+";");
        env.unindent();
        env.println("}");
        env.println("public boolean hasStaticSignature() {");
        env.indent();
        env.println("return "+!hasDependencies()+";");
        env.unindent();
        env.println("}");
        env.println();
        env.println("/** return the flat signature. Intended use is on decoder side */");
        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) 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 boolean canDecodeAndHandle() {");
        env.indent();
        env.println("return "+isSample+";");
        env.unindent();
        env.println("}");
        env.println();
        env.println("public void decodeAndHandle(Decoder d,");
        env.println("                            SampleHandler h) throws Exception {");
        env.indent();
        if( isSample) {
            if (isVoid()) {
              env.println(getName() + ".decode(d);");
              env.println("((Handler)h).handle_" + getName() + "();");
            } else {
              env.println("((Handler)h).handle_" + getName() + "(" + 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("");
    
     }
    
    
      public void TypeDecl.Java_emitEncoder(Java_env env) {
        env.print("public static void encode(Encoder e");
        if (!isVoid()) {
          env.print(", ");
          getType().Java_emitType(env);
          env.print(" value");
        }
        env.println(") throws IOException {");
        env.indent();
        getType().Java_emitEncoder(env, "value");
        env.unindent();
        env.println("}");
        env.println();
      }
    
      public void SampleDecl.Java_emitEncoder(Java_env env) {
        env.print("public static void encode(Encoder e");
        if (!isVoid()) {
          env.print(", ");
          getType().Java_emitType(env);
          env.print(" value");
        }
        env.println(") throws IOException {");
        env.indent();
        env.println("e.begin(" + getName() + ".class);");
        getType().Java_emitEncoder(env, "value");
        env.println("e.end(" + getName() + ".class);");
        env.unindent();
        env.println("}");
        env.println();
      }
    
      public void Type.Java_emitEncoder(Java_env env, String name) {
        throw new Error(this.getClass().getName() +
    		    ".Java_emitEncoder(Java_env env, String name)" +
    		    " not declared");
      }
    
      public void VoidType.Java_emitEncoder(Java_env env, String name) {
      }
    
      public void PrimType.Java_emitEncoder(Java_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;
        }
        env.println("(" + name + ");");
      }
    
      public void ArrayType.Java_emitEncoder(Java_env env, String name) {
        int baseDepth = env.getDepth();
        String prefix = "";
        for (int i = 0 ; i < getNumExp() ; i++) {
          String limit = getExp(i).Java_emitEncoder(env, name + prefix);
          env.print_block_begin();
          env.println("int i_" + (baseDepth + i) + "_max = " + limit + ";");
          prefix = prefix + "[0]";
        }
        for (int i = 0 ; i < getNumExp() ; i++) {
          String limit = "i_" + (baseDepth + i) + "_max";
          name = name + env.print_for_begin(limit);
        }
        getType().Java_emitEncoder(env, name);
        for (int i = 0 ; i < getNumExp() ; i++) {
          env.print_for_end();
          env.print_block_end();
        }
      }
    
      public String Exp.Java_emitEncoder(Java_env env, String name) {
        throw new Error(this.getClass().getName() +
    		    ".Java_emitEncoder(Java_env env, String name)" +
    		    " not declared");
      }
    
      public String IntegerLiteral.Java_emitEncoder(Java_env env, String name) {
        return getValue();
      }
    
      public String VariableSize.Java_emitEncoder(Java_env env, String name) {
        env.println("e.encodePacked32(" + name + ".length);");
        return name + ".length";
      }
    
      public void StructType.Java_emitEncoder(Java_env env, String name) {
        for (int i = 0 ; i < getNumField() ; i++) {
          Field f = getField(i);
          f.getType().Java_emitEncoder(env, name + "." + f.getName());
        }
      }
    
      public void UserType.Java_emitEncoder(Java_env env, String name) {
        if (Java_needInstance()) {
          env.println(getName() + ".encode(e, " + name + ");");
        } else {
          decl().getType().Java_emitEncoder(env, name);
        }
      }
    
      public void Decl.Java_emitDecoder(Java_env env) {
        env.print("public static ");
        getType().Java_emitType(env);
        env.println(" decode(Decoder d) throws IOException {");
        env.indent();
        if (!isVoid()) {
          getType().Java_emitType(env);
          env.println(" result;");
          getType().Java_emitDecoder(env, "result");
          env.println("return result;");
        }
        env.unindent();
        env.println("}");
        env.println();
      }
    
      public void Type.Java_emitDecoder(Java_env env, String name) {
        throw new Error(this.getClass().getName() +
    		    ".Java_emitDecoder(Java_env env, String name)" +
    		    " not declared");
      }
    
      public void VoidType.Java_emitDecoder(Java_env env, String name) {
      }
    
      public void PrimType.Java_emitDecoder(Java_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;
        }
      }
    
      public void ArrayType.Java_emitDecoder(Java_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).Java_emitDecoder(env);
          env.println(";");
        }
        for (int i = 0 ; i < getNumExp() ; i++) {
          String limit = "i_" + (baseDepth + i) + "_max";
          env.print(name + " = ");
          Java_emitNew(env, limit, getNumExp() - i);
          env.println(";");
          name = name + env.print_for_begin(limit);
        }
        getType().Java_emitDecoder(env, name);
        for (int i = 0 ; i < getNumExp() ; i++) {
          env.print_for_end();
        }
        env.unindent();
        env.println("}");
      }
    
      public void Exp.Java_emitDecoder(Java_env env) {
        throw new Error(this.getClass().getName() +
    		    ".Java_emitDecoder(Java_env env)" +
    		    " not declared");
      }
    
      public void IntegerLiteral.Java_emitDecoder(Java_env env) {
        env.print(getValue());
      }
    
      public void VariableSize.Java_emitDecoder(Java_env env) {
        env.print("d.decodePacked32()");
      }
    
      public void StructType.Java_emitDecoder(Java_env env, String name) {
        env.print(name + " = new ");
        Java_emitType(env);
        env.println("();");
        for (int i = 0 ; i < getNumField() ; i++) {
          Field f = getField(i);
          f.getType().Java_emitDecoder(env, name + "." + f.getName());
        }
      }
    
      public void UserType.Java_emitDecoder(Java_env env, String name) {
        if (Java_needInstance()) {
          env.println(name + " = " + getName() + ".decode(d);");
        } else {
          decl().getType().Java_emitDecoder(env, name);
        }
      }
    
      public void Type.Java_emitNew(Java_env env, String size) {
        throw new Error(this.getClass().getName() +
    		    ".Java_emitNew(Java_env env, String size)" +
    		    " not declared");
      }
    
      public void ArrayType.Java_emitNew(Java_env env, String size, int depth) {
        env.print("new ");
        getType().Java_emitTypePrefix(env);
        env.print("[" + size + "]");
        getType().Java_emitTypeSuffix(env);
        for (int i = 1 ; i < depth ; i++) {
          env.print("[]");
        }
      }
    
      public void Type.Java_emitTypePrefix(Java_env env) {
        throw new Error(this.getClass().getName() +
    		    ".Java_emitTypePrefix(Java_env env)" +
    		    " not declared");
      }
    
      public void PrimType.Java_emitTypePrefix(Java_env env) {
        switch (getToken()) {
          case LABCOMM_STRING: { env.print("String"); } break;
          default: { env.print(getName()); } break;
        }
      }
    
      public void UserType.Java_emitTypePrefix(Java_env env) {
        if (Java_needInstance()) {
          env.print(getName());
        } else {
          decl().getType().Java_emitTypePrefix(env);
        }
      }
    
      public void ArrayType.Java_emitTypePrefix(Java_env env){
        getType().Java_emitTypePrefix(env);
      }
    
      public void StructType.Java_emitTypePrefix(Java_env env){
        env.print(Java_structName());
      }
    
      public void Type.Java_emitTypeSuffix(Java_env env) {
      }
    
      public void UserType.Java_emitTypeSuffix(Java_env env) {
        if (! Java_needInstance()) {
          decl().getType().Java_emitTypeSuffix(env);
        }
      }
    
      public void ArrayType.Java_emitTypeSuffix(Java_env env){
        getType().Java_emitTypeSuffix(env);
        for (int i = 0 ; i < getNumExp() ; i++) {
          env.print("[]");
        }
      }
    
      public boolean Type.Java_needInstance() {
        throw new Error(this.getClass().getName() +
    		    ".Java_needInstance()" +
    		    " not declared");
      }
    
      public boolean VoidType.Java_needInstance() {
        return false;
      }
    
      public boolean PrimType.Java_needInstance() {
        return false;
      }
    
      public boolean UserType.Java_needInstance() {
        return decl().getType().Java_needInstance();
      }
    
      public boolean StructType.Java_needInstance() {
        return true;
      }
    
      public boolean ArrayType.Java_needInstance() {
        return getType().Java_needInstance();
      }
    
      public boolean Type.Java_isPrimitive() {
        return false;
      }
    
      public boolean PrimType.Java_isPrimitive() {
        return true;
      }
    
      public void Type.Java_emitInstance(Java_env env) {
        throw new Error(this.getClass().getName() +
    		    ".Java_emitInstance(Java_env env)" +
    		    " not declared");
      }
    
      public void VoidType.Java_emitInstance(Java_env env) {
      }
    
      public void PrimType.Java_emitInstance(Java_env env) {
      }
    
      public void ArrayType.Java_emitInstance(Java_env env) {
        getType().Java_emitInstance(env);
      }
    
      public void StructType.Java_emitInstance(Java_env env) {
        if (Java_Depth() > 0) {
          env.println("public static class " + Java_structName() + " {");
          env.indent();
        }
        for (int i = 0 ; i < getNumField() ; i++) {
          getField(i).getType().Java_emitInstance(env);
        }
        for (int i = 0 ; i < getNumField() ; i++) {
          getField(i).Java_emitField(env);
        }
        if (Java_Depth() > 0) {
          env.unindent();
          env.println("}");
        }
        env.println();
      }
    
      public void UserType.Java_emitInstance(Java_env env) {
      }
    
      public void Field.Java_emitField(Java_env env) {
        env.print("public ");
        getType().Java_emitType(env);
        env.println(" " + getName() + ";");
      }
    
      public void Type.Java_emitType(Java_env env) {
        throw new Error(this.getClass().getName() +
    		    ".Java_emitType(Java_env env)" +
    		    " not declared");
      }
    
      public void VoidType.Java_emitType(Java_env env) {
        env.print("void");
      }
    
      public void PrimType.Java_emitType(Java_env env) {
        switch (getToken()) {
          case LABCOMM_STRING: { env.print("String"); } break;
          default: { env.print(getName()); } break;
        }
      }
    
      public void UserType.Java_emitType(Java_env env) {
        decl().getType().Java_emitType(env);
      }
    
      public void ArrayType.Java_emitType(Java_env env){
        getType().Java_emitType(env);
        for (int i = 0 ; i < getNumExp() ; i++) {
          env.print("[]");
        }
      }
    
      public void StructType.Java_emitType(Java_env env){
        env.print(Java_structName());
      }
    }
    
    aspect Java_Signature {
        public void Signature.Java_emitSignature(Java_env env, boolean decl){
          // XXX should sendOnlyFlatSignatures be kept somewhere?
          //SignatureList sl = (parentDecl().sendOnlyFlatSignatures(env)) ? getFlatSignatureList() : getSignatureList();
          SignatureList sl = getSignatureList();
          sl.Java_emitSignature(env, decl);
        }
    
    //    public void Signature.Java_emitHierarchicalSignature(Java_env env, boolean decl){
    //      SignatureList sl = getSignatureList();
    //      sl.Java_emitSignature(env, decl);
    //    }
    //
        public abstract void SignatureLine.Java_emitSignature(Java_env env, boolean decl);
    
        public void TypeRefSignatureLine.Java_emitSignature(Java_env env, boolean isDecl){
          env.print(getIndentString());
          env.println("e.encodePacked32(e.getTypeId("+decl.getName()+".class));");
        }
    
        public void DataSignatureLine.Java_emitSignature(Java_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.Java_emitSignature(Java_env env, boolean decl) {
          env.println("private static void emitSignature(Encoder e) throws IOException{");
          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.Java_emitSignature(env, decl);
          }
          env.println("}");
          env.unindent();
      }
    
    }
    
    aspect Java_Info {
    
      public void Program.Java_info(PrintStream out, int version) {
        Java_env env = new Java_env(version, out);
        for (int i = 0; i < getNumDecl(); i++) {
          getDecl(i).Java_info(env);
        }
      }
    
      public void Decl.Java_info(Java_env env) {
        throw new Error(this.getClass().getName() +
    		    ".Java_info(Java_env env)" +
    		    " not declared");
      }
    
      public void TypeDecl.Java_info(Java_env env) {
        env.print(",Java,typedef," + getName() + ",");
        getType().Java_emitType(env);
        env.print(",not_applicable_for_Java");
        env.println();
      }
    
      public void SampleDecl.Java_info(Java_env env) {
        env.print(",Java,sample," + getName() + ",");
        getType().Java_emitType(env);
        env.print(",not_applicable_for_Java");
        env.println();
      }
    
    }