Skip to content

Commit 97329b7

Browse files
committedOct 30, 2014
transforms/inline: offload some work to remove_inter_assigns/remove_dead_code
1 parent 1c0c0b6 commit 97329b7

File tree

2 files changed

+29
-45
lines changed

2 files changed

+29
-45
lines changed
 

‎artiq/transforms/inline.py

+24-44
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import builtins
77
from copy import deepcopy
88

9-
from artiq.transforms.tools import eval_ast, value_to_ast
9+
from artiq.transforms.tools import eval_ast, value_to_ast, NotASTRepresentable
1010
from artiq.language import core as core_language
1111
from artiq.language import units
1212

@@ -45,7 +45,7 @@ def __init__(self):
4545
self.kernel_attr_init = []
4646

4747
# (id(obj), func_name, ref_name) or (id(obj), kernel_attr_name)
48-
# -> _UserVariable(name) / ast / constant_object
48+
# -> _UserVariable(name) / complex object
4949
self._to_inlined = dict()
5050
# inlined_name -> use_count
5151
self._use_count = dict()
@@ -57,10 +57,15 @@ def __init__(self):
5757
"range"):
5858
self._use_count[name] = 1
5959

60-
# node_or_value can be a AST node, used to inline function parameter values
61-
# that can be simplified later through constant folding.
62-
def register_replace(self, obj, func_name, ref_name, node_or_value):
63-
self._to_inlined[(id(obj), func_name, ref_name)] = node_or_value
60+
# Complex objects in the namespace of functions can be used in two ways:
61+
# 1. Calling a method on them (which gets inlined or RPCd)
62+
# 2. Getting or setting attributes (which are turned into local variables)
63+
# They are needed to implement "self", which is the only supported use
64+
# case.
65+
def register_complex_object(self, obj, func_name, ref_name,
66+
complex_object):
67+
assert(not isinstance(complex_object, ast.AST))
68+
self._to_inlined[(id(obj), func_name, ref_name)] = complex_object
6469

6570
def new_name(self, base_name):
6671
if base_name[-1].isdigit():
@@ -112,7 +117,7 @@ def resolve_attr(self, value, attr):
112117
def resolve_constant(self, obj, func_name, node):
113118
if isinstance(node, ast.Name):
114119
c = self.resolve_name(obj, func_name, node.id, False)
115-
if isinstance(c, (_UserVariable, ast.AST)):
120+
if isinstance(c, _UserVariable):
116121
raise ValueError("Not a constant")
117122
return c
118123
elif isinstance(node, ast.Attribute):
@@ -192,18 +197,10 @@ def visit_Name(self, node):
192197
ival = self.rm.resolve_name(self.obj, self.func_name, node.id, store)
193198
if isinstance(ival, _UserVariable):
194199
newnode = ast.Name(ival.name, node.ctx)
195-
elif isinstance(ival, ast.AST):
196-
assert(not store)
197-
newnode = deepcopy(ival)
198200
else:
199201
if store:
200-
raise NotImplementedError(
201-
"Cannot turn object into user variable")
202-
else:
203-
newnode = value_to_ast(ival)
204-
if newnode is None:
205-
raise NotImplementedError(
206-
"Cannot represent inlined value")
202+
raise NotImplementedError("Cannot assign to this object")
203+
newnode = value_to_ast(ival)
207204
return ast.copy_location(newnode, node)
208205

209206
def _resolve_attribute(self, node):
@@ -325,40 +322,23 @@ def visit_ExceptHandler(self, node):
325322
return node
326323

327324

328-
class _ListReadOnlyParams(ast.NodeVisitor):
329-
def visit_FunctionDef(self, node):
330-
if hasattr(self, "read_only_params"):
331-
raise ValueError("More than one function definition")
332-
self.read_only_params = {arg.arg for arg in node.args.args}
333-
self.generic_visit(node)
334-
335-
def visit_Name(self, node):
336-
if isinstance(node.ctx, ast.Store):
337-
try:
338-
self.read_only_params.remove(node.id)
339-
except KeyError:
340-
pass
341-
342-
343-
def _list_read_only_params(func_def):
344-
lrp = _ListReadOnlyParams()
345-
lrp.visit(func_def)
346-
return lrp.read_only_params
347-
348-
349325
def _initialize_function_params(func_def, k_args, k_kwargs, rm):
350326
obj = k_args[0]
351327
func_name = func_def.name
352328
param_init = []
353-
rop = _list_read_only_params(func_def)
354329
for arg_ast, arg_value in zip(func_def.args.args, k_args):
355-
arg_name = arg_ast.arg
356-
if arg_name in rop:
357-
rm.register_replace(obj, func_name, arg_name, arg_value)
330+
if isinstance(arg_value, ast.AST):
331+
value = arg_value
332+
else:
333+
try:
334+
value = value_to_ast(arg_value)
335+
except NotASTRepresentable:
336+
value = None
337+
if value is None:
338+
rm.register_complex_object(obj, func_name, arg_ast.arg, arg_value)
358339
else:
359-
uservar = rm.resolve_name(obj, func_name, arg_name, True)
340+
uservar = rm.resolve_name(obj, func_name, arg_ast.arg, True)
360341
target = ast.Name(uservar.name, ast.Store())
361-
value = value_to_ast(arg_value)
362342
param_init.append(ast.Assign(targets=[target], value=value))
363343
return param_init
364344

‎artiq/transforms/tools.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ def eval_ast(expr, symdict=dict()):
1313
return eval(code, symdict)
1414

1515

16+
class NotASTRepresentable(Exception):
17+
pass
18+
19+
1620
def value_to_ast(value):
1721
if isinstance(value, core_language.int64): # must be before int
1822
return ast.Call(
@@ -41,7 +45,7 @@ def value_to_ast(value):
4145
func=ast.Name("Quantity", ast.Load()),
4246
args=[value_to_ast(value.amount), ast.Str(value.unit)],
4347
keywords=[], starargs=None, kwargs=None)
44-
return None
48+
raise NotASTRepresentable(str(value))
4549

4650

4751
class NotConstant(Exception):

0 commit comments

Comments
 (0)
Please sign in to comment.