예제 #1
0
    def _rename_terms_over(self, phi, variable):
        ns = AlphaRenaming.NS()
        new_names = BidirectionalDict(
            {FolFormula(variable): FolFormula(variable)})

        def _scan(t):
            if t.root != '=':
                return type(t)(t.root, [_collect(x) or x for x in t.subtrees])

        def _collect(t):
            if t.root.kind == 'function':
                try:
                    t_prime = new_names.get_backwards(t)
                    return t_prime
                except KeyError:
                    if t.subtrees and all(
                            new_names.has_key(x) for x in t.subtrees):
                        c = FolFormula(
                            Identifier(u"β%d" % len(new_names),
                                       'variable',
                                       ns=ns))
                        new_names[c] = t
                        return c

        return TreeTransform([_scan],
                             dir=TreeTransform.BOTTOM_UP)(phi), new_names
예제 #2
0
 def _xform_toplevel(self, phi, constants, quantifier_context):
     for c in constants:
         phi, new_names = self._rename_terms_over(phi, c)
         del new_names[FolFormula(c)]
         phi = self._add_quantifier_prefix(phi, quantifier_context,
                                           new_names)
     return phi
예제 #3
0
 def xform(t):
     if not self.unnest.is_fine(t):
         raise ValueError, "nested term not allowed; in '%s'" % t
     r, s = t.root, t.subtrees
     s = sorted(s, key=lambda x: len(x.subtrees), reverse=True)
     if r == EQ and len(s) == 2 and s[0].root in self.funcs:
         if s[1].root in self.funcs:
             _ = FolFormula
             gamma = Identifier(u'γ', 'variable', ns=AlphaRenaming.NS())
             if (quantifier_type, t.context_sign) in [(_.FORALL, "+"),
                                                      (_.EXISTS, "-")]:
                 quantifier, connective = _.FORALL, _.IMPLIES
             elif (quantifier_type, t.context_sign) in [(_.FORALL, "-"),
                                                        (_.EXISTS, "+")
                                                        ]:
                 quantifier, connective = _.EXISTS, _.AND
             else:
                 raise ValueError, "invalid quantifier context %s" % (
                     (quantifier_type, t.context_sign), )
             return _(quantifier, [
                 _(gamma),
                 _(connective, [
                     _(self._rel(s[0].root),
                       s[0].subtrees + [_(gamma)]),
                     _(self._rel(s[1].root), s[1].subtrees + [_(gamma)])
                 ])
             ])
         else:
             return FolFormula(self._rel(s[0].root),
                               s[0].subtrees + s[1:])
예제 #4
0
 def __call__(self, t, e=None):
     """
     Modifies lemmas such that they have totality antecedents at the 
     beginning for global constants and then again for every universally
     quantified variable.
     """
     simpl = self._simplify
     ar = AlphaRenaming()
     if t.root == 'lemma' and len(t.subtrees) == 1:
         phi = simpl(t.subtrees[0])
         phi = self.unnest(phi, self.constants, FolFormula.FORALL)
         totc = self.construct_totality()
         relt = self.replace_equalities_with_atomic(
             self.relativize_quantifiers(phi),
             quantifier_type=FolFormula.EXISTS)
         phi = FolFormula(FolFormula.IMPLIES, [totc, relt])
         phi = FolFormula.conjunction(ar(conj) for conj in phi.split())
         return simpl(FolFormula(t.root, [phi]))
     else:
         phi = simpl(t)
         # @todo resolve cyclic dependency
         from eprv.synopsis.proof import CheckQuantifierAlternation
         if not CheckQuantifierAlternation().is_universal(phi):
             raise ValueError, "axioms must be universal; this one isn't: '%s'" % phi
         phi = self.unnest(phi, self.constants, FolFormula.FORALL)
         phi = simpl(
             self.replace_equalities_with_atomic(
                 phi, quantifier_type=FolFormula.FORALL))
         phi = FolFormula.conjunction(ar(conj) for conj in phi.split())
         return phi
예제 #5
0
    def __call__(self, program_text, compose_prefix=''):
        ast = self.parser(program_text)
        astf = ApplyTo(nodes=Identifier.promote).inplace(
            FolFormula.reconstruct(ast))
        if compose_prefix:
            for n in astf.nodes:
                if n.subtrees:
                    n.root = Identifier(compose_prefix + n.root.literal,
                                        'macro')

        return astf
예제 #6
0
 def _collect(t):
     if t.root.kind == 'function':
         try:
             t_prime = new_names.get_backwards(t)
             return t_prime
         except KeyError:
             if t.subtrees and all(
                     new_names.has_key(x) for x in t.subtrees):
                 c = FolFormula(
                     Identifier(u"β%d" % len(new_names),
                                'variable',
                                ns=ns))
                 new_names[c] = t
                 return c
예제 #7
0
class TypeDeclarations(FolManySortSignature):

    COLON_SEP = [':']
    FUNC_SEP = [u"→", '->', FolFormula.IMPLIES]
    PARAM_SEP = [u"×", FolIntegerArithmetic.mul, "*"]
    EMPTY_MARKER = [FolFormula(Identifier("", '?'))]

    def to_sorts(self, phi):
        if not isinstance(phi,
                          FolFormula) or phi.root not in self.COLON_SEP or len(
                              phi.subtrees) != 2:
            raise ValueError, "expected a declaration, found '%s'" % phi
        name, typename = phi.subtrees
        if not name.subtrees:
            name = name.root
        else:
            raise ValueError, "expected atomic identifier, found '%s' (in declaration '%s')" % (
                name, phi)
        if typename.root in self.FUNC_SEP:
            if len(typename.subtrees) == 2:
                left, right = typename.subtrees
            else:
                raise ValueError, "invalid usage of '%s' (in declaration '%s')" % (
                    self.FUNC_SEP[0], phi)
        else:
            left, right = self.EMPTY_MARKER, typename
        from_ = () if left == self.EMPTY_MARKER else map(
            self._typename, left.split(self.PARAM_SEP))
        to_ = '' if right == self.EMPTY_MARKER or right.root == "bool" else self._typename(
            right)
        return FolSorts({name: FolSorts.FunctionType(from_, to_)})

    def _typename(self, term):
        if term.subtrees:
            raise NotImplementedError, "Non-atomic type '%s'" % term
        return term.root

    def is_declaration(self, phi):
        return isinstance(phi, FolFormula) and phi.root in self.COLON_SEP

    def read_from(self, formulas):
        if not isinstance(formulas, (list, set, tuple)):
            formulas = (formulas, )
        for phi in formulas:
            self |= self.from_sorts(self.to_sorts(phi))
        return self
예제 #8
0
 def xform(t):
     r, s = t.root, t.subtrees
     if r == 'disable-relativization':
         return FolFormula.conjunction(s)
     elif r.kind == 'quantifier' and t.context_sign == '--':
         return None  # skip relativization for this quantifier (disable-relativization)
     elif r.kind == 'quantifier' and (u'β' in s[0].root.literal
                                      or u'γ' in s[0].root.literal):
         return None
     elif r == FolFormula.FORALL and t.context_sign == '+':
         return gen_tot(t, r, s, FolFormula.IMPLIES)
     elif r == FolFormula.EXISTS and t.context_sign == '-':
         return gen_tot(t, r, s, FolFormula.AND)
     elif r in [FolFormula.FORALL, FolFormula.EXISTS
                ] and t.context_sign == '+-':
         raise NotImplementedError, "ambiguous context for quantifier: '%s'" % (
             t, )
예제 #9
0
 def __mul__(self, line_of_text):
     """
     Quickly parse, expand, and return result as FolFormula.
     """
     return FolFormula.conjunction(self.expansion(line_of_text))
예제 #10
0
 def assumptions(self, t, collect=[]):
     if t.root == 'provided':
         collect += t.subtrees
         return FolFormula(FolFormula.TRUE)
예제 #11
0
 def obligations(self, t, collect=[]):
     if t.root == 'valid':
         collect += [
             type(t)(Identifier('lemma', '?'), [x]) for x in t.subtrees
         ]
         return FolFormula(FolFormula.TRUE)
예제 #12
0
 def _img(self, f, x, ns=None):
     f = self.BracketedModifier(f, 'modifier')
     return Identifier(FolFormula(f, [FolFormula(x)]), 'function', ns=ns)
예제 #13
0
    # Demo AST deserialization
    w = WhileFrontend.WhileASTDeserialize()
    print w(unicode(astf))

    print w(";{x:=y{i,j},y:=x.n{k,i},x.n:=y{i,i}}")
    print w(
        ";{;{x:=y{i,h},x:=null{j},x:=null{t},while {((i != null) & (t = null)), I, skip}}}"
    )
    raise SystemExit

    astf = fe("k:=i.n ; i.n:=j; j:=i; i:=k", 'wp ')
    astf = fe(
        "( if $C( i )$ then ( t := i.n ; j.n := null ; j.n := t ) else j := i ) ; i := i.n",
        'wp ')

    astf.subtrees += [FolFormula.promote("Q")]

    def compose_xform(t):
        import copy
        r, s = t.root, t.subtrees
        a = len(s)
        if r == 'wp ;' and a == 3:
            c1 = copy.deepcopy(s[0])
            c2 = copy.deepcopy(s[1])
            c2.subtrees += [s[2]]
            c1.subtrees += [c2]
            return c1
        if r == 'wp if' and a == 4:
            ct, ce = copy.deepcopy(s[1]), copy.deepcopy(s[2])
            ct.subtrees += [s[3]]
            ce.subtrees += [s[3]]