87 lines
2.6 KiB
Python
87 lines
2.6 KiB
Python
import ast
|
|
from type_def import PrimitiveType
|
|
from parse_expr import parse_expr
|
|
|
|
class Lifetime:
|
|
low: int
|
|
original: int
|
|
|
|
def __init__(self, scope):
|
|
self.low = self.original = scope
|
|
self.parent = None
|
|
|
|
def fold(self):
|
|
while self.parent is not None:
|
|
self.low = self.parent.low
|
|
self.original = self.parent.original
|
|
self.parent = self.parent.parent
|
|
return self
|
|
|
|
def ok(self, other):
|
|
self.fold()
|
|
if other == None:
|
|
return False
|
|
other.fold()
|
|
return self.low >= other.original and \
|
|
(other.original != self.low or self.low != 1)
|
|
|
|
def __str__(self):
|
|
self.fold()
|
|
return f'({self.low}, {self.original})'
|
|
|
|
|
|
def assign_expr(
|
|
scope: int,
|
|
sym_table: dict[str, Lifetime],
|
|
expr: ast.expr):
|
|
if isinstance(expr, ast.Expression):
|
|
body = expr.body
|
|
else:
|
|
body = expr
|
|
if isinstance(body.type, PrimitiveType):
|
|
body.lifetime = None
|
|
elif isinstance(body, ast.Attribute):
|
|
body.lifetime = assign_expr(scope, sym_table, body.value)
|
|
elif isinstance(body, ast.Subscript):
|
|
body.lifetime = assign_expr(scope, sym_table, body.value)
|
|
elif isinstance(body, ast.Name):
|
|
if body.id in sym_table:
|
|
body.lifetime = sym_table[body.id]
|
|
else:
|
|
body.lifetime = Lifetime(scope)
|
|
sym_table[body.id] = body.lifetime
|
|
else:
|
|
body.lifetime = Lifetime(scope)
|
|
return body.lifetime
|
|
|
|
|
|
def assign_stmt(
|
|
scope: int,
|
|
sym_table: dict[str, Lifetime],
|
|
nodes):
|
|
for node in nodes:
|
|
if isinstance(node, ast.Assign):
|
|
b = assign_expr(scope, sym_table, node.value)
|
|
for target in node.targets:
|
|
a = assign_expr(scope, sym_table, target)
|
|
if a == None and b == None:
|
|
continue
|
|
if not a.ok(b):
|
|
print(ast.unparse(node))
|
|
print(f'{a} <- {b}')
|
|
assert False
|
|
a.low = min(a.low, b.low)
|
|
a.original = max(a.original, b.original)
|
|
b.parent = a
|
|
elif isinstance(node, ast.If) or isinstance(node, ast.While):
|
|
assign_stmt(scope + 1, sym_table, node.body)
|
|
assign_stmt(scope + 1, sym_table, node.orelse)
|
|
elif isinstance(node, ast.Return):
|
|
a = assign_expr(scope, sym_table, node.value)
|
|
if a != None and a.fold().original > 1:
|
|
print(ast.unparse(node))
|
|
print(a)
|
|
assert False
|
|
|
|
|