Skip to content
experimenting compiling python to michelson using the ast module
Python
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
compiler.py
helpers.py
main.py
readme.org
vm.py
vm_types.py

readme.org

Goal of the project

We’d like to compile Python code to Tezos’ Micelson bytecode using Python’s ast module. So fare, what has been implemented is:

  • a virtual machine with a Michelson-like bytecode. Ideally it would need to be identical rather than inspired, I will be working on this in the following weeks [1]. The VM is in vm.py.
  • a compiler backend from a Python ast to the Michelson implemented in the VM to speed up development and allow easy testing. The compiler is in compiler.py.

[1] https://tezos.gitlab.io/whitedoc/michelson.html

Usage

So far, only number variables and additions have been implemented in the compiler :D I’ll update the readme as things evolve.

Here is an example of how to declare and call functions and variables. For a more complex example, with nest functions and closures, have a look at main.py

from vm import VM
from compiler import Compiler

vm = VM(isDebug=True)
source = "baz = 1 \ndef foo(a): \n    b = 2 \n    return a + b + 3 \nbar = foo(baz) \nfff = foo(bar) \nfoo(foo(bar))"""
c = Compiler(source, isDebug=False)
instructions = c.compile(c.ast)

log = lambda msg: print(f"\n*** {msg}\n")
log("SOURCES")
print(source)

log("EXECUTION")
# Leaves us with the following VM state:
# ("S: [1, '[func]', 6, 11, ('*', 16)] ; sp: ", '4')
vm._run_instructions(instructions)
*** SOURCES

baz = 1 
def foo(a): 
    b = 2 
    return a + b + 3 
bar = foo(baz) 
fff = foo(bar) 
foo(foo(bar))

*** EXECUTION

===  COMMENT ['baz = 1'] {}  ===
('S: [] ; sp: ', '-1')
('S: [] ; sp: ', '-1')
===  PUSH [1] {}  ===
('S: [] ; sp: ', '-1')
("S: [('*', 1)] ; sp: ", '0')
===  COMMENT ['Storing function foo at 1'] {}  ===
("S: [('*', 1)] ; sp: ", '0')
("S: [('*', 1)] ; sp: ", '0')
===  PUSH [[Instr(name='COMMENT', args=['b = 2'], kwargs={}), Instr(name='PUSH', args=[2], kwargs={}), Instr(name='COMMENT', args=['Loading a at 2, e.sp = 3, jump = 1'], kwargs={}), Instr(name='DIP', args=[1], kwargs={}), Instr(name='DUP', args=[], kwargs={}), Instr(name='DIG', args=[1], kwargs={}), Instr(name='COMMENT', args=['Loading b at 3, e.sp = 4, jump = 1'], kwargs={}), Instr(name='DIP', args=[1], kwargs={}), Instr(name='DUP', args=[], kwargs={}), Instr(name='DIG', args=[1], kwargs={}), Instr(name='ADD', args=[], kwargs={}), Instr(name='PUSH', args=[3], kwargs={}), Instr(name='ADD', args=[], kwargs={}), Instr(name='COMMENT', args=['Freeing var b at 3'], kwargs={}), Instr(name='DIP', args=[1], kwargs={}), Instr(name='DROP', args=[], kwargs={}), Instr(name='IIP', args=[1], kwargs={}), Instr(name='COMMENT', args=['Freeing var a at 2'], kwargs={}), Instr(name='DIP', args=[1], kwargs={}), Instr(name='DROP', args=[], kwargs={}), Instr(name='IIP', args=[1], kwargs={})]] {}  ===
("S: [('*', 1)] ; sp: ", '0')
("S: [1, ('*', '[func]')] ; sp: ", '1')
===  COMMENT ['bar = [object]'] {}  ===
("S: [1, ('*', '[func]')] ; sp: ", '1')
("S: [1, ('*', '[func]')] ; sp: ", '1')
===  COMMENT ['Moving to function foo at 1, e.sp = 1'] {}  ===
("S: [1, ('*', '[func]')] ; sp: ", '1')
("S: [1, ('*', '[func]')] ; sp: ", '1')
===  DIP [0] {}  ===
("S: [1, ('*', '[func]')] ; sp: ", '1')
("S: [1, ('*', '[func]')] ; sp: ", '1')
===  COMMENT ['Loading baz at 0, e.sp = 1, jump = 1'] {}  ===
("S: [1, ('*', '[func]')] ; sp: ", '1')
("S: [1, ('*', '[func]')] ; sp: ", '1')
===  DIP [1] {}  ===
("S: [1, ('*', '[func]')] ; sp: ", '1')
("S: [('*', 1), '[func]'] ; sp: ", '0')
===  DUP [] {}  ===
("S: [('*', 1), '[func]'] ; sp: ", '0')
("S: [1, ('*', 1), '[func]'] ; sp: ", '1')
===  DIG [1] {}  ===
("S: [1, ('*', 1), '[func]'] ; sp: ", '1')
("S: [1, '[func]', ('*', 1)] ; sp: ", '2')
===  COMMENT ['Executing function foo at 1'] {}  ===
("S: [1, '[func]', ('*', 1)] ; sp: ", '2')
("S: [1, '[func]', ('*', 1)] ; sp: ", '2')
===  EXEC [] {}  ===
("S: [1, '[func]', ('*', 1)] ; sp: ", '2')
@@@@@@@ Start executing function @@@@@@@
===  COMMENT ['b = 2'] {}  ===
("S: [1, '[func]', ('*', 1)] ; sp: ", '2')
("S: [1, '[func]', ('*', 1)] ; sp: ", '2')
===  PUSH [2] {}  ===
("S: [1, '[func]', ('*', 1)] ; sp: ", '2')
("S: [1, '[func]', 1, ('*', 2)] ; sp: ", '3')
===  COMMENT ['Loading a at 2, e.sp = 3, jump = 1'] {}  ===
("S: [1, '[func]', 1, ('*', 2)] ; sp: ", '3')
("S: [1, '[func]', 1, ('*', 2)] ; sp: ", '3')
===  DIP [1] {}  ===
("S: [1, '[func]', 1, ('*', 2)] ; sp: ", '3')
("S: [1, '[func]', ('*', 1), 2] ; sp: ", '2')
===  DUP [] {}  ===
("S: [1, '[func]', ('*', 1), 2] ; sp: ", '2')
("S: [1, '[func]', 1, ('*', 1), 2] ; sp: ", '3')
===  DIG [1] {}  ===
("S: [1, '[func]', 1, ('*', 1), 2] ; sp: ", '3')
("S: [1, '[func]', 1, 2, ('*', 1)] ; sp: ", '4')
===  COMMENT ['Loading b at 3, e.sp = 4, jump = 1'] {}  ===
("S: [1, '[func]', 1, 2, ('*', 1)] ; sp: ", '4')
("S: [1, '[func]', 1, 2, ('*', 1)] ; sp: ", '4')
===  DIP [1] {}  ===
("S: [1, '[func]', 1, 2, ('*', 1)] ; sp: ", '4')
("S: [1, '[func]', 1, ('*', 2), 1] ; sp: ", '3')
===  DUP [] {}  ===
("S: [1, '[func]', 1, ('*', 2), 1] ; sp: ", '3')
("S: [1, '[func]', 1, 2, ('*', 2), 1] ; sp: ", '4')
===  DIG [1] {}  ===
("S: [1, '[func]', 1, 2, ('*', 2), 1] ; sp: ", '4')
("S: [1, '[func]', 1, 2, 1, ('*', 2)] ; sp: ", '5')
===  ADD [] {}  ===
("S: [1, '[func]', 1, 2, 1, ('*', 2)] ; sp: ", '5')
("S: [1, '[func]', 1, 2, ('*', 3)] ; sp: ", '4')
===  PUSH [3] {}  ===
("S: [1, '[func]', 1, 2, ('*', 3)] ; sp: ", '4')
("S: [1, '[func]', 1, 2, 3, ('*', 3)] ; sp: ", '5')
===  ADD [] {}  ===
("S: [1, '[func]', 1, 2, 3, ('*', 3)] ; sp: ", '5')
("S: [1, '[func]', 1, 2, ('*', 6)] ; sp: ", '4')
===  COMMENT ['Freeing var b at 3'] {}  ===
("S: [1, '[func]', 1, 2, ('*', 6)] ; sp: ", '4')
("S: [1, '[func]', 1, 2, ('*', 6)] ; sp: ", '4')
===  DIP [1] {}  ===
("S: [1, '[func]', 1, 2, ('*', 6)] ; sp: ", '4')
("S: [1, '[func]', 1, ('*', 2), 6] ; sp: ", '3')
===  DROP [] {}  ===
("S: [1, '[func]', 1, ('*', 2), 6] ; sp: ", '3')
("S: [1, '[func]', ('*', 1), 6] ; sp: ", '2')
===  IIP [1] {}  ===
("S: [1, '[func]', ('*', 1), 6] ; sp: ", '2')
("S: [1, '[func]', 1, ('*', 6)] ; sp: ", '3')
===  COMMENT ['Freeing var a at 2'] {}  ===
("S: [1, '[func]', 1, ('*', 6)] ; sp: ", '3')
("S: [1, '[func]', 1, ('*', 6)] ; sp: ", '3')
===  DIP [1] {}  ===
("S: [1, '[func]', 1, ('*', 6)] ; sp: ", '3')
("S: [1, '[func]', ('*', 1), 6] ; sp: ", '2')
===  DROP [] {}  ===
("S: [1, '[func]', ('*', 1), 6] ; sp: ", '2')
("S: [1, ('*', '[func]'), 6] ; sp: ", '1')
===  IIP [1] {}  ===
("S: [1, ('*', '[func]'), 6] ; sp: ", '1')
("S: [1, '[func]', ('*', 6)] ; sp: ", '2')
@@@@@@@ End executing function @@@@@@@
("S: [1, '[func]', ('*', 6)] ; sp: ", '2')
===  DIG [0] {}  ===
("S: [1, '[func]', ('*', 6)] ; sp: ", '2')
("S: [1, '[func]', ('*', 6)] ; sp: ", '2')
===  COMMENT ['fff = [object]'] {}  ===
("S: [1, '[func]', ('*', 6)] ; sp: ", '2')
("S: [1, '[func]', ('*', 6)] ; sp: ", '2')
===  COMMENT ['Moving to function foo at 1, e.sp = 2'] {}  ===
("S: [1, '[func]', ('*', 6)] ; sp: ", '2')
("S: [1, '[func]', ('*', 6)] ; sp: ", '2')
===  DIP [1] {}  ===
("S: [1, '[func]', ('*', 6)] ; sp: ", '2')
("S: [1, ('*', '[func]'), 6] ; sp: ", '1')
===  COMMENT ['Loading bar at 2, e.sp = 1, jump = -1'] {}  ===
("S: [1, ('*', '[func]'), 6] ; sp: ", '1')
("S: [1, ('*', '[func]'), 6] ; sp: ", '1')
===  DIP [-1] {}  ===
("S: [1, ('*', '[func]'), 6] ; sp: ", '1')
("S: [1, '[func]', ('*', 6)] ; sp: ", '2')
===  DUP [] {}  ===
("S: [1, '[func]', ('*', 6)] ; sp: ", '2')
("S: [1, '[func]', 6, ('*', 6)] ; sp: ", '3')
===  DIG [-1] {}  ===
("S: [1, '[func]', 6, ('*', 6)] ; sp: ", '3')
("S: [1, '[func]', ('*', 6), 6] ; sp: ", '2')
===  COMMENT ['Executing function foo at 1'] {}  ===
("S: [1, '[func]', ('*', 6), 6] ; sp: ", '2')
("S: [1, '[func]', ('*', 6), 6] ; sp: ", '2')
===  EXEC [] {}  ===
("S: [1, '[func]', ('*', 6), 6] ; sp: ", '2')
@@@@@@@ Start executing function @@@@@@@
===  COMMENT ['b = 2'] {}  ===
("S: [1, '[func]', ('*', 6), 6] ; sp: ", '2')
("S: [1, '[func]', ('*', 6), 6] ; sp: ", '2')
===  PUSH [2] {}  ===
("S: [1, '[func]', ('*', 6), 6] ; sp: ", '2')
("S: [1, '[func]', 6, ('*', 2), 6] ; sp: ", '3')
===  COMMENT ['Loading a at 2, e.sp = 3, jump = 1'] {}  ===
("S: [1, '[func]', 6, ('*', 2), 6] ; sp: ", '3')
("S: [1, '[func]', 6, ('*', 2), 6] ; sp: ", '3')
===  DIP [1] {}  ===
("S: [1, '[func]', 6, ('*', 2), 6] ; sp: ", '3')
("S: [1, '[func]', ('*', 6), 2, 6] ; sp: ", '2')
===  DUP [] {}  ===
("S: [1, '[func]', ('*', 6), 2, 6] ; sp: ", '2')
("S: [1, '[func]', 6, ('*', 6), 2, 6] ; sp: ", '3')
===  DIG [1] {}  ===
("S: [1, '[func]', 6, ('*', 6), 2, 6] ; sp: ", '3')
("S: [1, '[func]', 6, 2, ('*', 6), 6] ; sp: ", '4')
===  COMMENT ['Loading b at 3, e.sp = 4, jump = 1'] {}  ===
("S: [1, '[func]', 6, 2, ('*', 6), 6] ; sp: ", '4')
("S: [1, '[func]', 6, 2, ('*', 6), 6] ; sp: ", '4')
===  DIP [1] {}  ===
("S: [1, '[func]', 6, 2, ('*', 6), 6] ; sp: ", '4')
("S: [1, '[func]', 6, ('*', 2), 6, 6] ; sp: ", '3')
===  DUP [] {}  ===
("S: [1, '[func]', 6, ('*', 2), 6, 6] ; sp: ", '3')
("S: [1, '[func]', 6, 2, ('*', 2), 6, 6] ; sp: ", '4')
===  DIG [1] {}  ===
("S: [1, '[func]', 6, 2, ('*', 2), 6, 6] ; sp: ", '4')
("S: [1, '[func]', 6, 2, 6, ('*', 2), 6] ; sp: ", '5')
===  ADD [] {}  ===
("S: [1, '[func]', 6, 2, 6, ('*', 2), 6] ; sp: ", '5')
("S: [1, '[func]', 6, 2, ('*', 8), 6] ; sp: ", '4')
===  PUSH [3] {}  ===
("S: [1, '[func]', 6, 2, ('*', 8), 6] ; sp: ", '4')
("S: [1, '[func]', 6, 2, 8, ('*', 3), 6] ; sp: ", '5')
===  ADD [] {}  ===
("S: [1, '[func]', 6, 2, 8, ('*', 3), 6] ; sp: ", '5')
("S: [1, '[func]', 6, 2, ('*', 11), 6] ; sp: ", '4')
===  COMMENT ['Freeing var b at 3'] {}  ===
("S: [1, '[func]', 6, 2, ('*', 11), 6] ; sp: ", '4')
("S: [1, '[func]', 6, 2, ('*', 11), 6] ; sp: ", '4')
===  DIP [1] {}  ===
("S: [1, '[func]', 6, 2, ('*', 11), 6] ; sp: ", '4')
("S: [1, '[func]', 6, ('*', 2), 11, 6] ; sp: ", '3')
===  DROP [] {}  ===
("S: [1, '[func]', 6, ('*', 2), 11, 6] ; sp: ", '3')
("S: [1, '[func]', ('*', 6), 11, 6] ; sp: ", '2')
===  IIP [1] {}  ===
("S: [1, '[func]', ('*', 6), 11, 6] ; sp: ", '2')
("S: [1, '[func]', 6, ('*', 11), 6] ; sp: ", '3')
===  COMMENT ['Freeing var a at 2'] {}  ===
("S: [1, '[func]', 6, ('*', 11), 6] ; sp: ", '3')
("S: [1, '[func]', 6, ('*', 11), 6] ; sp: ", '3')
===  DIP [1] {}  ===
("S: [1, '[func]', 6, ('*', 11), 6] ; sp: ", '3')
("S: [1, '[func]', ('*', 6), 11, 6] ; sp: ", '2')
===  DROP [] {}  ===
("S: [1, '[func]', ('*', 6), 11, 6] ; sp: ", '2')
("S: [1, ('*', '[func]'), 11, 6] ; sp: ", '1')
===  IIP [1] {}  ===
("S: [1, ('*', '[func]'), 11, 6] ; sp: ", '1')
("S: [1, '[func]', ('*', 11), 6] ; sp: ", '2')
@@@@@@@ End executing function @@@@@@@
("S: [1, '[func]', ('*', 11), 6] ; sp: ", '2')
===  DIG [1] {}  ===
("S: [1, '[func]', ('*', 11), 6] ; sp: ", '2')
("S: [1, '[func]', 6, ('*', 11)] ; sp: ", '3')
===  COMMENT ['Moving to function foo at 1, e.sp = 3'] {}  ===
("S: [1, '[func]', 6, ('*', 11)] ; sp: ", '3')
("S: [1, '[func]', 6, ('*', 11)] ; sp: ", '3')
===  DIP [2] {}  ===
("S: [1, '[func]', 6, ('*', 11)] ; sp: ", '3')
("S: [1, ('*', '[func]'), 6, 11] ; sp: ", '1')
===  COMMENT ['Moving to function foo at 1, e.sp = 1'] {}  ===
("S: [1, ('*', '[func]'), 6, 11] ; sp: ", '1')
("S: [1, ('*', '[func]'), 6, 11] ; sp: ", '1')
===  DIP [0] {}  ===
("S: [1, ('*', '[func]'), 6, 11] ; sp: ", '1')
("S: [1, ('*', '[func]'), 6, 11] ; sp: ", '1')
===  COMMENT ['Loading bar at 2, e.sp = 1, jump = -1'] {}  ===
("S: [1, ('*', '[func]'), 6, 11] ; sp: ", '1')
("S: [1, ('*', '[func]'), 6, 11] ; sp: ", '1')
===  DIP [-1] {}  ===
("S: [1, ('*', '[func]'), 6, 11] ; sp: ", '1')
("S: [1, '[func]', ('*', 6), 11] ; sp: ", '2')
===  DUP [] {}  ===
("S: [1, '[func]', ('*', 6), 11] ; sp: ", '2')
("S: [1, '[func]', 6, ('*', 6), 11] ; sp: ", '3')
===  DIG [-1] {}  ===
("S: [1, '[func]', 6, ('*', 6), 11] ; sp: ", '3')
("S: [1, '[func]', ('*', 6), 6, 11] ; sp: ", '2')
===  COMMENT ['Executing function foo at 1'] {}  ===
("S: [1, '[func]', ('*', 6), 6, 11] ; sp: ", '2')
("S: [1, '[func]', ('*', 6), 6, 11] ; sp: ", '2')
===  EXEC [] {}  ===
("S: [1, '[func]', ('*', 6), 6, 11] ; sp: ", '2')
@@@@@@@ Start executing function @@@@@@@
===  COMMENT ['b = 2'] {}  ===
("S: [1, '[func]', ('*', 6), 6, 11] ; sp: ", '2')
("S: [1, '[func]', ('*', 6), 6, 11] ; sp: ", '2')
===  PUSH [2] {}  ===
("S: [1, '[func]', ('*', 6), 6, 11] ; sp: ", '2')
("S: [1, '[func]', 6, ('*', 2), 6, 11] ; sp: ", '3')
===  COMMENT ['Loading a at 2, e.sp = 3, jump = 1'] {}  ===
("S: [1, '[func]', 6, ('*', 2), 6, 11] ; sp: ", '3')
("S: [1, '[func]', 6, ('*', 2), 6, 11] ; sp: ", '3')
===  DIP [1] {}  ===
("S: [1, '[func]', 6, ('*', 2), 6, 11] ; sp: ", '3')
("S: [1, '[func]', ('*', 6), 2, 6, 11] ; sp: ", '2')
===  DUP [] {}  ===
("S: [1, '[func]', ('*', 6), 2, 6, 11] ; sp: ", '2')
("S: [1, '[func]', 6, ('*', 6), 2, 6, 11] ; sp: ", '3')
===  DIG [1] {}  ===
("S: [1, '[func]', 6, ('*', 6), 2, 6, 11] ; sp: ", '3')
("S: [1, '[func]', 6, 2, ('*', 6), 6, 11] ; sp: ", '4')
===  COMMENT ['Loading b at 3, e.sp = 4, jump = 1'] {}  ===
("S: [1, '[func]', 6, 2, ('*', 6), 6, 11] ; sp: ", '4')
("S: [1, '[func]', 6, 2, ('*', 6), 6, 11] ; sp: ", '4')
===  DIP [1] {}  ===
("S: [1, '[func]', 6, 2, ('*', 6), 6, 11] ; sp: ", '4')
("S: [1, '[func]', 6, ('*', 2), 6, 6, 11] ; sp: ", '3')
===  DUP [] {}  ===
("S: [1, '[func]', 6, ('*', 2), 6, 6, 11] ; sp: ", '3')
("S: [1, '[func]', 6, 2, ('*', 2), 6, 6, 11] ; sp: ", '4')
===  DIG [1] {}  ===
("S: [1, '[func]', 6, 2, ('*', 2), 6, 6, 11] ; sp: ", '4')
("S: [1, '[func]', 6, 2, 6, ('*', 2), 6, 11] ; sp: ", '5')
===  ADD [] {}  ===
("S: [1, '[func]', 6, 2, 6, ('*', 2), 6, 11] ; sp: ", '5')
("S: [1, '[func]', 6, 2, ('*', 8), 6, 11] ; sp: ", '4')
===  PUSH [3] {}  ===
("S: [1, '[func]', 6, 2, ('*', 8), 6, 11] ; sp: ", '4')
("S: [1, '[func]', 6, 2, 8, ('*', 3), 6, 11] ; sp: ", '5')
===  ADD [] {}  ===
("S: [1, '[func]', 6, 2, 8, ('*', 3), 6, 11] ; sp: ", '5')
("S: [1, '[func]', 6, 2, ('*', 11), 6, 11] ; sp: ", '4')
===  COMMENT ['Freeing var b at 3'] {}  ===
("S: [1, '[func]', 6, 2, ('*', 11), 6, 11] ; sp: ", '4')
("S: [1, '[func]', 6, 2, ('*', 11), 6, 11] ; sp: ", '4')
===  DIP [1] {}  ===
("S: [1, '[func]', 6, 2, ('*', 11), 6, 11] ; sp: ", '4')
("S: [1, '[func]', 6, ('*', 2), 11, 6, 11] ; sp: ", '3')
===  DROP [] {}  ===
("S: [1, '[func]', 6, ('*', 2), 11, 6, 11] ; sp: ", '3')
("S: [1, '[func]', ('*', 6), 11, 6, 11] ; sp: ", '2')
===  IIP [1] {}  ===
("S: [1, '[func]', ('*', 6), 11, 6, 11] ; sp: ", '2')
("S: [1, '[func]', 6, ('*', 11), 6, 11] ; sp: ", '3')
===  COMMENT ['Freeing var a at 2'] {}  ===
("S: [1, '[func]', 6, ('*', 11), 6, 11] ; sp: ", '3')
("S: [1, '[func]', 6, ('*', 11), 6, 11] ; sp: ", '3')
===  DIP [1] {}  ===
("S: [1, '[func]', 6, ('*', 11), 6, 11] ; sp: ", '3')
("S: [1, '[func]', ('*', 6), 11, 6, 11] ; sp: ", '2')
===  DROP [] {}  ===
("S: [1, '[func]', ('*', 6), 11, 6, 11] ; sp: ", '2')
("S: [1, ('*', '[func]'), 11, 6, 11] ; sp: ", '1')
===  IIP [1] {}  ===
("S: [1, ('*', '[func]'), 11, 6, 11] ; sp: ", '1')
("S: [1, '[func]', ('*', 11), 6, 11] ; sp: ", '2')
@@@@@@@ End executing function @@@@@@@
("S: [1, '[func]', ('*', 11), 6, 11] ; sp: ", '2')
===  DIG [0] {}  ===
("S: [1, '[func]', ('*', 11), 6, 11] ; sp: ", '2')
("S: [1, '[func]', ('*', 11), 6, 11] ; sp: ", '2')
===  COMMENT ['Executing function foo at 1'] {}  ===
("S: [1, '[func]', ('*', 11), 6, 11] ; sp: ", '2')
("S: [1, '[func]', ('*', 11), 6, 11] ; sp: ", '2')
===  EXEC [] {}  ===
("S: [1, '[func]', ('*', 11), 6, 11] ; sp: ", '2')
@@@@@@@ Start executing function @@@@@@@
===  COMMENT ['b = 2'] {}  ===
("S: [1, '[func]', ('*', 11), 6, 11] ; sp: ", '2')
("S: [1, '[func]', ('*', 11), 6, 11] ; sp: ", '2')
===  PUSH [2] {}  ===
("S: [1, '[func]', ('*', 11), 6, 11] ; sp: ", '2')
("S: [1, '[func]', 11, ('*', 2), 6, 11] ; sp: ", '3')
===  COMMENT ['Loading a at 2, e.sp = 3, jump = 1'] {}  ===
("S: [1, '[func]', 11, ('*', 2), 6, 11] ; sp: ", '3')
("S: [1, '[func]', 11, ('*', 2), 6, 11] ; sp: ", '3')
===  DIP [1] {}  ===
("S: [1, '[func]', 11, ('*', 2), 6, 11] ; sp: ", '3')
("S: [1, '[func]', ('*', 11), 2, 6, 11] ; sp: ", '2')
===  DUP [] {}  ===
("S: [1, '[func]', ('*', 11), 2, 6, 11] ; sp: ", '2')
("S: [1, '[func]', 11, ('*', 11), 2, 6, 11] ; sp: ", '3')
===  DIG [1] {}  ===
("S: [1, '[func]', 11, ('*', 11), 2, 6, 11] ; sp: ", '3')
("S: [1, '[func]', 11, 2, ('*', 11), 6, 11] ; sp: ", '4')
===  COMMENT ['Loading b at 3, e.sp = 4, jump = 1'] {}  ===
("S: [1, '[func]', 11, 2, ('*', 11), 6, 11] ; sp: ", '4')
("S: [1, '[func]', 11, 2, ('*', 11), 6, 11] ; sp: ", '4')
===  DIP [1] {}  ===
("S: [1, '[func]', 11, 2, ('*', 11), 6, 11] ; sp: ", '4')
("S: [1, '[func]', 11, ('*', 2), 11, 6, 11] ; sp: ", '3')
===  DUP [] {}  ===
("S: [1, '[func]', 11, ('*', 2), 11, 6, 11] ; sp: ", '3')
("S: [1, '[func]', 11, 2, ('*', 2), 11, 6, 11] ; sp: ", '4')
===  DIG [1] {}  ===
("S: [1, '[func]', 11, 2, ('*', 2), 11, 6, 11] ; sp: ", '4')
("S: [1, '[func]', 11, 2, 11, ('*', 2), 6, 11] ; sp: ", '5')
===  ADD [] {}  ===
("S: [1, '[func]', 11, 2, 11, ('*', 2), 6, 11] ; sp: ", '5')
("S: [1, '[func]', 11, 2, ('*', 13), 6, 11] ; sp: ", '4')
===  PUSH [3] {}  ===
("S: [1, '[func]', 11, 2, ('*', 13), 6, 11] ; sp: ", '4')
("S: [1, '[func]', 11, 2, 13, ('*', 3), 6, 11] ; sp: ", '5')
===  ADD [] {}  ===
("S: [1, '[func]', 11, 2, 13, ('*', 3), 6, 11] ; sp: ", '5')
("S: [1, '[func]', 11, 2, ('*', 16), 6, 11] ; sp: ", '4')
===  COMMENT ['Freeing var b at 3'] {}  ===
("S: [1, '[func]', 11, 2, ('*', 16), 6, 11] ; sp: ", '4')
("S: [1, '[func]', 11, 2, ('*', 16), 6, 11] ; sp: ", '4')
===  DIP [1] {}  ===
("S: [1, '[func]', 11, 2, ('*', 16), 6, 11] ; sp: ", '4')
("S: [1, '[func]', 11, ('*', 2), 16, 6, 11] ; sp: ", '3')
===  DROP [] {}  ===
("S: [1, '[func]', 11, ('*', 2), 16, 6, 11] ; sp: ", '3')
("S: [1, '[func]', ('*', 11), 16, 6, 11] ; sp: ", '2')
===  IIP [1] {}  ===
("S: [1, '[func]', ('*', 11), 16, 6, 11] ; sp: ", '2')
("S: [1, '[func]', 11, ('*', 16), 6, 11] ; sp: ", '3')
===  COMMENT ['Freeing var a at 2'] {}  ===
("S: [1, '[func]', 11, ('*', 16), 6, 11] ; sp: ", '3')
("S: [1, '[func]', 11, ('*', 16), 6, 11] ; sp: ", '3')
===  DIP [1] {}  ===
("S: [1, '[func]', 11, ('*', 16), 6, 11] ; sp: ", '3')
("S: [1, '[func]', ('*', 11), 16, 6, 11] ; sp: ", '2')
===  DROP [] {}  ===
("S: [1, '[func]', ('*', 11), 16, 6, 11] ; sp: ", '2')
("S: [1, ('*', '[func]'), 16, 6, 11] ; sp: ", '1')
===  IIP [1] {}  ===
("S: [1, ('*', '[func]'), 16, 6, 11] ; sp: ", '1')
("S: [1, '[func]', ('*', 16), 6, 11] ; sp: ", '2')
@@@@@@@ End executing function @@@@@@@
("S: [1, '[func]', ('*', 16), 6, 11] ; sp: ", '2')
===  DIG [2] {}  ===
("S: [1, '[func]', ('*', 16), 6, 11] ; sp: ", '2')
("S: [1, '[func]', 6, 11, ('*', 16)] ; sp: ", '4')
You can’t perform that action at this time.