正经说起来,一个标准的“现代”解释器(编译器)应该是介事儿的:
把py源码解析成分析树 (Parser/pgen.c)
把分析树转化成抽象语法树AST(Abstract Syntax Tree) (Python/ast.c)
把AST转化成CFG(Control Flow Graph) (Python/compile.c)
基于Control Flow Graph优化生成bytecode (Python/compile.c)
抽象语法树 (AST)
抽象语法树(AST)是程序结构的一种高抽象层次的表达,有了它我们并再不需要源代码的存在了。它可以认为是源代码等价的一种抽象表达。CPython采用Zephyr抽象语法定义语言(ASDL)来描述AST。
import ast
def comp_to_expl(tree):
if hasattr(tree, 'body'):
i = 0
while i < len(tree.body):
if isinstance(a:=tree.body[i], ast.Assign) and isinstance(a.value, ast.ListComp):
tree.body = tree.body[:i] + \
[ast.Assign(
targets=[ast.Name(id = a.targets[0].id)], value = ast.List(elts = []),
lineno = a.lineno
)] + \
[ast.For(
target = a.value.generators[0].target,
iter = a.value.generators[0].iter,
body = [ast.Expr(
value = ast.Call(
func = ast.Attribute(value = ast.Name(id = a.targets[0].id), attr = 'append', ctx = ast.Load()),
args = [a.value.elt],
keywords = []
))],
lineno = a.lineno+1,
orelse = [],
)] + \
tree.body[i+1:]
i += 1
i += 1
for i in getattr(tree, '_fields', []):
if isinstance(v:=getattr(tree, i, None), list):
for i in v:
comp_to_expl(i)
elif isinstance(v, ast.AST):
comp_to_expl(v)
synt = ast.parse('a=[x for x in [1,2,3]]')
comp_to_expl(synt)