From 72f3b2b497184895e593d5a1c19056f9727dfc20 Mon Sep 17 00:00:00 2001 From: Joshua Potter Date: Tue, 15 Dec 2015 07:40:18 -0500 Subject: [PATCH] format --- src/mJAM/Assembler.java | 2 +- src/mJAM/Disassembler.java | 504 +++--- src/mJAM/Instruction.java | 48 +- src/mJAM/Interpreter.java | 1592 ++++++++--------- src/mJAM/Machine.java | 385 ++-- src/mJAM/ObjectFile.java | 112 +- src/mJAM/Test.java | 277 ++- src/miniJava/AbstractSyntaxTrees/AST.java | 24 +- .../AbstractSyntaxTrees/ASTDisplay.java | 586 +++--- .../AbstractSyntaxTrees/ArrayType.java | 24 +- .../AbstractSyntaxTrees/AssignStmt.java | 20 +- .../AbstractSyntaxTrees/BaseType.java | 20 +- .../AbstractSyntaxTrees/BinaryExpr.java | 25 +- .../AbstractSyntaxTrees/BlockStmt.java | 16 +- .../AbstractSyntaxTrees/BooleanLiteral.java | 12 +- .../AbstractSyntaxTrees/CallExpr.java | 20 +- .../AbstractSyntaxTrees/CallStmt.java | 20 +- .../AbstractSyntaxTrees/ClassDecl.java | 21 +- .../AbstractSyntaxTrees/ClassDeclList.java | 32 +- .../AbstractSyntaxTrees/ClassType.java | 24 +- .../AbstractSyntaxTrees/Declaration.java | 18 +- .../AbstractSyntaxTrees/Declarators.java | 21 +- .../AbstractSyntaxTrees/ExprList.java | 32 +- .../AbstractSyntaxTrees/Expression.java | 6 +- .../AbstractSyntaxTrees/FieldDecl.java | 25 +- .../AbstractSyntaxTrees/FieldDeclList.java | 32 +- src/miniJava/AbstractSyntaxTrees/IdRef.java | 16 +- .../AbstractSyntaxTrees/Identifier.java | 16 +- src/miniJava/AbstractSyntaxTrees/IfStmt.java | 36 +- .../AbstractSyntaxTrees/IndexedRef.java | 20 +- .../AbstractSyntaxTrees/IntLiteral.java | 12 +- src/miniJava/AbstractSyntaxTrees/Literal.java | 6 +- .../AbstractSyntaxTrees/LiteralExpr.java | 16 +- .../AbstractSyntaxTrees/LocalDecl.java | 6 +- .../AbstractSyntaxTrees/MemberDecl.java | 25 +- .../AbstractSyntaxTrees/MethodDecl.java | 25 +- .../AbstractSyntaxTrees/MethodDeclList.java | 32 +- .../AbstractSyntaxTrees/NewArrayExpr.java | 20 +- src/miniJava/AbstractSyntaxTrees/NewExpr.java | 6 +- .../AbstractSyntaxTrees/NewObjectExpr.java | 16 +- .../AbstractSyntaxTrees/Operator.java | 14 +- src/miniJava/AbstractSyntaxTrees/Package.java | 16 +- .../AbstractSyntaxTrees/ParameterDecl.java | 12 +- .../ParameterDeclList.java | 32 +- .../AbstractSyntaxTrees/QualifiedRef.java | 22 +- src/miniJava/AbstractSyntaxTrees/RefExpr.java | 16 +- .../AbstractSyntaxTrees/Reference.java | 12 +- .../AbstractSyntaxTrees/Statement.java | 6 +- .../AbstractSyntaxTrees/StatementList.java | 32 +- .../AbstractSyntaxTrees/Terminal.java | 10 +- src/miniJava/AbstractSyntaxTrees/ThisRef.java | 14 +- src/miniJava/AbstractSyntaxTrees/Type.java | 10 +- .../AbstractSyntaxTrees/TypeKind.java | 2 +- .../AbstractSyntaxTrees/UnaryExpr.java | 20 +- src/miniJava/AbstractSyntaxTrees/VarDecl.java | 12 +- .../AbstractSyntaxTrees/VarDeclStmt.java | 20 +- src/miniJava/AbstractSyntaxTrees/Visitor.java | 74 +- .../AbstractSyntaxTrees/WhileStmt.java | 20 +- src/miniJava/CodeGenerator/Code.java | 93 +- src/miniJava/CodeGenerator/Encoder.java | 1341 +++++++------- src/miniJava/CodeGenerator/RuntimeEntity.java | 24 +- src/miniJava/Compiler.java | 94 +- src/miniJava/ContextualAnalyzer/Analyzer.java | 1474 ++++++++------- src/miniJava/ContextualAnalyzer/IdTable.java | 220 +-- src/miniJava/ContextualAnalyzer/Reporter.java | 41 +- src/miniJava/SyntacticAnalyzer/Parser.java | 1444 ++++++++------- .../SyntacticAnalyzer/ParsingException.java | 10 +- src/miniJava/SyntacticAnalyzer/Scanner.java | 577 +++--- .../SyntacticAnalyzer/ScanningException.java | 10 +- .../SyntacticAnalyzer/SourcePosition.java | 20 +- src/miniJava/SyntacticAnalyzer/Token.java | 133 +- src/tester/Checkpoint1.java | 109 +- src/tester/Checkpoint2.java | 160 +- src/tester/Checkpoint3.java | 110 +- src/tester/Checkpoint4.java | 188 +- 75 files changed, 5203 insertions(+), 5339 deletions(-) diff --git a/src/mJAM/Assembler.java b/src/mJAM/Assembler.java index 6546944..e22326a 100644 --- a/src/mJAM/Assembler.java +++ b/src/mJAM/Assembler.java @@ -1,5 +1,5 @@ package mJAM; public class Assembler { - // TBD + // TBD } diff --git a/src/mJAM/Disassembler.java b/src/mJAM/Disassembler.java index 7d9b452..63647f8 100644 --- a/src/mJAM/Disassembler.java +++ b/src/mJAM/Disassembler.java @@ -13,297 +13,307 @@ import java.util.SortedSet; import java.util.TreeSet; /** - * Disassemble the mJAM object code - * from input file xxx.mJAM - * into output file xxx.asm + * Disassemble the mJAM object code from input file xxx.mJAM into output file + * xxx.asm * * @author prins * @version COMP 520 v2.2 */ public class Disassembler { - private String objectFileName; - private String asmName; - private FileWriter asmOut; - private boolean error = false; - private Map addrToLabel; + private String objectFileName; + private String asmName; + private FileWriter asmOut; + private boolean error = false; + private Map addrToLabel; - public Disassembler(String objectFileName) { - this.objectFileName = objectFileName; - } + public Disassembler(String objectFileName) { + this.objectFileName = objectFileName; + } - /** - * Writes the r-field of an instruction in the form "lregr", 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 void writeR(char leftbracket, int r, char rightbracket) { - asmWrite(Character.toString(leftbracket)); - asmWrite(Machine.intToReg[r].toString()); - asmWrite(Character.toString(rightbracket)); - } + /** + * Writes the r-field of an instruction in the form "lregr", 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 void writeR(char leftbracket, int r, char rightbracket) { + asmWrite(Character.toString(leftbracket)); + asmWrite(Machine.intToReg[r].toString()); + asmWrite(Character.toString(rightbracket)); + } - /** - * Writes a void n-field of an instruction. - */ - private void blankN() { - asmWrite(" "); - } + /** + * Writes a void n-field of an instruction. + */ + private void blankN() { + asmWrite(" "); + } - // 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 void writeN(int n) { - asmWrite(String.format("%-6s","(" + n + ")")); - } + // 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 void writeN(int n) { + asmWrite(String.format("%-6s", "(" + n + ")")); + } - /** - * Writes the d-field of an instruction. - * @param d the integer to write. - */ - private void writeD(int d) { - asmWrite(Integer.toString(d)); - } + /** + * Writes the d-field of an instruction. + * + * @param d + * the integer to write. + */ + private void writeD(int d) { + asmWrite(Integer.toString(d)); + } - /** - * Writes the name of primitive routine with relative address d. - * @param d the displacment of the primitive routine. - */ - private void writePrimitive(int d) { - Machine.Prim prim = Machine.intToPrim[d]; - asmWrite(String.format("%-8s",prim.toString())); - } - - /** - * Writes the given instruction in assembly-code format. - * @param instr the instruction to display. - */ - private void writeInstruction(Instruction instr) { + /** + * Writes the name of primitive routine with relative address d. + * + * @param d + * the displacment of the primitive routine. + */ + private void writePrimitive(int d) { + Machine.Prim prim = Machine.intToPrim[d]; + asmWrite(String.format("%-8s", prim.toString())); + } - String targetLabel = "***"; - // get label of destination addr, if instr transfers control - if (instr.r == Machine.Reg.CB.ordinal()) - targetLabel = addrToLabel.get(instr.d); + /** + * Writes the given instruction in assembly-code format. + * + * @param instr + * the instruction to display. + */ + private void writeInstruction(Instruction instr) { - Machine.Op instruction = Machine.intToOp[instr.op]; - asmWrite(String.format("%-7s",instruction.toString())); - switch (instruction) { - case LOAD: - blankN(); - writeD(instr.d); - writeR('[', instr.r, ']'); - break; + String targetLabel = "***"; + // get label of destination addr, if instr transfers control + if (instr.r == Machine.Reg.CB.ordinal()) + targetLabel = addrToLabel.get(instr.d); - case LOADA: - blankN(); - writeD(instr.d); - writeR('[', instr.r, ']'); - break; + Machine.Op instruction = Machine.intToOp[instr.op]; + asmWrite(String.format("%-7s", instruction.toString())); + switch (instruction) { + case LOAD: + blankN(); + writeD(instr.d); + writeR('[', instr.r, ']'); + break; - case LOADI: - break; + case LOADA: + blankN(); + writeD(instr.d); + writeR('[', instr.r, ']'); + break; - case LOADL: - blankN(); - writeD(instr.d); - break; + case LOADI: + break; - case STORE: - blankN(); - writeD(instr.d); - writeR('[', instr.r, ']'); - break; + case LOADL: + blankN(); + writeD(instr.d); + break; - case STOREI: - break; + case STORE: + blankN(); + writeD(instr.d); + writeR('[', instr.r, ']'); + break; - case CALL: - if (instr.r == Machine.Reg.PB.ordinal()) { - blankN(); - writePrimitive(instr.d); - } else { - blankN(); - asmWrite(targetLabel); - } - break; + case STOREI: + break; - case CALLI: - blankN(); - asmWrite(targetLabel); - break; + case CALL: + if (instr.r == Machine.Reg.PB.ordinal()) { + blankN(); + writePrimitive(instr.d); + } else { + blankN(); + asmWrite(targetLabel); + } + break; - case RETURN: - writeN(instr.n); - writeD(instr.d); - break; + case CALLI: + blankN(); + asmWrite(targetLabel); + break; - case CALLD: - blankN(); - writeD(instr.d); - break; + case RETURN: + writeN(instr.n); + writeD(instr.d); + break; - case PUSH: - blankN(); - writeD(instr.d); - break; + case CALLD: + blankN(); + writeD(instr.d); + break; - case POP: - blankN(); - writeD(instr.d); - break; + case PUSH: + blankN(); + writeD(instr.d); + break; - case JUMP: - blankN(); - asmWrite(targetLabel); - break; + case POP: + blankN(); + writeD(instr.d); + break; - case JUMPI: - break; + case JUMP: + blankN(); + asmWrite(targetLabel); + break; - case JUMPIF: - writeN(instr.n); - asmWrite(targetLabel); - break; + case JUMPI: + break; - case HALT: - writeN(instr.n); - break; + case JUMPIF: + writeN(instr.n); + asmWrite(targetLabel); + break; - default: - asmWrite("???? "); - writeN(instr.n); - writeD(instr.d); - writeR('[', instr.r, ']'); - break; - } - } + case HALT: + writeN(instr.n); + break; - /** - * disassembles program held in code store - */ - void disassembleProgram(String asmFileName) { + default: + asmWrite("???? "); + writeN(instr.n); + writeD(instr.d); + writeR('[', instr.r, ']'); + break; + } + } - try { - asmOut = new FileWriter(asmFileName); - } catch (IOException e) { - System.out.println("Disassembler: can not create asm output file " - + asmName); - error = true; - return; - } + /** + * disassembles program held in code store + */ + void disassembleProgram(String asmFileName) { - // collect all addresses that may be the target of a jump instruction - SortedSet targets = new TreeSet(); - for (int addr = Machine.CB; addr < Machine.CT; addr++) { - Instruction inst = Machine.code[addr]; - Machine.Op op = Machine.intToOp[inst.op]; - switch (op) { - case CALL: - case CALLI: - // only consider calls (branches) within code memory (i.e. not primitives) - if (inst.r == Machine.Reg.CB.ordinal()) - targets.add(inst.d); - break; - case JUMP: - // address following an unconditional branch is an implicit target - targets.add(addr+1); - targets.add(inst.d); - break; - case JUMPIF: - // a jump of any sort creates a branch target - targets.add(inst.d); - break; - default: - break; - } - } + try { + asmOut = new FileWriter(asmFileName); + } catch (IOException e) { + System.out.println("Disassembler: can not create asm output file " + asmName); + error = true; + return; + } - // map branch target addresses to unique labels - addrToLabel = new HashMap(); - int labelCounter = 10; - for (Integer addr : targets) { - String label = "L" + labelCounter++ ; - addrToLabel.put(addr, label); - } + // collect all addresses that may be the target of a jump instruction + SortedSet targets = new TreeSet(); + for (int addr = Machine.CB; addr < Machine.CT; addr++) { + Instruction inst = Machine.code[addr]; + Machine.Op op = Machine.intToOp[inst.op]; + switch (op) { + case CALL: + case CALLI: + // only consider calls (branches) within code memory (i.e. not + // primitives) + if (inst.r == Machine.Reg.CB.ordinal()) + targets.add(inst.d); + break; + case JUMP: + // address following an unconditional branch is an implicit + // target + targets.add(addr + 1); + targets.add(inst.d); + break; + case JUMPIF: + // a jump of any sort creates a branch target + targets.add(inst.d); + break; + default: + break; + } + } - // disassemble each instruction - for (int addr = Machine.CB; addr < Machine.CT; addr++) { - - // generate instruction address - asmWrite(String.format("%3d ", addr)); + // map branch target addresses to unique labels + addrToLabel = new HashMap(); + int labelCounter = 10; + for (Integer addr : targets) { + String label = "L" + labelCounter++; + addrToLabel.put(addr, label); + } - // if this addr is a branch target, output label - if (addrToLabel.containsKey(addr)) - asmWrite(String.format("%-7s", addrToLabel.get(addr) + ":")); - else - asmWrite(" "); + // disassemble each instruction + for (int addr = Machine.CB; addr < Machine.CT; addr++) { - // instruction - writeInstruction(Machine.code[addr]); + // generate instruction address + asmWrite(String.format("%3d ", addr)); - // newline - asmWrite("\n"); - } + // if this addr is a branch target, output label + if (addrToLabel.containsKey(addr)) + asmWrite(String.format("%-7s", addrToLabel.get(addr) + ":")); + else + asmWrite(" "); - // close output file - try { - asmOut.close(); - } catch (IOException e) { - error = true; - } - } + // instruction + writeInstruction(Machine.code[addr]); - private void asmWrite(String s) { - try { - asmOut.write(s); - } catch (IOException e) { - error = true; - } - } + // newline + asmWrite("\n"); + } - public static void main(String[] args) { - System.out.println("********** mJAM Disassembler (1.0) **********"); - String objectFileName = "obj.mJAM"; - if (args.length == 1) - objectFileName = args[0]; - Disassembler d = new Disassembler(objectFileName); - d.disassemble(); - } + // close output file + try { + asmOut.close(); + } catch (IOException e) { + error = true; + } + } - /** - * Disassemble object file - * @return true if error encountered else false - */ - public boolean disassemble() { - ObjectFile objectFile = new ObjectFile(objectFileName); + private void asmWrite(String s) { + try { + asmOut.write(s); + } catch (IOException e) { + error = true; + } + } - // read object file into code store - if (objectFile.read()) { - System.out.println("Disassembler: unable to read object file" - + objectFileName); - return true; - } + public static void main(String[] args) { + System.out.println("********** mJAM Disassembler (1.0) **********"); + String objectFileName = "obj.mJAM"; + if (args.length == 1) + objectFileName = args[0]; + Disassembler d = new Disassembler(objectFileName); + d.disassemble(); + } - // assembler-code output file name - if (objectFileName.endsWith(".mJAM")) - asmName = objectFileName.substring(0, objectFileName.length() - 5) - + ".asm"; - else - asmName = objectFileName + ".asm"; + /** + * Disassemble object file + * + * @return true if error encountered else false + */ + public boolean disassemble() { + ObjectFile objectFile = new ObjectFile(objectFileName); - // disassemble to file - disassembleProgram(asmName); + // read object file into code store + if (objectFile.read()) { + System.out.println("Disassembler: unable to read object file" + objectFileName); + return true; + } - if (error) { - System.out.println("Disassembler: unable to write asm file" - + asmName); - return true; - } - - return false; - } + // assembler-code output file name + if (objectFileName.endsWith(".mJAM")) + asmName = objectFileName.substring(0, objectFileName.length() - 5) + ".asm"; + else + asmName = objectFileName + ".asm"; + + // disassemble to file + disassembleProgram(asmName); + + if (error) { + System.out.println("Disassembler: unable to write asm file" + asmName); + return true; + } + + return false; + } } diff --git a/src/mJAM/Instruction.java b/src/mJAM/Instruction.java index 8e3ef84..4634dc1 100644 --- a/src/mJAM/Instruction.java +++ b/src/mJAM/Instruction.java @@ -7,30 +7,30 @@ package mJAM; public class Instruction { - public Instruction() { - op = 0; - r = 0; - n = 0; - d = 0; - } + public Instruction() { + op = 0; + r = 0; + n = 0; + d = 0; + } - public Instruction(int op, int n, int r, int d) { - this.op = op; - this.n = n; - this.r = r; - this.d = d; - } + public Instruction(int op, int n, int r, int d) { + this.op = op; + this.n = n; + this.r = r; + this.d = d; + } - // Java has no type synonyms, so the following representations are - // assumed: - // - // type - // OpCode = 0..15; {4 bits unsigned} - // Register = 0..15; (4 bits unsigned) - // Length = 0..255; {8 bits unsigned} - // Operand = -2147483648 .. +2147483647; (32 bits signed for use with LOADL) - public int op; // OpCode - public int r; // RegisterNumber - public int n; // Length - public int d; // Operand + // Java has no type synonyms, so the following representations are + // assumed: + // + // type + // OpCode = 0..15; {4 bits unsigned} + // Register = 0..15; (4 bits unsigned) + // Length = 0..255; {8 bits unsigned} + // Operand = -2147483648 .. +2147483647; (32 bits signed for use with LOADL) + public int op; // OpCode + public int r; // RegisterNumber + public int n; // Length + public int d; // Operand } diff --git a/src/mJAM/Interpreter.java b/src/mJAM/Interpreter.java index c2716f3..772139d 100644 --- a/src/mJAM/Interpreter.java +++ b/src/mJAM/Interpreter.java @@ -18,871 +18,841 @@ import java.util.Scanner; public class Interpreter { - // DATA STORE - static int[] data = new int[1024]; + // 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 - + // 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, OB, status, temp; + static int CT, CP, ST, HT, LB, OB, status, temp; - // machine status values - final static int running = 0, halted = 1, failedDataStoreFull = 2, - failedInvalidCodeAddress = 3, failedInvalidInstruction = 4, - failedOverflow = 5, failedZeroDivide = 6, failedIOError = 7, - failedArrayIndex = 8, failedNullRef = 9, failedHeapRef =10, - failedMethodIndex = 11; + // machine status values + final static int running = 0, halted = 1, failedDataStoreFull = 2, failedInvalidCodeAddress = 3, + failedInvalidInstruction = 4, failedOverflow = 5, failedZeroDivide = 6, failedIOError = 7, + failedArrayIndex = 8, failedNullRef = 9, failedHeapRef = 10, failedMethodIndex = 11; - static long accumulator; + static long accumulator; - // Debugger state - enum DebuggerStatus { - PAUSED, RUNNING - } + // Debugger state + enum DebuggerStatus { + PAUSED, RUNNING + } - static DebuggerStatus debuggerStatus = DebuggerStatus.PAUSED; - static ArrayList breakpoints = new ArrayList(); - static ArrayList sourceLines; + static DebuggerStatus debuggerStatus = DebuggerStatus.PAUSED; + static ArrayList breakpoints = new ArrayList(); + static ArrayList sourceLines; - static int content(int r) { - // Returns the current content of register r, - Machine.Reg reg = Machine.intToReg[r]; - switch (reg) { - 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 OB: - return OB; - case CP: - return CP; - default: - return 0; - } - } + static int content(int r) { + // Returns the current content of register r, + Machine.Reg reg = Machine.intToReg[r]; + switch (reg) { + 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 OB: + return OB; + case CP: + return CP; + default: + return 0; + } + } - // PROGRAM STATUS + // PROGRAM STATUS - static void dump() { - // Writes a summary of the machine state. - int addr, dynamicLink; - System.out.println(""); - System.out.println("At instruction " + CP - + ", state of mJAM data store and registers is:"); - System.out.println(""); - if (HT == HB) - System.out.println(" |--------| (heap is empty)"); - else { - System.out.println(" HB--> "); - System.out.println(" |--------|"); - for (addr = HB - 1; addr >= HT; addr--) { - System.out.print(rightPad(6, addr + ":")); - if (addr == OB) - System.out.print("OB--> "); - else if (addr == HT) - System.out.print("HT--> "); - else - System.out.print(" "); - System.out.println("|" + leftPad(8, String.valueOf(data[addr])) - + "|"); - } - System.out.println(" |--------|"); - } - System.out.println(" |////////|"); - System.out.println(" |////////|"); - if (ST == SB) - System.out.println(" |--------| (stack is empty)"); - else { - dynamicLink = LB; - System.out.println(" ST--> |////////|"); - System.out.println(" |--------|"); - for (addr = ST - 1; addr >= SB; addr--) { - System.out.print(rightPad(6, addr + ": ")); - if (addr == SB) - System.out.print("SB--> "); - else if (addr == LB) - System.out.print("LB--> "); - else - System.out.print(" "); - if ((addr == dynamicLink) && (dynamicLink != SB)) - System.out.print("|OB=" - + leftPad(5, String.valueOf(data[addr])) + "|"); - else if ((addr == dynamicLink + 1) && (dynamicLink != SB)) - System.out.print("|DL=" - + leftPad(5, String.valueOf(data[addr])) + "|"); - else if ((addr == dynamicLink + 2) && (dynamicLink != SB)) - System.out.print("|RA=" - + leftPad(5, String.valueOf(data[addr])) + "|"); - else - System.out.print("|" - + leftPad(8, String.valueOf(data[addr])) + "|"); - System.out.println(""); - if (addr == dynamicLink) { - System.out.println(" |--------|"); - dynamicLink = data[addr + 1]; - } - } - } - System.out.println(""); - } + static void dump() { + // Writes a summary of the machine state. + int addr, dynamicLink; + System.out.println(""); + System.out.println("At instruction " + CP + ", state of mJAM data store and registers is:"); + System.out.println(""); + if (HT == HB) + System.out.println(" |--------| (heap is empty)"); + else { + System.out.println(" HB--> "); + System.out.println(" |--------|"); + for (addr = HB - 1; addr >= HT; addr--) { + System.out.print(rightPad(6, addr + ":")); + if (addr == OB) + System.out.print("OB--> "); + else if (addr == HT) + System.out.print("HT--> "); + else + System.out.print(" "); + System.out.println("|" + leftPad(8, String.valueOf(data[addr])) + "|"); + } + System.out.println(" |--------|"); + } + System.out.println(" |////////|"); + System.out.println(" |////////|"); + if (ST == SB) + System.out.println(" |--------| (stack is empty)"); + else { + dynamicLink = LB; + System.out.println(" ST--> |////////|"); + System.out.println(" |--------|"); + for (addr = ST - 1; addr >= SB; addr--) { + System.out.print(rightPad(6, addr + ": ")); + if (addr == SB) + System.out.print("SB--> "); + else if (addr == LB) + System.out.print("LB--> "); + else + System.out.print(" "); + if ((addr == dynamicLink) && (dynamicLink != SB)) + System.out.print("|OB=" + leftPad(5, String.valueOf(data[addr])) + "|"); + else if ((addr == dynamicLink + 1) && (dynamicLink != SB)) + System.out.print("|DL=" + leftPad(5, String.valueOf(data[addr])) + "|"); + else if ((addr == dynamicLink + 2) && (dynamicLink != SB)) + System.out.print("|RA=" + leftPad(5, String.valueOf(data[addr])) + "|"); + else + System.out.print("|" + leftPad(8, String.valueOf(data[addr])) + "|"); + System.out.println(""); + if (addr == dynamicLink) { + System.out.println(" |--------|"); + dynamicLink = data[addr + 1]; + } + } + } + System.out.println(""); + } - private static String leftPad(int len, String s) { - int aLen = Math.max(len, s.length()); - StringBuffer buf = new StringBuffer(s); - String r = buf.insert(0, " ").toString(); - return r.substring(r.length() - aLen, r.length()); - } + private static String leftPad(int len, String s) { + int aLen = Math.max(len, s.length()); + StringBuffer buf = new StringBuffer(s); + String r = buf.insert(0, " ").toString(); + return r.substring(r.length() - aLen, r.length()); + } - private static String rightPad(int len, String s) { - int aLen = Math.max(len, s.length()); - String r = s + " "; - return r.substring(0, aLen); - } + private static String rightPad(int len, String s) { + int aLen = Math.max(len, s.length()); + String r = s + " "; + return r.substring(0, aLen); + } - static void showStatus() { - // Writes an indication of whether and why the program has terminated. - System.out.println(""); - System.out.print("*** "); - switch (status) { - case running: - System.out.println("Program is running."); - break; - case halted: - System.out.println("Program has halted normally."); - 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; - case failedArrayIndex: - System.out.println("Program has failed due to an array index error."); - break; - case failedNullRef: - System.out.println("Program has failed due to a null pointer reference."); - break; - case failedHeapRef: - System.out.println("Program has failed due to an invalid Heap reference."); - break; - case failedMethodIndex: - System.out.println("Program has failed due to an improper method index in CALLD."); - break; - default: - System.out.println("Machine is in an unknown state."); - break; - } - if (status != halted) - dump(); - } + static void showStatus() { + // Writes an indication of whether and why the program has terminated. + System.out.println(""); + System.out.print("*** "); + switch (status) { + case running: + System.out.println("Program is running."); + break; + case halted: + System.out.println("Program has halted normally."); + 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; + case failedArrayIndex: + System.out.println("Program has failed due to an array index error."); + break; + case failedNullRef: + System.out.println("Program has failed due to a null pointer reference."); + break; + case failedHeapRef: + System.out.println("Program has failed due to an invalid Heap reference."); + break; + case failedMethodIndex: + System.out.println("Program has failed due to an improper method index in CALLD."); + break; + default: + System.out.println("Machine is in an unknown state."); + break; + } + if (status != halted) + dump(); + } - // INTERPRETATION + // 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 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 invalidHeapRef(int addr) { - // if addr is null ptr or outside of heap bounds, sets status to failure - if (addr == Machine.nullRep) - status = failedNullRef; - else if (addr < HT + 2 || addr >= HB) - status = failedHeapRef; - return (status != running); - } + static boolean invalidHeapRef(int addr) { + // if addr is null ptr or outside of heap bounds, sets status to failure + if (addr == Machine.nullRep) + status = failedNullRef; + else if (addr < HT + 2 || addr >= HB) + status = failedHeapRef; + return (status != running); + } - static boolean isTrue(int datum) { - // Tests whether the given datum represents true. - return (datum == Machine.trueRep); - } + static boolean isTrue(int datum) { + // Tests whether the given datum represents true. + return (datum == Machine.trueRep); + } - 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.minintRep <= datum) && (datum <= Machine.maxintRep)) - return (int) datum; - else { - status = failedOverflow; - return 0; - } - } + 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.minintRep <= 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 toInt(boolean b) { + return b ? Machine.trueRep : Machine.falseRep; + } - static int currentChar; + static int currentChar; - static int readInt() throws java.io.IOException { - int temp = 0; - int sign = 1; + static int readInt() throws java.io.IOException { + int temp = 0; + int sign = 1; - do { - currentChar = System.in.read(); - } while (Character.isWhitespace((char) currentChar)); + 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 ((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)); + if (Character.isDigit((char) currentChar)) + do { + temp = temp * 10 + (currentChar - '0'); + currentChar = System.in.read(); + } while (Character.isDigit((char) currentChar)); - return sign * temp; - } + return sign * temp; + } - // Invoke primitive operation with argument(s) on the stack - // primitives are static and are not supplied an instance on the stack. - static void callPrimitive(int id) { + // Invoke primitive operation with argument(s) on the stack + // primitives are static and are not supplied an instance on the stack. + static void callPrimitive(int id) { - int addr, size, index; - char ch; + int addr, size, index; + char ch; - Machine.Prim prim = Machine.intToPrim[id]; - switch (prim) { - 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] = overflowChecked(-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: - ST = ST - 1; - data[ST - 1] = toInt(data[ST - 1] == data[ST]); - break; - case ne: - ST = ST - 1; - data[ST - 1] = toInt(data[ST - 1] != data[ST]); - 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] = (int) 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; - // output with prefix for tester - case putintnl: - ST = ST - 1; - accumulator = data[ST]; - System.out.print(">>> " + accumulator + "\n"); - break; - case alloc: - 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; - case newobj: - // ..., class obj addr, number of fields ==> ..., new obj addr - size = data[ST - 1] + 2; // number of fields + 2 word descriptor - checkSpace(size); - HT = HT - size; // reserve space - data[HT] = data[ST - 2]; // set class object addr - data[HT + 1] = size - 2; // set size of object - data[ST - 2] = HT + 2; // addr of new object instance, returned on stack - ST = ST - 1; // net effect of pop 2 args, push 1 result - for (int i = 2; i < size; i++) { - data[HT + i] = 0; // zero all fields of new object - } - break; - case newarr: - // ..., number of elements ==> ..., new int[] addr - size = data[ST - 1] + 2; // array + 2 word descriptor - checkSpace(size); - HT = HT - size; - data[HT] = -2; // tag for array - data[HT + 1] = size - 2; // size of array - data[ST - 1] = HT + 2; // addr of array instance, returned on stack - for (int i = 2; i < size; i++) { - data[HT + i] = 0; // zero all elements of new array - } - break; - case arrayref: - // ..., array addr a, element index i ==> ..., a[i] - addr = data[ST - 2]; - if (invalidHeapRef(addr)) - break; - index = data[ST - 1]; - if (data[addr - 2] != -2 || index < 0 || index >= data[addr - 1]) { - status = failedArrayIndex; - break; - } - data[ST - 2] = data[addr + index]; // result element, returned on stack - ST = ST - 1; // pop two args, return one result - break; - case arrayupd: - // ..., array addr a, element index i, new value v ==> ... - // and a[i] := v - addr = data[ST - 3]; - if (invalidHeapRef(addr)) - break; - index = data[ST - 2]; - if (data[addr - 2] != -2 || index < 0 || index >= data[addr - 1]) { - status = failedArrayIndex; - break; - } - data[addr + index] = data[ST - 1]; // update array element - ST = ST - 3; // pop 3 args, return no result - break; - case fieldref: - // ..., obj addr a, field index i ==> ..., value of ith field of a - addr = data[ST - 2]; - if (invalidHeapRef(addr)) - break; - index = data[ST - 1]; - if (index < 0 || index >= data[addr - 1]) { - status = failedArrayIndex; - break; - } - data[ST - 2] = data[addr + index]; // field to stack top - ST = ST - 1; // pop two args, return one result - break; - case fieldupd: - // ..., obj addr a, field index i, new value v ==> ... - // and a.i := v - addr = data[ST - 3]; - if (invalidHeapRef(addr)) - break; - index = data[ST - 2]; - if (index < 0 || index >= data[addr - 1]) { - status = failedArrayIndex; - break; - } - data[addr + index] = data[ST - 1]; // update field to new value - ST = ST - 3; // pop 3 args, return no result - break; - } - } + Machine.Prim prim = Machine.intToPrim[id]; + switch (prim) { + 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] = overflowChecked(-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: + ST = ST - 1; + data[ST - 1] = toInt(data[ST - 1] == data[ST]); + break; + case ne: + ST = ST - 1; + data[ST - 1] = toInt(data[ST - 1] != data[ST]); + 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] = (int) 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; + // output with prefix for tester + case putintnl: + ST = ST - 1; + accumulator = data[ST]; + System.out.print(">>> " + accumulator + "\n"); + break; + case alloc: + 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; + case newobj: + // ..., class obj addr, number of fields ==> ..., new obj addr + size = data[ST - 1] + 2; // number of fields + 2 word descriptor + checkSpace(size); + HT = HT - size; // reserve space + data[HT] = data[ST - 2]; // set class object addr + data[HT + 1] = size - 2; // set size of object + data[ST - 2] = HT + 2; // addr of new object instance, returned on + // stack + ST = ST - 1; // net effect of pop 2 args, push 1 result + for (int i = 2; i < size; i++) { + data[HT + i] = 0; // zero all fields of new object + } + break; + case newarr: + // ..., number of elements ==> ..., new int[] addr + size = data[ST - 1] + 2; // array + 2 word descriptor + checkSpace(size); + HT = HT - size; + data[HT] = -2; // tag for array + data[HT + 1] = size - 2; // size of array + data[ST - 1] = HT + 2; // addr of array instance, returned on stack + for (int i = 2; i < size; i++) { + data[HT + i] = 0; // zero all elements of new array + } + break; + case arrayref: + // ..., array addr a, element index i ==> ..., a[i] + addr = data[ST - 2]; + if (invalidHeapRef(addr)) + break; + index = data[ST - 1]; + if (data[addr - 2] != -2 || index < 0 || index >= data[addr - 1]) { + status = failedArrayIndex; + break; + } + data[ST - 2] = data[addr + index]; // result element, returned on + // stack + ST = ST - 1; // pop two args, return one result + break; + case arrayupd: + // ..., array addr a, element index i, new value v ==> ... + // and a[i] := v + addr = data[ST - 3]; + if (invalidHeapRef(addr)) + break; + index = data[ST - 2]; + if (data[addr - 2] != -2 || index < 0 || index >= data[addr - 1]) { + status = failedArrayIndex; + break; + } + data[addr + index] = data[ST - 1]; // update array element + ST = ST - 3; // pop 3 args, return no result + break; + case fieldref: + // ..., obj addr a, field index i ==> ..., value of ith field of a + addr = data[ST - 2]; + if (invalidHeapRef(addr)) + break; + index = data[ST - 1]; + if (index < 0 || index >= data[addr - 1]) { + status = failedArrayIndex; + break; + } + data[ST - 2] = data[addr + index]; // field to stack top + ST = ST - 1; // pop two args, return one result + break; + case fieldupd: + // ..., obj addr a, field index i, new value v ==> ... + // and a.i := v + addr = data[ST - 3]; + if (invalidHeapRef(addr)) + break; + index = data[ST - 2]; + if (index < 0 || index >= data[addr - 1]) { + status = failedArrayIndex; + break; + } + data[addr + index] = data[ST - 1]; // update field to new value + ST = ST - 3; // pop 3 args, return no result + break; + } + } - static void interpretOneOperation() { - // Fetch instruction ... - Instruction currentInstr = Machine.code[CP]; - // Decode instruction ... - int op = currentInstr.op; - int r = currentInstr.r; - int n = currentInstr.n; - int d = currentInstr.d; - int addr; - // Execute instruction ... + static void interpretOneOperation() { + // Fetch instruction ... + Instruction currentInstr = Machine.code[CP]; + // Decode instruction ... + int op = currentInstr.op; + int r = currentInstr.r; + int n = currentInstr.n; + int d = currentInstr.d; + int addr; + // Execute instruction ... - Machine.Op operation = Machine.intToOp[op]; + Machine.Op operation = Machine.intToOp[op]; - switch (operation) { - case LOAD: - addr = d + content(r); - checkSpace(1); - data[ST] = data[addr]; - ST = ST + 1; - 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(1); - data[ST] = data[addr]; - ST = ST + 1; - 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 - 1; - data[addr] = data[ST]; - CP = CP + 1; - break; - case STOREI: - ST = ST - 1; - addr = data[ST]; - ST = ST - 1; - data[addr] = data[ST]; - CP = CP + 1; - break; - - case CALL: - // call static method, including primitives - // arguments are on stack - addr = d + content(r); // effective address - if (addr >= Machine.PB) { - callPrimitive(addr - Machine.PB); - CP = CP + 1; - } else { - // static method in code segment, no instance addr on stack - checkSpace(3); - data[ST] = OB; // save caller OB in callee frame - data[ST + 1] = LB; // save caller LB in callee frame (dynamic link) - data[ST + 2] = CP + 1; // save caller return address in callee frame - OB = Machine.nullRep; // set callee OB (null since no instance) - LB = ST; // set LB = start of callee frame - ST = ST + 3; // set ST = end of callee frame - CP = addr; // execution resumes at addr specified in CALL inst - } - break; - - case CALLI: - // call instance method - // arguments on stack, followed by instance address - addr = d + content(r); // effective address - if (addr >= Machine.CT) { - // no instance methods outside of code segment - status = failedInvalidInstruction; - break; - } - // instance address is last arg on stack and is overwritten by frame - checkSpace(2); - temp = data[ST - 1]; // save instance address temporarily - data[ST - 1] = OB; // save caller OB in callee frame - data[ST] = LB; // save caller LB in callee frame (dynamic link) - data[ST + 1] = CP + 1; // save caller return address in callee frame - OB = temp; // set OB for callee - LB = ST - 1; // set LB = start of callee frame - ST = ST + 2; // set ST = end of callee frame - CP = addr; // execution resumes at addr specified in CALL inst - break; - - case RETURN: - // d = number of method args (does not include instance addr for CALLI) - // n = size of result (0 or 1) - if (n < 0 || n > 1) { - status = failedInvalidInstruction; - break; - } - addr = LB - d; // addr of caller args - OB = data[LB]; // restore caller OB, LB, CP - CP = data[LB + 2]; - LB = data[LB + 1]; - if (n == 1) - data[addr] = data[ST - 1]; // return value if any - ST = addr + n; // caller stack top - break; - - case CALLD: - // dynamic method dispatch of method with index d (origin 0) - // arguments on stack, followed by instance addr - { - addr = data[ST - 1]; // instance addr - if (invalidHeapRef(addr)) - break; - int classDescAddr = data[addr - 2]; - if (classDescAddr >= ST || classDescAddr <= SB || d >= data[classDescAddr + 1] || d < 0) { - status = failedMethodIndex; - break; - } - ST = ST - 1; - checkSpace(3); - data[ST] = OB; - data[ST + 1] = LB; - data[ST + 2] = CP + 1; - OB = addr; - LB = ST; - ST = ST + 3; - CP = data[classDescAddr + 2 + n]; - } - break; - case PUSH: // push d elements on stack - checkSpace(d); - ST = ST + d; - CP = CP + 1; - break; - case POP: // pop d elements off stack - ST = ST - d; - 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: - if (n > 0) { - // halt n > 0 --> snapshot machine state and continue execution - dump(); - CP = CP + 1; - } else - status = halted; - break; - } + switch (operation) { + case LOAD: + addr = d + content(r); + checkSpace(1); + data[ST] = data[addr]; + ST = ST + 1; + 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(1); + data[ST] = data[addr]; + ST = ST + 1; + 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 - 1; + data[addr] = data[ST]; + CP = CP + 1; + break; + case STOREI: + ST = ST - 1; + addr = data[ST]; + ST = ST - 1; + data[addr] = data[ST]; + CP = CP + 1; + break; - if ((CP < CB) || (CP >= CT)) - status = failedInvalidCodeAddress; + case CALL: + // call static method, including primitives + // arguments are on stack + addr = d + content(r); // effective address + if (addr >= Machine.PB) { + callPrimitive(addr - Machine.PB); + CP = CP + 1; + } else { + // static method in code segment, no instance addr on stack + checkSpace(3); + data[ST] = OB; // save caller OB in callee frame + data[ST + 1] = LB; // save caller LB in callee frame (dynamic + // link) + data[ST + 2] = CP + 1; // save caller return address in callee + // frame + OB = Machine.nullRep; // set callee OB (null since no instance) + LB = ST; // set LB = start of callee frame + ST = ST + 3; // set ST = end of callee frame + CP = addr; // execution resumes at addr specified in CALL inst + } + break; - if (breakpoints.indexOf(CP) != -1) { - debuggerStatus = DebuggerStatus.PAUSED; - System.out.println("Breakpoint hit: " + sourceLines.get(CP)); - } - } + case CALLI: + // call instance method + // arguments on stack, followed by instance address + addr = d + content(r); // effective address + if (addr >= Machine.CT) { + // no instance methods outside of code segment + status = failedInvalidInstruction; + break; + } + // instance address is last arg on stack and is overwritten by frame + checkSpace(2); + temp = data[ST - 1]; // save instance address temporarily + data[ST - 1] = OB; // save caller OB in callee frame + data[ST] = LB; // save caller LB in callee frame (dynamic link) + data[ST + 1] = CP + 1; // save caller return address in callee frame + OB = temp; // set OB for callee + LB = ST - 1; // set LB = start of callee frame + ST = ST + 2; // set ST = end of callee frame + CP = addr; // execution resumes at addr specified in CALL inst + break; - static void initMachine() { - // Initialize registers ... - ST = SB; - HT = HB; - LB = SB; - CP = CB; - OB = -1; // invalid instance addr - CT = Machine.CT; - status = running; - } + case RETURN: + // d = number of method args (does not include instance addr for + // CALLI) + // n = size of result (0 or 1) + if (n < 0 || n > 1) { + status = failedInvalidInstruction; + break; + } + addr = LB - d; // addr of caller args + OB = data[LB]; // restore caller OB, LB, CP + CP = data[LB + 2]; + LB = data[LB + 1]; + if (n == 1) + data[addr] = data[ST - 1]; // return value if any + ST = addr + n; // caller stack top + break; - static void interpretProgram() { - // Runs the program in code store. - initMachine(); - do { - interpretOneOperation(); - } while (status == running); - } + case CALLD: + // dynamic method dispatch of method with index d (origin 0) + // arguments on stack, followed by instance addr + { + addr = data[ST - 1]; // instance addr + if (invalidHeapRef(addr)) + break; + int classDescAddr = data[addr - 2]; + if (classDescAddr >= ST || classDescAddr <= SB || d >= data[classDescAddr + 1] || d < 0) { + status = failedMethodIndex; + break; + } + ST = ST - 1; + checkSpace(3); + data[ST] = OB; + data[ST + 1] = LB; + data[ST + 2] = CP + 1; + OB = addr; + LB = ST; + ST = ST + 3; + CP = data[classDescAddr + 2 + n]; + } + break; + case PUSH: // push d elements on stack + checkSpace(d); + ST = ST + d; + CP = CP + 1; + break; + case POP: // pop d elements off stack + ST = ST - d; + 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: + if (n > 0) { + // halt n > 0 --> snapshot machine state and continue execution + dump(); + CP = CP + 1; + } else + status = halted; + break; + } - static void runProgramFromStart() { - initMachine(); - continueProgram(); - } + if ((CP < CB) || (CP >= CT)) + status = failedInvalidCodeAddress; - static void continueProgram() { - debuggerStatus = DebuggerStatus.RUNNING; - do { - interpretOneOperation(); - } while (status == running && debuggerStatus == DebuggerStatus.RUNNING); - } + if (breakpoints.indexOf(CP) != -1) { + debuggerStatus = DebuggerStatus.PAUSED; + System.out.println("Breakpoint hit: " + sourceLines.get(CP)); + } + } - static void printHelp() { - String[] help = { - "p or print:", - " print entire machine state", - "l or list [offset] [size]:", - " print the instructions around CP + offset, with size lines on either side", - " offset = 0 and size = 2 by default", - "b or break [address]:", - " set a breakpoint at address", - " address = CP by default", - "del:", - " delete one or more breakpoints", - "n or next:", - " execute one instruction", - "c or continue:", - " continue running the program from current position, until next breakpoint or completion", - "r or run:", - " run the program from start, until next breakpoint or completion", - "i or info:", " list the current breakpoints", - "q, quit or :", " quit the debugger", - "Simply press enter to repeat the last command", "? or help:", - " print this help" }; + static void initMachine() { + // Initialize registers ... + ST = SB; + HT = HB; + LB = SB; + CP = CB; + OB = -1; // invalid instance addr + CT = Machine.CT; + status = running; + } - for (String line : help) { - System.out.println(" " + line); - } - } + static void interpretProgram() { + // Runs the program in code store. + initMachine(); + do { + interpretOneOperation(); + } while (status == running); + } - static void debugProgram() { - initMachine(); + static void runProgramFromStart() { + initMachine(); + continueProgram(); + } - BufferedReader inputReader = new BufferedReader(new InputStreamReader( - System.in)); + static void continueProgram() { + debuggerStatus = DebuggerStatus.RUNNING; + do { + interpretOneOperation(); + } while (status == running && debuggerStatus == DebuggerStatus.RUNNING); + } - String lastCommand = ""; + static void printHelp() { + String[] help = { "p or print:", " print entire machine state", "l or list [offset] [size]:", + " print the instructions around CP + offset, with size lines on either side", + " offset = 0 and size = 2 by default", "b or break [address]:", " set a breakpoint at address", + " address = CP by default", "del:", " delete one or more breakpoints", "n or next:", + " execute one instruction", "c or continue:", + " continue running the program from current position, until next breakpoint or completion", + "r or run:", " run the program from start, until next breakpoint or completion", "i or info:", + " list the current breakpoints", "q, quit or :", " quit the debugger", + "Simply press enter to repeat the last command", "? or help:", " print this help" }; - while (true) { - System.out.print("\n: "); - String inputLine; + for (String line : help) { + System.out.println(" " + line); + } + } - try { - inputLine = inputReader.readLine(); - } catch (IOException e) { - return; - } + static void debugProgram() { + initMachine(); - if (inputLine == null) - return; + BufferedReader inputReader = new BufferedReader(new InputStreamReader(System.in)); - Scanner scanner = new Scanner(inputLine); - String command = (scanner.hasNext() ? scanner.next() : lastCommand); - lastCommand = command; + String lastCommand = ""; - if (command.equals("?") || command.equals("help")) { - printHelp(); - } else if (command.equalsIgnoreCase("p") - || command.equalsIgnoreCase("print")) { - dump(); - } else if (command.equalsIgnoreCase("l") - || command.equalsIgnoreCase("list")) { - int offset = 0, size = 2; - if (scanner.hasNextInt()) - offset = scanner.nextInt(); - if (scanner.hasNextInt()) - size = scanner.nextInt(); + while (true) { + System.out.print("\n: "); + String inputLine; - for (int i = CP + offset - size; i <= CP + offset + size; ++i) { - if (i >= 0 && i < sourceLines.size()) - System.out.println((i == CP ? " >" : " ") - + sourceLines.get(i)); - } - } else if (command.equalsIgnoreCase("b") - || command.equalsIgnoreCase("break")) { - int addr = scanner.hasNextInt() ? scanner.nextInt() : CP; - if (!breakpoints.contains(addr)) - breakpoints.add(addr); - System.out.println("Added breakpoint at " - + sourceLines.get(addr)); - } else if (command.equalsIgnoreCase("del")) { - while (scanner.hasNextInt()) { - int addr = scanner.nextInt(), idx = breakpoints - .indexOf(addr); - if (idx != -1) { - breakpoints.remove(idx); - } else { - System.out.println("No breakpoint at " + addr); - } - } - } else if (command.equalsIgnoreCase("n") - || command.equalsIgnoreCase("next")) { - if (status == running) { - interpretOneOperation(); - } else { - System.out.println("Program is not running"); - } - } else if (command.equalsIgnoreCase("c") - || command.equalsIgnoreCase("continue")) { - continueProgram(); - } else if (command.equalsIgnoreCase("r") - || command.equalsIgnoreCase("run")) { - runProgramFromStart(); - } else if (command.equalsIgnoreCase("i") - || command.equalsIgnoreCase("info")) { - System.out.println("Breakpoints:"); - for (int b : breakpoints) { - System.out.println("\t" + sourceLines.get(b)); - } - } else if (command.equalsIgnoreCase("q") - || command.equalsIgnoreCase("quit")) { - scanner.close(); - return; - } else { - System.out.println("Unknown command '" + command - + "'. Type 'help' for a list of commands"); - } - scanner.close(); - } - } + try { + inputLine = inputReader.readLine(); + } catch (IOException e) { + return; + } - // RUNNING + if (inputLine == null) + return; - public static void main(String[] args) { - System.out - .println("********** mJAM Interpreter (Version 1.2) **********"); + Scanner scanner = new Scanner(inputLine); + String command = (scanner.hasNext() ? scanner.next() : lastCommand); + lastCommand = command; - String objectFileName; - if (args.length >= 1) - objectFileName = args[0]; - else - objectFileName = "obj.mJAM"; + if (command.equals("?") || command.equals("help")) { + printHelp(); + } else if (command.equalsIgnoreCase("p") || command.equalsIgnoreCase("print")) { + dump(); + } else if (command.equalsIgnoreCase("l") || command.equalsIgnoreCase("list")) { + int offset = 0, size = 2; + if (scanner.hasNextInt()) + offset = scanner.nextInt(); + if (scanner.hasNextInt()) + size = scanner.nextInt(); - String sourceFileName; - if (args.length >= 2) { - sourceFileName = args[1]; - debug(objectFileName, sourceFileName); - } else { - interpret(objectFileName); - } - } + for (int i = CP + offset - size; i <= CP + offset + size; ++i) { + if (i >= 0 && i < sourceLines.size()) + System.out.println((i == CP ? " >" : " ") + sourceLines.get(i)); + } + } else if (command.equalsIgnoreCase("b") || command.equalsIgnoreCase("break")) { + int addr = scanner.hasNextInt() ? scanner.nextInt() : CP; + if (!breakpoints.contains(addr)) + breakpoints.add(addr); + System.out.println("Added breakpoint at " + sourceLines.get(addr)); + } else if (command.equalsIgnoreCase("del")) { + while (scanner.hasNextInt()) { + int addr = scanner.nextInt(), idx = breakpoints.indexOf(addr); + if (idx != -1) { + breakpoints.remove(idx); + } else { + System.out.println("No breakpoint at " + addr); + } + } + } else if (command.equalsIgnoreCase("n") || command.equalsIgnoreCase("next")) { + if (status == running) { + interpretOneOperation(); + } else { + System.out.println("Program is not running"); + } + } else if (command.equalsIgnoreCase("c") || command.equalsIgnoreCase("continue")) { + continueProgram(); + } else if (command.equalsIgnoreCase("r") || command.equalsIgnoreCase("run")) { + runProgramFromStart(); + } else if (command.equalsIgnoreCase("i") || command.equalsIgnoreCase("info")) { + System.out.println("Breakpoints:"); + for (int b : breakpoints) { + System.out.println("\t" + sourceLines.get(b)); + } + } else if (command.equalsIgnoreCase("q") || command.equalsIgnoreCase("quit")) { + scanner.close(); + return; + } else { + System.out.println("Unknown command '" + command + "'. Type 'help' for a list of commands"); + } + scanner.close(); + } + } - public static void interpret(String objectFileName) { + // RUNNING - ObjectFile objectFile = new ObjectFile(objectFileName); - if (objectFile.read()) { - System.out.println("Unable to load object file " + objectFileName); - return; - } - interpretProgram(); - showStatus(); - } + public static void main(String[] args) { + System.out.println("********** mJAM Interpreter (Version 1.2) **********"); - public static void debug(String objectFileName, String sourceFileName) { - ObjectFile objectFile = new ObjectFile(objectFileName); - if (objectFile.read()) { - System.out.println("Unable to load object file " + objectFileName); - return; - } + String objectFileName; + if (args.length >= 1) + objectFileName = args[0]; + else + objectFileName = "obj.mJAM"; - sourceLines = new ArrayList(); - try { - BufferedReader reader = new BufferedReader(new FileReader(new File( - sourceFileName))); - String line = reader.readLine(); - while (line != null) { - sourceLines.add(line); - line = reader.readLine(); - } - reader.close(); - } catch (FileNotFoundException e) { - System.out.println("Unable to load source file " + sourceFileName); - return; - } catch (IOException ie) { - System.out.println("Unable to load source file " + sourceFileName); - return; - } + String sourceFileName; + if (args.length >= 2) { + sourceFileName = args[1]; + debug(objectFileName, sourceFileName); + } else { + interpret(objectFileName); + } + } - debugProgram(); - } + public static void interpret(String objectFileName) { + + ObjectFile objectFile = new ObjectFile(objectFileName); + if (objectFile.read()) { + System.out.println("Unable to load object file " + objectFileName); + return; + } + interpretProgram(); + showStatus(); + } + + public static void debug(String objectFileName, String sourceFileName) { + ObjectFile objectFile = new ObjectFile(objectFileName); + if (objectFile.read()) { + System.out.println("Unable to load object file " + objectFileName); + return; + } + + sourceLines = new ArrayList(); + try { + BufferedReader reader = new BufferedReader(new FileReader(new File(sourceFileName))); + String line = reader.readLine(); + while (line != null) { + sourceLines.add(line); + line = reader.readLine(); + } + reader.close(); + } catch (FileNotFoundException e) { + System.out.println("Unable to load source file " + sourceFileName); + return; + } catch (IOException ie) { + System.out.println("Unable to load source file " + sourceFileName); + return; + } + + debugProgram(); + } } diff --git a/src/mJAM/Machine.java b/src/mJAM/Machine.java index fb3b838..e4cfed4 100644 --- a/src/mJAM/Machine.java +++ b/src/mJAM/Machine.java @@ -2,231 +2,188 @@ package mJAM; /** * Defines names and sizes of mJAM instructions and primitives + * * @author prins * @version COMP 520 V2.2 */ public final class Machine { - - /** - * mJAM instructions - */ - public enum Op { - LOAD, - LOADA, - LOADI, - LOADL, - STORE, - STOREI, - CALL, // direct call of instance method - CALLI, // indirect call of instance method - CALLD, // dynamic call of instance method - RETURN, - PUSH, - POP, - JUMP, - JUMPI, - JUMPIF, - HALT; - } - public static Op [] intToOp = Op.values(); - - /** - * mJAM registers - */ - public enum Reg { - ZR, // zero, not used - CB, // code base - CT, // code top - CP, // code pointer - PB, // primitives base - PT, // primitives top - SB, // execution stack base - ST, // execution stack top - LB, // locals base - HB, // heap base - HT, // heap top - OB; // object base - } - public static Reg [] intToReg = Reg.values(); - - /** - * mJAM primitives - */ - public enum Prim { - 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, - putintnl, - alloc, - dispose, - newobj, - newarr, - arrayref, - arrayupd, - fieldref, - fieldupd; - } - public static Prim [] intToPrim = Prim.values(); - - - -// range for int constants - public final static long - minintRep = -2147483648, - maxintRep = 2147483647; - - - // CODE STORE REGISTERS - public final static int CB = 0; // start of code space - public final static int PB = 1024; // size of code space reserved for instructions - public final static int PT = PB + Prim.values().length; // code space reserved for primitives - - // CODE STORE - public static Instruction[] code = new Instruction[PB]; - public static int CT = CB; - - public static void initCodeGen() { - CT = CB; - } - - /** - * Places an instruction, with the given fields, into the next position in the code store - * @param op - operation - * @param n - length - * @param r - register - * @param d - displacement - */ -public static void emit(Op op, int n, Reg r, Prim d) { - emit(op.ordinal(), n, r.ordinal(), d.ordinal()); - } - -/** - * emit operation with single literal argument d (n,r not used). These are - * operations like LOADL 44, PUSH 3, and CALLD 1 - */ -public static void emit(Op op, int d) { - emit(op.ordinal(), 0, 0, d); -} - - /** - * emit "call primitive operation" (operation built-in to mJAM). This - * generates CALL primitiveop[PB] - */ - public static void emit(Prim d) { - emit(Op.CALL.ordinal(), 0, Machine.Reg.PB.ordinal(), d.ordinal()); - } - - /** - * emit operations without arguments. These are operations like - * LOADI and STOREI - */ - public static void emit(Op op) { - emit(op, 0, 0, 0); - } - - /** - * emit operation with register r and integer displacement. These are - * operations like JUMP 25[CB] and LOAD 6[LB] - */ - public static void emit(Op op, Reg r, int d) { - emit(op.ordinal(), 0, r.ordinal(), d); - } - - /** - * emit operation with n field, and register r and integer displacement. These are - * operations like JUMPIF (1) 25[CB]. In the assembly code the value of n is shown - * in parens. - */ - public static void emit(Op op, int n, Reg r, int d) { - emit(op.ordinal(), n, r.ordinal(), d); - } - - /** - * emit operation with integer n, r, d. These are operations - * like RETURN (1) 3 and HALT (4) 0. For RETURN the value - * of d is the number of caller args to pop off the callers - * stack and n is the number of values to return at caller stack - * top. n must be 0 or 1. - */ - public static void emit(Op op, int n, int r, int d) { - emit(op.ordinal(), n, r, d); - } - - /** - * helper operation for emit using integer values - */ -private static void emit (int op, int n, int r, int d) { - if (n > 255) { - System.out.println("length of operand can't exceed 255 words"); - n = 255; // to allow code generation to continue + /** + * mJAM instructions + */ + public enum Op { + LOAD, LOADA, LOADI, LOADL, STORE, STOREI, CALL, // direct call of + // instance method + CALLI, // indirect call of instance method + CALLD, // dynamic call of instance method + RETURN, PUSH, POP, JUMP, JUMPI, JUMPIF, HALT; } - if (CT >= Machine.PB) - System.out.println("mJAM: code segment capacity exceeded"); - - Instruction nextInstr = new Instruction(op, n, r, d); + + public static Op[] intToOp = Op.values(); + + /** + * mJAM registers + */ + public enum Reg { + ZR, // zero, not used + CB, // code base + CT, // code top + CP, // code pointer + PB, // primitives base + PT, // primitives top + SB, // execution stack base + ST, // execution stack top + LB, // locals base + HB, // heap base + HT, // heap top + OB; // object base + } + + public static Reg[] intToReg = Reg.values(); + + /** + * mJAM primitives + */ + public enum Prim { + 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, putintnl, alloc, dispose, newobj, newarr, arrayref, arrayupd, fieldref, fieldupd; + } + + public static Prim[] intToPrim = Prim.values(); + + // range for int constants + public final static long minintRep = -2147483648, maxintRep = 2147483647; + + // CODE STORE REGISTERS + public final static int CB = 0; // start of code space + public final static int PB = 1024; // size of code space reserved for + // instructions + public final static int PT = PB + Prim.values().length; // code space + // reserved for + // primitives + + // CODE STORE + public static Instruction[] code = new Instruction[PB]; + public static int CT = CB; + + public static void initCodeGen() { + CT = CB; + } + + /** + * Places an instruction, with the given fields, into the next position in + * the code store + * + * @param op + * - operation + * @param n + * - length + * @param r + * - register + * @param d + * - displacement + */ + public static void emit(Op op, int n, Reg r, Prim d) { + emit(op.ordinal(), n, r.ordinal(), d.ordinal()); + } + + /** + * emit operation with single literal argument d (n,r not used). These are + * operations like LOADL 44, PUSH 3, and CALLD 1 + */ + public static void emit(Op op, int d) { + emit(op.ordinal(), 0, 0, d); + } + + /** + * emit "call primitive operation" (operation built-in to mJAM). This + * generates CALL primitiveop[PB] + */ + public static void emit(Prim d) { + emit(Op.CALL.ordinal(), 0, Machine.Reg.PB.ordinal(), d.ordinal()); + } + + /** + * emit operations without arguments. These are operations like LOADI and + * STOREI + */ + public static void emit(Op op) { + emit(op, 0, 0, 0); + } + + /** + * emit operation with register r and integer displacement. These are + * operations like JUMP 25[CB] and LOAD 6[LB] + */ + public static void emit(Op op, Reg r, int d) { + emit(op.ordinal(), 0, r.ordinal(), d); + } + + /** + * emit operation with n field, and register r and integer displacement. + * These are operations like JUMPIF (1) 25[CB]. In the assembly code the + * value of n is shown in parens. + */ + public static void emit(Op op, int n, Reg r, int d) { + emit(op.ordinal(), n, r.ordinal(), d); + } + + /** + * emit operation with integer n, r, d. These are operations like RETURN (1) + * 3 and HALT (4) 0. For RETURN the value of d is the number of caller args + * to pop off the callers stack and n is the number of values to return at + * caller stack top. n must be 0 or 1. + */ + public static void emit(Op op, int n, int r, int d) { + emit(op.ordinal(), n, r, d); + } + + /** + * helper operation for emit using integer values + */ + private static void emit(int op, int n, int r, int d) { + if (n > 255) { + System.out.println("length of operand can't exceed 255 words"); + n = 255; // to allow code generation to continue + } + if (CT >= Machine.PB) + System.out.println("mJAM: code segment capacity exceeded"); + + Instruction nextInstr = new Instruction(op, n, r, d); Machine.code[CT] = nextInstr; CT = CT + 1; - } + } -/** - * @return address (relative to CB) of next instruction to be generated - */ -public static int nextInstrAddr() { - return CT; -} + /** + * @return address (relative to CB) of next instruction to be generated + */ + public static int nextInstrAddr() { + return CT; + } -/** - * Update the displacement component of the (JUMP or CALL) instruction at addr - * @param addr - * @param displacement - */ -public static void patch(int addr, int displacement) { - if (addr < 0 || addr >= CT) { - System.out.println("patch: address of instruction to be patched is out of range"); - return; - } - if (displacement < 0 || displacement > CT) { - System.out.println("patch: target address of patch is out of range"); - return; - } - Machine.code[addr].d = displacement; - return; -} + /** + * Update the displacement component of the (JUMP or CALL) instruction at + * addr + * + * @param addr + * @param displacement + */ + public static void patch(int addr, int displacement) { + if (addr < 0 || addr >= CT) { + System.out.println("patch: address of instruction to be patched is out of range"); + return; + } + if (displacement < 0 || displacement > CT) { + System.out.println("patch: target address of patch is out of range"); + return; + } + Machine.code[addr].d = displacement; + return; + } -// DATA REPRESENTATION + // DATA REPRESENTATION - public final static int - booleanSize = 1, - characterSize = 1, - integerSize = 1, - addressSize = 1, - linkDataSize = 3 * addressSize, // caller's OB, LB, CP - falseRep = 0, - trueRep = 1, - nullRep = 0; + public final static int booleanSize = 1, characterSize = 1, integerSize = 1, addressSize = 1, + linkDataSize = 3 * addressSize, // caller's OB, LB, CP + falseRep = 0, trueRep = 1, nullRep = 0; } diff --git a/src/mJAM/ObjectFile.java b/src/mJAM/ObjectFile.java index a164b3c..93b66d2 100644 --- a/src/mJAM/ObjectFile.java +++ b/src/mJAM/ObjectFile.java @@ -11,60 +11,64 @@ import java.io.FileOutputStream; import java.io.DataOutputStream; public class ObjectFile { - - String objectFileName; - public ObjectFile(String objectFileName) { - super(); - this.objectFileName = objectFileName; - } - - /** - * Write code store as object file - * @param output object file - * @return true if write fails - */ - public boolean write(){ - boolean failed = false; - try { - FileOutputStream objectFile = new FileOutputStream(objectFileName); - DataOutputStream is = new DataOutputStream(objectFile); - for (int i = Machine.CB; i < Machine.CT; i++ ){ - Instruction inst = Machine.code[i]; - is.writeInt(inst.op); - is.writeInt(inst.n); - is.writeInt(inst.r); - is.writeInt(inst.d); - } - objectFile.close(); - } - catch (Exception e) {failed = true;} - return failed; - } + String objectFileName; - /** - * Read object file into code store, setting CT - * @return true if object code read fails - */ - public boolean read() { - boolean failed = false; - try { - FileInputStream objectFile = new FileInputStream(objectFileName); - DataInputStream is = new DataInputStream(objectFile); - - Machine.CT = Machine.CB; - while (is.available() > 0 && Machine.CT < Machine.PB){ - Instruction inst = new Instruction(); - inst.op = is.readInt(); - inst.n = is.readInt(); - inst.r = is.readInt(); - inst.d = is.readInt(); - Machine.code[Machine.CT++] = inst; - } - objectFile.close(); - } catch (Exception e) { - failed = true; - } - return failed; - } + public ObjectFile(String objectFileName) { + super(); + this.objectFileName = objectFileName; + } + + /** + * Write code store as object file + * + * @param output + * object file + * @return true if write fails + */ + public boolean write() { + boolean failed = false; + try { + FileOutputStream objectFile = new FileOutputStream(objectFileName); + DataOutputStream is = new DataOutputStream(objectFile); + for (int i = Machine.CB; i < Machine.CT; i++) { + Instruction inst = Machine.code[i]; + is.writeInt(inst.op); + is.writeInt(inst.n); + is.writeInt(inst.r); + is.writeInt(inst.d); + } + objectFile.close(); + } catch (Exception e) { + failed = true; + } + return failed; + } + + /** + * Read object file into code store, setting CT + * + * @return true if object code read fails + */ + public boolean read() { + boolean failed = false; + try { + FileInputStream objectFile = new FileInputStream(objectFileName); + DataInputStream is = new DataInputStream(objectFile); + + Machine.CT = Machine.CB; + while (is.available() > 0 && Machine.CT < Machine.PB) { + Instruction inst = new Instruction(); + inst.op = is.readInt(); + inst.n = is.readInt(); + inst.r = is.readInt(); + inst.d = is.readInt(); + Machine.code[Machine.CT++] = inst; + } + objectFile.close(); + } catch (Exception e) { + failed = true; + } + return failed; + } } diff --git a/src/mJAM/Test.java b/src/mJAM/Test.java index c3b0d66..84d9ad5 100644 --- a/src/mJAM/Test.java +++ b/src/mJAM/Test.java @@ -4,154 +4,147 @@ * @version COMP 520 V2.2 */ package mJAM; + import mJAM.Machine.Op; import mJAM.Machine.Reg; import mJAM.Machine.Prim; // test class to construct and run an mJAM program -public class Test -{ - public static void main(String[] args){ - - Machine.initCodeGen(); - System.out.println("Generating test program object code"); - - /* class A { - * int x; - * int p(){return x;} - * } - */ - Machine.emit(Op.LOADL,11); // hello - Machine.emit(Prim.putintnl); - int patchme_coA = Machine.nextInstrAddr(); - Machine.emit(Op.JUMP,Reg.CB,0); // jump around methods of class A (branch to /*coA*/) - - // code for p() in A - int label_pA = Machine.nextInstrAddr(); -/*pA*/ Machine.emit(Op.LOAD,Reg.OB,0); // x at offset 0 in current instance of A - Machine.emit(Op.HALT,4,0,0); - Machine.emit(Op.RETURN,1,0,0); // return one value, pop zero args - - // build class object for A at 0[SB] - int label_coA = Machine.nextInstrAddr(); - Machine.patch(patchme_coA, label_coA); -/*coA*/ Machine.emit(Op.LOADL,-1); // no superclass object - Machine.emit(Op.LOADL,1); // number of methods - Machine.emit(Op.LOADA,Reg.CB,label_pA); // code addr of p_A - - - /* class B extends A { - * int y; - * int p(){return x + 22;} - * } - */ - int patchme_coB = Machine.nextInstrAddr(); - Machine.emit(Op.JUMP,Reg.CB,0); // branch around methods in class B - - // code for p() in B - int label_pB = Machine.nextInstrAddr(); -/*pB*/ Machine.emit(Op.LOAD,Reg.OB,0); // x at offset 0 in current instance - Machine.emit(Op.LOADL,22); - Machine.emit(Op.HALT,4,0,0); - Machine.emit(Prim.add); - Machine.emit(Op.RETURN,1,0,0); // return one value, pop zero args - - // build class object for B at 3[SB] - int label_coB = Machine.nextInstrAddr(); - Machine.patch(patchme_coB, label_coB); -/*coB*/ Machine.emit(Op.LOADA,Reg.SB,0); // addr of superclass object - Machine.emit(Op.LOADL,1); // number of methods - Machine.emit(Op.LOADA,Reg.CB,label_pB); // code addr of p_B +public class Test { + public static void main(String[] args) { - - /* class C { - * public static void main(String [] args) { - * A a = new A(); - * a.x = 33; - * System.out.println(a.p()); - * ... - */ - int patchme_coC = Machine.nextInstrAddr(); - Machine.emit(Op.JUMP,Reg.CB,0); // branch around methods of class C - - // code for main() in C - int label_mainC = Machine.nextInstrAddr(); -/*mainC*/ Machine.emit(Op.HALT,4,0,0); - // local var "a" will be at 3[LB] after init - Machine.emit(Op.LOADA,Reg.SB,0); // class descriptor for A - Machine.emit(Op.LOADL,1); // size of A - Machine.emit(Prim.newobj); // result addr becomes value of "a" - Machine.emit(Op.LOAD,Reg.LB,3); // value of "a" (heap addr) - Machine.emit(Op.LOADL,0); // "x" is field 0 in A - Machine.emit(Op.LOADL,33); // new value 33 - Machine.emit(Op.HALT,4,0,0); - Machine.emit(Prim.fieldupd); // a.x = 33 - Machine.emit(Op.LOAD,Reg.LB,3); // addr of instance "a" on heap - Machine.emit(Op.CALLI,Reg.CB,label_pA); // call to known instance method p_A - Machine.emit(Prim.putintnl); // print result - - /* ... - * A b = new B(); - * b.x = 44; - * System.out.println(b.p()); - * } // end main - * } // end class C - */ - // local var "b" will be at 4[LB] after init - Machine.emit(Op.LOADA,Reg.SB,3); // class descriptor for B - Machine.emit(Op.LOADL,2); // size of B - Machine.emit(Prim.newobj); // result addr becomes value of "b" - Machine.emit(Op.LOAD,Reg.LB,4); // fetch b - Machine.emit(Op.LOADL,0); // field 0 - Machine.emit(Op.LOADL,44); // b.x = 44 - Machine.emit(Prim.fieldupd); - Machine.emit(Op.HALT,4,0,0); - Machine.emit(Op.LOAD,Reg.LB,4); // addr of instance "b" - Machine.emit(Op.CALLD,0); // dynamic call, method index 0 (= method p) - Machine.emit(Prim.putintnl); // print result - Machine.emit(Op.RETURN,0,0,1); // return no value (void), pop 1 arg (= String [] args) - - // build class descriptor for C at 6[SB] - int label_coC = Machine.nextInstrAddr(); - Machine.patch(patchme_coC, label_coC); -/*coC*/ Machine.emit(Op.LOADL,-1); // no superclass object - Machine.emit(Op.LOADL,0); // number of methods = 0 - - /* - * End of class declarations - call main - */ - Machine.emit(Op.LOADL,Machine.nullRep); // put null on stack as value of main's arg - Machine.emit(Op.CALL,Reg.CB,label_mainC); // call known static main() - Machine.emit(Op.LOADL,88); // goodbye - Machine.emit(Prim.putintnl); - Machine.emit(Machine.Op.HALT,0,0,0); // halt + Machine.initCodeGen(); + System.out.println("Generating test program object code"); - /* write code as an object file */ - String objectCodeFileName = "test.mJAM"; - ObjectFile objF = new ObjectFile(objectCodeFileName); - System.out.print("Writing object code file " + objectCodeFileName + " ... "); - if (objF.write()) { - System.out.println("FAILED!"); - return; - } - else - System.out.println("SUCCEEDED"); - - /* create asm file using disassembler */ - String asmCodeFileName = "test.asm"; - System.out.print("Writing assembly file ... "); - Disassembler d = new Disassembler(objectCodeFileName); - if (d.disassemble()) { - System.out.println("FAILED!"); - return; - } - else - System.out.println("SUCCEEDED"); - - /* run code */ - System.out.println("Running code ... "); - Interpreter.debug(objectCodeFileName, asmCodeFileName); + /* + * class A { int x; int p(){return x;} } + */ + Machine.emit(Op.LOADL, 11); // hello + Machine.emit(Prim.putintnl); + int patchme_coA = Machine.nextInstrAddr(); + Machine.emit(Op.JUMP, Reg.CB, 0); // jump around methods of class A + // (branch to /*coA*/) - System.out.println("*** mJAM execution completed"); - } + // code for p() in A + int label_pA = Machine.nextInstrAddr(); + /* pA */ Machine.emit(Op.LOAD, Reg.OB, 0); // x at offset 0 in current + // instance of A + Machine.emit(Op.HALT, 4, 0, 0); + Machine.emit(Op.RETURN, 1, 0, 0); // return one value, pop zero args + + // build class object for A at 0[SB] + int label_coA = Machine.nextInstrAddr(); + Machine.patch(patchme_coA, label_coA); + /* coA */ Machine.emit(Op.LOADL, -1); // no superclass object + Machine.emit(Op.LOADL, 1); // number of methods + Machine.emit(Op.LOADA, Reg.CB, label_pA); // code addr of p_A + + /* + * class B extends A { int y; int p(){return x + 22;} } + */ + int patchme_coB = Machine.nextInstrAddr(); + Machine.emit(Op.JUMP, Reg.CB, 0); // branch around methods in class B + + // code for p() in B + int label_pB = Machine.nextInstrAddr(); + /* pB */ Machine.emit(Op.LOAD, Reg.OB, 0); // x at offset 0 in current + // instance + Machine.emit(Op.LOADL, 22); + Machine.emit(Op.HALT, 4, 0, 0); + Machine.emit(Prim.add); + Machine.emit(Op.RETURN, 1, 0, 0); // return one value, pop zero args + + // build class object for B at 3[SB] + int label_coB = Machine.nextInstrAddr(); + Machine.patch(patchme_coB, label_coB); + /* coB */ Machine.emit(Op.LOADA, Reg.SB, 0); // addr of superclass + // object + Machine.emit(Op.LOADL, 1); // number of methods + Machine.emit(Op.LOADA, Reg.CB, label_pB); // code addr of p_B + + /* + * class C { public static void main(String [] args) { A a = new A(); + * a.x = 33; System.out.println(a.p()); ... + */ + int patchme_coC = Machine.nextInstrAddr(); + Machine.emit(Op.JUMP, Reg.CB, 0); // branch around methods of class C + + // code for main() in C + int label_mainC = Machine.nextInstrAddr(); + /* mainC */ Machine.emit(Op.HALT, 4, 0, 0); + // local var "a" will be at 3[LB] after init + Machine.emit(Op.LOADA, Reg.SB, 0); // class descriptor for A + Machine.emit(Op.LOADL, 1); // size of A + Machine.emit(Prim.newobj); // result addr becomes value of "a" + Machine.emit(Op.LOAD, Reg.LB, 3); // value of "a" (heap addr) + Machine.emit(Op.LOADL, 0); // "x" is field 0 in A + Machine.emit(Op.LOADL, 33); // new value 33 + Machine.emit(Op.HALT, 4, 0, 0); + Machine.emit(Prim.fieldupd); // a.x = 33 + Machine.emit(Op.LOAD, Reg.LB, 3); // addr of instance "a" on heap + Machine.emit(Op.CALLI, Reg.CB, label_pA); // call to known instance + // method p_A + Machine.emit(Prim.putintnl); // print result + + /* + * ... A b = new B(); b.x = 44; System.out.println(b.p()); } // end main + * } // end class C + */ + // local var "b" will be at 4[LB] after init + Machine.emit(Op.LOADA, Reg.SB, 3); // class descriptor for B + Machine.emit(Op.LOADL, 2); // size of B + Machine.emit(Prim.newobj); // result addr becomes value of "b" + Machine.emit(Op.LOAD, Reg.LB, 4); // fetch b + Machine.emit(Op.LOADL, 0); // field 0 + Machine.emit(Op.LOADL, 44); // b.x = 44 + Machine.emit(Prim.fieldupd); + Machine.emit(Op.HALT, 4, 0, 0); + Machine.emit(Op.LOAD, Reg.LB, 4); // addr of instance "b" + Machine.emit(Op.CALLD, 0); // dynamic call, method index 0 (= method p) + Machine.emit(Prim.putintnl); // print result + Machine.emit(Op.RETURN, 0, 0, 1); // return no value (void), pop 1 arg + // (= String [] args) + + // build class descriptor for C at 6[SB] + int label_coC = Machine.nextInstrAddr(); + Machine.patch(patchme_coC, label_coC); + /* coC */ Machine.emit(Op.LOADL, -1); // no superclass object + Machine.emit(Op.LOADL, 0); // number of methods = 0 + + /* + * End of class declarations - call main + */ + Machine.emit(Op.LOADL, Machine.nullRep); // put null on stack as value + // of main's arg + Machine.emit(Op.CALL, Reg.CB, label_mainC); // call known static main() + Machine.emit(Op.LOADL, 88); // goodbye + Machine.emit(Prim.putintnl); + Machine.emit(Machine.Op.HALT, 0, 0, 0); // halt + + /* write code as an object file */ + String objectCodeFileName = "test.mJAM"; + ObjectFile objF = new ObjectFile(objectCodeFileName); + System.out.print("Writing object code file " + objectCodeFileName + " ... "); + if (objF.write()) { + System.out.println("FAILED!"); + return; + } else + System.out.println("SUCCEEDED"); + + /* create asm file using disassembler */ + String asmCodeFileName = "test.asm"; + System.out.print("Writing assembly file ... "); + Disassembler d = new Disassembler(objectCodeFileName); + if (d.disassemble()) { + System.out.println("FAILED!"); + return; + } else + System.out.println("SUCCEEDED"); + + /* run code */ + System.out.println("Running code ... "); + Interpreter.debug(objectCodeFileName, asmCodeFileName); + + System.out.println("*** mJAM execution completed"); + } } diff --git a/src/miniJava/AbstractSyntaxTrees/AST.java b/src/miniJava/AbstractSyntaxTrees/AST.java index 5982b3f..dbc1c5a 100644 --- a/src/miniJava/AbstractSyntaxTrees/AST.java +++ b/src/miniJava/AbstractSyntaxTrees/AST.java @@ -9,19 +9,19 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public abstract class AST { - public AST(SourcePosition posn) { - this.posn = posn; - } + public AST(SourcePosition posn) { + this.posn = posn; + } - public String toString() { - String fullClassName = this.getClass().getName(); - String cn = fullClassName.substring(1 + fullClassName.lastIndexOf('.')); - if (ASTDisplay.showPosition) - cn = cn + " " + posn.toString(); - return cn; - } + public String toString() { + String fullClassName = this.getClass().getName(); + String cn = fullClassName.substring(1 + fullClassName.lastIndexOf('.')); + if (ASTDisplay.showPosition) + cn = cn + " " + posn.toString(); + return cn; + } - public abstract R visit(Visitor v, A o); + public abstract R visit(Visitor v, A o); - public SourcePosition posn; + public SourcePosition posn; } diff --git a/src/miniJava/AbstractSyntaxTrees/ASTDisplay.java b/src/miniJava/AbstractSyntaxTrees/ASTDisplay.java index 08d18db..fac8c05 100644 --- a/src/miniJava/AbstractSyntaxTrees/ASTDisplay.java +++ b/src/miniJava/AbstractSyntaxTrees/ASTDisplay.java @@ -18,341 +18,339 @@ package miniJava.AbstractSyntaxTrees; */ public class ASTDisplay implements Visitor { - public static boolean showPosition = false; + public static boolean showPosition = false; - /** - * print text representation of AST to stdout - * - * @param ast - * root node of AST - */ - public void showTree(AST ast) { - System.out.println("======= AST Display ========================="); - ast.visit(this, ""); - System.out.println("============================================="); - } + /** + * print text representation of AST to stdout + * + * @param ast + * root node of AST + */ + public void showTree(AST ast) { + System.out.println("======= AST Display ========================="); + ast.visit(this, ""); + System.out.println("============================================="); + } - // methods to format output + // methods to format output - /** - * display arbitrary text for a node - * - * @param prefix - * spacing to indicate depth in AST - * @param text - * preformatted node display - */ - private void show(String prefix, String text) { - System.out.println(prefix + text); - } + /** + * display arbitrary text for a node + * + * @param prefix + * spacing to indicate depth in AST + * @param text + * preformatted node display + */ + private void show(String prefix, String text) { + System.out.println(prefix + text); + } - /** - * display AST node by name - * - * @param prefix - * spacing to indicate depth in AST - * @param node - * AST node, will be shown by name - */ - private void show(String prefix, AST node) { - System.out.println(prefix + node.toString()); - } + /** + * display AST node by name + * + * @param prefix + * spacing to indicate depth in AST + * @param node + * AST node, will be shown by name + */ + private void show(String prefix, AST node) { + System.out.println(prefix + node.toString()); + } - /** - * quote a string - * - * @param text - * string to quote - */ - private String quote(String text) { - return ("\"" + text + "\""); - } + /** + * quote a string + * + * @param text + * string to quote + */ + private String quote(String text) { + return ("\"" + text + "\""); + } - /** - * increase depth in AST - * - * @param prefix - * current spacing to indicate depth in AST - * @return new spacing - */ - private String indent(String prefix) { - return prefix + " "; - } + /** + * increase depth in AST + * + * @param prefix + * current spacing to indicate depth in AST + * @return new spacing + */ + private String indent(String prefix) { + return prefix + " "; + } - // ///////////////////////////////////////////////////////////////////////////// - // - // PACKAGE - // - // ///////////////////////////////////////////////////////////////////////////// + // ///////////////////////////////////////////////////////////////////////////// + // + // PACKAGE + // + // ///////////////////////////////////////////////////////////////////////////// - public Object visitPackage(Package prog, String arg) { - show(arg, prog); - ClassDeclList cl = prog.classDeclList; - show(arg, " ClassDeclList [" + cl.size() + "]"); - String pfx = arg + " . "; - for (ClassDecl c : prog.classDeclList) { - c.visit(this, pfx); - } - return null; - } + public Object visitPackage(Package prog, String arg) { + show(arg, prog); + ClassDeclList cl = prog.classDeclList; + show(arg, " ClassDeclList [" + cl.size() + "]"); + String pfx = arg + " . "; + for (ClassDecl c : prog.classDeclList) { + c.visit(this, pfx); + } + return null; + } - // ///////////////////////////////////////////////////////////////////////////// - // - // DECLARATIONS - // - // ///////////////////////////////////////////////////////////////////////////// + // ///////////////////////////////////////////////////////////////////////////// + // + // DECLARATIONS + // + // ///////////////////////////////////////////////////////////////////////////// - public Object visitClassDecl(ClassDecl clas, String arg) { - show(arg, clas); - show(indent(arg), quote(clas.name) + " classname"); - show(arg, " FieldDeclList [" + clas.fieldDeclList.size() + "]"); - String pfx = arg + " . "; - for (FieldDecl f : clas.fieldDeclList) - f.visit(this, pfx); - show(arg, " MethodDeclList [" + clas.methodDeclList.size() + "]"); - for (MethodDecl m : clas.methodDeclList) - m.visit(this, pfx); - return null; - } + public Object visitClassDecl(ClassDecl clas, String arg) { + show(arg, clas); + show(indent(arg), quote(clas.name) + " classname"); + show(arg, " FieldDeclList [" + clas.fieldDeclList.size() + "]"); + String pfx = arg + " . "; + for (FieldDecl f : clas.fieldDeclList) + f.visit(this, pfx); + show(arg, " MethodDeclList [" + clas.methodDeclList.size() + "]"); + for (MethodDecl m : clas.methodDeclList) + m.visit(this, pfx); + return null; + } - public Object visitFieldDecl(FieldDecl f, String arg) { - show(arg, "(" + (f.isPrivate ? "private" : "public") - + (f.isStatic ? " static) " : ") ") + f.toString()); - f.type.visit(this, indent(arg)); - show(indent(arg), quote(f.name) + " fieldname"); - return null; - } + public Object visitFieldDecl(FieldDecl f, String arg) { + show(arg, "(" + (f.isPrivate ? "private" : "public") + (f.isStatic ? " static) " : ") ") + f.toString()); + f.type.visit(this, indent(arg)); + show(indent(arg), quote(f.name) + " fieldname"); + return null; + } - public Object visitMethodDecl(MethodDecl m, String arg) { - show(arg, "(" + (m.isPrivate ? "private" : "public") - + (m.isStatic ? " static) " : ") ") + m.toString()); - m.type.visit(this, indent(arg)); - show(indent(arg), quote(m.name) + " methodname"); - ParameterDeclList pdl = m.parameterDeclList; - show(arg, " ParameterDeclList [" + pdl.size() + "]"); - String pfx = ((String) arg) + " . "; - for (ParameterDecl pd : pdl) { - pd.visit(this, pfx); - } - StatementList sl = m.statementList; - show(arg, " StmtList [" + sl.size() + "]"); - for (Statement s : sl) { - s.visit(this, pfx); - } - if (m.returnExp != null) { - m.returnExp.visit(this, indent(arg)); - } - return null; - } + public Object visitMethodDecl(MethodDecl m, String arg) { + show(arg, "(" + (m.isPrivate ? "private" : "public") + (m.isStatic ? " static) " : ") ") + m.toString()); + m.type.visit(this, indent(arg)); + show(indent(arg), quote(m.name) + " methodname"); + ParameterDeclList pdl = m.parameterDeclList; + show(arg, " ParameterDeclList [" + pdl.size() + "]"); + String pfx = ((String) arg) + " . "; + for (ParameterDecl pd : pdl) { + pd.visit(this, pfx); + } + StatementList sl = m.statementList; + show(arg, " StmtList [" + sl.size() + "]"); + for (Statement s : sl) { + s.visit(this, pfx); + } + if (m.returnExp != null) { + m.returnExp.visit(this, indent(arg)); + } + return null; + } - public Object visitParameterDecl(ParameterDecl pd, String arg) { - show(arg, pd); - pd.type.visit(this, indent(arg)); - show(indent(arg), quote(pd.name) + "parametername "); - return null; - } + public Object visitParameterDecl(ParameterDecl pd, String arg) { + show(arg, pd); + pd.type.visit(this, indent(arg)); + show(indent(arg), quote(pd.name) + "parametername "); + return null; + } - public Object visitVarDecl(VarDecl vd, String arg) { - show(arg, vd); - vd.type.visit(this, indent(arg)); - show(indent(arg), quote(vd.name) + " varname"); - return null; - } + public Object visitVarDecl(VarDecl vd, String arg) { + show(arg, vd); + vd.type.visit(this, indent(arg)); + show(indent(arg), quote(vd.name) + " varname"); + return null; + } - // ///////////////////////////////////////////////////////////////////////////// - // - // TYPES - // - // ///////////////////////////////////////////////////////////////////////////// + // ///////////////////////////////////////////////////////////////////////////// + // + // TYPES + // + // ///////////////////////////////////////////////////////////////////////////// - public Object visitBaseType(BaseType type, String arg) { - show(arg, type.typeKind + " " + type.toString()); - return null; - } + public Object visitBaseType(BaseType type, String arg) { + show(arg, type.typeKind + " " + type.toString()); + return null; + } - public Object visitClassType(ClassType type, String arg) { - show(arg, type); - show(indent(arg), quote(type.className.spelling) + " classname"); - return null; - } + public Object visitClassType(ClassType type, String arg) { + show(arg, type); + show(indent(arg), quote(type.className.spelling) + " classname"); + return null; + } - public Object visitArrayType(ArrayType type, String arg) { - show(arg, type); - type.eltType.visit(this, indent(arg)); - return null; - } + public Object visitArrayType(ArrayType type, String arg) { + show(arg, type); + type.eltType.visit(this, indent(arg)); + return null; + } - // ///////////////////////////////////////////////////////////////////////////// - // - // STATEMENTS - // - // ///////////////////////////////////////////////////////////////////////////// + // ///////////////////////////////////////////////////////////////////////////// + // + // STATEMENTS + // + // ///////////////////////////////////////////////////////////////////////////// - public Object visitBlockStmt(BlockStmt stmt, String arg) { - show(arg, stmt); - StatementList sl = stmt.sl; - show(arg, " StatementList [" + sl.size() + "]"); - String pfx = arg + " . "; - for (Statement s : sl) { - s.visit(this, pfx); - } - return null; - } + public Object visitBlockStmt(BlockStmt stmt, String arg) { + show(arg, stmt); + StatementList sl = stmt.sl; + show(arg, " StatementList [" + sl.size() + "]"); + String pfx = arg + " . "; + for (Statement s : sl) { + s.visit(this, pfx); + } + return null; + } - public Object visitVardeclStmt(VarDeclStmt stmt, String arg) { - show(arg, stmt); - stmt.varDecl.visit(this, indent(arg)); - stmt.initExp.visit(this, indent(arg)); - return null; - } + public Object visitVardeclStmt(VarDeclStmt stmt, String arg) { + show(arg, stmt); + stmt.varDecl.visit(this, indent(arg)); + stmt.initExp.visit(this, indent(arg)); + return null; + } - public Object visitAssignStmt(AssignStmt stmt, String arg) { - show(arg, stmt); - stmt.ref.visit(this, indent(arg)); - stmt.val.visit(this, indent(arg)); - return null; - } + public Object visitAssignStmt(AssignStmt stmt, String arg) { + show(arg, stmt); + stmt.ref.visit(this, indent(arg)); + stmt.val.visit(this, indent(arg)); + return null; + } - public Object visitCallStmt(CallStmt stmt, String arg) { - show(arg, stmt); - stmt.methodRef.visit(this, indent(arg)); - ExprList al = stmt.argList; - show(arg, " ExprList [" + al.size() + "]"); - String pfx = arg + " . "; - for (Expression e : al) { - e.visit(this, pfx); - } - return null; - } + public Object visitCallStmt(CallStmt stmt, String arg) { + show(arg, stmt); + stmt.methodRef.visit(this, indent(arg)); + ExprList al = stmt.argList; + show(arg, " ExprList [" + al.size() + "]"); + String pfx = arg + " . "; + for (Expression e : al) { + e.visit(this, pfx); + } + return null; + } - public Object visitIfStmt(IfStmt stmt, String arg) { - show(arg, stmt); - stmt.cond.visit(this, indent(arg)); - stmt.thenStmt.visit(this, indent(arg)); - if (stmt.elseStmt != null) - stmt.elseStmt.visit(this, indent(arg)); - return null; - } + public Object visitIfStmt(IfStmt stmt, String arg) { + show(arg, stmt); + stmt.cond.visit(this, indent(arg)); + stmt.thenStmt.visit(this, indent(arg)); + if (stmt.elseStmt != null) + stmt.elseStmt.visit(this, indent(arg)); + return null; + } - public Object visitWhileStmt(WhileStmt stmt, String arg) { - show(arg, stmt); - stmt.cond.visit(this, indent(arg)); - stmt.body.visit(this, indent(arg)); - return null; - } + public Object visitWhileStmt(WhileStmt stmt, String arg) { + show(arg, stmt); + stmt.cond.visit(this, indent(arg)); + stmt.body.visit(this, indent(arg)); + return null; + } - // ///////////////////////////////////////////////////////////////////////////// - // - // EXPRESSIONS - // - // ///////////////////////////////////////////////////////////////////////////// + // ///////////////////////////////////////////////////////////////////////////// + // + // EXPRESSIONS + // + // ///////////////////////////////////////////////////////////////////////////// - public Object visitUnaryExpr(UnaryExpr expr, String arg) { - show(arg, expr); - expr.operator.visit(this, indent(arg)); - expr.expr.visit(this, indent(indent(arg))); - return null; - } + public Object visitUnaryExpr(UnaryExpr expr, String arg) { + show(arg, expr); + expr.operator.visit(this, indent(arg)); + expr.expr.visit(this, indent(indent(arg))); + return null; + } - public Object visitBinaryExpr(BinaryExpr expr, String arg) { - show(arg, expr); - expr.operator.visit(this, indent(arg)); - expr.left.visit(this, indent(indent(arg))); - expr.right.visit(this, indent(indent(arg))); - return null; - } + public Object visitBinaryExpr(BinaryExpr expr, String arg) { + show(arg, expr); + expr.operator.visit(this, indent(arg)); + expr.left.visit(this, indent(indent(arg))); + expr.right.visit(this, indent(indent(arg))); + return null; + } - public Object visitRefExpr(RefExpr expr, String arg) { - show(arg, expr); - expr.ref.visit(this, indent(arg)); - return null; - } + public Object visitRefExpr(RefExpr expr, String arg) { + show(arg, expr); + expr.ref.visit(this, indent(arg)); + return null; + } - public Object visitCallExpr(CallExpr expr, String arg) { - show(arg, expr); - expr.functionRef.visit(this, indent(arg)); - ExprList al = expr.argList; - show(arg, " ExprList + [" + al.size() + "]"); - String pfx = arg + " . "; - for (Expression e : al) { - e.visit(this, pfx); - } - return null; - } + public Object visitCallExpr(CallExpr expr, String arg) { + show(arg, expr); + expr.functionRef.visit(this, indent(arg)); + ExprList al = expr.argList; + show(arg, " ExprList + [" + al.size() + "]"); + String pfx = arg + " . "; + for (Expression e : al) { + e.visit(this, pfx); + } + return null; + } - public Object visitLiteralExpr(LiteralExpr expr, String arg) { - show(arg, expr); - expr.literal.visit(this, indent(arg)); - return null; - } + public Object visitLiteralExpr(LiteralExpr expr, String arg) { + show(arg, expr); + expr.literal.visit(this, indent(arg)); + return null; + } - public Object visitNewArrayExpr(NewArrayExpr expr, String arg) { - show(arg, expr); - expr.eltType.visit(this, indent(arg)); - expr.sizeExpr.visit(this, indent(arg)); - return null; - } + public Object visitNewArrayExpr(NewArrayExpr expr, String arg) { + show(arg, expr); + expr.eltType.visit(this, indent(arg)); + expr.sizeExpr.visit(this, indent(arg)); + return null; + } - public Object visitNewObjectExpr(NewObjectExpr expr, String arg) { - show(arg, expr); - expr.classtype.visit(this, indent(arg)); - return null; - } + public Object visitNewObjectExpr(NewObjectExpr expr, String arg) { + show(arg, expr); + expr.classtype.visit(this, indent(arg)); + return null; + } - // ///////////////////////////////////////////////////////////////////////////// - // - // REFERENCES - // - // ///////////////////////////////////////////////////////////////////////////// + // ///////////////////////////////////////////////////////////////////////////// + // + // REFERENCES + // + // ///////////////////////////////////////////////////////////////////////////// - public Object visitQualifiedRef(QualifiedRef qr, String arg) { - show(arg, qr); - qr.id.visit(this, indent(arg)); - qr.ref.visit(this, indent(arg)); - return null; - } + public Object visitQualifiedRef(QualifiedRef qr, String arg) { + show(arg, qr); + qr.id.visit(this, indent(arg)); + qr.ref.visit(this, indent(arg)); + return null; + } - public Object visitIndexedRef(IndexedRef ir, String arg) { - show(arg, ir); - ir.indexExpr.visit(this, indent(arg)); - ir.ref.visit(this, indent(arg)); - return null; - } + public Object visitIndexedRef(IndexedRef ir, String arg) { + show(arg, ir); + ir.indexExpr.visit(this, indent(arg)); + ir.ref.visit(this, indent(arg)); + return null; + } - public Object visitIdRef(IdRef ref, String arg) { - show(arg, ref); - ref.id.visit(this, indent(arg)); - return null; - } + public Object visitIdRef(IdRef ref, String arg) { + show(arg, ref); + ref.id.visit(this, indent(arg)); + return null; + } - public Object visitThisRef(ThisRef ref, String arg) { - show(arg, ref); - return null; - } + public Object visitThisRef(ThisRef ref, String arg) { + show(arg, ref); + return null; + } - // ///////////////////////////////////////////////////////////////////////////// - // - // TERMINALS - // - // ///////////////////////////////////////////////////////////////////////////// + // ///////////////////////////////////////////////////////////////////////////// + // + // TERMINALS + // + // ///////////////////////////////////////////////////////////////////////////// - public Object visitIdentifier(Identifier id, String arg) { - show(arg, quote(id.spelling) + " " + id.toString()); - return null; - } + public Object visitIdentifier(Identifier id, String arg) { + show(arg, quote(id.spelling) + " " + id.toString()); + return null; + } - public Object visitOperator(Operator op, String arg) { - show(arg, quote(op.spelling) + " " + op.toString()); - return null; - } + public Object visitOperator(Operator op, String arg) { + show(arg, quote(op.spelling) + " " + op.toString()); + return null; + } - public Object visitIntLiteral(IntLiteral num, String arg) { - show(arg, quote(num.spelling) + " " + num.toString()); - return null; - } + public Object visitIntLiteral(IntLiteral num, String arg) { + show(arg, quote(num.spelling) + " " + num.toString()); + return null; + } - public Object visitBooleanLiteral(BooleanLiteral bool, String arg) { - show(arg, quote(bool.spelling) + " " + bool.toString()); - return null; - } + public Object visitBooleanLiteral(BooleanLiteral bool, String arg) { + show(arg, quote(bool.spelling) + " " + bool.toString()); + return null; + } } diff --git a/src/miniJava/AbstractSyntaxTrees/ArrayType.java b/src/miniJava/AbstractSyntaxTrees/ArrayType.java index 3275a14..85a5e38 100644 --- a/src/miniJava/AbstractSyntaxTrees/ArrayType.java +++ b/src/miniJava/AbstractSyntaxTrees/ArrayType.java @@ -10,18 +10,18 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class ArrayType extends Type { - public ArrayType(Type eltType, SourcePosition posn) { - super(TypeKind.ARRAY, posn); - this.eltType = eltType; - } + public ArrayType(Type eltType, SourcePosition posn) { + super(TypeKind.ARRAY, posn); + this.eltType = eltType; + } - public R visit(Visitor v, A o) { - return v.visitArrayType(this, o); - } - - public String toString() { - return eltType + " Array"; - } + public R visit(Visitor v, A o) { + return v.visitArrayType(this, o); + } - public Type eltType; + public String toString() { + return eltType + " Array"; + } + + public Type eltType; } diff --git a/src/miniJava/AbstractSyntaxTrees/AssignStmt.java b/src/miniJava/AbstractSyntaxTrees/AssignStmt.java index d7c3d44..aa59869 100644 --- a/src/miniJava/AbstractSyntaxTrees/AssignStmt.java +++ b/src/miniJava/AbstractSyntaxTrees/AssignStmt.java @@ -8,16 +8,16 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class AssignStmt extends Statement { - public AssignStmt(Reference r, Expression e, SourcePosition posn) { - super(posn); - ref = r; - val = e; - } + public AssignStmt(Reference r, Expression e, SourcePosition posn) { + super(posn); + ref = r; + val = e; + } - public R visit(Visitor v, A o) { - return v.visitAssignStmt(this, o); - } + public R visit(Visitor v, A o) { + return v.visitAssignStmt(this, o); + } - public Reference ref; - public Expression val; + public Reference ref; + public Expression val; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/BaseType.java b/src/miniJava/AbstractSyntaxTrees/BaseType.java index 69bc9af..c52724d 100644 --- a/src/miniJava/AbstractSyntaxTrees/BaseType.java +++ b/src/miniJava/AbstractSyntaxTrees/BaseType.java @@ -8,15 +8,15 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class BaseType extends Type { - public BaseType(TypeKind t, SourcePosition posn) { - super(t, posn); - } + public BaseType(TypeKind t, SourcePosition posn) { + super(t, posn); + } - public R visit(Visitor v, A o) { - return v.visitBaseType(this, o); - } - - public String toString() { - return typeKind.toString(); - } + public R visit(Visitor v, A o) { + return v.visitBaseType(this, o); + } + + public String toString() { + return typeKind.toString(); + } } diff --git a/src/miniJava/AbstractSyntaxTrees/BinaryExpr.java b/src/miniJava/AbstractSyntaxTrees/BinaryExpr.java index cb925a5..f7a4ece 100644 --- a/src/miniJava/AbstractSyntaxTrees/BinaryExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/BinaryExpr.java @@ -8,19 +8,18 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class BinaryExpr extends Expression { - public BinaryExpr(Operator o, Expression e1, Expression e2, - SourcePosition posn) { - super(posn); - operator = o; - left = e1; - right = e2; - } + public BinaryExpr(Operator o, Expression e1, Expression e2, SourcePosition posn) { + super(posn); + operator = o; + left = e1; + right = e2; + } - public R visit(Visitor v, A o) { - return v.visitBinaryExpr(this, o); - } + public R visit(Visitor v, A o) { + return v.visitBinaryExpr(this, o); + } - public Operator operator; - public Expression left; - public Expression right; + public Operator operator; + public Expression left; + public Expression right; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/BlockStmt.java b/src/miniJava/AbstractSyntaxTrees/BlockStmt.java index a2c7459..f15382e 100644 --- a/src/miniJava/AbstractSyntaxTrees/BlockStmt.java +++ b/src/miniJava/AbstractSyntaxTrees/BlockStmt.java @@ -8,14 +8,14 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class BlockStmt extends Statement { - public BlockStmt(StatementList sl, SourcePosition posn) { - super(posn); - this.sl = sl; - } + public BlockStmt(StatementList sl, SourcePosition posn) { + super(posn); + this.sl = sl; + } - public R visit(Visitor v, A o) { - return v.visitBlockStmt(this, o); - } + public R visit(Visitor v, A o) { + return v.visitBlockStmt(this, o); + } - public StatementList sl; + public StatementList sl; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/BooleanLiteral.java b/src/miniJava/AbstractSyntaxTrees/BooleanLiteral.java index 669c205..e0c80c3 100644 --- a/src/miniJava/AbstractSyntaxTrees/BooleanLiteral.java +++ b/src/miniJava/AbstractSyntaxTrees/BooleanLiteral.java @@ -9,11 +9,11 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class BooleanLiteral extends Literal { - public BooleanLiteral(String spelling, SourcePosition posn) { - super(spelling, posn); - } + public BooleanLiteral(String spelling, SourcePosition posn) { + super(spelling, posn); + } - public R visit(Visitor v, A o) { - return v.visitBooleanLiteral(this, o); - } + public R visit(Visitor v, A o) { + return v.visitBooleanLiteral(this, o); + } } diff --git a/src/miniJava/AbstractSyntaxTrees/CallExpr.java b/src/miniJava/AbstractSyntaxTrees/CallExpr.java index d17ba9f..9c2c82f 100644 --- a/src/miniJava/AbstractSyntaxTrees/CallExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/CallExpr.java @@ -8,16 +8,16 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class CallExpr extends Expression { - public CallExpr(Reference f, ExprList el, SourcePosition posn) { - super(posn); - functionRef = f; - argList = el; - } + public CallExpr(Reference f, ExprList el, SourcePosition posn) { + super(posn); + functionRef = f; + argList = el; + } - public R visit(Visitor v, A o) { - return v.visitCallExpr(this, o); - } + public R visit(Visitor v, A o) { + return v.visitCallExpr(this, o); + } - public Reference functionRef; - public ExprList argList; + public Reference functionRef; + public ExprList argList; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/CallStmt.java b/src/miniJava/AbstractSyntaxTrees/CallStmt.java index 2353a82..a056fdf 100644 --- a/src/miniJava/AbstractSyntaxTrees/CallStmt.java +++ b/src/miniJava/AbstractSyntaxTrees/CallStmt.java @@ -8,16 +8,16 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class CallStmt extends Statement { - public CallStmt(Reference m, ExprList el, SourcePosition posn) { - super(posn); - methodRef = m; - argList = el; - } + public CallStmt(Reference m, ExprList el, SourcePosition posn) { + super(posn); + methodRef = m; + argList = el; + } - public R visit(Visitor v, A o) { - return v.visitCallStmt(this, o); - } + public R visit(Visitor v, A o) { + return v.visitCallStmt(this, o); + } - public Reference methodRef; - public ExprList argList; + public Reference methodRef; + public ExprList argList; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/ClassDecl.java b/src/miniJava/AbstractSyntaxTrees/ClassDecl.java index d99706c..5b698ea 100644 --- a/src/miniJava/AbstractSyntaxTrees/ClassDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/ClassDecl.java @@ -9,17 +9,16 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class ClassDecl extends Declaration { - public ClassDecl(String cn, FieldDeclList fdl, MethodDeclList mdl, - SourcePosition posn) { - super(cn, null, posn); - fieldDeclList = fdl; - methodDeclList = mdl; - } + public ClassDecl(String cn, FieldDeclList fdl, MethodDeclList mdl, SourcePosition posn) { + super(cn, null, posn); + fieldDeclList = fdl; + methodDeclList = mdl; + } - public R visit(Visitor v, A o) { - return v.visitClassDecl(this, o); - } + public R visit(Visitor v, A o) { + return v.visitClassDecl(this, o); + } - public FieldDeclList fieldDeclList; - public MethodDeclList methodDeclList; + public FieldDeclList fieldDeclList; + public MethodDeclList methodDeclList; } diff --git a/src/miniJava/AbstractSyntaxTrees/ClassDeclList.java b/src/miniJava/AbstractSyntaxTrees/ClassDeclList.java index 495908d..02aa2c0 100644 --- a/src/miniJava/AbstractSyntaxTrees/ClassDeclList.java +++ b/src/miniJava/AbstractSyntaxTrees/ClassDeclList.java @@ -8,25 +8,25 @@ package miniJava.AbstractSyntaxTrees; import java.util.*; public class ClassDeclList implements Iterable { - public ClassDeclList() { - classDeclList = new ArrayList(); - } + public ClassDeclList() { + classDeclList = new ArrayList(); + } - public void add(ClassDecl cd) { - classDeclList.add(cd); - } + public void add(ClassDecl cd) { + classDeclList.add(cd); + } - public ClassDecl get(int i) { - return classDeclList.get(i); - } + public ClassDecl get(int i) { + return classDeclList.get(i); + } - public int size() { - return classDeclList.size(); - } + public int size() { + return classDeclList.size(); + } - public Iterator iterator() { - return classDeclList.iterator(); - } + public Iterator iterator() { + return classDeclList.iterator(); + } - private List classDeclList; + private List classDeclList; } diff --git a/src/miniJava/AbstractSyntaxTrees/ClassType.java b/src/miniJava/AbstractSyntaxTrees/ClassType.java index b1e8df9..fd8fe6e 100644 --- a/src/miniJava/AbstractSyntaxTrees/ClassType.java +++ b/src/miniJava/AbstractSyntaxTrees/ClassType.java @@ -8,18 +8,18 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class ClassType extends Type { - public ClassType(Identifier cn, SourcePosition posn) { - super(TypeKind.CLASS, posn); - className = cn; - } + public ClassType(Identifier cn, SourcePosition posn) { + super(TypeKind.CLASS, posn); + className = cn; + } - public R visit(Visitor v, A o) { - return v.visitClassType(this, o); - } - - public String toString() { - return "Class " + className.spelling; - } + public R visit(Visitor v, A o) { + return v.visitClassType(this, o); + } - public Identifier className; + public String toString() { + return "Class " + className.spelling; + } + + public Identifier className; } diff --git a/src/miniJava/AbstractSyntaxTrees/Declaration.java b/src/miniJava/AbstractSyntaxTrees/Declaration.java index 05f6021..7a01a80 100644 --- a/src/miniJava/AbstractSyntaxTrees/Declaration.java +++ b/src/miniJava/AbstractSyntaxTrees/Declaration.java @@ -11,14 +11,14 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public abstract class Declaration extends AST { - public Declaration(String name, Type type, SourcePosition posn) { - super(posn); - this.name = name; - this.type = type; - } + public Declaration(String name, Type type, SourcePosition posn) { + super(posn); + this.name = name; + this.type = type; + } - public RuntimeEntity entity; - public IdTable table; - public String name; - public Type type; + public RuntimeEntity entity; + public IdTable table; + public String name; + public Type type; } diff --git a/src/miniJava/AbstractSyntaxTrees/Declarators.java b/src/miniJava/AbstractSyntaxTrees/Declarators.java index e6c3a0e..6cbdba1 100644 --- a/src/miniJava/AbstractSyntaxTrees/Declarators.java +++ b/src/miniJava/AbstractSyntaxTrees/Declarators.java @@ -8,16 +8,15 @@ import miniJava.SyntacticAnalyzer.SourcePosition; */ public class Declarators { - public Declarators(boolean isPrivate, boolean isStatic, Type mt, - SourcePosition posn) { - this.isPrivate = isPrivate; - this.isStatic = isStatic; - this.mt = mt; - this.posn = posn; - } + public Declarators(boolean isPrivate, boolean isStatic, Type mt, SourcePosition posn) { + this.isPrivate = isPrivate; + this.isStatic = isStatic; + this.mt = mt; + this.posn = posn; + } - public boolean isPrivate; - public boolean isStatic; - public Type mt; - public SourcePosition posn; + public boolean isPrivate; + public boolean isStatic; + public Type mt; + public SourcePosition posn; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/ExprList.java b/src/miniJava/AbstractSyntaxTrees/ExprList.java index a30054f..77842a1 100644 --- a/src/miniJava/AbstractSyntaxTrees/ExprList.java +++ b/src/miniJava/AbstractSyntaxTrees/ExprList.java @@ -8,25 +8,25 @@ package miniJava.AbstractSyntaxTrees; import java.util.*; public class ExprList implements Iterable { - public ExprList() { - elist = new ArrayList(); - } + public ExprList() { + elist = new ArrayList(); + } - public void add(Expression e) { - elist.add(e); - } + public void add(Expression e) { + elist.add(e); + } - public Expression get(int i) { - return elist.get(i); - } + public Expression get(int i) { + return elist.get(i); + } - public int size() { - return elist.size(); - } + public int size() { + return elist.size(); + } - public Iterator iterator() { - return elist.iterator(); - } + public Iterator iterator() { + return elist.iterator(); + } - private List elist; + private List elist; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/Expression.java b/src/miniJava/AbstractSyntaxTrees/Expression.java index 34912ee..c06812d 100644 --- a/src/miniJava/AbstractSyntaxTrees/Expression.java +++ b/src/miniJava/AbstractSyntaxTrees/Expression.java @@ -9,8 +9,8 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public abstract class Expression extends AST { - public Expression(SourcePosition posn) { - super(posn); - } + public Expression(SourcePosition posn) { + super(posn); + } } diff --git a/src/miniJava/AbstractSyntaxTrees/FieldDecl.java b/src/miniJava/AbstractSyntaxTrees/FieldDecl.java index ee7e71e..ad087df 100644 --- a/src/miniJava/AbstractSyntaxTrees/FieldDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/FieldDecl.java @@ -9,20 +9,19 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class FieldDecl extends MemberDecl { - public FieldDecl(boolean isPrivate, boolean isStatic, Type t, String name, - SourcePosition posn) { - super(isPrivate, isStatic, t, name, posn); - } + public FieldDecl(boolean isPrivate, boolean isStatic, Type t, String name, SourcePosition posn) { + super(isPrivate, isStatic, t, name, posn); + } - public FieldDecl(MemberDecl md, SourcePosition posn) { - super(md, posn); - } + public FieldDecl(MemberDecl md, SourcePosition posn) { + super(md, posn); + } - public FieldDecl(Declarators d, String name) { - super(d.isPrivate, d.isStatic, d.mt, name, d.posn); - } + public FieldDecl(Declarators d, String name) { + super(d.isPrivate, d.isStatic, d.mt, name, d.posn); + } - public R visit(Visitor v, A o) { - return v.visitFieldDecl(this, o); - } + public R visit(Visitor v, A o) { + return v.visitFieldDecl(this, o); + } } diff --git a/src/miniJava/AbstractSyntaxTrees/FieldDeclList.java b/src/miniJava/AbstractSyntaxTrees/FieldDeclList.java index 03e8226..8179ef3 100644 --- a/src/miniJava/AbstractSyntaxTrees/FieldDeclList.java +++ b/src/miniJava/AbstractSyntaxTrees/FieldDeclList.java @@ -8,25 +8,25 @@ package miniJava.AbstractSyntaxTrees; import java.util.*; public class FieldDeclList implements Iterable { - public FieldDeclList() { - fieldDeclList = new ArrayList(); - } + public FieldDeclList() { + fieldDeclList = new ArrayList(); + } - public void add(FieldDecl cd) { - fieldDeclList.add(cd); - } + public void add(FieldDecl cd) { + fieldDeclList.add(cd); + } - public FieldDecl get(int i) { - return fieldDeclList.get(i); - } + public FieldDecl get(int i) { + return fieldDeclList.get(i); + } - public int size() { - return fieldDeclList.size(); - } + public int size() { + return fieldDeclList.size(); + } - public Iterator iterator() { - return fieldDeclList.iterator(); - } + public Iterator iterator() { + return fieldDeclList.iterator(); + } - private List fieldDeclList; + private List fieldDeclList; } diff --git a/src/miniJava/AbstractSyntaxTrees/IdRef.java b/src/miniJava/AbstractSyntaxTrees/IdRef.java index 696ec40..a6a033b 100644 --- a/src/miniJava/AbstractSyntaxTrees/IdRef.java +++ b/src/miniJava/AbstractSyntaxTrees/IdRef.java @@ -9,14 +9,14 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class IdRef extends Reference { - public IdRef(Identifier id, SourcePosition posn) { - super(posn); - this.id = id; - } + public IdRef(Identifier id, SourcePosition posn) { + super(posn); + this.id = id; + } - public R visit(Visitor v, A o) { - return v.visitIdRef(this, o); - } + public R visit(Visitor v, A o) { + return v.visitIdRef(this, o); + } - public Identifier id; + public Identifier id; } diff --git a/src/miniJava/AbstractSyntaxTrees/Identifier.java b/src/miniJava/AbstractSyntaxTrees/Identifier.java index dde46f7..38f04dc 100644 --- a/src/miniJava/AbstractSyntaxTrees/Identifier.java +++ b/src/miniJava/AbstractSyntaxTrees/Identifier.java @@ -10,14 +10,14 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class Identifier extends Terminal { - public Identifier(String s, SourcePosition posn) { - super(s, posn); - } + public Identifier(String s, SourcePosition posn) { + super(s, posn); + } - public R visit(Visitor v, A o) { - return v.visitIdentifier(this, o); - } + public R visit(Visitor v, A o) { + return v.visitIdentifier(this, o); + } - public Declaration decl; - public RuntimeEntity entity; + public Declaration decl; + public RuntimeEntity entity; } diff --git a/src/miniJava/AbstractSyntaxTrees/IfStmt.java b/src/miniJava/AbstractSyntaxTrees/IfStmt.java index f546cb2..d300377 100644 --- a/src/miniJava/AbstractSyntaxTrees/IfStmt.java +++ b/src/miniJava/AbstractSyntaxTrees/IfStmt.java @@ -8,25 +8,25 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class IfStmt extends Statement { - public IfStmt(Expression b, Statement t, Statement e, SourcePosition posn) { - super(posn); - cond = b; - thenStmt = t; - elseStmt = e; - } + public IfStmt(Expression b, Statement t, Statement e, SourcePosition posn) { + super(posn); + cond = b; + thenStmt = t; + elseStmt = e; + } - public IfStmt(Expression b, Statement t, SourcePosition posn) { - super(posn); - cond = b; - thenStmt = t; - elseStmt = null; - } + public IfStmt(Expression b, Statement t, SourcePosition posn) { + super(posn); + cond = b; + thenStmt = t; + elseStmt = null; + } - public R visit(Visitor v, A o) { - return v.visitIfStmt(this, o); - } + public R visit(Visitor v, A o) { + return v.visitIfStmt(this, o); + } - public Expression cond; - public Statement thenStmt; - public Statement elseStmt; + public Expression cond; + public Statement thenStmt; + public Statement elseStmt; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/IndexedRef.java b/src/miniJava/AbstractSyntaxTrees/IndexedRef.java index d009e2c..fb55a07 100644 --- a/src/miniJava/AbstractSyntaxTrees/IndexedRef.java +++ b/src/miniJava/AbstractSyntaxTrees/IndexedRef.java @@ -9,16 +9,16 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class IndexedRef extends Reference { - public IndexedRef(Reference ref, Expression expr, SourcePosition posn) { - super(posn); - this.ref = ref; - this.indexExpr = expr; - } + public IndexedRef(Reference ref, Expression expr, SourcePosition posn) { + super(posn); + this.ref = ref; + this.indexExpr = expr; + } - public R visit(Visitor v, A o) { - return v.visitIndexedRef(this, o); - } + public R visit(Visitor v, A o) { + return v.visitIndexedRef(this, o); + } - public Reference ref; - public Expression indexExpr; + public Reference ref; + public Expression indexExpr; } diff --git a/src/miniJava/AbstractSyntaxTrees/IntLiteral.java b/src/miniJava/AbstractSyntaxTrees/IntLiteral.java index 8b97e8e..69dfe49 100644 --- a/src/miniJava/AbstractSyntaxTrees/IntLiteral.java +++ b/src/miniJava/AbstractSyntaxTrees/IntLiteral.java @@ -9,11 +9,11 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class IntLiteral extends Literal { - public IntLiteral(String s, SourcePosition posn) { - super(s, posn); - } + public IntLiteral(String s, SourcePosition posn) { + super(s, posn); + } - public R visit(Visitor v, A o) { - return v.visitIntLiteral(this, o); - } + public R visit(Visitor v, A o) { + return v.visitIntLiteral(this, o); + } } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/Literal.java b/src/miniJava/AbstractSyntaxTrees/Literal.java index ae727fc..e307251 100644 --- a/src/miniJava/AbstractSyntaxTrees/Literal.java +++ b/src/miniJava/AbstractSyntaxTrees/Literal.java @@ -9,7 +9,7 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public abstract class Literal extends Terminal { - public Literal(String spelling, SourcePosition posn) { - super(spelling, posn); - } + public Literal(String spelling, SourcePosition posn) { + super(spelling, posn); + } } diff --git a/src/miniJava/AbstractSyntaxTrees/LiteralExpr.java b/src/miniJava/AbstractSyntaxTrees/LiteralExpr.java index 70aad01..3f7fbe0 100644 --- a/src/miniJava/AbstractSyntaxTrees/LiteralExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/LiteralExpr.java @@ -8,14 +8,14 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class LiteralExpr extends Expression { - public LiteralExpr(Literal c, SourcePosition posn) { - super(posn); - literal = c; - } + public LiteralExpr(Literal c, SourcePosition posn) { + super(posn); + literal = c; + } - public R visit(Visitor v, A o) { - return v.visitLiteralExpr(this, o); - } + public R visit(Visitor v, A o) { + return v.visitLiteralExpr(this, o); + } - public Literal literal; + public Literal literal; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/LocalDecl.java b/src/miniJava/AbstractSyntaxTrees/LocalDecl.java index 8968ac0..0fa9603 100644 --- a/src/miniJava/AbstractSyntaxTrees/LocalDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/LocalDecl.java @@ -9,8 +9,8 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public abstract class LocalDecl extends Declaration { - public LocalDecl(String name, Type t, SourcePosition posn) { - super(name, t, posn); - } + public LocalDecl(String name, Type t, SourcePosition posn) { + super(name, t, posn); + } } diff --git a/src/miniJava/AbstractSyntaxTrees/MemberDecl.java b/src/miniJava/AbstractSyntaxTrees/MemberDecl.java index 5a2df13..19998f5 100644 --- a/src/miniJava/AbstractSyntaxTrees/MemberDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/MemberDecl.java @@ -9,19 +9,18 @@ import miniJava.SyntacticAnalyzer.SourcePosition; abstract public class MemberDecl extends Declaration { - public MemberDecl(boolean isPrivate, boolean isStatic, Type mt, - String name, SourcePosition posn) { - super(name, mt, posn); - this.isPrivate = isPrivate; - this.isStatic = isStatic; - } + public MemberDecl(boolean isPrivate, boolean isStatic, Type mt, String name, SourcePosition posn) { + super(name, mt, posn); + this.isPrivate = isPrivate; + this.isStatic = isStatic; + } - public MemberDecl(MemberDecl md, SourcePosition posn) { - super(md.name, md.type, posn); - this.isPrivate = md.isPrivate; - this.isStatic = md.isStatic; - } + public MemberDecl(MemberDecl md, SourcePosition posn) { + super(md.name, md.type, posn); + this.isPrivate = md.isPrivate; + this.isStatic = md.isStatic; + } - public boolean isPrivate; - public boolean isStatic; + public boolean isPrivate; + public boolean isStatic; } diff --git a/src/miniJava/AbstractSyntaxTrees/MethodDecl.java b/src/miniJava/AbstractSyntaxTrees/MethodDecl.java index 71c58a2..bc46e1d 100644 --- a/src/miniJava/AbstractSyntaxTrees/MethodDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/MethodDecl.java @@ -9,19 +9,18 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class MethodDecl extends MemberDecl { - public MethodDecl(MemberDecl md, ParameterDeclList pl, StatementList sl, - Expression e, SourcePosition posn) { - super(md, posn); - parameterDeclList = pl; - statementList = sl; - returnExp = e; - } + public MethodDecl(MemberDecl md, ParameterDeclList pl, StatementList sl, Expression e, SourcePosition posn) { + super(md, posn); + parameterDeclList = pl; + statementList = sl; + returnExp = e; + } - public R visit(Visitor v, A o) { - return v.visitMethodDecl(this, o); - } + public R visit(Visitor v, A o) { + return v.visitMethodDecl(this, o); + } - public ParameterDeclList parameterDeclList; - public StatementList statementList; - public Expression returnExp; + public ParameterDeclList parameterDeclList; + public StatementList statementList; + public Expression returnExp; } diff --git a/src/miniJava/AbstractSyntaxTrees/MethodDeclList.java b/src/miniJava/AbstractSyntaxTrees/MethodDeclList.java index bf79e72..baff8b3 100644 --- a/src/miniJava/AbstractSyntaxTrees/MethodDeclList.java +++ b/src/miniJava/AbstractSyntaxTrees/MethodDeclList.java @@ -8,25 +8,25 @@ package miniJava.AbstractSyntaxTrees; import java.util.*; public class MethodDeclList implements Iterable { - public MethodDeclList() { - methodDeclList = new ArrayList(); - } + public MethodDeclList() { + methodDeclList = new ArrayList(); + } - public void add(MethodDecl cd) { - methodDeclList.add(cd); - } + public void add(MethodDecl cd) { + methodDeclList.add(cd); + } - public MethodDecl get(int i) { - return methodDeclList.get(i); - } + public MethodDecl get(int i) { + return methodDeclList.get(i); + } - public int size() { - return methodDeclList.size(); - } + public int size() { + return methodDeclList.size(); + } - public Iterator iterator() { - return methodDeclList.iterator(); - } + public Iterator iterator() { + return methodDeclList.iterator(); + } - private List methodDeclList; + private List methodDeclList; } diff --git a/src/miniJava/AbstractSyntaxTrees/NewArrayExpr.java b/src/miniJava/AbstractSyntaxTrees/NewArrayExpr.java index 52a8934..248cf08 100644 --- a/src/miniJava/AbstractSyntaxTrees/NewArrayExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/NewArrayExpr.java @@ -8,16 +8,16 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class NewArrayExpr extends NewExpr { - public NewArrayExpr(Type et, Expression e, SourcePosition posn) { - super(posn); - eltType = et; - sizeExpr = e; - } + public NewArrayExpr(Type et, Expression e, SourcePosition posn) { + super(posn); + eltType = et; + sizeExpr = e; + } - public R visit(Visitor v, A o) { - return v.visitNewArrayExpr(this, o); - } + public R visit(Visitor v, A o) { + return v.visitNewArrayExpr(this, o); + } - public Type eltType; - public Expression sizeExpr; + public Type eltType; + public Expression sizeExpr; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/NewExpr.java b/src/miniJava/AbstractSyntaxTrees/NewExpr.java index 9842110..ad77dad 100644 --- a/src/miniJava/AbstractSyntaxTrees/NewExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/NewExpr.java @@ -9,7 +9,7 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public abstract class NewExpr extends Expression { - public NewExpr(SourcePosition posn) { - super(posn); - } + public NewExpr(SourcePosition posn) { + super(posn); + } } diff --git a/src/miniJava/AbstractSyntaxTrees/NewObjectExpr.java b/src/miniJava/AbstractSyntaxTrees/NewObjectExpr.java index 82ea4ea..0b91cca 100644 --- a/src/miniJava/AbstractSyntaxTrees/NewObjectExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/NewObjectExpr.java @@ -8,14 +8,14 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class NewObjectExpr extends NewExpr { - public NewObjectExpr(ClassType ct, SourcePosition posn) { - super(posn); - classtype = ct; - } + public NewObjectExpr(ClassType ct, SourcePosition posn) { + super(posn); + classtype = ct; + } - public R visit(Visitor v, A o) { - return v.visitNewObjectExpr(this, o); - } + public R visit(Visitor v, A o) { + return v.visitNewObjectExpr(this, o); + } - public ClassType classtype; + public ClassType classtype; } diff --git a/src/miniJava/AbstractSyntaxTrees/Operator.java b/src/miniJava/AbstractSyntaxTrees/Operator.java index f570d02..e5833cd 100644 --- a/src/miniJava/AbstractSyntaxTrees/Operator.java +++ b/src/miniJava/AbstractSyntaxTrees/Operator.java @@ -10,13 +10,13 @@ import miniJava.SyntacticAnalyzer.Token; public class Operator extends Terminal { - public Operator(Token t, SourcePosition posn) { - super(t.spelling, posn); - } + public Operator(Token t, SourcePosition posn) { + super(t.spelling, posn); + } - public R visit(Visitor v, A o) { - return v.visitOperator(this, o); - } + public R visit(Visitor v, A o) { + return v.visitOperator(this, o); + } - public Token token; + public Token token; } diff --git a/src/miniJava/AbstractSyntaxTrees/Package.java b/src/miniJava/AbstractSyntaxTrees/Package.java index 638d322..96098cb 100644 --- a/src/miniJava/AbstractSyntaxTrees/Package.java +++ b/src/miniJava/AbstractSyntaxTrees/Package.java @@ -9,14 +9,14 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class Package extends AST { - public Package(ClassDeclList cdl, SourcePosition posn) { - super(posn); - classDeclList = cdl; - } + public Package(ClassDeclList cdl, SourcePosition posn) { + super(posn); + classDeclList = cdl; + } - public R visit(Visitor v, A o) { - return v.visitPackage(this, o); - } + public R visit(Visitor v, A o) { + return v.visitPackage(this, o); + } - public ClassDeclList classDeclList; + public ClassDeclList classDeclList; } diff --git a/src/miniJava/AbstractSyntaxTrees/ParameterDecl.java b/src/miniJava/AbstractSyntaxTrees/ParameterDecl.java index ba454e2..ba72fea 100644 --- a/src/miniJava/AbstractSyntaxTrees/ParameterDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/ParameterDecl.java @@ -9,11 +9,11 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class ParameterDecl extends LocalDecl { - public ParameterDecl(Type t, String name, SourcePosition posn) { - super(name, t, posn); - } + public ParameterDecl(Type t, String name, SourcePosition posn) { + super(name, t, posn); + } - public R visit(Visitor v, A o) { - return v.visitParameterDecl(this, o); - } + public R visit(Visitor v, A o) { + return v.visitParameterDecl(this, o); + } } diff --git a/src/miniJava/AbstractSyntaxTrees/ParameterDeclList.java b/src/miniJava/AbstractSyntaxTrees/ParameterDeclList.java index 2b80ada..a770f2c 100644 --- a/src/miniJava/AbstractSyntaxTrees/ParameterDeclList.java +++ b/src/miniJava/AbstractSyntaxTrees/ParameterDeclList.java @@ -8,25 +8,25 @@ package miniJava.AbstractSyntaxTrees; import java.util.*; public class ParameterDeclList implements Iterable { - public ParameterDeclList() { - parameterDeclList = new ArrayList(); - } + public ParameterDeclList() { + parameterDeclList = new ArrayList(); + } - public void add(ParameterDecl s) { - parameterDeclList.add(s); - } + public void add(ParameterDecl s) { + parameterDeclList.add(s); + } - public ParameterDecl get(int i) { - return parameterDeclList.get(i); - } + public ParameterDecl get(int i) { + return parameterDeclList.get(i); + } - public int size() { - return parameterDeclList.size(); - } + public int size() { + return parameterDeclList.size(); + } - public Iterator iterator() { - return parameterDeclList.iterator(); - } + public Iterator iterator() { + return parameterDeclList.iterator(); + } - private List parameterDeclList; + private List parameterDeclList; } diff --git a/src/miniJava/AbstractSyntaxTrees/QualifiedRef.java b/src/miniJava/AbstractSyntaxTrees/QualifiedRef.java index 74192a7..9a29b05 100644 --- a/src/miniJava/AbstractSyntaxTrees/QualifiedRef.java +++ b/src/miniJava/AbstractSyntaxTrees/QualifiedRef.java @@ -9,17 +9,17 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class QualifiedRef extends Reference { - public QualifiedRef(Reference ref, Identifier id, SourcePosition posn) { - super(posn); - this.ref = ref; - this.id = id; - } + public QualifiedRef(Reference ref, Identifier id, SourcePosition posn) { + super(posn); + this.ref = ref; + this.id = id; + } - @Override - public R visit(Visitor v, A o) { - return v.visitQualifiedRef(this, o); - } + @Override + public R visit(Visitor v, A o) { + return v.visitQualifiedRef(this, o); + } - public Reference ref; - public Identifier id; + public Reference ref; + public Identifier id; } diff --git a/src/miniJava/AbstractSyntaxTrees/RefExpr.java b/src/miniJava/AbstractSyntaxTrees/RefExpr.java index 2d570e2..d85e4e5 100644 --- a/src/miniJava/AbstractSyntaxTrees/RefExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/RefExpr.java @@ -8,14 +8,14 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class RefExpr extends Expression { - public RefExpr(Reference r, SourcePosition posn) { - super(posn); - ref = r; - } + public RefExpr(Reference r, SourcePosition posn) { + super(posn); + ref = r; + } - public R visit(Visitor v, A o) { - return v.visitRefExpr(this, o); - } + public R visit(Visitor v, A o) { + return v.visitRefExpr(this, o); + } - public Reference ref; + public Reference ref; } diff --git a/src/miniJava/AbstractSyntaxTrees/Reference.java b/src/miniJava/AbstractSyntaxTrees/Reference.java index c373659..5387c34 100644 --- a/src/miniJava/AbstractSyntaxTrees/Reference.java +++ b/src/miniJava/AbstractSyntaxTrees/Reference.java @@ -9,11 +9,11 @@ import miniJava.CodeGenerator.RuntimeEntity; import miniJava.SyntacticAnalyzer.SourcePosition; public abstract class Reference extends AST { - public Reference(SourcePosition posn) { - super(posn); - } + public Reference(SourcePosition posn) { + super(posn); + } - public String spelling; - public Declaration decl; - public RuntimeEntity entity; + public String spelling; + public Declaration decl; + public RuntimeEntity entity; } diff --git a/src/miniJava/AbstractSyntaxTrees/Statement.java b/src/miniJava/AbstractSyntaxTrees/Statement.java index 6d332b0..1fd8e93 100644 --- a/src/miniJava/AbstractSyntaxTrees/Statement.java +++ b/src/miniJava/AbstractSyntaxTrees/Statement.java @@ -9,8 +9,8 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public abstract class Statement extends AST { - public Statement(SourcePosition posn) { - super(posn); - } + public Statement(SourcePosition posn) { + super(posn); + } } diff --git a/src/miniJava/AbstractSyntaxTrees/StatementList.java b/src/miniJava/AbstractSyntaxTrees/StatementList.java index d2fbfb8..a31e40c 100644 --- a/src/miniJava/AbstractSyntaxTrees/StatementList.java +++ b/src/miniJava/AbstractSyntaxTrees/StatementList.java @@ -8,25 +8,25 @@ package miniJava.AbstractSyntaxTrees; import java.util.*; public class StatementList implements Iterable { - public StatementList() { - slist = new ArrayList(); - } + public StatementList() { + slist = new ArrayList(); + } - public void add(Statement s) { - slist.add(s); - } + public void add(Statement s) { + slist.add(s); + } - public Statement get(int i) { - return slist.get(i); - } + public Statement get(int i) { + return slist.get(i); + } - public int size() { - return slist.size(); - } + public int size() { + return slist.size(); + } - public Iterator iterator() { - return slist.iterator(); - } + public Iterator iterator() { + return slist.iterator(); + } - private List slist; + private List slist; } diff --git a/src/miniJava/AbstractSyntaxTrees/Terminal.java b/src/miniJava/AbstractSyntaxTrees/Terminal.java index 4ee4f21..9328ff8 100644 --- a/src/miniJava/AbstractSyntaxTrees/Terminal.java +++ b/src/miniJava/AbstractSyntaxTrees/Terminal.java @@ -9,10 +9,10 @@ import miniJava.SyntacticAnalyzer.SourcePosition; abstract public class Terminal extends AST { - public Terminal(String s, SourcePosition posn) { - super(posn); - spelling = s; - } + public Terminal(String s, SourcePosition posn) { + super(posn); + spelling = s; + } - public String spelling; + public String spelling; } diff --git a/src/miniJava/AbstractSyntaxTrees/ThisRef.java b/src/miniJava/AbstractSyntaxTrees/ThisRef.java index 874a590..81e1679 100644 --- a/src/miniJava/AbstractSyntaxTrees/ThisRef.java +++ b/src/miniJava/AbstractSyntaxTrees/ThisRef.java @@ -9,13 +9,13 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class ThisRef extends Reference { - public ThisRef(SourcePosition posn) { - super(posn); - } + public ThisRef(SourcePosition posn) { + super(posn); + } - @Override - public R visit(Visitor v, A o) { - return v.visitThisRef(this, o); - } + @Override + public R visit(Visitor v, A o) { + return v.visitThisRef(this, o); + } } diff --git a/src/miniJava/AbstractSyntaxTrees/Type.java b/src/miniJava/AbstractSyntaxTrees/Type.java index 463bfb6..4cfab37 100644 --- a/src/miniJava/AbstractSyntaxTrees/Type.java +++ b/src/miniJava/AbstractSyntaxTrees/Type.java @@ -9,11 +9,11 @@ import miniJava.SyntacticAnalyzer.SourcePosition; abstract public class Type extends AST { - public Type(TypeKind typ, SourcePosition posn) { - super(posn); - typeKind = typ; - } + public Type(TypeKind typ, SourcePosition posn) { + super(posn); + typeKind = typ; + } - public TypeKind typeKind; + public TypeKind typeKind; } diff --git a/src/miniJava/AbstractSyntaxTrees/TypeKind.java b/src/miniJava/AbstractSyntaxTrees/TypeKind.java index b9421bb..2897110 100644 --- a/src/miniJava/AbstractSyntaxTrees/TypeKind.java +++ b/src/miniJava/AbstractSyntaxTrees/TypeKind.java @@ -6,5 +6,5 @@ package miniJava.AbstractSyntaxTrees; public enum TypeKind { - VOID, INT, BOOLEAN, CLASS, ARRAY, UNSUPPORTED, ERROR; + VOID, INT, BOOLEAN, CLASS, ARRAY, UNSUPPORTED, ERROR; } diff --git a/src/miniJava/AbstractSyntaxTrees/UnaryExpr.java b/src/miniJava/AbstractSyntaxTrees/UnaryExpr.java index ecf8504..6b848e9 100644 --- a/src/miniJava/AbstractSyntaxTrees/UnaryExpr.java +++ b/src/miniJava/AbstractSyntaxTrees/UnaryExpr.java @@ -8,16 +8,16 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class UnaryExpr extends Expression { - public UnaryExpr(Operator o, Expression e, SourcePosition posn) { - super(posn); - operator = o; - expr = e; - } + public UnaryExpr(Operator o, Expression e, SourcePosition posn) { + super(posn); + operator = o; + expr = e; + } - public R visit(Visitor v, A o) { - return v.visitUnaryExpr(this, o); - } + public R visit(Visitor v, A o) { + return v.visitUnaryExpr(this, o); + } - public Operator operator; - public Expression expr; + public Operator operator; + public Expression expr; } \ No newline at end of file diff --git a/src/miniJava/AbstractSyntaxTrees/VarDecl.java b/src/miniJava/AbstractSyntaxTrees/VarDecl.java index 8231714..274fdff 100644 --- a/src/miniJava/AbstractSyntaxTrees/VarDecl.java +++ b/src/miniJava/AbstractSyntaxTrees/VarDecl.java @@ -9,11 +9,11 @@ import miniJava.SyntacticAnalyzer.SourcePosition; public class VarDecl extends LocalDecl { - public VarDecl(Type t, String name, SourcePosition posn) { - super(name, t, posn); - } + public VarDecl(Type t, String name, SourcePosition posn) { + super(name, t, posn); + } - public R visit(Visitor v, A o) { - return v.visitVarDecl(this, o); - } + public R visit(Visitor v, A o) { + return v.visitVarDecl(this, o); + } } diff --git a/src/miniJava/AbstractSyntaxTrees/VarDeclStmt.java b/src/miniJava/AbstractSyntaxTrees/VarDeclStmt.java index 56db252..e06a3a8 100644 --- a/src/miniJava/AbstractSyntaxTrees/VarDeclStmt.java +++ b/src/miniJava/AbstractSyntaxTrees/VarDeclStmt.java @@ -8,16 +8,16 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class VarDeclStmt extends Statement { - public VarDeclStmt(VarDecl vd, Expression e, SourcePosition posn) { - super(posn); - varDecl = vd; - initExp = e; - } + public VarDeclStmt(VarDecl vd, Expression e, SourcePosition posn) { + super(posn); + varDecl = vd; + initExp = e; + } - public R visit(Visitor v, A o) { - return v.visitVardeclStmt(this, o); - } + public R visit(Visitor v, A o) { + return v.visitVardeclStmt(this, o); + } - public VarDecl varDecl; - public Expression initExp; + public VarDecl varDecl; + public Expression initExp; } diff --git a/src/miniJava/AbstractSyntaxTrees/Visitor.java b/src/miniJava/AbstractSyntaxTrees/Visitor.java index 08c2541..da10c46 100644 --- a/src/miniJava/AbstractSyntaxTrees/Visitor.java +++ b/src/miniJava/AbstractSyntaxTrees/Visitor.java @@ -11,70 +11,70 @@ package miniJava.AbstractSyntaxTrees; */ public interface Visitor { - // Package - public ResultType visitPackage(Package prog, ArgType arg); + // Package + public ResultType visitPackage(Package prog, ArgType arg); - // Declarations - public ResultType visitClassDecl(ClassDecl cd, ArgType arg); + // Declarations + public ResultType visitClassDecl(ClassDecl cd, ArgType arg); - public ResultType visitFieldDecl(FieldDecl fd, ArgType arg); + public ResultType visitFieldDecl(FieldDecl fd, ArgType arg); - public ResultType visitMethodDecl(MethodDecl md, ArgType arg); + public ResultType visitMethodDecl(MethodDecl md, ArgType arg); - public ResultType visitParameterDecl(ParameterDecl pd, ArgType arg); + public ResultType visitParameterDecl(ParameterDecl pd, ArgType arg); - public ResultType visitVarDecl(VarDecl decl, ArgType arg); + public ResultType visitVarDecl(VarDecl decl, ArgType arg); - // Types - public ResultType visitBaseType(BaseType type, ArgType arg); + // Types + public ResultType visitBaseType(BaseType type, ArgType arg); - public ResultType visitClassType(ClassType type, ArgType arg); + public ResultType visitClassType(ClassType type, ArgType arg); - public ResultType visitArrayType(ArrayType type, ArgType arg); + public ResultType visitArrayType(ArrayType type, ArgType arg); - // Statements - public ResultType visitBlockStmt(BlockStmt stmt, ArgType arg); + // Statements + public ResultType visitBlockStmt(BlockStmt stmt, ArgType arg); - public ResultType visitVardeclStmt(VarDeclStmt stmt, ArgType arg); + public ResultType visitVardeclStmt(VarDeclStmt stmt, ArgType arg); - public ResultType visitAssignStmt(AssignStmt stmt, ArgType arg); + public ResultType visitAssignStmt(AssignStmt stmt, ArgType arg); - public ResultType visitCallStmt(CallStmt stmt, ArgType arg); + public ResultType visitCallStmt(CallStmt stmt, ArgType arg); - public ResultType visitIfStmt(IfStmt stmt, ArgType arg); + public ResultType visitIfStmt(IfStmt stmt, ArgType arg); - public ResultType visitWhileStmt(WhileStmt stmt, ArgType arg); + public ResultType visitWhileStmt(WhileStmt stmt, ArgType arg); - // Expressions - public ResultType visitUnaryExpr(UnaryExpr expr, ArgType arg); + // Expressions + public ResultType visitUnaryExpr(UnaryExpr expr, ArgType arg); - public ResultType visitBinaryExpr(BinaryExpr expr, ArgType arg); + public ResultType visitBinaryExpr(BinaryExpr expr, ArgType arg); - public ResultType visitRefExpr(RefExpr expr, ArgType arg); + public ResultType visitRefExpr(RefExpr expr, ArgType arg); - public ResultType visitCallExpr(CallExpr expr, ArgType arg); + public ResultType visitCallExpr(CallExpr expr, ArgType arg); - public ResultType visitLiteralExpr(LiteralExpr expr, ArgType arg); + public ResultType visitLiteralExpr(LiteralExpr expr, ArgType arg); - public ResultType visitNewObjectExpr(NewObjectExpr expr, ArgType arg); + public ResultType visitNewObjectExpr(NewObjectExpr expr, ArgType arg); - public ResultType visitNewArrayExpr(NewArrayExpr expr, ArgType arg); + public ResultType visitNewArrayExpr(NewArrayExpr expr, ArgType arg); - // References - public ResultType visitQualifiedRef(QualifiedRef ref, ArgType arg); + // References + public ResultType visitQualifiedRef(QualifiedRef ref, ArgType arg); - public ResultType visitIndexedRef(IndexedRef ref, ArgType arg); + public ResultType visitIndexedRef(IndexedRef ref, ArgType arg); - public ResultType visitIdRef(IdRef ref, ArgType arg); + public ResultType visitIdRef(IdRef ref, ArgType arg); - public ResultType visitThisRef(ThisRef ref, ArgType arg); + public ResultType visitThisRef(ThisRef ref, ArgType arg); - // Terminals - public ResultType visitIdentifier(Identifier id, ArgType arg); + // Terminals + public ResultType visitIdentifier(Identifier id, ArgType arg); - public ResultType visitOperator(Operator op, ArgType arg); + public ResultType visitOperator(Operator op, ArgType arg); - public ResultType visitIntLiteral(IntLiteral num, ArgType arg); + public ResultType visitIntLiteral(IntLiteral num, ArgType arg); - public ResultType visitBooleanLiteral(BooleanLiteral bool, ArgType arg); + public ResultType visitBooleanLiteral(BooleanLiteral bool, ArgType arg); } diff --git a/src/miniJava/AbstractSyntaxTrees/WhileStmt.java b/src/miniJava/AbstractSyntaxTrees/WhileStmt.java index 88d3a22..da7ceeb 100644 --- a/src/miniJava/AbstractSyntaxTrees/WhileStmt.java +++ b/src/miniJava/AbstractSyntaxTrees/WhileStmt.java @@ -8,16 +8,16 @@ package miniJava.AbstractSyntaxTrees; import miniJava.SyntacticAnalyzer.SourcePosition; public class WhileStmt extends Statement { - public WhileStmt(Expression b, Statement s, SourcePosition posn) { - super(posn); - cond = b; - body = s; - } + public WhileStmt(Expression b, Statement s, SourcePosition posn) { + super(posn); + cond = b; + body = s; + } - public R visit(Visitor v, A o) { - return v.visitWhileStmt(this, o); - } + public R visit(Visitor v, A o) { + return v.visitWhileStmt(this, o); + } - public Expression cond; - public Statement body; + public Expression cond; + public Statement body; } diff --git a/src/miniJava/CodeGenerator/Code.java b/src/miniJava/CodeGenerator/Code.java index fa32703..21fd113 100644 --- a/src/miniJava/CodeGenerator/Code.java +++ b/src/miniJava/CodeGenerator/Code.java @@ -4,52 +4,53 @@ import mJAM.Machine; import miniJava.AbstractSyntaxTrees.*; public class Code { - - public boolean addr; - public Declaration decl; - - /** - * If addr true, returns the address of the declaration. - * Otherwise, uses the size of the declaration in its place. - * @param op - * @param decl - * @param addr - */ - public Code(Declaration decl, boolean addr) { - this.decl = decl; - this.addr = addr; - } - - /** - * - * @param index - */ - public void modify(int instr) { - // Setup size - switch(decl.type.typeKind) { - case ARRAY: - case CLASS: - Machine.code[instr].n = Machine.addressSize; - case INT: - Machine.code[instr].n = Machine.integerSize; - case BOOLEAN: - Machine.code[instr].n = Machine.booleanSize; - case VOID: - Machine.code[instr].n = 0; - default: - Machine.code[instr].n = -1; - } - - // Setup displacement - if(addr) { - Machine.code[instr].d += decl.entity.addr; - } else { - Machine.code[instr].d += decl.entity.size; - } - - // Setup register - Machine.code[instr].r = decl.entity.reg.ordinal(); - } + public boolean addr; + public Declaration decl; + + /** + * If addr true, returns the address of the declaration. Otherwise, uses the + * size of the declaration in its place. + * + * @param op + * @param decl + * @param addr + */ + public Code(Declaration decl, boolean addr) { + this.decl = decl; + this.addr = addr; + } + + /** + * + * @param index + */ + public void modify(int instr) { + + // Setup size + switch (decl.type.typeKind) { + case ARRAY: + case CLASS: + Machine.code[instr].n = Machine.addressSize; + case INT: + Machine.code[instr].n = Machine.integerSize; + case BOOLEAN: + Machine.code[instr].n = Machine.booleanSize; + case VOID: + Machine.code[instr].n = 0; + default: + Machine.code[instr].n = -1; + } + + // Setup displacement + if (addr) { + Machine.code[instr].d += decl.entity.addr; + } else { + Machine.code[instr].d += decl.entity.size; + } + + // Setup register + Machine.code[instr].r = decl.entity.reg.ordinal(); + } } diff --git a/src/miniJava/CodeGenerator/Encoder.java b/src/miniJava/CodeGenerator/Encoder.java index 6ee76b6..20d7d1d 100644 --- a/src/miniJava/CodeGenerator/Encoder.java +++ b/src/miniJava/CodeGenerator/Encoder.java @@ -9,716 +9,709 @@ import miniJava.AbstractSyntaxTrees.Package; import miniJava.ContextualAnalyzer.Analyzer; public class Encoder implements Visitor { - - // Keeps track of variables placed on the stack - private int methodDataOffset = 0; - - // Maintains data to correct once completed traversal - private HashMap patches = new HashMap<>(); - - - // ///////////////////////////////////////////////////////////////////////////// - // - // PACKAGE - // - // ///////////////////////////////////////////////////////////////////////////// - @Override - public Object visitPackage(Package prog, Integer arg) { - - Machine.initCodeGen(); - - // Initialize all static fields - int staticFieldsSize = 0; - for(ClassDecl cd : prog.classDeclList) { - for(int i = 0; i < cd.fieldDeclList.size(); i++) { - FieldDecl fd = cd.fieldDeclList.get(i); - if(fd.isStatic) { - int size = getSize(fd.type); - fd.entity = new RuntimeEntity(size, staticFieldsSize, Reg.SB); - staticFieldsSize += size; - } - } - } - - if(staticFieldsSize > 0) { - Machine.emit(Op.PUSH, staticFieldsSize); - } - - // Build Classes - for(ClassDecl cd : prog.classDeclList) { - int cdPatch = Machine.nextInstrAddr(); - Machine.emit(Op.JUMP, Reg.CB, 0); - cd.visit(this, cdPatch); - } - - // Build main function - methodDataOffset = Machine.linkDataSize; - int mainPatch = Machine.nextInstrAddr(); - Machine.emit(Op.JUMP, Reg.CB, 0); - Analyzer.main.visit(this, null); + // Keeps track of variables placed on the stack + private int methodDataOffset = 0; - // Run main function - int mainLabel = Machine.nextInstrAddr(); - RuntimeEntity main = Analyzer.main.entity; + // Maintains data to correct once completed traversal + private HashMap patches = new HashMap<>(); - Machine.emit(Op.LOADL, Machine.nullRep); - Machine.emit(Op.CALL, Reg.CB, main.addr); - Machine.emit(Machine.Op.HALT, 0 ,0, 0); - Machine.patch(mainPatch, mainLabel); - - // Patch up - for(Integer instr : patches.keySet()) { - Code c = patches.get(instr); - c.modify(instr); - } - - return null; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // DECLARATIONS - // - // ///////////////////////////////////////////////////////////////////////////// + // ///////////////////////////////////////////////////////////////////////////// + // + // PACKAGE + // + // ///////////////////////////////////////////////////////////////////////////// - @Override - public Object visitClassDecl(ClassDecl cd, Integer patch) { - - // Get size of class - int size = 0; - for(FieldDecl fd : cd.fieldDeclList) { - if(!fd.isStatic) { - fd.visit(this, size); - size += fd.entity.size; - } - } - - // Build Instance Methods - for(MethodDecl md : cd.methodDeclList) { - if(md != Analyzer.main) { - md.visit(this, null); - } - } - - // Build Class Descriptor - int addr = Machine.nextInstrAddr(); - Machine.patch(patch, addr); - - Machine.emit(Op.LOADL, -1); // No superclasses allowed - Machine.emit(Op.LOADL, size); // Size of class - Machine.emit(Op.LOADA, Reg.CB, addr); // Address of class - - // Save entity - cd.entity = new RuntimeEntity(size, addr, Reg.CB); - - return null; - } + @Override + public Object visitPackage(Package prog, Integer arg) { - @Override - public Object visitFieldDecl(FieldDecl fd, Integer offset) { - - // Only non-static fields should ever reach this method - int size = getSize(fd.type); - fd.entity = new RuntimeEntity(size, offset, Reg.OB); - - return null; - } + Machine.initCodeGen(); - @Override - public Object visitMethodDecl(MethodDecl md, Integer arg) { - - // Reset for next local LB - methodDataOffset = Machine.linkDataSize; - - // Save Entity - int size = getSize(md.type); - int addr = Machine.nextInstrAddr(); - md.entity = new RuntimeEntity(size, addr, Reg.CB); - - // Setup parameters - int parameterSize = 0; - for(ParameterDecl pd : md.parameterDeclList) { - parameterSize += getSize(pd.type); - pd.visit(this, -parameterSize); - } - - // Build Body - for(Statement s : md.statementList) { - s.visit(this, null); - } - - // Setup Return - if(md.returnExp != null) { - md.returnExp.visit(this, null); - } - - Machine.emit(Op.RETURN, size, 0, parameterSize); + // Initialize all static fields + int staticFieldsSize = 0; + for (ClassDecl cd : prog.classDeclList) { + for (int i = 0; i < cd.fieldDeclList.size(); i++) { + FieldDecl fd = cd.fieldDeclList.get(i); + if (fd.isStatic) { + int size = getSize(fd.type); + fd.entity = new RuntimeEntity(size, staticFieldsSize, Reg.SB); + staticFieldsSize += size; + } + } + } - return null; - } + if (staticFieldsSize > 0) { + Machine.emit(Op.PUSH, staticFieldsSize); + } - @Override - public Object visitParameterDecl(ParameterDecl pd, Integer offset) { - - // Builds runtime entity (should be negative of LB) - int size = getSize(pd.type); - pd.entity = new RuntimeEntity(size, offset, Reg.LB); - - return null; - } + // Build Classes + for (ClassDecl cd : prog.classDeclList) { + int cdPatch = Machine.nextInstrAddr(); + Machine.emit(Op.JUMP, Reg.CB, 0); + cd.visit(this, cdPatch); + } - @Override - public Object visitVarDecl(VarDecl decl, Integer arg) { + // Build main function + methodDataOffset = Machine.linkDataSize; + int mainPatch = Machine.nextInstrAddr(); + Machine.emit(Op.JUMP, Reg.CB, 0); + Analyzer.main.visit(this, null); - // Builds runtime entity, offset at LB - int size = getSize(decl.type); - decl.entity = new RuntimeEntity(size, methodDataOffset, Reg.LB); - - // Allocates space on stack - Machine.emit(Op.PUSH, size); - methodDataOffset += size; - - return null; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // TYPES - // - // ///////////////////////////////////////////////////////////////////////////// + // Run main function + int mainLabel = Machine.nextInstrAddr(); + RuntimeEntity main = Analyzer.main.entity; - @Override - public Object visitBaseType(BaseType type, Integer arg) { - - return null; - } + Machine.emit(Op.LOADL, Machine.nullRep); + Machine.emit(Op.CALL, Reg.CB, main.addr); + Machine.emit(Machine.Op.HALT, 0, 0, 0); + Machine.patch(mainPatch, mainLabel); - @Override - public Object visitClassType(ClassType type, Integer arg) { - - return null; - } + // Patch up + for (Integer instr : patches.keySet()) { + Code c = patches.get(instr); + c.modify(instr); + } - @Override - public Object visitArrayType(ArrayType type, Integer arg) { - - return null; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // STATEMENTS - // - // ///////////////////////////////////////////////////////////////////////////// + return null; + } - @Override - public Object visitBlockStmt(BlockStmt stmt, Integer arg) { - - // Execute statements - int size = 0; - for(Statement s : stmt.sl) { - s.visit(this, null); - if(s instanceof VarDeclStmt) { - VarDeclStmt vds = (VarDeclStmt) s; - size += vds.varDecl.entity.size; - } - } - - // Pop off variable declarations - if(size > 0) { - Machine.emit(Op.POP, size); - methodDataOffset -= size; - } - - return null; - } + // ///////////////////////////////////////////////////////////////////////////// + // + // DECLARATIONS + // + // ///////////////////////////////////////////////////////////////////////////// - @Override - public Object visitVardeclStmt(VarDeclStmt stmt, Integer arg) { - - stmt.varDecl.visit(this, null); - stmt.initExp.visit(this, null); - - RuntimeEntity e = stmt.varDecl.entity; - Machine.emit(Op.STORE, e.size, e.reg, e.addr); - - return null; - } + @Override + public Object visitClassDecl(ClassDecl cd, Integer patch) { - @Override - public Object visitAssignStmt(AssignStmt stmt, Integer arg) { - - // Can potentially reach declaration directly - if(stmt.ref instanceof QualifiedRef) { - - QualifiedRef ref = (QualifiedRef) stmt.ref; - MemberDecl md = (MemberDecl) ref.id.decl; - - // Just access directly - if(md.isStatic) { - stmt.val.visit(this, null); - patches.put(Machine.nextInstrAddr(), new Code(md, true)); - Machine.emit(Op.STORE, getSize(md.type), Reg.SB, 0); - - return null; - } - - // Access member directly - else if(ref.ref instanceof ThisRef) { - stmt.val.visit(this, null); - - int addr = Machine.nextInstrAddr(); - int size = getSize(ref.id.decl.type); - patches.put(addr, new Code(ref.id.decl, true)); - Machine.emit(Op.STORE, size, Reg.OB, 0); - - return null; - } - } + // Get size of class + int size = 0; + for (FieldDecl fd : cd.fieldDeclList) { + if (!fd.isStatic) { + fd.visit(this, size); + size += fd.entity.size; + } + } - // Must access member iteratively - stmt.ref.visit(this, 1); - stmt.val.visit(this, null); - - if(stmt.ref instanceof QualifiedRef) { - Machine.emit(Prim.fieldupd); - } - - else if(stmt.ref instanceof IndexedRef) { - Machine.emit(Prim.arrayupd); - } - - else if(stmt.ref instanceof IdRef) { - int addr = Machine.nextInstrAddr(); - int size = getSize(stmt.ref.decl.type); - patches.put(addr, new Code(stmt.ref.decl, true)); - Machine.emit(Op.STORE, size, Reg.ZR, 0); - } - - return null; - } + // Build Instance Methods + for (MethodDecl md : cd.methodDeclList) { + if (md != Analyzer.main) { + md.visit(this, null); + } + } - @Override - public Object visitCallStmt(CallStmt stmt, Integer arg) { - - MethodDecl md = (MethodDecl) stmt.methodRef.decl; - - // Request to print out - if(md == Analyzer.println) { - stmt.argList.get(0).visit(this, null); - Machine.emit(Prim.putintnl); - return null; - } - - // Push parameters on (must iterate in reverse order) - for(int i = stmt.argList.size() - 1; i >= 0; i--) { - stmt.argList.get(i).visit(this, null); - } - - // Call method directly - if(md.isStatic) { - patches.put(Machine.nextInstrAddr(), new Code(md, true)); - Machine.emit(Op.CALL, Reg.CB, 0); - } - - // Get address of qualified object - else { - if(stmt.methodRef instanceof QualifiedRef) { - QualifiedRef ref = (QualifiedRef) stmt.methodRef; - ref.ref.visit(this, null); - } else { - Machine.emit(Op.LOADA, Machine.addressSize, Reg.OB, 0); - } - - patches.put(Machine.nextInstrAddr(), new Code(md, true)); - Machine.emit(Op.CALLI, Reg.CB, 0); - } - - // Clear off stack if necessary - int returnSize = getSize(md.type); - if(returnSize > 0) { - Machine.emit(Op.POP, returnSize); - } - - return null; - } + // Build Class Descriptor + int addr = Machine.nextInstrAddr(); + Machine.patch(patch, addr); - @Override - public Object visitIfStmt(IfStmt stmt, Integer arg) { - - stmt.cond.visit(this, null); - - // Do not have to build as many jump instructions in this case - if(stmt.elseStmt == null) { - int ifPatch = Machine.nextInstrAddr(); - Machine.emit(Op.JUMPIF, Machine.falseRep, Reg.CB, 0); - - stmt.thenStmt.visit(this, null); - Machine.patch(ifPatch, Machine.nextInstrAddr()); - - return null; - } - - // Must jump out at end of 'if' clause - int ifPatch = Machine.nextInstrAddr(); - Machine.emit(Op.JUMPIF, Machine.falseRep, Reg.CB, 0); - - stmt.thenStmt.visit(this, null); - int thenPatch = Machine.nextInstrAddr(); - Machine.emit(Op.JUMP, Reg.CB, 0); - - // Build 'else' clause - Machine.patch(ifPatch, Machine.nextInstrAddr()); - stmt.elseStmt.visit(this, null); - Machine.patch(thenPatch, Machine.nextInstrAddr()); - - return null; - } + Machine.emit(Op.LOADL, -1); // No superclasses allowed + Machine.emit(Op.LOADL, size); // Size of class + Machine.emit(Op.LOADA, Reg.CB, addr); // Address of class - @Override - public Object visitWhileStmt(WhileStmt stmt, Integer arg) { - - // Must check the condition each loop - int whileLabel = Machine.nextInstrAddr(); - stmt.cond.visit(this, null); - - // Jump out once condition fails - int whileEndPatch = Machine.nextInstrAddr(); - Machine.emit(Op.JUMPIF, Machine.falseRep, Reg.CB, 0); - - // Execute - stmt.body.visit(this, null); - Machine.emit(Op.JUMP, Reg.CB, whileLabel); - Machine.patch(whileEndPatch, Machine.nextInstrAddr()); - - return null; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // EXPRESSIONS - // - // ///////////////////////////////////////////////////////////////////////////// + // Save entity + cd.entity = new RuntimeEntity(size, addr, Reg.CB); - @Override - public Object visitUnaryExpr(UnaryExpr expr, Integer arg) { - - expr.expr.visit(this, null); - switch(expr.operator.spelling) { - case "!": - Machine.emit(Prim.not); - break; - case "-": - Machine.emit(Prim.neg); - break; - } - - return null; - } + return null; + } - @Override - public Object visitBinaryExpr(BinaryExpr expr, Integer arg) { - - String op = expr.operator.spelling; - - if(op.equals("&&") || op.equals("||")) { - int rep = (op.equals("&&")) ? Machine.falseRep : Machine.trueRep; - - expr.left.visit(this, null); - int leftJump = Machine.nextInstrAddr(); - Machine.emit(Op.JUMPIF, rep, Reg.CB, 0); - - expr.right.visit(this, null); - expr.operator.visit(this, null); - - Machine.patch(leftJump, Machine.nextInstrAddr()); - } - - else { - expr.left.visit(this, null); - expr.right.visit(this, null); - expr.operator.visit(this, null); - } - - return null; - } + @Override + public Object visitFieldDecl(FieldDecl fd, Integer offset) { - @Override - public Object visitRefExpr(RefExpr expr, Integer arg) { + // Only non-static fields should ever reach this method + int size = getSize(fd.type); + fd.entity = new RuntimeEntity(size, offset, Reg.OB); - expr.ref.visit(this, null); - - return null; - } + return null; + } - @Override - public Object visitCallExpr(CallExpr expr, Integer arg) { - - MethodDecl md = (MethodDecl) expr.functionRef.decl; - - // Push parameters on (must iterate in reverse order) - for(int i = expr.argList.size() - 1; i >= 0; i--) { - expr.argList.get(i).visit(this, null); - } - - // Call Method - if(md.isStatic) { - patches.put(Machine.nextInstrAddr(), new Code(md, true)); - Machine.emit(Op.CALL, Reg.CB, 0); - } else { - - if(expr.functionRef instanceof QualifiedRef) { - QualifiedRef ref = (QualifiedRef) expr.functionRef; - ref.ref.visit(this, null); - } else { - Machine.emit(Op.LOADA, Machine.addressSize, Reg.OB, 0); - } - - patches.put(Machine.nextInstrAddr(), new Code(md, true)); - Machine.emit(Op.CALLI, Reg.CB, 0); - } - - return null; - } + @Override + public Object visitMethodDecl(MethodDecl md, Integer arg) { - @Override - public Object visitLiteralExpr(LiteralExpr expr, Integer arg) { - - expr.literal.visit(this, null); - - return null; - } + // Reset for next local LB + methodDataOffset = Machine.linkDataSize; - @Override - public Object visitNewObjectExpr(NewObjectExpr expr, Integer arg) { - - Declaration decl = expr.classtype.className.decl; - - patches.put(Machine.nextInstrAddr(), new Code(decl, true)); - Machine.emit(Op.LOADA, Reg.CB, 0); - - patches.put(Machine.nextInstrAddr(), new Code(decl, false)); - Machine.emit(Op.LOADL, 0); - - Machine.emit(Prim.newobj); - - return null; - } + // Save Entity + int size = getSize(md.type); + int addr = Machine.nextInstrAddr(); + md.entity = new RuntimeEntity(size, addr, Reg.CB); - @Override - public Object visitNewArrayExpr(NewArrayExpr expr, Integer arg) { - - expr.sizeExpr.visit(this, null); - Machine.emit(Prim.newarr); - - return null; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // REFERENCES - // - // ///////////////////////////////////////////////////////////////////////////// + // Setup parameters + int parameterSize = 0; + for (ParameterDecl pd : md.parameterDeclList) { + parameterSize += getSize(pd.type); + pd.visit(this, -parameterSize); + } - @Override - public Object visitQualifiedRef(QualifiedRef ref, Integer arg) { - - // Array type always returns value - if(ref.ref.decl.type.typeKind == TypeKind.ARRAY) { - - // Get address of object - if(ref.ref instanceof QualifiedRef) { - ref.ref.visit(this, null); - } else if(ref.ref instanceof ThisRef) { - patches.put(Machine.nextInstrAddr(), new Code(ref.id.decl, true)); - Machine.emit(Op.STORE, getSize(ref.id.decl.type), Reg.OB, 0); - } else { - patches.put(Machine.nextInstrAddr(), new Code(ref.ref.decl, true)); - Machine.emit(Op.LOAD, Machine.addressSize, Reg.LB, 0); - } - - Machine.emit(Op.LOADL, 1); - Machine.emit(Prim.sub); - Machine.emit(Op.LOADI, Machine.integerSize); - - return null; - } - - MemberDecl md = (MemberDecl) ref.id.decl; - - // Assigning - if(arg != null) { - ref.ref.visit(this, null); - patches.put(Machine.nextInstrAddr(), new Code(ref.id.decl, true)); - Machine.emit(Op.LOADL, 0); - } - - // Retrieving - else if(md.isStatic) { - patches.put(Machine.nextInstrAddr(), new Code(md, true)); - Machine.emit(Op.LOAD, getSize(md.type), Reg.SB, 0); - } else { - ref.ref.visit(this, null); - int addr = Machine.nextInstrAddr(); - patches.put(addr, new Code(ref.decl, true)); - - Machine.emit(Op.LOADL, 0); - Machine.emit(Prim.fieldref); - } - - return null; - } + // Build Body + for (Statement s : md.statementList) { + s.visit(this, null); + } - @Override - public Object visitIndexedRef(IndexedRef ref, Integer arg) { - - ref.ref.visit(this, null); - ref.indexExpr.visit(this, null); - - // Retrieving - if(arg == null) { - Machine.emit(Prim.arrayref); - } - - return null; - } + // Setup Return + if (md.returnExp != null) { + md.returnExp.visit(this, null); + } - @Override - public Object visitIdRef(IdRef ref, Integer arg) { - - ref.entity = ref.decl.entity; - - // Retrieving - if(arg == null) { - int size = getSize(ref.decl.type); - int addr = Machine.nextInstrAddr(); - patches.put(addr, new Code(ref.decl, true)); - - Machine.emit(Op.LOAD, size, Reg.ZR, 0); - } - - return null; - } + Machine.emit(Op.RETURN, size, 0, parameterSize); - @Override - public Object visitThisRef(ThisRef ref, Integer arg) { - - Machine.emit(Op.LOADA, Machine.addressSize, Reg.OB, 0); - - return null; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // TERMINALS - // - // ///////////////////////////////////////////////////////////////////////////// + return null; + } - @Override - public Object visitIdentifier(Identifier id, Integer arg) { - - return null; - } + @Override + public Object visitParameterDecl(ParameterDecl pd, Integer offset) { - @Override - public Object visitOperator(Operator op, Integer arg) { - - switch(op.spelling) { - case "+": - Machine.emit(Prim.add); - break; - case "-": - Machine.emit(Prim.sub); - break; - case "*": - Machine.emit(Prim.mult); - break; - case "/": - Machine.emit(Prim.div); - break; - case "<": - Machine.emit(Prim.lt); - break; - case ">": - Machine.emit(Prim.gt); - break; - case "<=": - Machine.emit(Prim.le); - break; - case ">=": - Machine.emit(Prim.ge); - break; - case "==": - Machine.emit(Prim.eq); - break; - case "!=": - Machine.emit(Prim.ne); - break; - case "&&": - Machine.emit(Prim.and); - break; - case "||": - Machine.emit(Prim.or); - break; - } - - return null; - } + // Builds runtime entity (should be negative of LB) + int size = getSize(pd.type); + pd.entity = new RuntimeEntity(size, offset, Reg.LB); - @Override - public Object visitIntLiteral(IntLiteral num, Integer arg) { - - Integer lit = Integer.parseInt(num.spelling); - Machine.emit(Op.LOADL, lit.intValue()); - - return null; - } + return null; + } - @Override - public Object visitBooleanLiteral(BooleanLiteral bool, Integer arg) { - - if(bool.spelling.equals("true")) { - Machine.emit(Op.LOADL, Machine.trueRep); - } else { - Machine.emit(Op.LOADL, Machine.falseRep); - } - - return null; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // Convenience Methods - // - // ///////////////////////////////////////////////////////////////////////////// + @Override + public Object visitVarDecl(VarDecl decl, Integer arg) { - /** - * Get size of type for declaration purposes. - * @param t - * @return - */ - private int getSize(Type t) { - switch(t.typeKind) { - case ARRAY: - case CLASS: - return Machine.addressSize; - case INT: - return Machine.integerSize; - case BOOLEAN: - return Machine.booleanSize; - case VOID: - return 0; - default: - return -1; - } - } + // Builds runtime entity, offset at LB + int size = getSize(decl.type); + decl.entity = new RuntimeEntity(size, methodDataOffset, Reg.LB); + + // Allocates space on stack + Machine.emit(Op.PUSH, size); + methodDataOffset += size; + + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // TYPES + // + // ///////////////////////////////////////////////////////////////////////////// + + @Override + public Object visitBaseType(BaseType type, Integer arg) { + + return null; + } + + @Override + public Object visitClassType(ClassType type, Integer arg) { + + return null; + } + + @Override + public Object visitArrayType(ArrayType type, Integer arg) { + + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // STATEMENTS + // + // ///////////////////////////////////////////////////////////////////////////// + + @Override + public Object visitBlockStmt(BlockStmt stmt, Integer arg) { + + // Execute statements + int size = 0; + for (Statement s : stmt.sl) { + s.visit(this, null); + if (s instanceof VarDeclStmt) { + VarDeclStmt vds = (VarDeclStmt) s; + size += vds.varDecl.entity.size; + } + } + + // Pop off variable declarations + if (size > 0) { + Machine.emit(Op.POP, size); + methodDataOffset -= size; + } + + return null; + } + + @Override + public Object visitVardeclStmt(VarDeclStmt stmt, Integer arg) { + + stmt.varDecl.visit(this, null); + stmt.initExp.visit(this, null); + + RuntimeEntity e = stmt.varDecl.entity; + Machine.emit(Op.STORE, e.size, e.reg, e.addr); + + return null; + } + + @Override + public Object visitAssignStmt(AssignStmt stmt, Integer arg) { + + // Can potentially reach declaration directly + if (stmt.ref instanceof QualifiedRef) { + + QualifiedRef ref = (QualifiedRef) stmt.ref; + MemberDecl md = (MemberDecl) ref.id.decl; + + // Just access directly + if (md.isStatic) { + stmt.val.visit(this, null); + patches.put(Machine.nextInstrAddr(), new Code(md, true)); + Machine.emit(Op.STORE, getSize(md.type), Reg.SB, 0); + + return null; + } + + // Access member directly + else if (ref.ref instanceof ThisRef) { + stmt.val.visit(this, null); + + int addr = Machine.nextInstrAddr(); + int size = getSize(ref.id.decl.type); + patches.put(addr, new Code(ref.id.decl, true)); + Machine.emit(Op.STORE, size, Reg.OB, 0); + + return null; + } + } + + // Must access member iteratively + stmt.ref.visit(this, 1); + stmt.val.visit(this, null); + + if (stmt.ref instanceof QualifiedRef) { + Machine.emit(Prim.fieldupd); + } + + else if (stmt.ref instanceof IndexedRef) { + Machine.emit(Prim.arrayupd); + } + + else if (stmt.ref instanceof IdRef) { + int addr = Machine.nextInstrAddr(); + int size = getSize(stmt.ref.decl.type); + patches.put(addr, new Code(stmt.ref.decl, true)); + Machine.emit(Op.STORE, size, Reg.ZR, 0); + } + + return null; + } + + @Override + public Object visitCallStmt(CallStmt stmt, Integer arg) { + + MethodDecl md = (MethodDecl) stmt.methodRef.decl; + + // Request to print out + if (md == Analyzer.println) { + stmt.argList.get(0).visit(this, null); + Machine.emit(Prim.putintnl); + return null; + } + + // Push parameters on (must iterate in reverse order) + for (int i = stmt.argList.size() - 1; i >= 0; i--) { + stmt.argList.get(i).visit(this, null); + } + + // Call method directly + if (md.isStatic) { + patches.put(Machine.nextInstrAddr(), new Code(md, true)); + Machine.emit(Op.CALL, Reg.CB, 0); + } + + // Get address of qualified object + else { + if (stmt.methodRef instanceof QualifiedRef) { + QualifiedRef ref = (QualifiedRef) stmt.methodRef; + ref.ref.visit(this, null); + } else { + Machine.emit(Op.LOADA, Machine.addressSize, Reg.OB, 0); + } + + patches.put(Machine.nextInstrAddr(), new Code(md, true)); + Machine.emit(Op.CALLI, Reg.CB, 0); + } + + // Clear off stack if necessary + int returnSize = getSize(md.type); + if (returnSize > 0) { + Machine.emit(Op.POP, returnSize); + } + + return null; + } + + @Override + public Object visitIfStmt(IfStmt stmt, Integer arg) { + + stmt.cond.visit(this, null); + + // Do not have to build as many jump instructions in this case + if (stmt.elseStmt == null) { + int ifPatch = Machine.nextInstrAddr(); + Machine.emit(Op.JUMPIF, Machine.falseRep, Reg.CB, 0); + + stmt.thenStmt.visit(this, null); + Machine.patch(ifPatch, Machine.nextInstrAddr()); + + return null; + } + + // Must jump out at end of 'if' clause + int ifPatch = Machine.nextInstrAddr(); + Machine.emit(Op.JUMPIF, Machine.falseRep, Reg.CB, 0); + + stmt.thenStmt.visit(this, null); + int thenPatch = Machine.nextInstrAddr(); + Machine.emit(Op.JUMP, Reg.CB, 0); + + // Build 'else' clause + Machine.patch(ifPatch, Machine.nextInstrAddr()); + stmt.elseStmt.visit(this, null); + Machine.patch(thenPatch, Machine.nextInstrAddr()); + + return null; + } + + @Override + public Object visitWhileStmt(WhileStmt stmt, Integer arg) { + + // Must check the condition each loop + int whileLabel = Machine.nextInstrAddr(); + stmt.cond.visit(this, null); + + // Jump out once condition fails + int whileEndPatch = Machine.nextInstrAddr(); + Machine.emit(Op.JUMPIF, Machine.falseRep, Reg.CB, 0); + + // Execute + stmt.body.visit(this, null); + Machine.emit(Op.JUMP, Reg.CB, whileLabel); + Machine.patch(whileEndPatch, Machine.nextInstrAddr()); + + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // EXPRESSIONS + // + // ///////////////////////////////////////////////////////////////////////////// + + @Override + public Object visitUnaryExpr(UnaryExpr expr, Integer arg) { + + expr.expr.visit(this, null); + switch (expr.operator.spelling) { + case "!": + Machine.emit(Prim.not); + break; + case "-": + Machine.emit(Prim.neg); + break; + } + + return null; + } + + @Override + public Object visitBinaryExpr(BinaryExpr expr, Integer arg) { + + String op = expr.operator.spelling; + + if (op.equals("&&") || op.equals("||")) { + int rep = (op.equals("&&")) ? Machine.falseRep : Machine.trueRep; + + expr.left.visit(this, null); + int leftJump = Machine.nextInstrAddr(); + Machine.emit(Op.JUMPIF, rep, Reg.CB, 0); + + expr.right.visit(this, null); + expr.operator.visit(this, null); + + Machine.patch(leftJump, Machine.nextInstrAddr()); + } + + else { + expr.left.visit(this, null); + expr.right.visit(this, null); + expr.operator.visit(this, null); + } + + return null; + } + + @Override + public Object visitRefExpr(RefExpr expr, Integer arg) { + + expr.ref.visit(this, null); + + return null; + } + + @Override + public Object visitCallExpr(CallExpr expr, Integer arg) { + + MethodDecl md = (MethodDecl) expr.functionRef.decl; + + // Push parameters on (must iterate in reverse order) + for (int i = expr.argList.size() - 1; i >= 0; i--) { + expr.argList.get(i).visit(this, null); + } + + // Call Method + if (md.isStatic) { + patches.put(Machine.nextInstrAddr(), new Code(md, true)); + Machine.emit(Op.CALL, Reg.CB, 0); + } else { + + if (expr.functionRef instanceof QualifiedRef) { + QualifiedRef ref = (QualifiedRef) expr.functionRef; + ref.ref.visit(this, null); + } else { + Machine.emit(Op.LOADA, Machine.addressSize, Reg.OB, 0); + } + + patches.put(Machine.nextInstrAddr(), new Code(md, true)); + Machine.emit(Op.CALLI, Reg.CB, 0); + } + + return null; + } + + @Override + public Object visitLiteralExpr(LiteralExpr expr, Integer arg) { + + expr.literal.visit(this, null); + + return null; + } + + @Override + public Object visitNewObjectExpr(NewObjectExpr expr, Integer arg) { + + Declaration decl = expr.classtype.className.decl; + + patches.put(Machine.nextInstrAddr(), new Code(decl, true)); + Machine.emit(Op.LOADA, Reg.CB, 0); + + patches.put(Machine.nextInstrAddr(), new Code(decl, false)); + Machine.emit(Op.LOADL, 0); + + Machine.emit(Prim.newobj); + + return null; + } + + @Override + public Object visitNewArrayExpr(NewArrayExpr expr, Integer arg) { + + expr.sizeExpr.visit(this, null); + Machine.emit(Prim.newarr); + + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // REFERENCES + // + // ///////////////////////////////////////////////////////////////////////////// + + @Override + public Object visitQualifiedRef(QualifiedRef ref, Integer arg) { + + // Array type always returns value + if (ref.ref.decl.type.typeKind == TypeKind.ARRAY) { + + // Get address of object + if (ref.ref instanceof QualifiedRef) { + ref.ref.visit(this, null); + } else if (ref.ref instanceof ThisRef) { + patches.put(Machine.nextInstrAddr(), new Code(ref.id.decl, true)); + Machine.emit(Op.STORE, getSize(ref.id.decl.type), Reg.OB, 0); + } else { + patches.put(Machine.nextInstrAddr(), new Code(ref.ref.decl, true)); + Machine.emit(Op.LOAD, Machine.addressSize, Reg.LB, 0); + } + + Machine.emit(Op.LOADL, 1); + Machine.emit(Prim.sub); + Machine.emit(Op.LOADI, Machine.integerSize); + + return null; + } + + MemberDecl md = (MemberDecl) ref.id.decl; + + // Assigning + if (arg != null) { + ref.ref.visit(this, null); + patches.put(Machine.nextInstrAddr(), new Code(ref.id.decl, true)); + Machine.emit(Op.LOADL, 0); + } + + // Retrieving + else if (md.isStatic) { + patches.put(Machine.nextInstrAddr(), new Code(md, true)); + Machine.emit(Op.LOAD, getSize(md.type), Reg.SB, 0); + } else { + ref.ref.visit(this, null); + int addr = Machine.nextInstrAddr(); + patches.put(addr, new Code(ref.decl, true)); + + Machine.emit(Op.LOADL, 0); + Machine.emit(Prim.fieldref); + } + + return null; + } + + @Override + public Object visitIndexedRef(IndexedRef ref, Integer arg) { + + ref.ref.visit(this, null); + ref.indexExpr.visit(this, null); + + // Retrieving + if (arg == null) { + Machine.emit(Prim.arrayref); + } + + return null; + } + + @Override + public Object visitIdRef(IdRef ref, Integer arg) { + + ref.entity = ref.decl.entity; + + // Retrieving + if (arg == null) { + int size = getSize(ref.decl.type); + int addr = Machine.nextInstrAddr(); + patches.put(addr, new Code(ref.decl, true)); + + Machine.emit(Op.LOAD, size, Reg.ZR, 0); + } + + return null; + } + + @Override + public Object visitThisRef(ThisRef ref, Integer arg) { + + Machine.emit(Op.LOADA, Machine.addressSize, Reg.OB, 0); + + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // TERMINALS + // + // ///////////////////////////////////////////////////////////////////////////// + + @Override + public Object visitIdentifier(Identifier id, Integer arg) { + + return null; + } + + @Override + public Object visitOperator(Operator op, Integer arg) { + + switch (op.spelling) { + case "+": + Machine.emit(Prim.add); + break; + case "-": + Machine.emit(Prim.sub); + break; + case "*": + Machine.emit(Prim.mult); + break; + case "/": + Machine.emit(Prim.div); + break; + case "<": + Machine.emit(Prim.lt); + break; + case ">": + Machine.emit(Prim.gt); + break; + case "<=": + Machine.emit(Prim.le); + break; + case ">=": + Machine.emit(Prim.ge); + break; + case "==": + Machine.emit(Prim.eq); + break; + case "!=": + Machine.emit(Prim.ne); + break; + case "&&": + Machine.emit(Prim.and); + break; + case "||": + Machine.emit(Prim.or); + break; + } + + return null; + } + + @Override + public Object visitIntLiteral(IntLiteral num, Integer arg) { + + Integer lit = Integer.parseInt(num.spelling); + Machine.emit(Op.LOADL, lit.intValue()); + + return null; + } + + @Override + public Object visitBooleanLiteral(BooleanLiteral bool, Integer arg) { + + if (bool.spelling.equals("true")) { + Machine.emit(Op.LOADL, Machine.trueRep); + } else { + Machine.emit(Op.LOADL, Machine.falseRep); + } + + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // Convenience Methods + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * Get size of type for declaration purposes. + * + * @param t + * @return + */ + private int getSize(Type t) { + switch (t.typeKind) { + case ARRAY: + case CLASS: + return Machine.addressSize; + case INT: + return Machine.integerSize; + case BOOLEAN: + return Machine.booleanSize; + case VOID: + return 0; + default: + return -1; + } + } } diff --git a/src/miniJava/CodeGenerator/RuntimeEntity.java b/src/miniJava/CodeGenerator/RuntimeEntity.java index 8571a10..1b7a8a1 100644 --- a/src/miniJava/CodeGenerator/RuntimeEntity.java +++ b/src/miniJava/CodeGenerator/RuntimeEntity.java @@ -4,16 +4,16 @@ import mJAM.Machine.Reg; public class RuntimeEntity { - public Reg reg; - public int size; - public int addr; - - RuntimeEntity parent = null; - - public RuntimeEntity(int size, int addr, Reg reg) { - this.reg = reg; - this.size = size; - this.addr = addr; - } - + public Reg reg; + public int size; + public int addr; + + RuntimeEntity parent = null; + + public RuntimeEntity(int size, int addr, Reg reg) { + this.reg = reg; + this.size = size; + this.addr = addr; + } + } diff --git a/src/miniJava/Compiler.java b/src/miniJava/Compiler.java index 2306f03..5e13672 100644 --- a/src/miniJava/Compiler.java +++ b/src/miniJava/Compiler.java @@ -19,58 +19,58 @@ import miniJava.ContextualAnalyzer.Reporter; public class Compiler { - public static final int rc = 4; + public static final int rc = 4; - public static void main(String[] args) { + public static void main(String[] args) { - if (args.length == 0) { - System.out.println("No file specified"); - System.exit(rc); - } + if (args.length == 0) { + System.out.println("No file specified"); + System.exit(rc); + } - try (FileReader input = new FileReader(args[0])) { + try (FileReader input = new FileReader(args[0])) { - // Setup - Scanner scanner = new Scanner(new BufferedReader(input)); - Parser parser = new Parser(scanner); - Package p = parser.parse(); - - // Display - // ASTDisplay display = new ASTDisplay(); - // display.showTree(p); - - // Contextual Analyzer - IdTable table = new IdTable(); - Analyzer analyzer = new Analyzer(); - analyzer.visitPackage(p, table); - - // Compilation - if(Reporter.error) { - System.exit(rc); - } else { - - // Build mJAM assembly - Encoder encoder = new Encoder(); - encoder.visitPackage(p, null); - - // Create object file - int pos = args[0].lastIndexOf(".java"); - String objectFileName = args[0].substring(0, pos) + ".mJAM"; - ObjectFile objF = new ObjectFile(objectFileName); - if(objF.write()) { - Reporter.emit("Object File Failed."); - } - } - - System.exit(0); + // Setup + Scanner scanner = new Scanner(new BufferedReader(input)); + Parser parser = new Parser(scanner); + Package p = parser.parse(); - } catch (FileNotFoundException e) { - Reporter.emit(e.getMessage()); - } catch (IOException e) { - Reporter.emit(e.getMessage()); - } + // Display + // ASTDisplay display = new ASTDisplay(); + // display.showTree(p); - System.exit(rc); - } + // Contextual Analyzer + IdTable table = new IdTable(); + Analyzer analyzer = new Analyzer(); + analyzer.visitPackage(p, table); + + // Compilation + if (Reporter.error) { + System.exit(rc); + } else { + + // Build mJAM assembly + Encoder encoder = new Encoder(); + encoder.visitPackage(p, null); + + // Create object file + int pos = args[0].lastIndexOf(".java"); + String objectFileName = args[0].substring(0, pos) + ".mJAM"; + ObjectFile objF = new ObjectFile(objectFileName); + if (objF.write()) { + Reporter.emit("Object File Failed."); + } + } + + System.exit(0); + + } catch (FileNotFoundException e) { + Reporter.emit(e.getMessage()); + } catch (IOException e) { + Reporter.emit(e.getMessage()); + } + + System.exit(rc); + } } diff --git a/src/miniJava/ContextualAnalyzer/Analyzer.java b/src/miniJava/ContextualAnalyzer/Analyzer.java index 65f4bff..daec45d 100644 --- a/src/miniJava/ContextualAnalyzer/Analyzer.java +++ b/src/miniJava/ContextualAnalyzer/Analyzer.java @@ -10,789 +10,783 @@ import miniJava.SyntacticAnalyzer.Parser; import miniJava.SyntacticAnalyzer.Scanner; public class Analyzer implements Visitor { - - public Reporter reporter = new Reporter(); - - // Required Methods - public static MethodDecl main; - public static MethodDecl println; - - // Predefined - private static ArrayList predefined; - static - { - predefined = new ArrayList(); - predefined.add("class String { }"); - predefined.add("class _PrintStream { public void println(int n){} }"); - predefined.add("class System { public static _PrintStream out; }"); - } - - // Keep Track Of Declarations - private IdTable top = null; - private VarDecl currentVarDecl = null; - private ClassDecl currentClassDecl = null; - private MethodDecl currentMethodDecl = null; - - - // ///////////////////////////////////////////////////////////////////////////// - // - // PACKAGE - // - // ///////////////////////////////////////////////////////////////////////////// - @Override - public Type visitPackage(Package prog, IdTable table) { - - top = table; - - // Begin predefinitions - try { - for(String pd : predefined) { - Scanner scanner = new Scanner(pd, true); - Parser parser = new Parser(scanner); - ClassDecl cd = parser.parseClassDeclaration(); - - addDeclarations(cd, table); - cd.visit(this, table); - } - } catch(IOException e) { - Reporter.emit("System Predefinitions Error!"); - System.exit(Compiler.rc); - } - - // Add all second level declarations - for(ClassDecl cd : prog.classDeclList) { - addDeclarations(cd, table); - } - - // Begin traversal - for(ClassDecl cd : prog.classDeclList) { - cd.visit(this, table); - } - - // Check a main exists - if(main == null) { - Reporter.emit("Main method undeclared."); - } + public Reporter reporter = new Reporter(); - return null; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // DECLARATIONS - // - // ///////////////////////////////////////////////////////////////////////////// + // Required Methods + public static MethodDecl main; + public static MethodDecl println; - @Override - public Type visitClassDecl(ClassDecl cd, IdTable table) { - - currentClassDecl = cd; + // Predefined + private static ArrayList predefined; - for(FieldDecl fd : cd.fieldDeclList) { - fd.visit(this, cd.table); - } - - for(MethodDecl md : cd.methodDeclList) { - md.visit(this, cd.table); - } - - return null; - } + static { + predefined = new ArrayList(); + predefined.add("class String { }"); + predefined.add("class _PrintStream { public void println(int n){} }"); + predefined.add("class System { public static _PrintStream out; }"); + } - @Override - public Type visitFieldDecl(FieldDecl fd, IdTable table) { - - fd.type.visit(this, table); - if(fd.type.typeKind == TypeKind.VOID) { - Reporter.emit("Field " + fd.name + " at " + fd.posn + " cannot have type 'void'"); - } - - return null; - } + // Keep Track Of Declarations + private IdTable top = null; + private VarDecl currentVarDecl = null; + private ClassDecl currentClassDecl = null; + private MethodDecl currentMethodDecl = null; - @Override - public Type visitMethodDecl(MethodDecl md, IdTable table) { - - currentMethodDecl = md; - - // Save println method - if(println == null && md.name.equals("println")) { - println = md; - } - - // Save main method - if(isMain(md)) { - if(main != null) { - Reporter.emit("Main at " + md.posn + " previously defined at " + main.posn); - } else { - main = md; - } - } - - // Continue Traversal - md.type.visit(this, table); - - for(ParameterDecl pd : md.parameterDeclList) { - pd.visit(this, md.table); - } - - for(Statement s : md.statementList) { - s.visit(this, md.table); - } - - // Check return status - if(md.type.typeKind != TypeKind.VOID && md.returnExp == null) { - Reporter.emit("Method " + md.name + " at " + md.posn + " must have a return expression"); - } else if(md.type.typeKind == TypeKind.VOID && md.returnExp != null) { - Reporter.emit("Method " + md.name + " at " + md.posn + " cannot have a return expression"); - } - - if(md.returnExp != null) { - Type returnType = md.returnExp.visit(this, md.table); - if(!match(returnType, md.type)) { - Reporter.emit("Expected " + md.type + " but got " + returnType + " at " + md.returnExp.posn); - } - } + // ///////////////////////////////////////////////////////////////////////////// + // + // PACKAGE + // + // ///////////////////////////////////////////////////////////////////////////// - return null; - } + @Override + public Type visitPackage(Package prog, IdTable table) { - @Override - public Type visitParameterDecl(ParameterDecl pd, IdTable table) { - - table.add(pd); - pd.type.visit(this, table); - if(pd.type.typeKind == TypeKind.VOID) { - Reporter.emit("Parameter " + pd.name + " at " + pd.posn + " cannot have type 'void'"); - } - - return null; - } + top = table; - @Override - public Type visitVarDecl(VarDecl decl, IdTable table) { - - table.add(decl); - decl.type.visit(this, table); - if(decl.type.typeKind == TypeKind.VOID) { - Reporter.emit("Variable " + decl.name + " at " + decl.posn + " cannot have type 'void'"); - } - - return null; - } + // Begin predefinitions + try { + for (String pd : predefined) { + Scanner scanner = new Scanner(pd, true); + Parser parser = new Parser(scanner); + ClassDecl cd = parser.parseClassDeclaration(); - - // ///////////////////////////////////////////////////////////////////////////// - // - // TYPES - // - // ///////////////////////////////////////////////////////////////////////////// - - @Override - public Type visitBaseType(BaseType type, IdTable table) { - - return type; - } + addDeclarations(cd, table); + cd.visit(this, table); + } + } catch (IOException e) { + Reporter.emit("System Predefinitions Error!"); + System.exit(Compiler.rc); + } - @Override - public Type visitClassType(ClassType type, IdTable table) { - - type.className.visit(this, table); - - // Must check that the type is valid - String cn = type.className.spelling; - if(top.getDeclarationAtScope(cn) == null) { - Reporter.emit("Class '" + cn + "' undeclared at " + type.posn); - } - - return type; - } + // Add all second level declarations + for (ClassDecl cd : prog.classDeclList) { + addDeclarations(cd, table); + } - @Override - public Type visitArrayType(ArrayType type, IdTable table) { - - type.eltType.visit(this, table); - - return type; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // STATEMENTS - // - // ///////////////////////////////////////////////////////////////////////////// + // Begin traversal + for (ClassDecl cd : prog.classDeclList) { + cd.visit(this, table); + } - @Override - public Type visitBlockStmt(BlockStmt stmt, IdTable table) { - - table.push(); - - for(Statement s : stmt.sl) { - s.visit(this, table); - } - - table.pop(); - - return null; - } + // Check a main exists + if (main == null) { + Reporter.emit("Main method undeclared."); + } - @Override - public Type visitVardeclStmt(VarDeclStmt stmt, IdTable table) { - - stmt.varDecl.visit(this, table); - - currentVarDecl = stmt.varDecl; - Type exprType = stmt.initExp.visit(this, table); - currentVarDecl = null; - - // Types must match - if(!match(stmt.varDecl.type, exprType)) { - Reporter.emit("Expected " + stmt.varDecl.type + " but got " + exprType + " at " + stmt.initExp.posn); - } - - return null; - } + return null; + } - @Override - public Type visitAssignStmt(AssignStmt stmt, IdTable table) { - - Type refType = stmt.ref.visit(this, table); - Type valType = stmt.val.visit(this, table); - - if(!match(refType, valType)) { - Reporter.emit("Expected " + refType + " but got " + valType + " at " + stmt.posn); - } - - // Should never assign 'this' to anything - if(stmt.ref instanceof ThisRef) { - Reporter.emit("Cannot assign 'this' to a value at " + stmt.posn); - } - - // Should never assign a method a value - if(stmt.ref.decl instanceof MethodDecl) { - Reporter.emit("Cannot assign a method a value at " + stmt.posn); - } - - // Cannot assign array length field - if(stmt.ref instanceof QualifiedRef) { - QualifiedRef ref = (QualifiedRef) stmt.ref; - if(ref.ref.decl.type.typeKind == TypeKind.ARRAY && ref.id.spelling.equals("length")) { - Reporter.emit("'length' field cannot be changed at " + stmt.posn); - } - } - - return null; - } + // ///////////////////////////////////////////////////////////////////////////// + // + // DECLARATIONS + // + // ///////////////////////////////////////////////////////////////////////////// - @Override - public Type visitCallStmt(CallStmt stmt, IdTable table) { - - stmt.methodRef.visit(this, table); - - // Check valid parameter count - MethodDecl md = (MethodDecl) stmt.methodRef.decl; - if(md.parameterDeclList.size() != stmt.argList.size()) { - Reporter.emit("Expected " + md.parameterDeclList.size() + " parameters at " + stmt.posn); - return null; - } - - // Check parameter types match - for (int i = 0; i < stmt.argList.size(); i++) { - Expression e = stmt.argList.get(i); - Type exprType = e.visit(this, table); - ParameterDecl pd = md.parameterDeclList.get(i); + @Override + public Type visitClassDecl(ClassDecl cd, IdTable table) { - if(!match(pd.type, exprType)) { - Reporter.emit("Parameter " + pd.name + " is of type " + pd.type + " but got " + exprType + " at " + e.posn); - } - } + currentClassDecl = cd; - return null; - } + for (FieldDecl fd : cd.fieldDeclList) { + fd.visit(this, cd.table); + } - @Override - public Type visitIfStmt(IfStmt stmt, IdTable table) { - - // Conditional statement must have type boolean - Type condType = stmt.cond.visit(this, table); - if(condType.typeKind != TypeKind.BOOLEAN) { - Reporter.emit("Expected boolean but got " + condType + " at " + condType.posn); - } - - // A single variable declaration not allowed after conditional statement - if(stmt.thenStmt instanceof VarDeclStmt) { - Reporter.emit("Variable declaration not allowed solely in 'then' clause at " + stmt.thenStmt.posn); - return null; - } - - stmt.thenStmt.visit(this, table); - - // Check else statement - if (stmt.elseStmt != null) { - if (stmt.elseStmt instanceof VarDeclStmt) { - Reporter.emit("Variable declaration not allowed solely in 'else' clause at " + stmt.elseStmt.posn); - return null; - } - - stmt.elseStmt.visit(this, table); - } + for (MethodDecl md : cd.methodDeclList) { + md.visit(this, cd.table); + } - return null; - } + return null; + } - @Override - public Type visitWhileStmt(WhileStmt stmt, IdTable table) { - - // Conditional statement must have type boolean - Type condType = stmt.cond.visit(this, table); - if(condType.typeKind != TypeKind.BOOLEAN) { - Reporter.emit("Expected boolean but got " + condType + " at " + condType.posn); - } - - if(stmt.body instanceof VarDeclStmt) { - Reporter.emit("Variable declaration not allowed solely in 'while' clause at " + stmt.body.posn); - return null; - } + @Override + public Type visitFieldDecl(FieldDecl fd, IdTable table) { - stmt.body.visit(this, table); - - return null; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // EXPRESSIONS - // - // ///////////////////////////////////////////////////////////////////////////// + fd.type.visit(this, table); + if (fd.type.typeKind == TypeKind.VOID) { + Reporter.emit("Field " + fd.name + " at " + fd.posn + " cannot have type 'void'"); + } - @Override - public Type visitUnaryExpr(UnaryExpr expr, IdTable table) { - - Type exprType = expr.expr.visit(this, table); - Type opType = expr.operator.visit(this, table); - if(!match(exprType, opType)) { - String op = expr.operator.spelling; - Reporter.emit("Operator " + op + " applies to " + opType + " but got " + exprType + " at " + expr.posn); - } - - return opType; - } + return null; + } - @Override - public Type visitBinaryExpr(BinaryExpr expr, IdTable table) { - - Type lType = expr.left.visit(this, table); - Type rType = expr.right.visit(this, table); - - BaseType type = null; - String op = expr.operator.spelling; - switch(op) { - - // Equality Operators - case "==": - case "!=": - if(!match(lType, rType)) { - Reporter.emit("Left hand side must be of right hand side's type " + rType + " at " + expr.posn); - } - return new BaseType(TypeKind.BOOLEAN, expr.posn); - - // Boolean Operators - case "&&": - case "||": - type = new BaseType(TypeKind.BOOLEAN, expr.posn); - break; - - // Integer operators - case ">": - case "<": - case "+": - case "-": - case "*": - case "/": - case "<=": - case ">=": - type = new BaseType(TypeKind.INT, expr.posn); - break; - - default: - return new BaseType(TypeKind.ERROR, expr.posn); - } - - // Make sure types match - if(!match(lType, type)) { - Reporter.emit("Expected " + type + " but got " + lType + " at " + expr.posn); - } - - if(!match(rType, type)) { - Reporter.emit("Expected " + type + " but got " + lType + " at " + expr.posn); - } - - // Resulting type - return expr.operator.visit(this, table); - } + @Override + public Type visitMethodDecl(MethodDecl md, IdTable table) { - @Override - public Type visitRefExpr(RefExpr expr, IdTable table) { - - Type refType = expr.ref.visit(this, table); - Declaration decl = table.getDeclaration(expr.ref.spelling); - - // Should never reference a class name - if(decl instanceof ClassDecl) { - Reporter.emit("Class declaration referenced at " + expr.posn); - } + currentMethodDecl = md; - // Should never reference a method name - else if(decl instanceof MethodDecl) { - Reporter.emit("Method declaration referenced at " + expr.posn); - } - - // Cannot access instance members in static context - if(!(expr.ref instanceof QualifiedRef) && decl instanceof FieldDecl) { - FieldDecl fd = (FieldDecl) decl; - if(currentMethodDecl.isStatic && !fd.isStatic) { - Reporter.emit("Cannot access instance member in static context at " + expr.posn); - } - } + // Save println method + if (println == null && md.name.equals("println")) { + println = md; + } - return refType; - } + // Save main method + if (isMain(md)) { + if (main != null) { + Reporter.emit("Main at " + md.posn + " previously defined at " + main.posn); + } else { + main = md; + } + } - @Override - public Type visitCallExpr(CallExpr expr, IdTable table) { - - Type refType = expr.functionRef.visit(this, table); - - // Check parameter count matches - MethodDecl md = (MethodDecl) expr.functionRef.decl; - if(md.parameterDeclList.size() != expr.argList.size()) { - Reporter.emit("Expected " + md.parameterDeclList.size() + " parameters at " + expr.posn); - return refType; - } - - // Check parameter types match - for (int i = 0; i < expr.argList.size(); i++) { - Expression e = expr.argList.get(i); - Type exprType = e.visit(this, table); - ParameterDecl pd = md.parameterDeclList.get(i); + // Continue Traversal + md.type.visit(this, table); - if(!match(pd.type, exprType)) { - Reporter.emit("Parameter " + pd.name + " is of type " + pd.type + " but got " + exprType + " at " + e.posn); - } - } - - return refType; - } + for (ParameterDecl pd : md.parameterDeclList) { + pd.visit(this, md.table); + } - @Override - public Type visitLiteralExpr(LiteralExpr expr, IdTable table) { - - return expr.literal.visit(this, table); - } + for (Statement s : md.statementList) { + s.visit(this, md.table); + } - @Override - public Type visitNewObjectExpr(NewObjectExpr expr, IdTable table) { - - return expr.classtype.visit(this, table); - } + // Check return status + if (md.type.typeKind != TypeKind.VOID && md.returnExp == null) { + Reporter.emit("Method " + md.name + " at " + md.posn + " must have a return expression"); + } else if (md.type.typeKind == TypeKind.VOID && md.returnExp != null) { + Reporter.emit("Method " + md.name + " at " + md.posn + " cannot have a return expression"); + } - @Override - public Type visitNewArrayExpr(NewArrayExpr expr, IdTable table) { - - // Arrays only of classes and integers - Type eltType = expr.eltType.visit(this, table); - if(eltType.typeKind != TypeKind.INT && eltType.typeKind != TypeKind.CLASS) { - Reporter.emit("Cannot create array of type " + eltType + " at " + expr.posn); - } - - // Size must be an integer value - Type sizeType = expr.sizeExpr.visit(this, table); - if (sizeType.typeKind != TypeKind.INT) { - BaseType type = new BaseType(TypeKind.INT, expr.sizeExpr.posn); - Reporter.emit("Expected " + type + " but got " + sizeType + " at " + type.posn); - } + if (md.returnExp != null) { + Type returnType = md.returnExp.visit(this, md.table); + if (!match(returnType, md.type)) { + Reporter.emit("Expected " + md.type + " but got " + returnType + " at " + md.returnExp.posn); + } + } - return new ArrayType(eltType, expr.posn); - } + return null; + } - - // ///////////////////////////////////////////////////////////////////////////// - // - // REFERENCES - // - // ///////////////////////////////////////////////////////////////////////////// - - @Override - public Type visitQualifiedRef(QualifiedRef ref, IdTable table) { - - Type refType = ref.ref.visit(this, table); - - // Should not try and access a method in qualified manner - if(ref.ref.decl instanceof MethodDecl) { - Reporter.emit("Cannot use method " + ref.ref.decl.name + " in qualified manner at " + ref.ref.posn); - return new BaseType(TypeKind.ERROR, ref.ref.posn); - } - - // Array types can have a length field - if(refType.typeKind == TypeKind.ARRAY) { - if(!ref.id.spelling.equals("length")) { - Reporter.emit(ref.id.spelling + " attribute not available with arrays at " + ref.id.posn); - return new BaseType(TypeKind.ERROR, ref.id.posn); - } - - return new BaseType(TypeKind.INT, ref.id.posn); - } - - // Otherwise, should have a class type - if(refType.typeKind != TypeKind.CLASS) { - Reporter.emit("Qualified reference not of type class or array at " + ref.posn); - return new BaseType(TypeKind.ERROR, ref.posn); - } - - // Get member in question - ClassType ct = (ClassType) refType; - ClassDecl cd = (ClassDecl) top.getDeclarationAtScope(ct.className.spelling); - if(cd == null) { - Reporter.emit("Accessing non-existant class at " + ct.posn); - return new BaseType(TypeKind.ERROR, ref.posn); - } + @Override + public Type visitParameterDecl(ParameterDecl pd, IdTable table) { - MemberDecl md = (MemberDecl) cd.table.getDeclarationAtScope(ref.id.spelling); - if(md == null) { - Reporter.emit("Accessing non-existant field at " + ref.id.posn); - return new BaseType(TypeKind.ERROR, ref.posn); - } - - // Check if static member - Declaration decl = table.getDeclaration(ref.ref.spelling); - if(decl instanceof ClassDecl && !md.isStatic) { - Reporter.emit("Cannot access non-static member at " + ref.id.posn); - } - - // Check Visibility Status - if(md.isPrivate && cd != currentClassDecl) { - Reporter.emit("Cannot access private member at " + ref.id.posn); - } - - ref.decl = md; - ref.id.decl = md; - ref.spelling = ref.id.spelling; - - return md.type; - } + table.add(pd); + pd.type.visit(this, table); + if (pd.type.typeKind == TypeKind.VOID) { + Reporter.emit("Parameter " + pd.name + " at " + pd.posn + " cannot have type 'void'"); + } - @Override - public Type visitIndexedRef(IndexedRef ref, IdTable table) { - - Type refType = ref.ref.visit(this, table); - ref.spelling = ref.ref.spelling; - - // Must be an array type - if(refType.typeKind != TypeKind.ARRAY) { - Reporter.emit("Trying to index " + refType + " at " + ref.ref.posn); - return refType; - } - - // Index must be an integer value - Type indexType = ref.indexExpr.visit(this, table); - if(indexType.typeKind != TypeKind.INT) { - BaseType type = new BaseType(TypeKind.INT, ref.indexExpr.posn); - Reporter.emit("Expected " + type + " but got " + indexType + " at " + type.posn); - } - - // Array types can be of either classes or ints - ArrayType at = (ArrayType) refType; - if(at.eltType.typeKind == TypeKind.CLASS) { - ClassType ct = (ClassType) at.eltType; - ref.decl = table.getDeclaration(ct.className.spelling); - return ref.decl.type; - } else { - ref.decl = null; - return new BaseType(TypeKind.INT, ref.posn); - } - } + return null; + } - @Override - public Type visitIdRef(IdRef ref, IdTable table) { - - ref.id.visit(this, table); - ref.decl = ref.id.decl; - ref.spelling = ref.id.spelling; - - return ref.decl.type; - } + @Override + public Type visitVarDecl(VarDecl decl, IdTable table) { - @Override - public Type visitThisRef(ThisRef ref, IdTable table) { - - ref.spelling = "this"; - ref.decl = currentClassDecl; - if(currentMethodDecl.isStatic) { - Reporter.emit("'this' cannot be referenced in a static context at " + ref.posn); - } - - return ref.decl.type; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // TERMINALS - // - // ///////////////////////////////////////////////////////////////////////////// - - @Override - public Type visitIdentifier(Identifier id, IdTable table) { - - // An variable cannot be used in its declaration - if(currentVarDecl != null && currentVarDecl.name.equals(id.spelling)) { - Reporter.emit("Cannot use variable in declaration at " + id.posn); - } - - // Try to find declaration (and abort if not found) - id.decl = table.getDeclaration(id.spelling); - if(id.decl == null) { - Reporter.emit(id.spelling + " undefined at " + id.posn); - System.exit(Compiler.rc); - } - - // Cannot access instance method from static context - if(id.decl instanceof MemberDecl) { - MemberDecl md = (MemberDecl) id.decl; - if(currentMethodDecl.isStatic && !md.isStatic) { - Reporter.emit("Cannot access instance member " + md.name + " in a static context at " + id.posn); - } - } - - return id.decl.type; - - } + table.add(decl); + decl.type.visit(this, table); + if (decl.type.typeKind == TypeKind.VOID) { + Reporter.emit("Variable " + decl.name + " at " + decl.posn + " cannot have type 'void'"); + } - @Override - public Type visitOperator(Operator op, IdTable table) { - switch(op.spelling) { - case "!": - case "&&": - case "||": - case ">": - case "<": - case "<=": - case ">=": - case "==": - case "!=": - return new BaseType(TypeKind.BOOLEAN, op.posn); - - case "+": - case "-": - case "*": - case "/": - return new BaseType(TypeKind.INT, op.posn); - - default: - return new BaseType(TypeKind.ERROR, op.posn); - } - } + return null; + } - @Override - public Type visitIntLiteral(IntLiteral num, IdTable table) { - - return new BaseType(TypeKind.INT, num.posn); - } + // ///////////////////////////////////////////////////////////////////////////// + // + // TYPES + // + // ///////////////////////////////////////////////////////////////////////////// - @Override - public Type visitBooleanLiteral(BooleanLiteral bool, IdTable table) { - - return new BaseType(TypeKind.BOOLEAN, bool.posn); - } + @Override + public Type visitBaseType(BaseType type, IdTable table) { - - // ///////////////////////////////////////////////////////////////////////////// - // - // Convenience Functions - // - // ///////////////////////////////////////////////////////////////////////////// - - /** - * - * @param cd - * @param table - */ - private void addDeclarations(ClassDecl cd, IdTable table) { - - table.add(cd); - cd.table = new IdTable(table); - - for(FieldDecl fd : cd.fieldDeclList) { - cd.table.add(fd); - } - - for(MethodDecl md : cd.methodDeclList) { - cd.table.add(md); - md.table = new IdTable(cd.table); - } - } - - /** - * - * @param md - * @return - */ - private boolean isMain(MethodDecl md) { - - // Correct Signature - if(!md.isPrivate && md.isStatic) { - if(md.type.typeKind == TypeKind.VOID) { - if(md.name.equals("main") && md.parameterDeclList.size() == 1) { - - // Check parameter declaration - ParameterDecl pd = md.parameterDeclList.get(0); - if(pd.type.typeKind == TypeKind.ARRAY) { - ArrayType at = (ArrayType) pd.type; - if(at.eltType.typeKind == TypeKind.CLASS) { - ClassType ct = (ClassType) at.eltType; - - return ct.className.spelling.equals("String"); - } - } - } - } - } - - return false; - } - - /** - * - * @param t1 - * @param t2 - * @return - */ - private boolean match(Type t1, Type t2) { - - if(t1.typeKind != t2.typeKind) { - return false; - } + return type; + } - // Check Class Types match - else if(t1.typeKind == TypeKind.CLASS) { - ClassType c1 = (ClassType) t1; - ClassType c2 = (ClassType) t2; - - return c1.className.spelling.equals(c2.className.spelling); - } + @Override + public Type visitClassType(ClassType type, IdTable table) { - // Check Array Types match - else if(t1.typeKind == TypeKind.ARRAY) { - ArrayType a1 = (ArrayType) t1; - ArrayType a2 = (ArrayType) t2; - - return match(a1.eltType, a2.eltType); - } + type.className.visit(this, table); - return true; - } + // Must check that the type is valid + String cn = type.className.spelling; + if (top.getDeclarationAtScope(cn) == null) { + Reporter.emit("Class '" + cn + "' undeclared at " + type.posn); + } + + return type; + } + + @Override + public Type visitArrayType(ArrayType type, IdTable table) { + + type.eltType.visit(this, table); + + return type; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // STATEMENTS + // + // ///////////////////////////////////////////////////////////////////////////// + + @Override + public Type visitBlockStmt(BlockStmt stmt, IdTable table) { + + table.push(); + + for (Statement s : stmt.sl) { + s.visit(this, table); + } + + table.pop(); + + return null; + } + + @Override + public Type visitVardeclStmt(VarDeclStmt stmt, IdTable table) { + + stmt.varDecl.visit(this, table); + + currentVarDecl = stmt.varDecl; + Type exprType = stmt.initExp.visit(this, table); + currentVarDecl = null; + + // Types must match + if (!match(stmt.varDecl.type, exprType)) { + Reporter.emit("Expected " + stmt.varDecl.type + " but got " + exprType + " at " + stmt.initExp.posn); + } + + return null; + } + + @Override + public Type visitAssignStmt(AssignStmt stmt, IdTable table) { + + Type refType = stmt.ref.visit(this, table); + Type valType = stmt.val.visit(this, table); + + if (!match(refType, valType)) { + Reporter.emit("Expected " + refType + " but got " + valType + " at " + stmt.posn); + } + + // Should never assign 'this' to anything + if (stmt.ref instanceof ThisRef) { + Reporter.emit("Cannot assign 'this' to a value at " + stmt.posn); + } + + // Should never assign a method a value + if (stmt.ref.decl instanceof MethodDecl) { + Reporter.emit("Cannot assign a method a value at " + stmt.posn); + } + + // Cannot assign array length field + if (stmt.ref instanceof QualifiedRef) { + QualifiedRef ref = (QualifiedRef) stmt.ref; + if (ref.ref.decl.type.typeKind == TypeKind.ARRAY && ref.id.spelling.equals("length")) { + Reporter.emit("'length' field cannot be changed at " + stmt.posn); + } + } + + return null; + } + + @Override + public Type visitCallStmt(CallStmt stmt, IdTable table) { + + stmt.methodRef.visit(this, table); + + // Check valid parameter count + MethodDecl md = (MethodDecl) stmt.methodRef.decl; + if (md.parameterDeclList.size() != stmt.argList.size()) { + Reporter.emit("Expected " + md.parameterDeclList.size() + " parameters at " + stmt.posn); + return null; + } + + // Check parameter types match + for (int i = 0; i < stmt.argList.size(); i++) { + Expression e = stmt.argList.get(i); + Type exprType = e.visit(this, table); + ParameterDecl pd = md.parameterDeclList.get(i); + + if (!match(pd.type, exprType)) { + Reporter.emit( + "Parameter " + pd.name + " is of type " + pd.type + " but got " + exprType + " at " + e.posn); + } + } + + return null; + } + + @Override + public Type visitIfStmt(IfStmt stmt, IdTable table) { + + // Conditional statement must have type boolean + Type condType = stmt.cond.visit(this, table); + if (condType.typeKind != TypeKind.BOOLEAN) { + Reporter.emit("Expected boolean but got " + condType + " at " + condType.posn); + } + + // A single variable declaration not allowed after conditional statement + if (stmt.thenStmt instanceof VarDeclStmt) { + Reporter.emit("Variable declaration not allowed solely in 'then' clause at " + stmt.thenStmt.posn); + return null; + } + + stmt.thenStmt.visit(this, table); + + // Check else statement + if (stmt.elseStmt != null) { + if (stmt.elseStmt instanceof VarDeclStmt) { + Reporter.emit("Variable declaration not allowed solely in 'else' clause at " + stmt.elseStmt.posn); + return null; + } + + stmt.elseStmt.visit(this, table); + } + + return null; + } + + @Override + public Type visitWhileStmt(WhileStmt stmt, IdTable table) { + + // Conditional statement must have type boolean + Type condType = stmt.cond.visit(this, table); + if (condType.typeKind != TypeKind.BOOLEAN) { + Reporter.emit("Expected boolean but got " + condType + " at " + condType.posn); + } + + if (stmt.body instanceof VarDeclStmt) { + Reporter.emit("Variable declaration not allowed solely in 'while' clause at " + stmt.body.posn); + return null; + } + + stmt.body.visit(this, table); + + return null; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // EXPRESSIONS + // + // ///////////////////////////////////////////////////////////////////////////// + + @Override + public Type visitUnaryExpr(UnaryExpr expr, IdTable table) { + + Type exprType = expr.expr.visit(this, table); + Type opType = expr.operator.visit(this, table); + if (!match(exprType, opType)) { + String op = expr.operator.spelling; + Reporter.emit("Operator " + op + " applies to " + opType + " but got " + exprType + " at " + expr.posn); + } + + return opType; + } + + @Override + public Type visitBinaryExpr(BinaryExpr expr, IdTable table) { + + Type lType = expr.left.visit(this, table); + Type rType = expr.right.visit(this, table); + + BaseType type = null; + String op = expr.operator.spelling; + switch (op) { + + // Equality Operators + case "==": + case "!=": + if (!match(lType, rType)) { + Reporter.emit("Left hand side must be of right hand side's type " + rType + " at " + expr.posn); + } + return new BaseType(TypeKind.BOOLEAN, expr.posn); + + // Boolean Operators + case "&&": + case "||": + type = new BaseType(TypeKind.BOOLEAN, expr.posn); + break; + + // Integer operators + case ">": + case "<": + case "+": + case "-": + case "*": + case "/": + case "<=": + case ">=": + type = new BaseType(TypeKind.INT, expr.posn); + break; + + default: + return new BaseType(TypeKind.ERROR, expr.posn); + } + + // Make sure types match + if (!match(lType, type)) { + Reporter.emit("Expected " + type + " but got " + lType + " at " + expr.posn); + } + + if (!match(rType, type)) { + Reporter.emit("Expected " + type + " but got " + lType + " at " + expr.posn); + } + + // Resulting type + return expr.operator.visit(this, table); + } + + @Override + public Type visitRefExpr(RefExpr expr, IdTable table) { + + Type refType = expr.ref.visit(this, table); + Declaration decl = table.getDeclaration(expr.ref.spelling); + + // Should never reference a class name + if (decl instanceof ClassDecl) { + Reporter.emit("Class declaration referenced at " + expr.posn); + } + + // Should never reference a method name + else if (decl instanceof MethodDecl) { + Reporter.emit("Method declaration referenced at " + expr.posn); + } + + // Cannot access instance members in static context + if (!(expr.ref instanceof QualifiedRef) && decl instanceof FieldDecl) { + FieldDecl fd = (FieldDecl) decl; + if (currentMethodDecl.isStatic && !fd.isStatic) { + Reporter.emit("Cannot access instance member in static context at " + expr.posn); + } + } + + return refType; + } + + @Override + public Type visitCallExpr(CallExpr expr, IdTable table) { + + Type refType = expr.functionRef.visit(this, table); + + // Check parameter count matches + MethodDecl md = (MethodDecl) expr.functionRef.decl; + if (md.parameterDeclList.size() != expr.argList.size()) { + Reporter.emit("Expected " + md.parameterDeclList.size() + " parameters at " + expr.posn); + return refType; + } + + // Check parameter types match + for (int i = 0; i < expr.argList.size(); i++) { + Expression e = expr.argList.get(i); + Type exprType = e.visit(this, table); + ParameterDecl pd = md.parameterDeclList.get(i); + + if (!match(pd.type, exprType)) { + Reporter.emit( + "Parameter " + pd.name + " is of type " + pd.type + " but got " + exprType + " at " + e.posn); + } + } + + return refType; + } + + @Override + public Type visitLiteralExpr(LiteralExpr expr, IdTable table) { + + return expr.literal.visit(this, table); + } + + @Override + public Type visitNewObjectExpr(NewObjectExpr expr, IdTable table) { + + return expr.classtype.visit(this, table); + } + + @Override + public Type visitNewArrayExpr(NewArrayExpr expr, IdTable table) { + + // Arrays only of classes and integers + Type eltType = expr.eltType.visit(this, table); + if (eltType.typeKind != TypeKind.INT && eltType.typeKind != TypeKind.CLASS) { + Reporter.emit("Cannot create array of type " + eltType + " at " + expr.posn); + } + + // Size must be an integer value + Type sizeType = expr.sizeExpr.visit(this, table); + if (sizeType.typeKind != TypeKind.INT) { + BaseType type = new BaseType(TypeKind.INT, expr.sizeExpr.posn); + Reporter.emit("Expected " + type + " but got " + sizeType + " at " + type.posn); + } + + return new ArrayType(eltType, expr.posn); + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // REFERENCES + // + // ///////////////////////////////////////////////////////////////////////////// + + @Override + public Type visitQualifiedRef(QualifiedRef ref, IdTable table) { + + Type refType = ref.ref.visit(this, table); + + // Should not try and access a method in qualified manner + if (ref.ref.decl instanceof MethodDecl) { + Reporter.emit("Cannot use method " + ref.ref.decl.name + " in qualified manner at " + ref.ref.posn); + return new BaseType(TypeKind.ERROR, ref.ref.posn); + } + + // Array types can have a length field + if (refType.typeKind == TypeKind.ARRAY) { + if (!ref.id.spelling.equals("length")) { + Reporter.emit(ref.id.spelling + " attribute not available with arrays at " + ref.id.posn); + return new BaseType(TypeKind.ERROR, ref.id.posn); + } + + return new BaseType(TypeKind.INT, ref.id.posn); + } + + // Otherwise, should have a class type + if (refType.typeKind != TypeKind.CLASS) { + Reporter.emit("Qualified reference not of type class or array at " + ref.posn); + return new BaseType(TypeKind.ERROR, ref.posn); + } + + // Get member in question + ClassType ct = (ClassType) refType; + ClassDecl cd = (ClassDecl) top.getDeclarationAtScope(ct.className.spelling); + if (cd == null) { + Reporter.emit("Accessing non-existant class at " + ct.posn); + return new BaseType(TypeKind.ERROR, ref.posn); + } + + MemberDecl md = (MemberDecl) cd.table.getDeclarationAtScope(ref.id.spelling); + if (md == null) { + Reporter.emit("Accessing non-existant field at " + ref.id.posn); + return new BaseType(TypeKind.ERROR, ref.posn); + } + + // Check if static member + Declaration decl = table.getDeclaration(ref.ref.spelling); + if (decl instanceof ClassDecl && !md.isStatic) { + Reporter.emit("Cannot access non-static member at " + ref.id.posn); + } + + // Check Visibility Status + if (md.isPrivate && cd != currentClassDecl) { + Reporter.emit("Cannot access private member at " + ref.id.posn); + } + + ref.decl = md; + ref.id.decl = md; + ref.spelling = ref.id.spelling; + + return md.type; + } + + @Override + public Type visitIndexedRef(IndexedRef ref, IdTable table) { + + Type refType = ref.ref.visit(this, table); + ref.spelling = ref.ref.spelling; + + // Must be an array type + if (refType.typeKind != TypeKind.ARRAY) { + Reporter.emit("Trying to index " + refType + " at " + ref.ref.posn); + return refType; + } + + // Index must be an integer value + Type indexType = ref.indexExpr.visit(this, table); + if (indexType.typeKind != TypeKind.INT) { + BaseType type = new BaseType(TypeKind.INT, ref.indexExpr.posn); + Reporter.emit("Expected " + type + " but got " + indexType + " at " + type.posn); + } + + // Array types can be of either classes or ints + ArrayType at = (ArrayType) refType; + if (at.eltType.typeKind == TypeKind.CLASS) { + ClassType ct = (ClassType) at.eltType; + ref.decl = table.getDeclaration(ct.className.spelling); + return ref.decl.type; + } else { + ref.decl = null; + return new BaseType(TypeKind.INT, ref.posn); + } + } + + @Override + public Type visitIdRef(IdRef ref, IdTable table) { + + ref.id.visit(this, table); + ref.decl = ref.id.decl; + ref.spelling = ref.id.spelling; + + return ref.decl.type; + } + + @Override + public Type visitThisRef(ThisRef ref, IdTable table) { + + ref.spelling = "this"; + ref.decl = currentClassDecl; + if (currentMethodDecl.isStatic) { + Reporter.emit("'this' cannot be referenced in a static context at " + ref.posn); + } + + return ref.decl.type; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // TERMINALS + // + // ///////////////////////////////////////////////////////////////////////////// + + @Override + public Type visitIdentifier(Identifier id, IdTable table) { + + // An variable cannot be used in its declaration + if (currentVarDecl != null && currentVarDecl.name.equals(id.spelling)) { + Reporter.emit("Cannot use variable in declaration at " + id.posn); + } + + // Try to find declaration (and abort if not found) + id.decl = table.getDeclaration(id.spelling); + if (id.decl == null) { + Reporter.emit(id.spelling + " undefined at " + id.posn); + System.exit(Compiler.rc); + } + + // Cannot access instance method from static context + if (id.decl instanceof MemberDecl) { + MemberDecl md = (MemberDecl) id.decl; + if (currentMethodDecl.isStatic && !md.isStatic) { + Reporter.emit("Cannot access instance member " + md.name + " in a static context at " + id.posn); + } + } + + return id.decl.type; + + } + + @Override + public Type visitOperator(Operator op, IdTable table) { + switch (op.spelling) { + case "!": + case "&&": + case "||": + case ">": + case "<": + case "<=": + case ">=": + case "==": + case "!=": + return new BaseType(TypeKind.BOOLEAN, op.posn); + + case "+": + case "-": + case "*": + case "/": + return new BaseType(TypeKind.INT, op.posn); + + default: + return new BaseType(TypeKind.ERROR, op.posn); + } + } + + @Override + public Type visitIntLiteral(IntLiteral num, IdTable table) { + + return new BaseType(TypeKind.INT, num.posn); + } + + @Override + public Type visitBooleanLiteral(BooleanLiteral bool, IdTable table) { + + return new BaseType(TypeKind.BOOLEAN, bool.posn); + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // Convenience Functions + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * + * @param cd + * @param table + */ + private void addDeclarations(ClassDecl cd, IdTable table) { + + table.add(cd); + cd.table = new IdTable(table); + + for (FieldDecl fd : cd.fieldDeclList) { + cd.table.add(fd); + } + + for (MethodDecl md : cd.methodDeclList) { + cd.table.add(md); + md.table = new IdTable(cd.table); + } + } + + /** + * + * @param md + * @return + */ + private boolean isMain(MethodDecl md) { + + // Correct Signature + if (!md.isPrivate && md.isStatic) { + if (md.type.typeKind == TypeKind.VOID) { + if (md.name.equals("main") && md.parameterDeclList.size() == 1) { + + // Check parameter declaration + ParameterDecl pd = md.parameterDeclList.get(0); + if (pd.type.typeKind == TypeKind.ARRAY) { + ArrayType at = (ArrayType) pd.type; + if (at.eltType.typeKind == TypeKind.CLASS) { + ClassType ct = (ClassType) at.eltType; + + return ct.className.spelling.equals("String"); + } + } + } + } + } + + return false; + } + + /** + * + * @param t1 + * @param t2 + * @return + */ + private boolean match(Type t1, Type t2) { + + if (t1.typeKind != t2.typeKind) { + return false; + } + + // Check Class Types match + else if (t1.typeKind == TypeKind.CLASS) { + ClassType c1 = (ClassType) t1; + ClassType c2 = (ClassType) t2; + + return c1.className.spelling.equals(c2.className.spelling); + } + + // Check Array Types match + else if (t1.typeKind == TypeKind.ARRAY) { + ArrayType a1 = (ArrayType) t1; + ArrayType a2 = (ArrayType) t2; + + return match(a1.eltType, a2.eltType); + } + + return true; + } } diff --git a/src/miniJava/ContextualAnalyzer/IdTable.java b/src/miniJava/ContextualAnalyzer/IdTable.java index 50da518..ee5b2de 100644 --- a/src/miniJava/ContextualAnalyzer/IdTable.java +++ b/src/miniJava/ContextualAnalyzer/IdTable.java @@ -10,118 +10,118 @@ import miniJava.AbstractSyntaxTrees.*; * */ public class IdTable { - - private IdTable parent; - private ArrayList> scope; - - - // ///////////////////////////////////////////////////////////////////////////// - // - // CONSTRUCTORS - // - // ///////////////////////////////////////////////////////////////////////////// - /** - * - */ - public IdTable() { - this(null); - } - - /** - * - * @param parent - */ - public IdTable(IdTable parent) { - this.parent = parent; - this.scope = new ArrayList<>(); - push(); - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // ACTIVE SCOPE - // - // ///////////////////////////////////////////////////////////////////////////// + private IdTable parent; + private ArrayList> scope; - /** - * - */ - public void pop() { - int last = scope.size() - 1; - scope.remove(last); - } - - /** - * - */ - public void push() { - HashMap nested = new HashMap<>(); - scope.add(nested); - } - - /** - * - */ - public void add(Declaration decl) { - for(int i = 0; i < scope.size(); i++) { - HashMap nest = scope.get(i); - if(nest.containsKey(decl.name)) { - - Declaration prev = nest.get(decl.name); - - if(decl instanceof ClassDecl) { - Reporter.report(decl, prev, "Class"); - } else if(decl instanceof FieldDecl) { - Reporter.report(decl, prev, "Field"); - } else if(decl instanceof MethodDecl) { - Reporter.report(decl, prev, "Method"); - } else if(decl instanceof ParameterDecl) { - Reporter.report(decl, prev, "Parameter"); - } else if(decl instanceof VarDecl) { - Reporter.report(decl, prev, "Variable"); - } - - System.exit(Compiler.rc); - } - } - - scope.get(scope.size()-1).put(decl.name, decl); - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // GETTERS - // - // ///////////////////////////////////////////////////////////////////////////// + // ///////////////////////////////////////////////////////////////////////////// + // + // CONSTRUCTORS + // + // ///////////////////////////////////////////////////////////////////////////// - /** - * - * @param name - */ - public Declaration getDeclaration(String name) { - IdTable current = this; - while (current != null) { - Declaration decl = current.getDeclarationAtScope(name); - if (decl == null) current = current.parent; - else return decl; - } + /** + * + */ + public IdTable() { + this(null); + } - return null; - } - - /** - * - * @param name - */ - public Declaration getDeclarationAtScope(String name) { - for (int i = scope.size() - 1; i >= 0; i--) { - HashMap nest = scope.get(i); - if (nest.containsKey(name)) return nest.get(name); - } - - return null; - } + /** + * + * @param parent + */ + public IdTable(IdTable parent) { + this.parent = parent; + this.scope = new ArrayList<>(); + push(); + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // ACTIVE SCOPE + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * + */ + public void pop() { + int last = scope.size() - 1; + scope.remove(last); + } + + /** + * + */ + public void push() { + HashMap nested = new HashMap<>(); + scope.add(nested); + } + + /** + * + */ + public void add(Declaration decl) { + for (int i = 0; i < scope.size(); i++) { + HashMap nest = scope.get(i); + if (nest.containsKey(decl.name)) { + + Declaration prev = nest.get(decl.name); + + if (decl instanceof ClassDecl) { + Reporter.report(decl, prev, "Class"); + } else if (decl instanceof FieldDecl) { + Reporter.report(decl, prev, "Field"); + } else if (decl instanceof MethodDecl) { + Reporter.report(decl, prev, "Method"); + } else if (decl instanceof ParameterDecl) { + Reporter.report(decl, prev, "Parameter"); + } else if (decl instanceof VarDecl) { + Reporter.report(decl, prev, "Variable"); + } + + System.exit(Compiler.rc); + } + } + + scope.get(scope.size() - 1).put(decl.name, decl); + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // GETTERS + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * + * @param name + */ + public Declaration getDeclaration(String name) { + IdTable current = this; + while (current != null) { + Declaration decl = current.getDeclarationAtScope(name); + if (decl == null) + current = current.parent; + else + return decl; + } + + return null; + } + + /** + * + * @param name + */ + public Declaration getDeclarationAtScope(String name) { + for (int i = scope.size() - 1; i >= 0; i--) { + HashMap nest = scope.get(i); + if (nest.containsKey(name)) + return nest.get(name); + } + + return null; + } } diff --git a/src/miniJava/ContextualAnalyzer/Reporter.java b/src/miniJava/ContextualAnalyzer/Reporter.java index 0b65f4b..b467edc 100644 --- a/src/miniJava/ContextualAnalyzer/Reporter.java +++ b/src/miniJava/ContextualAnalyzer/Reporter.java @@ -3,25 +3,26 @@ package miniJava.ContextualAnalyzer; import miniJava.AbstractSyntaxTrees.Declaration; public class Reporter { - - public static boolean error = false; - - /** - * - * @param message - */ - public static void emit(String message) { - error = true; - System.out.println("***" + message); - } - - /** - * Redefinitions - * @param d1 - * @param d2 - */ - public static void report(Declaration d1, Declaration d2, String prefix) { - emit(prefix + " at " + d1.posn + " previously defined at " + d2.posn); - } + + public static boolean error = false; + + /** + * + * @param message + */ + public static void emit(String message) { + error = true; + System.out.println("***" + message); + } + + /** + * Redefinitions + * + * @param d1 + * @param d2 + */ + public static void report(Declaration d1, Declaration d2, String prefix) { + emit(prefix + " at " + d1.posn + " previously defined at " + d2.posn); + } } diff --git a/src/miniJava/SyntacticAnalyzer/Parser.java b/src/miniJava/SyntacticAnalyzer/Parser.java index 524163f..e4ae5c9 100644 --- a/src/miniJava/SyntacticAnalyzer/Parser.java +++ b/src/miniJava/SyntacticAnalyzer/Parser.java @@ -11,15 +11,9 @@ import miniJava.AbstractSyntaxTrees.Package; * * Program ::= (ClassDeclaration)* eot * - * ClassDeclaration ::= - * class id { - * (Declarators id (; | MethodDeclaration))* - * } + * ClassDeclaration ::= class id { (Declarators id (; | MethodDeclaration))* } * - * MethodDeclaration ::= - * (ParameterList?) { - * Statement* (return Expression ;)? - * } + * MethodDeclaration ::= (ParameterList?) { Statement* (return Expression ;)? } * * Declarators ::= (public | private)? static? Type * @@ -33,20 +27,13 @@ import miniJava.AbstractSyntaxTrees.Package; * * BaseRef ::= this | id ([ Expression])? * - * Statement ::= - * {Statement*} - * | Type id = Expression; - * | Reference = Expression; - * | Reference ( ArgumentList? ); - * | if (Expression) Statement (else Statement)? - * | while (Expression) Statement + * Statement ::= {Statement*} | Type id = Expression; | Reference = Expression; + * | Reference ( ArgumentList? ); | if (Expression) Statement (else Statement)? + * | while (Expression) Statement * - * Expression ::= - * num | true | false - * | ( Expression ) - * | new (id() | int [ Expression ] | id [ Expression ] ) - * | Reference ((ArgumentList?))? - * | DExpression + * Expression ::= num | true | false | ( Expression ) | new (id() | int [ + * Expression ] | id [ Expression ] ) | Reference ((ArgumentList?))? | + * DExpression * * DExpression ::= CExpression (|| CExpression)* * @@ -60,756 +47,757 @@ import miniJava.AbstractSyntaxTrees.Package; * * MExpression ::= Expression ((*|/) Expression)* * -*/ + */ public class Parser { - - private Scanner scanner; - private LinkedList stream; - - /** - * - * @param scanner - */ - public Parser(Scanner scanner) { - this.scanner = scanner; - this.stream = new LinkedList(); - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // Package - // - // ///////////////////////////////////////////////////////////////////////////// - - /** - * - * @return - * @throws IOException - */ - public Package parse() throws IOException { - - ClassDeclList decls = new ClassDeclList(); - while (peek(1).type == Token.TYPE.CLASS) { - decls.add(parseClassDeclaration()); - } - accept(Token.TYPE.EOT); - return new Package(decls, new SourcePosition(0, 0)); - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // DECLARATIONS - // - // ///////////////////////////////////////////////////////////////////////////// + private Scanner scanner; + private LinkedList stream; - /** - * - * @return - * @throws IOException - */ - public ClassDecl parseClassDeclaration() throws IOException { - - // Class Header - Token classToken = accept(Token.TYPE.CLASS); - String className = accept(Token.TYPE.ID).spelling; - - // Class Body - accept(Token.TYPE.LBRACKET); - - FieldDeclList fdl = new FieldDeclList(); - MethodDeclList mdl = new MethodDeclList(); - - // Haven't reached end of body - while (peek(1).type != Token.TYPE.RBRACKET) { - Declarators d = parseDeclarators(); - String memberName = accept(Token.TYPE.ID).spelling; - - // Field Declaration - FieldDecl fd = new FieldDecl(d, memberName); - if(peek(1).type == Token.TYPE.SEMICOLON) { - accept(Token.TYPE.SEMICOLON); - fdl.add(fd); - } - - // Method Declaration - else { - MethodDecl md = parseMethodDeclaration(fd); - mdl.add(md); - } - } - - accept(Token.TYPE.RBRACKET); - - // Build Class - ClassDecl decl = new ClassDecl(className, fdl, mdl, classToken.posn); - Identifier ident = new Identifier(className, classToken.posn); - decl.type = new ClassType(ident, classToken.posn); - - return decl; - } - - /** - * - * @return - * @throws IOException - */ - private Declarators parseDeclarators() throws IOException { - - boolean isStatic = false; - boolean isPrivate = false; - SourcePosition start = peek(1).posn; - - // Visibility - if (peek(1).type == Token.TYPE.PUBLIC) { - accept(Token.TYPE.PUBLIC); - } else if (peek(1).type == Token.TYPE.PRIVATE) { - isPrivate = true; - accept(Token.TYPE.PRIVATE); - } - - // Static - if (peek(1).type == Token.TYPE.STATIC) { - isStatic = true; - accept(Token.TYPE.STATIC); - } + /** + * + * @param scanner + */ + public Parser(Scanner scanner) { + this.scanner = scanner; + this.stream = new LinkedList(); + } - return new Declarators(isPrivate, isStatic, parseType(), start); - } - - /** - * - * @param f - * @return - * @throws IOException - */ - private MethodDecl parseMethodDeclaration(FieldDecl f) throws IOException { - - Expression returnExpr = null; - StatementList stl = new StatementList(); - - // Parameters - accept(Token.TYPE.LPAREN); - - ParameterDeclList pdl = new ParameterDeclList(); - if (peek(1).type != Token.TYPE.RPAREN) { - pdl = parseParameterList(); - } + // ///////////////////////////////////////////////////////////////////////////// + // + // Package + // + // ///////////////////////////////////////////////////////////////////////////// - accept(Token.TYPE.RPAREN); - - // Method Body - accept(Token.TYPE.LBRACKET); - - while (peek(1).type != Token.TYPE.RBRACKET) { - if (peek(1).type == Token.TYPE.RETURN) { - accept(Token.TYPE.RETURN); - returnExpr = parseExpression(); - accept(Token.TYPE.SEMICOLON); - break; - } - - stl.add(parseStatement()); - } - - accept(Token.TYPE.RBRACKET); + /** + * + * @return + * @throws IOException + */ + public Package parse() throws IOException { - return new MethodDecl(f, pdl, stl, returnExpr, f.posn); - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // TYPES - // - // ///////////////////////////////////////////////////////////////////////////// + ClassDeclList decls = new ClassDeclList(); + while (peek(1).type == Token.TYPE.CLASS) { + decls.add(parseClassDeclaration()); + } - /** - * - * @return - * @throws IOException - */ - private Type parseType() throws IOException { - - switch(peek(1).type) { - - case VOID: { - Token next = accept(Token.TYPE.VOID); - return new BaseType(TypeKind.VOID, next.posn); - } - - case BOOLEAN: { - Token next = accept(Token.TYPE.BOOLEAN); - return new BaseType(TypeKind.BOOLEAN, next.posn); - } - - case INT: { - Token next = accept(Token.TYPE.INT); - BaseType bt = new BaseType(TypeKind.INT, next.posn); - - if (peek(1).type == Token.TYPE.LSQUARE) { - accept(Token.TYPE.LSQUARE); - accept(Token.TYPE.RSQUARE); - return new ArrayType(bt, next.posn); - } - - return bt; - } - - case ID: { - Token next = accept(Token.TYPE.ID); - Identifier ident = new Identifier(next.spelling, next.posn); - ClassType ct = new ClassType(ident, ident.posn); - - if (peek(1).type == Token.TYPE.LSQUARE) { - accept(Token.TYPE.LSQUARE); - accept(Token.TYPE.RSQUARE); - return new ArrayType(ct, ident.posn); - } - - return ct; - } - - default: { - Token next = peek(1); - throw new ParsingException(next.posn); - } - } - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // Arguments - // - // ///////////////////////////////////////////////////////////////////////////// - - /** - * - * @return - * @throws IOException - */ - private ParameterDeclList parseParameterList() throws IOException { - - ParameterDeclList decls = new ParameterDeclList(); + accept(Token.TYPE.EOT); + return new Package(decls, new SourcePosition(0, 0)); + } - // First Parameter - Type fpt = parseType(); - Token next = accept(Token.TYPE.ID); - decls.add(new ParameterDecl(fpt, next.spelling, fpt.posn)); + // ///////////////////////////////////////////////////////////////////////////// + // + // DECLARATIONS + // + // ///////////////////////////////////////////////////////////////////////////// - // Remainder of List - while(peek(1).type == Token.TYPE.COMMA) { - accept(Token.TYPE.COMMA); - Type type = parseType(); - Token id = accept(Token.TYPE.ID); - decls.add(new ParameterDecl(type, id.spelling, type.posn)); - } + /** + * + * @return + * @throws IOException + */ + public ClassDecl parseClassDeclaration() throws IOException { - return decls; - } + // Class Header + Token classToken = accept(Token.TYPE.CLASS); + String className = accept(Token.TYPE.ID).spelling; - /** - * - * @return - * @throws IOException - */ - private ExprList parseArgumentList() throws IOException { - - ExprList el = new ExprList(); - el.add(parseExpression()); - - // Rest of argument list - while(peek(1).type == Token.TYPE.COMMA) { - accept(Token.TYPE.COMMA); - el.add(parseExpression()); - } + // Class Body + accept(Token.TYPE.LBRACKET); - return el; - } - + FieldDeclList fdl = new FieldDeclList(); + MethodDeclList mdl = new MethodDeclList(); - // ///////////////////////////////////////////////////////////////////////////// - // - // REFERENCES - // - // ///////////////////////////////////////////////////////////////////////////// + // Haven't reached end of body + while (peek(1).type != Token.TYPE.RBRACKET) { + Declarators d = parseDeclarators(); + String memberName = accept(Token.TYPE.ID).spelling; - /** - * - * @return - * @throws IOException - */ - private Reference parseReference() throws IOException { - - Reference ref = parseBaseRef(); - - while (peek(1).type == Token.TYPE.PERIOD) { - accept(Token.TYPE.PERIOD); - Token next = accept(Token.TYPE.ID); - Identifier ident = new Identifier(next.spelling, next.posn); - ref = new QualifiedRef(ref, ident, next.posn); + // Field Declaration + FieldDecl fd = new FieldDecl(d, memberName); + if (peek(1).type == Token.TYPE.SEMICOLON) { + accept(Token.TYPE.SEMICOLON); + fdl.add(fd); + } - // Must be indexed - if (peek(1).type == Token.TYPE.LSQUARE) { - accept(Token.TYPE.LSQUARE); - Expression expr = parseExpression(); - accept(Token.TYPE.RSQUARE); - ref = new IndexedRef(ref, expr, next.posn); - } - } + // Method Declaration + else { + MethodDecl md = parseMethodDeclaration(fd); + mdl.add(md); + } + } - return ref; - } + accept(Token.TYPE.RBRACKET); - /** - * - * @return - * @throws IOException - */ - private Reference parseBaseRef() throws IOException { - - if(peek(1).type == Token.TYPE.THIS) { - Token next = accept(Token.TYPE.THIS); - return new ThisRef(next.posn); - } - - Token next = accept(Token.TYPE.ID); - Identifier ident = new Identifier(next.spelling, next.posn); - IdRef ref = new IdRef(ident, ident.posn); + // Build Class + ClassDecl decl = new ClassDecl(className, fdl, mdl, classToken.posn); + Identifier ident = new Identifier(className, classToken.posn); + decl.type = new ClassType(ident, classToken.posn); - // Must be indexed - if (peek(1).type == Token.TYPE.LSQUARE) { - accept(Token.TYPE.LSQUARE); - Expression expr = parseExpression(); - accept(Token.TYPE.RSQUARE); - return new IndexedRef(ref, expr, next.posn); - } + return decl; + } - return ref; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // STATEMENTS - // - // ///////////////////////////////////////////////////////////////////////////// - - /** - * - * @return - * @throws IOException - */ - private Statement parseBlockStatement() throws IOException { - - StatementList stl = new StatementList(); - Token left = accept(Token.TYPE.LBRACKET); - - while(peek(1).type != Token.TYPE.RBRACKET) { - stl.add(parseStatement()); - } - - accept(Token.TYPE.RBRACKET); - - return new BlockStmt(stl, left.posn); - } - - /** - * - * @return - * @throws IOException - */ - private Statement parseIfStatement() throws IOException { - - Token next = accept(Token.TYPE.IF); - - // Conditional - accept(Token.TYPE.LPAREN); - Expression expr = parseExpression(); - accept(Token.TYPE.RPAREN); - - // Body - Statement s1 = parseStatement(); - - // Else Statement - if (peek(1).type == Token.TYPE.ELSE) { - accept(Token.TYPE.ELSE); - Statement s2 = parseStatement(); - return new IfStmt(expr, s1, s2, next.posn); - } + /** + * + * @return + * @throws IOException + */ + private Declarators parseDeclarators() throws IOException { - return new IfStmt(expr, s1, next.posn); - } - - /** - * - * @return - * @throws IOException - */ - private Statement parseWhileStatement() throws IOException { - - Token next = accept(Token.TYPE.WHILE); - - // Conditional - accept(Token.TYPE.LPAREN); - Expression e = parseExpression(); - accept(Token.TYPE.RPAREN); - - // Body - Statement s = parseStatement(); + boolean isStatic = false; + boolean isPrivate = false; + SourcePosition start = peek(1).posn; - return new WhileStmt(e, s, next.posn); - } - - /** - * - * @return - * @throws IOException - */ - private Statement parseVarDeclStatement() throws IOException { - - Type type = parseType(); - String name = accept(Token.TYPE.ID).spelling; - VarDecl v = new VarDecl(type, name, type.posn); - - accept(Token.TYPE.EQUALS); - Expression expr = parseExpression(); - accept(Token.TYPE.SEMICOLON); + // Visibility + if (peek(1).type == Token.TYPE.PUBLIC) { + accept(Token.TYPE.PUBLIC); + } else if (peek(1).type == Token.TYPE.PRIVATE) { + isPrivate = true; + accept(Token.TYPE.PRIVATE); + } - return new VarDeclStmt(v, expr, type.posn); - } - - /** - * - * @return - * @throws IOException - */ - private Statement parseReferenceStatement() throws IOException { - - Statement stmt = null; - Reference ref = parseReference(); + // Static + if (peek(1).type == Token.TYPE.STATIC) { + isStatic = true; + accept(Token.TYPE.STATIC); + } - // Reference ( ArgumentList? ) ; - if (peek(1).type == Token.TYPE.LPAREN) { - ExprList el = new ExprList(); - accept(Token.TYPE.LPAREN); - if(peek(1).type != Token.TYPE.RPAREN) { - el = parseArgumentList(); - } - accept(Token.TYPE.RPAREN); - stmt = new CallStmt(ref, el, ref.posn); - } + return new Declarators(isPrivate, isStatic, parseType(), start); + } - // Reference = Expression; - else { - accept(Token.TYPE.EQUALS); - Expression expr = parseExpression(); - stmt = new AssignStmt(ref, expr, ref.posn); - } + /** + * + * @param f + * @return + * @throws IOException + */ + private MethodDecl parseMethodDeclaration(FieldDecl f) throws IOException { - accept(Token.TYPE.SEMICOLON); - return stmt; - } - - /** - * - * @return - * @throws IOException - */ - private Statement parseStatement() throws IOException { - - switch (peek(1).type) { - - // { Statement* } - case LBRACKET: { - return parseBlockStatement(); - } - - // if (Expression) Statement (else Statement)? - case IF: { - return parseIfStatement(); - } - - // while (Expression) Statement - case WHILE: { - return parseWhileStatement(); - } - - // Type id = Expression; - case BOOLEAN: - case VOID: - case INT: - case ID: { - - Token.TYPE fst = peek(1).type; - Token.TYPE snd = peek(2).type; - Token.TYPE thd = peek(3).type; - - if(fst != Token.TYPE.ID || snd == Token.TYPE.ID) { - return parseVarDeclStatement(); - } else if(snd == Token.TYPE.LSQUARE && thd == Token.TYPE.RSQUARE) { - return parseVarDeclStatement(); - } - - /* Fall Through */ - } - - default: { - return parseReferenceStatement(); - } - } - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // EXPRESSIONS - // - // ///////////////////////////////////////////////////////////////////////////// + Expression returnExpr = null; + StatementList stl = new StatementList(); - private Expression parseSingleExpression() throws IOException { + // Parameters + accept(Token.TYPE.LPAREN); - switch (peek(1).type) { - - case NUM: { - Token next = accept(Token.TYPE.NUM); - IntLiteral il = new IntLiteral(next.spelling, next.posn); - return new LiteralExpr(il, next.posn); - } - - case TRUE: - case FALSE: { - Token next = accept(peek(1).type); - BooleanLiteral bl = new BooleanLiteral(next.spelling, next.posn); - return new LiteralExpr(bl, next.posn); - } - - // ( Expression ) - case LPAREN: { - accept(Token.TYPE.LPAREN); - Expression expr = parseExpression(); - accept(Token.TYPE.RPAREN); - - return expr; - } - - // unop Expression - case UNOP: - case BINOP: { - if (peek(1).spelling.equals("!") || peek(1).spelling.equals("-")) { - Token next = accept(peek(1).type); - Operator o = new Operator(next, next.posn); - Expression expr = parseSingleExpression(); - return new UnaryExpr(o, expr, next.posn); - } else { - throw new ParsingException(peek(1).posn); - } - } - - // new ( int [ Expression ] | id ( ) | id [ Expression ] ) - case NEW: { - - Token next = accept(Token.TYPE.NEW); - - if (peek(1).type == Token.TYPE.INT) { - accept(Token.TYPE.INT); - accept(Token.TYPE.LSQUARE); - Expression expr = parseExpression(); - accept(Token.TYPE.RSQUARE); - - BaseType b = new BaseType(TypeKind.INT, next.posn); - return new NewArrayExpr(b, expr, next.posn); - } - - else { - Token id = accept(Token.TYPE.ID); - Identifier ident = new Identifier(id.spelling, id.posn); - ClassType ct = new ClassType(ident, id.posn); - - if (peek(1).type == Token.TYPE.LPAREN) { - accept(Token.TYPE.LPAREN); - accept(Token.TYPE.RPAREN); - return new NewObjectExpr(ct, next.posn); - } else { - accept(Token.TYPE.LSQUARE); - Expression expr = parseExpression(); - accept(Token.TYPE.RSQUARE); - return new NewArrayExpr(ct, expr, next.posn); - } - } - } - - // Reference ((ArgumentList?))? - case THIS: - case ID: { - - Reference ref = parseReference(); - - if (peek(1).type == Token.TYPE.LPAREN) { - accept(Token.TYPE.LPAREN); - ExprList el = new ExprList(); - if (peek(1).type != Token.TYPE.RPAREN) { - el = parseArgumentList(); - } - accept(Token.TYPE.RPAREN); - return new CallExpr(ref, el, ref.posn); - } else { - return new RefExpr(ref, ref.posn); - } - } - - default: throw new ParsingException(peek(1).posn); - } - } - - /** - * Disjunctive - * @return - * @throws IOException - */ - private Expression parseExpression() throws IOException { - - Expression expr = parseCExpression(); - - while (peek(1).spelling.equals("||")) { - Token next = accept(Token.TYPE.BINOP); - Operator o = new Operator(next, next.posn); - expr = new BinaryExpr(o, expr, parseCExpression(), expr.posn); - } + ParameterDeclList pdl = new ParameterDeclList(); + if (peek(1).type != Token.TYPE.RPAREN) { + pdl = parseParameterList(); + } - return expr; - } + accept(Token.TYPE.RPAREN); - /** - * Conjunctive - * @return - * @throws IOException - */ - private Expression parseCExpression() throws IOException { + // Method Body + accept(Token.TYPE.LBRACKET); - Expression expr = parseEExpression(); - - while (peek(1).spelling.equals("&&")) { - Token next = accept(Token.TYPE.BINOP); - Operator o = new Operator(next, next.posn); - expr = new BinaryExpr(o, expr, parseEExpression(), expr.posn); - } + while (peek(1).type != Token.TYPE.RBRACKET) { + if (peek(1).type == Token.TYPE.RETURN) { + accept(Token.TYPE.RETURN); + returnExpr = parseExpression(); + accept(Token.TYPE.SEMICOLON); + break; + } - return expr; - } + stl.add(parseStatement()); + } - /** - * Equality - * @return - * @throws IOException - */ - private Expression parseEExpression() throws IOException { + accept(Token.TYPE.RBRACKET); - Expression expr = parseRExpression(); - - while (peek(1).spelling.equals("==") || peek(1).spelling.equals("!=")) { - Token next = accept(Token.TYPE.BINOP); - Operator o = new Operator(next, next.posn); - expr = new BinaryExpr(o, expr, parseRExpression(), expr.posn); - } + return new MethodDecl(f, pdl, stl, returnExpr, f.posn); + } - return expr; - } - - /** - * Relational - * @return - * @throws IOException - */ - private Expression parseRExpression() throws IOException { + // ///////////////////////////////////////////////////////////////////////////// + // + // TYPES + // + // ///////////////////////////////////////////////////////////////////////////// - Expression expr = parseAExpression(); - - while(peek(1).spelling.equals("<") || peek(1).spelling.equals("<=") - || peek(1).spelling.equals(">") || peek(1).spelling.equals(">=")) { - Token next = accept(Token.TYPE.BINOP); - Operator o = new Operator(next, next.posn); - expr = new BinaryExpr(o, expr, parseAExpression(), expr.posn); - } + /** + * + * @return + * @throws IOException + */ + private Type parseType() throws IOException { - return expr; - } + switch (peek(1).type) { - /** - * Additive - * @return - * @throws IOException - */ - private Expression parseAExpression() throws IOException { + case VOID: { + Token next = accept(Token.TYPE.VOID); + return new BaseType(TypeKind.VOID, next.posn); + } - Expression expr = parseMExpression(); - - while (peek(1).spelling.equals("+") || peek(1).spelling.equals("-")) { - Token next = accept(Token.TYPE.BINOP); - Operator o = new Operator(next, next.posn); - expr = new BinaryExpr(o, expr, parseMExpression(), expr.posn); - } + case BOOLEAN: { + Token next = accept(Token.TYPE.BOOLEAN); + return new BaseType(TypeKind.BOOLEAN, next.posn); + } - return expr; - } + case INT: { + Token next = accept(Token.TYPE.INT); + BaseType bt = new BaseType(TypeKind.INT, next.posn); - /** - * Multiplicative - * @return - * @throws IOException - */ - private Expression parseMExpression() throws IOException { - - Expression expr = parseSingleExpression(); - - while (peek(1).spelling.equals("*") || peek(1).spelling.equals("/")) { - Token next = accept(Token.TYPE.BINOP); - Operator o = new Operator(next, next.posn); - expr = new BinaryExpr(o, expr, parseSingleExpression(), expr.posn); - } + if (peek(1).type == Token.TYPE.LSQUARE) { + accept(Token.TYPE.LSQUARE); + accept(Token.TYPE.RSQUARE); + return new ArrayType(bt, next.posn); + } - return expr; - } - - - // ///////////////////////////////////////////////////////////////////////////// - // - // Convenience Methods - // - // ///////////////////////////////////////////////////////////////////////////// - - /** - * - * @param lookahead - * @return - * @throws IOException - */ - private Token peek(int lookahead) throws IOException { + return bt; + } - // Cache tokens - while (stream.size() < lookahead) { - Token next = scanner.scan(); - stream.addLast(next); - } + case ID: { + Token next = accept(Token.TYPE.ID); + Identifier ident = new Identifier(next.spelling, next.posn); + ClassType ct = new ClassType(ident, ident.posn); - return stream.get(lookahead - 1); - } + if (peek(1).type == Token.TYPE.LSQUARE) { + accept(Token.TYPE.LSQUARE); + accept(Token.TYPE.RSQUARE); + return new ArrayType(ct, ident.posn); + } - /** - * - * @param type - * @return - * @throws IOException - */ - private Token accept(Token.TYPE type) throws IOException { - - Token next = peek(1); - if(next.type == type) stream.poll(); - else throw new ParsingException(next.posn); + return ct; + } - return next; - } + default: { + Token next = peek(1); + throw new ParsingException(next.posn); + } + } + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // Arguments + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * + * @return + * @throws IOException + */ + private ParameterDeclList parseParameterList() throws IOException { + + ParameterDeclList decls = new ParameterDeclList(); + + // First Parameter + Type fpt = parseType(); + Token next = accept(Token.TYPE.ID); + decls.add(new ParameterDecl(fpt, next.spelling, fpt.posn)); + + // Remainder of List + while (peek(1).type == Token.TYPE.COMMA) { + accept(Token.TYPE.COMMA); + Type type = parseType(); + Token id = accept(Token.TYPE.ID); + decls.add(new ParameterDecl(type, id.spelling, type.posn)); + } + + return decls; + } + + /** + * + * @return + * @throws IOException + */ + private ExprList parseArgumentList() throws IOException { + + ExprList el = new ExprList(); + el.add(parseExpression()); + + // Rest of argument list + while (peek(1).type == Token.TYPE.COMMA) { + accept(Token.TYPE.COMMA); + el.add(parseExpression()); + } + + return el; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // REFERENCES + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * + * @return + * @throws IOException + */ + private Reference parseReference() throws IOException { + + Reference ref = parseBaseRef(); + + while (peek(1).type == Token.TYPE.PERIOD) { + accept(Token.TYPE.PERIOD); + Token next = accept(Token.TYPE.ID); + Identifier ident = new Identifier(next.spelling, next.posn); + ref = new QualifiedRef(ref, ident, next.posn); + + // Must be indexed + if (peek(1).type == Token.TYPE.LSQUARE) { + accept(Token.TYPE.LSQUARE); + Expression expr = parseExpression(); + accept(Token.TYPE.RSQUARE); + ref = new IndexedRef(ref, expr, next.posn); + } + } + + return ref; + } + + /** + * + * @return + * @throws IOException + */ + private Reference parseBaseRef() throws IOException { + + if (peek(1).type == Token.TYPE.THIS) { + Token next = accept(Token.TYPE.THIS); + return new ThisRef(next.posn); + } + + Token next = accept(Token.TYPE.ID); + Identifier ident = new Identifier(next.spelling, next.posn); + IdRef ref = new IdRef(ident, ident.posn); + + // Must be indexed + if (peek(1).type == Token.TYPE.LSQUARE) { + accept(Token.TYPE.LSQUARE); + Expression expr = parseExpression(); + accept(Token.TYPE.RSQUARE); + return new IndexedRef(ref, expr, next.posn); + } + + return ref; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // STATEMENTS + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * + * @return + * @throws IOException + */ + private Statement parseBlockStatement() throws IOException { + + StatementList stl = new StatementList(); + Token left = accept(Token.TYPE.LBRACKET); + + while (peek(1).type != Token.TYPE.RBRACKET) { + stl.add(parseStatement()); + } + + accept(Token.TYPE.RBRACKET); + + return new BlockStmt(stl, left.posn); + } + + /** + * + * @return + * @throws IOException + */ + private Statement parseIfStatement() throws IOException { + + Token next = accept(Token.TYPE.IF); + + // Conditional + accept(Token.TYPE.LPAREN); + Expression expr = parseExpression(); + accept(Token.TYPE.RPAREN); + + // Body + Statement s1 = parseStatement(); + + // Else Statement + if (peek(1).type == Token.TYPE.ELSE) { + accept(Token.TYPE.ELSE); + Statement s2 = parseStatement(); + return new IfStmt(expr, s1, s2, next.posn); + } + + return new IfStmt(expr, s1, next.posn); + } + + /** + * + * @return + * @throws IOException + */ + private Statement parseWhileStatement() throws IOException { + + Token next = accept(Token.TYPE.WHILE); + + // Conditional + accept(Token.TYPE.LPAREN); + Expression e = parseExpression(); + accept(Token.TYPE.RPAREN); + + // Body + Statement s = parseStatement(); + + return new WhileStmt(e, s, next.posn); + } + + /** + * + * @return + * @throws IOException + */ + private Statement parseVarDeclStatement() throws IOException { + + Type type = parseType(); + String name = accept(Token.TYPE.ID).spelling; + VarDecl v = new VarDecl(type, name, type.posn); + + accept(Token.TYPE.EQUALS); + Expression expr = parseExpression(); + accept(Token.TYPE.SEMICOLON); + + return new VarDeclStmt(v, expr, type.posn); + } + + /** + * + * @return + * @throws IOException + */ + private Statement parseReferenceStatement() throws IOException { + + Statement stmt = null; + Reference ref = parseReference(); + + // Reference ( ArgumentList? ) ; + if (peek(1).type == Token.TYPE.LPAREN) { + ExprList el = new ExprList(); + accept(Token.TYPE.LPAREN); + if (peek(1).type != Token.TYPE.RPAREN) { + el = parseArgumentList(); + } + accept(Token.TYPE.RPAREN); + stmt = new CallStmt(ref, el, ref.posn); + } + + // Reference = Expression; + else { + accept(Token.TYPE.EQUALS); + Expression expr = parseExpression(); + stmt = new AssignStmt(ref, expr, ref.posn); + } + + accept(Token.TYPE.SEMICOLON); + return stmt; + } + + /** + * + * @return + * @throws IOException + */ + private Statement parseStatement() throws IOException { + + switch (peek(1).type) { + + // { Statement* } + case LBRACKET: { + return parseBlockStatement(); + } + + // if (Expression) Statement (else Statement)? + case IF: { + return parseIfStatement(); + } + + // while (Expression) Statement + case WHILE: { + return parseWhileStatement(); + } + + // Type id = Expression; + case BOOLEAN: + case VOID: + case INT: + case ID: { + + Token.TYPE fst = peek(1).type; + Token.TYPE snd = peek(2).type; + Token.TYPE thd = peek(3).type; + + if (fst != Token.TYPE.ID || snd == Token.TYPE.ID) { + return parseVarDeclStatement(); + } else if (snd == Token.TYPE.LSQUARE && thd == Token.TYPE.RSQUARE) { + return parseVarDeclStatement(); + } + + /* Fall Through */ + } + + default: { + return parseReferenceStatement(); + } + } + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // EXPRESSIONS + // + // ///////////////////////////////////////////////////////////////////////////// + + private Expression parseSingleExpression() throws IOException { + + switch (peek(1).type) { + + case NUM: { + Token next = accept(Token.TYPE.NUM); + IntLiteral il = new IntLiteral(next.spelling, next.posn); + return new LiteralExpr(il, next.posn); + } + + case TRUE: + case FALSE: { + Token next = accept(peek(1).type); + BooleanLiteral bl = new BooleanLiteral(next.spelling, next.posn); + return new LiteralExpr(bl, next.posn); + } + + // ( Expression ) + case LPAREN: { + accept(Token.TYPE.LPAREN); + Expression expr = parseExpression(); + accept(Token.TYPE.RPAREN); + + return expr; + } + + // unop Expression + case UNOP: + case BINOP: { + if (peek(1).spelling.equals("!") || peek(1).spelling.equals("-")) { + Token next = accept(peek(1).type); + Operator o = new Operator(next, next.posn); + Expression expr = parseSingleExpression(); + return new UnaryExpr(o, expr, next.posn); + } else { + throw new ParsingException(peek(1).posn); + } + } + + // new ( int [ Expression ] | id ( ) | id [ Expression ] ) + case NEW: { + + Token next = accept(Token.TYPE.NEW); + + if (peek(1).type == Token.TYPE.INT) { + accept(Token.TYPE.INT); + accept(Token.TYPE.LSQUARE); + Expression expr = parseExpression(); + accept(Token.TYPE.RSQUARE); + + BaseType b = new BaseType(TypeKind.INT, next.posn); + return new NewArrayExpr(b, expr, next.posn); + } + + else { + Token id = accept(Token.TYPE.ID); + Identifier ident = new Identifier(id.spelling, id.posn); + ClassType ct = new ClassType(ident, id.posn); + + if (peek(1).type == Token.TYPE.LPAREN) { + accept(Token.TYPE.LPAREN); + accept(Token.TYPE.RPAREN); + return new NewObjectExpr(ct, next.posn); + } else { + accept(Token.TYPE.LSQUARE); + Expression expr = parseExpression(); + accept(Token.TYPE.RSQUARE); + return new NewArrayExpr(ct, expr, next.posn); + } + } + } + + // Reference ((ArgumentList?))? + case THIS: + case ID: { + + Reference ref = parseReference(); + + if (peek(1).type == Token.TYPE.LPAREN) { + accept(Token.TYPE.LPAREN); + ExprList el = new ExprList(); + if (peek(1).type != Token.TYPE.RPAREN) { + el = parseArgumentList(); + } + accept(Token.TYPE.RPAREN); + return new CallExpr(ref, el, ref.posn); + } else { + return new RefExpr(ref, ref.posn); + } + } + + default: + throw new ParsingException(peek(1).posn); + } + } + + /** + * Disjunctive + * + * @return + * @throws IOException + */ + private Expression parseExpression() throws IOException { + + Expression expr = parseCExpression(); + + while (peek(1).spelling.equals("||")) { + Token next = accept(Token.TYPE.BINOP); + Operator o = new Operator(next, next.posn); + expr = new BinaryExpr(o, expr, parseCExpression(), expr.posn); + } + + return expr; + } + + /** + * Conjunctive + * + * @return + * @throws IOException + */ + private Expression parseCExpression() throws IOException { + + Expression expr = parseEExpression(); + + while (peek(1).spelling.equals("&&")) { + Token next = accept(Token.TYPE.BINOP); + Operator o = new Operator(next, next.posn); + expr = new BinaryExpr(o, expr, parseEExpression(), expr.posn); + } + + return expr; + } + + /** + * Equality + * + * @return + * @throws IOException + */ + private Expression parseEExpression() throws IOException { + + Expression expr = parseRExpression(); + + while (peek(1).spelling.equals("==") || peek(1).spelling.equals("!=")) { + Token next = accept(Token.TYPE.BINOP); + Operator o = new Operator(next, next.posn); + expr = new BinaryExpr(o, expr, parseRExpression(), expr.posn); + } + + return expr; + } + + /** + * Relational + * + * @return + * @throws IOException + */ + private Expression parseRExpression() throws IOException { + + Expression expr = parseAExpression(); + + while (peek(1).spelling.equals("<") || peek(1).spelling.equals("<=") || peek(1).spelling.equals(">") + || peek(1).spelling.equals(">=")) { + Token next = accept(Token.TYPE.BINOP); + Operator o = new Operator(next, next.posn); + expr = new BinaryExpr(o, expr, parseAExpression(), expr.posn); + } + + return expr; + } + + /** + * Additive + * + * @return + * @throws IOException + */ + private Expression parseAExpression() throws IOException { + + Expression expr = parseMExpression(); + + while (peek(1).spelling.equals("+") || peek(1).spelling.equals("-")) { + Token next = accept(Token.TYPE.BINOP); + Operator o = new Operator(next, next.posn); + expr = new BinaryExpr(o, expr, parseMExpression(), expr.posn); + } + + return expr; + } + + /** + * Multiplicative + * + * @return + * @throws IOException + */ + private Expression parseMExpression() throws IOException { + + Expression expr = parseSingleExpression(); + + while (peek(1).spelling.equals("*") || peek(1).spelling.equals("/")) { + Token next = accept(Token.TYPE.BINOP); + Operator o = new Operator(next, next.posn); + expr = new BinaryExpr(o, expr, parseSingleExpression(), expr.posn); + } + + return expr; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // Convenience Methods + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * + * @param lookahead + * @return + * @throws IOException + */ + private Token peek(int lookahead) throws IOException { + + // Cache tokens + while (stream.size() < lookahead) { + Token next = scanner.scan(); + stream.addLast(next); + } + + return stream.get(lookahead - 1); + } + + /** + * + * @param type + * @return + * @throws IOException + */ + private Token accept(Token.TYPE type) throws IOException { + + Token next = peek(1); + if (next.type == type) + stream.poll(); + else + throw new ParsingException(next.posn); + + return next; + } } diff --git a/src/miniJava/SyntacticAnalyzer/ParsingException.java b/src/miniJava/SyntacticAnalyzer/ParsingException.java index 635e52d..a2655b2 100644 --- a/src/miniJava/SyntacticAnalyzer/ParsingException.java +++ b/src/miniJava/SyntacticAnalyzer/ParsingException.java @@ -6,11 +6,11 @@ import java.io.IOException; * */ public class ParsingException extends IOException { - - private static final long serialVersionUID = 1L; - public ParsingException(SourcePosition posn) { - super("Parsing error at " + posn); - } + private static final long serialVersionUID = 1L; + + public ParsingException(SourcePosition posn) { + super("Parsing error at " + posn); + } } \ No newline at end of file diff --git a/src/miniJava/SyntacticAnalyzer/Scanner.java b/src/miniJava/SyntacticAnalyzer/Scanner.java index e3ff840..1339011 100644 --- a/src/miniJava/SyntacticAnalyzer/Scanner.java +++ b/src/miniJava/SyntacticAnalyzer/Scanner.java @@ -4,303 +4,300 @@ import java.io.*; public class Scanner { - private int col = 1; - private int line = 1; - private boolean predefined; - private BufferedReader input; - - /** - * - * @param input - */ - public Scanner(BufferedReader input) { - this(input, false); - } - - /** - * - * @param input - * @param predefined - */ - public Scanner(String input, boolean predefined) { - this(new BufferedReader(new StringReader(input)), predefined); - } - - /** - * - * @param input - * @param predefined - */ - public Scanner(BufferedReader input, boolean predefined) { - this.input = input; - this.predefined = predefined; - } - + private int col = 1; + private int line = 1; + private boolean predefined; + private BufferedReader input; - // ///////////////////////////////////////////////////////////////////////////// - // - // Scanning - // - // ///////////////////////////////////////////////////////////////////////////// - - /** - * - * @return - * @throws IOException - */ - public Token scan() throws IOException { - Token token = null; - String spelling = ""; - - while (token == null) { - - int c = read(); - SourcePosition posn = new SourcePosition(col, line); - - if(c == -1) { - token = new Token("", Token.TYPE.EOT, posn); - } else { - spelling += (char) c; - - switch(c) { + /** + * + * @param input + */ + public Scanner(BufferedReader input) { + this(input, false); + } - // Operators - case '*': - case '+': - case '-': { - if(peek(c)) throw new ScanningException(posn); - token = new Token(spelling, Token.TYPE.BINOP, posn); - break; - } - - // Comment - case '/': { - if(peek('*')) { - read(); - readMultiLineComment(); - spelling = ""; - } else if(peek('/')) { - readSingleLineComment(); - spelling = ""; - } else { - token = new Token(spelling, Token.TYPE.BINOP, posn); - } - - break; - } - - // Relational - case '>': - case '<': { - if (peek('=')) spelling += (char) read(); - token = new Token(spelling, Token.TYPE.BINOP, posn); - break; - } - - // Negation - case '!': { - if(peek('=')) { - spelling += (char) read(); - token = new Token(spelling, Token.TYPE.BINOP, posn); - } else { - token = new Token(spelling, Token.TYPE.UNOP, posn); - } - - break; - } - - // Logical - case '&': - case '|': { - if(!peek(c)) { - throw new ScanningException(posn); - } else { - spelling += (char) read(); - token = new Token(spelling, Token.TYPE.BINOP, posn); - } - - break; - } - - // Other Operators - case '=': { - if(peek('=')) { - spelling += (char) read(); - token = new Token(spelling, Token.TYPE.BINOP, posn); - } else { - token = new Token(spelling, Token.TYPE.EQUALS, posn); - } - - break; - } - - // Miscellaneous - case '.': - case ',': - case '[': - case ']': - case '{': - case '}': - case '(': - case ')': - case ';': { - token = new Token(spelling, Token.symbols.get(c), posn); - break; - } - - default: { - - // Identifier or keyword - if(isAlpha(c)) { - int next = peek(); - while(isAlpha(next) || isDigit(next) || next == '_') { - spelling += (char) read(); - next = peek(); - } - - if(Token.keywords.containsKey(spelling)) { - token = new Token(spelling, Token.keywords.get(spelling), posn); - } else { - token = new Token(spelling, Token.TYPE.ID, posn); - } - } - - // Number - else if(isDigit(c)) { - int next = peek(); - while(isDigit(next)) { - spelling += (char) read(); - next = peek(); - } + /** + * + * @param input + * @param predefined + */ + public Scanner(String input, boolean predefined) { + this(new BufferedReader(new StringReader(input)), predefined); + } - token = new Token(spelling, Token.TYPE.NUM, posn); - } - - // Whitespace - else if(isWhitespace(c)) { - spelling = ""; - } - - // Unrecognized Character - else { - throw new ScanningException(posn); - } - } - } - } - } + /** + * + * @param input + * @param predefined + */ + public Scanner(BufferedReader input, boolean predefined) { + this.input = input; + this.predefined = predefined; + } - return token; - } + // ///////////////////////////////////////////////////////////////////////////// + // + // Scanning + // + // ///////////////////////////////////////////////////////////////////////////// + /** + * + * @return + * @throws IOException + */ + public Token scan() throws IOException { + Token token = null; + String spelling = ""; - - // ///////////////////////////////////////////////////////////////////////////// - // - // Convenience Methods - // - // ///////////////////////////////////////////////////////////////////////////// - - /** - * - * @param c - * @return - */ - private boolean isAlpha(int c) { - return (c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (predefined && c == '_'); - } - - /** - * - * @param c - * @return - */ - private boolean isDigit(int c) { - return c >= '0' && c <= '9'; - } - - /** - * - * @param c - * @return - */ - private boolean isWhitespace(int c) { - return c == ' ' || c == '\n' || c == '\r' || c == '\t'; - } - - /** - * - * @return - * @throws IOException - */ - private int peek() throws IOException { - input.mark(1); - int next = input.read(); - input.reset(); + while (token == null) { - return next; - } - - /** - * - * @param c - * @return - * @throws IOException - */ - private boolean peek(int c) throws IOException { - input.mark(1); - int next = input.read(); - input.reset(); + int c = read(); + SourcePosition posn = new SourcePosition(col, line); - return c == next; - } - - /** - * - * @return - * @throws IOException - */ - private int read() throws IOException { - int next = input.read(); - if(next == '\n' || next == '\r') { - col = 1; - line += 1; - } else { - col += 1; - } - - return next; - } - - /** - * - * @throws IOException - */ - private void readSingleLineComment() throws IOException { - col = 1; - line += 1; - input.readLine(); - } + if (c == -1) { + token = new Token("", Token.TYPE.EOT, posn); + } else { + spelling += (char) c; - /** - * - * @throws IOException - */ - private void readMultiLineComment() throws IOException { - int prev = '\0'; - int current = '\0'; - - while(prev != '*' || current != '/') { - prev = current; - current = read(); - - // Unterminated - if(current == -1) { - SourcePosition posn = new SourcePosition(line, col); - throw new ScanningException(posn); - } - } - } + switch (c) { + + // Operators + case '*': + case '+': + case '-': { + if (peek(c)) + throw new ScanningException(posn); + token = new Token(spelling, Token.TYPE.BINOP, posn); + break; + } + + // Comment + case '/': { + if (peek('*')) { + read(); + readMultiLineComment(); + spelling = ""; + } else if (peek('/')) { + readSingleLineComment(); + spelling = ""; + } else { + token = new Token(spelling, Token.TYPE.BINOP, posn); + } + + break; + } + + // Relational + case '>': + case '<': { + if (peek('=')) + spelling += (char) read(); + token = new Token(spelling, Token.TYPE.BINOP, posn); + break; + } + + // Negation + case '!': { + if (peek('=')) { + spelling += (char) read(); + token = new Token(spelling, Token.TYPE.BINOP, posn); + } else { + token = new Token(spelling, Token.TYPE.UNOP, posn); + } + + break; + } + + // Logical + case '&': + case '|': { + if (!peek(c)) { + throw new ScanningException(posn); + } else { + spelling += (char) read(); + token = new Token(spelling, Token.TYPE.BINOP, posn); + } + + break; + } + + // Other Operators + case '=': { + if (peek('=')) { + spelling += (char) read(); + token = new Token(spelling, Token.TYPE.BINOP, posn); + } else { + token = new Token(spelling, Token.TYPE.EQUALS, posn); + } + + break; + } + + // Miscellaneous + case '.': + case ',': + case '[': + case ']': + case '{': + case '}': + case '(': + case ')': + case ';': { + token = new Token(spelling, Token.symbols.get(c), posn); + break; + } + + default: { + + // Identifier or keyword + if (isAlpha(c)) { + int next = peek(); + while (isAlpha(next) || isDigit(next) || next == '_') { + spelling += (char) read(); + next = peek(); + } + + if (Token.keywords.containsKey(spelling)) { + token = new Token(spelling, Token.keywords.get(spelling), posn); + } else { + token = new Token(spelling, Token.TYPE.ID, posn); + } + } + + // Number + else if (isDigit(c)) { + int next = peek(); + while (isDigit(next)) { + spelling += (char) read(); + next = peek(); + } + + token = new Token(spelling, Token.TYPE.NUM, posn); + } + + // Whitespace + else if (isWhitespace(c)) { + spelling = ""; + } + + // Unrecognized Character + else { + throw new ScanningException(posn); + } + } + } + } + } + + return token; + } + + // ///////////////////////////////////////////////////////////////////////////// + // + // Convenience Methods + // + // ///////////////////////////////////////////////////////////////////////////// + + /** + * + * @param c + * @return + */ + private boolean isAlpha(int c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (predefined && c == '_'); + } + + /** + * + * @param c + * @return + */ + private boolean isDigit(int c) { + return c >= '0' && c <= '9'; + } + + /** + * + * @param c + * @return + */ + private boolean isWhitespace(int c) { + return c == ' ' || c == '\n' || c == '\r' || c == '\t'; + } + + /** + * + * @return + * @throws IOException + */ + private int peek() throws IOException { + input.mark(1); + int next = input.read(); + input.reset(); + + return next; + } + + /** + * + * @param c + * @return + * @throws IOException + */ + private boolean peek(int c) throws IOException { + input.mark(1); + int next = input.read(); + input.reset(); + + return c == next; + } + + /** + * + * @return + * @throws IOException + */ + private int read() throws IOException { + int next = input.read(); + if (next == '\n' || next == '\r') { + col = 1; + line += 1; + } else { + col += 1; + } + + return next; + } + + /** + * + * @throws IOException + */ + private void readSingleLineComment() throws IOException { + col = 1; + line += 1; + input.readLine(); + } + + /** + * + * @throws IOException + */ + private void readMultiLineComment() throws IOException { + int prev = '\0'; + int current = '\0'; + + while (prev != '*' || current != '/') { + prev = current; + current = read(); + + // Unterminated + if (current == -1) { + SourcePosition posn = new SourcePosition(line, col); + throw new ScanningException(posn); + } + } + } } diff --git a/src/miniJava/SyntacticAnalyzer/ScanningException.java b/src/miniJava/SyntacticAnalyzer/ScanningException.java index 6f29677..335672c 100644 --- a/src/miniJava/SyntacticAnalyzer/ScanningException.java +++ b/src/miniJava/SyntacticAnalyzer/ScanningException.java @@ -6,11 +6,11 @@ import java.io.IOException; * */ public class ScanningException extends IOException { - - private static final long serialVersionUID = 1L; - public ScanningException(SourcePosition posn) { - super("Scanning error at " + posn); - } + private static final long serialVersionUID = 1L; + + public ScanningException(SourcePosition posn) { + super("Scanning error at " + posn); + } } diff --git a/src/miniJava/SyntacticAnalyzer/SourcePosition.java b/src/miniJava/SyntacticAnalyzer/SourcePosition.java index 072d8fe..e287f4d 100644 --- a/src/miniJava/SyntacticAnalyzer/SourcePosition.java +++ b/src/miniJava/SyntacticAnalyzer/SourcePosition.java @@ -5,16 +5,16 @@ package miniJava.SyntacticAnalyzer; */ public class SourcePosition { - public final int col; - public final int line; + public final int col; + public final int line; - public SourcePosition(int col, int line) { - this.col = col; - this.line = line; - } + public SourcePosition(int col, int line) { + this.col = col; + this.line = line; + } - @Override - public String toString() { - return "(Line: " + line + ", Column: " + col + ")"; - } + @Override + public String toString() { + return "(Line: " + line + ", Column: " + col + ")"; + } } diff --git a/src/miniJava/SyntacticAnalyzer/Token.java b/src/miniJava/SyntacticAnalyzer/Token.java index ddd35f1..a3c5705 100644 --- a/src/miniJava/SyntacticAnalyzer/Token.java +++ b/src/miniJava/SyntacticAnalyzer/Token.java @@ -7,88 +7,63 @@ import java.util.HashMap; */ public class Token { - public enum TYPE { - - // Terminals - ID, - NUM, - UNOP, - BINOP, - EQUALS, - PERIOD, - COMMA, - LPAREN, - RPAREN, - LSQUARE, - RSQUARE, - LBRACKET, - RBRACKET, - SEMICOLON, + public enum TYPE { - // Keywords - IF, - ELSE, - NEW, - INT, - VOID, - THIS, - TRUE, - FALSE, - CLASS, - WHILE, - RETURN, - BOOLEAN, - STATIC, - PUBLIC, - PRIVATE, + // Terminals + ID, NUM, UNOP, BINOP, EQUALS, PERIOD, COMMA, LPAREN, RPAREN, LSQUARE, RSQUARE, LBRACKET, RBRACKET, SEMICOLON, - // End of Token Stream - EOT - }; + // Keywords + IF, ELSE, NEW, INT, VOID, THIS, TRUE, FALSE, CLASS, WHILE, RETURN, BOOLEAN, STATIC, PUBLIC, PRIVATE, - // Pair words with enumeration - public final static HashMap keywords; - static { - keywords = new HashMap(); - keywords.put("class", TYPE.CLASS); - keywords.put("return", TYPE.RETURN); - keywords.put("public", TYPE.PUBLIC); - keywords.put("private", TYPE.PRIVATE); - keywords.put("static", TYPE.STATIC); - keywords.put("int", TYPE.INT); - keywords.put("boolean", TYPE.BOOLEAN); - keywords.put("void", TYPE.VOID); - keywords.put("this", TYPE.THIS); - keywords.put("if", TYPE.IF); - keywords.put("else", TYPE.ELSE); - keywords.put("while", TYPE.WHILE); - keywords.put("true", TYPE.TRUE); - keywords.put("false", TYPE.FALSE); - keywords.put("new", TYPE.NEW); - } - - // Pair symbols with enumeration - public final static HashMap symbols; - static { - symbols = new HashMap(); - symbols.put((int) '.', TYPE.PERIOD); - symbols.put((int) ',', TYPE.COMMA); - symbols.put((int) '[', TYPE.LSQUARE); - symbols.put((int) ']', TYPE.RSQUARE); - symbols.put((int) '{', TYPE.LBRACKET); - symbols.put((int) '}', TYPE.RBRACKET); - symbols.put((int) '(', TYPE.LPAREN); - symbols.put((int) ')', TYPE.RPAREN); - symbols.put((int) ';', TYPE.SEMICOLON); - } + // End of Token Stream + EOT + }; - public final TYPE type; - public final String spelling; - public final SourcePosition posn; + // Pair words with enumeration + public final static HashMap keywords; - public Token(String spelling, TYPE type, SourcePosition posn) { - this.type = type; - this.posn = posn; - this.spelling = spelling; - } + static { + keywords = new HashMap(); + keywords.put("class", TYPE.CLASS); + keywords.put("return", TYPE.RETURN); + keywords.put("public", TYPE.PUBLIC); + keywords.put("private", TYPE.PRIVATE); + keywords.put("static", TYPE.STATIC); + keywords.put("int", TYPE.INT); + keywords.put("boolean", TYPE.BOOLEAN); + keywords.put("void", TYPE.VOID); + keywords.put("this", TYPE.THIS); + keywords.put("if", TYPE.IF); + keywords.put("else", TYPE.ELSE); + keywords.put("while", TYPE.WHILE); + keywords.put("true", TYPE.TRUE); + keywords.put("false", TYPE.FALSE); + keywords.put("new", TYPE.NEW); + } + + // Pair symbols with enumeration + public final static HashMap symbols; + + static { + symbols = new HashMap(); + symbols.put((int) '.', TYPE.PERIOD); + symbols.put((int) ',', TYPE.COMMA); + symbols.put((int) '[', TYPE.LSQUARE); + symbols.put((int) ']', TYPE.RSQUARE); + symbols.put((int) '{', TYPE.LBRACKET); + symbols.put((int) '}', TYPE.RBRACKET); + symbols.put((int) '(', TYPE.LPAREN); + symbols.put((int) ')', TYPE.RPAREN); + symbols.put((int) ';', TYPE.SEMICOLON); + } + + public final TYPE type; + public final String spelling; + public final SourcePosition posn; + + public Token(String spelling, TYPE type, SourcePosition posn) { + this.type = type; + this.posn = posn; + this.spelling = spelling; + } } diff --git a/src/tester/Checkpoint1.java b/src/tester/Checkpoint1.java index 64410e8..df6730a 100644 --- a/src/tester/Checkpoint1.java +++ b/src/tester/Checkpoint1.java @@ -12,60 +12,59 @@ import java.util.concurrent.Executors; * Put your tests in "tests/pa1_tests" folder in your Eclipse workspace directory */ public class Checkpoint1 { - - static ExecutorService threadPool = Executors.newCachedThreadPool(); - public static void main(String[] args) throws IOException, InterruptedException { - File testDir = new File(System.getProperty("java.class.path") - + "/../tests/pa1_tests"); - int failures = 0; - for (File x : testDir.listFiles()) { - int returnCode = runTest(x); - if (x.getName().indexOf("pass") != -1) { - if (returnCode == 0) - System.out.println(x.getName() + " passed successfully!"); - else { - failures++; - System.err.println(x.getName() - + " failed but should have passed!"); - } - } else { - if (returnCode == 4) - System.out.println(x.getName() + " failed successfully!"); - else { - System.err.println(x.getName() + " did not fail properly!"); - failures++; - } - } - } - System.out.println(failures + " failures in all."); - } - - private static int runTest(File x) throws IOException, InterruptedException { - ProcessBuilder pb = new ProcessBuilder("java", "miniJava.Compiler", x.getPath()).directory(new File(System.getProperty("java.class.path"))); - Process p = pb.start(); - threadPool.execute(new ProcessOutputter(p.getInputStream(), false)); - p.waitFor(); - return p.exitValue(); - } - - static class ProcessOutputter implements Runnable { - private Scanner processOutput; - private boolean output; - - public ProcessOutputter(InputStream _processStream, boolean _output) { - processOutput = new Scanner(_processStream); - output = _output; - } - @Override - public void run() { - while(processOutput.hasNextLine()) { - String line = processOutput.nextLine(); - if (output) - System.out.println(line); - } - } - - - } + static ExecutorService threadPool = Executors.newCachedThreadPool(); + + public static void main(String[] args) throws IOException, InterruptedException { + File testDir = new File(System.getProperty("java.class.path") + "/../tests/pa1_tests"); + int failures = 0; + for (File x : testDir.listFiles()) { + int returnCode = runTest(x); + if (x.getName().indexOf("pass") != -1) { + if (returnCode == 0) + System.out.println(x.getName() + " passed successfully!"); + else { + failures++; + System.err.println(x.getName() + " failed but should have passed!"); + } + } else { + if (returnCode == 4) + System.out.println(x.getName() + " failed successfully!"); + else { + System.err.println(x.getName() + " did not fail properly!"); + failures++; + } + } + } + System.out.println(failures + " failures in all."); + } + + private static int runTest(File x) throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("java", "miniJava.Compiler", x.getPath()) + .directory(new File(System.getProperty("java.class.path"))); + Process p = pb.start(); + threadPool.execute(new ProcessOutputter(p.getInputStream(), false)); + p.waitFor(); + return p.exitValue(); + } + + static class ProcessOutputter implements Runnable { + private Scanner processOutput; + private boolean output; + + public ProcessOutputter(InputStream _processStream, boolean _output) { + processOutput = new Scanner(_processStream); + output = _output; + } + + @Override + public void run() { + while (processOutput.hasNextLine()) { + String line = processOutput.nextLine(); + if (output) + System.out.println(line); + } + } + + } } diff --git a/src/tester/Checkpoint2.java b/src/tester/Checkpoint2.java index d9d7711..daf996e 100644 --- a/src/tester/Checkpoint2.java +++ b/src/tester/Checkpoint2.java @@ -13,86 +13,84 @@ import java.util.Scanner; */ public class Checkpoint2 { - - private static class ReturnInfo { - int returnCode; - String ast; - public ReturnInfo(int _returnCode, String _ast) { - returnCode = _returnCode; - ast = _ast; - } - } - - public static void main(String[] args) throws IOException, InterruptedException { - File testDir = new File(System.getProperty("java.class.path") - + "/../tests/pa2_tests"); - int failures = 0; - for (File x : testDir.listFiles()) { - if (x.getName().endsWith("out") || x.getName().startsWith(".")) - continue; - ReturnInfo info = runTest(x); - int returnCode = info.returnCode; - String ast = info.ast; - if (x.getName().indexOf("pass") != -1) { - if (returnCode == 0) { - String actualAST = getAST(new FileInputStream(x.getPath() + ".out")); - if (actualAST.equals(ast)) - System.out.println(x.getName() + " parsed successfully and has a correct AST!"); - else { - System.err.println(x.getName() + " parsed successfully but has an incorrect AST!"); - failures++; - } - } - else { - failures++; - System.err.println(x.getName() - + " failed to be parsed!"); - } - } else { - if (returnCode == 4) - System.out.println(x.getName() + " failed successfully!"); - else { - System.err.println(x.getName() + " did not fail properly!"); - failures++; - } - } - } - System.out.println(failures + " failures in all."); - } - - private static ReturnInfo runTest(File x) throws IOException, InterruptedException { - ProcessBuilder pb = new ProcessBuilder("java", "miniJava.Compiler", x.getPath()).directory(new File(System.getProperty("java.class.path"))); - pb.redirectErrorStream(true); - Process p = pb.start(); - String ast = getAST(p.getInputStream()); - p.waitFor(); - int exitValue = p.exitValue(); - return new ReturnInfo(exitValue, ast); - } - - - public static String getAST(InputStream stream) { - Scanner scan = new Scanner(stream); - String ast = null; - while (scan.hasNextLine()) { - String line = scan.nextLine(); - if (line.equals("======= AST Display =========================")) { - line = scan.nextLine(); - while(scan.hasNext() && !line.equals("=============================================")) { - ast += line + "\n"; - line = scan.nextLine(); - } - } - if (line.startsWith("*** ")) - System.out.println(line); - if (line.startsWith("ERROR")) { - System.out.println(line); - while(scan.hasNext()) - System.out.println(scan.next()); - } - } - scan.close(); - return ast; - } + private static class ReturnInfo { + int returnCode; + String ast; + + public ReturnInfo(int _returnCode, String _ast) { + returnCode = _returnCode; + ast = _ast; + } + } + + public static void main(String[] args) throws IOException, InterruptedException { + File testDir = new File(System.getProperty("java.class.path") + "/../tests/pa2_tests"); + int failures = 0; + for (File x : testDir.listFiles()) { + if (x.getName().endsWith("out") || x.getName().startsWith(".")) + continue; + ReturnInfo info = runTest(x); + int returnCode = info.returnCode; + String ast = info.ast; + if (x.getName().indexOf("pass") != -1) { + if (returnCode == 0) { + String actualAST = getAST(new FileInputStream(x.getPath() + ".out")); + if (actualAST.equals(ast)) + System.out.println(x.getName() + " parsed successfully and has a correct AST!"); + else { + System.err.println(x.getName() + " parsed successfully but has an incorrect AST!"); + failures++; + } + } else { + failures++; + System.err.println(x.getName() + " failed to be parsed!"); + } + } else { + if (returnCode == 4) + System.out.println(x.getName() + " failed successfully!"); + else { + System.err.println(x.getName() + " did not fail properly!"); + failures++; + } + } + } + System.out.println(failures + " failures in all."); + } + + private static ReturnInfo runTest(File x) throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("java", "miniJava.Compiler", x.getPath()) + .directory(new File(System.getProperty("java.class.path"))); + pb.redirectErrorStream(true); + Process p = pb.start(); + + String ast = getAST(p.getInputStream()); + p.waitFor(); + int exitValue = p.exitValue(); + return new ReturnInfo(exitValue, ast); + } + + public static String getAST(InputStream stream) { + Scanner scan = new Scanner(stream); + String ast = null; + while (scan.hasNextLine()) { + String line = scan.nextLine(); + if (line.equals("======= AST Display =========================")) { + line = scan.nextLine(); + while (scan.hasNext() && !line.equals("=============================================")) { + ast += line + "\n"; + line = scan.nextLine(); + } + } + if (line.startsWith("*** ")) + System.out.println(line); + if (line.startsWith("ERROR")) { + System.out.println(line); + while (scan.hasNext()) + System.out.println(scan.next()); + } + } + scan.close(); + return ast; + } } diff --git a/src/tester/Checkpoint3.java b/src/tester/Checkpoint3.java index 760e1f1..dd9c65f 100644 --- a/src/tester/Checkpoint3.java +++ b/src/tester/Checkpoint3.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.io.InputStream; import java.util.Scanner; - /* Automated regression tester for Checkpoint 3 tests * Created by Max Beckman-Harned * Put your tests in "tests/pa3_tests" folder in your Eclipse workspace directory @@ -13,61 +12,58 @@ import java.util.Scanner; */ public class Checkpoint3 { - - - public static void main(String[] args) throws IOException, InterruptedException { - File testDir = new File(System.getProperty("java.class.path") - + "/../tests/pa3_tests"); - int failures = 0; - for (File x : testDir.listFiles()) { - if (x.getName().endsWith("out") || x.getName().startsWith(".") || x.getName().endsWith("mJAM") || x.getName().endsWith("asm")) - continue; - int returnCode = runTest(x); - if (x.getName().indexOf("pass") != -1) { - if (returnCode == 0) { - System.out.println(x.getName() + " processed successfully!"); - } - else { - failures++; - System.err.println(x.getName() - + " failed to be processed!"); - } - } else { - if (returnCode == 4) - System.out.println(x.getName() + " failed successfully!"); - else { - System.err.println(x.getName() + " did not fail properly!"); - failures++; - } - } - } - System.out.println(failures + " failures in all."); - } - - private static int runTest(File x) throws IOException, InterruptedException { - ProcessBuilder pb = new ProcessBuilder("java", "miniJava.Compiler", x.getPath()).directory(new File(System.getProperty("java.class.path"))); - pb.redirectErrorStream(true); - Process p = pb.start(); - processStream(p.getInputStream()); - p.waitFor(); - int exitValue = p.exitValue(); - return exitValue; - } - - - public static void processStream(InputStream stream) { - Scanner scan = new Scanner(stream); - while (scan.hasNextLine()) { - String line = scan.nextLine(); - if (line.startsWith("*** ")) - System.out.println(line); - if (line.startsWith("ERROR")) { - System.out.println(line); - //while(scan.hasNext()) - //System.out.println(scan.next()); - } - } - scan.close(); - } + public static void main(String[] args) throws IOException, InterruptedException { + File testDir = new File(System.getProperty("java.class.path") + "/../tests/pa3_tests"); + int failures = 0; + for (File x : testDir.listFiles()) { + if (x.getName().endsWith("out") || x.getName().startsWith(".") || x.getName().endsWith("mJAM") + || x.getName().endsWith("asm")) + continue; + int returnCode = runTest(x); + if (x.getName().indexOf("pass") != -1) { + if (returnCode == 0) { + System.out.println(x.getName() + " processed successfully!"); + } else { + failures++; + System.err.println(x.getName() + " failed to be processed!"); + } + } else { + if (returnCode == 4) + System.out.println(x.getName() + " failed successfully!"); + else { + System.err.println(x.getName() + " did not fail properly!"); + failures++; + } + } + } + System.out.println(failures + " failures in all."); + } + + private static int runTest(File x) throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("java", "miniJava.Compiler", x.getPath()) + .directory(new File(System.getProperty("java.class.path"))); + pb.redirectErrorStream(true); + Process p = pb.start(); + + processStream(p.getInputStream()); + p.waitFor(); + int exitValue = p.exitValue(); + return exitValue; + } + + public static void processStream(InputStream stream) { + Scanner scan = new Scanner(stream); + while (scan.hasNextLine()) { + String line = scan.nextLine(); + if (line.startsWith("*** ")) + System.out.println(line); + if (line.startsWith("ERROR")) { + System.out.println(line); + // while(scan.hasNext()) + // System.out.println(scan.next()); + } + } + scan.close(); + } } diff --git a/src/tester/Checkpoint4.java b/src/tester/Checkpoint4.java index 9ff8089..aa9604e 100644 --- a/src/tester/Checkpoint4.java +++ b/src/tester/Checkpoint4.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.io.InputStream; import java.util.Scanner; - /* Automated regression tester for Checkpoint 4 tests * Created by Max Beckman-Harned * Put your tests in "tests/pa4_tests" folder in your Eclipse workspace directory @@ -13,100 +12,97 @@ import java.util.Scanner; */ public class Checkpoint4 { - - - public static void main(String[] args) throws IOException, InterruptedException { - File testDir = new File(System.getProperty("java.class.path") - + "/../tests/pa4_tests"); - int failures = 0; - for (File x : testDir.listFiles()) { - if (x.getName().startsWith(".") || x.getName().endsWith("mJAM") || x.getName().endsWith("asm")) - continue; - int returnCode = runTest(x); - if (x.getName().indexOf("pass") != -1) { - if (returnCode == 0) { - try { - int val = executeTest(x); - int expected = Integer.parseInt(x.getName().substring(5,7)); - if (val == expected) - System.out.println(x.getName() + " ran successfully!"); - else { - failures++; - System.err.println(x.getName() + " compiled but did not run successfully--got output " + val); - } - } - catch(Exception ex) { - failures++; - System.err.println(x.getName() + " did not output correctly."); - } - } - else { - failures++; - System.err.println(x.getName() - + " failed to be processed!"); - } - } else { - if (returnCode == 4) - System.out.println(x.getName() + " failed successfully!"); - else { - System.err.println(x.getName() + " did not fail properly!"); - failures++; - } - } - } - System.out.println(failures + " failures in all."); - } - - private static int runTest(File x) throws IOException, InterruptedException { - ProcessBuilder pb = new ProcessBuilder("java", "miniJava.Compiler", x.getPath()).directory(new File(System.getProperty("java.class.path"))); - pb.redirectErrorStream(true); - Process p = pb.start(); - processStream(p.getInputStream()); - p.waitFor(); - int exitValue = p.exitValue(); - return exitValue; - } - - private static int executeTest(File x) throws IOException, InterruptedException { - ProcessBuilder pb = new ProcessBuilder("java", "mJAM.Interpreter", x.getPath().replace(".java", ".mJAM")).directory(new File(System.getProperty("java.class.path"))); - Process process = pb.start(); - - Scanner scan = new Scanner(process.getInputStream()); - int num = -1; - while (scan.hasNextLine()) { - String line = scan.nextLine(); - if (line.startsWith(">>> ")) { - num = Integer.parseInt(line.substring(4)); - System.out.println("Result = " + num); - break; - } - } - while (scan.hasNextLine()) { - String line = scan.nextLine(); - if (line.startsWith("*** ")) { - System.out.println(line); - break; - } - } - scan.close(); - - return num; - } - - - public static void processStream(InputStream stream) { - Scanner scan = new Scanner(stream); - while (scan.hasNextLine()) { - String line = scan.nextLine(); - if (line.startsWith("*** ")) - System.out.println(line); - if (line.startsWith("ERROR")) { - System.out.println(line); - //while(scan.hasNext()) - //System.out.println(scan.next()); - } - } - scan.close(); - } + public static void main(String[] args) throws IOException, InterruptedException { + File testDir = new File(System.getProperty("java.class.path") + "/../tests/pa4_tests"); + int failures = 0; + for (File x : testDir.listFiles()) { + if (x.getName().startsWith(".") || x.getName().endsWith("mJAM") || x.getName().endsWith("asm")) + continue; + int returnCode = runTest(x); + if (x.getName().indexOf("pass") != -1) { + if (returnCode == 0) { + try { + int val = executeTest(x); + int expected = Integer.parseInt(x.getName().substring(5, 7)); + if (val == expected) + System.out.println(x.getName() + " ran successfully!"); + else { + failures++; + System.err + .println(x.getName() + " compiled but did not run successfully--got output " + val); + } + } catch (Exception ex) { + failures++; + System.err.println(x.getName() + " did not output correctly."); + } + } else { + failures++; + System.err.println(x.getName() + " failed to be processed!"); + } + } else { + if (returnCode == 4) + System.out.println(x.getName() + " failed successfully!"); + else { + System.err.println(x.getName() + " did not fail properly!"); + failures++; + } + } + } + System.out.println(failures + " failures in all."); + } + + private static int runTest(File x) throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("java", "miniJava.Compiler", x.getPath()) + .directory(new File(System.getProperty("java.class.path"))); + pb.redirectErrorStream(true); + Process p = pb.start(); + + processStream(p.getInputStream()); + p.waitFor(); + int exitValue = p.exitValue(); + return exitValue; + } + + private static int executeTest(File x) throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("java", "mJAM.Interpreter", x.getPath().replace(".java", ".mJAM")) + .directory(new File(System.getProperty("java.class.path"))); + Process process = pb.start(); + + Scanner scan = new Scanner(process.getInputStream()); + int num = -1; + while (scan.hasNextLine()) { + String line = scan.nextLine(); + if (line.startsWith(">>> ")) { + num = Integer.parseInt(line.substring(4)); + System.out.println("Result = " + num); + break; + } + } + while (scan.hasNextLine()) { + String line = scan.nextLine(); + if (line.startsWith("*** ")) { + System.out.println(line); + break; + } + } + scan.close(); + + return num; + } + + public static void processStream(InputStream stream) { + Scanner scan = new Scanner(stream); + while (scan.hasNextLine()) { + String line = scan.nextLine(); + if (line.startsWith("*** ")) + System.out.println(line); + if (line.startsWith("ERROR")) { + System.out.println(line); + // while(scan.hasNext()) + // System.out.println(scan.next()); + } + } + scan.close(); + } } \ No newline at end of file