diff --git a/.gitignore b/.gitignore index 36b13f1..01a1eb4 100644 --- a/.gitignore +++ b/.gitignore @@ -174,3 +174,5 @@ cython_debug/ # PyPI configuration file .pypirc +# IDE +.idea diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/Construction-of-Compilers.iml b/.idea/Construction-of-Compilers.iml deleted file mode 100644 index 24ef2ea..0000000 --- a/.idea/Construction-of-Compilers.iml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml deleted file mode 100644 index 94f5af2..0000000 --- a/.idea/dictionaries/project.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - btns - ldsp - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index a794ecf..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index f7274d5..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index dfd6964..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 8306744..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/.gitignore b/Project-01/uap25-pro01-tram/.gitignore new file mode 100644 index 0000000..75a07d4 --- /dev/null +++ b/Project-01/uap25-pro01-tram/.gitignore @@ -0,0 +1,5 @@ +# Java build dir +out + +# IDEA +.idea \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachine.java b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachine.java new file mode 100644 index 0000000..9dc83ce --- /dev/null +++ b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachine.java @@ -0,0 +1,68 @@ +package de.unitrier.st.uap.w25.tram; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +public class AbstractMachine { + protected List stack; + protected List prog; + + protected int FP = 0; + protected int PP = 0; + protected int PC = 0; + protected int TOP = 0; + + protected boolean debug = false; + + public AbstractMachine(Instruction[] prog) { + this.prog = Arrays.asList(prog); + this.stack = new LinkedList<>(); + } + + public AbstractMachine(Instruction[] prog, Integer[] stack) { + this(prog); + + this.stack = Arrays.asList(stack); + this.TOP = stack.length; + } + + public void setDebug(boolean debug) { + this.debug = debug; + } + + public void execute() { + for (Instruction instruction : prog) { + switch (instruction.getOpcode()) { + case Instruction.CONST: + int k = instruction.getArg1(); + this.stack.set(this.TOP + 1, k); + this.TOP += 1; + this.PC += 1; + break; + case Instruction.LOAD: break; + case Instruction.STORE: break; + case Instruction.ADD: break; + case Instruction.SUB: break; + case Instruction.MUL: break; + case Instruction.DIV: break; + case Instruction.LT: break; + case Instruction.GT: break; + case Instruction.EQ: break; + case Instruction.NEQ: break; + case Instruction.IFZERO: break; + case Instruction.GOTO: break; + case Instruction.HALT: break; + case Instruction.NOP: break; + case Instruction.INVOKE: break; + case Instruction.RETURN: break; + case Instruction.POP: break; + default: break; + } + } + } + + protected String config() { + return ""; + } +} diff --git a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Assembler.java b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Assembler.java new file mode 100644 index 0000000..1aa7bb5 --- /dev/null +++ b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Assembler.java @@ -0,0 +1,82 @@ +package de.unitrier.st.uap.w25.tram; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedList; + +public class Assembler { + static Instruction[] readTRAMCode(String filename) { + LinkedList code = new LinkedList(); + LinkedList lines = new LinkedList(); + HashMap labelmap = new HashMap(); + try (BufferedReader in = new BufferedReader(new FileReader(filename));) { + String line; + int lineNumber=0; + while((line = in.readLine())!=null) + { line=line.trim(); + if (line.startsWith("//") || line.startsWith("#") ) continue; + if (line.contains(":")) { + String[] labels=line.substring(0, line.indexOf(':')).split(","); + for (String label : labels) labelmap.put(label, lineNumber); + line = line.substring(line.indexOf(':')+1).trim(); + } + lines.add(line); + lineNumber++; + } + } catch (IOException e) { + File file = new File(filename); + System.err.println("Error reading file: " + file.getAbsolutePath()); + e.printStackTrace(); + } + for(String line: lines) { + code.add(convertToInstruction(line, labelmap)); + } + + return (Instruction[]) code.toArray(new Instruction[]{}); + } + + static Instruction convertToInstruction(String line, HashMap labelmap) { + String[] parts = line.split("\\s+"); + + return new Instruction( + stringToOpcode(parts[0]), + argToNumber(parts,1,labelmap), + argToNumber(parts,2,labelmap), + argToNumber(parts,3,labelmap)); + } + + static int stringToOpcode(String instr) { + switch(instr) { + case "CONST": return Instruction.CONST; + case "LOAD": return Instruction.LOAD; + case "STORE": return Instruction.STORE; + case "ADD": return Instruction.ADD; + case "SUB": return Instruction.SUB; + case "MUL": return Instruction.MUL; + case "DIV": return Instruction.DIV; + case "LT": return Instruction.LT; + case "GT": return Instruction.GT; + case "EQ": return Instruction.EQ; + case "NEQ": return Instruction.NEQ; + case "IFZERO": return Instruction.IFZERO; + case "GOTO": return Instruction.GOTO; + case "HALT": return Instruction.HALT; + case "NOP": return Instruction.NOP; + case "INVOKE": return Instruction.INVOKE; + case "RETURN": return Instruction.RETURN; + case "POP": return Instruction.POP; } + return -1; + } + + static Integer argToNumber(String[] parts, int index, HashMap labelmap) { + if (index>parts.length-1) return 0; + String arg=parts[index]; + try { return Integer.valueOf(arg); } + catch (NumberFormatException e) { + return labelmap.get(arg); + } + } +} \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Instruction.java b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Instruction.java new file mode 100644 index 0000000..434cad4 --- /dev/null +++ b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Instruction.java @@ -0,0 +1,330 @@ +/** + * Instructions for TRAM 2025 + */ + +package de.unitrier.st.uap.w25.tram; + +public class Instruction +{ + private int opcode; + private Integer arg1; + private Integer arg2; + private Integer arg3; + + public final static int CONST = 1; + public final static int LOAD = 2; + public final static int STORE = 3; + public final static int ADD = 4; + public final static int SUB = 5; + public final static int MUL = 6; + public final static int DIV = 7; + public final static int LT = 8; + public final static int GT = 9; + public final static int EQ = 10; + public final static int NEQ = 11; + public final static int IFZERO = 12; + public final static int GOTO = 13; + public final static int HALT = 14; + public final static int NOP = 15; + public final static int INVOKE = 16; + public final static int RETURN = 17; + public final static int POP = 18; + + + public Instruction(int opcode, Integer arg1, Integer arg2, Integer arg3) + { + this(opcode, arg1, arg2); + this.arg3 = arg3; + } + + + public Instruction(int opcode, Integer arg1, Integer arg2) + { + this(opcode, arg1); + this.arg2 = arg2; + } + + + public Instruction(int opcode, Integer arg1) + { + this(opcode); + this.arg1 = arg1; + } + + + public Instruction(int opcode) + { + this.opcode = opcode; + } + + + public Integer getArg1() + { + return arg1; + } + + + public void setArg1(Integer arg1) + { + this.arg1 = arg1; + } + + + public Integer getArg2() + { + return arg2; + } + + + public void setArg2(Integer arg2) + { + this.arg2 = arg2; + } + + + public Integer getArg3() + { + return arg3; + } + + + public void setArg3(Integer arg3) + { + this.arg3 = arg3; + } + + + public int getOpcode() + { + return opcode; + } + + + public void setOpcode(int opcode) + { + this.opcode = opcode; + } + + + @Override + public String toString() + { + String retStr = ""; + + switch (opcode) + { + case Instruction.CONST: + retStr += "CONST"; + break; + case Instruction.LOAD: + retStr += "LOAD"; + break; + case Instruction.STORE: + retStr += "STORE"; + break; + case Instruction.ADD: + retStr += "ADD"; + break; + case Instruction.SUB: + retStr += "SUB"; + break; + case Instruction.MUL: + retStr += "MUL"; + break; + case Instruction.DIV: + retStr += "DIV"; + break; + case Instruction.LT: + retStr += "LT"; + break; + case Instruction.GT: + retStr += "GT"; + break; + case Instruction.EQ: + retStr += "EQ"; + break; + case Instruction.NEQ: + retStr += "NEQ"; + break; + case Instruction.IFZERO: + retStr += "IFZERO"; + break; + case Instruction.GOTO: + retStr += "GOTO"; + break; + case Instruction.HALT: + retStr += "HALT"; + break; + case Instruction.NOP: + retStr += "NOP"; + break; + case Instruction.INVOKE: + retStr += "INVOKE"; + break; + case Instruction.RETURN: + retStr += "RETURN"; + break; + case Instruction.POP: + retStr += "POP"; + break; + default: + retStr += "ERROR"; + } + + if (arg1 != null) + { + retStr += " " + arg1; + + if (arg2 != null) + { + retStr += " " + arg2; + + if (arg3 != null) + { + retStr += " " + arg3; + } + } + } + + return retStr; + } + + + /*********************************************** + * Sample Programs + ***********************************************/ + + /** + * Quellkode: y = x*3+5*2 + * Annahmen: Variable x durch Kellerzelle 0 und Variable y durch Kellerzelle 1 implementiert, + * sowie PP=0, FP=0 und TOP=1. + */ + static Instruction[] program1 = new Instruction[] { + new Instruction(Instruction.CONST, 6), // value for x + new Instruction(Instruction.STORE, 0, 0), // store x + new Instruction(Instruction.LOAD, 0, 0), + new Instruction(Instruction.CONST, 3), + new Instruction(Instruction.MUL), + new Instruction(Instruction.CONST, 5), + new Instruction(Instruction.CONST, 2), + new Instruction(Instruction.MUL), + new Instruction(Instruction.ADD), + new Instruction(Instruction.STORE, 1, 0), + new Instruction(Instruction.HALT) }; + + /** + * Quellkode: x=10; if(x == 0) 100 else 200; 3 + * Annahmen: Variable x durch Kellerzelle 0 implementiert, sowie PP=0, FP=0 und TOP=0. + */ + static Instruction[] program2 = new Instruction[] { + new Instruction(Instruction.CONST, 10), + new Instruction(Instruction.STORE, 0, 0), + new Instruction(Instruction.LOAD, 0, 0), + new Instruction(Instruction.IFZERO, 6), // --> iftrue + new Instruction(Instruction.CONST, 200), + new Instruction(Instruction.GOTO, 7), // --> goto + // iftrue + new Instruction(Instruction.CONST, 100), + // goto + new Instruction(Instruction.NOP), + new Instruction(Instruction.CONST, 3), + new Instruction(Instruction.HALT) }; + + /** + * Quellkode: let square(x) { x*x } + * in square(10) + * Annahmen: Das Argument von square wird durch Kellerzelle 0 repraesentiert, sowie PP=0, FP=0 + * und TOP=-1 + */ + static Instruction[] program3 = new Instruction[] { + new Instruction(Instruction.CONST, 10), + new Instruction(Instruction.INVOKE, 1, 3, 0), // --> square + // return + new Instruction(Instruction.HALT), + // square + new Instruction(Instruction.LOAD, 0, 0), + new Instruction(Instruction.LOAD, 0, 0), + new Instruction(Instruction.MUL), + new Instruction(Instruction.RETURN) // --> return + }; + + /** + * Quellkode: let wrapper(number, threshold) { + * let square(x) { + * if (x*x > threshold) x + * else x*x + * } + * in square(number) + * } + * in wrapper(4, 10) + * Annahmen: Die Argumente von wrapper werden durch die Kellerzellen 0 und 1 repraesentiert, + * sowie PP=0, FP=0 und TOP=-1 + */ + static Instruction[] program4 = new Instruction[] { + new Instruction(Instruction.CONST, 4), + new Instruction(Instruction.CONST, 10), + new Instruction(Instruction.INVOKE, 2, 4, 0), // --> wrapper + // return wrapper + new Instruction(Instruction.HALT), + // wrapper + new Instruction(Instruction.LOAD, 0, 0), + new Instruction(Instruction.INVOKE, 1, 7, 0), // --> square + // return square + new Instruction(Instruction.RETURN), + // square + new Instruction(Instruction.LOAD, 0, 0), + new Instruction(Instruction.LOAD, 0, 0), + new Instruction(Instruction.MUL), + new Instruction(Instruction.LOAD, 1, 1), + new Instruction(Instruction.GT), + new Instruction(Instruction.IFZERO, 15), + new Instruction(Instruction.LOAD, 0, 0), + new Instruction(Instruction.RETURN), // --> return square + new Instruction(Instruction.LOAD, 0, 0), + new Instruction(Instruction.LOAD, 0, 0), + new Instruction(Instruction.MUL), + new Instruction(Instruction.RETURN) // --> return square + }; + + /** + * let f (x, y, z) { + * x = y + z; + * if ( y == 3) then + * 15 + * else + * f ( z = 3 ; 4 , y, z) + * } in f (2, 3, 4) + * + * Annahmen: keine + */ + static Instruction[] program5 = new Instruction[] { + new Instruction(Instruction.GOTO, 23), // --> L1 + new Instruction(Instruction.LOAD, 1, 0), // LF + new Instruction(Instruction.LOAD, 2, 0), + new Instruction(Instruction.ADD), + new Instruction(Instruction.STORE, 0, 0), + new Instruction(Instruction.LOAD, 0, 0), + new Instruction(Instruction.POP), + new Instruction(Instruction.LOAD, 1, 0), + new Instruction(Instruction.CONST, 3), + new Instruction(Instruction.EQ), + new Instruction(Instruction.IFZERO, 13), // --> L2 + new Instruction(Instruction.CONST, 15), + new Instruction(Instruction.GOTO, 21), // --> L3 + new Instruction(Instruction.CONST, 3), // L2 + new Instruction(Instruction.STORE, 2, 0), + new Instruction(Instruction.LOAD, 2, 0), + new Instruction(Instruction.POP), + new Instruction(Instruction.CONST, 4), + new Instruction(Instruction.LOAD, 1, 0), + new Instruction(Instruction.LOAD, 2, 0), + new Instruction(Instruction.INVOKE, 3, 1, 1), // --> LF + new Instruction(Instruction.NOP), // L3 + new Instruction(Instruction.RETURN), + new Instruction(Instruction.CONST, 2), // L1 + new Instruction(Instruction.CONST, 3), + new Instruction(Instruction.CONST, 4), + new Instruction(Instruction.INVOKE, 3, 1, 0), // --> LF + new Instruction(Instruction.HALT) + }; +} \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Main.java b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Main.java new file mode 100644 index 0000000..c1d152d --- /dev/null +++ b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Main.java @@ -0,0 +1,28 @@ +package de.unitrier.st.uap.w25.tram; + +final class Main +{ + private Main(){} + + public static void main(String[] argv) + { + Instruction[] code = Assembler.readTRAMCode( + // "tramcode/square.tram" + // "tramcode/wrapper.tram" + // "tramcode/example1.tram" + // "tramcode/example2.tram" + //"tramcode/example3.tram" + "tramcode/test.tram" + ); + + int lineNr=0; + for(Instruction instr: code) { + if (instr != null) { + System.out.println(String.format("%03d", lineNr) + "| " + instr.toString()); + lineNr++; + } + } + + // TODO: Create an instance of the abstract machine with reasonable parameters + } +} \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/tramcode/example1.tram b/Project-01/uap25-pro01-tram/tramcode/example1.tram new file mode 100644 index 0000000..5d9d0bb --- /dev/null +++ b/Project-01/uap25-pro01-tram/tramcode/example1.tram @@ -0,0 +1,14 @@ +// Quellkode: y = x*3+5*2 +// Annahmen: Variable x durch Kellerzelle 0 und Variable y durch Kellerzelle 1 implementiert, +// sowie PP=0, FP=0 und TOP=1. +CONST 6 +STORE 0 0 +LOAD 0 0 +CONST 3 +MUL +CONST 5 +CONST 2 +MUL +ADD +STORE 1 0 +HALT \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/tramcode/example2.tram b/Project-01/uap25-pro01-tram/tramcode/example2.tram new file mode 100644 index 0000000..12208f7 --- /dev/null +++ b/Project-01/uap25-pro01-tram/tramcode/example2.tram @@ -0,0 +1,13 @@ +// Quellkode: x=10; if(x == 0) 100 else 200; 3 +// Annahmen: Variable x durch Kellerzelle 0 implementiert, sowie PP=0, FP=0 und TOP=0. +// +CONST 10 +STORE 0 0 +LOAD 0 0 +IFZERO L1 +CONST 200 +GOTO L2 +L1: CONST 100 +L2: NOP +CONST 3 +HALT \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/tramcode/example3.tram b/Project-01/uap25-pro01-tram/tramcode/example3.tram new file mode 100644 index 0000000..d89419f --- /dev/null +++ b/Project-01/uap25-pro01-tram/tramcode/example3.tram @@ -0,0 +1,37 @@ + // Quellkode: let f (x, y, z) { + // x = y + z; + // if ( y == 3) then + // 15 + // else + // f ( z = 3 ; 4 , y, z) + // } in f (2, 3, 4) + // + // Annahmen: keine + GOTO L1 + LF: LOAD 1 0 + LOAD 2 0 + ADD + STORE 0 0 + LOAD 0 0 + POP + LOAD 1 0 + CONST 3 + EQ + IFZERO L2 + CONST 15 + GOTO L3 + CONST 3 + STORE 2 0 + LOAD 2 0 + POP + CONST 4 + LOAD 1 0 + LOAD 2 0 + INVOKE 3 LF 1 + L3: NOP + RETURN + L1: CONST 2 + CONST 3 + CONST 4 + INVOKE 3 LF 0 + HALT \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/tramcode/square.tram b/Project-01/uap25-pro01-tram/tramcode/square.tram new file mode 100644 index 0000000..a645e8e --- /dev/null +++ b/Project-01/uap25-pro01-tram/tramcode/square.tram @@ -0,0 +1,11 @@ +// Quellkode: let square(x) { x*x } +// in square(10) +// Annahmen: Das Argument von square wird durch Kellerzelle 0 repraesentiert, +// sowie PP=0, FP=0 und TOP=-1 +CONST 10 +INVOKE 1 LSQUARE 0 +HALT +LSQUARE: LOAD 0 0 +LOAD 0 0 +MUL +RETURN \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/tramcode/test.tram b/Project-01/uap25-pro01-tram/tramcode/test.tram new file mode 100644 index 0000000..44c9453 --- /dev/null +++ b/Project-01/uap25-pro01-tram/tramcode/test.tram @@ -0,0 +1,28 @@ + GOTO L2 +L1: LOAD 0 0 + CONST 0 + EQ + IFZERO L3 + CONST 0 + GOTO L4 +L3: LOAD 0 0 + CONST 1 + EQ + IFZERO L5 + CONST 1 + GOTO L6 +L5: LOAD 0 0 + CONST 1 + SUB + INVOKE 1 L1 1 + LOAD 0 0 + CONST 2 + SUB + INVOKE 1 L1 1 + ADD +L6: NOP +L4: NOP + RETURN +L2: CONST 6 + INVOKE 1 L1 0 + HALT \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/tramcode/wrapper.tram b/Project-01/uap25-pro01-tram/tramcode/wrapper.tram new file mode 100644 index 0000000..83fd896 --- /dev/null +++ b/Project-01/uap25-pro01-tram/tramcode/wrapper.tram @@ -0,0 +1,29 @@ +// Quellkode: let wrapper(number, threshold) { +// let square(x) { +// if (x*x > threshold) x +// else x*x +// } +// in square(number) +// } +// in wrapper(4, 10) +// Annahmen: Die Argumente von wrapper werden durch die Kellerzellen 0 und 1 repraesentiert, +// sowie PP=0, FP=0 und TOP=-1 +CONST 4 +CONST 10 +INVOKE 2 LWRAPPER 0 +HALT +LWRAPPER: LOAD 0 0 +INVOKE 1 LSQUARE 0 +RETURN +LSQUARE: LOAD 0 0 +LOAD 0 0 +MUL +LOAD 1 1 +GT +IFZERO L1 +LOAD 0 0 +RETURN +L1: LOAD 0 0 +LOAD 0 0 +MUL +RETURN \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/uap25-pro01-tram.iml b/Project-01/uap25-pro01-tram/uap25-pro01-tram.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/Project-01/uap25-pro01-tram/uap25-pro01-tram.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file