forked from M-Labs/artiq
transforms/inline: refactor and fix _ReferenceManager.inline
This commit is contained in:
parent
dc9515fc62
commit
123ddb26a1
|
@ -3,6 +3,7 @@ from fractions import Fraction
|
||||||
import inspect
|
import inspect
|
||||||
import textwrap
|
import textwrap
|
||||||
import ast
|
import ast
|
||||||
|
import builtins
|
||||||
|
|
||||||
from artiq.transforms.tools import eval_ast, value_to_ast
|
from artiq.transforms.tools import eval_ast, value_to_ast
|
||||||
from artiq.language import core as core_language
|
from artiq.language import core as core_language
|
||||||
|
@ -20,9 +21,8 @@ def _is_in_attr_list(obj, attr, al):
|
||||||
|
|
||||||
class _ReferenceManager:
|
class _ReferenceManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# (id(obj), funcname, local)
|
# (id(obj), func_name, local_name) or (id(obj), kernel_attr_name)
|
||||||
# -> _UserVariable(name) / ast / constant_object
|
# -> _UserVariable(name) / ast / constant_object
|
||||||
# local is None for kernel attributes
|
|
||||||
self.to_inlined = dict()
|
self.to_inlined = dict()
|
||||||
# inlined_name -> use_count
|
# inlined_name -> use_count
|
||||||
self.use_count = dict()
|
self.use_count = dict()
|
||||||
|
@ -48,33 +48,25 @@ class _ReferenceManager:
|
||||||
self.use_count[base_name] = 1
|
self.use_count[base_name] = 1
|
||||||
return base_name
|
return base_name
|
||||||
|
|
||||||
def get(self, obj, funcname, ref):
|
def get(self, obj, func_name, ref):
|
||||||
store = isinstance(ref.ctx, ast.Store)
|
|
||||||
|
|
||||||
if isinstance(ref, ast.Name):
|
if isinstance(ref, ast.Name):
|
||||||
key = (id(obj), funcname, ref.id)
|
key = (id(obj), func_name, ref.id)
|
||||||
try:
|
try:
|
||||||
return self.to_inlined[key]
|
return self.to_inlined[key]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
if store:
|
if isinstance(ref.ctx, ast.Store):
|
||||||
ival = _UserVariable(self.new_name(ref.id))
|
ival = _UserVariable(self.new_name(ref.id))
|
||||||
self.to_inlined[key] = ival
|
self.to_inlined[key] = ival
|
||||||
return ival
|
return ival
|
||||||
|
|
||||||
if isinstance(ref, ast.Attribute) and isinstance(ref.value, ast.Name):
|
|
||||||
try:
|
|
||||||
value = self.to_inlined[(id(obj), funcname, ref.value.id)]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
if _is_in_attr_list(value, ref.attr, "kernel_attr_ro"):
|
try:
|
||||||
if store:
|
return inspect.getmodule(obj).__dict__[ref.id]
|
||||||
raise TypeError(
|
except KeyError:
|
||||||
"Attempted to assign to read-only"
|
return getattr(builtins, ref.id)
|
||||||
" kernel attribute")
|
elif isinstance(ref, ast.Attribute):
|
||||||
return getattr(value, ref.attr)
|
target = self.get(obj, func_name, ref.value)
|
||||||
if _is_in_attr_list(value, ref.attr, "kernel_attr"):
|
if _is_in_attr_list(target, ref.attr, "kernel_attr"):
|
||||||
key = (id(value), ref.attr, None)
|
key = (id(target), ref.attr)
|
||||||
try:
|
try:
|
||||||
ival = self.to_inlined[key]
|
ival = self.to_inlined[key]
|
||||||
assert(isinstance(ival, _UserVariable))
|
assert(isinstance(ival, _UserVariable))
|
||||||
|
@ -82,7 +74,7 @@ class _ReferenceManager:
|
||||||
iname = self.new_name(ref.attr)
|
iname = self.new_name(ref.attr)
|
||||||
ival = _UserVariable(iname)
|
ival = _UserVariable(iname)
|
||||||
self.to_inlined[key] = ival
|
self.to_inlined[key] = ival
|
||||||
a = value_to_ast(getattr(value, ref.attr))
|
a = value_to_ast(getattr(target, ref.attr))
|
||||||
if a is None:
|
if a is None:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Cannot represent initial value"
|
"Cannot represent initial value"
|
||||||
|
@ -90,24 +82,10 @@ class _ReferenceManager:
|
||||||
self.kernel_attr_init.append(ast.Assign(
|
self.kernel_attr_init.append(ast.Assign(
|
||||||
[ast.Name(iname, ast.Store())], a))
|
[ast.Name(iname, ast.Store())], a))
|
||||||
return ival
|
return ival
|
||||||
|
|
||||||
if not store:
|
|
||||||
evd = self.get_constants(obj, funcname)
|
|
||||||
evd.update(inspect.getmodule(obj).__dict__)
|
|
||||||
return eval_ast(ref, evd)
|
|
||||||
else:
|
else:
|
||||||
raise KeyError(ast.dump(ref))
|
return getattr(target, ref.attr)
|
||||||
|
else:
|
||||||
def set(self, obj, funcname, name, value):
|
raise NotImplementedError
|
||||||
self.to_inlined[(id(obj), funcname, name)] = value
|
|
||||||
|
|
||||||
def get_constants(self, r_obj, r_funcname):
|
|
||||||
return {
|
|
||||||
local: v for (objid, funcname, local), v
|
|
||||||
in self.to_inlined.items()
|
|
||||||
if objid == id(r_obj)
|
|
||||||
and funcname == r_funcname
|
|
||||||
and not isinstance(v, (_UserVariable, ast.AST))}
|
|
||||||
|
|
||||||
|
|
||||||
_embeddable_calls = {
|
_embeddable_calls = {
|
||||||
|
@ -266,7 +244,7 @@ def _initialize_function_params(func_def, k_args, k_kwargs, rm):
|
||||||
for arg_ast, arg_value in zip(func_def.args.args, k_args):
|
for arg_ast, arg_value in zip(func_def.args.args, k_args):
|
||||||
arg_name = arg_ast.arg
|
arg_name = arg_ast.arg
|
||||||
if arg_name in rop:
|
if arg_name in rop:
|
||||||
rm.set(obj, func_name, arg_name, arg_value)
|
rm.to_inlined[(id(obj), func_name, arg_name)] = arg_value
|
||||||
else:
|
else:
|
||||||
target = rm.get(obj, func_name, ast.Name(arg_name, ast.Store()))
|
target = rm.get(obj, func_name, ast.Name(arg_name, ast.Store()))
|
||||||
value = value_to_ast(arg_value)
|
value = value_to_ast(arg_value)
|
||||||
|
|
Loading…
Reference in New Issue