initial push

main
simonkellet 1 year ago
parent fbd8c5bab0
commit 3655a949f3
  1. 21
      LICENSE
  2. 3
      Triangle.AbstractMachine.Disassembler/.gitignore
  3. 23
      Triangle.AbstractMachine.Disassembler/.project
  4. 12
      Triangle.AbstractMachine.Disassembler/build.gradle
  5. 18
      Triangle.AbstractMachine.Disassembler/pom.xml
  6. 351
      Triangle.AbstractMachine.Disassembler/src/main/java/triangle/abstractMachine/Disassembler.java
  7. 3
      Triangle.AbstractMachine.Interpreter/.gitignore
  8. 23
      Triangle.AbstractMachine.Interpreter/.project
  9. 12
      Triangle.AbstractMachine.Interpreter/build.gradle
  10. 18
      Triangle.AbstractMachine.Interpreter/pom.xml
  11. 645
      Triangle.AbstractMachine.Interpreter/src/main/java/triangle/abstractMachine/Interpreter.java
  12. 3
      Triangle.AbstractMachine/.gitignore
  13. 23
      Triangle.AbstractMachine/.project
  14. 4
      Triangle.AbstractMachine/build.gradle
  15. 12
      Triangle.AbstractMachine/pom.xml
  16. 67
      Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Instruction.java
  17. 54
      Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Machine.java
  18. 5
      Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/OpCode.java
  19. 6
      Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Primitive.java
  20. 5
      Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Register.java
  21. 4
      Triangle.Compiler/.gitignore
  22. 23
      Triangle.Compiler/.project
  23. 21
      Triangle.Compiler/build.gradle
  24. 18
      Triangle.Compiler/pom.xml
  25. 152
      Triangle.Compiler/src/main/java/triangle/Compiler.java
  26. 61
      Triangle.Compiler/src/main/java/triangle/ErrorReporter.java
  27. 46
      Triangle.Compiler/src/main/java/triangle/StdEnvironment.java
  28. 34
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/AbstractSyntaxTree.java
  29. 37
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/Program.java
  30. 32
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameter.java
  31. 32
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameterSequence.java
  32. 33
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ConstActualParameter.java
  33. 29
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/EmptyActualParameterSequence.java
  34. 33
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/FuncActualParameter.java
  35. 35
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/MultipleActualParameterSequence.java
  36. 33
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ProcActualParameter.java
  37. 32
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/SingleActualParameterSequence.java
  38. 33
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/VarActualParameter.java
  39. 35
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/ArrayAggregate.java
  40. 35
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleArrayAggregate.java
  41. 38
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleRecordAggregate.java
  42. 36
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/RecordAggregate.java
  43. 33
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleArrayAggregate.java
  44. 36
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleRecordAggregate.java
  45. 36
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/AssignCommand.java
  46. 36
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/CallCommand.java
  47. 32
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/Command.java
  48. 29
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/EmptyCommand.java
  49. 36
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/IfCommand.java
  50. 35
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/LetCommand.java
  51. 33
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/SequentialCommand.java
  52. 35
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/WhileCommand.java
  53. 39
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/BinaryOperatorDeclaration.java
  54. 42
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstDeclaration.java
  55. 9
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstantDeclaration.java
  56. 35
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/Declaration.java
  57. 53
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FuncDeclaration.java
  58. 12
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FunctionDeclaration.java
  59. 44
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcDeclaration.java
  60. 9
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcedureDeclaration.java
  61. 33
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/SequentialDeclaration.java
  62. 37
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/UnaryOperatorDeclaration.java
  63. 41
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VarDeclaration.java
  64. 9
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VariableDeclaration.java
  65. 33
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/ArrayExpression.java
  66. 37
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/BinaryExpression.java
  67. 36
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CallExpression.java
  68. 43
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CharacterExpression.java
  69. 29
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/EmptyExpression.java
  70. 44
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/Expression.java
  71. 36
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IfExpression.java
  72. 43
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IntegerExpression.java
  73. 35
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/LetExpression.java
  74. 33
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/RecordExpression.java
  75. 35
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/UnaryExpression.java
  76. 33
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/VnameExpression.java
  77. 51
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ConstFormalParameter.java
  78. 34
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/EmptyFormalParameterSequence.java
  79. 35
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameter.java
  80. 35
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameterSequence.java
  81. 59
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FuncFormalParameter.java
  82. 45
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/MultipleFormalParameterSequence.java
  83. 51
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ProcFormalParameter.java
  84. 42
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/SingleFormalParameterSequence.java
  85. 51
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/VarFormalParameter.java
  86. 37
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/CharacterLiteral.java
  87. 40
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Identifier.java
  88. 37
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/IntegerLiteral.java
  89. 37
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Operator.java
  90. 28
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Terminal.java
  91. 39
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/AnyTypeDenoter.java
  92. 52
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ArrayTypeDenoter.java
  93. 44
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/BoolTypeDenoter.java
  94. 44
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/CharTypeDenoter.java
  95. 39
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ErrorTypeDenoter.java
  96. 24
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/FieldTypeDenoter.java
  97. 44
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/IntTypeDenoter.java
  98. 53
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/MultipleFieldTypeDenoter.java
  99. 48
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/RecordTypeDenoter.java
  100. 43
      Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SimpleTypeDenoter.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 deryckb
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,3 @@
/target/
/.classpath
/build/

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Triangle.AbstractMachine.Disassembler</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

@ -0,0 +1,12 @@
apply plugin: 'java'
apply plugin: 'application'
sourceCompatibility = 11
dependencies {
implementation project(':Triangle.AbstractMachine')
}
application {
mainClass = 'Triangle.AbstractMachine.Disassembler'
}

@ -0,0 +1,18 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>triangle-disassembler</artifactId>
<parent>
<groupId>triangle.tools</groupId>
<artifactId>triangle-tools</artifactId>
<version>2.1</version>
<relativePath>../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>triangle.tools</groupId>
<artifactId>triangle-abstractmachine</artifactId>
<version>2.1</version>
</dependency>
</dependencies>
</project>

@ -0,0 +1,351 @@
/*
* @(#)Disassembler.java 2.1 2003/10/07
*
* Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
* Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
* and School of Computer and Math Sciences, The Robert Gordon University,
* St. Andrew Street, Aberdeen AB25 1HG, Scotland.
* All rights reserved.
*
* This software is provided free for educational use only. It may
* not be used for commercial purposes without the prior written permission
* of the authors.
*/
package triangle.abstractMachine;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* Disassembles the TAM code in the given file, and displays the instructions on
* standard output.
*
* For example:
*
* <pre>
* java TAM.Disassembler obj.tam
* </pre>
*
* <p>
* Copyright 1991 David A. Watt, University of Glasgow<br>
* Copyright 1998 Deryck F. Brown, The Robert Gordon University<br>
* </p>
*
*/
public class Disassembler {
static String objectName;
static int CT;
/**
* Writes the r-field of an instruction in the form "l<I>reg</I>r", where l and
* r are the bracket characters to use.
*
* @param leftbracket the character to print before the register.
* @param r the number of the register.
* @param rightbracket the character to print after the register.
*/
private static void writeR(char leftbracket, Register r, char rightbracket) {
System.out.print(leftbracket);
System.out.print(r.toString());
System.out.print(rightbracket);
}
private static void writeR(char leftBracket, int r, char rightBracket) {
var register = Register.values()[r];
writeR(leftBracket, register, rightBracket);
}
/**
* Writes a void n-field of an instruction.
*/
private static void blankN() {
System.out.print(" ");
}
// Writes the n-field of an instruction.
/**
* Writes the n-field of an instruction in the form "(n)".
*
* @param n the integer to write.
*/
private static void writeN(int n) {
System.out.print("(" + n + ") ");
if (n < 10) {
System.out.print(" ");
} else if (n < 100) {
System.out.print(" ");
}
}
/**
* Writes the d-field of an instruction.
*
* @param d the integer to write.
*/
private static void writeD(int d) {
System.out.print(d);
}
/**
* Writes the name of primitive routine with relative address d.
*
* @param d the displacement of the primitive routine.
*/
private static void writePrimitive(int d) {
var primitive = Primitive.values()[d];
switch (primitive) {
case ID:
System.out.print("id ");
break;
case NOT:
System.out.print("not ");
break;
case AND:
System.out.print("and ");
break;
case OR:
System.out.print("or ");
break;
case SUCC:
System.out.print("succ ");
break;
case PRED:
System.out.print("pred ");
break;
case NEG:
System.out.print("neg ");
break;
case ADD:
System.out.print("add ");
break;
case SUB:
System.out.print("sub ");
break;
case MULT:
System.out.print("mult ");
break;
case DIV:
System.out.print("div ");
break;
case MOD:
System.out.print("mod ");
break;
case LT:
System.out.print("lt ");
break;
case LE:
System.out.print("le ");
break;
case GE:
System.out.print("ge ");
break;
case GT:
System.out.print("gt ");
break;
case EQ:
System.out.print("eq ");
break;
case NE:
System.out.print("ne ");
break;
case EOL:
System.out.print("eol ");
break;
case EOF:
System.out.print("eof ");
break;
case GET:
System.out.print("get ");
break;
case PUT:
System.out.print("put ");
break;
case GETEOL:
System.out.print("geteol ");
break;
case PUTEOL:
System.out.print("puteol ");
break;
case GETINT:
System.out.print("getint ");
break;
case PUTINT:
System.out.print("putint ");
break;
case NEW:
System.out.print("new ");
break;
case DISPOSE:
System.out.print("dispose ");
break;
}
}
/**
* Writes the given instruction in assembly-code format.
*
* @param instr the instruction to display.
*/
private static void writeInstruction(Instruction instr) {
switch (instr.opCode) {
case LOAD:
System.out.print("LOAD ");
writeN(instr.length);
writeD(instr.operand);
writeR('[', instr.register, ']');
break;
case LOADA:
System.out.print("LOADA ");
blankN();
writeD(instr.operand);
writeR('[', instr.register, ']');
break;
case LOADI:
System.out.print("LOADI ");
writeN(instr.length);
break;
case LOADL:
System.out.print("LOADL ");
blankN();
writeD(instr.operand);
break;
case STORE:
System.out.print("STORE ");
writeN(instr.length);
writeD(instr.operand);
writeR('[', instr.register, ']');
break;
case STOREI:
System.out.print("STOREI");
writeN(instr.length);
break;
case CALL:
System.out.print("CALL ");
if (instr.register == Register.PB) {
blankN();
writePrimitive(instr.operand);
} else {
writeR('(', instr.length, ')');
System.out.print(" ");
writeD(instr.operand);
writeR('[', instr.register, ']');
}
break;
case CALLI:
System.out.print("CALLI ");
break;
case RETURN:
System.out.print("RETURN");
writeN(instr.length);
writeD(instr.operand);
break;
case PUSH:
System.out.print("PUSH ");
blankN();
writeD(instr.operand);
break;
case POP:
System.out.print("POP ");
writeN(instr.length);
writeD(instr.operand);
break;
case JUMP:
System.out.print("JUMP ");
blankN();
writeD(instr.operand);
writeR('[', instr.register, ']');
break;
case JUMPI:
System.out.print("JUMPI ");
break;
case JUMPIF:
System.out.print("JUMPIF");
writeN(instr.length);
writeD(instr.operand);
writeR('[', instr.register, ']');
break;
case HALT:
System.out.print("HALT ");
}
}
/**
* Writes all instructions of the program in code store.
*/
private static void disassembleProgram() {
for (int addr = Machine.CB; addr < CT; addr++) {
System.out.print(addr + ": ");
writeInstruction(Machine.code[addr]);
System.out.println();
}
}
// LOADING
/**
* Loads the TAM object program into code store from the named file.
*
* @param objectName the name of the file containing the program.
*/
static void loadObjectProgram(String objectName) {
var finished = false;
try (var objectFile = new FileInputStream(objectName)) {
var objectStream = new DataInputStream(objectFile);
var addr = Machine.CB;
while (!finished) {
Machine.code[addr] = Instruction.read(objectStream);
if (Machine.code[addr] == null) {
finished = true;
} else {
addr = addr + 1;
}
}
CT = addr;
} catch (FileNotFoundException s) {
CT = Machine.CB;
System.err.println("Error opening object file: " + s);
} catch (IOException s) {
CT = Machine.CB;
System.err.println("Error reading object file: " + s);
}
}
// DISASSEMBLE
public static void main(String[] args) {
System.out.println("********** TAM Disassembler (Sun Version 2.1) **********");
if (args.length == 1) {
objectName = args[0];
} else {
objectName = "obj.tam";
}
loadObjectProgram(objectName);
disassembleProgram();
}
}

@ -0,0 +1,3 @@
/target/
/.classpath
/build/

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Triangle.AbstractMachine.Interpreter</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

@ -0,0 +1,12 @@
apply plugin: 'java'
apply plugin: 'application'
sourceCompatibility = 11
dependencies {
implementation project(':Triangle.AbstractMachine')
}
application {
mainClass = 'Triangle.AbstractMachine.Interpreter'
}

@ -0,0 +1,18 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>triangle-interpreter</artifactId>
<parent>
<groupId>triangle.tools</groupId>
<artifactId>triangle-tools</artifactId>
<version>2.1</version>
<relativePath>../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>triangle.tools</groupId>
<artifactId>triangle-abstractmachine</artifactId>
<version>2.1</version>
</dependency>
</dependencies>
</project>

@ -0,0 +1,645 @@
/*
* @(#)Interpreter.java 2.1 2003/10/07
*
* Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
* Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
* and School of Computer and Math Sciences, The Robert Gordon University,
* St. Andrew Street, Aberdeen AB25 1HG, Scotland.
* All rights reserved.
*
* This software is provided free for educational use only. It may
* not be used for commercial purposes without the prior written permission
* of the authors.
*/
package triangle.abstractMachine;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Interpreter {
static long startTimeNanos = 0;
static String objectName;
// DATA STORE
static int[] data = new int[1024];
// DATA STORE REGISTERS AND OTHER REGISTERS
final static int CB = 0, SB = 0, HB = 1024; // = upper bound of data array + 1
static int CT, CP, ST, HT, LB, status;
// status values
final static int running = 0, halted = 1, failedDataStoreFull = 2, failedInvalidCodeAddress = 3,
failedInvalidInstruction = 4, failedOverflow = 5, failedZeroDivide = 6, failedIOError = 7;
static long accumulator;
static int content(int r) {
var register = Register.values()[r];
return content(register);
}
static int content(Register r) {
// Returns the current content of register r,
// even if r is one of the pseudo-registers L1..L6.
switch (r) {
case CB:
return CB;
case CT:
return CT;
case PB:
return Machine.PB;
case PT:
return Machine.PT;
case SB:
return SB;
case ST:
return ST;
case HB:
return HB;
case HT:
return HT;
case LB:
return LB;
case L1:
return data[LB];
case L2:
return data[data[LB]];
case L3:
return data[data[data[LB]]];
case L4:
return data[data[data[data[LB]]]];
case L5:
return data[data[data[data[data[LB]]]]];
case L6:
return data[data[data[data[data[data[LB]]]]]];
case CP:
return CP;
default:
return 0;
}
}
// PROGRAM STATUS
static void dump() {
// Writes a summary of the machine state.
System.out.println("");
System.out.println("State of data store and registers:");
System.out.println("");
if (HT == HB) {
System.out.println(" |--------| (heap is empty)");
} else {
System.out.println(" HB-->");
System.out.println(" |--------|");
for (var addr = HB - 1; addr >= HT; addr--) {
System.out.print(addr + ":");
if (addr == HT) {
System.out.print(" HT-->");
} else {
System.out.print(" ");
}
System.out.println("|" + data[addr] + "|");
}
System.out.println(" |--------|");
}
System.out.println(" |////////|");
System.out.println(" |////////|");
if (ST == SB) {
System.out.println(" |--------| (stack is empty)");
} else {
var dynamicLink = LB;
var staticLink = LB;
var localRegNum = Register.LB;
System.out.println(" ST--> |////////|");
System.out.println(" |--------|");
for (var addr = ST - 1; addr >= SB; addr--) {
System.out.print(addr + ":");
if (addr == SB) {
System.out.print(" SB-->");
} else if (addr == staticLink) {
switch (localRegNum) {
case LB:
System.out.print(" LB-->");
break;
case L1:
System.out.print(" L1-->");
break;
case L2:
System.out.print(" L2-->");
break;
case L3:
System.out.print(" L3-->");
break;
case L4:
System.out.print(" L4-->");
break;
case L5:
System.out.print(" L5-->");
break;
case L6:
System.out.print(" L6-->");
break;
default:
break;
}
staticLink = data[addr];
localRegNum = Register.values()[localRegNum.ordinal() + 1];
} else {
System.out.print(" ");
}
if (addr == dynamicLink && dynamicLink != SB) {
System.out.print("|SL=" + data[addr] + "|");
} else if (addr == dynamicLink + 1 && dynamicLink != SB) {
System.out.print("|DL=" + data[addr] + "|");
} else if (addr == dynamicLink + 2 && dynamicLink != SB) {
System.out.print("|RA=" + data[addr] + "|");
} else {
System.out.print("|" + data[addr] + "|");
}
System.out.println("");
if (addr == dynamicLink) {
System.out.println(" |--------|");
dynamicLink = data[addr + 1];
}
}
}
System.out.println("");
}
static void showStatus() {
// Writes an indication of whether and why the program has terminated.
System.out.println("");
switch (status) {
case running:
System.out.println("Program is running.");
break;
case halted:
System.out.println("Program has halted normally.");
System.out.println("Total execution time (ns): " + (System.nanoTime() - startTimeNanos));
break;
case failedDataStoreFull:
System.out.println("Program has failed due to exhaustion of Data Store.");
break;
case failedInvalidCodeAddress:
System.out.println("Program has failed due to an invalid code address.");
break;
case failedInvalidInstruction:
System.out.println("Program has failed due to an invalid instruction.");
break;
case failedOverflow:
System.out.println("Program has failed due to overflow.");
break;
case failedZeroDivide:
System.out.println("Program has failed due to division by zero.");
break;
case failedIOError:
System.out.println("Program has failed due to an IO error.");
break;
}
if (status != halted) {
dump();
}
}
// INTERPRETATION
static void checkSpace(int spaceNeeded) {
// Signals failure if there is not enough space to expand the stack or
// heap by spaceNeeded.
if (HT - ST < spaceNeeded) {
status = failedDataStoreFull;
}
}
static boolean isTrue(int datum) {
// Tests whether the given datum represents true.
return (datum == Machine.trueRep);
}
static boolean equal(int size, int addr1, int addr2) {
// Tests whether two multi-word objects are equal, given their common
// size and their base addresses.
boolean eq;
int index;
eq = true;
index = 0;
while (eq && (index < size)) {
if (data[addr1 + index] == data[addr2 + index]) {
index = index + 1;
} else {
eq = false;
}
}
return eq;
}
static int overflowChecked(long datum) {
// Signals failure if the datum is too large to fit into a single word,
// otherwise returns the datum as a single word.
if ((-Machine.maxintRep <= datum) && (datum <= Machine.maxintRep)) {
return (int) datum;
} else {
status = failedOverflow;
return 0;
}
}
static int toInt(boolean b) {
return b ? Machine.trueRep : Machine.falseRep;
}
static int currentChar;
static int readInt() throws java.io.IOException {
int temp = 0;
int sign = 1;
do {
currentChar = System.in.read();
} while (Character.isWhitespace((char) currentChar));
if ((currentChar == '-') || (currentChar == '+')) {
do {
sign = (currentChar == '-') ? -1 : 1;
currentChar = System.in.read();
} while ((currentChar == '-') || currentChar == '+');
}
if (Character.isDigit((char) currentChar)) {
do {
temp = temp * 10 + (currentChar - '0');
currentChar = System.in.read();
} while (Character.isDigit((char) currentChar));
}
return sign * temp;
}
static void callPrimitive(int primitiveDisplacement) {
// Invokes the given primitive routine.
int addr, size;
char ch;
var primitive = Primitive.values()[primitiveDisplacement];
switch (primitive) {
case ID:
break; // nothing to be done
case NOT:
data[ST - 1] = toInt(!isTrue(data[ST - 1]));
break;
case AND:
ST = ST - 1;
data[ST - 1] = toInt(isTrue(data[ST - 1]) & isTrue(data[ST]));
break;
case OR:
ST = ST - 1;
data[ST - 1] = toInt(isTrue(data[ST - 1]) | isTrue(data[ST]));
break;
case SUCC:
data[ST - 1] = overflowChecked(data[ST - 1] + 1);
break;
case PRED:
data[ST - 1] = overflowChecked(data[ST - 1] - 1);
break;
case NEG:
data[ST - 1] = -data[ST - 1];
break;
case ADD:
ST = ST - 1;
accumulator = data[ST - 1];
data[ST - 1] = overflowChecked(accumulator + data[ST]);
break;
case SUB:
ST = ST - 1;
accumulator = data[ST - 1];
data[ST - 1] = overflowChecked(accumulator - data[ST]);
break;
case MULT:
ST = ST - 1;
accumulator = data[ST - 1];
data[ST - 1] = overflowChecked(accumulator * data[ST]);
break;
case DIV:
ST = ST - 1;
accumulator = data[ST - 1];
if (data[ST] != 0) {
data[ST - 1] = (int) (accumulator / data[ST]);
} else {
status = failedZeroDivide;
}
break;
case MOD:
ST = ST - 1;
accumulator = data[ST - 1];
if (data[ST] != 0) {
data[ST - 1] = (int) (accumulator % data[ST]);
} else {
status = failedZeroDivide;
}
break;
case LT:
ST = ST - 1;
data[ST - 1] = toInt(data[ST - 1] < data[ST]);
break;
case LE:
ST = ST - 1;
data[ST - 1] = toInt(data[ST - 1] <= data[ST]);
break;
case GE:
ST = ST - 1;
data[ST - 1] = toInt(data[ST - 1] >= data[ST]);
break;
case GT:
ST = ST - 1;
data[ST - 1] = toInt(data[ST - 1] > data[ST]);
break;
case EQ:
size = data[ST - 1]; // size of each comparand
ST = ST - 2 * size;
data[ST - 1] = toInt(equal(size, ST - 1, ST - 1 + size));
break;
case NE:
size = data[ST - 1]; // size of each comparand
ST = ST - 2 * size;
data[ST - 1] = toInt(!equal(size, ST - 1, ST - 1 + size));
break;
case EOL:
data[ST] = toInt(currentChar == '\n');
ST = ST + 1;
break;
case EOF:
data[ST] = toInt(currentChar == -1);
ST = ST + 1;
break;
case GET:
ST = ST - 1;
addr = data[ST];
try {
currentChar = System.in.read();
} catch (java.io.IOException s) {
status = failedIOError;
}
data[addr] = currentChar;
break;
case PUT:
ST = ST - 1;
ch = (char) data[ST];
System.out.print(ch);
break;
case GETEOL:
try {
while ((currentChar = System.in.read()) != '\n')
;
} catch (java.io.IOException s) {
status = failedIOError;
}
break;
case PUTEOL:
System.out.println("");
break;
case GETINT:
ST = ST - 1;
addr = data[ST];
try {
accumulator = readInt();
} catch (java.io.IOException s) {
status = failedIOError;
}
data[addr] = (int) accumulator;
break;
case PUTINT:
ST = ST - 1;
accumulator = data[ST];
System.out.print(accumulator);
break;
case NEW:
size = data[ST - 1];
checkSpace(size);
HT = HT - size;
data[ST - 1] = HT;
break;
case DISPOSE:
ST = ST - 1; // no action taken at present
break;
}
}
static void interpretProgram() {
// Runs the program in code store.
Instruction currentInstr;
// Initialize registers ...
ST = SB;
HT = HB;
LB = SB;
CP = CB;
status = running;
do {
// Fetch instruction ...
currentInstr = Machine.code[CP];
// Decode instruction ...
var op = currentInstr.opCode;
var r = currentInstr.register;
var n = currentInstr.length;
var d = currentInstr.operand;
int addr;
// Execute instruction ...
switch (op) {
case LOAD:
addr = d + content(r);
checkSpace(n);
for (var index = 0; index < n; index++) {
data[ST + index] = data[addr + index];
}
ST = ST + n;
CP = CP + 1;
break;
case LOADA:
addr = d + content(r);
checkSpace(1);
data[ST] = addr;
ST = ST + 1;
CP = CP + 1;
break;
case LOADI:
ST = ST - 1;
addr = data[ST];
checkSpace(n);
for (var index = 0; index < n; index++) {
data[ST + index] = data[addr + index];
}
ST = ST + n;
CP = CP + 1;
break;
case LOADL:
checkSpace(1);
data[ST] = d;
ST = ST + 1;
CP = CP + 1;
break;
case STORE:
addr = d + content(r);
ST = ST - n;
for (var index = 0; index < n; index++) {
data[addr + index] = data[ST + index];
}
CP = CP + 1;
break;
case STOREI:
ST = ST - 1;
addr = data[ST];
ST = ST - n;
for (var index = 0; index < n; index++) {
data[addr + index] = data[ST + index];
}
CP = CP + 1;
break;
case CALL:
addr = d + content(r);
if (addr >= Machine.PB) {
callPrimitive(addr - Machine.PB);
CP = CP + 1;
} else {
checkSpace(3);
if (0 <= n && n <= 15) {
data[ST] = content(n); // static link
} else {
status = failedInvalidInstruction;
}
data[ST + 1] = LB; // dynamic link
data[ST + 2] = CP + 1; // return address
LB = ST;
ST = ST + 3;
CP = addr;
}
break;
case CALLI:
ST = ST - 2;
addr = data[ST + 1];
if (addr >= Machine.PB) {
callPrimitive(addr - Machine.PB);
CP = CP + 1;
} else {
// data[ST] = static link already
data[ST + 1] = LB; // dynamic link
data[ST + 2] = CP + 1; // return address
LB = ST;
ST = ST + 3;
CP = addr;
}
break;
case RETURN:
addr = LB - d;
CP = data[LB + 2];
LB = data[LB + 1];
ST = ST - n;
for (var index = 0; index < n; index++) {
data[addr + index] = data[ST + index];
}
ST = addr + n;
break;
case PUSH:
checkSpace(d);
ST = ST + d;
CP = CP + 1;
break;
case POP:
addr = ST - n - d;
ST = ST - n;
for (var index = 0; index < n; index++) {
data[addr + index] = data[ST + index];
}
ST = addr + n;
CP = CP + 1;
break;
case JUMP:
CP = d + content(r);
break;
case JUMPI:
ST = ST - 1;
CP = data[ST];
break;
case JUMPIF:
ST = ST - 1;
if (data[ST] == n) {
CP = d + content(r);
} else {
CP = CP + 1;
}
break;
case HALT:
status = halted;
break;
}
if (CP < CB || CP >= CT) {
status = failedInvalidCodeAddress;
}
} while (status == running);
}
// LOADING
static void loadObjectProgram(String objectName) {
// Loads the TAM object program into code store from the named file.
boolean finished = false;
try (var objectFile = new FileInputStream(objectName)) {
var objectStream = new DataInputStream(objectFile);
var addr = Machine.CB;
while (!finished) {
Machine.code[addr] = Instruction.read(objectStream);
if (Machine.code[addr] == null) {
finished = true;
} else {
addr = addr + 1;
}
}
CT = addr;
} catch (FileNotFoundException s) {
CT = CB;
System.err.println("Error opening object file: " + s);
} catch (IOException s) {
CT = CB;
System.err.println("Error reading object file: " + s);
}
}
// RUNNING
public static void main(String[] args) {
System.out.println("********** TAM Interpreter (Java Version 2.1) **********");
if (args.length == 1) {
objectName = args[0];
} else {
objectName = "obj.tam";
}
loadObjectProgram(objectName);
if (CT != CB) {
startTimeNanos = System.nanoTime();
interpretProgram();
showStatus();
}
}
}

@ -0,0 +1,3 @@
/target/
/.classpath
/build/

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Triangle.AbstractMachine</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

@ -0,0 +1,4 @@
apply plugin: 'java-library'
apply plugin: 'eclipse'
sourceCompatibility = 11

@ -0,0 +1,12 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>triangle-abstractmachine</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>triangle.tools</groupId>
<artifactId>triangle-tools</artifactId>
<version>2.1</version>
<relativePath>../</relativePath>
</parent>
</project>

@ -0,0 +1,67 @@
/*
* @(#)Instruction.java 2.1 2003/10/07
*
* Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
* Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
* and School of Computer and Math Sciences, The Robert Gordon University,
* St. Andrew Street, Aberdeen AB25 1HG, Scotland.
* All rights reserved.
*
* This software is provided free for educational use only. It may
* not be used for commercial purposes without the prior written permission
* of the authors.
*/
package triangle.abstractMachine;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
public class Instruction {
// Java has no type synonyms, so the following representations are
// assumed:
//
// type
// OpCode = 0..15; {4 bits unsigned}
// Length = 0..255; {8 bits unsigned}
// Operand = -32767..+32767; {16 bits signed}
// Represents TAM instructions.
final OpCode opCode;
final Register register;
final int length;
int operand; // Not final to allow for patching jump address
public Instruction(OpCode opcode, Register register, int length, int operand) {
this.opCode = opcode;
this.register = register;
this.length = length;
this.operand = operand;
}
public void setOperand(int operand) {
this.operand = operand;
}
public void write(DataOutputStream output) throws IOException {
output.writeInt(opCode.ordinal());
output.writeInt(register.ordinal());
output.writeInt(length);
output.writeInt(operand);
}
public static Instruction read(DataInputStream input) throws IOException {
try {
var opCode = OpCode.values()[input.readInt()];
var register = Register.values()[input.readInt()];
var length = input.readInt();
var operand = input.readInt();
return new Instruction(opCode, register, length, operand);
} catch (EOFException s) {
return null;
}
}
}

@ -0,0 +1,54 @@
/*
* @(#)Machine.java 2.1 2003/10/07
*
* Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
* Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
* and School of Computer and Math Sciences, The Robert Gordon University,
* St. Andrew Street, Aberdeen AB25 1HG, Scotland.
* All rights reserved.
*
* This software is provided free for educational use only. It may
* not be used for commercial purposes without the prior written permission
* of the authors.
*/
package triangle.abstractMachine;
public final class Machine {
public final static int maxRoutineLevel = 7;
// WORDS AND ADDRESSES
// Java has no type synonyms, so the following representations are
// assumed:
//
// type
// Word = -32767..+32767; {16 bits signed}
// DoubleWord = -2147483648..+2147483647; {32 bits signed}
// CodeAddress = 0..+32767; {15 bits unsigned}
// DataAddress = 0..+32767; {15 bits unsigned}
// INSTRUCTIONS
// CODE STORE
public static Instruction[] code = new Instruction[1024];
// CODE STORE REGISTERS
public final static int CB = 0, PB = 1024, // = upper bound of code array + 1
PT = 1052; // = PB + 28
// REGISTER NUMBERS
// DATA REPRESENTATION
public final static int booleanSize = 1, characterSize = 1, integerSize = 1, addressSize = 1,
closureSize = 2 * addressSize,
linkDataSize = 3 * addressSize,
falseRep = 0, trueRep = 1, maxintRep = 32767;
}

@ -0,0 +1,5 @@
package triangle.abstractMachine;
public enum OpCode {
LOAD, LOADA, LOADI, LOADL, STORE, STOREI, CALL, CALLI, RETURN, NOP, PUSH, POP, JUMP, JUMPI, JUMPIF, HALT
}

@ -0,0 +1,6 @@
package triangle.abstractMachine;
public enum Primitive {
ID, NOT, AND, OR, SUCC, PRED, NEG, ADD, SUB, MULT, DIV, MOD, LT, LE, GE, GT, EQ, NE, EOL, EOF, GET, PUT, GETEOL,
PUTEOL, GETINT, PUTINT, NEW, DISPOSE
}

@ -0,0 +1,5 @@
package triangle.abstractMachine;
public enum Register {
CB, CT, PB, PT, SB, ST, HB, HT, LB, L1, L2, L3, L4, L5, L6, CP
}