Start with project

This commit is contained in:
Jan-Niclas Loosen
2025-10-23 13:45:02 +02:00
parent 5e616dd0a2
commit b0974af092
21 changed files with 658 additions and 84 deletions

2
.gitignore vendored
View File

@@ -174,3 +174,5 @@ cython_debug/
# PyPI configuration file
.pypirc
# IDE
.idea

8
.idea/.gitignore generated vendored
View File

@@ -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

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.13 (Construction-of-Compilers)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@@ -1,8 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="project">
<words>
<w>btns</w>
<w>ldsp</w>
</words>
</dictionary>
</component>

View File

@@ -1,30 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPep8Inspection" enabled="true" level="INFORMATION" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="E302" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="N802" />
<option value="N806" />
<option value="N803" />
<option value="N801" />
<option value="N812" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="int.*" />
</list>
</option>
</inspection_tool>
</profile>
</component>

View File

@@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml generated
View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.13 (python_clients)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (Construction-of-Compilers)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Construction-of-Compilers.iml" filepath="$PROJECT_DIR$/.idea/Construction-of-Compilers.iml" />
</modules>
</component>
</project>

7
.idea/vcs.xml generated
View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -0,0 +1,5 @@
# Java build dir
out
# IDEA
.idea

View File

@@ -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<Integer> stack;
protected List<Instruction> 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 "";
}
}

View File

@@ -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<Instruction> code = new LinkedList<Instruction>();
LinkedList<String> lines = new LinkedList<String>();
HashMap<String,Integer> labelmap = new HashMap<String,Integer>();
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<String, Integer> 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<String, Integer> labelmap) {
if (index>parts.length-1) return 0;
String arg=parts[index];
try { return Integer.valueOf(arg); }
catch (NumberFormatException e) {
return labelmap.get(arg);
}
}
}

View File

@@ -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)
};
}

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>