Interpreter.mod 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. IMPLEMENTATION MODULE Interpreter; (* gf 05.01.89 *)
  2. FROM SYSTEM IMPORT WORD;
  3. FROM InOut IMPORT Read, ReadInt,
  4. Write, WriteLn, WriteInt, WriteString,
  5. Done, termCH, EOL;
  6. IMPORT STextIO, NumberIO;
  7. CONST
  8. stackSize = 1000;
  9. VAR
  10. stack : ARRAY [0..stackSize-1] OF CARDINAL; (* Program Stack *)
  11. zeroc : CHAR;
  12. PROCEDURE ReadLn;
  13. VAR c : CHAR;
  14. BEGIN
  15. c := termCH;
  16. WHILE c # EOL DO Read(c) END;
  17. END ReadLn;
  18. PROCEDURE Interpret(VAR code : ARRAY OF INSTR);
  19. VAR PC, BR, SP: CARDINAL; (* Program-, Base-, Stack-Registers *)
  20. IR : INSTR; (* Instruction Register *)
  21. tmpint : INTEGER; (* internal Register *)
  22. i : CARDINAL;
  23. SR, DR, CR: CARDINAL; (* internal Registers *)
  24. PROCEDURE base(l : CARDINAL) : CARDINAL;
  25. VAR b1: CARDINAL;
  26. BEGIN
  27. b1 := BR;
  28. WHILE l > 0 DO
  29. b1 := stack[b1]; DEC(l)
  30. END;
  31. RETURN b1
  32. END base;
  33. PROCEDURE INTArith(c: Command; op1, op2: INTEGER) : CARDINAL;
  34. VAR res : INTEGER;
  35. BEGIN
  36. CASE c OF
  37. ADDi: res := op1 + op2;
  38. | SUBi: res := op1 - op2;
  39. | MULi: res := op1 * op2;
  40. | DIVi: res := op1 DIV op2;
  41. | EQ : res := ORD(op1 = op2);
  42. | NE : res := ORD(op1 # op2);
  43. | LT : res := ORD(op1 < op2);
  44. | GE : res := ORD(op1 >= op2);
  45. | GT : res := ORD(op1 > op2);
  46. | LE : res := ORD(op1 <= op2);
  47. END;
  48. RETURN CARDINAL(res)
  49. END INTArith;
  50. BEGIN (* Interpret *)
  51. SP := 0;
  52. BR := 1;
  53. PC := 0;
  54. stack[1] := 0;
  55. stack[2] := 0;
  56. stack[3] := 0;
  57. REPEAT
  58. IR := code[PC];
  59. INC(PC);
  60. CASE IR.cmd OF
  61. MSP :(* modifiy SP by IR.val *)
  62. SP := CARDINAL(INTEGER(SP) + INTEGER(IR.val))
  63. | LDA :(* load address *)
  64. INC(SP);
  65. stack[SP] := base(IR.lev) + IR.val
  66. | LDI :(* load immediate value *)
  67. INC(SP); stack[SP] := IR.val;
  68. | LDIs:(* load immediate string of length 'IR.val' onto stack *)
  69. FOR CR := 0 TO IR.val - 1 DO
  70. i := CR MOD 6;
  71. IF i = 0 THEN
  72. IR := code[PC]; INC(PC)
  73. END;
  74. INC(SP); stack[SP] := ORD(IR.sval[i])
  75. END
  76. | MV :(* move 'IR.val' words *)
  77. SR := stack[SP - 1];
  78. DR := stack[SP];
  79. CR := IR.val;
  80. WHILE CR > 0 DO
  81. stack[DR] := stack[SR];
  82. INC(DR); INC(SR);
  83. DEC(CR)
  84. END;
  85. DEC(SP, 2)
  86. | JMP :(* unconditional jump *)
  87. PC := IR.val
  88. | JMPC:(* jump if condition was false *)
  89. IF stack[SP] = 0 THEN PC := IR.val END;
  90. DEC(SP)
  91. | CALL:(* generate new block mark and jump to procedure *)
  92. stack[SP+1] := base(IR.lev);
  93. stack[SP+2] := BR;
  94. stack[SP+3] := PC;
  95. BR := SP+1;
  96. PC := IR.val
  97. | RET :(* return from procedure *)
  98. SP := BR-1;
  99. PC := stack[SP+3];
  100. BR := stack[SP+2]
  101. | LD :(* load value *)
  102. stack[SP] := stack[ stack[SP] ]
  103. | ST :(* store value *)
  104. stack[ stack[SP] ] := stack[SP-1];
  105. DEC(SP, 2)
  106. | NEGi:(* negate top of stack value *)
  107. stack[SP] := CARDINAL(-INTEGER(stack[SP]))
  108. | ODDi:(* yields true if top of stack values was odd, else false *)
  109. stack[SP] := ORD(ODD(INTEGER(stack[SP])))
  110. (*=== integer arithmetic ===*)
  111. | ADDi,SUBi,MULi,DIVi,
  112. EQ, NE,
  113. LT, GE, GT, LE:
  114. DEC(SP);
  115. stack[SP] := INTArith(IR.cmd,
  116. INTEGER(stack[SP]),
  117. INTEGER(stack[SP+1]))
  118. (*=== boolean operations ===*)
  119. | ANDb:DEC(SP);
  120. stack[SP] := ORD((stack[SP] > 0) AND (stack[SP+1] > 0))
  121. | ORb :DEC(SP);
  122. stack[SP] := ORD((stack[SP] > 0) OR (stack[SP+1] > 0))
  123. | NOTb:stack[SP] := ORD( NOT(stack[SP] > 0))
  124. (*=== input/output ===*)
  125. | INi : (* read integer value onto stack *)
  126. INC(SP);
  127. STextIO.WriteString('Integer Input >');
  128. REPEAT
  129. NumberIO.ReadInt(tmpint);
  130. UNTIL tmpint <> 0;
  131. IF SP < stackSize THEN
  132. stack[SP] := CARDINAL(tmpint);
  133. ELSE
  134. STextIO.WriteString("Stack overload !");
  135. STextIO.WriteLn;
  136. PC := 0 (* terminate program *)
  137. END;
  138. (* ReadLn; *)
  139. | OUTi: (* write top of stack integer value *)
  140. NumberIO.WriteInt(INTEGER(stack[SP]), 7);
  141. DEC(SP)
  142. | OUTc: (* Write top of stack characters *)
  143. CR := stack[SP]; DEC(SP);
  144. WHILE CR > 0 DO
  145. STextIO.WriteChar(CHR(stack[SP]));
  146. DEC(SP);
  147. DEC(CR)
  148. END;
  149. END;
  150. (* flushing the input buffer*)
  151. UNTIL PC = 0;
  152. END Interpret;
  153. BEGIN
  154. END Interpreter.