예제 #1
0
def EArgDistinct(bag, key):
    from cozy.syntax_tools import mk_lambda
    b = EVar(fresh_name())
    distinct_keys = EUnaryOp(UOp.Distinct, EMap(b, key))
    res = EMap(distinct_keys,
        mk_lambda(None, lambda x:
            EUnaryOp(UOp.The, EFilter(b, mk_lambda(None, lambda y:
                EEq(x, key.apply_to(y)))))))
    return ELet(bag, ELambda(b, res))
예제 #2
0
 def make_subgoal(e, a=[], docstring=None):
     if skip_stateless_synthesis.value and not any(v in ctx for v in free_vars(e)):
         return e
     query_name = fresh_name("query")
     query = syntax.Query(query_name, syntax.Visibility.Internal, [], assumptions + a, e, docstring)
     query_vars = [v for v in free_vars(query) if v not in ctx]
     query.args = [(arg.id, arg.type) for arg in query_vars]
     subgoals.append(query)
     return syntax.ECall(query_name, tuple(query_vars)).with_type(e.type)
예제 #3
0
파일: optimization.py 프로젝트: uwplse/cozy
 def find_one(self, iterable):
     v = fresh_var(iterable.type.elem_type, "v")
     label = fresh_name("label")
     x = fresh_var(iterable.type.elem_type, "x")
     decl = SDecl(v, evaluation.construct_value(v.type))
     find = SEscapableBlock(label,
         SForEach(x, iterable, seq([
             SAssign(v, x),
             SEscapeBlock(label)])))
     self.stms.append(simplify_and_optimize(seq([decl, find])))
     return v
예제 #4
0
파일: optimization.py 프로젝트: uwplse/cozy
    def visit_EUnaryOp(self, e):
        op = e.op
        if op == UOp.Distinct:
            return self.visit_iterable(e)
        elif op == UOp.The:
            return self.find_one(e.e)
        elif op == UOp.Sum:
            sum_var = fresh_var(e.type, "sum")
            loop_var = fresh_var(e.e.type.elem_type, "x")
            self.stms.append(simplify_and_optimize(seq([
                SDecl(sum_var, ENum(0).with_type(e.type)),
                SForEach(loop_var, e.e,
                    SAssign(sum_var, EBinOp(sum_var, "+", loop_var).with_type(INT)))])))
            return sum_var
        elif op == UOp.Length:
            arg = EVar("x").with_type(e.e.type.elem_type)
            return self.visit(EUnaryOp(UOp.Sum, EMap(e.e, ELambda(arg, ONE)).with_type(INT_BAG)).with_type(INT))
        elif op == UOp.All:
            arg = EVar("x").with_type(e.e.type.elem_type)
            return self.visit(EUnaryOp(UOp.Empty, EFilter(e.e, ELambda(arg, ENot(arg))).with_type(INT_BAG)).with_type(INT))
        elif op == UOp.Any:
            arg = EVar("x").with_type(e.e.type.elem_type)
            return self.visit(EUnaryOp(UOp.Exists, EFilter(e.e, ELambda(arg, arg)).with_type(INT_BAG)).with_type(INT))
        elif op == UOp.Empty:
            iterable = e.e
            v = fresh_var(BOOL, "v")
            label = fresh_name("label")
            x = fresh_var(iterable.type.elem_type, "x")
            decl = SDecl(v, ETRUE)
            find = SEscapableBlock(label,
                SForEach(x, iterable, seq([
                    SAssign(v, EFALSE),
                    SEscapeBlock(label)])))
            self.stms.append(simplify_and_optimize(seq([decl, find])))
            return v
        elif op == UOp.Exists:
            return self.visit(ENot(EUnaryOp(UOp.Empty, e.e).with_type(BOOL)))
        # elif op == UOp.AreUnique:
        #     s = fresh_var(TSet(e.e.type.elem_type), "unique_elems")
        #     u = fresh_var(BOOL, "is_unique")
        #     x = fresh_var(e.e.type.elem_type)
        #     label = fresh_name("label")
        #     self.visit(seq([
        #         SDecl(s, EEmptyList().with_type(s.type)),
        #         SDecl(u, ETRUE),
        #         SEscapableBlock(label,
        #             SForEach(x, e.e,
        #                 SIf(EEscape("{s}.find({x}) != {s}.end()", ("s", "x"), (s, x)).with_type(BOOL),
        #                     seq([SAssign(u, EFALSE), SEscapeBlock(label)]),
        #                     SEscape("{indent}{s}.insert({x});\n", ("s", "x"), (s, x)))))]))
        #     return u.id

        return self.visit_Exp(e)
예제 #5
0
 def visit_EBinOp(self, e):
     op = e.op
     if op == "+" and (isinstance(e.e1.type, TBag)
                       or isinstance(e.e1.type, TSet)):
         raise NotImplementedError("adding collections: {}".format(e))
     elif op == "==":
         return self._eq(e.e1, e.e2)
     elif op == "===":
         # rewrite deep-equality test into regular equality
         op = "=="
     elif op == "!=":
         return self.visit(ENot(EEq(e.e1, e.e2)))
     elif op == BOp.Or:
         return self.visit(ECond(e.e1, T, e.e2).with_type(BOOL))
     elif op == BOp.And:
         return self.visit(ECond(e.e1, e.e2, F).with_type(BOOL))
     elif op == "-" and is_collection(e.type):
         t = e.type
         v = self.fv(t, "v")
         x = self.fv(t.t, "x")
         self.declare(v, e.e1)
         self.visit(SForEach(x, e.e2, SCall(v, "remove", [x])))
         return v.id
     elif op == BOp.In:
         if isinstance(e.e2.type, TSet):
             return self.test_set_containment_native(e.e2, e.e1)
         else:
             t = BOOL
             res = self.fv(t, "found")
             x = self.fv(e.e1.type, "x")
             label = fresh_name("label")
             self.visit(
                 seq([
                     SDecl(res.id, F),
                     SEscapableBlock(
                         label,
                         SForEach(
                             x, e.e2,
                             SIf(
                                 EBinOp(x, "==", e.e1).with_type(BOOL),
                                 seq([SAssign(res, T),
                                      SEscapeBlock(label)]), SNoOp())))
                 ]))
             return res.id
     return "({e1} {op} {e2})".format(e1=self.visit(e.e1),
                                      op=op,
                                      e2=self.visit(e.e2))
예제 #6
0
 def visit_EBinOp(self, e):
     if e.op in ("+", "-") and is_collection(e.type):
         return self.visit_iterable(e)
     elif e.op == BOp.In and not isinstance(e.e2.type, TSet):
         t = BOOL
         res = fresh_var(t, "found")
         x = fresh_var(e.e1.type, "x")
         label = fresh_name("label")
         self.stms.append(simplify_and_optimize(seq([
             SDecl(res, EFALSE),
             SEscapableBlock(label,
                 SForEach(x, e.e2, SIf(
                     EBinOp(x, "==", e.e1).with_type(BOOL),
                     seq([SAssign(res, ETRUE), SEscapeBlock(label)]),
                     SNoOp())))])))
         return res
     return self.visit_Exp(e)
예제 #7
0
파일: java.py 프로젝트: wcphkust/cozy
    def array_resize_for_index(self, elem_type, a, i):
        """Resize the array until `i` is a legal index.

        When i < 0, it will do nothing instead.
        """
        new_a = fresh_name(hint="new_array")
        if elem_type == BOOL:
            t = "long"
        else:
            t = self.strip_generics(self.visit(elem_type, name=""))
        len = EEscape("{a}.length", ["a"], [a]).with_type(INT)
        double_and_incr_size = SEscape(
            "{{indent}}{t}[] {new_a} = new {t}[({{len}} << 1) + 1];\n{{indent}}System.arraycopy({{a}}, 0, {new_a}, 0, {{len}});\n{{indent}}{{a}} = {new_a};\n".format(t=t, new_a=new_a),
            ["a", "len"], [a, len])
        self.visit(SWhile(
            EAll([EBinOp(i, ">=", ZERO).with_type(BOOL), ENot(self.array_in_bounds(elem_type, a, i))]),
            double_and_incr_size))
예제 #8
0
파일: library.py 프로젝트: sanidhya/cozy
 def for_each(self, id, iter, body):
     assert iter.type == self
     # assert isinstance(iter, EVar), pprint(iter)
     iter = shallow_copy(iter).with_type(self.rep_type())
     assert id.type == self.t
     next = fresh_name("next")
     return seq([
         SDecl(id.id, iter),
         SWhile(
             ENot(equal(id, self.null)),
             seq([
                 SDecl(next,
                       EGetField(id, self.next_ptr).with_type(id.type)),
                 body,
                 SAssign(id,
                         EVar(next).with_type(id.type))
             ]))
     ])
예제 #9
0
def multi(ldict, selfname, production, sep=None):
    """
    Usage:
        multi(locals(), NAME, P[, sep=SEP])
        where P and SEP are production names.

    This produces a production named NAME of the form

        NAME ::= empty | P (SEP P)*

    that produces tuples of whatever P produces.
    """

    if sep is None:
        sep = "empty"

    f1name = fresh_name("multisep")

    def f1(p):
        if len(p) > 2 and p[3]:
            p[0] = (p[1], ) + p[3]
        else:
            p[0] = (p[1], )

    f1.__doc__ = ("""{f1name} : {prod}
                    | {prod} {sep} {f1name}""".format(f1name=f1name,
                                                      prod=production,
                                                      sep=sep))
    f1.__name__ = "p_{}".format(f1name)
    ldict[f1.__name__] = f1

    def f2(p):
        if p[1]:
            p[0] = p[1]
        else:
            p[0] = ()

    f2.__doc__ = ("""{self} : empty
                  | {f1name}""".format(self=selfname, f1name=f1name))
    f2.__name__ = "p_{}".format(selfname)
    ldict[f2.__name__] = f2
예제 #10
0
파일: impls.py 프로젝트: uwplse/cozy
    def _setup_handle_updates(self):
        """
        This method creates update code for handle objects modified by each op.
        Must be called once after all user-specified queries have been added.
        """
        for op in self.op_specs:
            print("Setting up handle updates for {}...".format(op.name))
            handles = reachable_handles_at_method(self.spec, op)
            # print("-"*60)
            for t, bag in handles.items():
                # print("  {} : {}".format(pprint(t), pprint(bag)))
                h = fresh_var(t)
                lval = EGetField(h, "val").with_type(t.value_type)
                new_val = inc.mutate(lval, op.body)

                # get set of modified handles
                modified_handles = Query(
                    fresh_name("modified_handles"),
                    Visibility.Internal, [], op.assumptions,
                    EFilter(EUnaryOp(UOp.Distinct, bag).with_type(bag.type), ELambda(h, ENot(EEq(lval, new_val)))).with_type(bag.type),
                    "[{}] modified handles of type {}".format(op.name, pprint(t)))
                query_vars = [v for v in free_vars(modified_handles) if v not in self.abstract_state]
                modified_handles.args = [(arg.id, arg.type) for arg in query_vars]

                # modify each one
                subqueries = []
                state_update_stm = inc.mutate_in_place(
                    lval,
                    lval,
                    op.body,
                    abstract_state=self.abstract_state,
                    assumptions=list(op.assumptions) + [EDeepIn(h, bag), EIn(h, modified_handles.ret)],
                    invariants=self.abstract_invariants,
                    subgoals_out=subqueries)
                for sub_q in subqueries:
                    sub_q.docstring = "[{}] {}".format(op.name, sub_q.docstring)
                    state_update_stm = self._add_subquery(sub_q=sub_q, used_by=state_update_stm)
                if state_update_stm != SNoOp():
                    state_update_stm = SForEach(h, ECall(modified_handles.name, query_vars).with_type(bag.type), state_update_stm)
                    state_update_stm = self._add_subquery(sub_q=modified_handles, used_by=state_update_stm)
                self.handle_updates[(t, op.name)] = state_update_stm
예제 #11
0
    def _setup_handle_updates(self):
        """
        This method creates update code for handle objects modified by each op.
        Must be called once after all user-specified queries have been added.
        """
        for op in self.op_specs:
            print("Setting up handle updates for {}...".format(op.name))
            handles = reachable_handles_at_method(self.spec, op)
            # print("-"*60)
            for t, bag in handles.items():
                # print("  {} : {}".format(pprint(t), pprint(bag)))
                h = fresh_var(t)
                lval = EGetField(h, "val").with_type(t.value_type)
                new_val = inc.mutate(lval, op.body)

                # get set of modified handles
                modified_handles = Query(
                    fresh_name("modified_handles"),
                    Visibility.Internal, [], op.assumptions,
                    EFilter(EUnaryOp(UOp.Distinct, bag).with_type(bag.type), ELambda(h, ENot(EEq(lval, new_val)))).with_type(bag.type),
                    "[{}] modified handles of type {}".format(op.name, pprint(t)))
                query_vars = [v for v in free_vars(modified_handles) if v not in self.abstract_state]
                modified_handles.args = [(arg.id, arg.type) for arg in query_vars]

                # modify each one
                subqueries = []
                state_update_stm = inc.mutate_in_place(
                    lval,
                    lval,
                    op.body,
                    abstract_state=self.abstract_state,
                    assumptions=list(op.assumptions) + [EDeepIn(h, bag), EIn(h, modified_handles.ret)],
                    subgoals_out=subqueries)
                for sub_q in subqueries:
                    sub_q.docstring = "[{}] {}".format(op.name, sub_q.docstring)
                    state_update_stm = self._add_subquery(sub_q=sub_q, used_by=state_update_stm)
                if state_update_stm != SNoOp():
                    state_update_stm = SForEach(h, ECall(modified_handles.name, query_vars).with_type(bag.type), state_update_stm)
                    state_update_stm = self._add_subquery(sub_q=modified_handles, used_by=state_update_stm)
                self.handle_updates[(t, op.name)] = state_update_stm
예제 #12
0
파일: parsetools.py 프로젝트: uwplse/cozy
def multi(ldict, selfname, production, sep=None):
    """
    Usage:
        multi(locals(), NAME, P[, sep=SEP])
        where P and SEP are production names.

    This produces a production named NAME of the form

        NAME ::= empty | P (SEP P)*

    that produces tuples of whatever P produces.
    """

    if sep is None:
        sep = "empty"

    f1name = fresh_name("multisep")
    def f1(p):
        if len(p) > 2 and p[3]:
            p[0] = (p[1],) + p[3]
        else:
            p[0] = (p[1],)
    f1.__doc__ = (
        """{f1name} : {prod}
                    | {prod} {sep} {f1name}""".format(f1name=f1name, prod=production, sep=sep))
    f1.__name__ = "p_{}".format(f1name)
    ldict[f1.__name__] = f1

    def f2(p):
        if p[1]:
            p[0] = p[1]
        else:
            p[0] = ()
    f2.__doc__ = (
        """{self} : empty
                  | {f1name}""".format(self=selfname, f1name=f1name))
    f2.__name__ = "p_{}".format(selfname)
    ldict[f2.__name__] = f2
예제 #13
0
파일: java.py 프로젝트: wcphkust/cozy
 def visit_SForEach(self, for_each):
     x = for_each.loop_var
     iterable = for_each.iter
     body = for_each.body
     if not self.boxed and self.trovename(x.type) != "Object":
         iterable_src = self.visit(iterable)
         itname = fresh_name("iterator")
         self.write_stmt("gnu.trove.iterator.T{T}Iterator {it} = {iterable}.iterator();".format(
             it=itname,
             iterable=iterable_src,
             T=self.trovename(x.type)))
         self.begin_statement()
         self.write("while ({it}.hasNext()) ".format(it=itname))
         with self.block():
             self.declare(x, EEscape("{it}.next()".format(it=itname), (), ()).with_type(x.type))
             self.visit(body)
         self.end_statement()
         return
     iterable = self.visit(iterable)
     self.begin_statement()
     self.write("for (", self.visit(x.type, x.id), " : ", iterable, ") ")
     with self.block():
         self.visit(body)
     self.end_statement()
예제 #14
0
파일: cxx.py 프로젝트: uwplse/cozy
 def visit_SEscapableBlock(self, s):
     l = fresh_name("label")
     with extend(self.labels, s.label, l):
         self.visit(SScoped(s.body))
         self.write(l, ":\n")
예제 #15
0
 def fn(self, hint="var"):
     n = common.fresh_name(hint, omit=self.vars)
     self.vars.add(n)
     return n
예제 #16
0
 def visit_SEscapableBlock(self, s):
     l = fresh_name("label")
     with extend(self.labels, s.label, l):
         self.visit(SScoped(s.body))
         self.write(l, ":\n")
예제 #17
0
파일: library.py 프로젝트: sanidhya/cozy
 def update_key(self, m: Exp, k: Exp, v: EVar, change: Stm):
     idx = EVar(fresh_name("index")).with_type(TInt())
     return seq([
         SDecl(idx.id, self.to_index(k)),
         subst(change, {v.id: EVectorGet(m, idx)})
     ])
예제 #18
0
파일: library.py 프로젝트: sanidhya/cozy
 def __init__(self, t):
     super().__init__(t)
     self.next_ptr = fresh_name("next_ptr")
     self.prev_ptr = fresh_name("prev_ptr")
     self.null = ENull().with_type(self.rep_type())
예제 #19
0
    def implement_stmt(self, s: Stm, concretization_functions: {str:
                                                                Exp}) -> Stm:
        """Convert a call to a heap function into simpler statements.

        This function also requires the `concretization_functions` that
        describe the invariants for variables in `e`.
        """

        comparison_op = "<=" if isinstance(s.target.type, TMinHeap) else ">="
        f = heap_func(s.target, concretization_functions)
        if isinstance(s, SCall):
            elem_type = s.target.type.elem_type
            target_raw = EVar(s.target.id).with_type(
                self.rep_type(s.target.type))
            if s.func == "add_all":
                size = fresh_var(INT, "heap_size")
                i = fresh_var(INT, "i")
                x = fresh_var(elem_type, "x")
                return seq([
                    SDecl(size.id, s.args[0]),
                    SEnsureCapacity(
                        target_raw,
                        EBinOp(size, "+", ELen(s.args[1])).with_type(INT)),
                    SForEach(
                        x, s.args[1],
                        seq([
                            SAssign(EArrayGet(target_raw, size), x),
                            SDecl(i.id, size),
                            SWhile(
                                EAll([
                                    EBinOp(i, ">", ZERO).with_type(BOOL),
                                    ENot(
                                        EBinOp(
                                            f.apply_to(
                                                EArrayGet(
                                                    target_raw, _parent(i))),
                                            comparison_op,
                                            f.apply_to(EArrayGet(
                                                target_raw,
                                                i))).with_type(BOOL))
                                ]),
                                seq([
                                    SSwap(EArrayGet(target_raw, _parent(i)),
                                          EArrayGet(target_raw, i)),
                                    SAssign(i, _parent(i))
                                ])),
                            SAssign(size,
                                    EBinOp(size, "+", ONE).with_type(INT))
                        ]))
                ])
            elif s.func == "remove_all":
                size = fresh_var(INT, "heap_size")
                size_minus_one = EBinOp(size, "-", ONE).with_type(INT)
                i = fresh_var(INT, "i")
                x = fresh_var(elem_type, "x")
                label = fresh_name("stop_bubble_down")
                child_index = fresh_var(INT, "child_index")
                return seq([
                    SDecl(size.id, s.args[0]),
                    SForEach(
                        x,
                        s.args[1],
                        seq([
                            # find the element to remove
                            SDecl(i.id,
                                  EArrayIndexOf(target_raw, x).with_type(INT)),
                            # swap with last element in heap
                            SSwap(EArrayGet(target_raw, i),
                                  EArrayGet(target_raw, size_minus_one)),
                            # bubble down
                            SEscapableBlock(
                                label,
                                SWhile(
                                    _has_left_child(i, size_minus_one),
                                    seq([
                                        SDecl(child_index.id, _left_child(i)),
                                        SIf(
                                            EAll([
                                                _has_right_child(
                                                    i, size_minus_one),
                                                ENot(
                                                    EBinOp(
                                                        f.apply_to(
                                                            EArrayGet(
                                                                target_raw,
                                                                _left_child(
                                                                    i))),
                                                        comparison_op,
                                                        f.apply_to(
                                                            EArrayGet(
                                                                target_raw,
                                                                _right_child(
                                                                    i)))))
                                            ]),
                                            SAssign(child_index,
                                                    _right_child(i)), SNoOp()),
                                        SIf(
                                            ENot(
                                                EBinOp(
                                                    f.apply_to(
                                                        EArrayGet(
                                                            target_raw, i)),
                                                    comparison_op,
                                                    f.apply_to(
                                                        EArrayGet(
                                                            target_raw,
                                                            child_index)))),
                                            seq([
                                                SSwap(
                                                    EArrayGet(target_raw, i),
                                                    EArrayGet(
                                                        target_raw,
                                                        child_index)),
                                                SAssign(i, child_index)
                                            ]), SEscapeBlock(label))
                                    ]))),
                            # dec. size
                            SAssign(size, size_minus_one)
                        ]))
                ])
            else:
                raise ValueError("heaps do not support the function {}".format(
                    s.func))
        else:
            raise ValueError(
                "the statement {} is not an update to a heap variable".format(
                    pprint(s)))
예제 #20
0
파일: heaps.py 프로젝트: uwplse/cozy
    def implement_stmt(self, s : Stm, concretization_functions : { str : Exp }) -> Stm:
        """Convert a call to a heap function into simpler statements.

        This function also requires the `concretization_functions` that
        describe the invariants for variables in `e`.
        """

        comparison_op = "<=" if isinstance(s.target.type, TMinHeap) else ">="
        f = heap_func(s.target, concretization_functions)
        if isinstance(s, SCall):
            elem_type = s.target.type.elem_type
            target_raw = EVar(s.target.id).with_type(self.rep_type(s.target.type))
            target_len = ETupleGet(target_raw, 0).with_type(INT)
            target_array = ETupleGet(target_raw, 1).with_type(TArray(elem_type))
            if s.func == "add_all":
                size = fresh_var(INT, "heap_size")
                i = fresh_var(INT, "i")
                x = fresh_var(elem_type, "x")
                return seq([
                    SDecl(size, s.args[0]),
                    SEnsureCapacity(target_array, EBinOp(size, "+", ELen(s.args[1])).with_type(INT)),
                    SForEach(x, s.args[1], seq([
                        SAssign(target_len, EBinOp(target_len, "+", ONE).with_type(INT)),
                        SAssign(EArrayGet(target_array, size).with_type(elem_type), x),
                        SDecl(i, size),
                        SWhile(EAll([
                            EBinOp(i, ">", ZERO).with_type(BOOL),
                            ENot(EBinOp(f.apply_to(EArrayGet(target_array, _parent(i)).with_type(elem_type)), comparison_op, f.apply_to(EArrayGet(target_array, i).with_type(elem_type))).with_type(BOOL))]),
                            seq([
                                SSwap(EArrayGet(target_array, _parent(i)).with_type(elem_type), EArrayGet(target_array, i).with_type(elem_type)),
                                SAssign(i, _parent(i))])),
                        SAssign(size, EBinOp(size, "+", ONE).with_type(INT))]))])
            elif s.func == "remove_all":
                size = fresh_var(INT, "heap_size")
                size_minus_one = EBinOp(size, "-", ONE).with_type(INT)
                i = fresh_var(INT, "i")
                x = fresh_var(elem_type, "x")
                label = fresh_name("stop_bubble_down")
                child_index = fresh_var(INT, "child_index")
                return seq([
                    SDecl(size, s.args[0]),
                    SForEach(x, s.args[1], seq([
                        SAssign(target_len, EBinOp(target_len, "-", ONE).with_type(INT)),
                        # find the element to remove
                        SDecl(i, EArrayIndexOf(target_array, x).with_type(INT)),
                        # swap with last element in heap
                        SSwap(EArrayGet(target_array, i).with_type(elem_type), EArrayGet(target_array, size_minus_one).with_type(elem_type)),
                        # bubble down
                        SEscapableBlock(label, SWhile(_has_left_child(i, size_minus_one), seq([
                            SDecl(child_index, _left_child(i)),
                            SIf(EAll([_has_right_child(i, size_minus_one), ENot(EBinOp(f.apply_to(EArrayGet(target_array, _left_child(i)).with_type(elem_type)), comparison_op, f.apply_to(EArrayGet(target_array, _right_child(i)).with_type(elem_type))))]),
                                SAssign(child_index, _right_child(i)),
                                SNoOp()),
                            SIf(ENot(EBinOp(f.apply_to(EArrayGet(target_array, i).with_type(elem_type)), comparison_op, f.apply_to(EArrayGet(target_array, child_index).with_type(elem_type)))),
                                seq([
                                    SSwap(EArrayGet(target_array, i).with_type(elem_type), EArrayGet(target_array, child_index).with_type(elem_type)),
                                    SAssign(i, child_index)]),
                                SEscapeBlock(label))]))),
                        # dec. size
                        SAssign(size, size_minus_one)]))])
            elif s.func == "update":
                # TODO: implement this
                return SNoOp()
            else:
                raise ValueError("heaps do not support the function {}".format(s.func))
        else:
            raise ValueError("the statement {} is not an update to a heap variable".format(pprint(s)))
예제 #21
0
파일: cxx.py 프로젝트: sanidhya/cozy
 def visit_EBinOp(self, e, indent=""):
     op = e.op
     if op == "+" and (isinstance(e.e1.type, TBag)
                       or isinstance(e.e1.type, TSet)):
         raise NotImplementedError("adding collections: {}".format(e))
     elif op == "==":
         return self._eq(e.e1, e.e2, indent)
     elif op == BOp.In:
         if isinstance(e.e2.type, TSet):
             if type(e.e2.type) in (TSet, library.TNativeSet):
                 return self.test_set_containment_native(e.e2, e.e1, indent)
             else:
                 return self.visit(e.e2.type.contains(e.e1), indent)
         else:
             t = TBool()
             res = self.fv(t, "found")
             x = self.fv(e.e1.type, "x")
             label = fresh_name("label")
             setup = self.visit(
                 seq([
                     SDecl(res.id,
                           EBool(False).with_type(t)),
                     SEscapableBlock(
                         label,
                         SForEach(
                             x, e.e2,
                             SIf(
                                 EBinOp(x, "==", e.e1).with_type(BOOL),
                                 seq([
                                     SAssign(res,
                                             EBool(True).with_type(t)),
                                     SEscapeBlock(label)
                                 ]), SNoOp())))
                 ]), indent)
             return (setup, res.id)
     elif op == "-" and (isinstance(e.type, TBag) or isinstance(
             e.type, TList) or isinstance(e.type, TSet)):
         t = e.type
         if type(t) is TBag:
             t = library.TNativeList(t.t)
         v = self.fv(t, "v")
         x = self.fv(t.t, "x")
         stm = self.visit(SForEach(x, e.e2, SCall(v, "remove", [x])),
                          indent)
         return (
             "{}{};\n".format(indent, self.visit(v.type, v.id)) +
             self.visit(self.construct_concrete(v.type, e.e1, v), indent) +
             stm, v.id)
     elif op == BOp.Or:
         (s1, r1) = self.visit(e.e1, indent)
         (s2, r2) = self.visit(e.e2, indent)
         if s2:
             return self.visit(
                 ECond(e.e1, EBool(True), e.e2).with_type(TBool()), indent)
         else:
             return (s1, "({} || {})".format(r1, r2))
     elif op == BOp.And:
         (s1, r1) = self.visit(e.e1, indent)
         (s2, r2) = self.visit(e.e2, indent)
         if s2:
             return self.visit(
                 ECond(e.e1, e.e2, EBool(False)).with_type(TBool()), indent)
         else:
             return (s1, "({} && {})".format(r1, r2))
     ce1, e1 = self.visit(e.e1, indent)
     ce2, e2 = self.visit(e.e2, indent)
     return (ce1 + ce2, "({e1} {op} {e2})".format(e1=e1, op=op, e2=e2))
예제 #22
0
파일: cxx.py 프로젝트: sanidhya/cozy
 def visit_EUnaryOp(self, e, indent=""):
     op = e.op
     if op == UOp.The:
         return self.find_one(e.e, indent=indent)
     elif op == UOp.Sum:
         type = e.e.type.t
         res = self.fv(type, "sum")
         x = self.fv(type, "x")
         setup = self.visit(
             seq([
                 SDecl(res.id,
                       ENum(0).with_type(type)),
                 SForEach(x, e.e,
                          SAssign(res,
                                  EBinOp(res, "+", x).with_type(type)))
             ]), indent)
         return (setup, res.id)
     elif op == UOp.Length:
         arg = EVar("x").with_type(e.e.type.t)
         return self.visit(
             EUnaryOp(UOp.Sum,
                      EMap(e.e,
                           ELambda(arg,
                                   ONE)).with_type(INT_BAG)).with_type(INT),
             indent)
     elif op == UOp.All:
         arg = EVar("x").with_type(e.e.type.t)
         return self.visit(
             EUnaryOp(
                 UOp.Empty,
                 EFilter(e.e, ELambda(
                     arg, ENot(arg))).with_type(INT_BAG)).with_type(INT),
             indent)
     elif op == UOp.Any:
         arg = EVar("x").with_type(e.e.type.t)
         return self.visit(
             EUnaryOp(UOp.Exists,
                      EFilter(e.e, ELambda(
                          arg, arg)).with_type(INT_BAG)).with_type(INT),
             indent)
     elif op == UOp.Empty:
         iterable = e.e
         v = self.fv(BOOL, "v")
         label = fresh_name("label")
         x = self.fv(iterable.type.t, "x")
         decl = SDecl(v.id, T)
         find = SEscapableBlock(
             label,
             SForEach(x, iterable, seq([SAssign(v, F),
                                        SEscapeBlock(label)])))
         return (self.visit(seq([decl, find]), indent), v.id)
     elif op == UOp.Exists:
         return self.visit(ENot(EUnaryOp(UOp.Empty, e.e).with_type(BOOL)),
                           indent)
     elif op in ("-", UOp.Not):
         ce, ee = self.visit(e.e, indent)
         op_str = "!" if op == UOp.Not else str(op)
         return (ce, "({op}{ee})".format(op=op_str, ee=ee))
     elif op == UOp.Distinct:
         v = self.fv(e.type, "v")
         stm = self.construct_concrete(e.type, e, v)
         return ("{}{};\n".format(indent, self.visit(e.type, v.id)) +
                 self.visit(stm, indent), v.id)
     elif op == UOp.Reversed:
         v = self.fv(e.type, "v")
         stm = self.construct_concrete(e.type, e.e, v)
         stm = seq([stm, self.reverse_inplace(v)])
         return ("{}{};\n".format(indent, self.visit(e.type, v.id)) +
                 self.visit(stm, indent), v.id)
     else:
         raise NotImplementedError(op)
예제 #23
0
파일: cxx.py 프로젝트: sanidhya/cozy
 def visit_ENative(self, e, indent):
     assert e.e == ENum(0)
     v = fresh_name("tmp")
     decl = self.visit(e.type, v)
     return ("{}{};\n".format(indent, decl), v)
예제 #24
0
 def visit_EUnaryOp(self, e):
     op = e.op
     if op == UOp.The:
         return self.find_one(e.e)
     elif op == UOp.Sum:
         type = e.e.type.t
         res = self.fv(type, "sum")
         x = self.fv(type, "x")
         self.visit(
             seq([
                 SDecl(res.id,
                       ENum(0).with_type(type)),
                 SForEach(x, e.e,
                          SAssign(res,
                                  EBinOp(res, "+", x).with_type(type)))
             ]))
         return res.id
     elif op == UOp.Length:
         arg = EVar("x").with_type(e.e.type.t)
         return self.visit(
             EUnaryOp(UOp.Sum,
                      EMap(e.e,
                           ELambda(arg,
                                   ONE)).with_type(INT_BAG)).with_type(INT))
     elif op == UOp.All:
         arg = EVar("x").with_type(e.e.type.t)
         return self.visit(
             EUnaryOp(
                 UOp.Empty,
                 EFilter(e.e, ELambda(
                     arg, ENot(arg))).with_type(INT_BAG)).with_type(INT))
     elif op == UOp.Any:
         arg = EVar("x").with_type(e.e.type.t)
         return self.visit(
             EUnaryOp(UOp.Exists,
                      EFilter(e.e, ELambda(
                          arg, arg)).with_type(INT_BAG)).with_type(INT))
     elif op == UOp.Empty:
         iterable = e.e
         v = self.fv(BOOL, "v")
         label = fresh_name("label")
         x = self.fv(iterable.type.t, "x")
         decl = SDecl(v.id, T)
         find = SEscapableBlock(
             label,
             SForEach(x, iterable, seq([SAssign(v, F),
                                        SEscapeBlock(label)])))
         self.visit(seq([decl, find]))
         return v.id
     elif op == UOp.Exists:
         return self.visit(ENot(EUnaryOp(UOp.Empty, e.e).with_type(BOOL)))
     elif op in ("-", UOp.Not):
         ee = self.visit(e.e)
         op_str = "!" if op == UOp.Not else op
         return "({op}({ee}))".format(op=op_str, ee=ee)
     elif op == UOp.Distinct:
         v = self.fv(e.type, "v")
         self.declare(v, e)
         return v.id
     elif op == UOp.AreUnique:
         s = self.fv(TSet(e.e.type.t), "unique_elems")
         u = self.fv(BOOL, "is_unique")
         x = self.fv(e.e.type.t)
         label = fresh_name("label")
         self.visit(
             seq([
                 SDecl(s.id,
                       EEmptyList().with_type(s.type)),
                 SDecl(u.id, T),
                 SEscapableBlock(
                     label,
                     SForEach(
                         x, e.e,
                         SIf(
                             EEscape("{s}.find({x}) != {s}.end()",
                                     ("s", "x"), (s, x)).with_type(BOOL),
                             seq([SAssign(u, F),
                                  SEscapeBlock(label)]),
                             SEscape("{indent}{s}.insert({x});\n",
                                     ("s", "x"), (s, x)))))
             ]))
         return u.id
     elif op == UOp.Reversed:
         v = self.fv(e.type, "v")
         self.declare(v, e.e)
         self.visit(self.reverse_inplace(v))
         return v.id
     else:
         raise NotImplementedError(op)
예제 #25
0
파일: cxx.py 프로젝트: uwplse/cozy
 def fn(self, hint="var"):
     n = common.fresh_name(hint, omit=self.vars)
     self.vars.add(n)
     return n
예제 #26
0
def EIsSingleton(e):
    arg = EVar(fresh_name()).with_type(e.type.elem_type)
    return EBinOp(EUnaryOp(UOp.Sum, EMap(e, ELambda(arg, ONE)).with_type(TBag(INT))).with_type(INT), "<=", ONE).with_type(BOOL)
예제 #27
0
파일: impls.py 프로젝트: sanidhya/cozy
    def code(self) -> Spec:

        state_read_by_query = {
            query_name: free_vars(query)
            for query_name, query in self.query_impls.items()
        }

        def queries_used_by(stm):
            for e in all_exps(stm):
                if isinstance(e, ECall) and e.func in [
                        q.name for q in self.query_specs
                ]:
                    yield e.func

        # prevent read-after-write by lifting reads before writes.

        # list of SDecls
        temps = defaultdict(list)
        updates = dict(self.updates)

        for operator in self.op_specs:
            # Compute order constraints between statements:
            #   v1 -> v2 means that the update code for v1 should (if possible)
            #   appear before the update code for v2
            #   (i.e. the update code for v1 reads v2)
            g = igraph.Graph().as_directed()
            g.add_vertices(len(self.concrete_state))
            for (i, (v1, _)) in enumerate(self.concrete_state):
                v1_update_code = self.updates[(v1, operator.name)]
                v1_queries = list(queries_used_by(v1_update_code))
                for (j, (v2, _)) in enumerate(self.concrete_state):
                    # if v1_update_code reads v2...
                    if any(v2 in state_read_by_query[q] for q in v1_queries):
                        # then v1->v2
                        g.add_edges([(i, j)])

            # Find the minimum set of edges we need to break (see "feedback arc
            # set problem")
            edges_to_break = safe_feedback_arc_set(g, method="ip")
            g.delete_edges(edges_to_break)
            ordered_concrete_state = [
                self.concrete_state[i]
                for i in g.topological_sorting(mode="OUT")
            ]

            # Lift auxiliary declarations as needed
            things_updated = []
            for v, _ in ordered_concrete_state:
                things_updated.append(v)
                stm = updates[(v, operator.name)]

                for e in all_exps(stm):
                    if isinstance(e, ECall) and e.func in [
                            q.name for q in self.query_specs
                    ]:
                        problems = set(things_updated) & state_read_by_query[
                            e.func]

                        if problems:
                            name = fresh_name()
                            temps[operator.name].append(SDecl(name, e))
                            stm = replace(stm, e, EVar(name).with_type(e.type))
                            updates[(v, operator.name)] = stm

        # construct new op implementations
        new_ops = []
        for op in self.op_specs:

            stms = [updates[(v, op.name)] for (v, _) in ordered_concrete_state]
            stms.extend(hup
                        for ((t, op_name), hup) in self.handle_updates.items()
                        if op.name == op_name)
            new_stms = seq(temps[op.name] + stms)
            new_ops.append(Op(op.name, op.args, [], new_stms, op.docstring))

        # assemble final result
        return Spec(self.spec.name, self.spec.types, self.spec.extern_funcs,
                    [(v.id, e.type) for (v, e) in self.concrete_state], [],
                    list(self.query_impls.values()) + new_ops,
                    self.spec.header, self.spec.footer, self.spec.docstring)