def mergeEnv(env1, env2): ret = nil for p1 in env1: p2 = assq(first(p1), env2) if p2 != None: ret = ext(first(p1), union([rest(p1), rest(p2)]), ret) return ret
def find(self, code_seq): step = first(code_seq) if not step: return self.data elif step == DAH and self.left: return self.left.find(rest(code_seq)) elif step == DIT and self.right: return self.right.find(rest(code_seq)) return None
def onStack(call, args, stk): for p1 in stk: call2 = first(p1) args2 = rest(p1) if call == call2 and subtypeBindings(args, args2): return True return False
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
def find(a, rec2): for b in rec2: if (first(a) == first(b)) and typeEqual(rest(a), rest(b)): return True return False