transforms/inline: refactor and fix _ReferenceManager.inline

This commit is contained in:
Sebastien Bourdeauducq 2014-09-13 19:24:32 +08:00
parent dc9515fc62
commit 123ddb26a1
1 changed files with 31 additions and 53 deletions

View File

@ -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,66 +48,44 @@ 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
else:
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:
if _is_in_attr_list(value, ref.attr, "kernel_attr_ro"):
if store:
raise TypeError(
"Attempted to assign to read-only"
" kernel attribute")
return getattr(value, ref.attr)
if _is_in_attr_list(value, ref.attr, "kernel_attr"):
key = (id(value), ref.attr, None)
try: try:
ival = self.to_inlined[key] return inspect.getmodule(obj).__dict__[ref.id]
assert(isinstance(ival, _UserVariable))
except KeyError: except KeyError:
iname = self.new_name(ref.attr) return getattr(builtins, ref.id)
ival = _UserVariable(iname) elif isinstance(ref, ast.Attribute):
self.to_inlined[key] = ival target = self.get(obj, func_name, ref.value)
a = value_to_ast(getattr(value, ref.attr)) if _is_in_attr_list(target, ref.attr, "kernel_attr"):
if a is None: key = (id(target), ref.attr)
raise NotImplementedError( try:
"Cannot represent initial value" ival = self.to_inlined[key]
" of kernel attribute") assert(isinstance(ival, _UserVariable))
self.kernel_attr_init.append(ast.Assign( except KeyError:
[ast.Name(iname, ast.Store())], a)) iname = self.new_name(ref.attr)
return ival ival = _UserVariable(iname)
self.to_inlined[key] = ival
if not store: a = value_to_ast(getattr(target, ref.attr))
evd = self.get_constants(obj, funcname) if a is None:
evd.update(inspect.getmodule(obj).__dict__) raise NotImplementedError(
return eval_ast(ref, evd) "Cannot represent initial value"
" of kernel attribute")
self.kernel_attr_init.append(ast.Assign(
[ast.Name(iname, ast.Store())], a))
return ival
else:
return getattr(target, ref.attr)
else: else:
raise KeyError(ast.dump(ref)) raise NotImplementedError
def set(self, obj, funcname, name, value):
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)