Advertisement
Guest User

Untitled

a guest
Nov 27th, 2015
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.82 KB | None | 0 0
  1. """
  2. This is a quick experiment in implementing a stack machine that
  3. executes a set of given op codes. Just for fun.
  4. """
  5. class VMError(Exception):
  6. def __init__(self, kind):
  7. self.kind = kind
  8. self.message = ''
  9. def __str__(self):
  10. print "MICROVM", self.kind, self.message
  11. def __call__(self, message):
  12. self.message = message
  13. return self
  14.  
  15. StackError = VMError('StackError')
  16.  
  17. class Stack(list):
  18. def __init__(self, parent=None):
  19. self.parent = parent
  20. def pop(self):
  21. try:
  22. return super(Stack, self).pop()
  23. except:
  24. raise StackError('stack is empty')
  25.  
  26. class MicroOp(object):
  27. """ MicroOp is the implementation of an OpCode """
  28. def __init__(self, bytecode, mnemonic):
  29. self.bytecode = bytecode
  30. self.mnemonic = mnemonic
  31.  
  32. def execute(self, *args, **kwargs):
  33. pass
  34.  
  35. class ADD(MicroOp):
  36. def execute(self, *args, **kwargs):
  37. stack = kwargs.get('stack')
  38. opnum = args[0]
  39. opargs = [stack.pop() for i in range(opnum)]
  40. result = sum(opargs)
  41. stack.append(result)
  42. return result
  43.  
  44. class PUSH(MicroOp):
  45. def execute(self, *args, **kwargs):
  46. stack = kwargs.get('stack')
  47. stack.extend(args)
  48.  
  49. class PRINT(MicroOp):
  50. def execute(self, *args, **kwargs):
  51. stack = kwargs.get('stack')
  52. opnum = args[0] if args else 1
  53. opargs = [str(stack.pop()).replace('"', '').replace("'", '') for i in range(opnum)]
  54. print ' '.join(opargs)
  55.  
  56. OPCODES = {
  57. 0x01 : PUSH(0x01, 'PUSH'),
  58. 0x10 : ADD(0x10, 'ADD'),
  59. 0x20 : PRINT(0x20, 'PRINT'),
  60. }
  61.  
  62. MNEMONICS = { microop.mnemonic : opcode for opcode, microop in OPCODES.iteritems() }
  63.  
  64. class VM(object):
  65. """ A VM provides the execution context to run a byte code program """
  66. def __init__(self):
  67. self.stack = Stack()
  68.  
  69. def run(self, code):
  70. for op, args in code:
  71. OPCODES[op].execute(*args, stack=self.stack)
  72.  
  73. class Compiler(object):
  74. """ The compiler takes source code and produces byte code """
  75. def _native_value(self, value):
  76. tries = [int, float, str]
  77. for t in tries:
  78. try:
  79. return t(value)
  80. except:
  81. pass
  82. return value
  83.  
  84. def compile(self, source):
  85. code = []
  86. for loc, line in enumerate(source.split('\n')):
  87. if not line:
  88. continue
  89. parsed = line.split(' ', 1)
  90. mnemonic, args = parsed[0], parsed[1:]
  91. args = [self._native_value(arg) for arg in args]
  92. opcode = MNEMONICS.get(mnemonic)
  93. if opcode:
  94. code.append((opcode, args))
  95. else:
  96. raise SyntaxError("%d: invalid statement >%s<" % (loc, line))
  97. return code
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement