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 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 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 do(fn, arg, expand_args=False): """Execute a function explictly for its side effects. :fn: Function providing side effects to call. :arg: Parameter to fn. Multiple parameters are supported when expand_args is True. :expand_args: Indicate that the fn takes multiple parameters and the arg value should be expanded. This only applies when arg is a list. :returns: arg do() makes an easy way to insert functions that we are not interested in the return value of into a chain of function calls. It has support for calling multiple functions with multiple arguments. Keyword arguments are not supported. Example: We will first create a couple of functions that do nothing but write to the console as side effects. Create a function that writes to the console as a side effect. We do not care about the return value of this function. >>> def x1(a): ... print len(a) ... Create a function that provides data that we will process >>> def y1(a): ... return map(lambda x: x * a, range(1, a + 1)) ... Use do to handle the side effects and return the results of y1(). >>> do(x1, y1(3)) 3 [3, 6, 9] Or you can put the argument in directly. >>> do(x1, (1, 2, 3, 4, 5)) 5 (1, 2, 3, 4, 5) A list of functions can be passed into do(). Example: >>> def x2(l): ... print sum(l) ... >>> def x3(l): ... print reduce(lambda x, y: x * y, l) ... >>> do((x1, x2, x3), y1(4)) 4 40 6144 [4, 8, 12, 16] The results can be passed into other functions as if the do() call wasn't there. >>> sum(do(x1, y1(3))) 3 18 >>> sum(do((x1, x2, x3), y1(4))) 4 40 6144 40 By using the expand_args flag, do() is capable of handling functions that take multiple arguments. Here is an example: Create a couple of functions that have side effects >>> def foo(a, b, c): ... print a + b + c ... >>> def bar(a, b, c): ... print a * b * c ... And a function that generates values that can be used by the first two >>> def baz(x): ... return x, x * 2, x * 3 ... Now pipe the functions through do() >>> fn = (foo, bar) >>> do(fn, baz(1), expand_args=True) 6 6 (1, 2, 3) >>> do(fn, baz(2)) 12 48 (2, 4, 6) The do() function can be called by passing all the args as a list. >>> do(fn, (1, 4, 5), expand_args=True) 10 20 (1, 4, 5) The results of do() in the expand_args case is the arguments as a list. These can be then passed into other functions. >>> sum(do(fn, baz(2), expand_args=True)) 12 48 12 """ def multi_fn(fn_list, arg): """Call a list of functons :fn_list: List of functions :*args: Arguments to those functions. Each function will get the same arguments. :returns: Always returns True. """ _ = map(lambda f: f(*arg), fn_list) return True prepped_args = (expand_args and is_seq(arg) and arg) or \ (arg and [arg]) or \ None _ = (is_seq(fn) and multi_fn(fn, prepped_args)) or \ (prepped_args and fn(*prepped_args)) or \ fn(None) return (expand_args and prepped_args) or first(prepped_args)
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
def process_char(asker, root, c, parents): c = convert.to_char(asker, c) if convert.check_hard(asker, is_pointer(), root): if c == 'q': return asker.reply(value=quit) elif c == 'j': children = asker.ask(fields.get_field(visible_children(), root)).firm_answer if convert.check_hard(asker, lists.is_empty(), children): asker.pass_through(moved(down)) else: children = asker.refresh(children) first_child = asker.ask(fields.get_fields(lists.first(), children)).firm_answer asker.update(has_pointer_now(), root) asker.update(is_pointer_now(), first_child) return asker.reply() elif c == 'k': return asker.reply(value=moved(up)) elif c == 'z': asker.update(toggle_expanded(), root) return asker.reply() elif c == 'h': return asker.reply(value=moved(left)) elif c == 'l': #FIXME zoom out one by one instead of all of the way... #this is pretty straightforward if we are willing to go into and out of python #but it would surely be nicer to do it the 'right' way #I'm also pretty happy to wait asker.ask(explore_outline(root, parents)) return asker.reply(value=moved(left)) elif convert.check_hard(asker, has_pointer(), root): children = asker.ask(field.get_field(visible_children(), root)).firm_answer def make_handler(above, below): handler = Dispatcher("exploration child handler", ("question",)) @handler(moved.head) def move(asker, question, direction): if direction.head == down.head: if below is None: asker.pass_through(moved(direction)) else: asker.update(now_is_pointer(), below) asker.update(remove_pointer(), child) if direction.head == up.head: if above is None: asker.update(now_is_pointer(), root) asker.update(remove_pointer(), child) else: asker.update(add_pointer_to_bottom(), above) asker.update(remove_pointer(), child) elif direction.head == left.head: asker.update(remove_pointer(), child) asker.update(now_is_pointer(), root) return properties.trivial() #TODO insert a handler for changing underlying terms *etc* #I think that this is going to require some thought, #but I can wait return handler child_list = list(lists.iterator(asker, children)) new_parents = lists.snoc(parents, root) for i in range(len(child_list)): child = child_list[i] if i > 0: below = child_list[i-1] else: below = None if i < len(child_list) - 1: above = child_list[i+1] else: above = None asker.ask(process_char(child, c, new_parents), handler=make_handler(above, below)) return asker.reply()