Esempio n. 1
0
 def mksymbol(literal):
     if literal == 'true': return True
     if literal == 'false': return False
     try:
         return signature_vars[literal]
     except KeyError:
         return Identifier(literal, '?')
Esempio n. 2
0
class MainLoop(
        collections.namedtuple("MainLoop", "prologue cond body epilogue")):

    SEMI = Identifier(";", '?')
    SKIP = Identifier("skip", '?')
    BAD = "~ite(cond, wp_ae(loopBody,true), wp_ae(epilogue, post))"

    @classmethod
    def factor_loop(cls, program):
        stmts = program.split(";")
        for i, stmt in enumerate(stmts):
            if stmt.root == "while":
                cond, _, body = stmt.subtrees
                return cls(prologue=stmts[:i],
                           cond=cond,
                           body=body,
                           epilogue=stmts[i + 1:])
        return None

    @classmethod
    def locate_loop(cls, expansion):
        [program] = expansion("program")
        if program.subtrees:
            l = cls.factor_loop(program)
            if l: return l
        [cond] = expansion("cond")
        [body] = expansion("loopBody")
        return cls(prologue=[], cond=cond, body=body, epilogue=[])

    def redefine(self, synopsis):
        """
        Defines macros 'cond', 'loopBody', 'epilogue', and 'bad' in the environment.
        """
        stmts = lambda x: FolFormula.join(self.SEMI, x, self.SKIP)
        delta = synopsis.expansion.delta
        delta.transformers += [
            DeltaReduction.Transformer(delta, name, params=[], body=expr)
            for name, expr in [("cond", self.cond), (
                "loopBody", self.body), ("epilogue", stmts(self.epilogue))]
        ]

        if not any(
                getattr(t, 'head', None) == "bad" for t in delta.transformers):
            bad = synopsis.expansion.parser * self.BAD
            delta.transformers += [
                DeltaReduction.Transformer(delta, "bad", params=[], body=bad)
            ]
Esempio n. 3
0
class FolRegister(object):

    UNDEF = Identifier("?", 'predicate')

    def __init__(self, subset_of_symbols):
        self.symbols = subset_of_symbols

    def blur(self, phi):
        reg = self
        s = self.symbols

        class FormulaWalk(RichTreeWalk.Visitor):
            def enter(self, subtree, prune=lambda: None):
                r = subtree.root
                if isinstance(r, Identifier) and \
                     r.kind in ['function', 'predicate'] and r not in reg.symbols:
                    prune()
                    return reg.UNDEF
                else:
                    return r

            def join(self, node, prefix, infix, postfix):
                known = [a for a in infix if a.root != reg.UNDEF]
                if len(known) == len(infix):
                    return type(node)(prefix, known)
                elif prefix == FolFormula.AND and len(known) == 1:
                    return known[0]
                else:
                    return type(node)(reg.UNDEF)

            def done(self, root, final):
                return final

        if isinstance(phi, FolFormula):
            return RichTreeWalk(FormulaWalk())(phi)
        elif isinstance(phi, FolTheory):
            sig = self.blur(phi.signature)
            t = (y for y in (self.blur(x) for x in phi)
                 if y.root != self.UNDEF)
            return FolTheory(t).with_signature(sig)
        elif isinstance(phi, FolManySortSignature):
            return FolManySortSignature([(f, a)
                                         for f, a in phi.funcs if f in s],
                                        [(p, a)
                                         for p, a in phi.preds if p in s],
                                        self.blur(phi.sorts))
        elif isinstance(phi, FolSignature):
            return FolSignature([(f, a) for f, a in phi.funcs if f in s],
                                [(p, a) for p, a in phi.preds if p in s])
        elif isinstance(phi, FolSorts):
            return FolSorts(self.blur(phi.sorts))
        elif isinstance(phi, FolStructure):
            return FolStructure(domain=phi.domain,
                                interpretation=self.blur(phi.interpretation))
        elif isinstance(phi, dict):
            return dict(
                (sym, v) for sym, v in phi.iteritems() if sym in self.symbols)
        else:
            raise TypeError, phi
Esempio n. 4
0
    def _past_tense(consts, type_decls):
        consts0 = []
        for p in consts:
            p0 = Identifier('%s0' % p, p.kind)
            type_decls.sorts[p0] = type_decls.sorts[p][:]
            consts0 += [p0]

        return consts0
Esempio n. 5
0
 def _get_free_var(self, var):
     i = get_var_index(var)
     if i in self.vars:
         return self.vars[i].identifier
     else:
         self.vars[i] = v = self.Var(Identifier("$%d" % i, 'variable'),
                                     var.sort())
         return v.identifier
Esempio n. 6
0
 def signature(self):
     """
     Extracts a first-order sorted signature describing the type of
     the structure.
     """
     sorts = FolSorts()
     for name, (args, ret, _) in self.funcs.iteritems():
         # ~ symbols with '!' are reserved for compiler-generated aux
         if not "!" in name:
             nameid = Identifier(
                 name, '?')  # 'kind' will be filled by FolManySortSignature
             argtypes = [
                 Identifier(a.subtrees[0].root, 'sort') for a in args
             ]
             rettype = Identifier(ret.root, 'sort')
             if rettype == 'bool': rettype = ''
             sorts[nameid] = [FolSorts.FunctionType(argtypes, rettype)]
     return FolManySortSignature.from_sorts(sorts)
Esempio n. 7
0
def generate_order_and_sorting_properties(syn, vocab):
    sorted_templ = FolScheme(syn * "sorted(ivlco([?u],[?v],n*))")
    null = Identifier('null', 'function')
    a = AbstractionProperties.from_named_formulas(
        [('sorted%s%s' % (u, v), sorted_templ(u, v)) for u in vocab.consts
         for v in [null]], vocab)
    #a.props += generate_binary_properties_from_template\
    #        (FolScheme(syn * "R([?u],[?v])"), vocab.consts)
    return a
Esempio n. 8
0
 def lookup(self, literal):
     for sig in self.signatures:
         for symbol in sig.itersymbols():
             if symbol == literal or \
                     isinstance(symbol, Identifier) and \
                     symbol.mnemonic == literal:
                 return symbol
     else:
         return Identifier.promote(literal)
Esempio n. 9
0
def generate_named_properties(name_property_list, type_decls):
    named_axioms = []

    for name, property_formula in name_property_list:
        p = Identifier(name, 'predicate')
        type_decls.sorts[p] = [((), '')]
        axiom = FolFormula(FolFormula.IFF, [FolFormula(p), property_formula])
        named_axioms += [(p, axiom)]

    return named_axioms
Esempio n. 10
0
 def escaping(t):
     if t not in FolFormula.INFIXES and t not in [
             FolFormula.FORALL, FolFormula.EXISTS, FolFormula.NOT
     ]:
         if not (isinstance(t, Identifier)
                 and isinstance(t.literal, (int, float))):
             u = unicode(t)
             if not idre.match(u):
                 t = Identifier(u'[%s]' % u, '?')
     return t
Esempio n. 11
0
    def gen_uniq(self, sym):
        hist = self.histogram

        g = self.assigned.get(sym)
        if g is not None: return g
        literal = sym.literal
        hist[literal] = i = hist[literal] + 1
        ssc = '$%s' % i
        #ssc = self.num_sscript(i)
        self.assigned[sym] = g = Identifier(literal + ssc, sym.kind)
        return g
Esempio n. 12
0
 def _quantify_forall(self, t):
     vars0 = [
         self.Var(Identifier(t.var_name(i), 'variable'), None)
         for i in reversed(xrange(t.num_vars()))
     ]
     body = self.with_some_vars(vars0)(t.body())
     phi = body
     for v in vars0:
         phi = FolFormula(FolFormula.FORALL,
                          [FolFormula(v.identifier), phi])
     return phi
Esempio n. 13
0
class FolFormula(Tree):

    Identifier = Identifier

    AND = Identifier(u"∧", 'connective')
    OR = Identifier(u"∨", 'connective')
    NOT = Identifier(u"¬", 'connective')
    IMPLIES = Identifier(u"➝", 'connective')
    IFF = Identifier(u"↔", 'connective')
    FORALL = Identifier(u"∀", 'quantifier')
    EXISTS = Identifier(u"∃", 'quantifier')

    TRUE = Identifier(True, 'predicate')
    FALSE = Identifier(False, 'predicate')

    INFIXES = [
        IMPLIES, IFF, AND, OR, "=", "<", "<=", ">", ">=", "!=", u"≠", u"≤",
        u"≥", u"∈", u"∉", "+", "-", "*", "/", "^"
    ]

    LEFT = "LEFT"
    RIGHT = "RIGHT"
    ASSOC = "ASSOC"

    PREC = {
        AND: (1, ASSOC),
        OR: (2, ASSOC),
        IMPLIES: (3, RIGHT),
        IFF: (3, RIGHT)
    }

    def __unicode__(self):
        if self.root in [self.FORALL, self.EXISTS] and len(self.subtrees) == 2:
            return u"%s%r (%r)" % ((self.root, ) + tuple(self.subtrees))
        elif self.root in self.INFIXES and len(self.subtrees) == 2:
            p = lambda x, pos, r=self.root: self._parenthesize(r, x, pos)
            return u"%s %s %s" % (p(self.subtrees[0], self.LEFT), self.root,
                                  p(self.subtrees[1], self.RIGHT))
        elif isinstance(self.root, RepresentationForm):
            return self.root.repr(self.subtrees)
        elif isinstance(self.root, Identifier):
            if len(self.subtrees) == 0:
                return unicode(self.root)
            else:
                subreprs = u", ".join( ` x ` for x in self.subtrees)
                return u"%s(%s)" % (self.root, subreprs)
Esempio n. 14
0
 def xform(self, phi):
     if phi.root == 'fresh' and phi.subtrees:
         symbols = phi.subtrees[:-1]
         if any(x.subtrees for x in symbols):
             raise ValueError, "invalid fresh symbols '%s'" % symbols
         symbols = [x.root for x in symbols]
         phi = phi.subtrees[-1]
         newscope = AlphaRenaming.NS()
         return TreeNodeRename({
             k: Identifier(k.literal, k.kind, k.mnemonic, ns=newscope)
             for k in symbols
         })(phi)
Esempio n. 15
0
 def _ident(self, tok, arity):
     """ Creates an identifier from a given token. """
     if isinstance(tok, Identifier):
         return tok
     elif any(isinstance(tok, t) for t in self.native_types):
         return Identifier(tok, 'function')
     try:
         return self.OPERATOR_MAP[tok]
     except KeyError:
         try:
             return self.OPERATOR_MAP[(tok, arity)]
         except KeyError:
             return self.lookup(tok)
Esempio n. 16
0
def display_invariant(inv, abs_props):
    z3g = Z3Gate()
    fol_inv = z3g.formula_back(inv)
    bnd = [t.subtrees[0] for t in fol_inv.nodes if t.root.kind == 'quantifier']
    subst = {
        v: FolFormula(Identifier("x%d" % i, 'variable'))
        for i, v in enumerate(bnd)
    }
    subst.update(abs_props.defs)
    fol_inv = FolSubstitution(subst)(fol_inv)
    print " - " * 20
    print fol_inv
    print " - " * 20
Esempio n. 17
0
 def __call__(self, t):
     if is_var(t):
         return FolFormula(self._get_free_var(t))
     elif is_true(t) or is_false(t):
         return FolFormula(is_true(t))
     elif is_const(t):
         kind = 'predicate' if is_bool(t) else 'function'
         return FolFormula(Identifier(unicode(t), kind))
     elif is_quantifier(t) and t.is_forall():
         return self._quantify_forall(t)
     elif is_app(t):
         r = t.decl()
         for k, v in self.o.map_ops.iteritems():
             if is_app_of(t, k):
                 r = v
                 break
         else:
             r = Identifier(unicode(r), '?')
         if callable(r):
             return r([self(x) for x in t.children()])
         else:
             return FolFormula(r, [self(x) for x in t.children()])
     else:
         raise NotImplementedError
Esempio n. 18
0
    def __call__(self, z3_elements):
        sorts = FolSorts()
        decls = {}
        for z3_symbol in z3_elements:
            idf = Identifier(z3_symbol.name(), self._get_kind(z3_symbol))
            decls[idf] = z3_symbol
            if is_const(z3_symbol):
                sorts[idf] = FolSorts.FunctionType((), z3_symbol.sort())
            elif is_func_decl(z3_symbol):
                z3_domains = [
                    z3_symbol.domain(i) for i in xrange(z3_symbol.arity())
                ]
                z3_range = z3_symbol.range()
                sorts[idf] = FolSorts.FunctionType(tuple(z3_domains), z3_range)

        sigma = FolManySortSignature.from_sorts(sorts)
        sigma.z3_decls = decls
        return sigma
Esempio n. 19
0
    class Signature:
        eq = Identifier('=', 'predicate')
        neq = Identifier(u'≠', 'predicate')

        formal = FolSignature([], [(eq, 2), (neq, 2)])
Esempio n. 20
0
 def p_tagged_leaf(self, p):
     """atom : TAG IDENTIFIER
             | TAG ESCAPED_SYMBOL
     """
     p[0] = Tree(Identifier.promote(p[2], kind=p[1]))
Esempio n. 21
0
 class _:
     u = Identifier('u', 'function')
     v = Identifier('v', 'function')
     w = Identifier('w', 'function')
     R = Identifier('R', 'predicate')
     sorts = FolSorts({u: u'→V', v: u'→V', w: u'→V', R: u'V×V→'})
Esempio n. 22
0
 def prime(self):
     prime = lambda x: Identifier("%s'" % x.literal, x.kind)
     vocab_prime = TwoVocabulary()
     vocab_prime.locals = [(x, prime(x)) for _, x in self.locals]
     return vocab_prime
Esempio n. 23
0
 def p_tagged_func_leaf(self, p):
     """atom : FUNCTION_TAG IDENTIFIER
             | FUNCTION_TAG ESCAPED_SYMBOL
     """
     p[0] = Tree(Identifier.promote(p[2], kind='function'))
Esempio n. 24
0
def generate_gamma(syn, preds, decls):
    dtca = Identifier('dtca', '?')
    starred = [z for z in preds if '*' in z.literal]
    gamma = FolFormula.conjunction(
        [FolFormula(dtca, [FolFormula(z)]) for z in starred])
    return generate_z3_condition(gamma, syn, decls)
Esempio n. 25
0
 def unescape_identifier(s):
     return Identifier(self.naming.unescape(s.literal), s.kind, s.ns)
Esempio n. 26
0
                 if y.root != self.UNDEF)
            return FolTheory(t).with_signature(sig)
        elif isinstance(phi, FolManySortSignature):
            return FolManySortSignature([(f, a)
                                         for f, a in phi.funcs if f in s],
                                        [(p, a)
                                         for p, a in phi.preds if p in s],
                                        self.blur(phi.sorts))
        elif isinstance(phi, FolSignature):
            return FolSignature([(f, a) for f, a in phi.funcs if f in s],
                                [(p, a) for p, a in phi.preds if p in s])
        elif isinstance(phi, FolSorts):
            return FolSorts(self.blur(phi.sorts))
        elif isinstance(phi, FolStructure):
            return FolStructure(domain=phi.domain,
                                interpretation=self.blur(phi.interpretation))
        elif isinstance(phi, dict):
            return dict(
                (sym, v) for sym, v in phi.iteritems() if sym in self.symbols)
        else:
            raise TypeError, phi


if __name__ == '__main__':
    from logic.fol import FolSymbolic
    p = lambda x: Identifier(x, 'predicate')
    f = lambda x: Identifier(x, 'function')
    L = FolSymbolic.Language().with_(a=p('a'), b=f('b'), c=f('c'), d=f('d'))
    phi = L * "(a(b,c,d) | a(b,c,c)) & a(b,b,c)"
    print phi
    print FolRegister(set([p('a'), f('b'), f('c')])).blur(phi)
Esempio n. 27
0
from pattern.collection.basics import OneToOne
from logic.fol.semantics.graphs import AlgebraicStructureGraphTool

from z3support.adapter import Z3ModelToFolStructure, Z3FormulaToFolFormula
from mini_bmc import BMC
from logic.fol.syntax.transform.delta import DeltaReduction

#------------------------------------------------------------------------------#
#  Declarations
#

impSort = V = DeclareSort('V')
n = Function('n*', V, V, BoolSort())
n0 = Function('n*0', V, V, BoolSort())
n_prime = Function('n*@', V, V, BoolSort())
eqrel = Identifier('eqrel', 'macro')
eqpred = Identifier('eqpred', 'macro')


def nPlus(x, y):
    return And(x != y, n(x, y))


#
#------------------------------------------------------------------------------#


class Z3Gate(object):
    def __init__(self):
        self.z3_sort_map = OneToOne({
            'bool': BoolSort(),
Esempio n. 28
0
 def singl(self, t):   return FolFormula(Identifier((t.subtrees[0] if t.subtrees else t).root.token.value, '?'))
 def qua(self, t):     return FolFormula(self.PRIM[t.subtrees[0].root.token.value], [self.singl(t.subtrees[1]), t.subtrees[3]])
 def __call__(self, program):
     wps = WeakestPreSynthesis()    
     wps.configure(detptr_libraries())
     wps.syn.libs += [self.VC] #TODO - change        
     
     formulas , decls  =  wps_formula_get(wps,program)
     
     I_args = inv_args_get(wps, "I")
     
     formula = FolFormula.conjunction(formulas)
         
     prefix           =  wp_forall_prefix_get(formula)| set([Identifier('null', 'const')])
     bounded_prefix   =  AuxTransformers.get_all_bound_vars(formula)
     prefix-=bounded_prefix
     
     
     pprint( formulas )
     print  prefix
     
     
             
     z3_formulas_with_blasting = []    
 
     from shape2horn import hoist_forall
     from shape2horn import blast_horn
     from shape2horn import hoist_horn
     formulas_with_implies = []
     ackm_bools            = {}
     ackm_bools_to_vars    = {}
     
     #sanity = FormulaSanity()
             
     watch = Stopwatch()
     with watch:
             
         for f in formulas:
             
             if f.root == 'true':                    
                 continue 
             
             head    = f.subtrees[1]        
             body    = f.subtrees[0]
             head_ls = FolFormula.split(head) #splits conjunctions in head
             
             for i in head_ls:
                 #creates new formulas of form: body -> i
                 f_with_implies = create_f_with_implies(body,i)            
                 formulas_with_implies.append( f_with_implies )
                             
         for s in formulas_with_implies:
             print '--------   Input Clause   ----------------'
             print s      
             s_with_gamma = gamma_add( s )
             #renumber_bound_vars() renames bounded vars to unique numbers
             s_with_gamma = AuxTransformers.renumber_bound_vars( s_with_gamma )        
             print s_with_gamma                             
             z3_f = transform_formula_to_z3(prefix, s_with_gamma, decls)
             for f in hoist_horn(z3_f[0]):
                z3_f_hoisted = hoist_forall(f)
             		
                print '--------  Hoisted Formula  ------------------'
                print z3_f_hoisted
                blasted_f  =  blast_horn(z3_f_hoisted)
             
                print '--------  Blasted Formula  ---------------------'             
                #print blasted_f
                if 0:                        
                   blasted_f_with_replaced_n = replace_nstar_with_bools( blasted_f, \
                                                  decls, ackm_bools, ackm_bools_to_vars )            
                   f_with_ackm_reduction = ackerman_reduction_get( \
                                         blasted_f_with_replaced_n , ackm_bools_to_vars )
                #print ackm_bools_to_vars            
                z3_formulas_with_blasting.append( blasted_f )
         
         #benchmark_print_to_file(h, z3_formulas_with_blasting)            
         formulas_solver ( self, z3_formulas_with_blasting, decls["I"], I_args )
     
     print 'Total sovling time: ',watch.total_time,'sec'
Esempio n. 30
0
class FolSymbolic(Tree, promote.SimplisticPromoteMixIn):
    """
    Provides syntactic sugar for building first-order formulas.
    There are two recommended usage forms:
    1. Define variables of type FolSymbolic, each representing a single
       symbol (variable, function, predicate), then compose them using
       operators {~, &, |, >>, %, **, //}, and eventually call .to_formula().
       e.g.
       a = FolSymbolic(Identifier('a', 'predicate'))
       u = FolSymbolic(Identifier('u', 'variable'))
       phi = (u ** (a(u) >> ~a(u))).to_formula()
    2. Define a lambda function with arguments each representing a symbol
       (variable, function, predicate) and performing logical operations on
       them using {~, &, |, >>, %, **, //}; then call .formula(...).
       e.g.
       sig = {'a': Identifier('a', 'predicate'), 
              'u': Identifier('u', 'predicate')}
       phi = FolSymbolic(lambda a,u: u ** (a(u) >> ~a(u)))
    
    ~  stands for logical not (¬)
    &  stands for logical and (∧)
    |  stands for logical or (∨)
    >> stands for implication (➝)
    %  stands for if-and-only-if (↔)
    ** stands for universal quantification (∀)
    // stands for existential quantification (∃)
    """

    SUGAR = {
        '~': FolFormula.NOT,
        '&': FolFormula.AND,
        '|': FolFormula.OR,
        '>>': FolFormula.IMPLIES,
        '%': FolFormula.IFF,
        '**': FolFormula.FORALL,
        '//': FolFormula.EXISTS
    }
    VECTOR = Identifier(u"◦⃗", "macro")

    def __invert__(self):
        return type(self)('~', [self])

    def __and__(self, other):
        return type(self)('&', [self, other])

    def __or__(self, other):
        return type(self)('|', [self, other])

    def __rshift__(self, other):
        return type(self)('>>', [self, other])

    def __mod__(self, other):
        return type(self)('%', [self, other])

    def __pow__(self, other):
        return type(self)('**', [self, other])

    def __floordiv__(self, other):
        return type(self)('//', [self, other])

    def __sub__(self, operator):
        if isinstance(operator, FolSymbolic):
            operator = operator.root
        if isinstance(operator, Callable):
            return type(self)(operator(self.root), self.subtrees)
        else:
            return NotImplemented

    def __call__(self, *args):
        if self.subtrees:
            raise SyntaxError, "invalid use of () after '%r'" % self
        elif isinstance(self.root, Identifier):
            return type(self)(self.root, [
                x if isinstance(x, FolSymbolic) else FolSymbolic(x)
                for x in args
            ])
        else:
            return type(self)(
                self.root(*((x.root if isinstance(x, FolSymbolic) else x)
                            for x in args)))

    def __getitem__(self, subscript):
        if isinstance(self.root, (Sequence, Mapping)):
            return type(self)(self.root[subscript])
        else:
            return NotImplemented

    def build(self, root, subtrees):
        return type(self)(root, [self.promote(x) for x in subtrees])

    def with_identifiers(self, identifiers):
        self.identifiers = identifiers
        return self

    def to_formula(self):
        r = self.root
        if isinstance(r, FolFormula):
            return r
        elif isinstance(r, list):
            r = [isinstance(x, FolFormula) and x or FolFormula(x) for x in r]
            return FolFormula(self.VECTOR, r)
        else:
            formula = FolFormula(self.SUGAR.get(r, r),
                                 [sub.to_formula() for sub in self.subtrees])
            return self.expand_vectors(formula)

    def expand_vectors(self, formula):
        root = formula.root
        subtrees = formula.subtrees
        if root in [FolFormula.FORALL, FolFormula.EXISTS
                    ] and subtrees[0].root == self.VECTOR:
            formula = reduce(lambda x, y: FolFormula(root, [y, x]),
                             reversed(subtrees[0].subtrees), subtrees[1])
        elif isinstance(root, Identifier) and root.kind != "connective":
            flatten = [
                x for s in subtrees
                for x in (s.root != self.VECTOR and [s] or s.subtrees)
            ]
            formula = FolFormula(root, flatten)
        elif root == self.VECTOR:
            raise ValueError, "a vector is not allowed here: '%s'" % formula

        formula = FolFormula(
            formula.root, [self.expand_vectors(x) for x in formula.subtrees])
        return formula

    @classmethod
    def construct(cls, lambda_expr, signature_vars={}):
        import inspect  #@UnresolvedImport
        if isinstance(lambda_expr, str) or isinstance(lambda_expr, unicode):
            lambda_expr = flam(lambda_expr)
        symbols, _, _, _ = inspect.getargspec(lambda_expr)

        def mksymbol(literal):
            if literal == 'true': return True
            if literal == 'false': return False
            try:
                return signature_vars[literal]
            except KeyError:
                return Identifier(literal, '?')

        ids = [mksymbol(s) for s in symbols]
        ids_genuine = [i for i in ids if isinstance(i, Identifier)]
        id_args = tuple(cls(i) for i in ids)
        retval = lambda_expr(*id_args)
        return cls.promote(retval).with_identifiers(ids_genuine)

    @classmethod
    def formula(cls, lambda_expr, signature_vars={}):
        return cls.construct(lambda_expr, signature_vars).to_formula()

    class Language(object):
        """
        Just a bit of syntactic sugar to avoid too much repetition in programs
        where there are lots of formulas.
        """
        def __init__(self, signatures=[]):
            if not isinstance(signatures, collections.Sequence):
                signatures = [signatures]
            self.signatures = []
            for sig in signatures:
                if hasattr(sig, '__bases__'):
                    ex = [c for c in oop.all_ur_base(sig) if c is not object]
                else:
                    ex = [new.classobj('Signature', (), {'formal': sig})]
                self.signatures.extend(ex)
            self.dict = {}
            self.FolSymbolic = FolSymbolic
            for signature in reversed(self.signatures):
                self.dict.update(signature.__dict__)

        def with_(self, **kw):
            c = copy.copy(self)
            c.dict = copy.copy(c.dict)
            c.dict.update(kw)
            return c

        def with_sugar(self, *sugars):
            """
            Combines the functionality of one or more FolSymbolic mix-ins,
            for use in the syntax of formulas processed by this language.
            """
            bases = (CovertOps, ) + sugars + (self.FolSymbolic, )
            self.FolSymbolic = new.classobj('FolSymbolic+', bases,
                                            {'_': self.signatures[0]})
            return self

        @property
        def signature(self):
            return reduce(lambda x, y: x | y,
                          (s.formal
                           for s in self.signatures if hasattr(s, 'formal')))

        def formula(self, expr):
            return self.FolSymbolic.formula(expr, self.dict)

        def __mul__(self, expr):
            if isinstance(expr, list):
                from logic.fol.syntax.theory import FolTheory
                return FolTheory(self.formula(el) for el in expr)\
                        .with_signature(self.signature)
            else:
                return self.formula(expr)