X-Git-Url: http://svarog.pmf.uns.ac.rs/gitweb/?p=mjc2wsl.git;a=blobdiff_plain;f=src%2Fcom%2Fquemaster%2Ftransformations%2Fmjc2wsl%2Fmjc2wsl.java;h=233d5ae76bf5b5ecf9f0a441be244593e1ffc510;hp=68fd2a108c4c2efde206cb26696852636ee32f4d;hb=c32b5ce57ed98cda547444ba0c37293fe7a4bd9c;hpb=91b863207c21295ff02240fffa877097a2b66817;ds=sidebyside diff --git a/src/com/quemaster/transformations/mjc2wsl/mjc2wsl.java b/src/com/quemaster/transformations/mjc2wsl/mjc2wsl.java index 68fd2a1..233d5ae 100644 --- a/src/com/quemaster/transformations/mjc2wsl/mjc2wsl.java +++ b/src/com/quemaster/transformations/mjc2wsl/mjc2wsl.java @@ -1,6 +1,6 @@ package com.quemaster.transformations.mjc2wsl; /* - Copyright (C) 2014 Doni Pracner + Copyright (C) 2014,2015, 2016 Doni Pracner This file is part of mjc2wsl. @@ -40,7 +40,7 @@ import com.quemaster.transformations.TransMessages; */ public class mjc2wsl{ //default version name, used if the file is not found - private static String versionN = "0.1.x"; + private static String versionN = "v0.2.x"; private String versionFile = "version.properties"; @@ -52,7 +52,12 @@ public class mjc2wsl{ private boolean genPopPush=false; - private boolean genInlinePrint=false; + private boolean genInlinePrint = false; + + private boolean genLocalVars = true; + + // make an array for all local variables OTHERWISE make them separate + private boolean genLocalsAsArray = true; /** Constant used for marking a regular comment from the original file */ public static final char C_REG = ' '; @@ -135,8 +140,9 @@ public class mjc2wsl{ versionData = new Properties(); try { versionData.load(getClass().getResourceAsStream(versionFile)); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException | NullPointerException e) { + // it doesn't matter + //e.printStackTrace(); } } String ver = versionData.getProperty("version"); @@ -174,14 +180,20 @@ public class mjc2wsl{ public String createStandardStart(int numWords){ StringBuilder ret = new StringBuilder( "C:\" This file automatically converted from microjava bytecode\";\n" - +"C:\" with mjc2wsl v "+getVersion()+"\";\n"); + +"C:\" with mjc2wsl "+getVersion()+"\";\n"); ret.append("\nBEGIN"); ret.append("\nVAR <\n\t"); - ret.append("mjvm_locals := ARRAY(1,0),"); + if (!genLocalVars){ + ret.append("\n\ttempa := 0, tempb :=0, tempres := 0,"); + } else + ret.append("\n\tmjvm_flag_jump := 0,"); + + if (genLocalsAsArray) + ret.append("mjvm_locals := ARRAY(1,0),"); + ret.append("\n\tmjvm_statics := ARRAY("+numWords+",0),"); ret.append("\n\tmjvm_arrays := < >,"); - ret.append("\n\tmjvm_flag_jump := 0,"); ret.append("\n\tmjvm_objects := < >,"); ret.append("\n\tmjvm_estack := < >, mjvm_mstack := < > > :"); @@ -201,22 +213,17 @@ public class mjc2wsl{ ret.append("\nWHERE\n"); ret.append("\nFUNCT CHR(num) ==:\n"); - ret.append("\t@List_To_String(< num >)\n"); + ret.append("\t(@List_To_String(< num >))\n"); ret.append("END\n"); if (!genInlinePrint) { ret.append("\nPROC Print_MJ(val, format VAR)==\n"); - ret.append(createComment("print spacing", C_SPEC)); - ret.append("\n\tIF format>1 THEN\n\t\tFOR i:=2 TO "); - ret.append("format STEP 1 DO PRINFLUSH(\" \") OD\n"); - ret.append("\tFI;\n\tPRINFLUSH(val)\nEND\n"); + ret.append("PRINFLUSH(@Format(format, val ))"); + ret.append("\nEND\n"); ret.append("\nPROC Print_MJ_CHAR(val, format VAR)==\n"); - ret.append(createComment("print spacing", C_SPEC)); - ret.append("\n\tIF format>1 THEN\n\t\tFOR i:=2 TO "); - ret.append("format STEP 1 DO PRINFLUSH(\" \") OD\n"); - ret.append("\tFI;\n\tPRINFLUSH(CHR(val))\n"); - ret.append("END\n"); + ret.append("PRINFLUSH(@Format(format, CHR(val)))"); + ret.append("\nEND\n"); } ret.append("\nEND"); @@ -224,22 +231,31 @@ public class mjc2wsl{ } private String createStartVar(String... vars){ - StringBuilder ret = new StringBuilder("VAR < "); - ret.append(vars[0] + " := 0"); - for (int i=1; i : "); - - return ret.toString(); + if (genLocalVars) { + StringBuilder ret = new StringBuilder("VAR < "); + ret.append(vars[0] + " := 0"); + for (int i = 1; i < vars.length; i++) + ret.append(", " + vars[i] + " := 0"); + ret.append(" > : "); + + return ret.toString(); + } + return ""; } private String createEndVar(){ - return "ENDVAR;"; + if (genLocalVars) + return "ENDVAR;"; + else + return ""; } private String createLocal(int i) { // arrays start at 1 in WSL, so we need an offset - return "mjvm_locals[" + (i + 1) + "]"; + if (genLocalsAsArray) + return "mjvm_locals[" + (i + 1) + "]"; + else + return "mjvm_locals_" + i; } private String createStatic(int i) { @@ -347,6 +363,10 @@ public class mjc2wsl{ prl(createStandardStart(mjInput.getNumberOfWords(this))); prl("SKIP;\n ACTIONS a" + (14 + mjInput.getMainAdr(this)) + " :"); + + // the number of Locals for procedures; need to remember it for exits + int numberOfLocals = 0; + int op = mjInput.get(); while (op >= 0) { prl(" a" + mjInput.getCounter() + " =="); @@ -355,7 +375,7 @@ public class mjc2wsl{ if (genPrintForEachAddress) { prl("PRINT(\"a" + mjInput.getCounter() + "\");"); if (genPauseAfterEachAddress) - prl("debug_disposable_string := @Read_Line(Standard_Input_Port);"); + prl("@Read_Line_Proc(VAR debug_disposable_string, Standard_Input_Port);"); } switch (op) { case load: { @@ -591,18 +611,26 @@ public class mjc2wsl{ case jle: case jgt: case jge: { - prl(createStartVar("tempa", "tempb")); - prl(createTopTwoEStack()); - prl("IF tempb " + mjInput.getRelationFor(op) - + " tempa THEN mjvm_flag_jump := 1" - + " ELSE mjvm_flag_jump := 0" - + " FI;"); - prl(createEndVar()); - prl("IF mjvm_flag_jump = 1 THEN CALL a" - + (mjInput.getCounter() + mjInput.get2()) - + " ELSE CALL a" + (mjInput.getCounter() + 1) - + " FI;"); - + if (genLocalVars) { + prl(createStartVar("tempa", "tempb")); + prl(createTopTwoEStack()); + prl("IF tempb " + mjInput.getRelationFor(op) + + " tempa THEN mjvm_flag_jump := 1" + + " ELSE mjvm_flag_jump := 0" + + " FI;"); + prl(createEndVar()); + prl("IF mjvm_flag_jump = 1 THEN CALL a" + + (mjInput.getCounter() + mjInput.get2()) + + " ELSE CALL a" + (mjInput.getCounter() + 1) + + " FI;"); + } else { + prl(createTopTwoEStack()); + prl("IF tempb " + mjInput.getRelationFor(op) + + " tempa THEN CALL a" + + (mjInput.getCounter() + mjInput.get2()) + + " ELSE CALL a" + (mjInput.getCounter() + 1) + + " FI;"); + } break; } @@ -620,27 +648,46 @@ public class mjc2wsl{ case enter: { int parameters = mjInput.get(); - int locals = mjInput.get(); - prl(createToMStack("mjvm_locals")); - prl("mjvm_locals := ARRAY(" + locals + ",0);"); + numberOfLocals = mjInput.get(); + if (genLocalsAsArray) { + prl(createToMStack("mjvm_locals")); + prl("mjvm_locals := ARRAY(" + numberOfLocals + ",0);"); + } else { + // TODO maybe we should generate VAR block for these somewhere + for (int i = 0; i < numberOfLocals; i++) { + prl(createToMStack(createLocal(i))); + } + } + for (int i = parameters - 1; i >= 0; i--) prl(createFromEStack(createLocal(i))); break; } case exit: { - prl(createFromMStack("mjvm_locals")); + if (genLocalsAsArray) { + prl(createFromMStack("mjvm_locals")); + } else { + // there are as many locals as defined in the last enter + for (int i = numberOfLocals -1; i >= 0; i--) + prl(createFromMStack(createLocal(i))); + } break; } // read, print case bread: { - // TODO make it a char for read - messages.message("char is read like a number", TransMessages.M_WAR); - prl(createComment("char is read like a number", C_SPEC)); + // TODO maybe we'll need a bufer for multi chars! + prl(createStartVar("tempa")); + prl("@Read_Line_Proc(VAR tempa, Standard_Input_Port);"); + prl("tempa := @String_To_List(tempa)[1];"); + prl(createToEStack("tempa")); + prl(createEndVar()); + break; } case read: { prl(createStartVar("tempa")); - prl("tempa := @String_To_Num(@Read_Line(Standard_Input_Port));"); + prl("@Read_Line_Proc(VAR tempa, Standard_Input_Port);"); + prl("tempa := @String_To_Num(tempa);"); prl(createToEStack("tempa")); prl(createEndVar()); break; @@ -652,20 +699,19 @@ public class mjc2wsl{ prl(createTopTwoEStack()); if (genInlinePrint){ prl(createComment("print spacing and transformation",C_SPEC)); - prl("PRINFLUSH(SUBSTR(\" \", 0, MIN(10, MAX(0,tempa-1))), @List_To_String(< tempb >));"); + prl("PRINFLUSH(@Format(tempa, @List_To_String(< tempb >)));"); } else prl("Print_MJ_CHAR(tempb,tempa);"); prl(createEndVar()); break; } case print: { - // TODO printing numbers needs different lengths of spacing prl(createStartVar("tempa", "tempb")); prl(createTopTwoEStack()); if (genInlinePrint){ prl(createComment("print spacing",C_SPEC)); - prl("PRINFLUSH(SUBSTR(\" \", 0, MIN(10, MAX(0, tempa-SLENGTH(@String(tempb))))), tempb);"); + prl("PRINFLUSH(@Format(tempa,tempb));"); } else prl("Print_MJ(tempb,tempa);"); @@ -743,12 +789,26 @@ public class mjc2wsl{ } public void printHelpDirectives(){ - System.out.println("Alternatives for code generation:"); - System.out.println(" --genPopPush generate POP/PUSH instead of TAIL/HEAD"); - System.out.println(" --genHeadTail generate TAIL/HEAD instead of POP/PUSH "); + System.out.println("Alternatives for code generation (* are the defaults):"); + System.out.print(genPopPush?'*':' '); + System.out.println(" --genPopPush generate POP/PUSH instead of TAIL/HEAD"); + System.out.print(!genPopPush?'*':' '); + System.out.println(" --genHeadTail generate TAIL/HEAD instead of POP/PUSH "); + System.out.println(); + System.out.print(genInlinePrint?'*':' '); + System.out.println(" --genInlinePrint generate prints directly instead of procedure calls"); + System.out.print(!genInlinePrint?'*':' '); + System.out.println(" --genProcedurePrint generate prints as custom procedure calls"); + System.out.println(); + System.out.print(genLocalVars?'*':' '); + System.out.println(" --genLocalVars generate local VAR block for temp variables"); + System.out.print(!genLocalVars?'*':' '); + System.out.println(" --genGlobalVars do NOT generate local VAR block for temp variables"); System.out.println(); - System.out.println(" --genInlinePrint generate prints directly instead of procedure calls"); - System.out.println(" --genProcedurePrint generate prints as custom procedure calls"); + System.out.print(genLocalsAsArray?'*':' '); + System.out.println(" --genLocalsAsArray generate local variables as an array"); + System.out.print(!genLocalsAsArray?'*':' '); + System.out.println(" --genLocalsSeparate generate local variables as separate entities"); } public void printHelpHelp() { @@ -763,7 +823,7 @@ public class mjc2wsl{ } public void printVersion() { - System.out.println("MicroJava bytecode to WSL converter. v " + getVersion() + System.out.println("MicroJava bytecode to WSL converter " + getVersion() + ", by Doni Pracner"); } @@ -779,7 +839,7 @@ public class mjc2wsl{ printHelp(); } else { int i = 0; - while (i < args.length && args[i].charAt(0) == '-') { + while (i < args.length && args[i].length() > 0 && args[i].charAt(0) == '-') { if (args[i].compareTo("-h") == 0) { printHelp(); return; @@ -827,6 +887,16 @@ public class mjc2wsl{ genPopPush = false; } else if (args[i].compareToIgnoreCase("--genProcedurePrint") == 0) { genInlinePrint = false; + } else if (args[i].compareToIgnoreCase("--genLocalVars") == 0) { + genLocalVars = true; + } else if (args[i].compareToIgnoreCase("--genGlobalVars") == 0) { + genLocalVars = false; + } else if (args[i].compareToIgnoreCase("--genLocalsAsArray") == 0) { + genLocalsAsArray = true; + } else if (args[i].compareToIgnoreCase("--genLocalsSeparate") == 0) { + genLocalsAsArray = false; + } else { + System.err.println("unknown option: "+args[i]); } i++; } @@ -837,7 +907,7 @@ public class mjc2wsl{ } Path p = FileSystems.getDefault().getPath(args[i]); - if (!Files.exists(p)){ + if (!Files.isRegularFile(p)){ System.err.println("input file does not exist"); System.exit(1); }