boole/elaboration/elab.py
def sub_mvar(expr, undef=None):
    """Replace all meta-variables by their
    value in a term.
    
    Arguments:
    - `undef`: if this flag is set to True,
    fail on unresolved meta-vars.
    """
    return SubMvar(undef=undef).visit(expr)
boole/semantics/value.py
class Value(object):
    """The class of semantic values
    
    Arguments:
    - `pyval`: a python value
    - `desc`: a boole expression that, together with the pyval,
    gives a description of the object in question
    - `is_num`: a boolean, indicates that pyval supports numeric operations
    """

    def __init__(self, pyval=None, desc=None, is_num=False):
        """Creats the object
        """
        self.pyval = pyval
        self.desc = desc
        self._is_num = is_num
        
    # TODO: what should the string method do? For now, just take the Python
    # object
    def __str__(self):
        return str(self.pyval)
    
    def is_num(self):
        return self._is_num
boole/core/expr.py
def subst_expr(exprs, expr, is_open=None):
    """Instantiate DB indices in expr according
    to expr_list
    
    Arguments:
    - `expr_list`: a list of expressions
    - `expr`: an expression
    """
    if is_open != None:
        subster = SubstExpr(exprs, is_open=is_open)
    else:
        subster = SubstExpr(exprs)
    return subster.visit(expr, 0)
boole/core/expr.py
class Sub(Expr):
    """The subtype relation. Makes sense regardless
    of the type of the expressions.
    """
    
    def __init__(self, lhs, rhs):
        """
        
        Arguments:
        - `lhs`: an expression
        - `rhs`: an expression
        """
        Expr.__init__(self)
        self.lhs = lhs
        self.rhs = rhs
        self._hash = hash(("Sub", self.lhs, self.rhs))

    def accept(self, visitor, *args, **kwargs):
        """The accept method allows the definition of
        recursive functions over objects of type expr.
        
        Arguments:
        - `visitor`: an object of class ExprVisitor
        - `*args`: arguments to the visitor instance
        - `**kwargs`: named arguments to the visitor instance
        """
        return visitor.visit_sub(self, *args, **kwargs)

    def to_string(self):
        """
        
        Arguments:
        - `self`:
        """
        return "Sub({0!s}, {1!s})".format(self.lhs, self.rhs)

    def is_sub(self):
        return True

    def eq(self, expr):
        """Structural equality.
        
        Arguments:
        - `expr`: an expression
        """
        if expr.is_sub():
            return (self.lhs.equals(expr.lhs)) and (self.rhs.equals(expr.rhs))
        else:
            return False
boole/core/expr.py
def root_app(expr):
    """Returns the pair (r, args)
    such that expr = r(*args)
    
    Arguments:
    - `expr`: an expression
    """
    root = expr
    args = []
    while root.is_app():
        args.append(root.arg)
        root = root.fun
        #The arguments were collected in reverse order
    args.reverse()
    return (root, args)
boole/core/expr.py
def root_clause(expr):
    """Returns r such that expr is of the form
    forall(x1,...,forall(xn, p1 >= (p2 >= ... (pm >= r))))
    replacing xi with fresh variables
    
    Arguments:
    - `expr`: an expression
    """
    root = expr
    while root.is_forall():
        _, root = open_bound_fresh(root)
    while is_impl(root):
        root = arg_i(root, 1)
    return root
boole/core/expr.py
class Pair(Expr):
    """Elements of Sigma types. They need to carry around their type,
    for type-checking to be decidable.
    """
    
    def __init__(self, fst, snd, type):
        """
        
        Arguments:
        - `fst`: an expression denoting the first component
        - `snd`: an expression denoting the second component
        - `type`: an expression
        """
        Expr.__init__(self)
        self.fst = fst
        self.snd = snd
        self.type = type
        self._hash = hash(("Pair", self.type, self.fst, self.snd))

    def accept(self, visitor, *args, **kwargs):
        """The accept method allows the definition of
        recursive functions over objects of type expr.
        
        Arguments:
        - `visitor`: an object of class ExprVisitor
        - `*args`: arguments to the visitor instance
        - `**kwargs`: named arguments to the visitor instance
        """
        return visitor.visit_pair(self, *args, **kwargs)

    def to_string(self):
        return "Pair({0!s},{1!s},{2!s})".\
               format(self.fst, self.snd, self.type)
        
    def is_pair(self):
        return True

    def eq(self, expr):
        """Structural equality.
        
        Arguments:
        - `expr`: an expression
        """
        if expr.is_pair():
            return self.fst.equals(expr.fst) and \
                   self.snd.equals(expr.snd) and \
                   self.type.equals(expr.type)
        else:
            return False
boole/core/expr.py
def root_pi(expr):
    """Returns the pair (r, [an,..,a0])
    such that expr = Pi(a0, Pi(.. Pi(an, r)..)
    
    Arguments:
    - `expr`: an expression
    """
    root = expr
    args = []
    while root.is_pi():
        args.append(root.dom)
        _, root = open_bound_fresh(root)
    return (root, args)
boole/core/expr.py
class Fst(Expr):
    """First projection for Sigma types
    """
    
    def __init__(self, expr):
        """
        
        Arguments:
        - `expr`: the expression to which is applied the projection.
        """
        Expr.__init__(self)
        self.expr = expr
        self._hash = hash(("Fst", self.expr))
    
    def accept(self, visitor, *args, **kwargs):
        """The accept method allows the definition of
        recursive functions over objects of type expr.
        
        Arguments:
        - `visitor`: an object of class ExprVisitor
        - `*args`: arguments to the visitor instance
        - `**kwargs`: named arguments to the visitor instance
        """
        return visitor.visit_fst(self, *args, **kwargs)

    def to_string(self):
        """
        
        Arguments:
        - `self`:
        """
        return "Fst({0!s})".format(self.expr)

    def is_fst(self):
        return True

    def equals(self, expr):
        """Structural equality.
        
        Arguments:
        - `expr`: an expression
        """
        if expr.is_fst():
            return self.expr.equals(expr.expr)
        else:
            return False
boole/core/expr.py
class Snd(Expr):
    """Second projection for Sigma types
    """
    
    def __init__(self, expr):
        """
        
        Arguments:
        - `expr`: the expression to which is applied the projection.
        """
        Expr.__init__(self)
        self.expr = expr
        self._hash = hash(("Snd", self.expr))
    
    def accept(self, visitor, *args, **kwargs):
        """The accept method allows the definition of
        recursive functions over objects of type expr.
        
        Arguments:
        - `visitor`: an object of class ExprVisitor
        - `*args`: arguments to the visitor instance
        - `**kwargs`: named arguments to the visitor instance
        """
        return visitor.visit_snd(self, *args, **kwargs)

    def to_string(self):
        """
        
        Arguments:
        - `self`:
        """
        return "Snd({0!s})".format(self.expr)

    def is_snd(self):
        return True

    def eq(self, expr):
        """Structural equality.
        
        Arguments:
        - `expr`: an expression
        """
        if expr.is_snd():
            return self.expr.equals(expr.expr)
        else:
            return False
boole/core/expr.py
class Box(Expr):
    """Boxed epressions: a boxed expression
    carries a an expression, a type and a witness that the type of
    the expression is a subtype of the given type.
    """
    
    def __init__(self, conv, expr, type):
        """
        
        Arguments:
        - `conv`: A witness to the equality between the type
        of expr and type
        - `expr`: The expression denoted by the box
        - `type`: The type assigned to expr
        """
        Expr.__init__(self)
        self.conv = conv
        self.expr = expr
        self.type = type
        self._hash = hash(("Box", self.expr))

    def accept(self, visitor, *args, **kwargs):
        """The accept method allows the definition of
        recursive functions over objects of type expr.
        
        Arguments:
        - `visitor`: an object of class ExprVisitor
        - `*args`: arguments to the visitor instance
        - `**kwargs`: named arguments to the visitor instance
        """
        return visitor.visit_box(self, *args, **kwargs)

    def to_string(self):
        return "Box({0!s},{1!s},{2!s})".format(self.conv, self.expr, self.type)

    def is_box(self):
        return True

    def eq(self, expr):
        """Structural equality.
        
        Arguments:
        - `expr`: an expression
        """
        if expr.is_box():
            return self.expr.equals(expr.expr)
        else:
            return False
boole/elaboration/elab.py
def mvar_infer(expr, ctxt=None):
    """Infer the type of an expression and return the pair
    (type, proof obligations) or raise an exception of type
    ExprTypeError.
    
    Arguments:
    - `expr`: an expression
    """
    if ctxt == None:
        ty_ctxt_name = meta_var_gen.get_name('_unif_ctxt')
        ty_ctxt = context.Context(ty_ctxt_name)
    else:
        ty_ctxt = ctxt
    prf_obl_name = meta_var_gen.get_name('_unif_goals')
    prf_obl = goals.empty_goals(prf_obl_name, ty_ctxt)
    ty = t.ExprInfer().visit(expr, prf_obl)
    return (ty, prf_obl)
boole/elaboration/elab.py
def app_expr(f, f_ty, cast, args):
    """Applies a function to a list of
    arguments, some of which are implicit.
    
    Arguments:
    - `f`: an expression denoting the function
    - `f_ty`: the function type
    - `cast`: list of evidence terms for the type conversions
    of each argument
    - `args`: a list of arguments
    """
    tm = f
    rem_args = args
    rem_cast = cast
    rem_ty = f_ty

    #TODO: This is a bit of a hack. We need "maximally inserted arguments"
    #as in Coq to do this cleanly
    if len(args) == 0:
        while rem_ty.is_pi()\
              and rem_ty.info.implicit:
            mvar = mk_meta(rem_ty.binder.var, rem_ty.dom)
            #At this point we give the trivial evidence.
            #after the term is created, we go through the whole
            #term to collect local information (variables) and to add them
            #the evidence term
            mcast = trivial()
            tm = t.App(mcast, tm, mvar)
            rem_ty = e.subst_expr([mvar], rem_ty.body)
    else:
        while len(rem_args) != 0:
            if rem_ty.is_pi()\
               and rem_ty.info.implicit:
                mvar = mk_meta(rem_ty.binder.var, rem_ty.dom)
                mcast = trivial()
                tm = t.App(mcast, tm, mvar)
                rem_ty = e.subst_expr([mvar], rem_ty.body)
            elif rem_ty.is_pi():
                tm = t.App(rem_cast[0], tm, rem_args[0])
                rem_ty = e.subst_expr([rem_args[0]], rem_ty.body)
                rem_cast = rem_cast[1:]
                rem_args = rem_args[1:]
            else:
                #In this case, something is wrong with the type
                #of f, and we simply blindly apply all the remaining
                #arguments.
                tm = t.App(rem_cast[0], tm, rem_args[0])
                rem_cast = rem_cast[1:]
                rem_args = rem_args[1:]
    return tm
boole/core/expr.py
class Const(Expr):
    """A constant declaration. Variables
    and constants are identified.
    """

    def __init__(self, name, type, value=None, **kwargs):
        """
        
        Arguments:
        - `name`: A name representing the constant
        - `type`: an expression representing its type
        - `value`: possibly a semantic value, making this an interpreted
        constant
        """
        Expr.__init__(self)
        self.name = name
        self.type = type
        self.value = value
        for k in kwargs:
            self.info[k] = kwargs[k]
        self._hash = hash(('Const', self.name, self.type))

    def accept(self, visitor, *args, **kwargs):
        """The accept method allows the definition of
        recursive functions over objects of type expr.
        
        Arguments:
        - `visitor`: an object of class ExprVisitor
        - `*args`: arguments to the visitor instance
        - `**kwargs`: named arguments to the visitor instance
        """
        return visitor.visit_const(self, *args, **kwargs)

    def to_string(self):
        return self.name

    def is_const(self):
        return True

    def eq(self, expr):
        """Structural equality. Simply compares names.
        
        Arguments:
        - `expr`: an expression
        """
        if expr.is_const():
            return self.name == expr.name
        else:
            return False


Question: from boole.core.info import *
from boole.core.context import *
from boole.core.expr import Const, Sub, Pair, Fst, Snd, Box, root_app, \
  root_clause, root_pi, subst_expr
from boole.elaboration.color import *
from boole.elaboration.elab import app_expr, mvar_infer, sub_mvar
from boole.semantics.value import Value
from config import current_ctxt, push_ctxt
import boole.core.expr as e
import boole.core.typing as typing
import elab as elab_tools
import boole.core.tactics as tac
import unif as u
import boole.semantics.value as v
import config as conf
import boole.user_conf as user_conf


def print_bool():
    return color.green + "Bool" + color.reset


def print_type():
    return color.green + "Type" + color.reset


def print_ev(expr):
    if len(expr.tele) == 0:
        return color.cyan + "triv()" + color.reset
    else:
        return expr.to_string()


def typ_str(expr):
    if expr.is_const():
        return print_const(expr)
    if expr.is_app():
        return print_app(expr)
    elif expr.is_pi():
        return print_pi(expr)
    elif expr.is_sig():
        return print_sig(expr)
    elif expr.is_sub():
        return print_sub(expr)
    elif expr.is_bool():
        return print_bool()
    elif expr.is_type():
        return print_type()
    else:
        return expr.to_string()


binder_utf_name = {
    'pi': color.purple + 'Π' + color.reset,
    'sig': color.purple + 'Σ' + color.reset,
    'abst': color.purple + 'λ' + color.reset,
    'forall': color.purple + '∀' + color.reset,
    'exists': color.purple + '∃' + color.reset
    }


def print_bound(expr):
    b = expr.binder
    vars, body = e.open_bound_fresh_consts(expr)
    name = binder_utf_name[b.name]
    if len(vars) == 1:
        return "{0!s}({1!s}, {2!s})".format(name, vars[0], body)
    else:
        vars_str = ', '.join(map(str, vars))
        return "{0!s}([{1!s}], {2!s})".format(name, vars_str, body)


def tm_str(expr):
    if expr.is_const():
        return print_const(expr)
    if expr.is_app():
        return print_app(expr)
    elif expr.is_pair():
        return print_pair(expr)
    elif expr.is_fst():
        return print_fst(expr)
    elif expr.is_snd():
        return print_snd(expr)
    elif expr.is_sub():
        return print_eq(expr)
    elif expr.is_bound():
        return print_bound(expr)
    elif expr.is_ev():
        return print_ev(expr)
    elif expr.is_box():
        return print_box(expr)
    else:
        return expr.to_string()


###############################################################################
#
# Constructors for terms and types
#
###############################################################################

# 'standard' information for terms and types.
# The fields are filled in below.

st_term = ExprInfo('term_info', {})
st_typ = ExprInfo('type_info', {})


# cast Python objects to appropriate expressions
def to_expr(expr):
    if isinstance(expr, int):
        return ii(expr)
    elif isinstance(expr, float):
        return rr(expr)
    # handle Sage literals
    elif type(expr).__name__ == 'Integer':
        return ii(int(expr))
    elif type(expr).__name__ == 'RealLiteral':
        return rr(float(expr))
    else:
        return expr


@with_info(st_term)
def pair(expr1, expr2):
    """Turn a pair of simply typed arguments
    into a Pair.
    
    Arguments:
    - `expr1`: an expression or int or float
    - `expr1`: an expression or int or float
    """
    e1 = to_expr(expr1)
    e2 = to_expr(expr2)
    ty1, _ = typing.infer(e1, ctxt=conf.current_ctxt())
    ty2, _ = typing.infer(e2, ctxt=conf.current_ctxt())

Answer:     return Pair(e1, e2, typ_mul(ty1, ty2))