From 095f296a3eb9c0776258075b1067170360de2e97 Mon Sep 17 00:00:00 2001 From: Anders Blomdell <anders.blomdell@control.lth.se> Date: Tue, 25 Nov 2014 18:03:17 +0100 Subject: [PATCH] First stab at separating compiler for different versions --- .gitignore | 1 + compiler/{ => 2006}/ArrayTypeRewrite.jrag | 0 compiler/{ => 2006}/CS_CodeGen.jrag | 0 compiler/{ => 2006}/C_CodeGen.jrag | 0 compiler/{ => 2006}/DeclNames.jrag | 0 compiler/{ => 2006}/ErrorCheck.jrag | 0 compiler/{ => 2006}/FlatSignature.jrag | 0 compiler/{ => 2006}/Java_CodeGen.jrag | 0 compiler/{ => 2006}/LabComm.ast | 0 compiler/2006/LabComm.java | 404 +++++ compiler/{ => 2006}/LabCommParser.parser | 3 +- compiler/{ => 2006}/LabCommScanner.flex | 4 +- compiler/{ => 2006}/LabCommTokens.jrag | 0 compiler/{ => 2006}/NameAnalysis.jrag | 0 compiler/{ => 2006}/PrettyPrint.jrag | 0 compiler/{ => 2006}/Python_CodeGen.jrag | 0 compiler/{ => 2006}/RAPID_CodeGen.jrag | 0 compiler/{ => 2006}/Signature.jrag | 2 +- compiler/{ => 2006}/TypeCheck.jrag | 0 compiler/{ => 2006}/TypeReferences.jrag | 0 compiler/{ => 2006}/Version.jrag | 0 compiler/2014/ArrayTypeRewrite.jrag | 43 + compiler/2014/CS_CodeGen.jrag | 971 ++++++++++++ compiler/2014/C_CodeGen.jrag | 1694 +++++++++++++++++++++ compiler/2014/DeclNames.jrag | 14 + compiler/2014/ErrorCheck.jrag | 31 + compiler/2014/FlatSignature.jrag | 123 ++ compiler/2014/Java_CodeGen.jrag | 1056 +++++++++++++ compiler/2014/LabComm.ast | 39 + compiler/2014/LabComm.java | 404 +++++ compiler/2014/LabCommParser.parser | 133 ++ compiler/2014/LabCommScanner.flex | 87 ++ compiler/2014/LabCommTokens.jrag | 21 + compiler/2014/NameAnalysis.jrag | 67 + compiler/2014/PrettyPrint.jrag | 117 ++ compiler/2014/Python_CodeGen.jrag | 232 +++ compiler/2014/RAPID_CodeGen.jrag | 369 +++++ compiler/2014/Signature.jrag | 236 +++ compiler/2014/TypeCheck.jrag | 36 + compiler/2014/TypeReferences.jrag | 46 + compiler/2014/Version.jrag | 15 + compiler/LabComm.java | 417 +---- compiler/build.xml | 135 +- compiler/cs_codegen.patch | 34 - compiler/java_array_encode.patch | 24 - 45 files changed, 6260 insertions(+), 498 deletions(-) rename compiler/{ => 2006}/ArrayTypeRewrite.jrag (100%) rename compiler/{ => 2006}/CS_CodeGen.jrag (100%) rename compiler/{ => 2006}/C_CodeGen.jrag (100%) rename compiler/{ => 2006}/DeclNames.jrag (100%) rename compiler/{ => 2006}/ErrorCheck.jrag (100%) rename compiler/{ => 2006}/FlatSignature.jrag (100%) rename compiler/{ => 2006}/Java_CodeGen.jrag (100%) rename compiler/{ => 2006}/LabComm.ast (100%) create mode 100644 compiler/2006/LabComm.java rename compiler/{ => 2006}/LabCommParser.parser (97%) rename compiler/{ => 2006}/LabCommScanner.flex (96%) rename compiler/{ => 2006}/LabCommTokens.jrag (100%) rename compiler/{ => 2006}/NameAnalysis.jrag (100%) rename compiler/{ => 2006}/PrettyPrint.jrag (100%) rename compiler/{ => 2006}/Python_CodeGen.jrag (100%) rename compiler/{ => 2006}/RAPID_CodeGen.jrag (100%) rename compiler/{ => 2006}/Signature.jrag (99%) rename compiler/{ => 2006}/TypeCheck.jrag (100%) rename compiler/{ => 2006}/TypeReferences.jrag (100%) rename compiler/{ => 2006}/Version.jrag (100%) create mode 100644 compiler/2014/ArrayTypeRewrite.jrag create mode 100644 compiler/2014/CS_CodeGen.jrag create mode 100644 compiler/2014/C_CodeGen.jrag create mode 100644 compiler/2014/DeclNames.jrag create mode 100644 compiler/2014/ErrorCheck.jrag create mode 100644 compiler/2014/FlatSignature.jrag create mode 100644 compiler/2014/Java_CodeGen.jrag create mode 100644 compiler/2014/LabComm.ast create mode 100644 compiler/2014/LabComm.java create mode 100644 compiler/2014/LabCommParser.parser create mode 100644 compiler/2014/LabCommScanner.flex create mode 100644 compiler/2014/LabCommTokens.jrag create mode 100644 compiler/2014/NameAnalysis.jrag create mode 100644 compiler/2014/PrettyPrint.jrag create mode 100644 compiler/2014/Python_CodeGen.jrag create mode 100644 compiler/2014/RAPID_CodeGen.jrag create mode 100644 compiler/2014/Signature.jrag create mode 100644 compiler/2014/TypeCheck.jrag create mode 100644 compiler/2014/TypeReferences.jrag create mode 100644 compiler/2014/Version.jrag delete mode 100644 compiler/cs_codegen.patch delete mode 100644 compiler/java_array_encode.patch diff --git a/.gitignore b/.gitignore index 19ab6d0..24cebf1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*~ *.class *.o lib/c/liblabcomm.a diff --git a/compiler/ArrayTypeRewrite.jrag b/compiler/2006/ArrayTypeRewrite.jrag similarity index 100% rename from compiler/ArrayTypeRewrite.jrag rename to compiler/2006/ArrayTypeRewrite.jrag diff --git a/compiler/CS_CodeGen.jrag b/compiler/2006/CS_CodeGen.jrag similarity index 100% rename from compiler/CS_CodeGen.jrag rename to compiler/2006/CS_CodeGen.jrag diff --git a/compiler/C_CodeGen.jrag b/compiler/2006/C_CodeGen.jrag similarity index 100% rename from compiler/C_CodeGen.jrag rename to compiler/2006/C_CodeGen.jrag diff --git a/compiler/DeclNames.jrag b/compiler/2006/DeclNames.jrag similarity index 100% rename from compiler/DeclNames.jrag rename to compiler/2006/DeclNames.jrag diff --git a/compiler/ErrorCheck.jrag b/compiler/2006/ErrorCheck.jrag similarity index 100% rename from compiler/ErrorCheck.jrag rename to compiler/2006/ErrorCheck.jrag diff --git a/compiler/FlatSignature.jrag b/compiler/2006/FlatSignature.jrag similarity index 100% rename from compiler/FlatSignature.jrag rename to compiler/2006/FlatSignature.jrag diff --git a/compiler/Java_CodeGen.jrag b/compiler/2006/Java_CodeGen.jrag similarity index 100% rename from compiler/Java_CodeGen.jrag rename to compiler/2006/Java_CodeGen.jrag diff --git a/compiler/LabComm.ast b/compiler/2006/LabComm.ast similarity index 100% rename from compiler/LabComm.ast rename to compiler/2006/LabComm.ast diff --git a/compiler/2006/LabComm.java b/compiler/2006/LabComm.java new file mode 100644 index 0000000..58234a5 --- /dev/null +++ b/compiler/2006/LabComm.java @@ -0,0 +1,404 @@ +package se.lth.control.labcomm2006.compiler; + +import java.io.*; +import java.util.*; + +public class LabComm { + + private static void println(String s) { + System.out.println(s); + } + + private static void print_help() { + println("\n Usage: java -jar labcom.jar [options*] FILE"); + println(""); + println(" --help Shows this help text"); + println(" -v Be verbose"); + println(" --ver=VERSION Generate code for labcomm VERSION (=2006 or 2013)"); + println("[ C options ]"); + println(" -C Generates C/H code in FILE.[ch]"); + println(" --cprefix=PREFIX Prefixes C types with PREFIX"); + println(" --cinclude=FILE Include FILE in generated .c"); + println(" --c=CFILE Generates C code in CFILE"); + println(" --h=HFILE Generates H code in HFILE"); + println("[ C# options]"); + println(" --cs Generates C# code in FILE.cs"); + println(" --cs=CSFILE Generates C# code in CSFILE"); + println(" --csnamespace=NAMESPACE Place C# classes in NAMESPACE"); + println("[ Java options ]"); + println(" --java=JDIR Generates Java files in JDIR"); + println(" --javapackage=PACKAGE Place Java classes in PACKAGE"); + println("[ Python options ]"); + println(" -P Generates Python code in FILE.py"); + println(" --python=PFILE Generates Python code in PFILE"); + println("[ RAPID options ]"); + println(" --rapid Generates RAPID code in FILE.sys"); + println("[ Misc options ]"); + println(" --pretty=PFILE Pretty prints to PFILE"); + println(" --typeinfo=TIFILE Generates typeinfo in TIFILE"); + } + + /** To be cleaned up. + */ + private static void checkVersion(int v) { + if(! (v == 2006 || v == 2013) ) { + System.err.println(" Unknown version: " + v); + System.err.println(" Supported versions: 2006, 2013 "); + System.exit(2); + } + } + + private static void genH(Program p, String hName, + Vector cIncludes, String coreName, String prefix, int ver) { + try { + FileOutputStream f; + PrintStream out; + + f = new FileOutputStream(hName); + out = new PrintStream(f); + p.C_genH(out, cIncludes, coreName, prefix, ver); + out.close(); + } catch (IOException e) { + System.err.println("IOException: " + hName + " " + e); + } + } + + private static void genC(Program p, String cName, + Vector cIncludes, String coreName, String prefix, int ver) { + try { + FileOutputStream f; + PrintStream out; + + f = new FileOutputStream(cName); + out = new PrintStream(f); + p.C_genC(out, cIncludes, coreName, prefix, ver); + out.close(); + } catch (IOException e) { + System.err.println("IOException: " + cName + " " + e); + } + } + + private static void genCS(Program p, String csName, String csNamespace, int ver) { +// throw new Error("C# generation currently disabled"); + try { + p.CS_gen(csName, csNamespace, ver); + } catch (IOException e) { + System.err.println("IOException: " + csName + " " + + csNamespace + " " + e); + } + } + + private static void genJava(Program p, String dirName, String packageName, int ver) { + try { + p.J_gen(dirName, packageName, ver); + } catch (IOException e) { + System.err.println("IOException: " + dirName + " " + + packageName + " " + e); + } + } + + private static void genPython(Program p, String filename, String prefix, int ver) { + try { + FileOutputStream f; + PrintStream out; + + f = new FileOutputStream(filename); + out = new PrintStream(f); + p.Python_gen(out, prefix, ver); + out.close(); + } catch (IOException e) { + System.err.println("IOException: " + filename + " " + e); + } + } + + private static void genRAPID(Program p, String filename, String prefix, int ver) { + try { + p.RAPID_gen(filename, prefix, ver); + } catch (IOException e) { + System.err.println("IOException: " + filename + " " + e); + } + } + + /** Helper class to contain command line options + and their associated behaviour + **/ + private static class Opts { + final String[] args; + String coreName = null; + String prefix = null; + boolean verbose = false; + int ver = 2013; //Version 2013 as default + String cFile = null; + String hFile = null; + Vector cIncludes = new Vector(); + String cPrefix; // gets default value (prefix) in processFilename + String csFile = null; + String csNamespace = null; + String javaDir = null; + String javaPackage = ""; + String pythonFile = null; + String prettyFile = null; + String typeinfoFile = null; + String rapidFile = null; + String fileName = null; + + Opts(String[] args) { + this.args = args; + } + + private static String getCoreName(String s) { + int i = s.lastIndexOf('.'); + return s.substring(0, i > 0 ? i : s.length()); + } + + private static String getFileName(String s) { + return s.substring(s.lastIndexOf('/') + 1, s.length()); + } + + private static String getBaseName(String s) { + s = getFileName(s); + int i = s.lastIndexOf('.'); + return s.substring(0, i > 0 ? i : s.length()); + } + + private static String getPrefix(String s) { + return s.substring(s.lastIndexOf('/') + 1, s.length()); + } + + boolean processFilename(){ + // Scan for first non-option + for (int i = 0 ; i < args.length ; i++) { + if (! args[i].startsWith("-")) { + fileName = args[i]; + break; + } + } + if (fileName != null) { + coreName = getBaseName(fileName); + prefix = getPrefix(coreName); + cPrefix = prefix; + } + return fileName != null; + } + + void processArgs(){ + for (int i = 0 ; i < args.length ; i++) { + if (fileName == null || + args[i].equals("-help") || + args[i].equals("-h") || + args[i].equals("--help")) { + print_help(); + System.exit(0); + } else if (args[i].equals("-v")) { + verbose=true; + } else if (args[i].startsWith("--ver=")) { + ver = Integer.parseInt(args[i].substring(6)); + checkVersion(ver); + } else if (args[i].equals("-C")) { + cFile = coreName + ".c"; + hFile = coreName + ".h"; + } else if (args[i].startsWith("--cinclude=")) { + cIncludes.add(args[i].substring(11)); + } else if (args[i].startsWith("--cprefix=")) { + cPrefix = args[i].substring(10); + } else if (args[i].startsWith("--c=")) { + cFile = args[i].substring(4); + } else if (args[i].startsWith("--h=")) { + hFile = args[i].substring(4); + } else if (args[i].equals("--cs")) { + csFile = coreName + ".cs"; + } else if (args[i].startsWith("--cs=")) { + csFile = args[i].substring(5); + } else if (args[i].startsWith("--csnamespace=")) { + csNamespace = args[i].substring(14); + } else if (args[i].startsWith("--java=")) { + javaDir = args[i].substring(7); + } else if (args[i].startsWith("--javapackage=")) { + javaPackage = args[i].substring(14); + } else if (args[i].equals("-P")) { + pythonFile = coreName + ".py"; + } else if (args[i].startsWith("--python=")) { + pythonFile = args[i].substring(9); + } else if (args[i].startsWith("--pretty=")) { + prettyFile = args[i].substring(9); + } else if (args[i].startsWith("--typeinfo=")) { + typeinfoFile = args[i].substring(11); + } else if (args[i].equals("--rapid")) { + rapidFile = coreName + ".sys"; + } else if (i == args.length - 1) { + fileName = args[i]; + } else { + System.err.println(" Unknown argument " + args[i]); + print_help(); + System.exit(2); + } + } + if(prefix==null){ + System.err.println(" WARNING! prefix==null"); + prefix=""; + } + } + + Program parseFile(){ + Program ast = null; + try { + // Check for errors + LabCommScanner scanner = new LabCommScanner( + new FileReader(fileName)); + LabCommParser parser = new LabCommParser(); + Program p = (Program)parser.parse(scanner); + Collection errors = new LinkedList(); + p.errorCheck(errors); + + if (errors.isEmpty()) { + ast = p; + } else { + for (Iterator iter = errors.iterator(); iter.hasNext(); ) { + String s = (String)iter.next(); + System.out.println(s); + } + } + } catch (FileNotFoundException e) { + System.err.println("Could not find file: " + fileName); + } catch (IOException e) { + System.err.println("IOException: " + fileName + " " + e); + } catch (beaver.Parser.Exception e) { + System.err.println(e.getMessage()); + } + return ast; + } + + boolean generateC(Program ast) { + boolean wroteFile = false; + Vector hIncludes = new Vector(cIncludes); + if (hFile != null) { + cIncludes.add(hFile); + } + if (cFile != null) { + printStatus("C: " , cFile); + genC(ast, cFile, cIncludes, coreName, cPrefix, ver); + wroteFile = true; + } + if (hFile != null) { + printStatus("H: " , hFile); + genH(ast, hFile, hIncludes, coreName, cPrefix, ver); + wroteFile = true; + } + return wroteFile; + } + + boolean generateCS(Program ast) { + boolean wroteFile = false; + if (csFile != null) { + printStatus("C#: " , csFile); + genCS(ast, csFile, csNamespace, ver); + wroteFile = true; + } + return wroteFile; + } + + boolean generateJava(Program ast) { + boolean wroteFile = false; + if (javaDir != null) { + printStatus("Java: " , javaDir); + genJava(ast, javaDir, javaPackage, ver); + wroteFile = true; + } + return wroteFile; + } + + boolean generatePython(Program ast) { + boolean wroteFile = false; + if (pythonFile != null) { + printStatus("Python: " , pythonFile); + genPython(ast, pythonFile, prefix, ver); + wroteFile = true; + } + return wroteFile; + } + + boolean generateRAPID(Program ast) { + boolean wroteFile = false; + if (rapidFile != null) { + printStatus("RAPID: " , rapidFile); + genRAPID(ast, rapidFile, coreName, ver); + wroteFile = true; + } + return wroteFile; + } + boolean generatePrettyPrint(Program ast) { + boolean wroteFile = false; + if (prettyFile != null) { + printStatus("Pretty: " , prettyFile); + try { + FileOutputStream f = new FileOutputStream(prettyFile); + PrintStream out = new PrintStream(f); + ast.pp(out); + out.close(); + wroteFile = true; + } catch (IOException e) { + System.err.println("IOException: " + prettyFile + " " + e); + } + } + return wroteFile; + } + + boolean generateTypeinfo(Program ast) { + boolean wroteFile = false; + if (typeinfoFile != null) { + printStatus("TypeInfo: " , typeinfoFile); + try { + FileOutputStream f = new FileOutputStream(typeinfoFile); + PrintStream out = new PrintStream(f); + ast.C_info(out, cPrefix, ver); + ast.Java_info(out, ver); + ast.CS_info(out, csNamespace, ver); + wroteFile = true; + } catch (IOException e) { + System.err.println("IOException: " + typeinfoFile + " " + e); + } + } + return wroteFile; + } + + private void printStatus(String kind, String filename){ + if (verbose) { + System.err.println("Generating "+kind+": " + filename); + } + } + } + + + public static void main(String[] args) { + Opts opts = new Opts(args); + if(!opts.processFilename()) { + print_help(); + System.exit(1); + } else { + opts.processArgs(); + Program ast = opts.parseFile(); + + if (ast != null) { + + boolean fileWritten = false; + + fileWritten |= opts.generateC(ast); + fileWritten |= opts.generateCS(ast); + fileWritten |= opts.generateJava(ast); + fileWritten |= opts.generatePython(ast); + fileWritten |= opts.generateRAPID(ast); + fileWritten |= opts.generatePrettyPrint(ast); + fileWritten |= opts.generateTypeinfo(ast); + + // if no output to files, prettyprint on stdout + if (!fileWritten) { + ast.pp(System.out); + } + } else { + // Catch-all for compilation errors + System.err.println("Error in specification"); + System.exit(3); + } + } + } +} diff --git a/compiler/LabCommParser.parser b/compiler/2006/LabCommParser.parser similarity index 97% rename from compiler/LabCommParser.parser rename to compiler/2006/LabCommParser.parser index f326d63..e1fb352 100644 --- a/compiler/LabCommParser.parser +++ b/compiler/2006/LabCommParser.parser @@ -1,5 +1,6 @@ %header {: - package AST; +package se.lth.control.labcomm2006.compiler; +import se.lth.control.labcomm2006.compiler.*; :}; %embed {: public static class SourceError extends Error { diff --git a/compiler/LabCommScanner.flex b/compiler/2006/LabCommScanner.flex similarity index 96% rename from compiler/LabCommScanner.flex rename to compiler/2006/LabCommScanner.flex index 4bb82d3..685f824 100644 --- a/compiler/LabCommScanner.flex +++ b/compiler/2006/LabCommScanner.flex @@ -1,8 +1,8 @@ -package AST; +package se.lth.control.labcomm2006.compiler; import beaver.Symbol; import beaver.Scanner; -import AST.LabCommParser.Terminals; +import se.lth.control.labcomm2006.compiler.LabCommParser.Terminals; %% diff --git a/compiler/LabCommTokens.jrag b/compiler/2006/LabCommTokens.jrag similarity index 100% rename from compiler/LabCommTokens.jrag rename to compiler/2006/LabCommTokens.jrag diff --git a/compiler/NameAnalysis.jrag b/compiler/2006/NameAnalysis.jrag similarity index 100% rename from compiler/NameAnalysis.jrag rename to compiler/2006/NameAnalysis.jrag diff --git a/compiler/PrettyPrint.jrag b/compiler/2006/PrettyPrint.jrag similarity index 100% rename from compiler/PrettyPrint.jrag rename to compiler/2006/PrettyPrint.jrag diff --git a/compiler/Python_CodeGen.jrag b/compiler/2006/Python_CodeGen.jrag similarity index 100% rename from compiler/Python_CodeGen.jrag rename to compiler/2006/Python_CodeGen.jrag diff --git a/compiler/RAPID_CodeGen.jrag b/compiler/2006/RAPID_CodeGen.jrag similarity index 100% rename from compiler/RAPID_CodeGen.jrag rename to compiler/2006/RAPID_CodeGen.jrag diff --git a/compiler/Signature.jrag b/compiler/2006/Signature.jrag similarity index 99% rename from compiler/Signature.jrag rename to compiler/2006/Signature.jrag index d542d43..5395095 100644 --- a/compiler/Signature.jrag +++ b/compiler/2006/Signature.jrag @@ -76,7 +76,7 @@ aspect Signature { } //add(data, comment); break; - case 2013: // Use new encoding with varints + case 2014: // Use new encoding with varints byte[] tmp = new byte[5]; long v = value & 0xffffffff; int i, j; diff --git a/compiler/TypeCheck.jrag b/compiler/2006/TypeCheck.jrag similarity index 100% rename from compiler/TypeCheck.jrag rename to compiler/2006/TypeCheck.jrag diff --git a/compiler/TypeReferences.jrag b/compiler/2006/TypeReferences.jrag similarity index 100% rename from compiler/TypeReferences.jrag rename to compiler/2006/TypeReferences.jrag diff --git a/compiler/Version.jrag b/compiler/2006/Version.jrag similarity index 100% rename from compiler/Version.jrag rename to compiler/2006/Version.jrag diff --git a/compiler/2014/ArrayTypeRewrite.jrag b/compiler/2014/ArrayTypeRewrite.jrag new file mode 100644 index 0000000..28e3c79 --- /dev/null +++ b/compiler/2014/ArrayTypeRewrite.jrag @@ -0,0 +1,43 @@ +aspect ArrayRewrite { + + syn boolean Dim.isVariable() { + for (int i = 0 ; i < getNumExp() ; i++) { + if (getExp(i) instanceof VariableSize) { + return true; + } + } + return false; + } + + rewrite ParseArrayType { + when (! getDim(0).isVariable()) + to FixedArrayType { + if (getNumDim() == 1) { + return new FixedArrayType(getType(), + getDim(0).getExpList()); + } else { + List l = new List(); + for (int i = 1 ; i < getNumDim() ; i++) { + l.add(getDim(i)); + } + return new FixedArrayType(new ParseArrayType(getType(), l), + getDim(0).getExpList()); + } + } + when (getDim(0).isVariable()) + to VariableArrayType { + if (getNumDim() == 1) { + return new VariableArrayType(getType(), + getDim(0).getExpList()); + } else { + List l = new List(); + for (int i = 1 ; i < getNumDim() ; i++) { + l.add(getDim(i)); + } + return new VariableArrayType(new ParseArrayType(getType(), l), + getDim(0).getExpList()); + } + } + } + +} diff --git a/compiler/2014/CS_CodeGen.jrag b/compiler/2014/CS_CodeGen.jrag new file mode 100644 index 0000000..e1da497 --- /dev/null +++ b/compiler/2014/CS_CodeGen.jrag @@ -0,0 +1,971 @@ +import java.io.*; +import java.util.*; + +aspect CS_CodeGenEnv { + + // Environment wrapper for CS-code generation + // handles indentation, file writing, + + public class CS_env { + + public final int version; + public final String verStr; + private int indent; + private int depth; + private CS_printer printer; + private HashMap unique = new HashMap(); + + final private static class CS_printer { + + private boolean newline = true; + private File file; + private PrintStream out; + private IOException exception; + + + public CS_printer(File f) { + file = f; + File parentFile = f.getParentFile(); + if(parentFile != null) { + parentFile.mkdirs(); + } + } + + public CS_printer(PrintStream out) { + this.out = out; + } + + public void close() throws IOException { + if (out != null) { + out.close(); + } + if (exception != null) { + throw exception; + } + } + + public PrintStream getPrintStream() { + return(out); + } + + public void checkOpen() { + if (out == null && exception == null) { + try { + out = new PrintStream(new FileOutputStream(file)); + } catch (IOException e) { + exception = e; + } + } + } + + public void print(CS_env env, String s) { + checkOpen(); + if (newline) { + newline = false; + for (int i = 0 ; i < env.indent ; i++) { + out.print(" "); + } + } + out.print(s); + } + + public void println(CS_env env, String s) { + checkOpen(); + print(env, s); + out.println(); + newline = true; + } + } + + private CS_env(int indent, CS_printer printer, int version) { + this.version = version; + this.indent = indent; + this.printer = printer; + this.verStr = LabCommVersion.versionString(version); + } + + public CS_env(File f, int version) { + this(0, new CS_printer(f), version); + } + + public CS_env(PrintStream out, int version) { + this(0, new CS_printer(out), version); + } + + public void close() throws IOException { + printer.close(); + } + + public PrintStream getPrintStream() { + return printer.getPrintStream(); + } + public void indent(int amount) { + indent += amount; + } + + public void indent() { + indent(1); + } + + public void unindent(int amount) { + indent -= amount; + if (indent < 0) { + throw new Error("Negative indent level"); + } + } + + public void unindent() { + unindent(1); + } + + public void print(String s) { + printer.print(this, s); + } + + public void println(String s) { + printer.println(this, s); + } + + public void println() { + printer.println(this, ""); + } + + public int getDepth() { + return depth; + } + + public String print_for_begin(String limit) { + print("for (int i_" + depth + " = 0 ; "); + print("i_" + depth + " < " + limit + " ; "); + println("i_" + depth + "++) {"); + indent(); + depth++; + return "i_" + (depth - 1); + } + + public void print_for_end() { + depth--; + unindent(); + println("}"); + } + + public void print_block_begin() { + println("{"); + indent(); + } + + public void print_block_end() { + unindent(); + println("}"); + } + + public String getUnique(Object o) { + String result = (String)unique.get(o); + if (result == null) { + result = "_" + (unique.size() + 1) + "_"; + } + unique.put(o, result); + return result; + } + + } + +} + +aspect CS_StructName { + + inh int Decl.CS_Depth(); + inh int Type.CS_Depth(); + eq Program.getDecl(int i).CS_Depth() = 0; + eq StructType.getField(int i).CS_Depth() = CS_Depth() + 1; + + inh String Type.CS_structName(); + eq Program.getDecl(int i).CS_structName() = getDecl(i).getName(); + eq StructType.getField(int i).CS_structName() { + if (CS_Depth() == 0) { + return "struct_" + getField(i).getName(); + } else { + return CS_structName() + "_" + getField(i).getName(); + } + } +} + +aspect CS_Void { + + syn boolean Decl.CS_isVoid() = getType().CS_isVoid(); + syn boolean UserType.CS_isVoid() = decl().CS_isVoid(); + syn boolean Type.CS_isVoid() = false; + syn boolean VoidType.CS_isVoid() = true; + +} + +aspect CS_CodeGen { + + public void Program.CS_gen(String file, + String namespace, int version) throws IOException { + // Registration class + CS_env env = new CS_env(new File(file), version); + if (namespace != null && namespace.length() > 0) { + env.println("namespace " + namespace + "{"); + env.indent(); + } + env.println("using System;"); + env.println("using se.lth.control.labcomm;"); + for (int i = 0; i < getNumDecl(); i++) { + Decl d = getDecl(i); + try { + d.CS_emitClass(env); + } catch (Error e) { + System.err.println(d.getName()); + throw e; + } + } + if (namespace != null && namespace.length() > 0) { + env.unindent(); + env.println("}"); + } + } + +} + +aspect CS_Register { + + public void Program.CS_emitTypeRegister(CS_env env) { + } + + public void Decl.CS_emitTypeRegister(CS_env env) { + throw new Error(this.getClass().getName() + + ".CS_emitTypeRegister(CS_env env)" + + " not declared"); + } + + public void SampleDecl.CS_emitTypeRegister(CS_env env) { + env.println(getName() + ".register(c);"); + } + + public void TypeDecl.CS_emitTypeRegister(CS_env env) { + // TODO + } + +} + +aspect CS_Class { + + public void Decl.CS_emitClass(CS_env env) { + throw new Error(this.getClass().getName() + + ".CS_emitClass(CS_env env)" + + " not declared"); + } + + public void Decl.CS_emitDeclPP(CS_env env){ + env.println("/* "); + pp(env.getPrintStream()); + + CS_emitUserTypeDeps(env,null,false); + CS_emitUserTypeRefs(env,null,false); + env.println("*/"); + + } + + public void Decl.CS_emitUserTypeDeps(CS_env env, String via, boolean outputCode){ + Iterator<Decl> it = type_dependencies().iterator(); + while(it.hasNext()) { + Decl t = it.next(); + + t.CS_emitUserTypeDeps(env, t.getName(), outputCode); + if( outputCode && t.getType().isUserType() ) { + env.println(t.getName()+".register(e);"); + } else { // Just output a comment + String refpath = (via == null) ? "directly" : "indirectly via "+via; + env.println(" //Depends ("+refpath+") on "+t.getName() ); + } + } + } + + public void Decl.CS_emitUserTypeRefs(CS_env env, String via, boolean outputCode){ + if( isReferenced() ) { + Iterator<Decl> it = type_references().iterator(); + while(it.hasNext()) { + Decl t = it.next(); + + t.CS_emitUserTypeRefs(env, t.getName(), outputCode); + if(outputCode) { + env.println(t.getName()+".register(e);"); + } else { // Just output a comment + String refpath = (via == null) ? "directly" : "indirectly via "+via; + env.println(" //Is referenced ("+refpath+") by "+t.getName() ); + } + } + } + } + + public void Decl.CS_emitRegisterEncoder(CS_env env) { + env.println("public static void register(Encoder e){"); + env.indent(); + env.println("e.register(dispatcher);"); + env.unindent(); + env.println("}"); + env.println("public static void registerSampleRef(Encoder e) {"); + env.indent(); + env.println("e.registerSampleRef(dispatcher);"); + env.unindent(); + env.println("}"); + env.println(); + } + + public void Decl.CS_emitRegisterDecoder(CS_env env) { + env.println("public static void register(Decoder d, Handler h) {"); + env.indent(); + env.println("d.register(dispatcher, h);"); + env.unindent(); + env.println("}"); + env.println(); + env.println("public static void registerSampleRef(Decoder d) {"); + env.indent(); + env.println("d.registerSampleRef(dispatcher);"); + env.unindent(); + env.println("}"); + env.println(); + } + + public void TypeDecl.CS_emitClass(CS_env env) { + if (getType().CS_needInstance()) { + // Hackish prettyprint preamble + env.println("/* "); + pp(env.getPrintStream()); + env.println("*/"); + env.println(); + env.println("public class " + getName() + " : SampleType {"); + env.println(); + env.indent(); + getType().CS_emitInstance(env); + if( isReferenced()) { + CS_emitRegisterEncoder(env); + CS_emitDispatcher(env,false); + } + CS_emitSignature(env); + CS_emitEncoder(env); + CS_emitDecoder(env); + env.unindent(); + env.println("}"); + } + } + + public void SampleDecl.CS_emitClass(CS_env env) { + env.println("/* "); + pp(env.getPrintStream()); + env.println("*/"); + env.println(); + env.println("public class " + getName() + " : Sample {"); + env.println(); + env.indent(); + getType().CS_emitInstance(env); + env.println("public interface Handler : SampleHandler {"); + env.print(" void handle("); + if (!isVoid()) { + getType().CS_emitType(env); + env.print(" value"); + } + env.println(");"); + env.println("}"); + env.println(); + CS_emitDispatcher(env,true); + CS_emitRegisterEncoder(env); + CS_emitRegisterDecoder(env); + CS_emitEncoder(env); + CS_emitDecoder(env); + CS_emitSignature(env); + + env.println("}"); + } + + public void Decl.CS_emitSignature(CS_env env) { + CS_emitFlatSignature(env); +// if(isReferenced() || isSampleDecl()){ +// Signature signature = getSignature(); +// signature.CS_emitSignature(env, !isSampleDecl()); +// } + } + + public void Decl.CS_emitFlatSignature(CS_env env){ + env.println("private static byte[] signature = new byte[] {"); + env.indent(); + SignatureList signature = flatSignature(env.version); + for (int i = 0 ; i < signature.size() ; i++) { + String comment = signature.getComment(i); + if (comment != null) { + env.println(signature.getIndent(i) + "// " + comment); + } + byte[] data = signature.getData(i, env.version); + if (data != null) { + env.print(signature.getIndent(i)); + for (int j = 0 ; j < data.length ; j++) { + //env.print(data[j] + ", "); + env.print(String.format("0x%02X, ", data[j])) ; + } + env.println(); + } + } + env.unindent(); + env.println("};"); + env.println(); + } + + //XXX TODO: refactor: split into a static class ("TypeDefSingleton"?)and a (smaller) dispatcher + public void Decl.CS_emitDispatcher(CS_env env, boolean isSample) { + String genericStr = ""; //env.versionHasMetaData()?"<"+getName()+">":""; + env.println("private static Dispatcher dispatcher = new Dispatcher();"); + env.println(); + env.println("public SampleDispatcher getDispatcher() {"); + env.indent(); + env.println("return dispatcher;"); + env.unindent(); + env.println("}"); + env.println(); + env.println("private class Dispatcher : SampleDispatcher{"); + env.indent(); + env.println(); + env.println("public Type getSampleClass() {"); + env.indent(); + env.println("return typeof(" + getName() + ");"); + env.unindent(); + env.println("}"); + env.println(); + env.println("public String getName() {"); + env.indent(); + env.println("return \"" + getName() + "\";"); + env.unindent(); + env.println("}"); + env.println(); + env.println("public byte getTypeDeclTag() {"); + env.indent(); + if(isSample) { + env.println("return Constant.SAMPLE_DEF;"); + } else { + env.println("return Constant.TYPE_DEF;"); + } + env.unindent(); + env.println("}"); + env.println(); + env.println("public bool isSample() {"); + env.indent(); + env.println("return "+isSample+";"); + env.unindent(); + env.println("}"); + env.println("/** return the flat signature. */"); + env.println("public byte[] getSignature() {"); + env.indent(); + env.println("return signature;"); + env.unindent(); + env.println("}"); + env.println(); +// env.println("public void encodeSignature(Encoder e) throws IOException{"); +// env.indent(); +// env.println("emitSignature(e);"); +// env.unindent(); +// env.println("}"); +// env.println(); +// env.println("public void encodeSignatureMetadata(Encoder e, int index){"); +// env.indent(); +// env.println("e.encodePacked32(Constant.TYPE_DEF);"); +// env.println("e.encodePacked32(index);"); +// env.println("e.encodeString(getName());"); +// env.println("emitSignature(e);"); +// env.unindent(); +// env.println("}"); +// env.println(); + env.println("public bool canDecodeAndHandle() {"); + env.indent(); + env.println("return "+isSample+";"); + env.unindent(); + env.println("}"); + env.println(); + env.println("public void decodeAndHandle(Decoder d,"); + env.println(" SampleHandler h) {"); + env.indent(); + if( isSample) { + if (isVoid()) { + env.println(getName() + ".decode(d);"); + env.println("((Handler)h).handle();"); + } else { + env.println("((Handler)h).handle(" + getName() + ".decode(d));"); + } + } else { + env.println("throw new Exception(\"A typedef has no handler, the corresponding method on the sample class should be called.\");"); + } + env.unindent(); + env.println("}"); + env.println(""); + env.unindent(); + env.println("}"); + env.println(""); + + } //TODO, fix above method + + public void TypeDecl.CS_emitEncoder(CS_env env) { + env.print("public static void encode(Encoder e"); + if (!isVoid()) { + env.print(", "); + getType().CS_emitType(env); + env.print(" value"); + } + env.println(") {"); + env.indent(); + getType().CS_emitEncoder(env, "value"); + env.unindent(); + env.println("}"); + env.println(); + } + + public void SampleDecl.CS_emitEncoder(CS_env env) { + env.print("public static void encode(Encoder e"); + if (!isVoid()) { + env.print(", "); + getType().CS_emitType(env); + env.print(" value"); + } + env.println(") {"); + env.indent(); + env.println("e.begin(typeof(" + getName() + "));"); + getType().CS_emitEncoder(env, "value"); + env.println("e.end(typeof(" + getName() + "));"); + env.unindent(); + env.println("}"); + env.println(); + } + + public void Type.CS_emitEncoder(CS_env env, String name) { + throw new Error(this.getClass().getName() + + ".CS_emitEncoder(CS_env env, String name)" + + " not declared"); + } + + public void VoidType.CS_emitEncoder(CS_env env, String name) { + } + + public void PrimType.CS_emitEncoder(CS_env env, String name) { + switch (getToken()) { + case LABCOMM_BOOLEAN: { env.print("e.encodeBoolean"); } break; + case LABCOMM_BYTE: { env.print("e.encodeByte"); } break; + case LABCOMM_SHORT: { env.print("e.encodeShort"); } break; + case LABCOMM_INT: { env.print("e.encodeInt"); } break; + case LABCOMM_LONG: { env.print("e.encodeLong"); } break; + case LABCOMM_FLOAT: { env.print("e.encodeFloat"); } break; + case LABCOMM_DOUBLE: { env.print("e.encodeDouble"); } break; + case LABCOMM_STRING: { env.print("e.encodeString"); } break; + case LABCOMM_SAMPLE: { env.print("e.encodeSampleRef"); } break; + } + env.println("(" + name + ");"); + } + + public void ArrayType.CS_emitEncoder(CS_env env, String name) { + env.print_block_begin(); + int baseDepth = env.getDepth(); + for (int i = 0 ; i < getNumExp() ; i++) { + String limit = getExp(i).CS_emitEncoder(env, + name + ".GetLength(" + i + ")"); + env.println("int i_" + (baseDepth + i) + "_max = " + limit + ";"); + } + String index = null; + for (int i = 0 ; i < getNumExp() ; i++) { + String limit = "i_" + (baseDepth + i) + "_max"; + if (i == 0) { + index = env.print_for_begin(limit); + } else { + index = index + ", " + env.print_for_begin(limit); + } + } + getType().CS_emitEncoder(env, name + "[" + index + "]"); + for (int i = 0 ; i < getNumExp() ; i++) { + env.print_for_end(); + } + env.print_block_end(); + } + + public String Exp.CS_emitEncoder(CS_env env, String name) { + throw new Error(this.getClass().getName() + + ".CS_emitEncoder(CS_env env, String name)" + + " not declared"); + } + + public String IntegerLiteral.CS_emitEncoder(CS_env env, String name) { + return getValue(); + } + + public String VariableSize.CS_emitEncoder(CS_env env, String name) { + env.println("e.encodePacked32(" + name + ");"); + return name; + } + + public void StructType.CS_emitEncoder(CS_env env, String name) { + for (int i = 0 ; i < getNumField() ; i++) { + Field f = getField(i); + f.getType().CS_emitEncoder(env, name + "." + f.getName()); + } + } + + public void UserType.CS_emitEncoder(CS_env env, String name) { + if (CS_needInstance()) { + env.println(getName() + ".encode(e, " + name + ");"); + } else { + decl().getType().CS_emitEncoder(env, name); + } + } + + public void Decl.CS_emitDecoder(CS_env env) { + env.print("public static "); + getType().CS_emitType(env); + env.println(" decode(Decoder d) {"); + env.indent(); + if (!isVoid()) { + getType().CS_emitType(env); + env.println(" result;"); + getType().CS_emitDecoder(env, "result"); + env.println("return result;"); + } + env.unindent(); + env.println("}"); + env.println(); + } + + public void Type.CS_emitDecoder(CS_env env, String name) { + throw new Error(this.getClass().getName() + + ".CS_emitDecoder(CS_env env, String name)" + + " not declared"); + } + + public void VoidType.CS_emitDecoder(CS_env env, String name) { + } + + public void PrimType.CS_emitDecoder(CS_env env, String name) { + env.print(name + " = "); + switch (getToken()) { + case LABCOMM_BOOLEAN: { env.println("d.decodeBoolean();"); } break; + case LABCOMM_BYTE: { env.println("d.decodeByte();"); } break; + case LABCOMM_SHORT: { env.println("d.decodeShort();"); } break; + case LABCOMM_INT: { env.println("d.decodeInt();"); } break; + case LABCOMM_LONG: { env.println("d.decodeLong();"); } break; + case LABCOMM_FLOAT: { env.println("d.decodeFloat();"); } break; + case LABCOMM_DOUBLE: { env.println("d.decodeDouble();"); } break; + case LABCOMM_STRING: { env.println("d.decodeString();"); } break; + case LABCOMM_SAMPLE: { env.println("d.decodeSampleRef();"); } break; + default: { + throw new Error("PrimType.CS_emitDecoder(CS_env env, String name)" + + " unknown token type"); + } + } + } + + public void ArrayType.CS_emitDecoder(CS_env env, String name) { + env.println("{"); + env.indent(); + int baseDepth = env.getDepth(); + for (int i = 0 ; i < getNumExp() ; i++) { + env.print("int i_" + (baseDepth + i) + "_max = "); + getExp(i).CS_emitDecoder(env); + env.println(";"); + } + env.print(name + " = new "); + getType().CS_emitTypePrefix(env); + env.print("["); + for (int i = 0 ; i < getNumExp() ; i++) { + if (i > 0) { + env.print(", "); + } + env.print("i_" + (baseDepth + i) + "_max"); + } + env.print("]"); + getType().CS_emitTypeSuffix(env); + env.println(";"); + + String index = null; + for (int i = 0 ; i < getNumExp() ; i++) { + String limit = "i_" + (baseDepth + i) + "_max"; + if (i == 0) { + index = env.print_for_begin(limit); + } else { + index = index + ", " + env.print_for_begin(limit); + } + } + getType().CS_emitDecoder(env, name + "[" + index + "]"); + for (int i = 0 ; i < getNumExp() ; i++) { + env.print_for_end(); + } + env.unindent(); + env.println("}"); + } + + public void Exp.CS_emitDecoder(CS_env env) { + throw new Error(this.getClass().getName() + + ".CS_emitDecoder(CS_env env)" + + " not declared"); + } + + public void IntegerLiteral.CS_emitDecoder(CS_env env) { + env.print(getValue()); + } + + public void VariableSize.CS_emitDecoder(CS_env env) { + env.print("d.decodePacked32()"); + } + + public void StructType.CS_emitDecoder(CS_env env, String name) { + env.print(name + " = new "); + CS_emitType(env); + env.println("();"); + for (int i = 0 ; i < getNumField() ; i++) { + Field f = getField(i); + f.getType().CS_emitDecoder(env, name + "." + f.getName()); + } + } + + public void UserType.CS_emitDecoder(CS_env env, String name) { + if (CS_needInstance()) { + env.println(name + " = " + getName() + ".decode(d);"); + } else { + decl().getType().CS_emitDecoder(env, name); + } + } + + public void Type.CS_emitTypePrefix(CS_env env) { + throw new Error(this.getClass().getName() + + ".CS_emitTypePrefix(CS_env env)" + + " not declared"); + } + + public void PrimType.CS_emitTypePrefix(CS_env env) { + switch (getToken()) { + case LABCOMM_STRING: { env.print("String"); } break; + case LABCOMM_SAMPLE: { env.print("Type"); } break; + default: { env.print(getName()); } break; + } + } + + public void UserType.CS_emitTypePrefix(CS_env env) { + if (CS_needInstance()) { + env.print(getName()); + } else { + decl().getType().CS_emitTypePrefix(env); + } + } + + public void ArrayType.CS_emitTypePrefix(CS_env env){ + getType().CS_emitTypePrefix(env); + } + + public void StructType.CS_emitTypePrefix(CS_env env){ + env.print(CS_structName()); + } + + public void Type.CS_emitTypeSuffix(CS_env env) { + } + + public void UserType.CS_emitTypeSuffix(CS_env env) { + if (! CS_needInstance()) { + decl().getType().CS_emitTypeSuffix(env); + } + } + + public void ArrayType.CS_emitTypeSuffix(CS_env env){ + env.print("["); + for (int i = 1 ; i < getNumExp() ; i++) { + env.print(","); + } + env.print("]"); + getType().CS_emitTypeSuffix(env); + } + + public boolean Type.CS_needInstance() { + throw new Error(this.getClass().getName() + + ".CS_needInstance()" + + " not declared"); + } + + public boolean VoidType.CS_needInstance() { + return false; + } + + public boolean PrimType.CS_needInstance() { + return false; + } + + public boolean UserType.CS_needInstance() { + return decl().getType().CS_needInstance(); + } + + public boolean StructType.CS_needInstance() { + return true; + } + + public boolean ArrayType.CS_needInstance() { + return getType().CS_needInstance(); + } + + public boolean Type.CS_isPrimitive() { + return false; + } + + public boolean PrimType.CS_isPrimitive() { + return true; + } + + public void Type.CS_emitInstance(CS_env env) { + throw new Error(this.getClass().getName() + + ".CS_emitInstance(CS_env env)" + + " not declared"); + } + + public void VoidType.CS_emitInstance(CS_env env) { + } + + public void PrimType.CS_emitInstance(CS_env env) { + } + + public void ArrayType.CS_emitInstance(CS_env env) { + getType().CS_emitInstance(env); + } + + public void StructType.CS_emitInstance(CS_env env) { + if (CS_Depth() > 0) { + env.println("public class " + CS_structName() + " {"); + env.indent(); + } + for (int i = 0 ; i < getNumField() ; i++) { + getField(i).getType().CS_emitInstance(env); + } + for (int i = 0 ; i < getNumField() ; i++) { + getField(i).CS_emitField(env); + } + if (CS_Depth() > 0) { + env.unindent(); + env.println("}"); + } + env.println(); + } + + public void UserType.CS_emitInstance(CS_env env) { + } + + public void Field.CS_emitField(CS_env env) { + env.print("public "); + getType().CS_emitType(env); + env.println(" " + getName() + ";"); + } + + public void Type.CS_emitType(CS_env env) { + throw new Error(this.getClass().getName() + + ".CS_emitType(CS_env env)" + + " not declared"); + } + + public void VoidType.CS_emitType(CS_env env) { + env.print("void"); + } + + public void PrimType.CS_emitType(CS_env env) { + switch (getToken()) { + case LABCOMM_STRING: { env.print("String"); } break; + case LABCOMM_BOOLEAN: { env.print("bool"); } break; + case LABCOMM_SAMPLE: { env.print("Type"); } break; + default: { env.print(getName()); } break; + } + } + + public void UserType.CS_emitType(CS_env env) { + decl().getType().CS_emitType(env); + } + + public void ArrayType.CS_emitType(CS_env env){ + getType().CS_emitTypePrefix(env); + env.print("["); + for (int i = 1 ; i < getNumExp() ; i++) { + env.print(","); + } + env.print("]"); + getType().CS_emitTypeSuffix(env); + } + + public void StructType.CS_emitType(CS_env env){ + env.print(CS_structName()); + } + +} + +aspect CS_Signature { + public void Signature.CS_emitSignature(CS_env env, boolean decl){ + + SignatureList sl = getSignatureList(); + sl.CS_emitSignature(env, decl); + } + + public abstract void SignatureLine.CS_emitSignature(CS_env env, boolean decl); + + public void TypeRefSignatureLine.CS_emitSignature(CS_env env, boolean isDecl){ + env.print(getIndentString()); + env.println("e.encodePacked32(e.getTypeId( typeof("+decl.getName()+")));"); + } + + public void DataSignatureLine.CS_emitSignature(CS_env env, boolean decl){ + byte[] data = getData(env.version); + if (data != null) { + env.print(getIndentString()); + for (int j = 0 ; j < data.length ; j++) { + //env.print("e.encodeByte((byte)"+data[j]+");"); + env.print("e.encodeByte((byte)"+ String.format("0x%02X ", data[j]) +"); "); + } + env.println(); + } + } + public void SignatureList.CS_emitSignature(CS_env env, boolean decl) { + env.println("private static void emitSignature(Encoder e){"); + env.indent(); + for (int i = 0 ; i < size() ; i++) { + String comment = getComment(i); + if (comment != null && comment.length() > 0) { + env.println(getIndent(i) + "// " + comment); + } + SignatureLine l = getSignatureLine(i); + l.CS_emitSignature(env, decl); + } + env.println("}"); + env.unindent(); + } + +} + +aspect CS_Info { + + public void Program.CS_info(PrintStream out, String namespace, int version) { + CS_env env = new CS_env(out, version); + if (namespace == null) { + namespace = ""; + } else { + namespace = namespace + "."; + } + for (int i = 0; i < getNumDecl(); i++) { + getDecl(i).CS_info(env, namespace); + } + } + + public void Decl.CS_info(CS_env env, String namespace) { + throw new Error(this.getClass().getName() + + ".CS_info(CS_env env)" + + " not declared"); + } + + public void TypeDecl.CS_info(CS_env env, String namespace) { + env.print(";C#;typedef;" + namespace + getName() + ";"); + getType().CS_emitType(env) ; + env.print(";not_applicable_for_C#"); + env.println(); + } + + public void SampleDecl.CS_info(CS_env env, String namespace) { + env.print(";C#;sample;" + namespace + getName() + ";"); + getType().CS_emitType(env); + env.print(";not_applicable_for_C#"); + env.println(); + } + +} + diff --git a/compiler/2014/C_CodeGen.jrag b/compiler/2014/C_CodeGen.jrag new file mode 100644 index 0000000..0beef11 --- /dev/null +++ b/compiler/2014/C_CodeGen.jrag @@ -0,0 +1,1694 @@ +import java.util.Vector; + +aspect C_CodeGenEnv { + + // Environment wrapper for C-code generation + // handles qualid nesting, indentation, file writing and + // prefix propagation + + public class C_env { + + final private static class C_printer { + + private boolean newline = true; + private PrintStream out; + + public C_printer(PrintStream out) { + this.out = out; + } + + public void print(C_env env, String s) { + if (newline) { + newline = false; + for (int i = 0 ; i < env.indent ; i++) { + out.print(" "); + } + } + out.print(s); + } + public void println(C_env env, String s) { + print(env, s); + out.println(); + newline = true; + } + } + + public final int version; //labcomm version (2006 or 2014) + public final String verStr; // version suffix to append (currently _2006 and empty string) + + public final String qualid; + public final String lcName; + public final String rawPrefix; + public final String prefix; + private int indent; + public final int depth; + private C_printer printer; + public final int nestedLevel; + private boolean rootIsPointer; + private int rootLevel; + + public boolean versionHasMetaData() { + return version != 2006; + } + + private C_env(String qualid, String lcName, String rawPrefix, + int indent, int depth, C_printer printer, + int nestedLevel, int version) + { + this.version = version; + this.verStr = LabCommVersion.versionString(version); + this.qualid = qualid; + this.lcName = lcName; + this.rawPrefix = rawPrefix; + if (rawPrefix == null) { + System.err.println("WARNING: prefix==null"); + this.prefix = ""; + } else if (rawPrefix.equals("")) { + this.prefix = rawPrefix; + } else { + this.prefix = rawPrefix + "_"; + } + this.indent = indent; + this.depth = depth; + this.printer = printer; + this.nestedLevel = nestedLevel; + } + + public C_env(String qualid, String lcName, String rawPrefix, + PrintStream out, int version) + { + this(qualid, lcName, rawPrefix, 0, 0, new C_printer(out), 0, version); + } + + public C_env(String qualid, String lcName, String rawPrefix, + int indent, int depth, C_printer printer, int version) { + this(qualid, lcName, rawPrefix, indent, depth, printer, 0, version); + } + + public C_env nestArray(String suffix) { + return new C_env(qualid + suffix, lcName, rawPrefix, + indent, depth + 1, printer, nestedLevel + 1, version); + } + + public C_env nestStruct(String suffix) { + return new C_env(qualid + suffix, lcName, rawPrefix, + indent, depth, printer, nestedLevel + 1, version); + } + + public void indent() { + indent++; + } + + public void unindent() { + indent--; + } + + public String prefix() { + return rawPrefix; + } + + public void print(String s) { + printer.print(this, s); + } + + public void println() { + printer.println(this, ""); + } + + public void println(String s) { + printer.println(this, s); + } + + public C_env setPointer() { + rootIsPointer = true; + rootLevel = nestedLevel; + return this; + } + + public String memberAccessor() { + return (rootIsPointer && (nestedLevel == rootLevel)) ? "->" : "."; + } + + public String accessor() { + return (rootIsPointer && (nestedLevel == rootLevel)) ? "*" : ""; + } + } + + public C_env ArrayType.C_Nest(C_env env) { + throw new Error(this.getClass().getName() + + ".C_Nest(C_env env)" + + " not declared"); + } + + public C_env FixedArrayType.C_Nest(C_env env) { + String index = env.memberAccessor() + "a"; + for (int i = 0 ; i < getNumExp() ; i++) { + index += "[i_" + env.depth + "_" + i + "]"; + } + return env.nestArray(index); + } + + public C_env VariableArrayType.C_Nest(C_env env) { + return env.nestArray(env.memberAccessor() + "a[i_" + env.depth + "]"); + } + + +} + +aspect C_IsDynamic { + + // Determine if a type has dynamically allocated data + syn boolean Decl.C_isDynamic() = getType().C_isDynamic(); + syn boolean Type.C_isDynamic() = false; + syn boolean PrimType.C_isDynamic() = getToken() == LABCOMM_STRING; + syn boolean UserType.C_isDynamic() = + lookupType(getName()).getType().C_isDynamic(); + syn boolean StructType.C_isDynamic() { + for (int i = 0 ; i < getNumField() ; i++) { + if (getField(i).getType().C_isDynamic()) { + return true; + } + } + return false; + } + syn boolean FixedArrayType.C_isDynamic() = getType().C_isDynamic(); + syn boolean VariableArrayType.C_isDynamic() = true; +} + +aspect C_CodeGen { + + public void Program.C_genH(PrintStream out, Vector includes, + String lcName, String prefix, int version) { + C_env env = new C_env("", lcName, prefix, out, version); + + // Hackish prettyprint preamble + out.println("/* LabComm declarations:"); + pp(out); + out.println("*/"); + env.println(""); + env.println(""); + env.println("#ifndef __LABCOMM_" + env.lcName + "_H__"); + env.println("#define __LABCOMM_" + env.lcName + "_H__"); + env.println(""); + + // Include + env.println("#include \"labcomm"+env.verStr+".h\""); + for (int i = 0 ; i < includes.size() ; i++) { + env.println("#include \"" + includes.get(i) + "\""); + } + env.println(""); + + C_emitH(env); + + env.println("#endif"); + } + + public void Program.C_genC(PrintStream out, Vector includes, + String lcName, String prefix, int version) { + C_env env = new C_env("", lcName, prefix, out, version); + + // Include + env.println("#include \"labcomm"+env.verStr+".h\""); + env.println("#include \"labcomm"+env.verStr+"_private.h\""); + for (int i = 0 ; i < includes.size() ; i++) { + env.println("#include \"" + includes.get(i) + "\""); + } + env.println(""); + + // Method Implementations + C_emitC(env); + } + + public void Program.C_emitH(C_env env) { + for (int i = 0; i < getNumDecl(); i++) { + getDecl(i).C_emitType(env); + getDecl(i).C_emitDecoderDeclaration(env); + getDecl(i).C_emitEncoderDeclaration(env); + getDecl(i).C_emitSizeofDeclaration(env); + getDecl(i).C_emitCopyDeclaration(env); + getDecl(i).C_emitCopyDeallocationDeclaration(env); + env.println(""); + } + C_emitConstructorDeclaration(env); + C_emitForAll(env); + } + + public void Program.C_emitC(C_env env) { + for (int i = 0; i < getNumDecl(); i++) { + getDecl(i).C_emitSignature(env); + getDecl(i).C_emitDecoder(env); + getDecl(i).C_emitDecoderRegisterHandler(env); + getDecl(i).C_emitDecoderIoctl(env); + getDecl(i).C_emitEncoder(env); + getDecl(i).C_emitEncoderRegisterHandler(env); + getDecl(i).C_emitEncoderIoctl(env); + getDecl(i).C_emitSizeof(env); + getDecl(i).C_emitCopy(env); + getDecl(i).C_emitCopyDeallocation(env); + } + C_emitConstructor(env); + } + +} + +aspect C_Common { + + public void ArrayType.C_emitLoopVariables(C_env env) { + for (int i = 0 ; i < getNumExp() ; i++) { + env.println("int i_" + env.depth + "_" + i + ";"); + } + } + +} + +aspect C_Type { + + public void Decl.C_emitType(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitType(C_env env)" + + " not declared"); + } + + public void TypeDecl.C_emitType(C_env env) { + env.println("#ifndef PREDEFINED_" + env.prefix + getName()); + env.print("typedef "); + getType().C_emitType(env, env.prefix + getName()); + env.println(";"); + env.println("#endif"); + } + + public void SampleDecl.C_emitType(C_env env) { + env.println("#ifndef PREDEFINED_" + env.prefix + getName()); + env.print("typedef "); + getType().C_emitType(env, env.prefix + getName()); + env.println(";"); + env.println("#endif"); + env.println("extern const struct labcomm"+env.verStr+"_signature " + + "*labcomm"+env.verStr+"_signature_" + env.prefix + getName() + + ";"); + } + + public void Type.C_emitType(C_env env, String name) { + throw new Error(this.getClass().getName() + + ".C_emitType(C_env env, String name)" + + " not declared"); + } + + public void VoidType.C_emitType(C_env env, String name) { + env.print("char " + name); + } + + public void PrimType.C_emitType(C_env env, String name) { + switch (getToken()) { + case LABCOMM_BOOLEAN: { env.print("uint8_t"); } break; + case LABCOMM_BYTE: { env.print("uint8_t"); } break; + case LABCOMM_SHORT: { env.print("int16_t"); } break; + case LABCOMM_INT: { env.print("int32_t"); } break; + case LABCOMM_LONG: { env.print("int64_t"); } break; + case LABCOMM_FLOAT: { env.print("float"); } break; + case LABCOMM_DOUBLE: { env.print("double"); } break; + case LABCOMM_STRING: { env.print("char*"); } break; + case LABCOMM_SAMPLE: { + env.print("const struct labcomm_signature *"); + } break; + } + env.print(" " + name); + } + + public void UserType.C_emitType(C_env env, String name) { + env.print(env.prefix + getName() + " " + name); + } + + public void StructType.C_emitType(C_env env, String name) { + env.println("struct {"); + env.indent(); + for (int i = 0 ; i < getNumField() ; i++) { + getField(i).C_emitType(env); + env.println(";"); + } + env.unindent(); + env.print("} " + name); + } + + public void Field.C_emitType(C_env env) { + getType().C_emitType(env, getName()); + } + + public void FixedArrayType.C_emitType(C_env env, String name) { + env.println("struct {"); + env.indent(); + StringBuffer index = new StringBuffer("a"); + for (int i = 0 ; i < getNumExp() ; i++) { + index.append("[" + getExp(i).C_getValue() + "]"); + } + getType().C_emitType(env, index.toString()); + env.println(";"); + env.unindent(); + env.print("} " + name); + } + + public void VariableArrayType.C_emitType(C_env env, String name) { + env.println("struct {"); + env.indent(); + for (int i = 0 ; i < getNumExp() ; i++) { + if (getExp(i) instanceof VariableSize) { + env.println("int n_" + i + ";"); + } else { + env.println("// n_" + i + "=" + getExp(i).C_getValue()); + } + } + getType().C_emitType(env, "*a"); + env.println(";"); + env.unindent(); + env.print("} " + name); + } + + public String Exp.C_getValue() { + throw new Error(this.getClass().getName() + + ".C_getValue()" + + " not declared"); + } + + public String IntegerLiteral.C_getValue() { + return getValue(); + } + +} + +aspect C_Declarations { + + public void Decl.C_emitDecoderDeclaration(C_env env) { + } + + public void SampleDecl.C_emitDecoderDeclaration(C_env env) { + env.println("int labcomm"+env.verStr+"_decoder_register_" + + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm"+env.verStr+"_decoder *d,"); + env.println("void (*handler)("); + env.indent(); + env.println(env.prefix + getName() + " *v,"); + env.println("void *context"); + env.unindent(); + env.println("),"); + env.println("void *context"); + env.unindent(); + env.println(");"); + + env.println("int labcomm"+env.verStr+"_decoder_ioctl_" + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm"+env.verStr+"_decoder *d,"); + env.println("int ioctl_action,"); + env.println("..."); + env.unindent(); + env.println(");"); + } + + public void Decl.C_emitEncoderDeclaration(C_env env) { + } +// + public void SampleDecl.C_emitEncoderDeclaration(C_env env) { + env.println("int labcomm"+env.verStr+"_encoder_register_" + + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm"+env.verStr+"_encoder *e);"); + env.unindent(); + + env.println("int labcomm"+env.verStr+"_encode_" + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm"+env.verStr+"_encoder *e"); + if(!isVoid() ) { + env.println(", "+env.prefix + getName() + " *v"); + } + env.unindent(); + env.println(");"); + + env.println("int labcomm"+env.verStr+"_encoder_ioctl_" + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm"+env.verStr+"_encoder *e,"); + env.println("int ioctl_action,"); + env.println("..."); + env.unindent(); + env.println(");"); + } + +} + +aspect C_Limit { + + public String Exp.C_getLimit(C_env env, int i) { + throw new Error(this.getClass().getName() + + ".C_emitDecoderLimit(C_env env, int i)" + + " not declared"); + } + + public String IntegerLiteral.C_getLimit(C_env env, int i) { + return getValue(); + } + + public String VariableSize.C_getLimit(C_env env, int i) { + return env.qualid + env.memberAccessor() + "n_" + i; + } + +} + +aspect C_Index { + + public void ArrayType.C_emitCalcIndex(C_env env) { + } + + public void VariableArrayType.C_emitCalcIndex(C_env env) { + env.print("int i_" + env.depth + " = "); + + String i_prefix = "i_" + env.depth + "_"; + String expr = i_prefix + "0"; + for (int i = 1 ; i < getNumExp() ; i++) { + expr = "(" + expr + ") * " + + getExp(i).C_getLimit(env, i) + " + " + + i_prefix + i; + } + env.println(expr + ";"); + } + +} + +aspect C_Decoder { + + public void Decl.C_emitDecoder(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitDecoder(C_env env)" + + " not declared"); + } + + public void TypeDecl.C_emitDecoder(C_env env) { + } + + public void SampleDecl.C_emitDecoder(C_env env) { + env = env.nestStruct("v"); + env.println("static void decode_" + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm"+env.verStr+"_reader *r,"); + env.println("void (*handle)("); + env.indent(); + env.println(env.prefix + getName() + " *v,"); + env.println("void *context"); + env.unindent(); + env.println("),"); + env.println("void *context"); + env.unindent(); + env.println(")"); + env.println("{"); + env.indent(); + env.println(env.prefix + getName() + " v;"); + getType().C_emitDecoder(env); + env.println("handle(&v, context);"); + if (C_isDynamic()) { + env.println("{"); + env.indent(); + getType().C_emitDecoderDeallocation(env); + env.unindent(); + env.println("}"); + } + env.unindent(); + env.println("}"); + } + + public void Type.C_emitDecoder(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitDecoder(C_env env)" + + " not declared"); + } + + public void VoidType.C_emitDecoder(C_env env) { + } + + public void PrimType.C_emitDecoder(C_env env) { + env.print(env.qualid + " = "); + switch (getToken()) { + case LABCOMM_SAMPLE: { + env.println("labcomm_internal_decoder_index_to_signature(" + + "r->decoder, labcomm"+env.verStr+"_read_int(r));"); + } break; + default: { + env.println("labcomm"+env.verStr+"_read_" + getName() + "(r);"); + }; break; + } + } + + public void UserType.C_emitDecoder(C_env env) { + lookupType(getName()).getType().C_emitDecoder(env); + } + + public void StructType.C_emitDecoder(C_env env) { + for (int i = 0 ; i < getNumField() ; i++) { + getField(i).C_emitDecoder(env); + } + } + + public void ArrayType.C_emitDecoder(C_env env) { + C_emitDecoderDecodeLimit(env); + C_emitDecoderArrayAllocate(env); + env.println("{"); + env.indent(); + C_emitLoopVariables(env); + for (int i = 0 ; i < getNumExp() ; i++) { + String iterator = "i_" + env.depth + "_" + i; + env.println("for (" + iterator + " = 0" + + " ; " + + iterator + " < " + getExp(i).C_getLimit(env, i) + + " ; " + + iterator + "++) {"); + env.indent(); + } + C_emitCalcIndex(env); + getType().C_emitDecoder(C_Nest(env)); + for (int i = getNumExp() - 1 ; i >= 0 ; i--) { + env.unindent(); + env.println("}"); + } + env.unindent(); + env.println("}"); + } + + public void Field.C_emitDecoder(C_env env) { + getType().C_emitDecoder(env.nestStruct("." + getName())); + } + + public void Exp.C_emitDecoderDecodeLimit(C_env env, int i) { + } + + public void VariableSize.C_emitDecoderDecodeLimit(C_env env, int i) { + env.println(env.qualid + ".n_" + i + " = labcomm"+env.verStr+"_read_packed32(r);"); + } + + public void ArrayType.C_emitDecoderDecodeLimit(C_env env) { + for (int i = 0 ; i < getNumExp() ; i++) { + getExp(i).C_emitDecoderDecodeLimit(env, i); + } + } + + public void ArrayType.C_emitDecoderArrayAllocate(C_env env) { + } + + public void VariableArrayType.C_emitDecoderArrayAllocate(C_env env) { + env.print(env.qualid + + ".a = labcomm"+env.verStr+"_memory_alloc(r->memory, 1, sizeof(" + + env.qualid + ".a[0])"); + for (int i = 0 ; i < getNumExp() ; i++) { + env.print(" * " + getExp(i).C_getLimit(env, i)); + } + env.println(");"); + } + + // Code for deallocation of dynamically allocated data + + public void Type.C_emitDecoderDeallocation(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitDecoderDeallocation(C_env env)" + + " not declared"); + } + + public void PrimType.C_emitDecoderDeallocation(C_env env) { + if (C_isDynamic()) { + env.println("labcomm"+env.verStr+"_memory_free(r->memory, 1, " + + env.qualid + ");"); + } + } + + public void UserType.C_emitDecoderDeallocation(C_env env) { + if (C_isDynamic()) { + lookupType(getName()).getType().C_emitDecoderDeallocation(env); + } + } + + public void StructType.C_emitDecoderDeallocation(C_env env) { + if (C_isDynamic()) { + for (int i = 0 ; i < getNumField() ; i++) { + getField(i).C_emitDecoderDeallocation(env); + } + } + } + + public void ArrayType.C_emitDecoderDeallocation(C_env env) { + if (getType().C_isDynamic()) { + env.println("{"); + env.indent(); + C_emitLoopVariables(env); + for (int i = 0 ; i < getNumExp() ; i++) { + String iterator = "i_" + env.depth + "_" + i; + env.println("for (" + iterator + " = 0" + + " ; " + + iterator + " < " + getExp(i).C_getLimit(env, i) + + " ; " + + iterator + "++) {"); + env.indent(); + } + C_emitCalcIndex(env); + getType().C_emitDecoderDeallocation(C_Nest(env)); + for (int i = 0 ; i < getNumExp() ; i++) { + env.unindent(); + env.println("}"); + } + env.unindent(); + env.println("}"); + } + } + + public void VariableArrayType.C_emitDecoderDeallocation(C_env env) { + super.C_emitDecoderDeallocation(env); + env.println("labcomm"+env.verStr+"_memory_free(r->memory, 1, " + + env.qualid + ".a);"); + } + + public void Field.C_emitDecoderDeallocation(C_env env) { + getType().C_emitDecoderDeallocation(env.nestStruct("." + getName())); + } + + public void Decl.C_emitDecoderRegisterHandler(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitDecoderRegisterHandler(C_env env)" + + " not declared"); + } + + public void TypeDecl.C_emitDecoderRegisterHandler(C_env env) { + } + + public void SampleDecl.C_emitDecoderRegisterHandler(C_env env) { + env.println("int labcomm"+env.verStr+"_decoder_register_" + + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm"+env.verStr+"_decoder *d,"); + env.println("void (*handler)("); + env.indent(); + env.println(env.prefix + getName() + " *v,"); + env.println("void *context"); + env.unindent(); + env.println("),"); + env.println("void *context"); + env.unindent(); + env.println(")"); + env.println("{"); + env.indent(); + env.println("return labcomm"+env.verStr+"_internal_decoder_register("); + env.indent(); + env.println("d,"); + env.println("&signature_" + env.prefix + getName() + ","); + env.println("(labcomm"+env.verStr+"_decoder_function)decode_" + env.prefix + getName() + ","); + env.println("(labcomm"+env.verStr+"_handler_function)handler,"); + env.println("context"); + env.unindent(); + env.println(");"); + env.unindent(); + env.println("}"); + } + +} + +aspect C_copy { + + private void SampleDecl.C_emitCopyFunctionParam(C_env env, String src, + String dst) + { + env.println("void labcomm" + env.verStr + "_copy_" + + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm" + env.verStr + "_memory *mem,"); + env.println(env.prefix + getName() + " *" + dst + ","); + env.println(env.prefix + getName() + " *" + src); + env.unindent(); + env.print(")"); + } + + public void Decl.C_emitCopyDeclaration(C_env env) { + } + + public void SampleDecl.C_emitCopyDeclaration(C_env env) { + C_emitCopyFunctionParam(env, "src", "dst"); + env.println(";"); + } + + public void Decl.C_emitCopy(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitCopy(C_env env)" + + " not declared"); + } + + public void TypeDecl.C_emitCopy(C_env env) { + } + + public void SampleDecl.C_emitCopy(C_env env) { + final String dst = "dst"; + final String src = "src"; + C_env env_src = env.nestStruct(src).setPointer(); + C_env env_dst = env.nestStruct(dst).setPointer(); + + C_emitCopyFunctionParam(env_src, src, dst); + env_src.println(""); + env_src.println("{"); + env_src.indent(); + getType().C_emitCopy(env_src, env_dst); + env_src.unindent(); + env_src.println("}"); + } + + public void Type.C_emitCopy(C_env env_src, C_env env_dst) { + throw new Error(this.getClass().getName() + + ".C_emitCopy(C_env env)" + + " not declared"); + } + + public void VoidType.C_emitCopy(C_env env_src, C_env env_dst) { + } + + public void PrimType.C_emitCopy(C_env env_src, C_env env_dst) { + if (C_isDynamic()) { + env_src.println(String.format( + "%s%s = labcomm%s_memory_alloc(mem, 1, strlen(%s%s)+1);", + env_dst.accessor(), env_dst.qualid, + env_src.verStr, + env_src.accessor(), env_src.qualid)); + env_src.println(String.format( + "memcpy(%s%s, %s%s, strlen(%s%s)+1);", + env_dst.accessor(), env_dst.qualid, + env_src.accessor(), env_src.qualid, + env_src.accessor(), env_src.qualid)); + } else { + env_src.println(env_dst.accessor() + env_dst.qualid + " = " + + env_src.accessor() + env_src.qualid + ";"); + } + } + + public void UserType.C_emitCopy(C_env env_src, C_env env_dst) { + lookupType(getName()).getType().C_emitCopy(env_src, env_dst); + } + + public void StructType.C_emitCopy(C_env env_src, C_env env_dst) { + for (int i = 0 ; i < getNumField() ; i++) { + getField(i).C_emitCopy(env_src, env_dst); + } + } + + public void ArrayType.C_emitCopy(C_env env_src, C_env env_dst) { + C_emitCopyDecodeLimit(env_src, env_dst); + C_emitCopyArrayAllocate(env_src, env_dst); + env_src.println("{"); + env_src.indent(); + C_emitLoopVariables(env_src); + for (int i = 0 ; i < getNumExp() ; i++) { + String iterator = "i_" + env_src.depth + "_" + i; + env_src.println("for (" + iterator + " = 0" + + " ; " + + iterator + " < " + getExp(i).C_getLimit(env_src, i) + + " ; " + + iterator + "++) {"); + env_src.indent(); + } + C_emitCalcIndex(env_src); + getType().C_emitCopy(C_Nest(env_src), C_Nest(env_dst)); + for (int i = getNumExp() - 1 ; i >= 0 ; i--) { + env_src.unindent(); + env_src.println("}"); + } + env_src.unindent(); + env_src.println("}"); + } + + public void Field.C_emitCopy(C_env env_src, C_env env_dst) { + String fnam = env_src.memberAccessor() + getName(); + getType().C_emitCopy(env_src.nestStruct(fnam), env_dst.nestStruct(fnam)); + } + + public void Exp.C_emitCopyDecodeLimit(C_env env_src, C_env env_dst, int i) { + // Ordinary array has no length-member. + } + + public void VariableSize.C_emitCopyDecodeLimit(C_env env_src, C_env env_dst, int i) { + String src = env_src.qualid + env_src.memberAccessor() + "n_" + i; + String dst = env_dst.qualid + env_dst.memberAccessor() + "n_" + i; + env_src.println(dst + " = " + src + ";"); + } + + public void ArrayType.C_emitCopyDecodeLimit(C_env env_src, C_env env_dst) { + for (int i = 0 ; i < getNumExp() ; i++) { + getExp(i).C_emitCopyDecodeLimit(env_src, env_dst, i); + } + } + + public void ArrayType.C_emitCopyArrayAllocate(C_env env_src, C_env env_dst) { + } + + public void VariableArrayType.C_emitCopyArrayAllocate(C_env env_src, + C_env env_dst) + { + env_src.print(env_dst.qualid + env_dst.memberAccessor() + + "a = labcomm" + env_src.verStr + + "_memory_alloc(mem, 1, sizeof(" + + env_src.qualid + env_src.memberAccessor() + "a[0])"); + for (int i = 0 ; i < getNumExp() ; i++) { + env_src.print(" * " + getExp(i).C_getLimit(env_src, i)); + } + env_dst.println(");"); + } + + // Code for deallocation of dynamically allocated data in a copy. + + private void SampleDecl.C_emitCopyDeallocationFunctionParam(C_env env, + String par) + { + env.println("void labcomm" + env.verStr + "_copy_free_" + + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm" + env.verStr + "_memory *mem,"); + env.println(env.prefix + getName() + " *" + par); + env.unindent(); + env.print(")"); + } + + public void Decl.C_emitCopyDeallocationDeclaration(C_env env) { + } + + public void SampleDecl.C_emitCopyDeallocationDeclaration(C_env env) { + C_emitCopyDeallocationFunctionParam(env, "c"); + env.println(";"); + } + + public void Decl.C_emitCopyDeallocation(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitCopy(C_env env)" + + " not declared"); + } + + public void TypeDecl.C_emitCopyDeallocation(C_env env) { + } + + public void SampleDecl.C_emitCopyDeallocation(C_env env) { + String par = "par"; + env = env.nestStruct(par).setPointer(); + + C_emitCopyDeallocationFunctionParam(env, par); + env.println(""); + env.println("{"); + env.indent(); + getType().C_emitCopyDeallocation(env); + env.unindent(); + env.println("}"); + } + + public void Type.C_emitCopyDeallocation(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitCopyDeallocation(C_env env)" + + " not declared"); + } + + public void VoidType.C_emitCopyDeallocation(C_env env) { + } + + public void PrimType.C_emitCopyDeallocation(C_env env) { + if (C_isDynamic()) { + env.println("labcomm" + env.verStr + "_memory_free(mem, 1, " + + env.accessor() + env.qualid + ");"); + } + } + + public void UserType.C_emitCopyDeallocation(C_env env) { + if (C_isDynamic()) { + lookupType(getName()).getType().C_emitCopyDeallocation(env); + } + } + + public void StructType.C_emitCopyDeallocation(C_env env) { + if (C_isDynamic()) { + for (int i = 0 ; i < getNumField() ; i++) { + getField(i).C_emitCopyDeallocation(env); + } + } + } + + public void ArrayType.C_emitCopyDeallocation(C_env env) { + if (getType().C_isDynamic()) { + env.println("{"); + env.indent(); + C_emitLoopVariables(env); + for (int i = 0 ; i < getNumExp() ; i++) { + String iterator = "i_" + env.depth + "_" + i; + env.println("for (" + iterator + " = 0" + + " ; " + + iterator + " < " + getExp(i).C_getLimit(env, i) + + " ; " + + iterator + "++) {"); + env.indent(); + } + C_emitCalcIndex(env); + getType().C_emitCopyDeallocation(C_Nest(env)); + for (int i = 0 ; i < getNumExp() ; i++) { + env.unindent(); + env.println("}"); + } + env.unindent(); + env.println("}"); + } + } + + public void VariableArrayType.C_emitCopyDeallocation(C_env env) { + super.C_emitCopyDeallocation(env); + env.println("labcomm" + env.verStr + "_memory_free(mem, 1, " + + env.qualid + env.memberAccessor() + "a);"); + } + + public void Field.C_emitCopyDeallocation(C_env env) { + getType().C_emitCopyDeallocation(env.nestStruct(env.memberAccessor() + + getName())); + } +} + +aspect C_DecoderIoctl { + + public void Decl.C_emitDecoderIoctl(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitDecoderIoctl(C_env env)" + + " not declared"); + } + + public void TypeDecl.C_emitDecoderIoctl(C_env env) { + } + + public void SampleDecl.C_emitDecoderIoctl(C_env env) { + env.println("int labcomm"+env.verStr+"_decoder_ioctl_" + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm"+env.verStr+"_decoder *d,"); + env.println("int ioctl_action,"); + env.println("..."); + env.unindent(); + env.println(")"); + env.println("{"); + env.indent(); + env.println("int result;"); + env.println("va_list va;"); + env.println("va_start(va, ioctl_action);"); + env.println("result = labcomm"+env.verStr+"_internal_decoder_ioctl("); + env.indent(); + env.println("d, &signature_" + env.prefix + getName() + ", "); + env.println("ioctl_action, va);"); + env.unindent(); + env.println("va_end(va);"); + env.println("return result;"); + env.unindent(); + env.println("}"); + } +} + + +aspect C_Encoder { + + public void Decl.C_emitEncoder(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitEncoder()" + + " not declared"); + } + + public void TypeDecl.C_emitEncoder(C_env env) { + // do nothing for type decls + } + + public void SampleDecl.C_emitEncoder(C_env env) { + env = env.nestStruct("(*v)"); + env.println("static int encode_" + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm"+env.verStr+"_writer *w"); + if(!isVoid() ) { + env.println(", "+env.prefix + getName() + " *v"); + } + env.unindent(); + env.println(")"); + env.println("{"); + env.indent(); + env.println("int result = 0;"); + getType().C_emitEncoder(env); + env.println("return result;"); + env.unindent(); + env.println("}"); + + // Typesafe encode wrapper + env.println("int labcomm"+env.verStr+"_encode_" + env.prefix + getName() + "("); + env.println("struct labcomm"+env.verStr+"_encoder *e"); + if(!isVoid() ) { + env.println(", "+env.prefix + getName() + " *v"); + } + env.unindent(); + env.println(")"); + env.println("{"); + env.indent(); + env.println("return labcomm"+env.verStr+"_internal_encode(e, &signature_" + + env.prefix + getName() + + ", (labcomm"+env.verStr+"_encoder_function)encode_" + + env.prefix + getName() + + (!isVoid()?", v":", NULL")+");"); + env.unindent(); + env.println("}"); + } + + public void Type.C_emitEncoder(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitEncoder(C_env env)" + + " not declared"); + } + + public void VoidType.C_emitEncoder(C_env env) { + env.println("result = 0;"); + } + + public void PrimType.C_emitEncoder(C_env env) { + env.print("result = "); + switch (getToken()) { + case LABCOMM_SAMPLE: { + env.println("labcomm"+env.verStr+"_write_int(w, " + + "labcomm_internal_encoder_signature_to_index(w->encoder, " + + env.qualid + "));"); + } break; + default: { + env.println("labcomm"+env.verStr+"_write_" + getName() + + "(w, " + env.qualid + ");"); + } break; + } + env.println("if (result != 0) { return result; }"); + } + + public void UserType.C_emitEncoder(C_env env) { + decl().getType().C_emitEncoder(env); + } + + public void StructType.C_emitEncoder(C_env env) { + for (int i = 0 ; i < getNumField() ; i++) { + getField(i).C_emitEncoder(env); + } + } + + public void ArrayType.C_emitEncoder(C_env env) { + C_emitEncoderEncodeLimit(env); + env.println("{"); + env.indent(); + C_emitLoopVariables(env); + for (int i = 0 ; i < getNumExp() ; i++) { + String iterator = "i_" + env.depth + "_" + i; + env.println("for (" + iterator + " = 0" + + " ; " + + iterator + " < " + getExp(i).C_getLimit(env, i) + + " ; " + + iterator + "++) {"); + env.indent(); + } + C_emitCalcIndex(env); + getType().C_emitEncoder(C_Nest(env)); + for (int i = getNumExp() - 1 ; i >= 0 ; i--) { + env.unindent(); + env.println("}"); + } + env.unindent(); + env.println("}"); + } + + public void Field.C_emitEncoder(C_env env) { + getType().C_emitEncoder(env.nestStruct("." + getName())); + } + + public void Exp.C_emitEncoderEncodeLimit(C_env env, int i) { + } + + public void VariableSize.C_emitEncoderEncodeLimit(C_env env, int i) { + env.println("labcomm"+env.verStr+"_write_packed32(w, " + env.qualid + ".n_" + i + ");"); + } + + public void ArrayType.C_emitEncoderEncodeLimit(C_env env) { + for (int i = 0 ; i < getNumExp() ; i++) { + getExp(i).C_emitEncoderEncodeLimit(env, i); + } + } + + public void Decl.C_emitEncoderRegisterHandler(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitEncoderRegisterHandler(C_env env)" + + " not declared"); + } + + public void TypeDecl.C_emitEncoderRegisterHandler(C_env env) { + // do nothing for type decls + } + + public void SampleDecl.C_emitEncoderRegisterHandler(C_env env) { + env.println("int labcomm"+env.verStr+"_encoder_register_" + + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm"+env.verStr+"_encoder *e"); + env.unindent(); + env.println(")"); + env.println("{"); + env.indent(); + C_emitUserTypeDeps(env, null, false); //XXX HERE BE DRAGONS + //currently set to false to turn off + //outputting of code + env.println("return labcomm"+env.verStr+"_internal_encoder_register("); + env.indent(); + env.println("e,"); + env.println("&signature_" + env.prefix + getName() + ","); + env.println("(labcomm"+env.verStr+"_encoder_function)encode_" + env.prefix + getName()); + env.unindent(); + env.println(");"); + env.unindent(); + env.println("}"); + } + +} + +aspect C_EncoderIoctl { + + public void Decl.C_emitEncoderIoctl(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitEncoderIoctl()" + + " not declared"); + } + + public void TypeDecl.C_emitEncoderIoctl(C_env env) { + } + + public void SampleDecl.C_emitEncoderIoctl(C_env env) { + env.println("int labcomm"+env.verStr+"_encoder_ioctl_" + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm"+env.verStr+"_encoder *e,"); + env.println("int ioctl_action,"); + env.println("..."); + env.unindent(); + env.println(")"); + env.println("{"); + env.indent(); + env.println("int result;"); + env.println("va_list va;"); + env.println("va_start(va, ioctl_action);"); + env.println("result = labcomm"+env.verStr+"_internal_encoder_ioctl("); + env.indent(); + env.println("e, &signature_" + env.prefix + getName() + ", "); + env.println("ioctl_action, va);"); + env.unindent(); + env.println("va_end(va);"); + env.println("return result;"); + env.unindent(); + env.println("}"); + } + +} + +aspect C_TypeDependencies { + public void Decl.C_emitUserTypeDeps(C_env env, String via, boolean outputCode) { + if( hasDependencies() ) { + Iterator<Decl> it = type_dependencies().iterator(); + while(it.hasNext()) { + Decl t = it.next(); + + t.C_emitUserTypeDeps(env, t.getName(), outputCode); + if(outputCode) { + System.out.println("Decl.C_emitUserTypeDeps registering "+t.getName()); + env.println("labcomm"+env.verStr+"_encoder_register_"+env.prefix + t.getName()+"(e);"); + } else { // Just output a comment + String refpath = (via == null) ? "directly" : "indirectly via "+via; + env.println(" //Depends ("+refpath+") on "+t.getName() ); + } + } + } + } + public void Decl.C_emitUserTypeRefs(C_env env, String via, boolean outputCode) { + if( isReferenced() ) { + Iterator<Decl> it = type_references().iterator(); + while(it.hasNext()) { + Decl t = it.next(); + + t.C_emitUserTypeRefs(env, t.getName(), outputCode); + if(outputCode) { + env.println("labcomm"+env.verStr+"_encoder_register_"+env.prefix + t.getName()+"(e);"); + } else { // Just output a comment + String refpath = (via == null) ? "directly" : "indirectly via "+via; + env.println(" //Is referenced ("+refpath+") by "+t.getName() ); + } + } + } + } +} + +aspect C_Signature { + + public void ASTNode.C_emitSignature(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitSignature(C_env env)" + + " not declared"); + } + + syn String Decl.C_DeclTypeString(); + eq SampleDecl.C_DeclTypeString() = "LABCOMM_SAMPLE"; + eq TypeDecl.C_DeclTypeString() = "LABCOMM_TYPEDEF"; + + public void Decl.C_emitSignature(C_env env) { + C_emitFlatSignature(env); +// +// if( false && (isReferenced() || isSampleDecl())){ +// Signature signature = getSignature(); +// signature.C_emitSignature(env, !isSampleDecl()); +// } else { +// env.println("// not emitting signature for "+getName()+isReferenced()+isSampleDecl()); +// } +// if(env.versionHasMetaData()) { +// if(isReferenced() || isSampleDecl()){ +// env.println("(int (*)(void *))labcomm"+env.verStr+"_signature_" + +// env.prefix + getName() + "_emit_signature"); +// } else { +// env.println("NULL"); // HERE BE DRAGONS! Is it worth the size saving to skip emitting the emit_signature function for unused types? +// // The code won't likely end up in a target system anyway? +// } +// } +// env.unindent(); +// env.println(" };"); +// + } + + public void ASTNode.C_emitFlatSignature(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitFlatSignature(C_env env)" + + " not declared"); + } + + public void Decl.C_emitFlatSignature(C_env env) { + } + + public void SampleDecl.C_emitFlatSignature(C_env env){ + env.println("static unsigned char signature_bytes_" + + env.prefix + getName() + "[] = {"); + 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.println("};"); + + C_emitSizeofValue(env); + env.println("static struct labcomm"+env.verStr+"_signature " + + "signature_" + env.prefix + getName() + " = {"); + env.indent(); + env.println("\"" + getName() + "\","); + env.println("sizeof_" + env.prefix + getName() + ","); + env.println("sizeof(signature_bytes_" + env.prefix + getName() + "),"); + env.println("signature_bytes_" + env.prefix + getName() + ","); + env.println("0"); + env.unindent(); + env.println(" };"); + env.println("const struct labcomm"+env.verStr+"_signature " + + "*labcomm"+env.verStr+"_signature_" + env.prefix + getName() + + " = &signature_" + env.prefix + getName() + ";"); + } + + public void Signature.C_emitSignature(C_env env, boolean decl){ + getSignatureList().C_emitSignature(env, decl); + } + + public abstract void SignatureLine.C_emitSignature(C_env env, boolean decl); + + public void TypeRefSignatureLine.C_emitSignature(C_env env, boolean isDecl){ + //env.print(getIndentString()); + //env.println("LABCOMM_SIGDEF_SIGNATURE(labcomm"+env.verStr+"_signature_" + env.prefix + decl.getName() +"),"); + } + + public void DataSignatureLine.C_emitSignature(C_env env, boolean decl){ + // String comment = getComment(); + // if (comment != null && comment.length() > 0) { + // env.println(getIndentString() + "// " + comment); + // } + // byte[] data = getData(env.version); + // if (data != null && data.length > 0) { + // env.print(getIndentString()); + // env.print("LABCOMM_SIGDEF_BYTES("+data.length+", \""); + // for (int j = 0 ; j < data.length ; j++) { + // byte d = data[j]; + // //if(d>='a'&&d<='z' || d>='A'&&d<='Z'|| d>='0'&&d<='9' ) + // // env.print(""+(char)d); + // //else + // env.print("\\x"+Integer.toHexString(d)); + // } + // env.println("\"),"); + // } + } +// +// +// byte[] data = getData(env.version); +// if (data != null) { +// for (int j = 0 ; j < data.length ; j++) { +// env.print(getIndentString()); +// //env.print("printf(\"labcomm"+env.verStr+"_write_byte( w, (unsigned char)"+ String.format("0x%02X ", data[j]) +")\\n\"); "); +// env.print("labcomm"+env.verStr+"_write_byte( w, (unsigned char)"+ String.format("0x%02X ", data[j]) +"); "); +// env.println("if (result != 0) { return result; }"); +// } +// env.println(); +// } +// +//} + public void SignatureList.C_emitSignature(C_env env, boolean decl) { +// env.println("static struct labcomm_signature_data signature_tree_" + +// env.prefix + parentDecl().getName() + "[] = {"); +// env.indent(); +// for (int i = 0 ; i < size() ; i++) { +// SignatureLine l = getSignatureLine(i); +// l.C_emitSignature(env, decl); +// } +// +// env.println("LABCOMM_SIGDEF_END"); +// env.println("};"); +// env.unindent(); +// env.println(); + } + + + +// public void SampleDecl.C_emitSignature(C_env env) { +// env.println("static unsigned char signature_bytes_" + +// env.prefix + getName() + "[] = {"); +// SignatureList signature = signature(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); +// if (data != null) { +// env.print(signature.getIndent(i)); +// for (int j = 0 ; j < data.length ; j++) { +// env.print(data[j] + ", "); +// } +// env.println(""); +// } +// } +// env.println("};"); +// env.println("struct labcomm"+env.verStr+"_signature labcomm"+env.verStr+"_signature_" + +// env.prefix + getName() + " = {"); +// env.indent(); +// env.println("LABCOMM_SAMPLE, \"" + getName() + "\","); +// env.println("(int (*)(struct labcomm"+env.verStr+"_signature *, void *))labcomm"+env.verStr+"_sizeof_" + +// env.prefix + getName() + ","); +// env.println("sizeof(signature_bytes_" + env.prefix + getName() + "),"); +// env.println("signature_bytes_" + env.prefix + getName() + ","); +// env.println("0"); +// env.unindent(); +// env.println(" };"); +// } + +} +aspect C_Constructor { + public void ASTNode.C_emitConstructor(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitConstructor(C_env env)" + + " not declared"); + } + + public void Program.C_emitConstructor(C_env env) { + env.println("LABCOMM_CONSTRUCTOR void init_" + + env.prefix + "_signatures(void)"); + env.println("{"); + env.indent(); + env.println("static int initialized = 0;"); + env.println("if (initialized == 0) {"); + env.indent(); + env.println("initialized = 1;"); + for (int i = 0; i < getNumDecl(); i++) { + getDecl(i).C_emitConstructor(env); + } + env.unindent(); + env.println("}"); + env.unindent(); + env.println("}"); + } + + public void Decl.C_emitConstructor(C_env env) { + } +//XXX + public void SampleDecl.C_emitConstructor(C_env env) { + env.println("labcomm"+env.verStr+"_set_local_index(&signature_" + + env.prefix + getName() + ");"); + } + + + public void ASTNode.C_emitConstructorDeclaration(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitConstructorDeclaration(C_env env)" + + " not declared"); + } + + public void Program.C_emitConstructorDeclaration(C_env env) { + env.println("void init_" + env.prefix + "_signatures(void);"); + } + +} + +aspect C_Sizeof { + public void Decl.C_emitSizeofDeclaration(C_env env) { + } + + public void SampleDecl.C_emitSizeofDeclaration(C_env env) { + env.println("extern int labcomm"+env.verStr+"_sizeof_" + env.prefix + getName() + + "(" + env.prefix + getName() + " *v);"); + } + + public int Decl.C_fixedSizeof() { + return getType().C_fixedSizeof(); + } + + public void Decl.C_emitSizeof(C_env env) { + } + + public void SampleDecl.C_emitSizeof(C_env env) { + env = env.nestStruct("(*v)"); + env.println("int labcomm"+env.verStr+"_sizeof_" + env.prefix + getName() + + "(" + env.prefix + getName() + " *v)"); + env.println("{"); + env.indent(); + env.println("return labcomm"+env.verStr+"_internal_sizeof(" + + "&signature_" + env.prefix + getName() + + ", v);"); + env.unindent(); + env.println("}"); + } + + public int Type.C_fixedSizeof() { + throw new Error(this.getClass().getName() + + ".C_fixedSizeof()" + + " not declared"); + } + + public int VoidType.C_fixedSizeof() { + return 0; + } + + public int PrimType.C_fixedSizeof() { + switch (getToken()) { + case LABCOMM_BOOLEAN: { return 1; } + case LABCOMM_BYTE: { return 1; } + case LABCOMM_SHORT: { return 2; } + case LABCOMM_INT: { return 4; } + case LABCOMM_LONG: { return 8; } + case LABCOMM_FLOAT: { return 4; } + case LABCOMM_DOUBLE: { return 8; } + case LABCOMM_SAMPLE: { return 4; } + default: { + throw new Error(this.getClass().getName() + + ".C_fixedSizeof()" + + " unknown size (" + getName() + ")"); + } + } + } + + public int UserType.C_fixedSizeof() { + return lookupType(getName()).getType().C_fixedSizeof(); + } + + public int StructType.C_fixedSizeof() { + int result = 0; + for (int i = 0 ; i < getNumField() ; i++) { + result += getField(i).getType().C_fixedSizeof(); + } + return result; + } + + public int ArrayType.C_fixedSizeof() { + int elements = 1; + for (int i = 0 ; i < getNumExp() ; i++) { + int n = Integer.parseInt(((IntegerLiteral)getExp(i)).getValue()); + elements = elements * n; + } + return getType().C_fixedSizeof() * elements; + } + + public void Decl.C_emitSizeofValue(C_env env) { + } + + public void SampleDecl.C_emitSizeofValue(C_env env) { + env = env.nestStruct("(*v)"); + env.println("static int sizeof_" + env.prefix + getName() + "(void *vv)"); + env.println("{"); + env.indent(); + env.println("int result = 0;"); + if (C_isDynamic()) { + env.println(env.prefix + getName() + " *v = vv;"); + getType().C_emitSizeof(env); + } else { + env.println("result += " + C_fixedSizeof() + ";"); + } + env.println("return result;"); + env.unindent(); + env.println("}"); + } + + public void Type.C_emitSizeof(C_env env) { + throw new Error(this.getClass().getName() + + ".C_emitSizeof(C_env env)" + + " not declared"); + } + + public void PrimType.C_emitSizeof(C_env env) { + switch (getToken()) { + case LABCOMM_STRING: { + env.print("{ int l = strlen(" + env.qualid + "); "); + env.println("result += labcomm"+env.verStr+"_size_packed32(l) + l; }"); + } break; + default: { + throw new Error(this.getClass().getName() + + ".C_emitSizeof(C_env env)" + + " known size (" + getName() + ")"); + } + } + } + + public void UserType.C_emitSizeof(C_env env) { + lookupType(getName()).getType().C_emitSizeof(env); + } + + public void StructType.C_emitSizeof(C_env env) { + int fixed = 0; + for (int i = 0 ; i < getNumField() ; i++) { + if (getField(i).getType().C_isDynamic()) { + getField(i).getType().C_emitSizeof( + env.nestStruct("." + getField(i).getName())); + } else { + fixed += getField(i).getType().C_fixedSizeof(); + } + } + if (fixed > 0) { + env.println("result += " + fixed + ";"); + } + } + + public void ArrayType.C_emitSizeof(C_env env) { + if (getType().C_isDynamic()) { + env.println("{"); + env.indent(); + C_emitLoopVariables(env); + for (int i = 0 ; i < getNumExp() ; i++) { + String iterator = "i_" + env.depth + "_" + i; + env.println("for (" + iterator + " = 0" + + " ; " + + iterator + " < " + getExp(i).C_getLimit(env, i) + + " ; " + + iterator + "++) {"); + env.indent(); + } + C_emitCalcIndex(env); + getType().C_emitSizeof(C_Nest(env)); + for (int i = 0 ; i < getNumExp() ; i++) { + env.unindent(); + env.println("}"); + } + env.unindent(); + env.println("}"); + } else { + for (int i = 0 ; i < getNumExp() ; i++) { + env.println("result += labcomm"+env.verStr+"_size_packed32(" + + getExp(i).C_getLimit(env, i) + ");"); + } + env.print("result += " + getType().C_fixedSizeof()); + for (int i = 0 ; i < getNumExp() ; i++) { + env.print(" * " + getExp(i).C_getLimit(env, i)); + } + env.println(";"); + } + } +} + +aspect C_forAll { + + public void Program.C_emitForAll(C_env env) { + env.print("#define LABCOMM_FORALL_SAMPLES_" + env.lcName + + "(func, sep)"); + env.indent(); + boolean needSeparator = false; + for (int i = 0; i < getNumDecl(); i++) { + String s = getDecl(i).C_forAll(env); + if (s != null) { + if (needSeparator) { env.print(" sep"); } + env.println(" \\"); + env.print(s); + needSeparator = true; + } + } + env.println(""); + env.unindent(); + } + + public String Decl.C_forAll(C_env env) { + return null; + } + + public String SampleDecl.C_forAll(C_env env) { + return "func(" + getName() + ", " + env.prefix + getName() + ")"; + } + +} + +aspect C_Info { + + public void Program.C_info(PrintStream out, String prefix, int version) { + C_env env = new C_env("", "", prefix, out, version); + for (int i = 0; i < getNumDecl(); i++) { + getDecl(i).C_info(env); + } + } + + public void Decl.C_info(C_env env) { + throw new Error(this.getClass().getName() + + ".C_info((C_env env)" + + " not declared"); + } + + public void TypeDecl.C_info(C_env env) { + env.println(",C,typedef," + env.prefix + getName() + "," + + env.prefix + getName() + "," + + C_info_type_or_void(env.prefix)); + } + + public void SampleDecl.C_info(C_env env) { + env.println(",C,sample," + env.prefix + getName() + "," + + env.prefix + getName() + "," + + C_info_type_or_void(env.prefix)); + } + + // make void types explicitly as they require special treatment + // in encoder/decoder calls + protected String Decl.C_info_type_or_void(String prefix) { + if(isVoid() ) { + return "void"; + } else { + return prefix + getName() ; + } + } +} diff --git a/compiler/2014/DeclNames.jrag b/compiler/2014/DeclNames.jrag new file mode 100644 index 0000000..042739b --- /dev/null +++ b/compiler/2014/DeclNames.jrag @@ -0,0 +1,14 @@ +aspect DeclNames { + inh String Type.declName(); + eq Decl.getType().declName() = getName(); + + inh String Field.declName(); + eq StructType.getField(int i).declName() = declName(); + + //TODO: aspect should be renamed to parent-something + + inh Decl Type.parentDecl(); + inh Decl Field.parentDecl(); + eq Decl.getType().parentDecl() = this; + eq StructType.getField(int i).parentDecl() = parentDecl(); +} diff --git a/compiler/2014/ErrorCheck.jrag b/compiler/2014/ErrorCheck.jrag new file mode 100644 index 0000000..caa8081 --- /dev/null +++ b/compiler/2014/ErrorCheck.jrag @@ -0,0 +1,31 @@ +import java.util.Collection; + +aspect ErrorCheck { + + syn int ASTNode.lineNumber() = getLine(getStart()); + + protected String ASTNode.errors = null; + + protected void ASTNode.error(String s) { + s = "Error at " + lineNumber() + ": " + s; + if(errors == null) { + errors = s; + } else { + errors = errors + "\n" + s; + } + } + + protected boolean ASTNode.hasErrors() { + return errors != null; + } + public void ASTNode.errorCheck(Collection collection) { + nameCheck(); + typeCheck(); + if(hasErrors()) + collection.add(errors); + for(int i = 0; i < getNumChild(); i++) { + getChild(i).errorCheck(collection); + } + } + +} diff --git a/compiler/2014/FlatSignature.jrag b/compiler/2014/FlatSignature.jrag new file mode 100644 index 0000000..2a9ca4d --- /dev/null +++ b/compiler/2014/FlatSignature.jrag @@ -0,0 +1,123 @@ +import java.util.*; + +aspect FlatSignature { + + public SignatureList Decl.flatSignature(int version) { + SignatureList result = getSignature().getFlatSignatureList(); + return result; + } + + public void ASTNode.flatSignature(SignatureList list) { + throw new Error(this.getClass().getName() + + ".flatSignature(SignatureList list)" + + " not declared"); + } + + public void TypeDecl.flatSignature(SignatureList list) { + getType().flatSignature(list); + } + + public void SampleDecl.flatSignature(SignatureList list) { + getType().flatSignature(list); + } + + public void SampleRefType.flatSignature(SignatureList list) { + list.addInt(LABCOMM_SAMPLE_REF, "sample"); + } + + public void VoidType.flatSignature(SignatureList list) { + list.addInt(LABCOMM_STRUCT, "void"); + list.addInt(0, null); + } + + public void PrimType.flatSignature(SignatureList list) { + list.addInt(getToken(), null); + } + + public void UserType.flatSignature(SignatureList list) { + lookupType(getName()).flatSignature(list); + } + + public void ArrayType.flatSignature(SignatureList list) { + list.addInt(LABCOMM_ARRAY, signatureComment()); + list.indent(); + list.addInt(getNumExp(), null); + for (int i = 0 ; i < getNumExp() ; i++) { + getExp(i).flatSignature(list); + } + getType().flatSignature(list); + list.unindent(); + list.add(null, "}"); + } + + public void StructType.flatSignature(SignatureList list) { + list.addInt(LABCOMM_STRUCT, "struct { " + getNumField() + " fields"); + list.indent(); + list.addInt(getNumField(), null); + for (int i = 0 ; i < getNumField() ; i++) { + getField(i).flatSignature(list); + } + list.unindent(); + list.add(null, "}"); + } + + public void Field.flatSignature(SignatureList list) { + list.addString(getName(), signatureComment()); + getType().flatSignature(list); + } + + public void IntegerLiteral.flatSignature(SignatureList list) { + list.addInt(Integer.parseInt(getValue()), null); + } + + public void VariableSize.flatSignature(SignatureList list) { + list.addInt(0, null); + } + + public String ArrayType.signatureComment() { + StringBuffer result = new StringBuffer("array ["); + for (int i = 0 ; i < getNumExp() ; i++) { + if (i > 0) { + result.append(", "); + } + result.append(getExp(i).signatureComment()); + } + result.append("]"); + return result.toString(); + } + + public String ASTNode.signatureComment() { + throw new Error(this.getClass().getName() + + ".signatureComment()" + + " not declared"); + } + + public String Field.signatureComment() { + return getType().signatureComment() + " '" + getName() +"'"; + } + + public String SampleRefType.signatureComment() { + return "sample"; + } + + public String PrimType.signatureComment() { + return getName(); + } + + public String UserType.signatureComment() { + return getName(); + } + + public String StructType.signatureComment() { + return "struct"; + } + + public String IntegerLiteral.signatureComment() { + return getValue(); + } + + public String VariableSize.signatureComment() { + return "_"; + } + +} diff --git a/compiler/2014/Java_CodeGen.jrag b/compiler/2014/Java_CodeGen.jrag new file mode 100644 index 0000000..478a0ac --- /dev/null +++ b/compiler/2014/Java_CodeGen.jrag @@ -0,0 +1,1056 @@ +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(); + + 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 = LabCommVersion.versionString(version); + 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() ); + } + } +// 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); + env.println("e.register(dispatcher);"); + env.unindent(); + env.println("}"); + env.println("public static void registerSampleRef(Encoder e) throws IOException{"); + env.indent(); + env.println("e.registerSampleRef(dispatcher);"); + 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, h);"); + env.unindent(); + env.println("}"); + env.println("public static void registerSampleRef(Decoder d) throws IOException {"); + env.indent(); + env.println("d.registerSampleRef(dispatcher);"); + 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 Dispatcher dispatcher = new Dispatcher();"); + env.println(); + env.println("public SampleDispatcher getDispatcher() {"); + env.indent(); + env.println("return dispatcher;"); + env.unindent(); + env.println("}"); + env.println(); + env.println("private static class Dispatcher implements SampleDispatcher "+genericStr+"{"); + env.indent(); + 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. */"); + 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; + case LABCOMM_SAMPLE: { env.print("e.encodeSampleRef"); } 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; + case LABCOMM_SAMPLE: { env.println("d.decodeSampleRef();"); } 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; + case LABCOMM_SAMPLE: { env.print("Class"); } 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; + case LABCOMM_SAMPLE: { env.print("Class"); } 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(); + } + +} diff --git a/compiler/2014/LabComm.ast b/compiler/2014/LabComm.ast new file mode 100644 index 0000000..904cc17 --- /dev/null +++ b/compiler/2014/LabComm.ast @@ -0,0 +1,39 @@ +Program ::= Decl*; + +//TODO: Add signatures to the abstract grammar, so that +//they can be extended and refined by more than one aspect. +//sketch: +Signature ::= SignatureList FlatSignatureList:SignatureList; +SignatureList ::= SignatureLine*; +abstract SignatureLine ::= <Indent:int> <Comment:String>; +abstract DataSignatureLine : SignatureLine; +ByteArraySignatureLine : DataSignatureLine ::= <Data:byte[]>; +IntSignatureLine : DataSignatureLine ::= <Data:int>; +StringSignatureLine : DataSignatureLine ::= <Data:String>; +TypeRefSignatureLine : SignatureLine ::= Decl; + + +//abstract Decl ::= Type <Name:String>; +// the signature list be defined as a non-terminal attribute: +abstract Decl ::= Type <Name:String> /Signature/; +TypeDecl : Decl; +SampleDecl : Decl; + +Field ::= Type <Name:String>; + +abstract Type; +VoidType : Type; +SampleRefType : Type; +PrimType : Type ::= <Name:String> <Token:int>; +UserType : Type ::= <Name:String>; +StructType : Type ::= Field*; +ParseArrayType : Type ::= Type Dim*; +abstract ArrayType :Type ::= Type Exp*; +VariableArrayType : ArrayType; +FixedArrayType : ArrayType; + +Dim ::= Exp*; + +abstract Exp; +IntegerLiteral : Exp ::= <Value:String>; +VariableSize : Exp; diff --git a/compiler/2014/LabComm.java b/compiler/2014/LabComm.java new file mode 100644 index 0000000..d041389 --- /dev/null +++ b/compiler/2014/LabComm.java @@ -0,0 +1,404 @@ +package se.lth.control.labcomm2014.compiler; + +import java.io.*; +import java.util.*; + +public class LabComm { + + private static void println(String s) { + System.out.println(s); + } + + private static void print_help() { + println("\n Usage: java -jar labcom.jar [options*] FILE"); + println(""); + println(" --help Shows this help text"); + println(" -v Be verbose"); + println(" --ver=VERSION Generate code for labcomm VERSION (=2006 or 2013)"); + println("[ C options ]"); + println(" -C Generates C/H code in FILE.[ch]"); + println(" --cprefix=PREFIX Prefixes C types with PREFIX"); + println(" --cinclude=FILE Include FILE in generated .c"); + println(" --c=CFILE Generates C code in CFILE"); + println(" --h=HFILE Generates H code in HFILE"); + println("[ C# options]"); + println(" --cs Generates C# code in FILE.cs"); + println(" --cs=CSFILE Generates C# code in CSFILE"); + println(" --csnamespace=NAMESPACE Place C# classes in NAMESPACE"); + println("[ Java options ]"); + println(" --java=JDIR Generates Java files in JDIR"); + println(" --javapackage=PACKAGE Place Java classes in PACKAGE"); + println("[ Python options ]"); + println(" -P Generates Python code in FILE.py"); + println(" --python=PFILE Generates Python code in PFILE"); + println("[ RAPID options ]"); + println(" --rapid Generates RAPID code in FILE.sys"); + println("[ Misc options ]"); + println(" --pretty=PFILE Pretty prints to PFILE"); + println(" --typeinfo=TIFILE Generates typeinfo in TIFILE"); + } + + /** To be cleaned up. + */ + private static void checkVersion(int v) { + if(! (v == 2006 || v == 2014) ) { + System.err.println(" Unknown version: " + v); + System.err.println(" Supported versions: 2006, 2014 "); + System.exit(2); + } + } + + private static void genH(Program p, String hName, + Vector cIncludes, String coreName, String prefix, int ver) { + try { + FileOutputStream f; + PrintStream out; + + f = new FileOutputStream(hName); + out = new PrintStream(f); + p.C_genH(out, cIncludes, coreName, prefix, ver); + out.close(); + } catch (IOException e) { + System.err.println("IOException: " + hName + " " + e); + } + } + + private static void genC(Program p, String cName, + Vector cIncludes, String coreName, String prefix, int ver) { + try { + FileOutputStream f; + PrintStream out; + + f = new FileOutputStream(cName); + out = new PrintStream(f); + p.C_genC(out, cIncludes, coreName, prefix, ver); + out.close(); + } catch (IOException e) { + System.err.println("IOException: " + cName + " " + e); + } + } + + private static void genCS(Program p, String csName, String csNamespace, int ver) { +// throw new Error("C# generation currently disabled"); + try { + p.CS_gen(csName, csNamespace, ver); + } catch (IOException e) { + System.err.println("IOException: " + csName + " " + + csNamespace + " " + e); + } + } + + private static void genJava(Program p, String dirName, String packageName, int ver) { + try { + p.J_gen(dirName, packageName, ver); + } catch (IOException e) { + System.err.println("IOException: " + dirName + " " + + packageName + " " + e); + } + } + + private static void genPython(Program p, String filename, String prefix, int ver) { + try { + FileOutputStream f; + PrintStream out; + + f = new FileOutputStream(filename); + out = new PrintStream(f); + p.Python_gen(out, prefix, ver); + out.close(); + } catch (IOException e) { + System.err.println("IOException: " + filename + " " + e); + } + } + + private static void genRAPID(Program p, String filename, String prefix, int ver) { + try { + p.RAPID_gen(filename, prefix, ver); + } catch (IOException e) { + System.err.println("IOException: " + filename + " " + e); + } + } + + /** Helper class to contain command line options + and their associated behaviour + **/ + private static class Opts { + final String[] args; + String coreName = null; + String prefix = null; + boolean verbose = false; + int ver = 2013; //Version 2013 as default + String cFile = null; + String hFile = null; + Vector cIncludes = new Vector(); + String cPrefix; // gets default value (prefix) in processFilename + String csFile = null; + String csNamespace = null; + String javaDir = null; + String javaPackage = ""; + String pythonFile = null; + String prettyFile = null; + String typeinfoFile = null; + String rapidFile = null; + String fileName = null; + + Opts(String[] args) { + this.args = args; + } + + private static String getCoreName(String s) { + int i = s.lastIndexOf('.'); + return s.substring(0, i > 0 ? i : s.length()); + } + + private static String getFileName(String s) { + return s.substring(s.lastIndexOf('/') + 1, s.length()); + } + + private static String getBaseName(String s) { + s = getFileName(s); + int i = s.lastIndexOf('.'); + return s.substring(0, i > 0 ? i : s.length()); + } + + private static String getPrefix(String s) { + return s.substring(s.lastIndexOf('/') + 1, s.length()); + } + + boolean processFilename(){ + // Scan for first non-option + for (int i = 0 ; i < args.length ; i++) { + if (! args[i].startsWith("-")) { + fileName = args[i]; + break; + } + } + if (fileName != null) { + coreName = getBaseName(fileName); + prefix = getPrefix(coreName); + cPrefix = prefix; + } + return fileName != null; + } + + void processArgs(){ + for (int i = 0 ; i < args.length ; i++) { + if (fileName == null || + args[i].equals("-help") || + args[i].equals("-h") || + args[i].equals("--help")) { + print_help(); + System.exit(0); + } else if (args[i].equals("-v")) { + verbose=true; + } else if (args[i].startsWith("--ver=")) { + ver = Integer.parseInt(args[i].substring(6)); + checkVersion(ver); + } else if (args[i].equals("-C")) { + cFile = coreName + ".c"; + hFile = coreName + ".h"; + } else if (args[i].startsWith("--cinclude=")) { + cIncludes.add(args[i].substring(11)); + } else if (args[i].startsWith("--cprefix=")) { + cPrefix = args[i].substring(10); + } else if (args[i].startsWith("--c=")) { + cFile = args[i].substring(4); + } else if (args[i].startsWith("--h=")) { + hFile = args[i].substring(4); + } else if (args[i].equals("--cs")) { + csFile = coreName + ".cs"; + } else if (args[i].startsWith("--cs=")) { + csFile = args[i].substring(5); + } else if (args[i].startsWith("--csnamespace=")) { + csNamespace = args[i].substring(14); + } else if (args[i].startsWith("--java=")) { + javaDir = args[i].substring(7); + } else if (args[i].startsWith("--javapackage=")) { + javaPackage = args[i].substring(14); + } else if (args[i].equals("-P")) { + pythonFile = coreName + ".py"; + } else if (args[i].startsWith("--python=")) { + pythonFile = args[i].substring(9); + } else if (args[i].startsWith("--pretty=")) { + prettyFile = args[i].substring(9); + } else if (args[i].startsWith("--typeinfo=")) { + typeinfoFile = args[i].substring(11); + } else if (args[i].equals("--rapid")) { + rapidFile = coreName + ".sys"; + } else if (i == args.length - 1) { + fileName = args[i]; + } else { + System.err.println(" Unknown argument " + args[i]); + print_help(); + System.exit(2); + } + } + if(prefix==null){ + System.err.println(" WARNING! prefix==null"); + prefix=""; + } + } + + Program parseFile(){ + Program ast = null; + try { + // Check for errors + LabCommScanner scanner = new LabCommScanner( + new FileReader(fileName)); + LabCommParser parser = new LabCommParser(); + Program p = (Program)parser.parse(scanner); + Collection errors = new LinkedList(); + p.errorCheck(errors); + + if (errors.isEmpty()) { + ast = p; + } else { + for (Iterator iter = errors.iterator(); iter.hasNext(); ) { + String s = (String)iter.next(); + System.out.println(s); + } + } + } catch (FileNotFoundException e) { + System.err.println("Could not find file: " + fileName); + } catch (IOException e) { + System.err.println("IOException: " + fileName + " " + e); + } catch (beaver.Parser.Exception e) { + System.err.println(e.getMessage()); + } + return ast; + } + + boolean generateC(Program ast) { + boolean wroteFile = false; + Vector hIncludes = new Vector(cIncludes); + if (hFile != null) { + cIncludes.add(hFile); + } + if (cFile != null) { + printStatus("C: " , cFile); + genC(ast, cFile, cIncludes, coreName, cPrefix, ver); + wroteFile = true; + } + if (hFile != null) { + printStatus("H: " , hFile); + genH(ast, hFile, hIncludes, coreName, cPrefix, ver); + wroteFile = true; + } + return wroteFile; + } + + boolean generateCS(Program ast) { + boolean wroteFile = false; + if (csFile != null) { + printStatus("C#: " , csFile); + genCS(ast, csFile, csNamespace, ver); + wroteFile = true; + } + return wroteFile; + } + + boolean generateJava(Program ast) { + boolean wroteFile = false; + if (javaDir != null) { + printStatus("Java: " , javaDir); + genJava(ast, javaDir, javaPackage, ver); + wroteFile = true; + } + return wroteFile; + } + + boolean generatePython(Program ast) { + boolean wroteFile = false; + if (pythonFile != null) { + printStatus("Python: " , pythonFile); + genPython(ast, pythonFile, prefix, ver); + wroteFile = true; + } + return wroteFile; + } + + boolean generateRAPID(Program ast) { + boolean wroteFile = false; + if (rapidFile != null) { + printStatus("RAPID: " , rapidFile); + genRAPID(ast, rapidFile, coreName, ver); + wroteFile = true; + } + return wroteFile; + } + boolean generatePrettyPrint(Program ast) { + boolean wroteFile = false; + if (prettyFile != null) { + printStatus("Pretty: " , prettyFile); + try { + FileOutputStream f = new FileOutputStream(prettyFile); + PrintStream out = new PrintStream(f); + ast.pp(out); + out.close(); + wroteFile = true; + } catch (IOException e) { + System.err.println("IOException: " + prettyFile + " " + e); + } + } + return wroteFile; + } + + boolean generateTypeinfo(Program ast) { + boolean wroteFile = false; + if (typeinfoFile != null) { + printStatus("TypeInfo: " , typeinfoFile); + try { + FileOutputStream f = new FileOutputStream(typeinfoFile); + PrintStream out = new PrintStream(f); + ast.C_info(out, cPrefix, ver); + ast.Java_info(out, ver); + ast.CS_info(out, csNamespace, ver); + wroteFile = true; + } catch (IOException e) { + System.err.println("IOException: " + typeinfoFile + " " + e); + } + } + return wroteFile; + } + + private void printStatus(String kind, String filename){ + if (verbose) { + System.err.println("Generating "+kind+": " + filename); + } + } + } + + + public static void main(String[] args) { + Opts opts = new Opts(args); + if(!opts.processFilename()) { + print_help(); + System.exit(1); + } else { + opts.processArgs(); + Program ast = opts.parseFile(); + + if (ast != null) { + + boolean fileWritten = false; + + fileWritten |= opts.generateC(ast); + fileWritten |= opts.generateCS(ast); + fileWritten |= opts.generateJava(ast); + fileWritten |= opts.generatePython(ast); + fileWritten |= opts.generateRAPID(ast); + fileWritten |= opts.generatePrettyPrint(ast); + fileWritten |= opts.generateTypeinfo(ast); + + // if no output to files, prettyprint on stdout + if (!fileWritten) { + ast.pp(System.out); + } + } else { + // Catch-all for compilation errors + System.err.println("Error in specification"); + System.exit(3); + } + } + } +} diff --git a/compiler/2014/LabCommParser.parser b/compiler/2014/LabCommParser.parser new file mode 100644 index 0000000..e7fb759 --- /dev/null +++ b/compiler/2014/LabCommParser.parser @@ -0,0 +1,133 @@ +%header {: + package se.lth.control.labcomm2014.compiler; + import se.lth.control.labcomm2014.compiler.*; +:}; +%embed {: + public static class SourceError extends Error { + public SourceError(String msg) { + super(msg); + } + } + class Events extends Parser.Events { + public void syntaxError(Symbol token) { + StringBuffer s = new StringBuffer(); + s.append(token.getLine(token.getStart()) + ", " + token.getColumn(token.getStart()) + "\n"); + s.append(" *** Syntactic error: unexpected token " + Terminals.NAMES[token.getId()]); + throw new SourceError(s.toString()); + //super.syntaxError(token); + //throw new RuntimeException(token.getLine(token.getStart()) + ", " + + // token.getColumn(token.getStart()) + ": Syntax Error"); + } + public void scannerError(Scanner.Exception e) { + StringBuffer s = new StringBuffer(); + s.append(e.line + ", " + e.column + "\n"); + s.append(" *** Lexical error: " + e.getMessage()); + throw new SourceError(s.toString()); + //super.scannerError(e); + //throw new RuntimeException("Unexpected token"); + } + + } + + { + report = new Events(); // Use error handler in parser + } +:}; + +Program goal = + /* Empty program */ {: return new Program(); :} + | decl_list.l {: return new Program(l); :} + ; + +List decl_list = + decl.d {: return new List().add(d); :} + | decl_list.l decl.d {: return l.add(d); :} + ; + +Decl decl = + type_decl.t {: return t; :} + | sample_decl.s {: return s; :} + ; + +List var_decl_list = + var_decl.v {: return new List().add(v); :} + | var_decl_list.l var_decl.v {: return l.add(v); :} + ; + +Field var_decl = + type.t IDENTIFIER SEMICOLON {: return new Field(t, IDENTIFIER); :} + | type.t IDENTIFIER dim_list.d SEMICOLON + {: return new Field(new ParseArrayType(t, d), IDENTIFIER); :} + ; + +TypeDecl type_decl = + TYPEDEF type.t IDENTIFIER SEMICOLON {: return new TypeDecl(t, IDENTIFIER); :} + | TYPEDEF type.t IDENTIFIER dim_list.d SEMICOLON + {: return new TypeDecl(new ParseArrayType(t, d), IDENTIFIER); :} + ; + +SampleDecl sample_decl = + SAMPLE type.t IDENTIFIER SEMICOLON + {: return new SampleDecl(t, IDENTIFIER); :} + | SAMPLE type.t IDENTIFIER dim_list.d SEMICOLON + {: return new SampleDecl(new ParseArrayType(t, d), IDENTIFIER); :} + ; + +Type type = + prim_type.p {: return p; :} + | user_type.u {: return u; :} + | struct_type.s {: return s; :} + | void_type.v {: return v; :} + ; + +PrimType prim_type = + BOOLEAN + {: return new PrimType(BOOLEAN, ASTNode.LABCOMM_BOOLEAN); :} + | BYTE + {: return new PrimType(BYTE, ASTNode.LABCOMM_BYTE); :} + | SHORT + {: return new PrimType(SHORT, ASTNode.LABCOMM_SHORT); :} + | INT + {: return new PrimType(INT, ASTNode.LABCOMM_INT); :} + | LONG + {: return new PrimType(LONG, ASTNode.LABCOMM_LONG); :} + | FLOAT + {: return new PrimType(FLOAT, ASTNode.LABCOMM_FLOAT); :} + | DOUBLE + {: return new PrimType(DOUBLE, ASTNode.LABCOMM_DOUBLE); :} + | STRING + {: return new PrimType(STRING, ASTNode.LABCOMM_STRING); :} + | SAMPLE + {: return new PrimType(SAMPLE, ASTNode.LABCOMM_SAMPLE); :} + ; + +UserType user_type = + IDENTIFIER {: return new UserType(IDENTIFIER); :} + ; + +StructType struct_type = + STRUCT LBRACE var_decl_list.l RBRACE {: return new StructType(l); :} + ; + +VoidType void_type = + VOID {: return new VoidType(); :} +; + +List dim_list = + dim.d {: return new List().add(d); :} + | dim_list.l dim.d {: return l.add(d); :} + ; + +Dim dim = + LBRACK exp_list.e RBRACK {: return new Dim(e); :} + ; + +List exp_list = + exp.e {: return new List().add(e); :} + | exp_list.l COMMA exp.e {: return l.add(e); :} + ; + +Exp exp = + INTEGER_LITERAL {: return new IntegerLiteral(INTEGER_LITERAL); :} + | UNDERSCORE {: return new VariableSize(); :} + ; diff --git a/compiler/2014/LabCommScanner.flex b/compiler/2014/LabCommScanner.flex new file mode 100644 index 0000000..b58cbb6 --- /dev/null +++ b/compiler/2014/LabCommScanner.flex @@ -0,0 +1,87 @@ +package se.lth.control.labcomm2014.compiler; + +import beaver.Symbol; +import beaver.Scanner; +import se.lth.control.labcomm2014.compiler.LabCommParser.Terminals; + +%% + +%public +%final +%class LabCommScanner +%extends Scanner + +%type Symbol +%function nextToken +%yylexthrow Scanner.Exception + +%unicode +%line %column + +%{ + StringBuffer strbuf = new StringBuffer(128); + + private Symbol sym(short id) { + return new Symbol(id, yyline + 1, yycolumn + 1, len(), str()); + } + + private Symbol sym(short id, String value) { + return new Symbol(id, yyline + 1, yycolumn + 1, len(), value); + } + + private String str() { return yytext(); } + private int len() { return yylength(); } +%} + +LineTerminator = \n|\r|\r\n +InputCharacter = [^\r\n] + +WhiteSpace = [ ] | \t | \f | {LineTerminator} + +Comment = {TraditionalComment} + | {EndOfLineComment} + +TraditionalComment = "/*" [^*] ~"*/" | "/*" "*"+ "/" | "/*" "*"+ [^/*] ~"*/" +EndOfLineComment = "//" {InputCharacter}* {LineTerminator}? + +Identifier = [:jletter:][:jletterdigit:]* + +DecimalNumeral = 0 | {NonZeroDigit} {Digits}? +Digits = {Digit}+ +Digit = 0 | {NonZeroDigit} +NonZeroDigit = [1-9] + +%% + +<YYINITIAL> { + {WhiteSpace} { } + {Comment} { } + + "sample" { return sym(Terminals.SAMPLE); } + "typedef" { return sym(Terminals.TYPEDEF); } + "struct" { return sym(Terminals.STRUCT); } + "void" { return sym(Terminals.VOID); } + "boolean" { return sym(Terminals.BOOLEAN); } + "byte" { return sym(Terminals.BYTE); } + "short" { return sym(Terminals.SHORT); } + "int" { return sym(Terminals.INT); } + "long" { return sym(Terminals.LONG); } + "float" { return sym(Terminals.FLOAT); } + "double" { return sym(Terminals.DOUBLE); } + "string" { return sym(Terminals.STRING); } + + {DecimalNumeral} { return sym(Terminals.INTEGER_LITERAL); } + "_" { return sym(Terminals.UNDERSCORE); } + "{" { return sym(Terminals.LBRACE); } + "}" { return sym(Terminals.RBRACE); } + "[" { return sym(Terminals.LBRACK); } + "]" { return sym(Terminals.RBRACK); } + ";" { return sym(Terminals.SEMICOLON); } + "," { return sym(Terminals.COMMA); } + + {Identifier} { return sym(Terminals.IDENTIFIER); } +} + +// fall through errors +.|\n { throw new RuntimeException("Illegal character \""+str()+ "\" at line "+yyline+", column "+yycolumn); } +<<EOF>> { return sym(Terminals.EOF); } diff --git a/compiler/2014/LabCommTokens.jrag b/compiler/2014/LabCommTokens.jrag new file mode 100644 index 0000000..557714b --- /dev/null +++ b/compiler/2014/LabCommTokens.jrag @@ -0,0 +1,21 @@ +aspect LabCommTokens { + + public static final int ASTNode.LABCOMM_VERSION = 0x01; + public static final int ASTNode.LABCOMM_SAMPLE_DEF = 0x02; // The flat signature + public static final int ASTNode.LABCOMM_SAMPLE_REF = 0x03; + public static final int ASTNode.LABCOMM_TYPE_DEF = 0x04; // and type declarations, hierarchically + + public static final int ASTNode.LABCOMM_ARRAY = 0x10; + public static final int ASTNode.LABCOMM_STRUCT = 0x11; + + public static final int ASTNode.LABCOMM_BOOLEAN = 0x20; + public static final int ASTNode.LABCOMM_BYTE = 0x21; + public static final int ASTNode.LABCOMM_SHORT = 0x22; + public static final int ASTNode.LABCOMM_INT = 0x23; + public static final int ASTNode.LABCOMM_LONG = 0x24; + public static final int ASTNode.LABCOMM_FLOAT = 0x25; + public static final int ASTNode.LABCOMM_DOUBLE = 0x26; + public static final int ASTNode.LABCOMM_STRING = 0x27; + public static final int ASTNode.LABCOMM_SAMPLE = 0x28; + +} diff --git a/compiler/2014/NameAnalysis.jrag b/compiler/2014/NameAnalysis.jrag new file mode 100644 index 0000000..92dbb41 --- /dev/null +++ b/compiler/2014/NameAnalysis.jrag @@ -0,0 +1,67 @@ + +aspect NameAnalysis { + + inh String Decl.lookupName(String name); + eq Program.getDecl(int index).lookupName(String name) { + for (int i = 0; i < index; i++) { + String s = getDecl(i).getName(); + if (s.equals(name)) { + return s; + } + } + return null; + } + inh String Field.lookupName(String name); + eq StructType.getField(int index).lookupName(String name) { + for (int i = 0; i < index; i++) { + String s = getField(i).getName(); + if (s.equals(name)) { + return s; + } + } + return null; + } + + inh TypeDecl Decl.lookupType(String name); + inh TypeDecl UserType.lookupType(String name); + eq Program.getDecl(int index).lookupType(String name) { + for(int i = 0; i < index; i++) { + Decl d = getDecl(i); + if(d instanceof TypeDecl && d.getName().equals(name)) { + return (TypeDecl)d; + } + } + return null; + } + + syn TypeDecl Type.decl(); + eq Type.decl() = null; + eq UserType.decl() = lookupType(getName()); + eq PrimType.decl() = null; //HERE BE DRAGONS XXX + + + public void ASTNode.nameCheck() { + for (int i = 0; i < getNumChild(); i++) { + getChild(i).nameCheck(); + } + } + + public void Decl.nameCheck() { + if (lookupType(getName()) != null || lookupName(getName()) != null) { + error(getName() + " multiply declared"); + } + } + + public void Field.nameCheck() { + if(lookupName(getName()) != null) { + error(getName() + " multiply declared"); + } + } + + public void UserType.nameCheck() { + if (decl() == null) { + error("Use of undeclared type"); + } + } + +} diff --git a/compiler/2014/PrettyPrint.jrag b/compiler/2014/PrettyPrint.jrag new file mode 100644 index 0000000..a7fa877 --- /dev/null +++ b/compiler/2014/PrettyPrint.jrag @@ -0,0 +1,117 @@ +import java.io.PrintStream; + +aspect PPIndentation { + + inh String Exp.pp_indent(); + inh String Field.pp_indent(); + inh String StructType.pp_indent(); + eq StructType.getField(int index).pp_indent() = pp_indent() + " "; + eq Program.getDecl(int index).pp_indent() = ""; + +} + +aspect PrettyPrint { + + public void ASTNode.pp(PrintStream out) { + throw new Error(this.getClass().getName() + + ".pp(PrintStream out)" + + " not declared"); + } + + public void Program.pp(PrintStream out) { + for(int i = 0; i < getNumDecl(); i++) { + getDecl(i).pp(out); + } + } + + // Pretty print declarations + public void TypeDecl.pp(PrintStream out) { + out.print("typedef "); + getType().ppIdentifier(out, getName()); + out.println(";"); + } + + public void SampleDecl.pp(PrintStream out) { + out.print("sample "); + getType().ppIdentifier(out, getName()); + out.println(";"); + } + + public void Field.pp(PrintStream out) { + out.print(pp_indent()); + getType().ppIdentifier(out, getName()); + out.println(";"); + } + + // Pretty print variable of a given type + public void Type.ppIdentifier(PrintStream out, String id) { + ppPrefix(out); + out.print(" "); + out.print(id); + } + + public void ArrayType.ppIdentifier(PrintStream out, String id) { + ppPrefix(out); + out.print(" "); + out.print(id); + ppSuffix(out); + } + + // PrettyPrint prefix type info + public void Type.ppPrefix(PrintStream out) { + throw new Error(this.getClass().getName() + + ".ppPrefix(PrintStream out)" + + " not declared"); + } + + public void VoidType.ppPrefix(PrintStream out) { + out.print("void"); + } + + public void SampleRefType.ppPrefix(PrintStream out) { + out.print("sample"); + } + + public void PrimType.ppPrefix(PrintStream out) { + out.print(getName()); + } + + public void UserType.ppPrefix(PrintStream out) { + out.print(getName()); + } + + public void ArrayType.ppPrefix(PrintStream out) { + getType().ppPrefix(out); + } + + public void StructType.ppPrefix(PrintStream out) { + out.println("struct {"); + for (int i = 0 ; i < getNumField() ; i++) { + getField(i).pp(out); + } + out.print(pp_indent()); + out.print("}"); + } + + // PrettyPrint suffix type info (array dimensions) + public void Type.ppSuffix(PrintStream out) { } + + public void ArrayType.ppSuffix(PrintStream out) { + out.print("["); + for (int i = 0 ; i < getNumExp() ; i++) { + if (i > 0) { out.print(", "); } + getExp(i).pp(out); + } + out.print("]"); + getType().ppSuffix(out); + } + + public void IntegerLiteral.pp(PrintStream out) { + out.print(getValue()); + } + + public void VariableSize.pp(PrintStream out) { + out.print("_"); + } + +} diff --git a/compiler/2014/Python_CodeGen.jrag b/compiler/2014/Python_CodeGen.jrag new file mode 100644 index 0000000..17203b8 --- /dev/null +++ b/compiler/2014/Python_CodeGen.jrag @@ -0,0 +1,232 @@ +aspect Python_CodeGenEnv { + + // Environment wrapper for Python code generation + // handles qualid nesting, indentation, file writing and + // prefix propagation + + public class Python_env { + + final private class Python_printer { + + private boolean newline = true; + private PrintStream out; + + public Python_printer(PrintStream out) { + this.out = out; + } + + public void print(Python_env env, String s) { + if (newline) { + newline = false; + for (int i = 0 ; i < env.indent ; i++) { + out.print(" "); + } + } + out.print(s); + } + + public void println(Python_env env, String s) { + print(env, s); + out.println(); + newline = true; + } + + public void println(Python_env env) { + out.println(); + newline = true; + } + + } + + private int indent; + private Python_printer printer; + + public Python_env(PrintStream out) { + this.indent = 0; + this.printer = new Python_printer(out); + } + + public void indent() { + indent++; + } + + public void unindent() { + indent--; + } + + public void print(String s) { + printer.print(this, s); + } + + public void println(String s) { + printer.println(this, s); + } + + public void println() { + printer.println(this); + } + + } + +} + +aspect Python_CodeGen { + + public void Program.Python_gen(PrintStream out, String baseName, int version) { + // Remove when Blomdell has verified that it is OK to ignore version + // when generating python code. + System.err.println("*** Warning! Python_gen ignores version: "+version); + Python_env env = new Python_env(out); + env.println("#!/usr/bin/python"); + env.println("# Auto generated " + baseName); + env.println(); + env.println("import labcomm"); + env.println("import StringIO"); + env.println(); + Python_genTypes(env); + //env.println("typedef = ["); + //env.indent(); + //for (int i = 0 ; i < getNumDecl() ; i++) { + // getDecl(i).Python_genTypedefListEntry(env); + //} + //env.unindent(); + //env.println("]"); + env.println("sample = ["); + env.indent(); + for (int i = 0 ; i < getNumDecl() ; i++) { + getDecl(i).Python_genSampleListEntry(env); + } + env.unindent(); + env.println("]"); + } + +} + +aspect PythonTypes { + + public void Program.Python_genTypes(Python_env env) { + for (int i = 0 ; i < getNumDecl() ; i++) { + getDecl(i).Python_genSignature(env); + } + } + + public void Decl.Python_genSignature(Python_env env) { + throw new Error(this.getClass().getName() + + ".Python_genSignature(Python_env env)" + + " not declared"); + } + + public void TypeDecl.Python_genSignature(Python_env env) { +/* + env.println("class " + getName() + "(object):"); + env.indent(); + env.println("signature = labcomm.typedef('" + getName() + "',"); + env.indent(); + getType().Python_genSignature(env); + env.unindent(); + env.println(")"); + env.unindent(); + env.println(); +*/ + } + + public void SampleDecl.Python_genSignature(Python_env env) { + env.println("class " + getName() + "(object):"); + env.indent(); + env.println("signature = labcomm.sample('" + getName() + "', "); + env.indent(); + getType().Python_genSignature(env); + env.unindent(); + env.println(")"); + env.unindent(); + env.println(); + } + + public void UserType.Python_genSignature(Python_env env) { + lookupType(getName()).getType().Python_genSignature(env); + } + + public void Type.Python_genSignature(Python_env env) { + throw new Error(this.getClass().getName() + + ".Python_genSignature(Python_env env)" + + " not declared"); + } + + public void PrimType.Python_genSignature(Python_env env) { + switch (getToken()) { + case LABCOMM_BOOLEAN: { env.print("labcomm.BOOLEAN()"); } break; + case LABCOMM_BYTE: { env.print("labcomm.BYTE()"); } break; + case LABCOMM_SHORT: { env.print("labcomm.SHORT()"); } break; + case LABCOMM_INT: { env.print("labcomm.INTEGER()"); } break; + case LABCOMM_LONG: { env.print("labcomm.LONG()"); } break; + case LABCOMM_FLOAT: { env.print("labcomm.FLOAT()"); } break; + case LABCOMM_DOUBLE: { env.print("labcomm.DOUBLE()"); } break; + case LABCOMM_STRING: { env.print("labcomm.STRING()"); } break; + case LABCOMM_SAMPLE: { env.print("labcomm.SAMPLE()"); } break; + } + } + + public void ArrayType.Python_genSignature(Python_env env) { + env.print("labcomm.array(["); + for (int i = 0 ; i < getNumExp() ; i++) { + if (i > 0) { env.print(", "); } + env.print(getExp(i).Python_getValue()); + } + env.println("],"); + env.indent(); + getType().Python_genSignature(env); + env.print(")"); + env.unindent(); + } + + public void StructType.Python_genSignature(Python_env env) { + env.println("labcomm.struct(["); + env.indent(); + for (int i = 0 ; i < getNumField() ; i++) { + if (i > 0) { env.println(","); } + getField(i).Python_genSignature(env); + } + env.print("])"); + env.unindent(); + } + + public void VoidType.Python_genSignature(Python_env env) { + env.println("labcomm.struct([])"); + } + + public void Field.Python_genSignature(Python_env env) { + env.print("('" + getName() + "', "); + getType().Python_genSignature(env); + env.print(")"); + } + + public void Decl.Python_genTypedefListEntry(Python_env env) { + } + + public void TypeDecl.Python_genTypedefListEntry(Python_env env) { + env.println("('" + getName() + "', " + getName() + ".signature),"); + } + + public void Decl.Python_genSampleListEntry(Python_env env) { + } + + public void SampleDecl.Python_genSampleListEntry(Python_env env) { + env.println("('" + getName() + "', " + getName() + ".signature),"); + } + + public String Exp.Python_getValue() { + throw new Error(this.getClass().getName() + + ".Python_getValue()" + + " not declared"); + } + + public String IntegerLiteral.Python_getValue() { + return getValue(); + } + + public String VariableSize.Python_getValue() { + return "0"; + } + +} + diff --git a/compiler/2014/RAPID_CodeGen.jrag b/compiler/2014/RAPID_CodeGen.jrag new file mode 100644 index 0000000..b367ee5 --- /dev/null +++ b/compiler/2014/RAPID_CodeGen.jrag @@ -0,0 +1,369 @@ + +aspect RAPID_env { + public class RAPID_env { + public final int version; + private String prefix; + private StringBuilder types; + private StringBuilder constants; + private StringBuilder procedures; + private PrintStream ps; + + public RAPID_env(PrintStream ps, String prefix, int version) + { + this.version = version; + this.types = new StringBuilder(); + this.constants = new StringBuilder(); + this.procedures = new StringBuilder(); + this.prefix = prefix; + this.ps = ps; + } + + public String prefix() { return this.prefix; } + + public String addRecord(String name, java.util.List<String> components) + { + String recordName = this.prefix + "_" + name; + types.append("\tRECORD " + recordName); + types.append("\n"); + for (String c : components) { + types.append("\t\t" + c + "\n"); + } + types.append("\tENDRECORD"); + types.append("\n\n"); + return recordName; + } + + public void addConstant(String type, String name, String value) { + this.constants.append("\tLOCAL CONST " + type + " " + name + + " := " + value + ";\n"); + } + + public void addProc(String name, java.util.List<String> params, + java.util.List<String> stmts) + { + this.procedures.append("\tLOCAL PROC " + name + "("); + for (int i = 0; i < params.size(); i++) { + this.procedures.append(params.get(i)); + if (i < params.size() - 1) { + this.procedures.append(", "); + } + } + this.procedures.append(")\n"); + for (String stmt : stmts) { + this.procedures.append("\t\t" + stmt + "\n"); + } + this.procedures.append("\tERROR\n\t\tRAISE ;\n\tENDPROC\n\n"); + } + + public void flush() + { + ps.println("MODULE " + prefix() + "(SYSMODULE)"); + ps.println(); + ps.print(types.toString()); + ps.println(); + ps.println("\tLOCAL CONST string prefix:=\"" + this.prefix + "\";"); + ps.print(constants.toString()); + ps.println(); + ps.print(procedures.toString()); + ps.println(); + ps.print("ENDMODULE"); + } + } +} + +aspect RAPID_CodeGen { + + public void ASTNode.RAPID_gen(RAPID_env env) { + throw new UnsupportedOperationException(); + } + + public void Program.RAPID_gen(String file, String prefix, int version) + throws IOException + { + PrintStream ps = new PrintStream(new FileOutputStream(new File(file))); + RAPID_env env = new RAPID_env(ps, prefix, version); + RAPID_gen(env); + } + + public void Program.RAPID_gen(RAPID_env env) + { + for (int i = 0; i < getNumDecl(); i++) { + getDecl(i).RAPID_gen(env); + } + env.flush(); + } + + public void Decl.RAPID_gen(RAPID_env env) { + throw new UnsupportedOperationException("RAPID code generation (currently) does not support "+getClass().getSimpleName()); + } + + public void TypeDecl.RAPID_gen(RAPID_env env) { + System.out.println("***WARNING! TypeDecl.RapidGen(.) a NOP after sig reorganization."); + System.out.println(" (Tell a developer to) remove this warning when tested"); + } + + public void Decl.RAPID_emitFlatSignature(RAPID_env env, String sig_len_name, String sig_name) { + System.out.println("***WARNING! Code not tested after reorganization of signatures."); + System.out.println(" (Tell a developer to) remove this warning when tested"); + SignatureList sig = flatSignature(env.version); + StringBuilder sb = new StringBuilder(); + sb.append("["); + byte[] d = null; + int sig_len = 0; + for (int i = 0; i < sig.size(); i++) { + d = sig.getData(i, env.version); + for (int j = 0; d != null && j < d.length; j++) { + sb.append(d[j] + ","); + sig_len++; + } + } + sb.delete(sb.length() - 1, sb.length()); + sb.append("]"); + env.addConstant("num", sig_len_name, "" + sig_len); + env.addConstant("byte", sig_name + "{" + sig_len_name + "}", + sb.toString()); + } + + public void SampleDecl.RAPID_gen(RAPID_env env) { + // Add type declarations + String fullName = getType().RAPID_AddType(env, getName()); + // Add signature constants + String sig_len_name = "signature_len_" + getName(); + String sig_name = "signature_" + getName(); + + RAPID_emitFlatSignature(env, sig_len_name, sig_name); + + // Add decode procedures + ArrayList<String> params = new ArrayList<String>(); + ArrayList<String> stmts = new ArrayList<String>(); + params.add("VAR LabComm_Decoder_Sample s"); + params.add("string handler"); + stmts.add("s.prefix := prefix;"); + stmts.add("s.name := \"" + getName() + "\";"); + stmts.add("s.handler := handler;"); + env.addProc("Dec_Reg_" + getName(), params, stmts); + + params.clear(); + stmts.clear(); + params.add("VAR LabComm_Decoder_Sample s"); + params.add("VAR rawbytes sig"); + params.add("num user_id"); + stmts.add("VAR byte tmp_sig{" + sig_len_name + "};"); + stmts.add("IF RawBytesLen(sig)<>" + sig_len_name + " THEN"); + stmts.add("\tRETURN;"); + stmts.add("ENDIF"); + stmts.add("FOR i FROM 1 TO " + sig_len_name + " DO"); + stmts.add("\tUnpackRawBytes sig, i, tmp_sig{i}, \\Hex1;"); + stmts.add("ENDFOR"); + stmts.add("IF tmp_sig<>" + sig_name + " THEN"); + stmts.add("\tRETURN;"); + stmts.add("ENDIF"); + stmts.add("s.user_id := user_id;"); + env.addProc("Reg_If_Signature_Of_" + getName(), params, stmts); + + params.clear(); + stmts.clear(); + params.add("VAR Decoder d"); + params.add("VAR LabComm_Stream st"); + params.add("VAR LabComm_Decoder_Sample s"); + stmts.add("VAR " + fullName + " tmp;"); + getType().RAPID_AddDecodeInstr(env, stmts, "tmp", "st"); + stmts.add("% s.handler % tmp;"); + env.addProc("Decode_And_Handle_" + getName(), params, stmts); + + params.clear(); + stmts.clear(); + params.add("VAR Encoder e"); + params.add("VAR LabComm_Stream st"); + params.add("VAR LabComm_Encoder_Sample s"); + stmts.add("s.prefix := prefix;"); + stmts.add("s.name := \"" + getName() + "\";"); + stmts.add("Encoder_Register_Sample e, st, s;"); + env.addProc("Enc_Reg_" + getName(), params, stmts); + + params.clear(); + stmts.clear(); + params.add("VAR Encoder e"); + params.add("VAR LabComm_Stream s"); + stmts.add("VAR rawbytes buffer;"); + stmts.add("FOR i FROM 1 TO " + sig_len_name + " DO"); + stmts.add("\tPackRawBytes " + sig_name + + "{i}, buffer, \\Network, i, \\Hex1;"); + stmts.add("ENDFOR"); + stmts.add("SocketSend s.soc, \\RawData:=buffer, \\NoOfBytes:=" + + sig_len_name + ";"); + env.addProc("Encode_Signature_" + getName(), params, stmts); + + params.clear(); + stmts.clear(); + params.add("VAR Encoder e"); + params.add("VAR LabComm_Stream st"); + params.add("VAR LabComm_Encoder_Sample s"); + params.add("VAR " + fullName + " val"); + stmts.add("Encode_Packed st, s.user_id;"); + getType().RAPID_AddEncodeInstr(env, stmts, "val", "st"); + env.addProc("Encode_" + getName(), params, stmts); + } + + public String Type.RAPID_AddType(RAPID_env env, String name) { + throw new UnsupportedOperationException("RAPID code generation does (currently) not support "+getClass().getSimpleName()); + } + + public String StructType.RAPID_AddType(RAPID_env env, String name) { + ArrayList<String> components = new ArrayList<String>(); + for (int i = 0; i < getNumField(); i++) { + Field f = getField(i); + components.add( + f.getType().RAPID_AddType(env, name + "_" + f.getName()) + + " " + f.getName() + ";"); + } + String typeName = env.addRecord(name, components); + return typeName; + } + + public String FixedArrayType.RAPID_AddType(RAPID_env env, String name) { + String typeName = getType().RAPID_AddType(env, name + "_e"); + if (getNumExp() > 1) { + throw new UnsupportedOperationException("RAPID generation only (currently) supports one-dimensional arrays"); + } + ArrayList<String> components = new ArrayList<String>(); + for (int i = 1; i <= getExp(0).RAPID_getValue(); i++) { + components.add(typeName + " e" + i + ";"); + } + String completeName = env.addRecord("list_" + name, components); + return completeName; + } + + public String PrimType.RAPID_AddType(RAPID_env env, String name) { + if (getToken() == LABCOMM_SHORT || + getToken() == LABCOMM_FLOAT || + getToken() == LABCOMM_INT) { + return "num"; + } else if (getToken() == LABCOMM_LONG) { + return "dnum"; + } else if (getToken() == LABCOMM_STRING) { + return "string"; + } else if (getToken() == LABCOMM_BOOLEAN) { + return "bool"; + } else if (getToken() == LABCOMM_BYTE) { + return "byte"; + } + throw new UnsupportedOperationException("RAPID code generation does not (currently) support "+getName()); + } + + public void Type.RAPID_AddDecodeInstr(RAPID_env env, + java.util.List<String> instrs, + String var_name, String stream_name) { + throw new UnsupportedOperationException("RAPID code generation does not (currently) support "+getClass().getSimpleName()); + } + + public void StructType.RAPID_AddDecodeInstr(RAPID_env env, + java.util.List<String> instrs, + String var_name, String stream_name) { + for (int i = 0; i < getNumField(); i++) { + getField(i).getType().RAPID_AddDecodeInstr(env, instrs, + var_name + "." + getField(i).getName(), stream_name); + } + } + + public void FixedArrayType.RAPID_AddDecodeInstr(RAPID_env env, + java.util.List<String> instrs, + String var_name, String stream_name) { + for (int i = 1; i <= getExp(0).RAPID_getValue(); i++) { + getType().RAPID_AddDecodeInstr(env, instrs, + var_name + ".e" + i, stream_name); + } + } + + public void PrimType.RAPID_AddDecodeInstr(RAPID_env env, + java.util.List<String> instrs, + String var_name, String stream_name) { + switch(getToken()) { + case LABCOMM_BYTE: + instrs.add("Decode_Byte " + stream_name + "," + var_name + ";"); + break; + case LABCOMM_BOOLEAN: + instrs.add("Decode_Bool " + stream_name + "," + var_name + ";"); + break; + case LABCOMM_SHORT: + instrs.add("Decode_Short " + stream_name + "," + var_name + ";"); + break; + case LABCOMM_INT: + instrs.add("Decode_Int " + stream_name + "," + var_name + ";"); + break; + case LABCOMM_LONG: + instrs.add("Decode_Long " + stream_name + "," + var_name + ";"); + break; + case LABCOMM_FLOAT: + instrs.add("Decode_Float " + stream_name + "," + var_name + ";"); + break; + case LABCOMM_STRING: + instrs.add("Decode_String " + stream_name + "," + var_name + ";"); + break; + default: + throw new UnsupportedOperationException("RAPID code generation does not (currently) support "+getName()); + } + } + + public void Type.RAPID_AddEncodeInstr(RAPID_env env, + java.util.List<String> instrs, + String var_name, String stream_name) { + throw new UnsupportedOperationException("RAPID code generation does not (currently) support "+getClass().getSimpleName()); + } + + public void StructType.RAPID_AddEncodeInstr(RAPID_env env, + java.util.List<String> instrs, + String var_name, String stream_name) { + for (int i = 0; i < getNumField(); i++) { + getField(i).getType().RAPID_AddEncodeInstr(env, instrs, + var_name + "." + getField(i).getName(), stream_name); + } + } + + public void FixedArrayType.RAPID_AddEncodeInstr(RAPID_env env, + java.util.List<String> instrs, + String var_name, String stream_name) { + for (int i = 1; i <= getExp(0).RAPID_getValue(); i++) { + getType().RAPID_AddEncodeInstr(env, instrs, + var_name + ".e" + i, stream_name); + } + } + + public void PrimType.RAPID_AddEncodeInstr(RAPID_env env, + java.util.List<String> instrs, + String var_name, String stream_name) { + switch(getToken()) { + case LABCOMM_BYTE: + instrs.add("Encode_Byte " + stream_name + "," + var_name + ";"); + break; + case LABCOMM_BOOLEAN: + instrs.add("Encode_Bool " + stream_name + "," + var_name + ";"); + break; + case LABCOMM_SHORT: + instrs.add("Encode_Short " + stream_name + "," + var_name + ";"); + break; + case LABCOMM_INT: + instrs.add("Encode_Int " + stream_name + "," + var_name + ";"); + break; + case LABCOMM_LONG: + instrs.add("Encode_Long " + stream_name + "," + var_name + ";"); + break; + case LABCOMM_FLOAT: + instrs.add("Encode_Float " + stream_name + "," + var_name + ";"); + break; + case LABCOMM_STRING: + instrs.add("Encode_String " + stream_name + "," + var_name + ";"); + break; + default: + throw new UnsupportedOperationException("RAPID code generation does not (currently) support "+getName()); + } + } + + public int Exp.RAPID_getValue() { + throw new UnsupportedOperationException("RAPID code generation does not (currently) support "+getClass().getSimpleName()); + } + + public int IntegerLiteral.RAPID_getValue() { + return Integer.parseInt(getValue()); + } +} diff --git a/compiler/2014/Signature.jrag b/compiler/2014/Signature.jrag new file mode 100644 index 0000000..5395095 --- /dev/null +++ b/compiler/2014/Signature.jrag @@ -0,0 +1,236 @@ +import java.util.*; + +aspect Signature { + + syn boolean Decl.isSampleDecl(); + eq TypeDecl.isSampleDecl() = false; + eq SampleDecl.isSampleDecl() = true; + + syn boolean Decl.sendOnlyFlatSignatures(Java_env env) = (env.version==2006); + + eq Decl.getSignature().parentDecl() = this; + eq Signature.getSignatureList().parentDecl() = parentDecl(); + + inh Decl Signature.parentDecl(); + inh Decl SignatureList.parentDecl(); + + + syn nta Signature Decl.getSignature() { + SignatureList sl = new SignatureList(); + genSigLineForDecl(sl, true); + SignatureList fsl = new SignatureList(); + flatSignature(fsl); + Signature sig = new Signature(); + sig.setSignatureList(sl); + sig.setFlatSignatureList(fsl); + setSignature(sig); + return sig; + } + + public String SignatureLine.getIndentString() { + StringBuffer result = new StringBuffer(); + int indent = getIndent(); + for (int i = 0 ; i < indent ; i++) { + result.append(" "); + } + return result.toString(); + } + + syn byte[] SignatureLine.getData(int version) = null; + // return new byte[0]; + + private Decl TypeRefSignatureLine.decl; + public TypeRefSignatureLine.TypeRefSignatureLine(int indent, Decl decl, String comment) { + super(indent, comment); + this.decl = decl; + } + public void SignatureList.addTypeRef(Decl type, String comment) { + addSignatureLine(new TypeRefSignatureLine(indent, type, comment)); + } + + public ByteArraySignatureLine.ByteArraySignatureLine(int indent, byte[] data, String comment) { + super(indent, comment); + setData(data); + } + + public IntSignatureLine.IntSignatureLine(int indent, int data, String comment) { + super(indent, comment); + setData(data); + } + + public void SignatureList.add(byte[] data, String comment) { + addSignatureLine(new ByteArraySignatureLine(indent, data, comment)); + } + + public void SignatureList.addInt(int data, String comment) { + addSignatureLine(new IntSignatureLine(indent, data, comment)); + } + + protected byte[] DataSignatureLine.getIntBytes(int value, int version) { + byte data[]; + switch(version) { + case 2006: // Use old encoding with 32 bit integers + data = new byte[4]; + for (int i = 0 ; i < 4 ; i++) { + data[3 - i] = (byte)((value >> (8 * i)) & 0xff); + } + //add(data, comment); + break; + case 2014: // Use new encoding with varints + byte[] tmp = new byte[5]; + long v = value & 0xffffffff; + int i, j; + for (i = 0 ; i == 0 || v != 0 ; i++, v = (v >> 7)) { + tmp[i] = (byte)(v & 0x7f); + } + byte[] packed = new byte[i]; + for (i = i - 1, j = 0 ; i >= 0 ; i--, j++) { + packed[j] = (byte)(tmp[i] | (i!=0?0x80:0x00)); + } + //add(packed, comment); + data = packed; + break; + default: + throw new RuntimeException("Unsupported version = "+version+". This should never happen."); + } + return data; + } + + eq IntSignatureLine.getData(int version) { + return getIntBytes(getData(), version); + } + + public void SignatureList.addString(String data, String comment) { + addSignatureLine(new StringSignatureLine(indent, comment, data)); + } + eq StringSignatureLine.getData(int version) { + byte[] lenBytes = getIntBytes(getData().length(), version); + byte[] data = new byte[lenBytes.length+getData().length()]; + + // first add the encoded length + for (int i = 0 ; i < lenBytes.length ; i++) { + data[i] = lenBytes[i]; + } + // and then the actual chars + for (int i = 0 ; i < getData().length() ; i++) { + int idx = lenBytes.length + i; + data[idx] = (byte)(getData().charAt(i) & 0xff); + } + return data; + } + + public int SignatureList.size() { + return getNumSignatureLine(); + } + + public String SignatureList.getIndent(int i) { + StringBuffer result = new StringBuffer(); + int indent = getSignatureLine(i).getIndent(); + for (i = 0 ; i < indent ; i++) { + result.append(" "); + } + return result.toString(); + } + + public byte[] SignatureList.getData(int i, int version) { + return getSignatureLine(i).getData(version); + } + + public String SignatureList.getComment(int i) { + return getSignatureLine(i).getComment(); + } + + private int SignatureList.indent; + + public void SignatureList.indent() { + indent++; + } + + public void SignatureList.unindent() { + indent--; + } + + + public void ASTNode.genSigLineForDecl(SignatureList list, boolean decl) { + throw new Error(this.getClass().getName() + + ".genSigLineForDecl(SignatureList list)" + + " not declared"); + } + + public void TypeDecl.genSigLineForDecl(SignatureList list, boolean decl) { + //System.out.println("************ TypeDecl.genSigLine("+decl+").... for "+getName()); + if(decl){ + getType().genSigLineForDecl(list, decl); + }else{ + list.addTypeRef(this, "//TODO (from list.addTypeRef)"); + } + } + + public void SampleDecl.genSigLineForDecl(SignatureList list, boolean decl) { + //System.out.println("************ SampleDecl.genSigLine("+decl+").... for "+getName()); + getType().genSigLineForDecl(list, decl); + } + + public void VoidType.genSigLineForDecl(SignatureList list, boolean decl) { + list.addInt(LABCOMM_STRUCT, "void"); + list.addInt(0, null); + } + + public void SampleRefType.genSigLineForDecl(SignatureList list, boolean decl) { + list.addInt(LABCOMM_SAMPLE_REF, "sample"); + } + public void PrimType.genSigLineForDecl(SignatureList list, boolean decl) { + list.addInt(getToken(), null); + } + + public void UserType.genSigLineForDecl(SignatureList list, boolean decl) { + if(decl){ + //System.out.println("************ UserType.genSigLine("+decl+").... for "+getName()); + TypeDecl thet=lookupType(getName()); + //System.out.println("************ thet: "+thet.getName() +":"+thet.getType()); + thet.genSigLineForDecl(list, decl); + }else{ + //System.out.println("************ UserType.genSigLine("+decl+").... for "+getName()); + TypeDecl thet = lookupType(getName()); + // System.out.println("************ thet: "+thet.getName() +":"+thet.getType()); + list.addTypeRef(thet, null); + } + } + + public void ArrayType.genSigLineForDecl(SignatureList list, boolean decl) { + list.addInt(LABCOMM_ARRAY, signatureComment()); + list.indent(); + list.addInt(getNumExp(), null); + for (int i = 0 ; i < getNumExp() ; i++) { + getExp(i).genSigLineForDecl(list, false); + } + getType().genSigLineForDecl(list, false); + list.unindent(); + list.add(null, "}"); + } + + public void StructType.genSigLineForDecl(SignatureList list, boolean decl) { + list.addInt(LABCOMM_STRUCT, "struct { " + getNumField() + " fields"); + list.indent(); + list.addInt(getNumField(), null); + for (int i = 0 ; i < getNumField() ; i++) { + getField(i).genSigLineForDecl(list, false); + } + list.unindent(); + list.add(null, "}"); + } + + public void Field.genSigLineForDecl(SignatureList list, boolean decl) { + list.addString(getName(), signatureComment()); + getType().genSigLineForDecl(list, decl); + } + + public void IntegerLiteral.genSigLineForDecl(SignatureList list, boolean decl) { + list.addInt(Integer.parseInt(getValue()), null); + } + + public void VariableSize.genSigLineForDecl(SignatureList list, boolean decl) { + list.addInt(0, null); + } + +} diff --git a/compiler/2014/TypeCheck.jrag b/compiler/2014/TypeCheck.jrag new file mode 100644 index 0000000..a640ace --- /dev/null +++ b/compiler/2014/TypeCheck.jrag @@ -0,0 +1,36 @@ +aspect TypeCheck { + public void ASTNode.typeCheck() { + // calls to the different type checks to be performed + nullTypeCheck(); + } + +// void is not allowed as a field in a struct or an array element + + syn boolean Type.isNull(); + eq Type.isNull() = false; + eq VoidType.isNull() = true; + eq UserType.isNull() = decl().isNull(); + + syn boolean TypeDecl.isNull(); + eq TypeDecl.isNull() = getType().isNull(); + + public void ASTNode.nullTypeCheck() {} + + public void Field.nullTypeCheck() { + if(getType().isNull()) { + error("field " + getName() + " of struct "+ declName()+ " may not be of type void"); + } + } + + public void ParseArrayType.nullTypeCheck() { + if(getType().isNull()) { + error("elements of array "+declName()+" may not be of type void"); + } + } + + public void ArrayType.nullTypeCheck() { + if(getType().isNull()) { + error("elements of array "+declName()+" may not be of type void"); + } + } +} diff --git a/compiler/2014/TypeReferences.jrag b/compiler/2014/TypeReferences.jrag new file mode 100644 index 0000000..0a7cd9b --- /dev/null +++ b/compiler/2014/TypeReferences.jrag @@ -0,0 +1,46 @@ +aspect User_Types { + syn String Type.getTypeName(); + eq Type.getTypeName() = getClass().getName(); + eq PrimType.getTypeName() = getName(); + eq UserType.getTypeName() = getName(); + + syn boolean Type.isUserType(); + eq Type.isUserType() = false; + eq UserType.isUserType() = true; +} + +aspect Type_References { + + // The dependencies on other type declarations for a Decl. + coll Set<Decl> Decl.type_dependencies() [new HashSet<Decl>()] with add; + + Field contributes ((UserType)getType()).decl() + when parentDecl() != null && getType().isUserType() + to Decl.type_dependencies() + for parentDecl(); + + UserType contributes decl() + when parentDecl() != null + to Decl.type_dependencies() + for parentDecl(); + /* + Field contributes getType().decl() + when parentDecl() != null && getType().isLeafType() + to Decl.type_dependencies() + for parentDecl(); + */ + + + // The references from other type declarations to a Decl. + coll Set<Decl> Decl.type_references() [new HashSet<Decl>()] with add; + + Decl contributes this + to Decl.type_references() + for each type_dependencies(); + + syn boolean Decl.hasDependencies(); + eq Decl.hasDependencies() = !type_dependencies().isEmpty(); + + syn boolean Decl.isReferenced(); + eq Decl.isReferenced() = !type_references().isEmpty(); +} diff --git a/compiler/2014/Version.jrag b/compiler/2014/Version.jrag new file mode 100644 index 0000000..f080578 --- /dev/null +++ b/compiler/2014/Version.jrag @@ -0,0 +1,15 @@ +aspect Version { + + /* An auxilliary class for handling naming and prefixes connected + * to the LabComm version + */ + class LabCommVersion { + public static String versionString(int version) { + return (version == 2006) ? "2006" : ""; + } + + public static boolean versionHasPragma(int version) { + return version != 2006; + } + } +} diff --git a/compiler/LabComm.java b/compiler/LabComm.java index d323eeb..a6f4c6b 100644 --- a/compiler/LabComm.java +++ b/compiler/LabComm.java @@ -1,403 +1,36 @@ -import AST.*; -import java.io.*; -import java.util.*; +import java.util.Vector; public class LabComm { - private static void println(String s) { - System.out.println(s); - } - - private static void print_help() { - println("\n Usage: java -jar labcom.jar [options*] FILE"); - println(""); - println(" --help Shows this help text"); - println(" -v Be verbose"); - println(" --ver=VERSION Generate code for labcomm VERSION (=2006 or 2013)"); - println("[ C options ]"); - println(" -C Generates C/H code in FILE.[ch]"); - println(" --cprefix=PREFIX Prefixes C types with PREFIX"); - println(" --cinclude=FILE Include FILE in generated .c"); - println(" --c=CFILE Generates C code in CFILE"); - println(" --h=HFILE Generates H code in HFILE"); - println("[ C# options]"); - println(" --cs Generates C# code in FILE.cs"); - println(" --cs=CSFILE Generates C# code in CSFILE"); - println(" --csnamespace=NAMESPACE Place C# classes in NAMESPACE"); - println("[ Java options ]"); - println(" --java=JDIR Generates Java files in JDIR"); - println(" --javapackage=PACKAGE Place Java classes in PACKAGE"); - println("[ Python options ]"); - println(" -P Generates Python code in FILE.py"); - println(" --python=PFILE Generates Python code in PFILE"); - println("[ RAPID options ]"); - println(" --rapid Generates RAPID code in FILE.sys"); - println("[ Misc options ]"); - println(" --pretty=PFILE Pretty prints to PFILE"); - println(" --typeinfo=TIFILE Generates typeinfo in TIFILE"); - } + public static void main(String[] args) throws Exception { + String ver = null; + Vector<String> outargs = new Vector<String>(); - /** To be cleaned up. - */ - private static void checkVersion(int v) { - if(! (v == 2006 || v == 2013) ) { - System.err.println(" Unknown version: " + v); - System.err.println(" Supported versions: 2006, 2013 "); - System.exit(2); - } - } - - private static void genH(Program p, String hName, - Vector cIncludes, String coreName, String prefix, int ver) { - try { - FileOutputStream f; - PrintStream out; - - f = new FileOutputStream(hName); - out = new PrintStream(f); - p.C_genH(out, cIncludes, coreName, prefix, ver); - out.close(); - } catch (IOException e) { - System.err.println("IOException: " + hName + " " + e); - } - } - - private static void genC(Program p, String cName, - Vector cIncludes, String coreName, String prefix, int ver) { - try { - FileOutputStream f; - PrintStream out; - - f = new FileOutputStream(cName); - out = new PrintStream(f); - p.C_genC(out, cIncludes, coreName, prefix, ver); - out.close(); - } catch (IOException e) { - System.err.println("IOException: " + cName + " " + e); - } - } - - private static void genCS(Program p, String csName, String csNamespace, int ver) { -// throw new Error("C# generation currently disabled"); - try { - p.CS_gen(csName, csNamespace, ver); - } catch (IOException e) { - System.err.println("IOException: " + csName + " " + - csNamespace + " " + e); - } - } - - private static void genJava(Program p, String dirName, String packageName, int ver) { - try { - p.J_gen(dirName, packageName, ver); - } catch (IOException e) { - System.err.println("IOException: " + dirName + " " + - packageName + " " + e); - } - } - - private static void genPython(Program p, String filename, String prefix, int ver) { - try { - FileOutputStream f; - PrintStream out; - - f = new FileOutputStream(filename); - out = new PrintStream(f); - p.Python_gen(out, prefix, ver); - out.close(); - } catch (IOException e) { - System.err.println("IOException: " + filename + " " + e); - } - } - - private static void genRAPID(Program p, String filename, String prefix, int ver) { - try { - p.RAPID_gen(filename, prefix, ver); - } catch (IOException e) { - System.err.println("IOException: " + filename + " " + e); - } - } - - /** Helper class to contain command line options - and their associated behaviour - **/ - private static class Opts { - final String[] args; - String coreName = null; - String prefix = null; - boolean verbose = false; - int ver = 2013; //Version 2013 as default - String cFile = null; - String hFile = null; - Vector cIncludes = new Vector(); - String cPrefix; // gets default value (prefix) in processFilename - String csFile = null; - String csNamespace = null; - String javaDir = null; - String javaPackage = ""; - String pythonFile = null; - String prettyFile = null; - String typeinfoFile = null; - String rapidFile = null; - String fileName = null; - - Opts(String[] args) { - this.args = args; - } - - private static String getCoreName(String s) { - int i = s.lastIndexOf('.'); - return s.substring(0, i > 0 ? i : s.length()); - } - - private static String getFileName(String s) { - return s.substring(s.lastIndexOf('/') + 1, s.length()); - } - - private static String getBaseName(String s) { - s = getFileName(s); - int i = s.lastIndexOf('.'); - return s.substring(0, i > 0 ? i : s.length()); - } - - private static String getPrefix(String s) { - return s.substring(s.lastIndexOf('/') + 1, s.length()); - } - - boolean processFilename(){ - // Scan for first non-option - for (int i = 0 ; i < args.length ; i++) { - if (! args[i].startsWith("-")) { - fileName = args[i]; - break; - } - } - if (fileName != null) { - coreName = getBaseName(fileName); - prefix = getPrefix(coreName); - cPrefix = prefix; - } - return fileName != null; - } - - void processArgs(){ - for (int i = 0 ; i < args.length ; i++) { - if (fileName == null || - args[i].equals("-help") || - args[i].equals("-h") || - args[i].equals("--help")) { - print_help(); - System.exit(0); - } else if (args[i].equals("-v")) { - verbose=true; - } else if (args[i].startsWith("--ver=")) { - ver = Integer.parseInt(args[i].substring(6)); - checkVersion(ver); - } else if (args[i].equals("-C")) { - cFile = coreName + ".c"; - hFile = coreName + ".h"; - } else if (args[i].startsWith("--cinclude=")) { - cIncludes.add(args[i].substring(11)); - } else if (args[i].startsWith("--cprefix=")) { - cPrefix = args[i].substring(10); - } else if (args[i].startsWith("--c=")) { - cFile = args[i].substring(4); - } else if (args[i].startsWith("--h=")) { - hFile = args[i].substring(4); - } else if (args[i].equals("--cs")) { - csFile = coreName + ".cs"; - } else if (args[i].startsWith("--cs=")) { - csFile = args[i].substring(5); - } else if (args[i].startsWith("--csnamespace=")) { - csNamespace = args[i].substring(14); - } else if (args[i].startsWith("--java=")) { - javaDir = args[i].substring(7); - } else if (args[i].startsWith("--javapackage=")) { - javaPackage = args[i].substring(14); - } else if (args[i].equals("-P")) { - pythonFile = coreName + ".py"; - } else if (args[i].startsWith("--python=")) { - pythonFile = args[i].substring(9); - } else if (args[i].startsWith("--pretty=")) { - prettyFile = args[i].substring(9); - } else if (args[i].startsWith("--typeinfo=")) { - typeinfoFile = args[i].substring(11); - } else if (args[i].equals("--rapid")) { - rapidFile = coreName + ".sys"; - } else if (i == args.length - 1) { - fileName = args[i]; - } else { - System.err.println(" Unknown argument " + args[i]); - print_help(); - System.exit(2); + for (String s: args) { + if (s.startsWith("--ver=")) { + String newver = s.substring(6); + if (ver != null && !ver.equals(newver)) { + throw new Exception("Mismatching versions '" + ver + + "' != '" + newver); + } + ver = newver; + } else { + outargs.add(s); } - if(prefix==null){ - System.err.println(" WARNING! prefix==null"); - prefix=""; - } - } - - Program parseFile(){ - Program ast = null; - try { - // Check for errors - LabCommScanner scanner = new LabCommScanner( - new FileReader(fileName)); - LabCommParser parser = new LabCommParser(); - Program p = (Program)parser.parse(scanner); - Collection errors = new LinkedList(); - p.errorCheck(errors); - - if (errors.isEmpty()) { - ast = p; - } else { - for (Iterator iter = errors.iterator(); iter.hasNext(); ) { - String s = (String)iter.next(); - System.out.println(s); - } - } - } catch (FileNotFoundException e) { - System.err.println("Could not find file: " + fileName); - } catch (IOException e) { - System.err.println("IOException: " + fileName + " " + e); - } catch (beaver.Parser.Exception e) { - System.err.println(e.getMessage()); - } - return ast; - } - - boolean generateC(Program ast) { - boolean wroteFile = false; - Vector hIncludes = new Vector(cIncludes); - if (hFile != null) { - cIncludes.add(hFile); - } - if (cFile != null) { - printStatus("C: " , cFile); - genC(ast, cFile, cIncludes, coreName, cPrefix, ver); - wroteFile = true; - } - if (hFile != null) { - printStatus("H: " , hFile); - genH(ast, hFile, hIncludes, coreName, cPrefix, ver); - wroteFile = true; - } - return wroteFile; - } - - boolean generateCS(Program ast) { - boolean wroteFile = false; - if (csFile != null) { - printStatus("C#: " , csFile); - genCS(ast, csFile, csNamespace, ver); - wroteFile = true; - } - return wroteFile; - } - - boolean generateJava(Program ast) { - boolean wroteFile = false; - if (javaDir != null) { - printStatus("Java: " , javaDir); - genJava(ast, javaDir, javaPackage, ver); - wroteFile = true; - } - return wroteFile; - } - - boolean generatePython(Program ast) { - boolean wroteFile = false; - if (pythonFile != null) { - printStatus("Python: " , pythonFile); - genPython(ast, pythonFile, prefix, ver); - wroteFile = true; - } - return wroteFile; - } - - boolean generateRAPID(Program ast) { - boolean wroteFile = false; - if (rapidFile != null) { - printStatus("RAPID: " , rapidFile); - genRAPID(ast, rapidFile, coreName, ver); - wroteFile = true; - } - return wroteFile; - } - boolean generatePrettyPrint(Program ast) { - boolean wroteFile = false; - if (prettyFile != null) { - printStatus("Pretty: " , prettyFile); - try { - FileOutputStream f = new FileOutputStream(prettyFile); - PrintStream out = new PrintStream(f); - ast.pp(out); - out.close(); - wroteFile = true; - } catch (IOException e) { - System.err.println("IOException: " + prettyFile + " " + e); - } - } - return wroteFile; - } - - boolean generateTypeinfo(Program ast) { - boolean wroteFile = false; - if (typeinfoFile != null) { - printStatus("TypeInfo: " , typeinfoFile); - try { - FileOutputStream f = new FileOutputStream(typeinfoFile); - PrintStream out = new PrintStream(f); - ast.C_info(out, cPrefix, ver); - ast.Java_info(out, ver); - ast.CS_info(out, csNamespace, ver); - wroteFile = true; - } catch (IOException e) { - System.err.println("IOException: " + typeinfoFile + " " + e); - } - } - return wroteFile; } - - private void printStatus(String kind, String filename){ - if (verbose) { - System.err.println("Generating "+kind+": " + filename); - } + for (String s: outargs) { + System.out.println(s); } + if (ver != null && ver.equals("2006")) { + outargs.add(0, "--ver=2006"); + se.lth.control.labcomm2006.compiler.LabComm.main(outargs.toArray( + new String[0])); + } else if (ver == null || ver.equals("2014")) { + outargs.add(0, "--ver=2014"); + se.lth.control.labcomm2014.compiler.LabComm.main(outargs.toArray( + new String[0])); + } } - - public static void main(String[] args) { - Opts opts = new Opts(args); - if(!opts.processFilename()) { - print_help(); - System.exit(1); - } else { - opts.processArgs(); - Program ast = opts.parseFile(); - - if (ast != null) { - - boolean fileWritten = false; - - fileWritten |= opts.generateC(ast); - fileWritten |= opts.generateCS(ast); - fileWritten |= opts.generateJava(ast); - fileWritten |= opts.generatePython(ast); - fileWritten |= opts.generateRAPID(ast); - fileWritten |= opts.generatePrettyPrint(ast); - fileWritten |= opts.generateTypeinfo(ast); - - // if no output to files, prettyprint on stdout - if (!fileWritten) { - ast.pp(System.out); - } - } else { - // Catch-all for compilation errors - System.err.println("Error in specification"); - System.exit(3); - } - } - } } diff --git a/compiler/build.xml b/compiler/build.xml index bcfe310..32c5448 100644 --- a/compiler/build.xml +++ b/compiler/build.xml @@ -23,48 +23,9 @@ <taskdef name="beaver" classname="beaver.comp.run.AntTask" classpath="tools/beaver-ant.jar"/> <!-- "jastadd" is an ant task class in jastadd2.jar --> <taskdef name="jastadd" classname="jastadd.JastAddTask" -classpath="tools/jastadd2.jar"/> + classpath="tools/jastadd2.jar"/> - -<!-- compile sources --> -<target name="build" depends="gen"> - <javac debug="true" nowarn="true" srcdir="." includes="**/*.java" excludes="test/** examples/**" classpath=".:${tools}/beaver-rt.jar:${tools}/junit.jar" - fork="true" memoryMaximumSize="128M"> - <!-- compilerarg value="-Xlint"/ --> - </javac> -</target> - -<!-- generate compiler source files --> -<target name="gen"> - <!-- create AST node types and weave aspect modules --> - <echo message = "Running JastAdd"/> - <jastadd package="${package}" rewrite="true" beaver="true" novisitcheck="true" lazyMaps="true" outdir="${basedir}"> - <fileset dir="."> - <include name="**/*.ast"/> - <include name="**/*.jrag"/> - <include name="**/*.jadd"/> - </fileset> - </jastadd> - <!-- generate the scanner --> - <echo message = "Running jflex"/> - <jflex file="LabCommScanner.flex" outdir="AST" nobak="yes"/> - <!-- generate the parser phase 1, create a full .lalr specification from fragments--> - <echo message = "Running parser phase 1"/> - <concat destfile="AST/LabCommParser.all" binary="true"> - <fileset dir="."> - <include name="*.parser"/> - </fileset> - </concat> - <!-- generate the parser phase 2, translating .lalr to .beaver --> - <java fork="true" dir="${basedir}" classpath="${tools}/proj.jar:${tools}/beaver-rt.jar" classname="Main"> - <arg line="AST/LabCommParser.all AST/LabCommParser.beaver"/> - </java> - <!-- generate the parser phase 3, translating .beaver to .java --> - <beaver file="AST/LabCommParser.beaver" terminalNames="yes" compress="yes" useSwitch="yes"/> -</target> - - <!-- compile sources --> <target name="test" depends="jar"> <echo message = "Running tests"/> @@ -77,8 +38,10 @@ classpath="tools/jastadd2.jar"/> <!-- remove generated source files and .class files --> <target name="clean" depends="cleanGen"> <!-- delete all .class files recursively --> + <delete dir="gen"/> <delete> <fileset dir="." includes="**/*.class"/> + <fileset dir="." includes="gen"/> <fileset dir="." includes="labcomm_compiler.jar"/> </delete> @@ -87,21 +50,105 @@ classpath="tools/jastadd2.jar"/> <!-- remove generated source files and their .class files --> <target name="cleanGen"> - <delete dir="${package}"/> + <delete dir="${package}"/> </target> <target name="jar" depends="build"> <jar destfile="labcomm_compiler.jar"> - <fileset dir="." includes="LabComm*.class"/> - <fileset dir="." includes="AST/*.class"/> + <fileset dir="gen" includes="**/*.class"/> <zipfileset src="tools/beaver-rt.jar" includes="beaver/*.class"/> <manifest> <attribute name="Main-Class" value="LabComm"/> </manifest> </jar> </target> - + +<!-- generate compiler source files --> +<target name="gen_compiler_version"> + <local name="package"/> + <local name="package_path"/> + <property name="package" value="se.lth.control.labcomm${version}.compiler"/> + <loadresource property="package_path"> + <propertyresource name="package"/> + <filterchain> + <tokenfilter> + <filetokenizer/> + <replacestring from="." to="/"/> + </tokenfilter> + </filterchain> + </loadresource> + + <mkdir dir="${outdir}"/> + + <!-- create AST node types and weave aspect modules --> + <echo message = "Running JastAdd"/> + <jastadd package="${package}" rewrite="true" beaver="true" + novisitcheck="true" lazyMaps="true" outdir="${outdir}"> + <fileset dir="."> + <include name="${version}/*.ast"/> + <include name="${version}/*.jrag"/> + <include name="${version}/*.jadd"/> + </fileset> + </jastadd> + + <!-- generate the scanner --> + <echo message = "Running jflex -> ${package} ${package_path}"/> + <jflex file="${version}/LabCommScanner.flex" + outdir="${outdir}/${package_path}" nobak="yes"/> + + <!-- generate the parser phase 1, create a full .lalr specification + from fragments--> + <echo message = "Running parser phase 1"/> + <concat destfile="${outdir}/${package_path}/LabCommParser.all" binary="true"> + <fileset dir="."> + <include name="${version}/*.parser"/> + </fileset> + </concat> + + <!-- generate the parser phase 2, translating .lalr to .beaver --> + <echo message = "translating .lalr to .beaver"/> + <java fork="true" dir="${basedir}" + classpath="${tools}/proj.jar:${tools}/beaver-rt.jar" classname="Main"> + <arg line="${outdir}/${package_path}/LabCommParser.all + ${outdir}/${package_path}/LabCommParser.beaver"/> + </java> + + <!-- generate the parser phase 3, translating .beaver to .java --> + <echo message = "translating .beaver to .java"/> + <beaver file="${outdir}/${package_path}/LabCommParser.beaver" + terminalNames="yes" compress="yes" useSwitch="yes"/> + + <echo message = "compiling .java"/> +<!-- + <javac debug="true" srcdir="." destdir="${outdir}" + includes="${version}/*.java ${outdir}/${package_path}/*.java" + classpath="gen:${tools}/beaver-rt.jar:${tools}/junit.jar" + includeantruntime="false" + fork="true" memoryMaximumSize="128M"> + <!- -compilerarg value="-Xlint"/- -> + </javac> +--> +</target> + +<target name="build"> + <antcall target="gen_compiler_version"> + <param name="version" value="2006"/> + <param name="outdir" value="gen"/> + </antcall> + <antcall target="gen_compiler_version"> + <param name="version" value="2014"/> + <param name="outdir" value="gen"/> + </antcall> + <echo message = "compiling main"/> + <javac debug="true" srcdir="." destdir="gen" + includes="*.java 2006/*.java 2014/*.java gen/**/*.java" + classpath="gen:${tools}/beaver-rt.jar:${tools}/junit.jar" + includeantruntime="false" + fork="true" memoryMaximumSize="128M"> + <!--compilerarg value="-Xlint"/--> + </javac> +</target> </project> diff --git a/compiler/cs_codegen.patch b/compiler/cs_codegen.patch deleted file mode 100644 index 397a493..0000000 --- a/compiler/cs_codegen.patch +++ /dev/null @@ -1,34 +0,0 @@ -*** CS_CodeGen.old 2010-06-03 13:46:00.000000000 +0200 ---- CS_CodeGen.jrag 2010-06-03 14:05:00.000000000 +0200 -*************** -*** 419,424 **** ---- 419,426 ---- - 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; -*************** -*** 434,439 **** ---- 436,443 ---- - 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) { -*************** -*** 725,730 **** ---- 729,735 ---- - 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; - } - } diff --git a/compiler/java_array_encode.patch b/compiler/java_array_encode.patch deleted file mode 100644 index 684a55e..0000000 --- a/compiler/java_array_encode.patch +++ /dev/null @@ -1,24 +0,0 @@ -*** Java_CodeGen.old 2010-05-31 10:13:44.000000000 +0200 ---- Java_CodeGen.jrag 2010-05-31 10:22:55.000000000 +0200 -*************** -*** 445,450 **** ---- 445,452 ---- - 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]"; - } -*************** -*** 456,461 **** ---- 458,465 ---- - 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) { -- GitLab