📄 encoder.java
字号:
// Value-or-variable names public Object visitDotVname(DotVname ast, Object o) { Frame frame = (Frame) o; RuntimeEntity baseObject = (RuntimeEntity) ast.V.visit(this, frame); ast.offset = ast.V.offset + ((Field) ast.I.decl.entity).fieldOffset; // I.decl points to the appropriate record field ast.indexed = ast.V.indexed; return baseObject; } public Object visitSimpleVname(SimpleVname ast, Object o) { ast.offset = 0; ast.indexed = false; return ast.I.decl.entity; } public Object visitSubscriptVname(SubscriptVname ast, Object o) { Frame frame = (Frame) o; RuntimeEntity baseObject; int elemSize, indexSize; baseObject = (RuntimeEntity) ast.V.visit(this, frame); ast.offset = ast.V.offset; ast.indexed = ast.V.indexed; elemSize = ((Integer) ast.type.visit(this, null)).intValue(); if (ast.E instanceof IntegerExpression) { IntegerLiteral IL = ((IntegerExpression) ast.E).IL; ast.offset = ast.offset + Integer.parseInt(IL.spelling) * elemSize; } else { // v-name is indexed by a proper expression, not a literal if (ast.indexed) frame.size = frame.size + Machine.integerSize; indexSize = ((Integer) ast.E.visit(this, frame)).intValue(); if (elemSize != 1) { emit(Machine.LOADLop, 0, 0, elemSize); emit(Machine.CALLop, Machine.SBr, Machine.PBr, Machine.multDisplacement); } if (ast.indexed) emit(Machine.CALLop, Machine.SBr, Machine.PBr, Machine.addDisplacement); else ast.indexed = true; } return baseObject; } // Programs public Object visitProgram(Program ast, Object o) { return ast.C.visit(this, o); } public Encoder (ErrorReporter reporter) { this.reporter = reporter; nextInstrAddr = Machine.CB; elaborateStdEnvironment(); } private ErrorReporter reporter; // Generates code to run a program. // showingTable is true iff entity description details // are to be displayed. public final void encodeRun (Program theAST, boolean showingTable) { tableDetailsReqd = showingTable; //startCodeGeneration(); theAST.visit(this, new Frame (0, 0)); emit(Machine.HALTop, 0, 0, 0); } // Decides run-time representation of a standard constant. private final void elaborateStdConst (Declaration constDeclaration, int value) { if (constDeclaration instanceof ConstDeclaration) { ConstDeclaration decl = (ConstDeclaration) constDeclaration; int typeSize = ((Integer) decl.E.type.visit(this, null)).intValue(); decl.entity = new KnownValue(typeSize, value); writeTableDetails(constDeclaration); } } // Decides run-time representation of a standard routine. private final void elaborateStdPrimRoutine (Declaration routineDeclaration, int routineOffset) { routineDeclaration.entity = new PrimitiveRoutine (Machine.closureSize, routineOffset); writeTableDetails(routineDeclaration); } private final void elaborateStdEqRoutine (Declaration routineDeclaration, int routineOffset) { routineDeclaration.entity = new EqualityRoutine (Machine.closureSize, routineOffset); writeTableDetails(routineDeclaration); } private final void elaborateStdRoutine (Declaration routineDeclaration, int routineOffset) { routineDeclaration.entity = new KnownRoutine (Machine.closureSize, 0, routineOffset); writeTableDetails(routineDeclaration); } private final void elaborateStdEnvironment() { tableDetailsReqd = false; elaborateStdConst(StdEnvironment.falseDecl, Machine.falseRep); elaborateStdConst(StdEnvironment.trueDecl, Machine.trueRep); elaborateStdPrimRoutine(StdEnvironment.notDecl, Machine.notDisplacement); elaborateStdPrimRoutine(StdEnvironment.andDecl, Machine.andDisplacement); elaborateStdPrimRoutine(StdEnvironment.orDecl, Machine.orDisplacement); elaborateStdConst(StdEnvironment.maxintDecl, Machine.maxintRep); elaborateStdPrimRoutine(StdEnvironment.addDecl, Machine.addDisplacement); elaborateStdPrimRoutine(StdEnvironment.subtractDecl, Machine.subDisplacement); elaborateStdPrimRoutine(StdEnvironment.multiplyDecl, Machine.multDisplacement); elaborateStdPrimRoutine(StdEnvironment.divideDecl, Machine.divDisplacement); elaborateStdPrimRoutine(StdEnvironment.moduloDecl, Machine.modDisplacement); elaborateStdPrimRoutine(StdEnvironment.lessDecl, Machine.ltDisplacement); elaborateStdPrimRoutine(StdEnvironment.notgreaterDecl, Machine.leDisplacement); elaborateStdPrimRoutine(StdEnvironment.greaterDecl, Machine.gtDisplacement); elaborateStdPrimRoutine(StdEnvironment.notlessDecl, Machine.geDisplacement); elaborateStdPrimRoutine(StdEnvironment.chrDecl, Machine.idDisplacement); elaborateStdPrimRoutine(StdEnvironment.ordDecl, Machine.idDisplacement); elaborateStdPrimRoutine(StdEnvironment.eolDecl, Machine.eolDisplacement); elaborateStdPrimRoutine(StdEnvironment.eofDecl, Machine.eofDisplacement); elaborateStdPrimRoutine(StdEnvironment.getDecl, Machine.getDisplacement); elaborateStdPrimRoutine(StdEnvironment.putDecl, Machine.putDisplacement); elaborateStdPrimRoutine(StdEnvironment.getintDecl, Machine.getintDisplacement); elaborateStdPrimRoutine(StdEnvironment.putintDecl, Machine.putintDisplacement); elaborateStdPrimRoutine(StdEnvironment.geteolDecl, Machine.geteolDisplacement); elaborateStdPrimRoutine(StdEnvironment.puteolDecl, Machine.puteolDisplacement); elaborateStdEqRoutine(StdEnvironment.equalDecl, Machine.eqDisplacement); elaborateStdEqRoutine(StdEnvironment.unequalDecl, Machine.neDisplacement); } // Saves the object program in the named file. public void saveObjectProgram(String objectName) { FileOutputStream objectFile = null; DataOutputStream objectStream = null; int addr; try { objectFile = new FileOutputStream (objectName); objectStream = new DataOutputStream (objectFile); addr = Machine.CB; for (addr = Machine.CB; addr < nextInstrAddr; addr++) Machine.code[addr].write(objectStream); objectFile.close(); } catch (FileNotFoundException s) { System.err.println ("Error opening object file: " + s); } catch (IOException s) { System.err.println ("Error writing object file: " + s); } } boolean tableDetailsReqd; public static void writeTableDetails(AST ast) { } // OBJECT CODE // Implementation notes: // Object code is generated directly into the TAM Code Store, starting at CB. // The address of the next instruction is held in nextInstrAddr. private int nextInstrAddr; // Appends an instruction, with the given fields, to the object code. private void emit (int op, int n, int r, int d) { Instruction nextInstr = new Instruction(); if (n > 255) { reporter.reportRestriction("length of operand can't exceed 255 words"); n = 255; // to allow code generation to continue } nextInstr.op = op; nextInstr.n = n; nextInstr.r = r; nextInstr.d = d; if (nextInstrAddr == Machine.PB) reporter.reportRestriction("too many instructions for code segment"); else { Machine.code[nextInstrAddr] = nextInstr; nextInstrAddr = nextInstrAddr + 1; } } // Patches the d-field of the instruction at address addr. private void patch (int addr, int d) { Machine.code[addr].d = d; } // DATA REPRESENTATION public int characterValuation (String spelling) { // Returns the machine representation of the given character literal. return spelling.charAt(1); // since the character literal is of the form 'x'} } // REGISTERS // Returns the register number appropriate for object code at currentLevel // to address a data object at objectLevel. private int displayRegister (int currentLevel, int objectLevel) { if (objectLevel == 0) return Machine.SBr; else if (currentLevel - objectLevel <= 6) return Machine.LBr + currentLevel - objectLevel; // LBr|L1r|...|L6r else { reporter.reportRestriction("can't access data more than 6 levels out"); return Machine.L6r; // to allow code generation to continue } } // Generates code to fetch the value of a named constant or variable // and push it on to the stack. // currentLevel is the routine level where the vname occurs. // frameSize is the anticipated size of the local stack frame when // the constant or variable is fetched at run-time. // valSize is the size of the constant or variable's value. private void encodeStore(Vname V, Frame frame, int valSize) { RuntimeEntity baseObject = (RuntimeEntity) V.visit(this, frame); // If indexed = true, code will have been generated to load an index value. if (valSize > 255) { reporter.reportRestriction("can't store values larger than 255 words"); valSize = 255; // to allow code generation to continue } if (baseObject instanceof KnownAddress) { ObjectAddress address = ((KnownAddress) baseObject).address; if (V.indexed) { emit(Machine.LOADAop, 0, displayRegister(frame.level, address.level), address.displacement + V.offset); emit(Machine.CALLop, Machine.SBr, Machine.PBr, Machine.addDisplacement); emit(Machine.STOREIop, valSize, 0, 0); } else { emit(Machine.STOREop, valSize, displayRegister(frame.level, address.level), address.displacement + V.offset); } } else if (baseObject instanceof UnknownAddress) { ObjectAddress address = ((UnknownAddress) baseObject).address; emit(Machine.LOADop, Machine.addressSize, displayRegister(frame.level, address.level), address.displacement); if (V.indexed) emit(Machine.CALLop, Machine.SBr, Machine.PBr, Machine.addDisplacement); if (V.offset != 0) { emit(Machine.LOADLop, 0, 0, V.offset); emit(Machine.CALLop, Machine.SBr, Machine.PBr, Machine.addDisplacement); } emit(Machine.STOREIop, valSize, 0, 0); } } // Generates code to fetch the value of a named constant or variable // and push it on to the stack. // currentLevel is the routine level where the vname occurs. // frameSize is the anticipated size of the local stack frame when // the constant or variable is fetched at run-time. // valSize is the size of the constant or variable's value. private void encodeFetch(Vname V, Frame frame, int valSize) { RuntimeEntity baseObject = (RuntimeEntity) V.visit(this, frame); // If indexed = true, code will have been generated to load an index value. if (valSize > 255) { reporter.reportRestriction("can't load values larger than 255 words"); valSize = 255; // to allow code generation to continue } if (baseObject instanceof KnownValue) { // presumably offset = 0 and indexed = false int value = ((KnownValue) baseObject).value; emit(Machine.LOADLop, 0, 0, value); } else if ((baseObject instanceof UnknownValue) || (baseObject instanceof KnownAddress)) { ObjectAddress address = (baseObject instanceof UnknownValue) ? ((UnknownValue) baseObject).address : ((KnownAddress) baseObject).address; if (V.indexed) { emit(Machine.LOADAop, 0, displayRegister(frame.level, address.level), address.displacement + V.offset); emit(Machine.CALLop, Machine.SBr, Machine.PBr, Machine.addDisplacement); emit(Machine.LOADIop, valSize, 0, 0); } else emit(Machine.LOADop, valSize, displayRegister(frame.level, address.level), address.displacement + V.offset); } else if (baseObject instanceof UnknownAddress) { ObjectAddress address = ((UnknownAddress) baseObject).address; emit(Machine.LOADop, Machine.addressSize, displayRegister(frame.level, address.level), address.displacement); if (V.indexed) emit(Machine.CALLop, Machine.SBr, Machine.PBr, Machine.addDisplacement); if (V.offset != 0) { emit(Machine.LOADLop, 0, 0, V.offset); emit(Machine.CALLop, Machine.SBr, Machine.PBr, Machine.addDisplacement); } emit(Machine.LOADIop, valSize, 0, 0); } } // Generates code to compute and push the address of a named variable. // vname is the program phrase that names this variable. // currentLevel is the routine level where the vname occurs. // frameSize is the anticipated size of the local stack frame when // the variable is addressed at run-time. private void encodeFetchAddress (Vname V, Frame frame) { RuntimeEntity baseObject = (RuntimeEntity) V.visit(this, frame); // If indexed = true, code will have been generated to load an index value. if (baseObject instanceof KnownAddress) { ObjectAddress address = ((KnownAddress) baseObject).address; emit(Machine.LOADAop, 0, displayRegister(frame.level, address.level), address.displacement + V.offset); if (V.indexed) emit(Machine.CALLop, Machine.SBr, Machine.PBr, Machine.addDisplacement); } else if (baseObject instanceof UnknownAddress) { ObjectAddress address = ((UnknownAddress) baseObject).address; emit(Machine.LOADop, Machine.addressSize,displayRegister(frame.level, address.level), address.displacement); if (V.indexed) emit(Machine.CALLop, Machine.SBr, Machine.PBr, Machine.addDisplacement); if (V.offset != 0) { emit(Machine.LOADLop, 0, 0, V.offset); emit(Machine.CALLop, Machine.SBr, Machine.PBr, Machine.addDisplacement); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -