import java.io.*; import java.util.*; aspect Java_CodeGenEnv { // Environment wrapper for Java-code generation // handles indentation, file writing, public class Java_env { private int indent; private int depth; private Java_printer printer; private HashMap unique = new HashMap(); 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; } 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 indent, Java_printer printer) { this.indent = indent; this.printer = printer; } public Java_env(File f) { this.indent = 0; this.printer = new Java_printer(f); } public Java_env(PrintStream out) { this.indent = 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 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 Type.isVoid() = false; syn boolean VoidType.isVoid() = true; } aspect Java_CodeGen { public void Program.J_gen(String dir, String pack) throws IOException { Java_env env; /* // Registration class env = new Java_env(new File(dir, "LabCommRegister.java")); if (pack != null && pack.length() > 0) { env.println("package " + pack + ";"); } env.println("public class LabCommRegister {"); env.println(); env.indent(); Java_emitTypeRegister(env); env.unindent(); env.println(); env.println("}"); env.close(); */ for (int i = 0; i < getNumDecl(); i++) { Decl d = getDecl(i); try { env = new Java_env(new File(dir, d.getName() + ".java")); d.Java_emitClass(env, pack); env.close(); } catch (Error e) { System.err.println(d.getName()); throw e; } } } } aspect Java_Register { public void Program.Java_emitTypeRegister(Java_env env) { /* env.println("static void register(LabCommChannel c) {"); env.indent(); for (int i = 0; i < getNumDecl(); i++) { getDecl(i).Java_emitTypeRegister(env); } env.unindent(); env.println("}"); */ } public void Decl.Java_emitTypeRegister(Java_env env) { throw new Error(this.getClass().getName() + ".Java_emitTypeRegister(Java_env env)" + " not declared"); } public void SampleDecl.Java_emitTypeRegister(Java_env env) { env.println(getName() + ".register(c);"); } public void TypeDecl.Java_emitTypeRegister(Java_env env) { // TODO } } 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 TypeDecl.Java_emitClass(Java_env env, String pack) { if (getType().Java_needInstance()) { // Hackish prettyprint preamble env.println("/* "); pp(env.getPrintStream()); env.println("*/"); if (pack != null && pack.length() > 0) { env.println("package " + pack + ";"); } env.println("import java.io.IOException;"); env.println("import se.lth.control.labcomm.LabCommType;"); env.println("import se.lth.control.labcomm.LabCommEncoder;"); env.println("import se.lth.control.labcomm.LabCommDecoder;"); env.println(); env.println("public class " + getName() + " implements LabCommType {"); env.println(); env.indent(); getType().Java_emitInstance(env); Java_emitEncoder(env); Java_emitDecoder(env); env.unindent(); env.println("}"); } } public void SampleDecl.Java_emitClass(Java_env env, String pack) { env.println("/* "); pp(env.getPrintStream()); env.println("*/"); if (pack != null && pack.length() > 0) { env.println("package " + pack + ";"); } env.println("import java.io.IOException;"); env.println("import se.lth.control.labcomm.LabCommDecoder;"); env.println("import se.lth.control.labcomm.LabCommDispatcher;"); env.println("import se.lth.control.labcomm.LabCommEncoder;"); env.println("import se.lth.control.labcomm.LabCommHandler;"); env.println("import se.lth.control.labcomm.LabCommSample;"); env.println(); env.println("public class " + getName() + " implements LabCommSample {"); env.println(); env.indent(); getType().Java_emitInstance(env); env.println("public interface Handler extends LabCommHandler {"); 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(LabCommDecoder d, Handler h) throws IOException {"); env.indent(); env.println("d.register(new Dispatcher(), h);"); env.unindent(); env.println("}"); env.println(); env.println("public static void register(LabCommEncoder e) throws IOException {"); env.indent(); env.println("e.register(new Dispatcher());"); env.unindent(); env.println("}"); env.println(); env.println("private static class Dispatcher implements LabCommDispatcher {"); env.indent(); env.println(); env.println("public Class 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[] getSignature() {"); env.indent(); env.println("return signature;"); env.unindent(); env.println("}"); env.println(); env.println("public void decodeAndHandle(LabCommDecoder d,"); env.println(" LabCommHandler h) throws Exception {"); env.indent(); if (isVoid()) { env.println(getName() + ".decode(d);"); env.println("((Handler)h).handle_" + getName() + "();"); } else { env.println("((Handler)h).handle_" + getName() + "(" + getName() + ".decode(d));"); } env.unindent(); env.println("}"); env.println(""); env.unindent(); env.println("}"); env.println(""); Java_emitEncoder(env); Java_emitDecoder(env); env.println("private static byte[] signature = new byte[] {"); env.indent(); SignatureList signature = signature(); 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); 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(); env.println("}"); } public void TypeDecl.Java_emitEncoder(Java_env env) { env.print("public static void encode(LabCommEncoder 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(LabCommEncoder 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.println("{"); env.indent(); 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.unindent(); env.println("}"); } 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.encodeInt(" + 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(LabCommDecoder 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.decodeInt()"); } 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 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_Info { public void Program.Java_info(PrintStream out) { Java_env env = new Java_env(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.println(); } public void SampleDecl.Java_info(Java_env env) { env.print("Java,sample," + getName() + ","); getType().Java_emitType(env); env.println(); } }