forked from M-Labs/artiq
Remove leftover artiq/transforms/.
This commit is contained in:
parent
e5b58b50aa
commit
f5187eb140
|
@ -1,62 +0,0 @@
|
||||||
"""
|
|
||||||
This transform implements time management functions (delay_mu/now_mu/at_mu)
|
|
||||||
using an accumulator 'now' and simple replacement rules:
|
|
||||||
|
|
||||||
delay_mu(t) -> now += t
|
|
||||||
now_mu() -> now
|
|
||||||
at_mu(t) -> now = t
|
|
||||||
|
|
||||||
The function delay(), that uses seconds, must be lowered to delay_mu() before
|
|
||||||
invoking this transform.
|
|
||||||
The accumulator is initialized to an int64 value at the beginning of the
|
|
||||||
output function.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import ast
|
|
||||||
|
|
||||||
|
|
||||||
class _TimeLowerer(ast.NodeTransformer):
|
|
||||||
def visit_Call(self, node):
|
|
||||||
if node.func.id == "now_mu":
|
|
||||||
return ast.copy_location(ast.Name("now", ast.Load()), node)
|
|
||||||
else:
|
|
||||||
self.generic_visit(node)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_Expr(self, node):
|
|
||||||
r = node
|
|
||||||
if isinstance(node.value, ast.Call):
|
|
||||||
funcname = node.value.func.id
|
|
||||||
if funcname == "delay_mu":
|
|
||||||
r = ast.copy_location(
|
|
||||||
ast.AugAssign(target=ast.Name("now", ast.Store()),
|
|
||||||
op=ast.Add(),
|
|
||||||
value=node.value.args[0]),
|
|
||||||
node)
|
|
||||||
elif funcname == "at_mu":
|
|
||||||
r = ast.copy_location(
|
|
||||||
ast.Assign(targets=[ast.Name("now", ast.Store())],
|
|
||||||
value=node.value.args[0]),
|
|
||||||
node)
|
|
||||||
self.generic_visit(r)
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def lower_time(func_def):
|
|
||||||
_TimeLowerer().visit(func_def)
|
|
||||||
call_init = ast.Call(
|
|
||||||
func=ast.Name("syscall", ast.Load()),
|
|
||||||
args=[ast.Str("now_init")], keywords=[])
|
|
||||||
stmt_init = ast.Assign(targets=[ast.Name("now", ast.Store())],
|
|
||||||
value=call_init)
|
|
||||||
call_save = ast.Call(
|
|
||||||
func=ast.Name("syscall", ast.Load()),
|
|
||||||
args=[ast.Str("now_save"), ast.Name("now", ast.Load())], keywords=[])
|
|
||||||
stmt_save = ast.Expr(call_save)
|
|
||||||
func_def.body = [
|
|
||||||
stmt_init,
|
|
||||||
ast.Try(body=func_def.body,
|
|
||||||
handlers=[],
|
|
||||||
orelse=[],
|
|
||||||
finalbody=[stmt_save])
|
|
||||||
]
|
|
|
@ -1,109 +0,0 @@
|
||||||
"""
|
|
||||||
This transform turns calls to delay() that use non-integer time
|
|
||||||
expressed in seconds into calls to delay_mu() that use int64 time
|
|
||||||
expressed in multiples of ref_period.
|
|
||||||
|
|
||||||
It does so by inserting multiplication/division/rounding operations around
|
|
||||||
those calls.
|
|
||||||
|
|
||||||
The seconds_to_mu and mu_to_seconds core language functions are also
|
|
||||||
implemented here, as well as watchdog to syscall conversion.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import ast
|
|
||||||
|
|
||||||
from artiq.transforms.tools import value_to_ast
|
|
||||||
|
|
||||||
|
|
||||||
def _seconds_to_mu(ref_period, node):
|
|
||||||
divided = ast.copy_location(
|
|
||||||
ast.BinOp(left=node,
|
|
||||||
op=ast.Div(),
|
|
||||||
right=value_to_ast(ref_period)),
|
|
||||||
node)
|
|
||||||
return ast.copy_location(
|
|
||||||
ast.Call(func=ast.Name("round64", ast.Load()),
|
|
||||||
args=[divided], keywords=[]),
|
|
||||||
divided)
|
|
||||||
|
|
||||||
|
|
||||||
def _mu_to_seconds(ref_period, node):
|
|
||||||
return ast.copy_location(
|
|
||||||
ast.BinOp(left=node,
|
|
||||||
op=ast.Mult(),
|
|
||||||
right=value_to_ast(ref_period)),
|
|
||||||
node)
|
|
||||||
|
|
||||||
|
|
||||||
class _TimeQuantizer(ast.NodeTransformer):
|
|
||||||
def __init__(self, ref_period):
|
|
||||||
self.ref_period = ref_period
|
|
||||||
self.watchdog_id_counter = 0
|
|
||||||
|
|
||||||
def visit_Call(self, node):
|
|
||||||
funcname = node.func.id
|
|
||||||
if funcname == "delay":
|
|
||||||
node.func.id = "delay_mu"
|
|
||||||
if (isinstance(node.args[0], ast.Call)
|
|
||||||
and node.args[0].func.id == "mu_to_seconds"):
|
|
||||||
# optimize:
|
|
||||||
# delay(mu_to_seconds(x)) -> delay_mu(x)
|
|
||||||
node.args[0] = self.visit(node.args[0].args[0])
|
|
||||||
else:
|
|
||||||
node.args[0] = _seconds_to_mu(self.ref_period,
|
|
||||||
self.visit(node.args[0]))
|
|
||||||
return node
|
|
||||||
elif funcname == "seconds_to_mu":
|
|
||||||
return _seconds_to_mu(self.ref_period,
|
|
||||||
self.visit(node.args[0]))
|
|
||||||
elif funcname == "mu_to_seconds":
|
|
||||||
return _mu_to_seconds(self.ref_period,
|
|
||||||
self.visit(node.args[0]))
|
|
||||||
else:
|
|
||||||
self.generic_visit(node)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_With(self, node):
|
|
||||||
self.generic_visit(node)
|
|
||||||
if (isinstance(node.items[0].context_expr, ast.Call)
|
|
||||||
and node.items[0].context_expr.func.id == "watchdog"):
|
|
||||||
|
|
||||||
idname = "__watchdog_id_" + str(self.watchdog_id_counter)
|
|
||||||
self.watchdog_id_counter += 1
|
|
||||||
|
|
||||||
time = ast.BinOp(left=node.items[0].context_expr.args[0],
|
|
||||||
op=ast.Mult(),
|
|
||||||
right=ast.Num(1000))
|
|
||||||
time_int = ast.Call(
|
|
||||||
func=ast.Name("round", ast.Load()),
|
|
||||||
args=[time], keywords=[])
|
|
||||||
syscall_set = ast.Call(
|
|
||||||
func=ast.Name("syscall", ast.Load()),
|
|
||||||
args=[ast.Str("watchdog_set"), time_int], keywords=[])
|
|
||||||
stmt_set = ast.copy_location(
|
|
||||||
ast.Assign(targets=[ast.Name(idname, ast.Store())],
|
|
||||||
value=syscall_set),
|
|
||||||
node)
|
|
||||||
|
|
||||||
syscall_clear = ast.Call(
|
|
||||||
func=ast.Name("syscall", ast.Load()),
|
|
||||||
args=[ast.Str("watchdog_clear"),
|
|
||||||
ast.Name(idname, ast.Load())], keywords=[])
|
|
||||||
stmt_clear = ast.copy_location(ast.Expr(syscall_clear), node)
|
|
||||||
|
|
||||||
node.items[0] = ast.withitem(
|
|
||||||
context_expr=ast.Name(id="sequential",
|
|
||||||
ctx=ast.Load()),
|
|
||||||
optional_vars=None)
|
|
||||||
node.body = [
|
|
||||||
stmt_set,
|
|
||||||
ast.Try(body=node.body,
|
|
||||||
handlers=[],
|
|
||||||
orelse=[],
|
|
||||||
finalbody=[stmt_clear])
|
|
||||||
]
|
|
||||||
return node
|
|
||||||
|
|
||||||
|
|
||||||
def quantize_time(func_def, ref_period):
|
|
||||||
_TimeQuantizer(ref_period).visit(func_def)
|
|
|
@ -1,139 +0,0 @@
|
||||||
import ast
|
|
||||||
from fractions import Fraction
|
|
||||||
|
|
||||||
from artiq.language import core as core_language
|
|
||||||
from artiq.language import units
|
|
||||||
|
|
||||||
|
|
||||||
embeddable_funcs = (
|
|
||||||
core_language.delay_mu, core_language.at_mu, core_language.now_mu,
|
|
||||||
core_language.delay,
|
|
||||||
core_language.seconds_to_mu, core_language.mu_to_seconds,
|
|
||||||
core_language.syscall, core_language.watchdog,
|
|
||||||
range, bool, int, float, round, len,
|
|
||||||
core_language.int64, core_language.round64,
|
|
||||||
Fraction, core_language.EncodedException
|
|
||||||
)
|
|
||||||
embeddable_func_names = {func.__name__ for func in embeddable_funcs}
|
|
||||||
|
|
||||||
|
|
||||||
def is_embeddable(func):
|
|
||||||
for ef in embeddable_funcs:
|
|
||||||
if func is ef:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def eval_ast(expr, symdict=dict()):
|
|
||||||
if not isinstance(expr, ast.Expression):
|
|
||||||
expr = ast.copy_location(ast.Expression(expr), expr)
|
|
||||||
ast.fix_missing_locations(expr)
|
|
||||||
code = compile(expr, "<ast>", "eval")
|
|
||||||
return eval(code, symdict)
|
|
||||||
|
|
||||||
|
|
||||||
class NotASTRepresentable(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def value_to_ast(value):
|
|
||||||
if isinstance(value, core_language.int64): # must be before int
|
|
||||||
return ast.Call(
|
|
||||||
func=ast.Name("int64", ast.Load()),
|
|
||||||
args=[ast.Num(int(value))], keywords=[])
|
|
||||||
elif isinstance(value, bool) or value is None:
|
|
||||||
# must also be before int
|
|
||||||
# isinstance(True/False, int) == True
|
|
||||||
return ast.NameConstant(value)
|
|
||||||
elif isinstance(value, (int, float)):
|
|
||||||
return ast.Num(value)
|
|
||||||
elif isinstance(value, Fraction):
|
|
||||||
return ast.Call(
|
|
||||||
func=ast.Name("Fraction", ast.Load()),
|
|
||||||
args=[ast.Num(value.numerator), ast.Num(value.denominator)], keywords=[])
|
|
||||||
elif isinstance(value, str):
|
|
||||||
return ast.Str(value)
|
|
||||||
elif isinstance(value, list):
|
|
||||||
elts = [value_to_ast(elt) for elt in value]
|
|
||||||
return ast.List(elts, ast.Load())
|
|
||||||
else:
|
|
||||||
for kg in core_language.kernel_globals:
|
|
||||||
if value is getattr(core_language, kg):
|
|
||||||
return ast.Name(kg, ast.Load())
|
|
||||||
raise NotASTRepresentable(str(value))
|
|
||||||
|
|
||||||
|
|
||||||
class NotConstant(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def eval_constant(node):
|
|
||||||
if isinstance(node, ast.Num):
|
|
||||||
return node.n
|
|
||||||
elif isinstance(node, ast.Str):
|
|
||||||
return node.s
|
|
||||||
elif isinstance(node, ast.NameConstant):
|
|
||||||
return node.value
|
|
||||||
elif isinstance(node, ast.Call):
|
|
||||||
funcname = node.func.id
|
|
||||||
if funcname == "int64":
|
|
||||||
return core_language.int64(eval_constant(node.args[0]))
|
|
||||||
elif funcname == "Fraction":
|
|
||||||
numerator = eval_constant(node.args[0])
|
|
||||||
denominator = eval_constant(node.args[1])
|
|
||||||
return Fraction(numerator, denominator)
|
|
||||||
else:
|
|
||||||
raise NotConstant
|
|
||||||
else:
|
|
||||||
raise NotConstant
|
|
||||||
|
|
||||||
|
|
||||||
_replaceable_funcs = {
|
|
||||||
"bool", "int", "float", "round",
|
|
||||||
"int64", "round64", "Fraction",
|
|
||||||
"seconds_to_mu", "mu_to_seconds"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def _is_ref_transparent(dependencies, expr):
|
|
||||||
if isinstance(expr, (ast.NameConstant, ast.Num, ast.Str)):
|
|
||||||
return True
|
|
||||||
elif isinstance(expr, ast.Name):
|
|
||||||
dependencies.add(expr.id)
|
|
||||||
return True
|
|
||||||
elif isinstance(expr, ast.UnaryOp):
|
|
||||||
return _is_ref_transparent(dependencies, expr.operand)
|
|
||||||
elif isinstance(expr, ast.BinOp):
|
|
||||||
return (_is_ref_transparent(dependencies, expr.left)
|
|
||||||
and _is_ref_transparent(dependencies, expr.right))
|
|
||||||
elif isinstance(expr, ast.BoolOp):
|
|
||||||
return all(_is_ref_transparent(dependencies, v) for v in expr.values)
|
|
||||||
elif isinstance(expr, ast.Call):
|
|
||||||
return (expr.func.id in _replaceable_funcs and
|
|
||||||
all(_is_ref_transparent(dependencies, arg)
|
|
||||||
for arg in expr.args))
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def is_ref_transparent(expr):
|
|
||||||
dependencies = set()
|
|
||||||
if _is_ref_transparent(dependencies, expr):
|
|
||||||
return True, dependencies
|
|
||||||
else:
|
|
||||||
return False, None
|
|
||||||
|
|
||||||
|
|
||||||
class _NodeCounter(ast.NodeVisitor):
|
|
||||||
def __init__(self):
|
|
||||||
self.count = 0
|
|
||||||
|
|
||||||
def generic_visit(self, node):
|
|
||||||
self.count += 1
|
|
||||||
ast.NodeVisitor.generic_visit(self, node)
|
|
||||||
|
|
||||||
|
|
||||||
def count_all_nodes(node):
|
|
||||||
nc = _NodeCounter()
|
|
||||||
nc.visit(node)
|
|
||||||
return nc.count
|
|
|
@ -1,575 +0,0 @@
|
||||||
import sys
|
|
||||||
import ast
|
|
||||||
|
|
||||||
|
|
||||||
# Large float and imaginary literals get turned into infinities in the AST.
|
|
||||||
# We unparse those infinities to INFSTR.
|
|
||||||
INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1)
|
|
||||||
|
|
||||||
|
|
||||||
def _interleave(inter, f, seq):
|
|
||||||
"""Call f on each item in seq, calling inter() in between.
|
|
||||||
"""
|
|
||||||
seq = iter(seq)
|
|
||||||
try:
|
|
||||||
f(next(seq))
|
|
||||||
except StopIteration:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
for x in seq:
|
|
||||||
inter()
|
|
||||||
f(x)
|
|
||||||
|
|
||||||
|
|
||||||
class _Unparser:
|
|
||||||
"""Methods in this class recursively traverse an AST and
|
|
||||||
output source code for the abstract syntax; original formatting
|
|
||||||
is disregarded. """
|
|
||||||
|
|
||||||
def __init__(self, tree):
|
|
||||||
"""Print the source for tree to the "result" string."""
|
|
||||||
self.result = ""
|
|
||||||
self._indent = 0
|
|
||||||
self.dispatch(tree)
|
|
||||||
self.result += "\n"
|
|
||||||
|
|
||||||
def fill(self, text=""):
|
|
||||||
"Indent a piece of text, according to the current indentation level"
|
|
||||||
self.result += "\n"+" "*self._indent + text
|
|
||||||
|
|
||||||
def write(self, text):
|
|
||||||
"Append a piece of text to the current line."
|
|
||||||
self.result += text
|
|
||||||
|
|
||||||
def enter(self):
|
|
||||||
"Print ':', and increase the indentation."
|
|
||||||
self.write(":")
|
|
||||||
self._indent += 1
|
|
||||||
|
|
||||||
def leave(self):
|
|
||||||
"Decrease the indentation level."
|
|
||||||
self._indent -= 1
|
|
||||||
|
|
||||||
def dispatch(self, tree):
|
|
||||||
"Dispatcher function, dispatching tree type T to method _T."
|
|
||||||
if isinstance(tree, list):
|
|
||||||
for t in tree:
|
|
||||||
self.dispatch(t)
|
|
||||||
return
|
|
||||||
meth = getattr(self, "_"+tree.__class__.__name__)
|
|
||||||
meth(tree)
|
|
||||||
|
|
||||||
# Unparsing methods
|
|
||||||
#
|
|
||||||
# There should be one method per concrete grammar type
|
|
||||||
# Constructors should be grouped by sum type. Ideally,
|
|
||||||
# this would follow the order in the grammar, but
|
|
||||||
# currently doesn't.
|
|
||||||
|
|
||||||
def _Module(self, tree):
|
|
||||||
for stmt in tree.body:
|
|
||||||
self.dispatch(stmt)
|
|
||||||
|
|
||||||
# stmt
|
|
||||||
def _Expr(self, tree):
|
|
||||||
self.fill()
|
|
||||||
self.dispatch(tree.value)
|
|
||||||
|
|
||||||
def _Import(self, t):
|
|
||||||
self.fill("import ")
|
|
||||||
_interleave(lambda: self.write(", "), self.dispatch, t.names)
|
|
||||||
|
|
||||||
def _ImportFrom(self, t):
|
|
||||||
self.fill("from ")
|
|
||||||
self.write("." * t.level)
|
|
||||||
if t.module:
|
|
||||||
self.write(t.module)
|
|
||||||
self.write(" import ")
|
|
||||||
_interleave(lambda: self.write(", "), self.dispatch, t.names)
|
|
||||||
|
|
||||||
def _Assign(self, t):
|
|
||||||
self.fill()
|
|
||||||
for target in t.targets:
|
|
||||||
self.dispatch(target)
|
|
||||||
self.write(" = ")
|
|
||||||
self.dispatch(t.value)
|
|
||||||
|
|
||||||
def _AugAssign(self, t):
|
|
||||||
self.fill()
|
|
||||||
self.dispatch(t.target)
|
|
||||||
self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
|
|
||||||
self.dispatch(t.value)
|
|
||||||
|
|
||||||
def _Return(self, t):
|
|
||||||
self.fill("return")
|
|
||||||
if t.value:
|
|
||||||
self.write(" ")
|
|
||||||
self.dispatch(t.value)
|
|
||||||
|
|
||||||
def _Pass(self, t):
|
|
||||||
self.fill("pass")
|
|
||||||
|
|
||||||
def _Break(self, t):
|
|
||||||
self.fill("break")
|
|
||||||
|
|
||||||
def _Continue(self, t):
|
|
||||||
self.fill("continue")
|
|
||||||
|
|
||||||
def _Delete(self, t):
|
|
||||||
self.fill("del ")
|
|
||||||
_interleave(lambda: self.write(", "), self.dispatch, t.targets)
|
|
||||||
|
|
||||||
def _Assert(self, t):
|
|
||||||
self.fill("assert ")
|
|
||||||
self.dispatch(t.test)
|
|
||||||
if t.msg:
|
|
||||||
self.write(", ")
|
|
||||||
self.dispatch(t.msg)
|
|
||||||
|
|
||||||
def _Global(self, t):
|
|
||||||
self.fill("global ")
|
|
||||||
_interleave(lambda: self.write(", "), self.write, t.names)
|
|
||||||
|
|
||||||
def _Nonlocal(self, t):
|
|
||||||
self.fill("nonlocal ")
|
|
||||||
_interleave(lambda: self.write(", "), self.write, t.names)
|
|
||||||
|
|
||||||
def _Yield(self, t):
|
|
||||||
self.write("(")
|
|
||||||
self.write("yield")
|
|
||||||
if t.value:
|
|
||||||
self.write(" ")
|
|
||||||
self.dispatch(t.value)
|
|
||||||
self.write(")")
|
|
||||||
|
|
||||||
def _YieldFrom(self, t):
|
|
||||||
self.write("(")
|
|
||||||
self.write("yield from")
|
|
||||||
if t.value:
|
|
||||||
self.write(" ")
|
|
||||||
self.dispatch(t.value)
|
|
||||||
self.write(")")
|
|
||||||
|
|
||||||
def _Raise(self, t):
|
|
||||||
self.fill("raise")
|
|
||||||
if not t.exc:
|
|
||||||
assert not t.cause
|
|
||||||
return
|
|
||||||
self.write(" ")
|
|
||||||
self.dispatch(t.exc)
|
|
||||||
if t.cause:
|
|
||||||
self.write(" from ")
|
|
||||||
self.dispatch(t.cause)
|
|
||||||
|
|
||||||
def _Try(self, t):
|
|
||||||
self.fill("try")
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.body)
|
|
||||||
self.leave()
|
|
||||||
for ex in t.handlers:
|
|
||||||
self.dispatch(ex)
|
|
||||||
if t.orelse:
|
|
||||||
self.fill("else")
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.orelse)
|
|
||||||
self.leave()
|
|
||||||
if t.finalbody:
|
|
||||||
self.fill("finally")
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.finalbody)
|
|
||||||
self.leave()
|
|
||||||
|
|
||||||
def _ExceptHandler(self, t):
|
|
||||||
self.fill("except")
|
|
||||||
if t.type:
|
|
||||||
self.write(" ")
|
|
||||||
self.dispatch(t.type)
|
|
||||||
if t.name:
|
|
||||||
self.write(" as ")
|
|
||||||
self.write(t.name)
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.body)
|
|
||||||
self.leave()
|
|
||||||
|
|
||||||
def _ClassDef(self, t):
|
|
||||||
self.write("\n")
|
|
||||||
for deco in t.decorator_list:
|
|
||||||
self.fill("@")
|
|
||||||
self.dispatch(deco)
|
|
||||||
self.fill("class "+t.name)
|
|
||||||
self.write("(")
|
|
||||||
comma = False
|
|
||||||
for e in t.bases:
|
|
||||||
if comma:
|
|
||||||
self.write(", ")
|
|
||||||
else:
|
|
||||||
comma = True
|
|
||||||
self.dispatch(e)
|
|
||||||
for e in t.keywords:
|
|
||||||
if comma:
|
|
||||||
self.write(", ")
|
|
||||||
else:
|
|
||||||
comma = True
|
|
||||||
self.dispatch(e)
|
|
||||||
self.write(")")
|
|
||||||
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.body)
|
|
||||||
self.leave()
|
|
||||||
|
|
||||||
def _FunctionDef(self, t):
|
|
||||||
self.write("\n")
|
|
||||||
for deco in t.decorator_list:
|
|
||||||
self.fill("@")
|
|
||||||
self.dispatch(deco)
|
|
||||||
self.fill("def "+t.name + "(")
|
|
||||||
self.dispatch(t.args)
|
|
||||||
self.write(")")
|
|
||||||
if t.returns:
|
|
||||||
self.write(" -> ")
|
|
||||||
self.dispatch(t.returns)
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.body)
|
|
||||||
self.leave()
|
|
||||||
|
|
||||||
def _For(self, t):
|
|
||||||
self.fill("for ")
|
|
||||||
self.dispatch(t.target)
|
|
||||||
self.write(" in ")
|
|
||||||
self.dispatch(t.iter)
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.body)
|
|
||||||
self.leave()
|
|
||||||
if t.orelse:
|
|
||||||
self.fill("else")
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.orelse)
|
|
||||||
self.leave()
|
|
||||||
|
|
||||||
def _If(self, t):
|
|
||||||
self.fill("if ")
|
|
||||||
self.dispatch(t.test)
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.body)
|
|
||||||
self.leave()
|
|
||||||
# collapse nested ifs into equivalent elifs.
|
|
||||||
while (t.orelse and len(t.orelse) == 1 and
|
|
||||||
isinstance(t.orelse[0], ast.If)):
|
|
||||||
t = t.orelse[0]
|
|
||||||
self.fill("elif ")
|
|
||||||
self.dispatch(t.test)
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.body)
|
|
||||||
self.leave()
|
|
||||||
# final else
|
|
||||||
if t.orelse:
|
|
||||||
self.fill("else")
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.orelse)
|
|
||||||
self.leave()
|
|
||||||
|
|
||||||
def _While(self, t):
|
|
||||||
self.fill("while ")
|
|
||||||
self.dispatch(t.test)
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.body)
|
|
||||||
self.leave()
|
|
||||||
if t.orelse:
|
|
||||||
self.fill("else")
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.orelse)
|
|
||||||
self.leave()
|
|
||||||
|
|
||||||
def _With(self, t):
|
|
||||||
self.fill("with ")
|
|
||||||
_interleave(lambda: self.write(", "), self.dispatch, t.items)
|
|
||||||
self.enter()
|
|
||||||
self.dispatch(t.body)
|
|
||||||
self.leave()
|
|
||||||
|
|
||||||
# expr
|
|
||||||
def _Bytes(self, t):
|
|
||||||
self.write(repr(t.s))
|
|
||||||
|
|
||||||
def _Str(self, tree):
|
|
||||||
self.write(repr(tree.s))
|
|
||||||
|
|
||||||
def _Name(self, t):
|
|
||||||
self.write(t.id)
|
|
||||||
|
|
||||||
def _NameConstant(self, t):
|
|
||||||
self.write(repr(t.value))
|
|
||||||
|
|
||||||
def _Num(self, t):
|
|
||||||
# Substitute overflowing decimal literal for AST infinities.
|
|
||||||
self.write(repr(t.n).replace("inf", INFSTR))
|
|
||||||
|
|
||||||
def _List(self, t):
|
|
||||||
self.write("[")
|
|
||||||
_interleave(lambda: self.write(", "), self.dispatch, t.elts)
|
|
||||||
self.write("]")
|
|
||||||
|
|
||||||
def _ListComp(self, t):
|
|
||||||
self.write("[")
|
|
||||||
self.dispatch(t.elt)
|
|
||||||
for gen in t.generators:
|
|
||||||
self.dispatch(gen)
|
|
||||||
self.write("]")
|
|
||||||
|
|
||||||
def _GeneratorExp(self, t):
|
|
||||||
self.write("(")
|
|
||||||
self.dispatch(t.elt)
|
|
||||||
for gen in t.generators:
|
|
||||||
self.dispatch(gen)
|
|
||||||
self.write(")")
|
|
||||||
|
|
||||||
def _SetComp(self, t):
|
|
||||||
self.write("{")
|
|
||||||
self.dispatch(t.elt)
|
|
||||||
for gen in t.generators:
|
|
||||||
self.dispatch(gen)
|
|
||||||
self.write("}")
|
|
||||||
|
|
||||||
def _DictComp(self, t):
|
|
||||||
self.write("{")
|
|
||||||
self.dispatch(t.key)
|
|
||||||
self.write(": ")
|
|
||||||
self.dispatch(t.value)
|
|
||||||
for gen in t.generators:
|
|
||||||
self.dispatch(gen)
|
|
||||||
self.write("}")
|
|
||||||
|
|
||||||
def _comprehension(self, t):
|
|
||||||
self.write(" for ")
|
|
||||||
self.dispatch(t.target)
|
|
||||||
self.write(" in ")
|
|
||||||
self.dispatch(t.iter)
|
|
||||||
for if_clause in t.ifs:
|
|
||||||
self.write(" if ")
|
|
||||||
self.dispatch(if_clause)
|
|
||||||
|
|
||||||
def _IfExp(self, t):
|
|
||||||
self.write("(")
|
|
||||||
self.dispatch(t.body)
|
|
||||||
self.write(" if ")
|
|
||||||
self.dispatch(t.test)
|
|
||||||
self.write(" else ")
|
|
||||||
self.dispatch(t.orelse)
|
|
||||||
self.write(")")
|
|
||||||
|
|
||||||
def _Set(self, t):
|
|
||||||
assert(t.elts) # should be at least one element
|
|
||||||
self.write("{")
|
|
||||||
_interleave(lambda: self.write(", "), self.dispatch, t.elts)
|
|
||||||
self.write("}")
|
|
||||||
|
|
||||||
def _Dict(self, t):
|
|
||||||
self.write("{")
|
|
||||||
|
|
||||||
def write_pair(pair):
|
|
||||||
(k, v) = pair
|
|
||||||
self.dispatch(k)
|
|
||||||
self.write(": ")
|
|
||||||
self.dispatch(v)
|
|
||||||
_interleave(lambda: self.write(", "), write_pair,
|
|
||||||
zip(t.keys, t.values))
|
|
||||||
self.write("}")
|
|
||||||
|
|
||||||
def _Tuple(self, t):
|
|
||||||
self.write("(")
|
|
||||||
if len(t.elts) == 1:
|
|
||||||
(elt,) = t.elts
|
|
||||||
self.dispatch(elt)
|
|
||||||
self.write(",")
|
|
||||||
else:
|
|
||||||
_interleave(lambda: self.write(", "), self.dispatch, t.elts)
|
|
||||||
self.write(")")
|
|
||||||
|
|
||||||
unop = {"Invert": "~", "Not": "not", "UAdd": "+", "USub": "-"}
|
|
||||||
|
|
||||||
def _UnaryOp(self, t):
|
|
||||||
self.write("(")
|
|
||||||
self.write(self.unop[t.op.__class__.__name__])
|
|
||||||
self.write(" ")
|
|
||||||
self.dispatch(t.operand)
|
|
||||||
self.write(")")
|
|
||||||
|
|
||||||
binop = {"Add": "+", "Sub": "-", "Mult": "*", "Div": "/", "Mod": "%",
|
|
||||||
"LShift": "<<", "RShift": ">>",
|
|
||||||
"BitOr": "|", "BitXor": "^", "BitAnd": "&",
|
|
||||||
"FloorDiv": "//", "Pow": "**"}
|
|
||||||
|
|
||||||
def _BinOp(self, t):
|
|
||||||
self.write("(")
|
|
||||||
self.dispatch(t.left)
|
|
||||||
self.write(" " + self.binop[t.op.__class__.__name__] + " ")
|
|
||||||
self.dispatch(t.right)
|
|
||||||
self.write(")")
|
|
||||||
|
|
||||||
cmpops = {"Eq": "==", "NotEq": "!=",
|
|
||||||
"Lt": "<", "LtE": "<=", "Gt": ">", "GtE": ">=",
|
|
||||||
"Is": "is", "IsNot": "is not", "In": "in", "NotIn": "not in"}
|
|
||||||
|
|
||||||
def _Compare(self, t):
|
|
||||||
self.write("(")
|
|
||||||
self.dispatch(t.left)
|
|
||||||
for o, e in zip(t.ops, t.comparators):
|
|
||||||
self.write(" " + self.cmpops[o.__class__.__name__] + " ")
|
|
||||||
self.dispatch(e)
|
|
||||||
self.write(")")
|
|
||||||
|
|
||||||
boolops = {ast.And: "and", ast.Or: "or"}
|
|
||||||
|
|
||||||
def _BoolOp(self, t):
|
|
||||||
self.write("(")
|
|
||||||
s = " %s " % self.boolops[t.op.__class__]
|
|
||||||
_interleave(lambda: self.write(s), self.dispatch, t.values)
|
|
||||||
self.write(")")
|
|
||||||
|
|
||||||
def _Attribute(self, t):
|
|
||||||
self.dispatch(t.value)
|
|
||||||
# Special case: 3.__abs__() is a syntax error, so if t.value
|
|
||||||
# is an integer literal then we need to either parenthesize
|
|
||||||
# it or add an extra space to get 3 .__abs__().
|
|
||||||
if isinstance(t.value, ast.Num) and isinstance(t.value.n, int):
|
|
||||||
self.write(" ")
|
|
||||||
self.write(".")
|
|
||||||
self.write(t.attr)
|
|
||||||
|
|
||||||
def _Call(self, t):
|
|
||||||
self.dispatch(t.func)
|
|
||||||
self.write("(")
|
|
||||||
comma = False
|
|
||||||
for e in t.args:
|
|
||||||
if comma:
|
|
||||||
self.write(", ")
|
|
||||||
else:
|
|
||||||
comma = True
|
|
||||||
self.dispatch(e)
|
|
||||||
for e in t.keywords:
|
|
||||||
if comma:
|
|
||||||
self.write(", ")
|
|
||||||
else:
|
|
||||||
comma = True
|
|
||||||
self.dispatch(e)
|
|
||||||
self.write(")")
|
|
||||||
|
|
||||||
def _Subscript(self, t):
|
|
||||||
self.dispatch(t.value)
|
|
||||||
self.write("[")
|
|
||||||
self.dispatch(t.slice)
|
|
||||||
self.write("]")
|
|
||||||
|
|
||||||
def _Starred(self, t):
|
|
||||||
self.write("*")
|
|
||||||
self.dispatch(t.value)
|
|
||||||
|
|
||||||
# slice
|
|
||||||
def _Ellipsis(self, t):
|
|
||||||
self.write("...")
|
|
||||||
|
|
||||||
def _Index(self, t):
|
|
||||||
self.dispatch(t.value)
|
|
||||||
|
|
||||||
def _Slice(self, t):
|
|
||||||
if t.lower:
|
|
||||||
self.dispatch(t.lower)
|
|
||||||
self.write(":")
|
|
||||||
if t.upper:
|
|
||||||
self.dispatch(t.upper)
|
|
||||||
if t.step:
|
|
||||||
self.write(":")
|
|
||||||
self.dispatch(t.step)
|
|
||||||
|
|
||||||
def _ExtSlice(self, t):
|
|
||||||
_interleave(lambda: self.write(', '), self.dispatch, t.dims)
|
|
||||||
|
|
||||||
# argument
|
|
||||||
def _arg(self, t):
|
|
||||||
self.write(t.arg)
|
|
||||||
if t.annotation:
|
|
||||||
self.write(": ")
|
|
||||||
self.dispatch(t.annotation)
|
|
||||||
|
|
||||||
# others
|
|
||||||
def _arguments(self, t):
|
|
||||||
first = True
|
|
||||||
# normal arguments
|
|
||||||
defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults
|
|
||||||
for a, d in zip(t.args, defaults):
|
|
||||||
if first:
|
|
||||||
first = False
|
|
||||||
else:
|
|
||||||
self.write(", ")
|
|
||||||
self.dispatch(a)
|
|
||||||
if d:
|
|
||||||
self.write("=")
|
|
||||||
self.dispatch(d)
|
|
||||||
|
|
||||||
# varargs, or bare '*' if no varargs but keyword-only arguments present
|
|
||||||
if t.vararg or t.kwonlyargs:
|
|
||||||
if first:
|
|
||||||
first = False
|
|
||||||
else:
|
|
||||||
self.write(", ")
|
|
||||||
self.write("*")
|
|
||||||
if t.vararg:
|
|
||||||
self.write(t.vararg.arg)
|
|
||||||
if t.vararg.annotation:
|
|
||||||
self.write(": ")
|
|
||||||
self.dispatch(t.vararg.annotation)
|
|
||||||
|
|
||||||
# keyword-only arguments
|
|
||||||
if t.kwonlyargs:
|
|
||||||
for a, d in zip(t.kwonlyargs, t.kw_defaults):
|
|
||||||
if first:
|
|
||||||
first = False
|
|
||||||
else:
|
|
||||||
self.write(", ")
|
|
||||||
self.dispatch(a),
|
|
||||||
if d:
|
|
||||||
self.write("=")
|
|
||||||
self.dispatch(d)
|
|
||||||
|
|
||||||
# kwargs
|
|
||||||
if t.kwarg:
|
|
||||||
if first:
|
|
||||||
first = False
|
|
||||||
else:
|
|
||||||
self.write(", ")
|
|
||||||
self.write("**"+t.kwarg.arg)
|
|
||||||
if t.kwarg.annotation:
|
|
||||||
self.write(": ")
|
|
||||||
self.dispatch(t.kwarg.annotation)
|
|
||||||
|
|
||||||
def _keyword(self, t):
|
|
||||||
if t.arg is None:
|
|
||||||
self.write("**")
|
|
||||||
else:
|
|
||||||
self.write(t.arg)
|
|
||||||
self.write("=")
|
|
||||||
self.dispatch(t.value)
|
|
||||||
|
|
||||||
def _Lambda(self, t):
|
|
||||||
self.write("(")
|
|
||||||
self.write("lambda ")
|
|
||||||
self.dispatch(t.args)
|
|
||||||
self.write(": ")
|
|
||||||
self.dispatch(t.body)
|
|
||||||
self.write(")")
|
|
||||||
|
|
||||||
def _alias(self, t):
|
|
||||||
self.write(t.name)
|
|
||||||
if t.asname:
|
|
||||||
self.write(" as "+t.asname)
|
|
||||||
|
|
||||||
def _withitem(self, t):
|
|
||||||
self.dispatch(t.context_expr)
|
|
||||||
if t.optional_vars:
|
|
||||||
self.write(" as ")
|
|
||||||
self.dispatch(t.optional_vars)
|
|
||||||
|
|
||||||
|
|
||||||
def unparse(tree):
|
|
||||||
unparser = _Unparser(tree)
|
|
||||||
return unparser.result
|
|
Loading…
Reference in New Issue