bytecode_ir.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. """Provides data structures that represent parsed Modelverse bytecode graphs."""
  2. class Instruction(object):
  3. """Represents a Modelverse bytecode instruction."""
  4. def __init__(self):
  5. self.next_instruction = None
  6. self.debug_information = None
  7. class VariableNode(object):
  8. """Represents a variable node, which has an identifier and an optional name."""
  9. def __init__(self, node_id, name):
  10. self.node_id = node_id
  11. self.name = name
  12. def __str__(self):
  13. return 'var(%d, %s)' % (self.node_id, self.name)
  14. def __repr__(self):
  15. return 'VariableNode(%r, %r)' % (self.node_id, self.name)
  16. class SelectInstruction(Instruction):
  17. """Represents an 'if/else' instruction."""
  18. def __init__(self, condition, if_clause, else_clause):
  19. Instruction.__init__(self)
  20. self.condition = condition
  21. self.if_clause = if_clause
  22. self.else_clause = else_clause
  23. constructor_parameters = (
  24. ('cond', Instruction),
  25. ('then', Instruction),
  26. ('else', Instruction))
  27. def __repr__(self):
  28. return '@%r: SelectInstruction(@%r, @%r, @%r)' % (
  29. id(self), id(self.condition), id(self.if_clause), id(self.else_clause))
  30. class WhileInstruction(Instruction):
  31. """Represents a 'while' instruction."""
  32. def __init__(self, condition, body):
  33. Instruction.__init__(self)
  34. self.condition = condition
  35. self.body = body
  36. constructor_parameters = (
  37. ('cond', Instruction),
  38. ('body', Instruction))
  39. def __repr__(self):
  40. return '@%r: WhileInstruction(@%r, @%r)' % (
  41. id(self), id(self.condition), id(self.body))
  42. class BreakInstruction(Instruction):
  43. """Represents a 'break' instruction."""
  44. def __init__(self, loop):
  45. Instruction.__init__(self)
  46. self.loop = loop
  47. constructor_parameters = (('while', WhileInstruction),)
  48. def __repr__(self):
  49. return '@%r: BreakInstruction(@%r)' % (
  50. id(self), id(self.loop))
  51. class ContinueInstruction(Instruction):
  52. """Represents a 'continue' instruction."""
  53. def __init__(self, loop):
  54. Instruction.__init__(self)
  55. self.loop = loop
  56. constructor_parameters = (('while', WhileInstruction),)
  57. def __repr__(self):
  58. return '@%r: ContinueInstruction(@%r)' % (
  59. id(self), id(self.loop))
  60. class ReturnInstruction(Instruction):
  61. """Represents a 'return' instruction, which terminates the current function
  62. and optionally returns a value."""
  63. def __init__(self, value):
  64. Instruction.__init__(self)
  65. self.value = value
  66. constructor_parameters = (('value', Instruction),)
  67. def __repr__(self):
  68. return '@%r: ReturnInstruction(@%r)' % (
  69. id(self), id(self.value))
  70. class CallInstruction(Instruction):
  71. """Represents a 'call' instruction, which calls a function with an argument
  72. list, encoded as a list of name-instruction tuples."""
  73. def __init__(self, target, argument_list):
  74. Instruction.__init__(self)
  75. self.target = target
  76. self.argument_list = argument_list
  77. def __repr__(self):
  78. return '@%r: CallInstruction(@%r, [%s])' % (
  79. id(self), id(self.target),
  80. ', '.join(['%s=@%r' % (name, id(value)) for name, value in self.argument_list]))
  81. class ConstantInstruction(Instruction):
  82. """Represents a 'constant' instruction, which produces a reference
  83. to a constant node."""
  84. def __init__(self, constant_id):
  85. Instruction.__init__(self)
  86. self.constant_id = constant_id
  87. assert self.constant_id is not None
  88. constructor_parameters = (('node', int),)
  89. def __repr__(self):
  90. return '@%r: ConstantInstruction(%r)' % (id(self), self.constant_id)
  91. class InputInstruction(Instruction):
  92. """Represents an 'input' instruction, which pops a node from the input
  93. queue."""
  94. def __init__(self):
  95. Instruction.__init__(self)
  96. constructor_parameters = ()
  97. def __repr__(self):
  98. return '@%r: InputInstruction()' % id(self)
  99. class OutputInstruction(Instruction):
  100. """Represents an 'output' instruction, which pushes a node onto the output
  101. queue."""
  102. def __init__(self, value):
  103. Instruction.__init__(self)
  104. self.value = value
  105. constructor_parameters = (('value', Instruction),)
  106. def __repr__(self):
  107. return '@%r: OutputInstruction(@%r)' % (
  108. id(self), id(self.value))
  109. class DeclareInstruction(Instruction):
  110. """Represents a 'declare' instruction, which declares a local variable."""
  111. def __init__(self, variable):
  112. Instruction.__init__(self)
  113. self.variable = variable
  114. constructor_parameters = (('var', VariableNode),)
  115. def __repr__(self):
  116. return '@%r: DeclareInstruction(%r)' % (
  117. id(self), self.variable)
  118. class GlobalInstruction(Instruction):
  119. """Represents a 'global' instruction, which declares a global variable."""
  120. def __init__(self, variable):
  121. Instruction.__init__(self)
  122. self.variable = variable
  123. constructor_parameters = (('var', VariableNode),)
  124. def __repr__(self):
  125. return '@%r: GlobalInstruction(%r)' % (
  126. id(self), self.variable)
  127. class ResolveInstruction(Instruction):
  128. """Represents a 'resolve' instruction, which resolves a variable node/name as
  129. either a local or global variable."""
  130. def __init__(self, variable):
  131. Instruction.__init__(self)
  132. self.variable = variable
  133. constructor_parameters = (('var', VariableNode),)
  134. def __repr__(self):
  135. return '@%r: ResolveInstruction(%r)' % (
  136. id(self), self.variable)
  137. class AccessInstruction(Instruction):
  138. """Represents an 'access' instruction, which loads the node pointed to by a
  139. pointer node."""
  140. def __init__(self, pointer):
  141. Instruction.__init__(self)
  142. self.pointer = pointer
  143. constructor_parameters = (('var', Instruction),)
  144. def __repr__(self):
  145. return '@%r: AccessInstruction(@%r)' % (
  146. id(self), id(self.pointer))
  147. class AssignInstruction(Instruction):
  148. """Represents an 'assign' instruction, which sets the node pointed to by a
  149. pointer node to the given node."""
  150. def __init__(self, pointer, value):
  151. Instruction.__init__(self)
  152. self.pointer = pointer
  153. self.value = value
  154. constructor_parameters = (
  155. ('var', Instruction),
  156. ('value', Instruction))
  157. def __repr__(self):
  158. return '@%r: AssignInstruction(@%r, @%r)' % (
  159. id(self), id(self.pointer), id(self.value))
  160. INSTRUCTION_TYPE_MAPPING = {
  161. 'if' : SelectInstruction,
  162. 'while' : WhileInstruction,
  163. 'return' : ReturnInstruction,
  164. 'constant' : ConstantInstruction,
  165. 'resolve' : ResolveInstruction,
  166. 'declare' : DeclareInstruction,
  167. 'global' : GlobalInstruction,
  168. 'assign' : AssignInstruction,
  169. 'access' : AccessInstruction,
  170. 'output' : OutputInstruction,
  171. 'input' : InputInstruction,
  172. 'call' : CallInstruction,
  173. 'break' : BreakInstruction,
  174. 'continue' : ContinueInstruction
  175. }
  176. """Maps instruction names to types."""