Finish logged machine

This commit is contained in:
Jan-Niclas Loosen
2025-10-25 18:44:02 +02:00
parent 59b6371966
commit a22a2f3ea6
6 changed files with 102 additions and 83 deletions

View File

@@ -1,6 +1,4 @@
package de.unitrier.st.uap.w25.tram;
import java.nio.file.attribute.UserPrincipalLookupService;
import java.util.*;
public class AbstractMachine {
@@ -12,11 +10,13 @@ public class AbstractMachine {
protected int PC = 0;
protected int TOP = -1;
// Init machine with program and empty stack
public AbstractMachine(Instruction[] prog) {
this.prog = new ArrayList<>(Arrays.asList(prog));
this.stack = new ArrayList<>();
}
// Init machine with program and stack
public AbstractMachine(Instruction[] prog, Integer[] stack) {
this(prog);
@@ -25,25 +25,15 @@ public class AbstractMachine {
}
// Executes until halts and returns final configuration
public String execute() {
public void execute() {
while(!isHalted()) {
executeStep();
}
return configuration();
}
// Executes until halts and returns configurations of all steps
public ArrayList<String> executeDebug() {
ArrayList<String> out = new ArrayList<>();
while(!isHalted()) {
String conf = executeStep();
out.add(conf);
}
return out;
confStr();
}
// Executes single step and returns configuration
public String executeStep() {
public void executeStep() {
ensureCapacity(this.TOP);
Instruction inst = this.prog.get(this.PC);
@@ -191,8 +181,6 @@ public class AbstractMachine {
break;
default: break;
}
return configuration();
}
public boolean isHalted() {
@@ -233,23 +221,30 @@ public class AbstractMachine {
}
}
// Prints the machine's current configuration
public String configuration() {
// Returns the machine's current configuration as string
public String confStr() {
StringBuilder sb = new StringBuilder();
sb.append("TOP=").append(this.TOP)
.append(" PC=").append(this.PC)
.append(" PP=").append(this.PP)
.append(" FP=").append(this.FP)
.append("\nSTACK: [");
.append(" PC=").append(this.PC)
.append(" PP=").append(this.PP)
.append(" FP=").append(this.FP)
.append("\nSTACK: ")
.append(stackStr());
return sb.toString();
}
// Returns the machine's current stack as string
public String stackStr() {
StringBuilder sb = new StringBuilder();
sb.append("[");
int limit = Math.min(this.stack.size(), this.TOP + 1);
for (int i = 0; i < limit; i++) {
sb.append(this.stack.get(i));
if (i < limit - 1) sb.append(", ");
}
sb.append("]");
return sb.toString();
}

View File

@@ -4,7 +4,6 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class AbstractMachineTests {
@Test
void testExample1() {
Instruction[] code = Assembler.readTRAMCode("tramcode/example1.tram");
@@ -25,7 +24,7 @@ public class AbstractMachineTests {
assertTrue(tram.isHalted(), "Machine should halt.");
var results = tram.results();
assertEquals(200, results.get(results.size() - 2), "Expected value 200 since x!=0.");
assertEquals(3, results.get(results.size() - 1), "Expected final constant 3 on stack.");
assertEquals(3, results.getLast(), "Expected final constant 3 on stack.");
}
@Test

View File

@@ -1,7 +1,3 @@
/**
* Instructions for TRAM 2025
*/
package de.unitrier.st.uap.w25.tram;
public class Instruction

View File

@@ -2,42 +2,60 @@ 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 {
private static final Logger logger = LogManager.getLogger(LoggedMachine.class);
protected static Logger logger = LogManager.getLogger(LoggedMachine.class);
protected 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);
}
@Override
public String executeStep() {
String confBefore = configuration();
logger.debug("Before step:\n" + confBefore);
// Enable file logging
public static void toFile(String fileName) {
ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
String confAfter = super.executeStep();
logger.debug("After step:\n" + confAfter);
AppenderComponentBuilder fileAppender = builder.newAppender("File", "File")
.addAttribute("fileName", fileName)
.add(builder.newLayout("PatternLayout")
.addAttribute("pattern", "%d{HH:mm:ss} %-5level %msg%n"));
return confAfter;
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);
}
@Override
public String execute() {
logger.info("Execution started");
String result = super.execute();
logger.info("Execution finished:\n" + configuration());
return result;
public void execute() {
logger.info("Executing...");
logger.debug("{}: {}", 0, confStr());
while(!isHalted()) {
executeStep();
}
logger.info("Finished with STACK: {}", stackStr());
}
@Override
public java.util.ArrayList<String> executeDebug() {
logger.info("Debug execution started");
var out = super.executeDebug();
logger.info("Debug execution finished");
return out;
public void executeStep() {
int step = stepCounter++;
super.executeStep();
logger.debug("{}: {}", step, confStr());
}
}

View File

@@ -1,40 +1,33 @@
package de.unitrier.st.uap.w25.tram;
final class Main
{
private Main(){}
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
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"
);
final class Main {
private Main() {}
int lineNr=0;
for(Instruction instr: code) {
if (instr != null) {
System.out.println(String.format("%03d", lineNr) + "| " + instr.toString());
lineNr++;
}
}
static void main(String[] argv) {
// Configurator.setRootLevel(Level.DEBUG);
Configurator.setRootLevel(Level.INFO);
// TODO: Create an instance of the abstract machine with reasonable parameters
AbstractMachine tram = new AbstractMachine(code, new Integer[]{}); // empty stack or predefined args
Instruction[] code = Assembler.readTRAMCode(
//"tramcode/square.tram"
//"tramcode/wrapper.tram"
//"tramcode/example1.tram"
//"tramcode/example2.tram"
//"tramcode/example3.tram"
"tramcode/test.tram"
);
System.out.println("Initial configuration:");
System.out.println(tram.configuration());
// int lineNr = 0;
// for (Instruction instr : code) {
// if (instr != null) {
// System.out.println(String.format("%03d", lineNr) + "| " + instr);
// lineNr++;
// }
// }
// Stepwise execution (debug)
System.out.println("\nExecution trace:");
for (String conf : tram.executeDebug()) {
System.out.println(conf);
}
System.out.println("\nFinal configuration:");
System.out.println(tram.configuration());
}
LoggedMachine tram = new LoggedMachine(code, new Integer[]{}); // empty stack or predefined args
tram.execute();
}
}

View File

@@ -10,8 +10,8 @@
<orderEntry type="module-library">
<library name="JUnit4">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.13.1/junit-4.13.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar!/" />
<root url="jar://$MODULE_DIR$/lib/junit-4.13.1.jar!/" />
<root url="jar://$MODULE_DIR$/lib/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
@@ -33,5 +33,23 @@
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/log4j-core-2.24.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/log4j-api-2.24.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>