6
6
import builtins
7
7
from copy import deepcopy
8
8
9
- from artiq .transforms .tools import eval_ast , value_to_ast
9
+ from artiq .transforms .tools import eval_ast , value_to_ast , NotASTRepresentable
10
10
from artiq .language import core as core_language
11
11
from artiq .language import units
12
12
@@ -45,7 +45,7 @@ def __init__(self):
45
45
self .kernel_attr_init = []
46
46
47
47
# (id(obj), func_name, ref_name) or (id(obj), kernel_attr_name)
48
- # -> _UserVariable(name) / ast / constant_object
48
+ # -> _UserVariable(name) / complex object
49
49
self ._to_inlined = dict ()
50
50
# inlined_name -> use_count
51
51
self ._use_count = dict ()
@@ -57,10 +57,15 @@ def __init__(self):
57
57
"range" ):
58
58
self ._use_count [name ] = 1
59
59
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
64
69
65
70
def new_name (self , base_name ):
66
71
if base_name [- 1 ].isdigit ():
@@ -112,7 +117,7 @@ def resolve_attr(self, value, attr):
112
117
def resolve_constant (self , obj , func_name , node ):
113
118
if isinstance (node , ast .Name ):
114
119
c = self .resolve_name (obj , func_name , node .id , False )
115
- if isinstance (c , ( _UserVariable , ast . AST ) ):
120
+ if isinstance (c , _UserVariable ):
116
121
raise ValueError ("Not a constant" )
117
122
return c
118
123
elif isinstance (node , ast .Attribute ):
@@ -192,18 +197,10 @@ def visit_Name(self, node):
192
197
ival = self .rm .resolve_name (self .obj , self .func_name , node .id , store )
193
198
if isinstance (ival , _UserVariable ):
194
199
newnode = ast .Name (ival .name , node .ctx )
195
- elif isinstance (ival , ast .AST ):
196
- assert (not store )
197
- newnode = deepcopy (ival )
198
200
else :
199
201
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 )
207
204
return ast .copy_location (newnode , node )
208
205
209
206
def _resolve_attribute (self , node ):
@@ -325,40 +322,23 @@ def visit_ExceptHandler(self, node):
325
322
return node
326
323
327
324
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
-
349
325
def _initialize_function_params (func_def , k_args , k_kwargs , rm ):
350
326
obj = k_args [0 ]
351
327
func_name = func_def .name
352
328
param_init = []
353
- rop = _list_read_only_params (func_def )
354
329
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 )
358
339
else :
359
- uservar = rm .resolve_name (obj , func_name , arg_name , True )
340
+ uservar = rm .resolve_name (obj , func_name , arg_ast . arg , True )
360
341
target = ast .Name (uservar .name , ast .Store ())
361
- value = value_to_ast (arg_value )
362
342
param_init .append (ast .Assign (targets = [target ], value = value ))
363
343
return param_init
364
344
0 commit comments