Skip to content
Snippets Groups Projects
Forked from Anders Blomdell / LabComm
598 commits behind the upstream repository.
CS_CodeGen.jrag 20.15 KiB
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;
        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) {
      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 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 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.print_block_begin();
      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.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();
  }

}