1
0
forked from VimPlug/jedi

most evaluate representation classes probably receive the evaluator instance now

This commit is contained in:
Dave Halter
2013-12-24 19:47:52 +01:00
parent 85a12e8866
commit 39ed0d0f8a
3 changed files with 47 additions and 38 deletions

View File

@@ -255,10 +255,12 @@ class Evaluator(object):
r = func.var.params[r.position_nr] r = func.var.params[r.position_nr]
# add docstring knowledge # add docstring knowledge
doc_params = docstrings.follow_param(r) """
doc_params = docstrings.follow_param(r) TODO ENABLE
if doc_params: if doc_params:
res_new += doc_params res_new += doc_params
continue continue
"""
if not r.is_generated: if not r.is_generated:
res_new += dynamic.search_params(r) res_new += dynamic.search_params(r)
@@ -267,7 +269,7 @@ class Evaluator(object):
if c in ('*', '**'): if c in ('*', '**'):
t = 'tuple' if c == '*' else 'dict' t = 'tuple' if c == '*' else 'dict'
res_new = [er.Instance( res_new = [er.Instance(
self.find_name(builtin.Builtin.scope, t)[0]) self, self.find_name(builtin.Builtin.scope, t)[0])
] ]
if not r.assignment_details: if not r.assignment_details:
# this means that there are no default params, # this means that there are no default params,
@@ -284,7 +286,7 @@ class Evaluator(object):
if check_instance is not None: if check_instance is not None:
# class renames # class renames
add = [er.InstanceElement(check_instance, a, True) add = [er.InstanceElement(self, check_instance, a, True)
if isinstance(a, (er.Function, pr.Function)) if isinstance(a, (er.Function, pr.Function))
else a for a in add] else a for a in add]
res_new += add res_new += add
@@ -346,7 +348,7 @@ class Evaluator(object):
if isinstance(scope, er.InstanceElement): if isinstance(scope, er.InstanceElement):
inst = scope.instance inst = scope.instance
else: else:
inst = er.Instance(er.Class(until())) inst = er.Instance(self, er.Class(self, until()))
inst.is_generated = True inst.is_generated = True
result.append(inst) result.append(inst)
elif par.isinstance(pr.Statement): elif par.isinstance(pr.Statement):
@@ -543,7 +545,7 @@ class Evaluator(object):
result += self.follow_statement(call.stmt) result += self.follow_statement(call.stmt)
else: else:
if isinstance(call, pr.Lambda): if isinstance(call, pr.Lambda):
result.append(er.Function(call)) result.append(er.Function(self, call))
# With things like params, these can also be functions... # With things like params, these can also be functions...
elif isinstance(call, pr.Base) and call.isinstance( elif isinstance(call, pr.Base) and call.isinstance(
er.Function, er.Class, er.Instance, dynamic.ArrayInstance): er.Function, er.Class, er.Instance, dynamic.ArrayInstance):
@@ -595,7 +597,7 @@ class Evaluator(object):
# for pr.Literal # for pr.Literal
scopes = self.find_name(builtin.Builtin.scope, current.type_as_string()) scopes = self.find_name(builtin.Builtin.scope, current.type_as_string())
# Make instances of those number/string objects. # Make instances of those number/string objects.
scopes = [er.Instance(s, (current.value,)) for s in scopes] scopes = [er.Instance(self, s, (current.value,)) for s in scopes]
result = imports.strip_imports(self, scopes) result = imports.strip_imports(self, scopes)
return self.follow_paths(path, result, scope, position=position) return self.follow_paths(path, result, scope, position=position)
@@ -662,7 +664,7 @@ class Evaluator(object):
return self.follow_paths(path, set(result), call_scope, position=position) return self.follow_paths(path, set(result), call_scope, position=position)
def execute(self, scope, params, evaluate_generator=False): def execute(self, scope, params, evaluate_generator=False):
return er.Execution(scope, params).get_return_types(evaluate_generator) return er.Execution(self, scope, params).get_return_types(evaluate_generator)
def goto(self, stmt, call_path=None): def goto(self, stmt, call_path=None):
if call_path is None: if call_path is None:

View File

@@ -5,7 +5,7 @@
""" """
def memoize_default(default, cache_is_in_self=False): def memoize_default(default, cache_is_in_self=False, first_arg_is_evaluator=False):
""" This is a typical memoization decorator, BUT there is one difference: """ This is a typical memoization decorator, BUT there is one difference:
To prevent recursion it sets defaults. To prevent recursion it sets defaults.
@@ -17,6 +17,8 @@ def memoize_default(default, cache_is_in_self=False):
def wrapper(obj, *args, **kwargs): def wrapper(obj, *args, **kwargs):
if cache_is_in_self: if cache_is_in_self:
cache = obj.memoize_cache cache = obj.memoize_cache
elif first_arg_is_evaluator: # needed for meta classes
cache = args[0].memoize_cache
else: else:
cache = obj._evaluator.memoize_cache cache = obj._evaluator.memoize_cache
@@ -24,7 +26,7 @@ def memoize_default(default, cache_is_in_self=False):
memo = cache[function] memo = cache[function]
except KeyError: except KeyError:
memo = {} memo = {}
cache[function] = function cache[function] = memo
key = (args, frozenset(kwargs.items())) key = (args, frozenset(kwargs.items()))
if key in memo: if key in memo:
@@ -39,10 +41,11 @@ def memoize_default(default, cache_is_in_self=False):
class CachedMetaClass(type): class CachedMetaClass(type):
""" This is basically almost the same than the decorator above, it just
caches class initializations. I haven't found any other way, so I do it
with meta classes.
""" """
@memoize_default(None) This is basically almost the same than the decorator above, it just caches
class initializations. I haven't found any other way, so I'm doing it with
meta classes.
"""
@memoize_default(None, first_arg_is_evaluator=True)
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
return super(CachedMetaClass, self).__call__(*args, **kwargs) return super(CachedMetaClass, self).__call__(*args, **kwargs)

View File

@@ -34,7 +34,7 @@ class Executable(pr.IsScope):
:param var_args: The param input array, consist of `pr.Array` or list. :param var_args: The param input array, consist of `pr.Array` or list.
""" """
def __init__(self, evaluator, base, var_args=()): def __init__(self, evaluator, base, var_args=()):
self.evaluator = evaluator self._evaluator = evaluator
self.base = base self.base = base
self.var_args = var_args self.var_args = var_args
@@ -74,8 +74,8 @@ class Instance(use_metaclass(CachedMetaClass, Executable)):
@memoize_default(None) @memoize_default(None)
def _get_method_execution(self, func): def _get_method_execution(self, func):
func = InstanceElement(self, func, True) func = InstanceElement(self._evaluator, self, func, True)
return Execution(func, self.var_args) return Execution(self._evaluator, func, self.var_args)
def _get_func_self_name(self, func): def _get_func_self_name(self, func):
""" """
@@ -96,7 +96,7 @@ class Instance(use_metaclass(CachedMetaClass, Executable)):
""" """
n = copy.copy(name) n = copy.copy(name)
n.names = n.names[1:] n.names = n.names[1:]
names.append(InstanceElement(self, n)) names.append(InstanceElement(self._evaluator, self, n))
names = [] names = []
# This loop adds the names of the self object, copies them and removes # This loop adds the names of the self object, copies them and removes
@@ -125,17 +125,17 @@ class Instance(use_metaclass(CachedMetaClass, Executable)):
add_self_dot_name(n) add_self_dot_name(n)
for s in self.base.get_super_classes(): for s in self.base.get_super_classes():
names += Instance(s)._get_self_attributes() names += Instance(self._evaluator, s)._get_self_attributes()
return names return names
def get_subscope_by_name(self, name): def get_subscope_by_name(self, name):
sub = self.base.get_subscope_by_name(name) sub = self.base.get_subscope_by_name(name)
return InstanceElement(self, sub, True) return InstanceElement(self._evaluator, self, sub, True)
def execute_subscope_by_name(self, name, args=()): def execute_subscope_by_name(self, name, args=()):
method = self.get_subscope_by_name(name) method = self.get_subscope_by_name(name)
return Execution(method, args).get_return_types() return Execution(self._evaluator, method, args).get_return_types()
def get_descriptor_return(self, obj): def get_descriptor_return(self, obj):
""" Throws a KeyError if there's no method. """ """ Throws a KeyError if there's no method. """
@@ -154,7 +154,7 @@ class Instance(use_metaclass(CachedMetaClass, Executable)):
class_names = self.base.instance_names() class_names = self.base.instance_names()
for var in class_names: for var in class_names:
names.append(InstanceElement(self, var, True)) names.append(InstanceElement(self._evaluator, self, var, True))
return names return names
def scope_generator(self): def scope_generator(self):
@@ -167,7 +167,7 @@ class Instance(use_metaclass(CachedMetaClass, Executable)):
names = [] names = []
class_names = self.base.instance_names() class_names = self.base.instance_names()
for var in class_names: for var in class_names:
names.append(InstanceElement(self, var, True)) names.append(InstanceElement(self._evaluator, self, var, True))
yield self, names yield self, names
def get_index_types(self, index=None): def get_index_types(self, index=None):
@@ -195,9 +195,9 @@ class InstanceElement(use_metaclass(CachedMetaClass, pr.Base)):
InstanceElement is a wrapper for any object, that is used as an instance InstanceElement is a wrapper for any object, that is used as an instance
variable (e.g. self.variable or class methods). variable (e.g. self.variable or class methods).
""" """
def __init__(self, instance, var, is_class_var=False): def __init__(self, evaluator, instance, var, is_class_var=False):
if isinstance(var, pr.Function): if isinstance(var, pr.Function):
var = Function(var) var = Function(evaluator, var)
elif isinstance(var, pr.Class): elif isinstance(var, pr.Class):
var = Class(var) var = Class(var)
self.instance = instance self.instance = instance
@@ -213,7 +213,7 @@ class InstanceElement(use_metaclass(CachedMetaClass, pr.Base)):
and par == self.instance.base.base: and par == self.instance.base.base:
par = self.instance par = self.instance
elif not isinstance(par, pr.Module): elif not isinstance(par, pr.Module):
par = InstanceElement(self.instance, par, self.is_class_var) par = InstanceElement(self.instance._evaluator, self.instance, par, self.is_class_var)
return par return par
def get_parent_until(self, *args, **kwargs): def get_parent_until(self, *args, **kwargs):
@@ -228,13 +228,13 @@ class InstanceElement(use_metaclass(CachedMetaClass, pr.Base)):
def get_commands(self): def get_commands(self):
# Copy and modify the array. # Copy and modify the array.
return [InstanceElement(self.instance, command, self.is_class_var) return [InstanceElement(self.instance._evaluator, self.instance, command, self.is_class_var)
if not isinstance(command, unicode) else command if not isinstance(command, unicode) else command
for command in self.var.get_commands()] for command in self.var.get_commands()]
def __iter__(self): def __iter__(self):
for el in self.var.__iter__(): for el in self.var.__iter__():
yield InstanceElement(self.instance, el, self.is_class_var) yield InstanceElement(self.instance._evaluator, self.instance, el, self.is_class_var)
def __getattr__(self, name): def __getattr__(self, name):
return getattr(self.var, name) return getattr(self.var, name)
@@ -352,12 +352,12 @@ class Function(use_metaclass(CachedMetaClass, pr.IsScope)):
debug.warning('multiple decorators found', self.base_func, debug.warning('multiple decorators found', self.base_func,
dec_results) dec_results)
# Create param array. # Create param array.
old_func = Function(f, is_decorated=True) old_func = Function(self._evaluator, f, is_decorated=True)
if instance is not None and decorator.isinstance(Function): if instance is not None and decorator.isinstance(Function):
old_func = InstanceElement(instance, old_func) old_func = InstanceElement(self._evaluator, instance, old_func)
instance = None instance = None
wrappers = Execution(decorator, (old_func,)).get_return_types() wrappers = Execution(self._evaluator, decorator, (old_func,)).get_return_types()
if not len(wrappers): if not len(wrappers):
debug.warning('no wrappers found', self.base_func) debug.warning('no wrappers found', self.base_func)
return None return None
@@ -369,7 +369,7 @@ class Function(use_metaclass(CachedMetaClass, pr.IsScope)):
debug.dbg('decorator end', f) debug.dbg('decorator end', f)
if f != self.base_func and isinstance(f, pr.Function): if f != self.base_func and isinstance(f, pr.Function):
f = Function(f) f = Function(self._evaluator, f)
return f return f
def get_decorated_func(self, instance=None): def get_decorated_func(self, instance=None):
@@ -380,7 +380,7 @@ class Function(use_metaclass(CachedMetaClass, pr.IsScope)):
# If the decorator func is not found, just ignore the decorator # If the decorator func is not found, just ignore the decorator
# function, because sometimes decorators are just really # function, because sometimes decorators are just really
# complicated. # complicated.
return Function(self.base_func, True) return Function(self._evaluator, self.base_func, True)
return decorated_func return decorated_func
def get_magic_method_names(self): def get_magic_method_names(self):
@@ -473,12 +473,12 @@ class Execution(Executable):
cls = Class(cls) cls = Class(cls)
su = cls.get_super_classes() su = cls.get_super_classes()
if su: if su:
return [Instance(su[0])] return [Instance(self._evaluator, su[0])]
return [] return []
if base.isinstance(Class): if base.isinstance(Class):
# There maybe executions of executions. # There maybe executions of executions.
return [Instance(base, self.var_args)] return [Instance(self._evaluator, base, self.var_args)]
elif isinstance(base, Generator): elif isinstance(base, Generator):
return base.iter_content() return base.iter_content()
else: else:
@@ -508,7 +508,10 @@ class Execution(Executable):
if func.is_generator and not evaluate_generator: if func.is_generator and not evaluate_generator:
return [Generator(func, self.var_args)] return [Generator(func, self.var_args)]
else: else:
"""
stmts = docstrings.find_return_types(func) stmts = docstrings.find_return_types(func)
"""
stmts=[]
for r in self.returns: for r in self.returns:
if r is not None: if r is not None:
stmts += self._evaluator.follow_statement(r) stmts += self._evaluator.follow_statement(r)
@@ -727,7 +730,7 @@ class Execution(Executable):
copied = helpers.fast_parent_copy(element) copied = helpers.fast_parent_copy(element)
copied.parent = self._scope_copy(copied.parent) copied.parent = self._scope_copy(copied.parent)
if isinstance(copied, pr.Function): if isinstance(copied, pr.Function):
copied = Function(copied) copied = Function(self._evaluator, copied)
objects.append(copied) objects.append(copied)
return objects return objects
@@ -781,7 +784,8 @@ class Execution(Executable):
class Generator(use_metaclass(CachedMetaClass, pr.Base, Iterable)): class Generator(use_metaclass(CachedMetaClass, pr.Base, Iterable)):
""" Cares for `yield` statements. """ """ Cares for `yield` statements. """
def __init__(self, func, var_args): def __init__(self, evaluator, func, var_args):
# Need evaluator for `CachedMetaClass`.
super(Generator, self).__init__() super(Generator, self).__init__()
self.func = func self.func = func
self.var_args = var_args self.var_args = var_args
@@ -807,7 +811,7 @@ class Generator(use_metaclass(CachedMetaClass, pr.Base, Iterable)):
def iter_content(self): def iter_content(self):
""" returns the content of __iter__ """ """ returns the content of __iter__ """
return Execution(self.func, self.var_args).get_return_types(True) return Execution(self._evaluator, self.func, self.var_args).get_return_types(True)
def get_index_types(self, index=None): def get_index_types(self, index=None):
debug.warning('Tried to get array access on a generator', self) debug.warning('Tried to get array access on a generator', self)
@@ -897,7 +901,7 @@ class Array(use_metaclass(CachedMetaClass, pr.Base, Iterable)):
""" """
# `array.type` is a string with the type, e.g. 'list'. # `array.type` is a string with the type, e.g. 'list'.
scope = self._evaluator.find_name(builtin.Builtin.scope, self._array.type)[0] scope = self._evaluator.find_name(builtin.Builtin.scope, self._array.type)[0]
scope = Instance(scope) scope = Instance(self._evaluator, scope)
names = scope.get_defined_names() names = scope.get_defined_names()
return [ArrayMethod(n) for n in names] return [ArrayMethod(n) for n in names]