-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Intro: https://en.wikipedia.org/wiki/Static_single_assignment_form
Convert Python to SSA form. Baseline example:
a = 0
if a:
x = 1
else:
x = 2
print(x)
Schematic transformation to SSA would be:
a0 = 0
if a0:
x0 = 1
else:
x1 = 2
x2 = __phi__(x0, x1)
print(x2)
However, that's not executable form. Can actually make it executable with more syntactic noise:
from ssa_interp import *
# All vars should be initialized
x0 = x1 = None
a0 = 0
__label__("bb0")
if a0:
__label__("bb1")
x0 = 1
else:
__label__("bb2")
x1 = 2
# Crucial point - __phi__'s really should be first "instructions" of
# the basic block, even before a label.
x2 = __phi__({"bb1": x0, "bb2": x1})
__label__("bb3")
print(x2)
Where ssa_interp.py is:
__all__ = ("__label__", "__phi__")
_last_bblock = None
def __label__(lab):
global _last_bblock
_last_bblock = lab
def __phi__(choices):
global _last_bblock
return choices[_last_bblock]
The challenge is to convert arbitrary Python source code to such an SSA form. See how far we can go without explicit __goto__. The first suspects would be break/continue. But Aycock/Hosrpool aren't put down by them. Indeed, break/continue are static control flow, so we just add CFG edge, and it's not important what we have in the surface form.
The real suspect is of course exception handling. But while it's conceptually dynamic control flow, we can over-approximate it statically. That would lead to ugly multi-var phi's, but such is exception handling. That's why many languages afraid of it. Us shouldn't ;-).