Test conf
This commit is contained in:
15
Project-01/uap25-pro01-tram/README.md
Normal file
15
Project-01/uap25-pro01-tram/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
**Author: Jan-Niclas Loosen (1540907)**
|
||||
|
||||
|
||||
The jar ``jar/tram.jar`` contains all required dependencies.
|
||||
|
||||
```bash
|
||||
java -jar tram.jar <tramFile> [options]
|
||||
```
|
||||
**Optional arguments:**
|
||||
|
||||
`--debug`: Enables debug logging to the console.
|
||||
|
||||
`--debug <logFile>`: Enables debug logging and writes output to the specified file.
|
||||
|
||||
`--stack [v1,v2,...]`: Initializes the stack with the given integers (for example `[4,10]`).
|
||||
39
Project-01/uap25-pro01-tram/build.sh
Normal file
39
Project-01/uap25-pro01-tram/build.sh
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
OUT=jar
|
||||
MAIN_CLASS=de.unitrier.st.uap.w25.tram.Main
|
||||
JAR_NAME=tram.jar
|
||||
LIB=lib
|
||||
TMP=$OUT/tmp
|
||||
|
||||
# Clean and prepare
|
||||
rm -rf "$OUT"
|
||||
mkdir -p "$TMP"
|
||||
|
||||
# 1. Compile sources
|
||||
if [ -d "$LIB" ]; then
|
||||
javac -d "$TMP" -cp "$LIB/*" $(find src -name "*.java")
|
||||
else
|
||||
javac -d "$TMP" $(find src -name "*.java")
|
||||
fi
|
||||
|
||||
# 2. Unpack dependency jars
|
||||
if [ -d "$LIB" ]; then
|
||||
for jar in "$LIB"/*.jar; do
|
||||
[ -f "$jar" ] && jar xf "$jar" -C "$TMP"
|
||||
done
|
||||
fi
|
||||
|
||||
# 3. Create manifest
|
||||
echo "Main-Class: $MAIN_CLASS" > "$TMP/MANIFEST.MF"
|
||||
|
||||
# 4. Package into single jar
|
||||
jar cfm "$OUT/$JAR_NAME" "$TMP/MANIFEST.MF" -C "$TMP" .
|
||||
|
||||
# 5. Clean temporary files
|
||||
rm -rf "$TMP"
|
||||
|
||||
echo "Built: $OUT/$JAR_NAME"
|
||||
echo "Run with:"
|
||||
echo " java -jar $OUT/$JAR_NAME"
|
||||
BIN
Project-01/uap25-pro01-tram/jar/tram.jar
Normal file
BIN
Project-01/uap25-pro01-tram/jar/tram.jar
Normal file
Binary file not shown.
@@ -26,7 +26,7 @@ public class AbstractMachine {
|
||||
|
||||
// Executes until halts and returns final configuration
|
||||
public void execute() {
|
||||
while(!isHalted()) {
|
||||
while (!isHalted()) {
|
||||
executeStep();
|
||||
}
|
||||
confStr();
|
||||
@@ -34,152 +34,160 @@ public class AbstractMachine {
|
||||
|
||||
// Executes single step and returns configuration
|
||||
public void executeStep() {
|
||||
ensureCapacity(this.TOP);
|
||||
Instruction inst = this.prog.get(this.PC);
|
||||
try {
|
||||
ensureCapacity(this.TOP);
|
||||
Instruction inst = this.prog.get(this.PC);
|
||||
|
||||
int arg1 = inst.getArg1() != null ? inst.getArg1() : 0;
|
||||
int arg2 = inst.getArg2() != null ? inst.getArg2() : 0;
|
||||
int arg3 = inst.getArg3() != null ? inst.getArg3() : 0;
|
||||
int arg1 = inst.getArg1() != null ? inst.getArg1() : 0;
|
||||
int arg2 = inst.getArg2() != null ? inst.getArg2() : 0;
|
||||
int arg3 = inst.getArg3() != null ? inst.getArg3() : 0;
|
||||
|
||||
switch (inst.getOpcode()) {
|
||||
case Instruction.CONST:
|
||||
// Pg. 9
|
||||
this.stack.set(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));
|
||||
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));
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
if (divB == 0) {
|
||||
throw new ArithmeticException("Division by zero");
|
||||
}
|
||||
|
||||
this.stack.set(this.TOP - 1, 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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
this.TOP -= 1;
|
||||
this.PC += 1;
|
||||
break;
|
||||
case Instruction.IFZERO:
|
||||
// Pg. 13
|
||||
if (this.stack.get(this.TOP) == 0) {
|
||||
this.PC = arg1;
|
||||
}
|
||||
else {
|
||||
switch (inst.getOpcode()) {
|
||||
case Instruction.CONST:
|
||||
// Pg. 9
|
||||
this.stack.set(this.TOP + 1, arg1);
|
||||
this.TOP += 1;
|
||||
this.PC += 1;
|
||||
}
|
||||
this.TOP -= 1;
|
||||
break;
|
||||
case Instruction.GOTO:
|
||||
// Pg. 13
|
||||
this.PC = arg1;
|
||||
break;
|
||||
case Instruction.HALT:
|
||||
// Pg. 13
|
||||
this.PC = -1;
|
||||
break;
|
||||
case Instruction.NOP:
|
||||
// Pg. 13
|
||||
this.PC += 1;
|
||||
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));
|
||||
this.PP = this.TOP - arg1 + 1;
|
||||
this.FP = this.TOP + 1;
|
||||
this.TOP += 5;
|
||||
this.PC = arg2;
|
||||
break;
|
||||
case Instruction.RETURN:
|
||||
// Pg. 24
|
||||
int res = this.stack.get(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);
|
||||
break;
|
||||
case Instruction.POP:
|
||||
// Not in docs, see MaMa
|
||||
this.TOP -= 1;
|
||||
this.PC += 1;
|
||||
break;
|
||||
default: break;
|
||||
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));
|
||||
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));
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
if (divB == 0) {
|
||||
throw new ArithmeticException("Division by zero");
|
||||
}
|
||||
|
||||
this.stack.set(this.TOP - 1, 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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
this.TOP -= 1;
|
||||
this.PC += 1;
|
||||
break;
|
||||
case Instruction.IFZERO:
|
||||
// Pg. 13
|
||||
if (this.stack.get(this.TOP) == 0) {
|
||||
this.PC = arg1;
|
||||
} else {
|
||||
this.PC += 1;
|
||||
}
|
||||
this.TOP -= 1;
|
||||
break;
|
||||
case Instruction.GOTO:
|
||||
// Pg. 13
|
||||
this.PC = arg1;
|
||||
break;
|
||||
case Instruction.HALT:
|
||||
// Pg. 13
|
||||
this.PC = -1;
|
||||
break;
|
||||
case Instruction.NOP:
|
||||
// Pg. 13
|
||||
this.PC += 1;
|
||||
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));
|
||||
this.PP = this.TOP - arg1 + 1;
|
||||
this.FP = this.TOP + 1;
|
||||
this.TOP += 5;
|
||||
this.PC = arg2;
|
||||
break;
|
||||
case Instruction.RETURN:
|
||||
// Pg. 24
|
||||
int res = this.stack.get(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);
|
||||
break;
|
||||
case Instruction.POP:
|
||||
// Not in docs, see MaMa
|
||||
this.TOP -= 1;
|
||||
this.PC += 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
String line = this.prog.get(this.PC).toString();
|
||||
String msg = e.getMessage();
|
||||
msg = String.format("Error at PC=%d (%s): %s%nCurrent stack=%s", this.PC, line, msg, stackStr());
|
||||
throw new RuntimeException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,14 +215,13 @@ public class AbstractMachine {
|
||||
protected void ensureCapacity(int currSize) {
|
||||
int size = stack.size();
|
||||
|
||||
// Initialize stack with default capacity of 16
|
||||
if (size == 0) {
|
||||
for (int i = 0; i < 16; i++) stack.add(0);
|
||||
return;
|
||||
// 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
|
||||
// (largest instruction, INVOKE, needs 5 additional cells)
|
||||
if (currSize >= size - 8) {
|
||||
int newSize = size * 2;
|
||||
for (int i = size; i < newSize; i++) stack.add(0);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
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 {
|
||||
@@ -66,8 +69,98 @@ public class AbstractMachineTests {
|
||||
AbstractMachine tram = new AbstractMachine(code, new Integer[]{}); // empty stack
|
||||
tram.execute();
|
||||
|
||||
assertTrue(tram.isHalted(), "Machine should halt after executing wrapper(4,10).");
|
||||
assertTrue(tram.isHalted(), "Machine should halt.");
|
||||
int result = tram.result();
|
||||
assertEquals(4, result, "Expected result of wrapper(4,10) = 4.");
|
||||
}
|
||||
|
||||
@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() {
|
||||
Instruction[] code = Assembler.readTRAMCode("tramcode/mod.tram");
|
||||
AbstractMachine tram = new AbstractMachine(code, new Integer[]{17, 5});
|
||||
tram.execute();
|
||||
|
||||
assertTrue(tram.isHalted(), "Machine should halt.");
|
||||
int result = tram.result();
|
||||
assertEquals(2, result, "Expected 17 mod 5 = 2.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testModExactDivision() {
|
||||
Instruction[] code = Assembler.readTRAMCode("tramcode/mod.tram");
|
||||
AbstractMachine tram = new AbstractMachine(code, new Integer[]{20, 5});
|
||||
tram.execute();
|
||||
|
||||
assertTrue(tram.isHalted(), "Machine should halt.");
|
||||
int result = tram.result();
|
||||
assertEquals(0, result, "Expected 20 mod 5 = 0.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testModSmallerDividend() {
|
||||
Instruction[] code = Assembler.readTRAMCode("tramcode/mod.tram");
|
||||
AbstractMachine tram = new AbstractMachine(code, new Integer[]{3, 10});
|
||||
tram.execute();
|
||||
|
||||
assertTrue(tram.isHalted(), "Machine should halt.");
|
||||
int result = tram.result();
|
||||
assertEquals(3, result, "Expected 3 mod 10 = 3.");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testGGTx17y5() {
|
||||
Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram");
|
||||
AbstractMachine tram = new AbstractMachine(code, new Integer[]{17, 5});
|
||||
tram.execute();
|
||||
|
||||
assertTrue(tram.isHalted(), "Machine should halt.");
|
||||
int result = tram.result();
|
||||
assertEquals(1, result, "Expected ggt(17,5) = 1.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGGTx25y0() {
|
||||
Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram");
|
||||
AbstractMachine tram = new AbstractMachine(code, new Integer[]{25, 0});
|
||||
tram.execute();
|
||||
|
||||
assertTrue(tram.isHalted(), "Machine should halt.");
|
||||
int result = tram.result();
|
||||
assertEquals(25, result, "Expected ggt(25,0) = 25.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGGTx0y25() {
|
||||
Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram");
|
||||
AbstractMachine tram = new AbstractMachine(code, new Integer[]{0, 25});
|
||||
tram.execute();
|
||||
|
||||
assertTrue(tram.isHalted(), "Machine should halt.");
|
||||
int result = tram.result();
|
||||
assertEquals(25, result, "Expected ggt(0,25) = 25.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,53 +2,19 @@ package de.unitrier.st.uap.w25.tram;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.core.LoggerContext;
|
||||
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
|
||||
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
|
||||
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
|
||||
import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
|
||||
|
||||
// Write subclass to enhance Single-Responsibility-Principle
|
||||
public class LoggedMachine extends AbstractMachine {
|
||||
protected static Logger logger = LogManager.getLogger(LoggedMachine.class);
|
||||
protected int stepCounter = 0;
|
||||
private static final Logger logger = LogManager.getLogger(LoggedMachine.class);
|
||||
private int stepCounter = 0;
|
||||
|
||||
// No changes in the constructor
|
||||
public LoggedMachine(Instruction[] prog) {
|
||||
super(prog);
|
||||
}
|
||||
|
||||
// No changes in the constructor
|
||||
public LoggedMachine(Instruction[] prog, Integer[] stack) {
|
||||
super(prog, stack);
|
||||
}
|
||||
|
||||
// Enable file logging
|
||||
public static void toFile(String fileName) {
|
||||
ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
|
||||
|
||||
AppenderComponentBuilder fileAppender = builder.newAppender("File", "File")
|
||||
.addAttribute("fileName", fileName)
|
||||
.add(builder.newLayout("PatternLayout")
|
||||
.addAttribute("pattern", "%d{HH:mm:ss} %-5level %msg%n"));
|
||||
|
||||
builder.add(fileAppender);
|
||||
builder.add(builder.newRootLogger(Level.DEBUG).add(builder.newAppenderRef("File")));
|
||||
|
||||
LoggerContext ctx = LoggerContext.getContext(false);
|
||||
ctx.start(builder.build());
|
||||
|
||||
logger = LogManager.getLogger(LoggedMachine.class);
|
||||
}
|
||||
public LoggedMachine(Instruction[] prog) { super(prog); }
|
||||
public LoggedMachine(Instruction[] prog, Integer[] stack) { super(prog, stack); }
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
logger.info("Executing...");
|
||||
logger.debug("{}: {}", 0, confStr());
|
||||
while(!isHalted()) {
|
||||
executeStep();
|
||||
}
|
||||
logger.debug("0: {}", confStr());
|
||||
while (!isHalted()) executeStep();
|
||||
logger.info("Finished with STACK: {}", stackStr());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@ package de.unitrier.st.uap.w25.tram;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.core.config.Configurator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@@ -12,27 +10,21 @@ import java.util.List;
|
||||
public final class Main {
|
||||
private Main() {}
|
||||
|
||||
public static void main(String[] argv) {
|
||||
static void main(String[] argv) {
|
||||
if (argv.length < 1) {
|
||||
System.err.println("Usage:");
|
||||
System.err.println(" java -jar tram.jar <tramFile> [--debug [logFile]] [--stack [v1,v2,...]]");
|
||||
System.err.println(" java -jar tram.jar <tramFile> [--debug] [--stack [v1,v2,...]]");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
String tramPath = argv[0];
|
||||
boolean debug = false;
|
||||
String logFile = null;
|
||||
String stackArg = null;
|
||||
|
||||
// Parse arguments
|
||||
for (int i = 1; i < argv.length; i++) {
|
||||
switch (argv[i]) {
|
||||
case "--debug" -> {
|
||||
debug = true;
|
||||
if (i + 1 < argv.length && !argv[i + 1].startsWith("--")) {
|
||||
logFile = argv[++i];
|
||||
}
|
||||
}
|
||||
case "--debug" -> debug = true;
|
||||
case "--stack" -> {
|
||||
if (i + 1 < argv.length) {
|
||||
stackArg = argv[++i];
|
||||
@@ -55,24 +47,9 @@ public final class Main {
|
||||
System.exit(4);
|
||||
}
|
||||
|
||||
// Configure logging
|
||||
// Configure console logging only
|
||||
if (debug) {
|
||||
Configurator.setRootLevel(Level.DEBUG);
|
||||
if (logFile != null) {
|
||||
Path logPath = Path.of(logFile);
|
||||
try {
|
||||
Files.createDirectories(logPath.getParent() != null ? logPath.getParent() : Path.of("."));
|
||||
if (!Files.exists(logPath)) Files.createFile(logPath);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error: cannot create log file -> " + logPath);
|
||||
e.printStackTrace();
|
||||
System.exit(5);
|
||||
}
|
||||
LoggedMachine.toFile(logPath.toString());
|
||||
System.out.println("Debug logging to file: " + logPath);
|
||||
} else {
|
||||
System.out.println("Debug logging to console.");
|
||||
}
|
||||
} else {
|
||||
Configurator.setRootLevel(Level.INFO);
|
||||
}
|
||||
@@ -88,20 +65,13 @@ public final class Main {
|
||||
System.out.println("Execution complete.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a stack argument given in Python list notation, e.g. "[1,2,3]"
|
||||
*/
|
||||
// Parse "[1,2,3]" or "1,2,3"
|
||||
private static Integer[] parseStack(String stackArg) {
|
||||
if (stackArg == null || stackArg.isBlank()) {
|
||||
return new Integer[] {};
|
||||
}
|
||||
if (stackArg == null || stackArg.isBlank()) return new Integer[]{};
|
||||
String trimmed = stackArg.trim();
|
||||
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
||||
if (trimmed.startsWith("[") && trimmed.endsWith("]"))
|
||||
trimmed = trimmed.substring(1, trimmed.length() - 1);
|
||||
}
|
||||
if (trimmed.isBlank()) {
|
||||
return new Integer[] {};
|
||||
}
|
||||
if (trimmed.isBlank()) return new Integer[]{};
|
||||
|
||||
String[] parts = trimmed.split(",");
|
||||
List<Integer> list = new ArrayList<>();
|
||||
@@ -115,4 +85,4 @@ public final class Main {
|
||||
}
|
||||
return list.toArray(new Integer[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
Project-01/uap25-pro01-tram/tramcode/ggt.tram
Normal file
22
Project-01/uap25-pro01-tram/tramcode/ggt.tram
Normal file
@@ -0,0 +1,22 @@
|
||||
// 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
|
||||
HALT
|
||||
|
||||
LGGT:
|
||||
// b
|
||||
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)
|
||||
RETURN
|
||||
12
Project-01/uap25-pro01-tram/tramcode/mod.tram
Normal file
12
Project-01/uap25-pro01-tram/tramcode/mod.tram
Normal file
@@ -0,0 +1,12 @@
|
||||
# Quellkode: let mod(a,b) { a - (a / b) * b } in mod(14,5)
|
||||
# Annahmen: a→stack[0], b→stack[1], PP=0, FP=0, TOP=-1
|
||||
INVOKE 2 MOD 0
|
||||
HALT
|
||||
|
||||
MOD: LOAD 1 0
|
||||
LOAD 1 0
|
||||
DIV
|
||||
LOAD 2 0
|
||||
MUL
|
||||
SUB
|
||||
RETURN
|
||||
Reference in New Issue
Block a user