mirror of https://github.com/m-labs/artiq.git
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