def add_line(asker, view, new_line): return asker.reply(answer=updates.update( updates.apply_to_field( lines_field(), lists.append(new_line) ), view ))
def invokeClosure(call, actualParams, clo, env, stk): """ @types: ast.Call, list[ast.AST], Closure, LinkedList, LinkedList -> list[Type] """ debug("invoking closure", clo.func, "with args", actualParams) debug(clo.func.body) func = clo.func fenv = clo.env pos = nil kwarg = nil # bind positionals first poslen = min(len(func.args.args), len(actualParams)) for i in xrange(poslen): t = infer(actualParams[i], env, stk) pos = bind(func.args.args[i], t, pos) # put extra positionals into vararg if provided # report error and go on otherwise if len(actualParams) > len(func.args.args): if func.args.vararg == None: err = TypeError("excess arguments to function") putInfo(call, err) return [err] else: ts = [] for i in xrange(len(func.args.args), len(actualParams)): t = infer(actualParams[i], env, stk) ts = ts + t pos = bind(func.args.vararg, ts, pos) # bind keywords, collect kwarg ids = map(getId, func.args.args) for k in call.keywords: ts = infer(k.value, env, stk) tloc1 = lookup(k.arg, pos) if tloc1 != None: putInfo(call, TypeError("multiple values for keyword argument", k.arg, tloc1)) elif k.arg not in ids: kwarg = bind(k.arg, ts, kwarg) else: pos = bind(k.arg, ts, pos) # put extras in kwarg or report them # bind call.keywords to func.args.kwarg if kwarg != nil: if func.args.kwarg != None: pos = bind(func.args.kwarg, [DictType(reverse(kwarg))], pos) else: putInfo(call, TypeError("unexpected keyword arguements", kwarg)) elif func.args.kwarg != None: pos = bind(func.args.kwarg, [DictType(nil)], pos) # bind defaults, avoid overwriting bound vars # types for defaults are already inferred when the function was defined i = len(func.args.args) - len(func.args.defaults) _ = len(func.args.args) for j in xrange(len(clo.defaults)): tloc = lookup(getId(func.args.args[i]), pos) if tloc == None: pos = bind(func.args.args[i], clo.defaults[j], pos) i += 1 # finish building the input type fromtype = maplist(lambda p: SimplePair(first(p), typeOnly(rest(p))), pos) # check whether the same call site is on stack with same input types # if so, we are back to a loop, terminate if onStack(call, fromtype, stk): return [bottomType] # push the call site onto the stack and analyze the function body stk = ext(call, fromtype, stk) fenv = append(pos, fenv) to = infer(func.body, fenv, stk) # record the function type putInfo(func, FuncType(reverse(fromtype), to)) return to