3"""Exact executable-AST helpers for HIL convergence structural checks."""
5from __future__
import annotations
10def same_statement(node: ast.stmt, source: str) -> bool:
11 """Compare executable AST rather than source tokens or comments."""
12 expected = ast.parse(source).body[0]
13 return ast.dump(node, include_attributes=
False) == ast.dump(expected, include_attributes=
False)
16def function(tree: ast.Module, name: str) -> ast.FunctionDef |
None:
17 """Return one uniquely named top-level function."""
19 node
for node
in tree.body
if isinstance(node, ast.FunctionDef)
and node.name == name
21 return matches[0]
if len(matches) == 1
else None
24def statement_index(function_node: ast.FunctionDef, source: str) -> int:
25 """Find one exact executable top-level statement in a function."""
27 index
for index, node
in enumerate(function_node.body)
if same_statement(node, source)
29 return matches[0]
if len(matches) == 1
else -1
32def assignment(function_node: ast.FunctionDef, name: str) -> ast.expr |
None:
33 """Return one exact top-level simple-assignment value."""
36 for node
in function_node.body
37 if isinstance(node, ast.Assign)
38 and len(node.targets) == 1
39 and isinstance(node.targets[0], ast.Name)
40 and node.targets[0].id == name
42 return matches[0]
if len(matches) == 1
else None
45def nested_assignment(function_node: ast.FunctionDef, name: str) -> ast.expr |
None:
46 """Return one uniquely named simple assignment anywhere in a function."""
48 for node
in ast.walk(function_node):
49 if not isinstance(node, ast.Assign)
or len(node.targets) != 1:
51 target = node.targets[0]
52 if isinstance(target, ast.Name)
and target.id == name:
53 matches.append(node.value)
54 return matches[0]
if len(matches) == 1
else None
57def return_strings(function_node: ast.FunctionDef |
None) -> set[str]:
58 """Return executable string literals from one unique return expression."""
59 if function_node
is None:
61 returns = [node.value
for node
in function_node.body
if isinstance(node, ast.Return)]
66 for node
in ast.walk(returns[0])
67 if isinstance(node, ast.Constant)
and isinstance(node.value, str)
71def module_assignment(tree: ast.Module, name: str) -> ast.expr |
None:
72 """Return one exact top-level module assignment value."""
76 if isinstance(node, ast.Assign)
77 and len(node.targets) == 1
78 and isinstance(node.targets[0], ast.Name)
79 and node.targets[0].id == name
81 return matches[0]
if len(matches) == 1
else None