import java.io.*; import java.util.*; aspect CS_CodeGenEnv { // Environment wrapper for CS-code generation // handles indentation, file writing, public class CS_env { private int indent; private int depth; private CS_printer printer; private HashMap unique = new HashMap(); final private class CS_printer { private boolean newline = true; private File file; private PrintStream out; private IOException exception; public CS_printer(File f) { file = f; } 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) { this.indent = indent; this.printer = printer; } public CS_env(File f) { this.indent = 0; this.printer = new CS_printer(f); } public CS_env(PrintStream out) { this.indent = 0; this.printer = new CS_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 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 Type.CS_isVoid() = false; syn boolean VoidType.CS_isVoid() = true; } aspect CS_CodeGen { public void Program.CS_gen(String file, String namespace) throws IOException { // Registration class CS_env env = new CS_env(new File(file)); 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) { /* env.println("static void register(LabCommChannel c) {"); env.indent(); for (int i = 0; i < getNumDecl(); i++) { getDecl(i).CS_emitTypeRegister(env); } env.unindent(); env.println("}"); */ } 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 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() + " : LabCommType {"); env.println(); env.indent(); getType().CS_emitInstance(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() + " : LabCommSample {"); env.println(); env.indent(); getType().CS_emitInstance(env); env.println("public interface Handler : LabCommHandler {"); env.print(" void handle("); if (!isVoid()) { getType().CS_emitType(env); env.print(" value"); } env.println(");"); env.println("}"); env.println(); env.println("public static void register(LabCommDecoder d, Handler h) {"); env.indent(); env.println("d.register(new Dispatcher(), h);"); env.unindent(); env.println("}"); env.println(); env.println("public static void register(LabCommEncoder e) {"); env.indent(); env.println("e.register(new Dispatcher());"); env.unindent(); env.println("}"); env.println(); env.println("private class Dispatcher : LabCommDispatcher {"); 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[] getSignature() {"); env.indent(); env.println("return signature;"); env.unindent(); env.println("}"); env.println(); env.println("public void decodeAndHandle(LabCommDecoder d, LabCommHandler h) {"); env.indent(); if (isVoid()) { env.println(getName() + ".decode(d);"); env.println("((Handler)h).handle();"); } else { env.println("((Handler)h).handle(" + getName() + ".decode(d));"); } env.unindent(); env.println("}"); env.println(""); env.unindent(); env.println("}"); env.println(""); CS_emitEncoder(env); CS_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.CS_emitEncoder(CS_env env) { env.print("public static void encode(LabCommEncoder 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(LabCommEncoder 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; } env.println("(" + name + ");"); } public void ArrayType.CS_emitEncoder(CS_env env, String name) { int baseDepth = env.getDepth(); for (int i = 0 ; i < getNumExp() ; i++) { String limit = getExp(i).CS_emitEncoder(env, name + ".GetLength(" + i + ")"); env.println("{"); env.indent(); 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.unindent(); env.println("}"); } 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.encodeInt(" + 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(LabCommDecoder 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; } } 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.println("]"); 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.decodeInt()"); } 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_emitNew(CS_env env, String size) { throw new Error(this.getClass().getName() + ".CS_emitNew(CS_env env, String size)" + " not declared"); } public void ArrayType.CS_emitNew(CS_env env, String size, int depth) { env.print("new "); getType().CS_emitTypePrefix(env); env.print("[" + size + "]"); getType().CS_emitTypeSuffix(env); for (int i = 1 ; i < depth ; i++) { env.print("[]"); } } 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; 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){ getType().CS_emitTypeSuffix(env); env.print("["); for (int i = 1 ; i < getNumExp() ; i++) { env.print(","); } env.print("]"); } public boolean Type.CS_needInstance() { throw new Error(this.getClass().getName() + ".CS_needInstance()" + " not declared"); } 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 static 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; 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_emitType(env); env.print("["); for (int i = 1 ; i < getNumExp() ; i++) { env.print(","); } env.print("]"); } public void StructType.CS_emitType(CS_env env){ env.print(CS_structName()); } } aspect CS_Info { public void Program.CS_info(PrintStream out, String namespace) { CS_env env = new CS_env(out); 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.println(); } public void SampleDecl.CS_info(CS_env env, String namespace) { env.print("C#,sample," + namespace + getName() + ","); getType().CS_emitType(env); env.println(); } }