Example #1
0
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
Example #2
0
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
Example #3
0
 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
Example #4
0
File: do.py Project: d-gold/dg_fn
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)
Example #5
0
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
Example #6
0
 def find(a, rec2):
     for b in rec2:
         if (first(a) == first(b)) and typeEqual(rest(a), rest(b)):
             return True
     return False
Example #7
0
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()