diff --git a/Project-01/uap25-pro01-tram/jar/tram.jar b/Project-01/uap25-pro01-tram/jar/tram.jar index ca34862..9261f40 100644 Binary files a/Project-01/uap25-pro01-tram/jar/tram.jar and b/Project-01/uap25-pro01-tram/jar/tram.jar differ 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 index 8fbb022..e68bcd2 100644 --- 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 @@ -35,7 +35,6 @@ public class AbstractMachine { // Executes single step and returns configuration public void executeStep() { try { - ensureCapacity(this.TOP); Instruction inst = this.prog.get(this.PC); int arg1 = inst.getArg1() != null ? inst.getArg1() : 0; @@ -45,96 +44,96 @@ public class AbstractMachine { switch (inst.getOpcode()) { case Instruction.CONST: // Pg. 9 - this.stack.set(this.TOP + 1, arg1); + write(this.TOP + 1, arg1); this.TOP += 1; this.PC += 1; break; case Instruction.LOAD: // Pg. 25 int loadSpp = spp(arg2, this.PP, this.FP); - this.stack.set(this.TOP + 1, this.stack.get(loadSpp + arg1)); + write(this.TOP + 1, read(loadSpp + arg1)); this.TOP += 1; this.PC += 1; break; case Instruction.STORE: // Pg. 25 int storeSpp = spp(arg2, this.PP, this.FP); - this.stack.set(storeSpp + arg1, this.stack.get(this.TOP)); + write(storeSpp + arg1, read(this.TOP)); this.TOP -= 1; this.PC += 1; break; case Instruction.ADD: // Pg. 9 - int addA = stack.get(this.TOP - 1); - int addB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, addA + addB); + int addA = read(this.TOP - 1); + int addB = read(this.TOP); + write(this.TOP - 1, addA + addB); this.TOP -= 1; this.PC += 1; break; case Instruction.SUB: // Pg. 9 - int subA = stack.get(this.TOP - 1); - int subB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, subA - subB); + int subA = read(this.TOP - 1); + int subB = read(this.TOP); + write(this.TOP - 1, subA - subB); this.TOP -= 1; this.PC += 1; break; case Instruction.MUL: // Pg. 9 - int mulA = stack.get(this.TOP - 1); - int mulB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, mulA * mulB); + int mulA = read(this.TOP - 1); + int mulB = read(this.TOP); + write(this.TOP - 1, mulA * mulB); this.TOP -= 1; this.PC += 1; break; case Instruction.DIV: // Pg. 9 - int divA = stack.get(this.TOP - 1); - int divB = stack.get(this.TOP); + int divA = read(this.TOP - 1); + int divB = read(this.TOP); if (divB == 0) { throw new ArithmeticException("Division by zero"); } - this.stack.set(this.TOP - 1, divA / divB); + write(this.TOP - 1, Math.floorDiv(divA, divB)); this.TOP -= 1; this.PC += 1; break; case Instruction.LT: // Pg. 12 - int ltA = stack.get(this.TOP - 1); - int ltB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, ltA < ltB ? 1 : 0); + int ltA = read(this.TOP - 1); + int ltB = read(this.TOP); + write(this.TOP - 1, ltA < ltB ? 1 : 0); this.TOP -= 1; this.PC += 1; break; case Instruction.GT: // Pg. 12 - int gtA = stack.get(this.TOP - 1); - int gtB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, gtA > gtB ? 1 : 0); + int gtA = read(this.TOP - 1); + int gtB = read(this.TOP); + write(this.TOP - 1, gtA > gtB ? 1 : 0); this.TOP -= 1; this.PC += 1; break; case Instruction.EQ: // Pg. 12 - int eqA = stack.get(this.TOP - 1); - int eqB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, eqA == eqB ? 1 : 0); + int eqA = read(this.TOP - 1); + int eqB = read(this.TOP); + write(this.TOP - 1, eqA == eqB ? 1 : 0); this.TOP -= 1; this.PC += 1; break; case Instruction.NEQ: // Pg. 12 - int neqA = stack.get(this.TOP - 1); - int neqB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, neqA != neqB ? 1 : 0); + int neqA = read(this.TOP - 1); + int neqB = read(this.TOP); + write(this.TOP - 1, neqA != neqB ? 1 : 0); this.TOP -= 1; this.PC += 1; break; case Instruction.IFZERO: // Pg. 13 - if (this.stack.get(this.TOP) == 0) { + if (read(this.TOP) == 0) { this.PC = arg1; } else { this.PC += 1; @@ -155,11 +154,11 @@ public class AbstractMachine { break; case Instruction.INVOKE: // Pg. 23 - this.stack.set(this.TOP + 1, this.PC + 1); - this.stack.set(this.TOP + 2, this.PP); - this.stack.set(this.TOP + 3, this.FP); - this.stack.set(this.TOP + 4, spp(arg3, this.PP, this.FP)); - this.stack.set(this.TOP + 5, sfp(arg3, this.PP, this.FP)); + write(this.TOP + 1, this.PC + 1); + write(this.TOP + 2, this.PP); + write(this.TOP + 3, this.FP); + write(this.TOP + 4, spp(arg3, this.PP, this.FP)); + write(this.TOP + 5, sfp(arg3, this.PP, this.FP)); this.PP = this.TOP - arg1 + 1; this.FP = this.TOP + 1; this.TOP += 5; @@ -167,12 +166,12 @@ public class AbstractMachine { break; case Instruction.RETURN: // Pg. 24 - int res = this.stack.get(this.TOP); + int res = read(this.TOP); this.TOP = this.PP; - this.PC = this.stack.get(this.FP); - this.PP = this.stack.get(this.FP + 1); - this.FP = this.stack.get(this.FP + 2); - this.stack.set(this.TOP, res); + this.PC = read(this.FP); + this.PP = read(this.FP + 1); + this.FP = read(this.FP + 2); + write(this.TOP, res); break; case Instruction.POP: // Not in docs, see MaMa @@ -211,23 +210,6 @@ public class AbstractMachine { return sfp(d-1, this.stack.get(fp+3), this.stack.get(fp+4)); } - // Called before each instruction - protected void ensureCapacity(int currSize) { - int size = stack.size(); - - // Always ensure a minimum working capacity of 16 - if (size < 16) { - for (int i = size; i < 16; i++) stack.add(0); - size = 16; - } - - // Double list capacity when fewer than 8 free slots remain - if (currSize >= size - 8) { - int newSize = size * 2; - for (int i = size; i < newSize; i++) stack.add(0); - } - } - // Returns the machine's current configuration as string public String confStr() { StringBuilder sb = new StringBuilder(); @@ -266,4 +248,13 @@ public class AbstractMachine { } return result; } + + protected void write(int index, int value) { + while (stack.size() <= index) stack.add(0); + stack.set(index, value); + } + + protected int read(int index) { + return stack.get(index); + } } diff --git a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachineTests.java b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachineTests.java index 8747397..4650aaa 100644 --- a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachineTests.java +++ b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachineTests.java @@ -2,8 +2,6 @@ package de.unitrier.st.uap.w25.tram; import org.junit.jupiter.api.Test; -import java.util.ArrayList; - import static org.junit.jupiter.api.Assertions.*; public class AbstractMachineTests { @@ -75,29 +73,7 @@ public class AbstractMachineTests { } @Test - void testGGTx48y18() { - Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); - AbstractMachine tram = new AbstractMachine(code, new Integer[]{48, 18}); - tram.execute(); - - assertTrue(tram.isHalted(), "Machine should halt."); - int result = tram.result(); - assertEquals(6, result, "Expected ggt(48,18) = 6."); - } - - @Test - void testGGTx270y192() { - Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); - AbstractMachine tram = new AbstractMachine(code, new Integer[]{270, 192}); - tram.execute(); - - assertTrue(tram.isHalted(), "Machine should halt."); - int result = tram.result(); - assertEquals(6, result, "Expected ggt(270,192) = 6."); - } - - @Test - void testModPositive() { + void testMODx5y2() { Instruction[] code = Assembler.readTRAMCode("tramcode/mod.tram"); AbstractMachine tram = new AbstractMachine(code, new Integer[]{17, 5}); tram.execute(); @@ -108,7 +84,7 @@ public class AbstractMachineTests { } @Test - void testModExactDivision() { + void testMODx20y5() { Instruction[] code = Assembler.readTRAMCode("tramcode/mod.tram"); AbstractMachine tram = new AbstractMachine(code, new Integer[]{20, 5}); tram.execute(); @@ -119,7 +95,7 @@ public class AbstractMachineTests { } @Test - void testModSmallerDividend() { + void testMODx3y10() { Instruction[] code = Assembler.readTRAMCode("tramcode/mod.tram"); AbstractMachine tram = new AbstractMachine(code, new Integer[]{3, 10}); tram.execute(); @@ -129,6 +105,16 @@ public class AbstractMachineTests { assertEquals(3, result, "Expected 3 mod 10 = 3."); } + @Test + void testMODx37y16() { + Instruction[] code = Assembler.readTRAMCode("tramcode/mod.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{37,16}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(5, result, "Expected 37 mod 16 = 5."); + } @Test void testGGTx17y5() { @@ -163,4 +149,80 @@ public class AbstractMachineTests { assertEquals(25, result, "Expected ggt(0,25) = 25."); } + @Test + void testGGTx270y192() { + Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{270, 192}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(6, result, "Expected ggt(270,192) = 6."); + } + + @Test + void testGGTx48y18() { + Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{48, 18}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(6, result, "Expected ggt(48,18) = 6."); + } + + @Test + void testGGTx3y9() { + Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{3,9}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(3, result, "Expected ggt(48,18) = 6."); + } + + @Test + void testGGTx9y3() { + Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{9,3}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(3, result, "Expected ggt(48,18) = 6."); + } + + @Test + void testGGTx24y4() { + Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{24,4}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(4, result, "Expected ggt(48,18) = 6."); + } + + @Test + void testGGTx16y37() { + Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{16,37}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(1, result, "Expected ggt(16,37) = 1."); + } + + @Test + void testGGTx37y16() { + Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{37,16}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(1, result, "Expected ggt(37,16) = 1."); + } } diff --git a/Project-01/uap25-pro01-tram/tramcode/ggt.tram b/Project-01/uap25-pro01-tram/tramcode/ggt.tram index 95e6d95..f157eac 100644 --- a/Project-01/uap25-pro01-tram/tramcode/ggt.tram +++ b/Project-01/uap25-pro01-tram/tramcode/ggt.tram @@ -1,22 +1,26 @@ // Quellkode: ggt(a,b) { if (b==0) then a else ggt(b, a mod b) } // Annahmen: Die Argumente a und b werden durch Kellerzellen 0 und 1 repräsentiert, // sowie PP=0, FP=0 und TOP=-1 -INVOKE 2 LGGT 0 -POP +INVOKE 2 GGT 0 HALT -LGGT: -// b +GGT: LOAD 1 0 +IFZERO RET LOAD 1 0 -// if b != 0 -> 1 -IFZERO 1 -// return a -LOAD 0 0 -RETURN -L1: -LOAD 1 0 // b LOAD 0 0 LOAD 1 0 -MOD // a mod b -INVOKE 2 LGGT 0 // ggt(b, a mod b) +INVOKE 2 MOD 1 +INVOKE 2 GGT 0 RETURN + +RET: LOAD 0 0 +RETURN + +MOD: LOAD 0 0 +LOAD 1 0 +LOAD 0 0 +LOAD 1 0 +DIV +MUL +SUB +RETURN \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/tramcode/mod.tram b/Project-01/uap25-pro01-tram/tramcode/mod.tram index 1dbf814..7ec4c8b 100644 --- a/Project-01/uap25-pro01-tram/tramcode/mod.tram +++ b/Project-01/uap25-pro01-tram/tramcode/mod.tram @@ -3,10 +3,11 @@ INVOKE 2 MOD 0 HALT -MOD: LOAD 1 0 +MOD: LOAD 0 0 +LOAD 1 0 +LOAD 0 0 LOAD 1 0 DIV -LOAD 2 0 MUL SUB RETURN