| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- IMPLEMENTATION MODULE Interpreter; (* gf 05.01.89 *)
- FROM SYSTEM IMPORT WORD;
- FROM InOut IMPORT Read, ReadInt,
- Write, WriteLn, WriteInt, WriteString,
- Done, termCH, EOL;
- IMPORT STextIO, NumberIO;
- CONST
- stackSize = 1000;
- VAR
- stack : ARRAY [0..stackSize-1] OF CARDINAL; (* Program Stack *)
- zeroc : CHAR;
- PROCEDURE ReadLn;
- VAR c : CHAR;
- BEGIN
- c := termCH;
- WHILE c # EOL DO Read(c) END;
- END ReadLn;
- PROCEDURE Interpret(VAR code : ARRAY OF INSTR);
- VAR PC, BR, SP: CARDINAL; (* Program-, Base-, Stack-Registers *)
- IR : INSTR; (* Instruction Register *)
- tmpint : INTEGER; (* internal Register *)
- i : CARDINAL;
- SR, DR, CR: CARDINAL; (* internal Registers *)
- PROCEDURE base(l : CARDINAL) : CARDINAL;
- VAR b1: CARDINAL;
- BEGIN
- b1 := BR;
- WHILE l > 0 DO
- b1 := stack[b1]; DEC(l)
- END;
- RETURN b1
- END base;
- PROCEDURE INTArith(c: Command; op1, op2: INTEGER) : CARDINAL;
- VAR res : INTEGER;
- BEGIN
- CASE c OF
- ADDi: res := op1 + op2;
- | SUBi: res := op1 - op2;
- | MULi: res := op1 * op2;
- | DIVi: res := op1 DIV op2;
- | EQ : res := ORD(op1 = op2);
- | NE : res := ORD(op1 # op2);
- | LT : res := ORD(op1 < op2);
- | GE : res := ORD(op1 >= op2);
- | GT : res := ORD(op1 > op2);
- | LE : res := ORD(op1 <= op2);
- END;
- RETURN CARDINAL(res)
- END INTArith;
- BEGIN (* Interpret *)
- SP := 0;
- BR := 1;
- PC := 0;
- stack[1] := 0;
- stack[2] := 0;
- stack[3] := 0;
- REPEAT
- IR := code[PC];
- INC(PC);
- CASE IR.cmd OF
- MSP :(* modifiy SP by IR.val *)
- SP := CARDINAL(INTEGER(SP) + INTEGER(IR.val))
- | LDA :(* load address *)
- INC(SP);
- stack[SP] := base(IR.lev) + IR.val
- | LDI :(* load immediate value *)
- INC(SP); stack[SP] := IR.val;
- | LDIs:(* load immediate string of length 'IR.val' onto stack *)
- FOR CR := 0 TO IR.val - 1 DO
- i := CR MOD 6;
- IF i = 0 THEN
- IR := code[PC]; INC(PC)
- END;
- INC(SP); stack[SP] := ORD(IR.sval[i])
- END
- | MV :(* move 'IR.val' words *)
- SR := stack[SP - 1];
- DR := stack[SP];
- CR := IR.val;
- WHILE CR > 0 DO
- stack[DR] := stack[SR];
- INC(DR); INC(SR);
- DEC(CR)
- END;
- DEC(SP, 2)
- | JMP :(* unconditional jump *)
- PC := IR.val
- | JMPC:(* jump if condition was false *)
- IF stack[SP] = 0 THEN PC := IR.val END;
- DEC(SP)
- | CALL:(* generate new block mark and jump to procedure *)
- stack[SP+1] := base(IR.lev);
- stack[SP+2] := BR;
- stack[SP+3] := PC;
- BR := SP+1;
- PC := IR.val
- | RET :(* return from procedure *)
- SP := BR-1;
- PC := stack[SP+3];
- BR := stack[SP+2]
- | LD :(* load value *)
- stack[SP] := stack[ stack[SP] ]
- | ST :(* store value *)
- stack[ stack[SP] ] := stack[SP-1];
- DEC(SP, 2)
- | NEGi:(* negate top of stack value *)
- stack[SP] := CARDINAL(-INTEGER(stack[SP]))
- | ODDi:(* yields true if top of stack values was odd, else false *)
- stack[SP] := ORD(ODD(INTEGER(stack[SP])))
- (*=== integer arithmetic ===*)
- | ADDi,SUBi,MULi,DIVi,
- EQ, NE,
- LT, GE, GT, LE:
- DEC(SP);
- stack[SP] := INTArith(IR.cmd,
- INTEGER(stack[SP]),
- INTEGER(stack[SP+1]))
- (*=== boolean operations ===*)
- | ANDb:DEC(SP);
- stack[SP] := ORD((stack[SP] > 0) AND (stack[SP+1] > 0))
- | ORb :DEC(SP);
- stack[SP] := ORD((stack[SP] > 0) OR (stack[SP+1] > 0))
- | NOTb:stack[SP] := ORD( NOT(stack[SP] > 0))
- (*=== input/output ===*)
- | INi : (* read integer value onto stack *)
- INC(SP);
- STextIO.WriteString('Integer Input >');
- REPEAT
- NumberIO.ReadInt(tmpint);
- UNTIL tmpint <> 0;
- IF SP < stackSize THEN
- stack[SP] := CARDINAL(tmpint);
- ELSE
- STextIO.WriteString("Stack overload !");
- STextIO.WriteLn;
- PC := 0 (* terminate program *)
- END;
- (* ReadLn; *)
- | OUTi: (* write top of stack integer value *)
- NumberIO.WriteInt(INTEGER(stack[SP]), 7);
- DEC(SP)
- | OUTc: (* Write top of stack characters *)
- CR := stack[SP]; DEC(SP);
- WHILE CR > 0 DO
- STextIO.WriteChar(CHR(stack[SP]));
- DEC(SP);
- DEC(CR)
- END;
- END;
- (* flushing the input buffer*)
- UNTIL PC = 0;
- END Interpret;
- BEGIN
- END Interpreter.
|