PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/PEG_GrammarExplorer/PEG_GrammarExplorer/PegSamples/python_2_5_2/input/simple_baby.py

http://github.com/chrisjowen/nLess
Python | 110 lines | 82 code | 11 blank | 17 comment | 14 complexity | 3d5a6d81e3d8e278eb13d3b1e83a4725 MD5 | raw file
  1. def comp2(n):
  2. "Constrain n to the range of a 32-bit 2s-complement number"
  3. if not (-pow(2,31) <=n < pow(2,31)):
  4. if n>0: n = -pow(2,31) + (n-pow(2,31))
  5. else: n = pow(2,31) + n + pow(2,31)
  6. return n
  7. class SSEM:
  8. def __init__(self):
  9. # There are 32 32-bit words which make up the memory
  10. self.store = [0]*32
  11. # Zero the accumulator and the program counter
  12. self.accum = self.CI = 0
  13. self.stopped = 0
  14. def step(self):
  15. """Perform a single instruction, updating the store and registers."""
  16. if self.stopped: return # Do nothing when the machine is stopped
  17. # 2.3: "The CI is always incremented prior to fetching an
  18. # instruction for execution..."
  19. self.CI = comp2( (self.CI + 1) )
  20. # Fetch the instruction
  21. inst = self.store[ self.CI & 31]
  22. # Decode the line number affected by the instruction, and the
  23. # function number
  24. lineno, funcno = inst & 31, (inst >> 13) & 7
  25. assert 0<= funcno <=7
  26. if funcno == 0:
  27. # s,C : JMP : Copy content of Store line to CI
  28. self.CI = self.store[ lineno ]
  29. elif funcno == 1:
  30. # c+s,C : JRP : Add content of Store line to CI
  31. self.CI = comp2(self.CI + self.store[ lineno ])
  32. elif funcno == 2:
  33. # -s,A : LDN : Copy content of Store line, negated, to accum
  34. self.accum = comp2 (- self.store[ lineno ])
  35. elif funcno == 3:
  36. # a,S : STO : Copy content of acc. to Store line
  37. self.store[ lineno ] = self.accum
  38. elif funcno == 4 or funcno==5:
  39. # a-s,A : SUB : Subtract content of Store line from accum
  40. self.accum = comp2( self.accum - self.store[ lineno ] )
  41. elif funcno == 6:
  42. # Test : CMP : Skip next instruction if content of accum
  43. # is negative
  44. if self.accum < 0: self.CI = comp2(self.CI + 1)
  45. elif funcno == 7:
  46. # Stop : STOP : Light "Stop" neon and halt the machine
  47. self.stopped = 1
  48. # Assertions to test invariants
  49. assert -pow(2,31) <= self.accum <pow(2,31)
  50. assert -pow(2,31) <= self.store[ lineno ] <pow(2,31)
  51. assert -pow(2,31) <= self.CI <pow(2,31)
  52. import re, string
  53. inst_pat = re.compile("""\s*
  54. (?P<mnemonic>JMP|JRP|LDN|STOP|STO|SUB|CMP)
  55. \s*
  56. (?P<arg>\d+) # numeric argument""", re.VERBOSE | re.IGNORECASE)
  57. # There are two variants of the SUB instruction; SUB has an opcode of
  58. # 4, and SUBF has an opcode of 5. Both have the exact same effects,
  59. # and differ only in their opcode.
  60. opcode = {'JMP':0, 'JRP':1, 'LDN':2, 'STO':3, 'SUB':4, 'SUBF':5,
  61. 'CMP':6, 'STOP':7 }
  62. def assemble(inst_list):
  63. if len(inst_list)>32:
  64. raise ValueError, "Only room for 32 instructions"
  65. machine = SSEM()
  66. for i in range(len(inst_list)):
  67. m = inst_pat.match(string.upper(inst_list[i]))
  68. if not m: raise ValueError, "Error in assembly code: " + inst_list[i]
  69. mnemonic, arg = m.group('mnemonic'), m.group('arg')
  70. arg = string.atoi(arg)
  71. machine.store[ i ] = arg | (opcode[mnemonic] << 13)
  72. return machine
  73. if __name__ == '__main__':
  74. # Try the addition test
  75. p=pow(2,31)
  76. assert (comp2(p-1), comp2(p), comp2(p+1)) == (p-1, -p, -p+1)
  77. assert (comp2(-p), comp2(-p-1), comp2(-p-2)) == (-p, p-1, p-2)
  78. m=assemble(['JMP 0',
  79. 'LDN 28',
  80. 'SUB 29',
  81. 'STO 30',
  82. 'LDN 30',
  83. 'STO 30',
  84. 'STOP 0'])
  85. x = p-1 ; y = -p
  86. m.store[28] = x ; m.store[29] = y
  87. while not m.stopped:
  88. m.step()
  89. assert m.store[30] == comp2(x+y)