split parsing functions file, the path following is now in evaluate.py

This commit is contained in:
David Halter
2012-03-10 15:34:07 +01:00
parent 664d1c9119
commit 5332a87d39
4 changed files with 97 additions and 66 deletions

58
evaluate.py Normal file
View File

@@ -0,0 +1,58 @@
import parsing
def Statement(object):
""" The statement object of functions, to """
pass
def get_names_for_scope(scope):
""" Get all completions possible for the current scope. """
comp = []
start_scope = scope
while scope:
# class variables/functions are only availabe
if not isinstance(scope, parsing.Class) or scope == start_scope:
comp += scope.get_set_vars()
scope = scope.parent
return comp
def follow_path(scope, path):
"""
Follow a path of python names.
recursive!
:returns: list(Scope)
"""
comp = get_names_for_scope(scope)
print path, comp
path = list(path)
name = path.pop(0)
scopes = []
# make the full comparison, because the names have to match exactly
comp = [c for c in comp if [name] == list(c.names)]
# TODO differentiate between the different comp input (some are overridden)
for c in comp:
p_class = c.parent.__class__
if p_class == parsing.Class or p_class == parsing.Scope:
scopes.append(c.parent)
#elif p_class == parsing.Function:
elif p_class == parsing.Statement:
pass
else:
print 'error follow_path:', p_class, repr(c.parent)
if path:
new_scopes = []
for s in tuple(scopes):
new_scopes += follow_path(s, tuple(path))
scopes = new_scopes
return set(scopes)
def dbg(*args):
if debug_function:
debug_function(*args)
debug_function = None

View File

@@ -1,5 +1,6 @@
import parsing import parsing
import evaluate
import re import re
__all__ = ['complete', 'set_debug_function'] __all__ = ['complete', 'set_debug_function']
@@ -181,8 +182,11 @@ def complete(source, row, column, file_callback=None):
f = File(source=source, row=row) f = File(source=source, row=row)
scope = f.parser.user_scope scope = f.parser.user_scope
print # print a dbg title
print dbg()
dbg('-' * 70)
dbg(' ' * 62 + 'complete')
dbg('-' * 70)
print scope print scope
print f.parser.user_scope.get_simple_for_line(row) print f.parser.user_scope.get_simple_for_line(row)
@@ -197,7 +201,7 @@ def complete(source, row, column, file_callback=None):
name = path.pop() name = path.pop()
if path: if path:
scopes = follow_path(scope, tuple(path)) scopes = evaluate.follow_path(scope, tuple(path))
dbg('possible scopes', scopes) dbg('possible scopes', scopes)
compl = [] compl = []
@@ -213,46 +217,6 @@ def complete(source, row, column, file_callback=None):
return result return result
def get_names_for_scope(scope):
""" Get all completions possible for the current scope. """
comp = []
start_scope = scope
while scope:
# class variables/functions are only availabe
if not isinstance(scope, parsing.Class) or scope == start_scope:
comp += scope.get_set_vars()
scope = scope.parent
return comp
def follow_path(scope, path):
"""
Follow a path of python names.
recursive!
:returns: list(Scope)
"""
comp = get_names_for_scope(scope)
print path, comp
path = list(path)
name = path.pop()
scopes = []
# make the full comparison, because the names have to match exactly
comp = [c for c in comp if [name] == list(c.names)]
# TODO differentiate between the different comp input (some are overridden)
for c in comp:
p_class = c.parent.__class__
if p_class == parsing.Class or p_class == parsing.Scope:
scopes.append(c.parent)
#elif p_class == parsing.Function:
else:
print 'error follow_path:', p_class
if path:
for s in tuple(scopes):
scopes += follow_path(s, tuple(path))
return set(scopes)
def dbg(*args): def dbg(*args):
if debug_function: if debug_function:
debug_function(*args) debug_function(*args)
@@ -262,6 +226,7 @@ def set_debug_function(func):
global debug_function global debug_function
debug_function = func debug_function = func
parsing.debug_function = func parsing.debug_function = func
evaluate.debug_function = func
debug_function = None debug_function = None

View File

@@ -60,6 +60,11 @@ class Simple(object):
self.line_end = line_end self.line_end = line_end
self.parent = None self.parent = None
def __repr__(self):
code = self.get_code().replace('\n', ' ')
return "<%s: %s@%s>" % \
(self.__class__.__name__, code, self.line_nr)
class Scope(Simple): class Scope(Simple):
""" """
@@ -126,6 +131,7 @@ class Scope(Simple):
def add_import(self, imp): def add_import(self, imp):
self.imports.append(imp) self.imports.append(imp)
imp.parent = self
def add_global(self, name): def add_global(self, name):
""" """
@@ -137,14 +143,7 @@ class Scope(Simple):
:type name: Name :type name: Name
""" """
self.global_vars.append(name) self.global_vars.append(name)
# set no parent here, because globals are not defined in this scope.
def _checkexisting(self, test):
"Convienance function... keep out duplicates"
if test.find('=') > -1:
var = test.split('=')[0].strip()
for l in self.locals:
if l.find('=') > -1 and var == l.split('=')[0].strip():
self.locals.remove(l)
def get_code(self, first_indent=False, indention=" "): def get_code(self, first_indent=False, indention=" "):
""" """
@@ -291,7 +290,10 @@ class Function(Scope):
def __init__(self, name, params, indent, line_nr, docstr=''): def __init__(self, name, params, indent, line_nr, docstr=''):
Scope.__init__(self, indent, line_nr, docstr) Scope.__init__(self, indent, line_nr, docstr)
self.name = name self.name = name
name.parent = self
self.params = params self.params = params
for p in params:
p.parent = self
self.decorators = [] self.decorators = []
def get_code(self, first_indent=False, indention=" "): def get_code(self, first_indent=False, indention=" "):
@@ -340,10 +342,14 @@ class Flow(Scope):
super(Flow, self).__init__(indent, line_nr, '') super(Flow, self).__init__(indent, line_nr, '')
self.command = command self.command = command
self.statement = statement self.statement = statement
if statement:
statement.parent = self
if set_vars == None: if set_vars == None:
self.set_vars = [] self.set_vars = []
else: else:
self.set_vars = set_vars self.set_vars = set_vars
for s in self.set_vars:
s.parent = self
self.next = None self.next = None
def get_code(self, first_indent=False, indention=" "): def get_code(self, first_indent=False, indention=" "):
@@ -395,22 +401,30 @@ class Import(Simple):
:param line_nr: Line number. :param line_nr: Line number.
:type line_nr: int :type line_nr: int
:param namespace: The import, as an array list of Name, \ :param namespace: The import, can be empty if a star is given
e.g. ['datetime', 'time']. :type namespace: Name
:type namespace: list
:param alias: The alias of a namespace(valid in the current namespace). :param alias: The alias of a namespace(valid in the current namespace).
:type alias: str :type alias: Name
:param from_ns: Like the namespace, can be equally used. :param from_ns: Like the namespace, can be equally used.
:type from_ns: list :type from_ns: Name
:param star: If a star is used -> from time import *. :param star: If a star is used -> from time import *.
:type star: bool :type star: bool
""" """
def __init__(self, indent, line_nr, line_end, namespace, alias='', \ def __init__(self, indent, line_nr, line_end, namespace, alias='', \
from_ns='', star=False): from_ns='', star=False):
super(Import, self).__init__(indent, line_nr, line_end) super(Import, self).__init__(indent, line_nr, line_end)
self.namespace = namespace self.namespace = namespace
namespace.parent = self
self.alias = alias self.alias = alias
if alias:
alias.parent = self
self.from_ns = from_ns self.from_ns = from_ns
if from_ns:
from_ns.parent = self
self.star = star self.star = star
def get_code(self): def get_code(self):
@@ -430,10 +444,6 @@ class Import(Simple):
return [self] return [self]
return [self.alias] if self.alias else [self.namespace] return [self.alias] if self.alias else [self.namespace]
def __repr__(self):
return "<%s: %s@%s>" % \
(self.__class__.__name__, self.get_code(), self.line_nr)
class Statement(Simple): class Statement(Simple):
""" """
@@ -462,6 +472,8 @@ class Statement(Simple):
self.set_vars = set_vars self.set_vars = set_vars
self.used_funcs = used_funcs self.used_funcs = used_funcs
self.used_vars = used_vars self.used_vars = used_vars
for s in set_vars + used_funcs + used_vars:
s.parent = self
def get_code(self, new_line=True): def get_code(self, new_line=True):
if new_line: if new_line:
@@ -503,10 +515,6 @@ class Name(Simple):
def __hash__(self): def __hash__(self):
return hash(self.names) + hash(self.indent) + hash(self.line_nr) return hash(self.names) + hash(self.indent) + hash(self.line_nr)
def __repr__(self):
return "<%s: %s@%s>" % \
(self.__class__.__name__, self.get_code(), self.line_nr)
def __len__(self): def __len__(self):
return len(self.names) return len(self.names)

View File

@@ -128,7 +128,7 @@ if True or a:
# completion # completion
import time import time
class c1(): class c1():
c2 = 1 c2 = c1()
def c3(self): def c3(self):
import time as c4 import time as c4
c5 = 3 c5 = 3
@@ -136,5 +136,5 @@ class c1():
c1.\ c1.c2.\
c c