示例#1
0
 def __init__(self,
              ctx: SynthCtx,
              state: [EVar],
              assumptions: [Exp],
              q: Query,
              k,
              hints: [Exp] = [],
              freebies: [Exp] = [],
              ops: [Op] = [],
              funcs: {str: TFunc} = {}):
     assert all(
         v in state for v in free_vars(q)
     ), "Oops, query looks malformed due to {}:\n{}\nfree_vars({})".format(
         [v for v in free_vars(q) if v not in state], pprint(q), repr(q))
     super().__init__()
     self.ctx = ctx
     self.state = state
     self.assumptions = assumptions
     q = shallow_copy(q)
     q.ret = wrap_naked_statevars(q.ret, OrderedSet(state))
     self.q = q
     self.hints = hints
     self.freebies = freebies
     self.ops = ops
     self.k = k
     self.funcs = OrderedDict(funcs)
示例#2
0
    def codegen(self, e: Exp, concretization_functions: {str: Exp},
                out: EVar) -> Stm:
        """Return statements that write the result of `e` to `out`.

        The returned statements must declare the variable `out`; it will not be
        declared by the caller.

        This function also requires the `concretization_functions` that
        describe the invariants for variables in `e`.
        """
        if isinstance(e, EMakeMinTreeMultiset) or isinstance(
                e, EMakeMaxTreeMultiset):
            assert out.type == self.rep_type(e.type)
            extended_concretization_functions = dict(concretization_functions)
            extended_concretization_functions[out.id] = e
            dummy_out = EVar(out.id).with_type(e.type)
            return seq([
                SDecl(out, None),
                self.implement_stmt(SCall(dummy_out, "add_all", (e.e, )),
                                    extended_concretization_functions)
            ])
        elif isinstance(e, ETreeMultisetElems):
            elem_type = e.type.elem_type
            x = fresh_var(elem_type, "x")
            from cozy.syntax_tools import shallow_copy
            xs = shallow_copy(e.e).replace_type(e.type)
            return seq([
                SDecl(out,
                      EEmptyList().with_type(out.type)),
                SForEach(x, xs, SCall(out, "add", (x, )))
            ])
        elif isinstance(e, ETreeMultisetPeek):
            return SDecl(out, e)
        else:
            raise NotImplementedError(e)
示例#3
0
 def visit_SDecl(self, s):
     var = s.var
     assert isinstance(var, EVar)
     if not hasattr(var, "type"):
         # This should not be necessary, but it guards against sloppiness
         # elsewhere.
         var = shallow_copy(var).with_type(s.val.type)
     return self.declare(var, s.val)
示例#4
0
def add_implicit_handle_assumptions(spec : Spec) -> Spec:
    """
    At the start of every method, for all reachable handles (i.e. those stored
    on the data structure plus those in arguments):
        If two different handles have the same address, then they have the same
        value.
    """
    spec = shallow_copy(spec)
    new_methods = []
    for m in spec.methods:
        handles = reachable_handles_at_method(spec, m)
        new_assumptions = implicit_handle_assumptions_for_method(handles, m)
        m = shallow_copy(m)
        m.assumptions = list(m.assumptions) + new_assumptions
        new_methods.append(m)
    spec.methods = new_methods
    return spec
示例#5
0
    def _add_subquery(self, sub_q : Query, used_by : Stm) -> Stm:
        with task("adding query", query=sub_q.name):
            sub_q = shallow_copy(sub_q)
            with task("checking whether we need more handle assumptions"):
                new_a = implicit_handle_assumptions_for_method(
                    reachable_handles_at_method(self.spec, sub_q),
                    sub_q)
                if not valid(EImplies(EAll(sub_q.assumptions), EAll(new_a))):
                    event("we do!")
                    sub_q.assumptions = list(itertools.chain(sub_q.assumptions, new_a))

            with task("simplifying"):
                orig_a = sub_q.assumptions
                orig_a_size = sum(a.size() for a in sub_q.assumptions)
                orig_ret_size = sub_q.ret.size()
                sub_q.assumptions = tuple(simplify_or_ignore(a) for a in sub_q.assumptions)
                sub_q.ret = simplify(sub_q.ret)
                a_size = sum(a.size() for a in sub_q.assumptions)
                ret_size = sub_q.ret.size()
                event("|assumptions|: {} -> {}".format(orig_a_size, a_size))
                event("|ret|: {} -> {}".format(orig_ret_size, ret_size))

                if a_size > orig_a_size:
                    print("NO, BAD SIMPLIFICATION")
                    print("original")
                    for a in orig_a:
                        print(" - {}".format(pprint(a)))
                    print("simplified")
                    for a in sub_q.assumptions:
                        print(" - {}".format(pprint(a)))
                    assert False

            state_vars = self.abstract_state
            funcs = self.extern_funcs
            qq = find_one(self.query_specs, lambda qq: dedup_queries.value and queries_equivalent(qq, sub_q, state_vars=state_vars, extern_funcs=funcs))
            if qq is not None:
                event("subgoal {} is equivalent to {}".format(sub_q.name, qq.name))
                arg_reorder = [[x[0] for x in sub_q.args].index(a) for (a, t) in qq.args]
                class Repl(BottomUpRewriter):
                    def visit_ECall(self, e):
                        args = tuple(self.visit(a) for a in e.args)
                        if e.func == sub_q.name:
                            args = tuple(args[idx] for idx in arg_reorder)
                            return ECall(qq.name, args).with_type(e.type)
                        else:
                            return ECall(e.func, args).with_type(e.type)
                used_by = Repl().visit(used_by)
            else:
                self.add_query(sub_q)
            return used_by
示例#6
0
文件: library.py 项目: sanidhya/cozy
 def implement_add(self, target, args):
     assert target.type == self
     target = shallow_copy(target).with_type(self.rep_type())
     new_elem, = args
     return seq([
         SAssign(
             EGetField(new_elem, self.next_ptr).with_type(self.t), target),
         SAssign(
             EGetField(new_elem, self.prev_ptr).with_type(self.t),
             self.null),
         SIf(
             ENot(equal(target, self.null)),
             SAssign(
                 EGetField(target, self.prev_ptr).with_type(self.t),
                 new_elem), SNoOp()),
         SAssign(target, new_elem)
     ])
示例#7
0
文件: library.py 项目: sanidhya/cozy
 def construct_concrete(self, e: Exp, out: Exp):
     assert out.type == self, "{} : {}".format(pprint(e), pprint(e.type))
     out = shallow_copy(out).with_type(self.rep_type())
     assert isinstance(e, EMakeMap2)  # TODO?
     k = fresh_var(self.k, "k")
     return seq([
         SAssign(
             EVectorGet(out,
                        ENum(i).with_type(INT)).with_type(self.v),
             construct_value(self.v)) for (i, k) in enumerate(self.all_keys)
     ] + [
         SForEach(
             k, e.e,
             SAssign(
                 EVectorGet(out, k).with_type(self.v),
                 ELet(k, e.value).with_type(self.v)))
     ])
示例#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 __init__(self,
              ctx: SynthCtx,
              state: [EVar],
              assumptions: [Exp],
              q: Query,
              k,
              hints: [Exp] = [],
              examples: [dict] = None):
     super().__init__()
     self.ctx = ctx
     self.state = state
     self.assumptions = assumptions
     self.q = shallow_copy(q)
     assert all(
         v in state for v in free_vars(q)
     ), "Oops, query looks malformed due to {}:\n{}\nfree_vars({})".format(
         [v for v in free_vars(q) if v not in state], pprint(q), repr(q))
     q.ret = wrap_naked_statevars(q.ret, OrderedSet(state))
     self.hints = hints
     self.examples = examples
     self.k = k
示例#10
0
文件: library.py 项目: sanidhya/cozy
 def implement_remove(self, target, args):
     assert target.type == self
     target = shallow_copy(target).with_type(self.rep_type())
     elem, = args
     prev = EGetField(elem, self.prev_ptr).with_type(self.t)
     next = EGetField(elem, self.next_ptr).with_type(self.t)
     return seq([
         SIf(equal(elem, target), SAssign(target, next), SNoOp()),
         SIf(
             ENot(equal(prev, self.null)),
             SAssign(
                 EGetField(prev, self.next_ptr).with_type(self.t), next),
             SNoOp()),
         SIf(
             ENot(equal(next, self.null)),
             SAssign(
                 EGetField(next, self.prev_ptr).with_type(self.t), prev),
             SNoOp()),
         SAssign(next, self.null),
         SAssign(prev, self.null)
     ])
示例#11
0
 def __init__(self,
              state: [EVar],
              assumptions: [Exp],
              q: Query,
              context: Context,
              solutions_q,
              hints: [Exp] = [],
              freebies: [Exp] = [],
              ops: [Op] = [],
              improve_count=None):
     super().__init__()
     self.state = state
     self.assumptions = assumptions
     q = shallow_copy(q)
     q.ret = wrap_naked_statevars(q.ret, OrderedSet(state))
     self.q = q
     self.context = context
     self.hints = hints
     self.freebies = freebies
     self.ops = ops
     self.solutions_q = solutions_q
     self.improve_count = improve_count
示例#12
0
文件: library.py 项目: sanidhya/cozy
 def construct_concrete(self, e: Exp, out: Exp):
     print(pprint(e))
     if self == out.type:
         out = shallow_copy(out).with_type(self.rep_type())
     x = fresh_var(self.t, "x")
     return seq([
         SAssign(out, self.null),
         SForEach(
             x, e,
             seq([
                 SAssign(
                     EGetField(x, self.next_ptr).with_type(self.t), out),
                 SAssign(
                     EGetField(x, self.prev_ptr).with_type(self.t),
                     self.null),
                 SIf(
                     ENot(equal(out, self.null)),
                     SAssign(
                         EGetField(out, self.prev_ptr).with_type(self.t),
                         x), SNoOp()),
                 SAssign(out, x)
             ]))
     ])
示例#13
0
文件: impls.py 项目: sanidhya/cozy
    def _add_subquery(self, sub_q: Query, used_by: Stm) -> Stm:
        print("Adding new query {}...".format(sub_q.name))
        # orig_ret = sub_q.ret
        # print("rewritng ret for {}".format(pprint(orig_ret)))
        sub_q = shallow_copy(sub_q)
        sub_q.assumptions += tuple(
            implicit_handle_assumptions_for_method(
                reachable_handles_at_method(self.spec, sub_q), sub_q))
        sub_q.ret = simplify(sub_q.ret)
        # sub_q = rewrite_ret(sub_q, simplify)
        # if sub_q.ret != orig_ret:
        #     print("rewrote ret")
        #     print(" --> {}".format(pprint(sub_q.ret)))

        qq = find_one(
            self.query_specs,
            lambda qq: dedup_queries.value and queries_equivalent(qq, sub_q))
        if qq is not None:
            print("########### subgoal {} is equivalent to {}".format(
                sub_q.name, qq.name))
            arg_reorder = [[x[0] for x in sub_q.args].index(a)
                           for (a, t) in qq.args]

            class Repl(BottomUpRewriter):
                def visit_ECall(self, e):
                    args = tuple(self.visit(a) for a in e.args)
                    if e.func == sub_q.name:
                        args = tuple(args[idx] for idx in arg_reorder)
                        return ECall(qq.name, args).with_type(e.type)
                    else:
                        return ECall(e.func, args).with_type(e.type)

            used_by = Repl().visit(used_by)
        else:
            self.add_query(sub_q)
        return used_by
示例#14
0
    def _add_subquery(self, sub_q: Query, used_by: Stm) -> Stm:
        """Add a query that helps maintain some other state.

        Parameters:
            sub_q - the specification of the helper query
            used_by - the statement that calls `sub_q`

        If a query already exists that is equivalent to `sub_q`, this method
        returns `used_by` rewritten to use the existing query and does not add
        the query to the implementation.  Otherwise it returns `used_by`
        unchanged.
        """

        with task("adding query", query=sub_q.name):
            sub_q = shallow_copy(sub_q)
            with task("checking whether we need more handle assumptions"):
                new_a = implicit_handle_assumptions(
                    reachable_handles_at_method(self.spec, sub_q))
                if not valid(EImplies(EAll(sub_q.assumptions), EAll(new_a))):
                    event("we do!")
                    sub_q.assumptions = list(
                        itertools.chain(sub_q.assumptions, new_a))

            with task("repairing state var boundaries"):
                extra_available_state = [
                    e for v, e in self._concretization_functions
                ]
                sub_q.ret = repair_well_formedness(
                    strip_EStateVar(sub_q.ret), self.context_for_method(sub_q),
                    extra_available_state)

            with task("simplifying"):
                orig_a = sub_q.assumptions
                orig_a_size = sum(a.size() for a in sub_q.assumptions)
                orig_ret_size = sub_q.ret.size()
                sub_q.assumptions = tuple(
                    simplify_or_ignore(a) for a in sub_q.assumptions)
                sub_q.ret = simplify(sub_q.ret)
                a_size = sum(a.size() for a in sub_q.assumptions)
                ret_size = sub_q.ret.size()
                event("|assumptions|: {} -> {}".format(orig_a_size, a_size))
                event("|ret|: {} -> {}".format(orig_ret_size, ret_size))

                if a_size > orig_a_size:
                    print("NO, BAD SIMPLIFICATION")
                    print("original")
                    for a in orig_a:
                        print(" - {}".format(pprint(a)))
                    print("simplified")
                    for a in sub_q.assumptions:
                        print(" - {}".format(pprint(a)))
                    assert False

            state_vars = self.abstract_state
            funcs = self.extern_funcs
            qq = find_one(
                self.query_specs, lambda qq: dedup_queries.value and
                queries_equivalent(qq,
                                   sub_q,
                                   state_vars=state_vars,
                                   extern_funcs=funcs,
                                   assumptions=EAll(self.abstract_invariants)))
            if qq is not None:
                event("subgoal {} is equivalent to {}".format(
                    sub_q.name, qq.name))
                arg_reorder = [[x[0] for x in sub_q.args].index(a)
                               for (a, t) in qq.args]

                class Repl(BottomUpRewriter):
                    def visit_ECall(self, e):
                        args = tuple(self.visit(a) for a in e.args)
                        if e.func == sub_q.name:
                            args = tuple(args[idx] for idx in arg_reorder)
                            return ECall(qq.name, args).with_type(e.type)
                        else:
                            return ECall(e.func, args).with_type(e.type)

                used_by = Repl().visit(used_by)
            else:
                self.add_query(sub_q)
            return used_by
示例#15
0
文件: library.py 项目: sanidhya/cozy
 def find_one(self, target):
     print("finding one {} : {}".format(pprint(target),
                                        pprint(target.type)))
     assert target.type == self
     target = shallow_copy(target).with_type(self.rep_type())
     return target