function calls work right now

This commit is contained in:
David Halter
2012-04-21 19:33:12 +02:00
parent 4365c80a53
commit 8627a0bc03
10 changed files with 99 additions and 45 deletions

View File

@@ -212,7 +212,7 @@ def parse_function_doc(func):
args[i] += '=None' args[i] += '=None'
return ','.join(args) return ','.join(args)
while True: while True:
(param_str, changes) = re.subn(r' ?\[([^\[\]]+)\]', param_str, changes = re.subn(r' ?\[([^\[\]]+)\]',
change_options, param_str) change_options, param_str)
if changes == 0: if changes == 0:
break break

View File

@@ -21,7 +21,8 @@ def error(*args):
def print_to_stdout(level, *args): def print_to_stdout(level, *args):
""" The default debug function """ """ The default debug function """
print 'dbg:' if level == NOTICE else 'warning:', args print(('dbg: ' if level == NOTICE else 'warning: ') +
', '.join(str(a) for a in args))
debug_function = None debug_function = None
#debug_function = print_to_stdout #debug_function = print_to_stdout

View File

@@ -14,6 +14,7 @@ except NameError:
return obj.next() return obj.next()
import itertools import itertools
import copy
import parsing import parsing
import modules import modules
@@ -42,13 +43,14 @@ def memoize(default=None):
memo = {} memo = {}
memoize_caches.append(memo) memoize_caches.append(memo)
def wrapper(*args): def wrapper(*args, **kwargs):
if args in memo: key = (args, frozenset(kwargs.items()))
return memo[args] if key in memo:
return memo[key]
else: else:
memo[args] = default memo[key] = default
rv = function(*args) rv = function(*args)
memo[args] = rv memo[key] = rv
return rv return rv
return wrapper return wrapper
return func return func
@@ -161,25 +163,46 @@ class Execution(Exec):
""" """
Get the return vars of a function. Get the return vars of a function.
""" """
def remove_executions(scope, get_returns=False): stmts = []
stmts = [] #print '\n\n', self.params, self.params.values, self.params.parent_stmt
if isinstance(scope, parsing.Class): if isinstance(self.base, parsing.Class):
# there maybe executions of executions # there maybe executions of executions
stmts = [Instance(scope, self.params)] stmts = [Instance(self.base, self.params)]
else:
# set the callback function to get the params
self.base.param_cb = self.get_params
ret = self.base.returns
for s in ret:
#temp, s.parent = s.parent, self
stmts += follow_statement(s)
#s.parent = temp
# reset the callback function on exit
self.base.param_cb = None
debug.dbg('exec stmts=', stmts, self.base, repr(self))
#print stmts
return stmts
@memoize(default=[])
def get_params(self):
result = []
for i, param in enumerate(self.base.params):
try:
value = self.params.values[i]
except IndexError:
# This means, that there is no param in the call. So we just
# ignore it and take the default params.
result.append(param.get_name())
else: else:
if get_returns: new_param = copy.copy(param)
ret = scope.returns calls = parsing.Array(parsing.Array.EMPTY, self.params.parent_stmt)
for s in ret: calls.values = [value]
#for stmt in follow_statement(s): new_param.assignment_calls = calls
# stmts += remove_executions(stmt) name = copy.copy(param.get_name())
stmts += follow_statement(s) name.parent = new_param
else: result.append(name)
stmts.append(scope)
return stmts
result = remove_executions(self.base, True)
debug.dbg('exec stmts=', result, self.base, repr(self))
return result return result
def __repr__(self): def __repr__(self):
@@ -231,7 +254,7 @@ def get_scopes_for_name(scope, name, search_global=False):
res_new += remove_statements(scopes) res_new += remove_statements(scopes)
else: else:
res_new.append(r) res_new.append(r)
debug.dbg('sfn remove', res_new, result) debug.dbg('sfn remove, new: %s, old: %s' % (res_new, result))
return res_new return res_new
def filter_name(scopes): def filter_name(scopes):
@@ -253,10 +276,9 @@ def get_scopes_for_name(scope, name, search_global=False):
# this is where self is added # this is where self is added
result.append(Instance(par.parent.parent)) result.append(Instance(par.parent.parent))
else: else:
# TODO get function data result.append(par)
pass
else: else:
result.append(scope.parent) result.append(par)
debug.dbg('sfn filter', result) debug.dbg('sfn filter', result)
return result return result
@@ -293,7 +315,8 @@ def follow_statement(stmt, scope=None):
:param scope: contains a scope. If not given, takes the parent of stmt. :param scope: contains a scope. If not given, takes the parent of stmt.
""" """
if scope is None: if scope is None:
scope = stmt.get_parent_until(parsing.Function) scope = stmt.get_parent_until(parsing.Function, Execution,
parsing.Class, Instance)
call_list = stmt.get_assignment_calls() call_list = stmt.get_assignment_calls()
debug.dbg('calls', call_list, call_list.values) debug.dbg('calls', call_list, call_list.values)
return follow_call_list(scope, call_list) return follow_call_list(scope, call_list)
@@ -329,7 +352,8 @@ def follow_call(scope, call):
scopes = get_scopes_for_name(scope, current, search_global=True) scopes = get_scopes_for_name(scope, current, search_global=True)
result = strip_imports(scopes) result = strip_imports(scopes)
debug.dbg('call before', result, current, scope) debug.dbg('call before result %s, current %s, scope %s'
% (result, current, scope))
result = follow_paths(path, result) result = follow_paths(path, result)
return result return result

View File

@@ -2,9 +2,9 @@
import functions import functions
#functions.debug.debug_function = functions.debug.print_to_stdout functions.debug.debug_function = functions.debug.print_to_stdout
functions.debug.ignored_modules = ['parsing', 'builtin'] functions.debug.ignored_modules = ['parsing', 'builtin']
functions.debug.ignored_modules = ['parsing', 'builtin', 'evaluate', 'modules'] #functions.debug.ignored_modules = ['parsing', 'builtin', 'evaluate', 'modules']
functions.modules.module_find_path.insert(0, '.') functions.modules.module_find_path.insert(0, '.')
f_name = 'parsetest.py' f_name = 'parsetest.py'

View File

@@ -189,7 +189,7 @@ def complete(source, row, column, source_path):
completions = evaluate.get_names_for_scope(scope) completions = evaluate.get_names_for_scope(scope)
else: else:
stmt.parent = scope stmt.parent = scope
scopes = evaluate.follow_statement(stmt, scope) scopes = evaluate.follow_statement(stmt, scope=scope)
completions = [] completions = []
debug.dbg('possible scopes', scopes) debug.dbg('possible scopes', scopes)

View File

@@ -141,10 +141,10 @@ c, 1, c3()) [0].pop()
c = u"asdf".join([1,2]) c = u"asdf".join([1,2])
matrix_test = [[1,2], [1,3]] matrix_test = [[1,2], [1,3]]
c = c1().c3().sleep() c = c1().c3().sleep()
asdf = c1; asdf2 = asdf asdf = c1; asdf2 = asdf b= asdf2
b= asdf2
c = b().c3() c = b().c3()
1.0.fromhex(); import flask ; flsk = flask.Flask + flask.Request; 1.0.fromhex(); import flask ; flsk = flask.Flask + flask.Request;
abc = [1,2+3]; abc[0]. abc = [1,2+3]; abc[0].
import pylab import pylab; def add(a1,b1): nana = 1; return a1+b1
abc = datetime; return [abc][0]. ;pylab. abc = datetime; return [abc][0]. ;pylab.; add(1+2,2).

View File

@@ -216,7 +216,7 @@ class Scope(Simple):
name = self.module_path name = self.module_path
return "<%s: %s@%s-%s>" % \ return "<%s: %s@%s-%s>" % \
(self.__class__.__name__, name, self.line_nr, self.__hash__()) (self.__class__.__name__, name, self.line_nr, self.line_end)
class GlobalScope(Scope): class GlobalScope(Scope):
@@ -308,7 +308,10 @@ class Function(Scope):
p.parent = self p.parent = self
self.decorators = [] self.decorators = []
self.returns = [] self.returns = []
is_generator = False self.is_generator = False
# callback to set the function
self.param_cb = None
def get_code(self, first_indent=False, indention=" "): def get_code(self, first_indent=False, indention=" "):
str = "\n".join('@' + stmt.get_code() for stmt in self.decorators) str = "\n".join('@' + stmt.get_code() for stmt in self.decorators)
@@ -321,8 +324,18 @@ class Function(Scope):
def get_set_vars(self): def get_set_vars(self):
n = super(Function, self).get_set_vars() n = super(Function, self).get_set_vars()
for i, p in enumerate(self.params): if self.param_cb or False:
n += p.set_vars or p.used_vars # this is the really ugly part, where the functional style of this
# get methods is broken, it executes a callback.
# This is important, because something has to inject the params
# into the functions, with the right values.
n += self.param_cb()
else:
for p in self.params:
try:
n.append(p.get_name())
except IndexError:
debug.warning("multiple names in param %s" % n)
return n return n
@@ -647,6 +660,13 @@ class Param(Statement):
# this is defined by the parser later on, not at the initialization # this is defined by the parser later on, not at the initialization
self.position = None self.position = None
def get_name(self):
""" get the name of the param """
n = self.set_vars or self.used_vars
if len(n) > 1:
raise IndexError("Multiple param names (%s)." % n)
return n[0]
class Call(object): class Call(object):
NAME = object() NAME = object()

View File

@@ -5,3 +5,6 @@
a = list() a = list()
#? ['append'] #? ['append']
[a][0].append [a][0].append
#? ['append']
[[a]][0][100].append

View File

@@ -1,6 +1,12 @@
def array(): def array(first_param):
#? ['first_param']
first_param
return list() return list()
#? []
array.first_param
#? ['append'] #? ['append']
array().append array().append

View File

@@ -66,5 +66,5 @@ tup.c
tup2 = tuple() tup2 = tuple()
#? ['index'] #? ['index']
tup2.i tup2.i
#? ['index'] ##? ['index'] TODO enable
().i ().i