def deftype(name, **kwargs): """Define a type constant, and add it to conf.current_ctxt. Arguments: - `name`: """ c = mktype(name, **kwargs) conf.current_ctxt().add_const(c) if conf.verbose: print "{0!s} : {1!s} is assumed.\n".format(c, c.type) return c
def deftype(name, **kwargs): """Define a type constant, and add it to current_ctxt. Arguments: - `name`: """ c = mktype(name, **kwargs) current_ctxt().add_const(c) if conf.verbose: print "{0!s} : {1!s} is assumed.\n".format(c, c.type) return c
def defhyp(name, prop): """Declare a constant of type bool, add it to the list of hypotheses. Arguments: - `name`: the name of the hypothesis - `prop`: the proposition """ c = defconst(name, prop) typing.infer(c.type, type=e.Bool(), ctxt=conf.current_ctxt()) conf.current_ctxt().hyps[name] = c.type return c
def defhyp(name, prop): """Declare a constant of type bool, add it to the list of hypotheses. Arguments: - `name`: the name of the hypothesis - `prop`: the proposition """ c = defconst(name, prop) typing.infer(c.type, type=e.Bool(), ctxt=current_ctxt()) current_ctxt().hyps[name] = c.type return c
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()) return Pair(e1, e2, typ_mul(ty1, ty2))
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=current_ctxt()) ty2, _ = typing.infer(e2, ctxt=current_ctxt()) return Pair(e1, e2, typ_mul(ty1, ty2))
def defvar(name, type, unfold=None, **kwargs): """Define a constant, check it is well-typed, and return it. Arguments: - `name`: the name of the constant - `type`: the type of the constant - `unfold`: list of names to unfold when attempting to prove the TCCs - `**kwargs`: extra values to be passed to the tag of the created constant. """ c = const(name, type, **kwargs) c, _, obl = elaborate(c, type, unfold) c.info['checked'] = True if obl.is_solved(): if conf.verbose: print "{0!s} : {1!s} is assumed.\n".format(c, c.type) else: current_ctxt().goals[obl.name] = obl print "In the declaration:\n{0!s} : {1!s}".format(name, c.type) print "remaining type-checking constraints!" print obl return c
def defvar(name, type, unfold=None, **kwargs): """Define a constant, check it is well-typed, and return it. Arguments: - `name`: the name of the constant - `type`: the type of the constant - `unfold`: list of names to unfold when attempting to prove the TCCs - `**kwargs`: extra values to be passed to the tag of the created constant. """ c = const(name, type, **kwargs) c, _, obl = elaborate(c, type, unfold) c.info['checked'] = True if obl.is_solved(): if conf.verbose: print "{0!s} : {1!s} is assumed.\n".format(c, c.type) else: conf.current_ctxt().goals[obl.name] = obl print "In the declaration:\n{0!s} : {1!s}".format(name, c.type) print "remaining type-checking constraints!" print obl return c
def get_def(name): """Return the definition associated to name in the current or parent contexts Arguments: - `name`: """ return current_ctxt().get_rec(name, 'defs')
def defclass(name, params, defn): """Define a type class with the given name and type Arguments: - `name`: a string - `params`: a list of parameters - `def`: the definition of the class, which may depend on the parameters """ class_ty = pi(params, Bool) class_def = abst(params, defn) c = defexpr(name, class_def, type=class_ty) c.info['is_class'] = True conf.current_ctxt().classes[name] = c.type c_def = conf.current_ctxt().defs[name] conf.current_ctxt().class_def[name] = c_def return c
def get_def(name): """Return the definition associated to name in the current or parent contexts Arguments: - `name`: """ return conf.current_ctxt().get_rec(name, 'defs')
def defclass(name, params, defn): """Define a type class with the given name and type Arguments: - `name`: a string - `params`: a list of parameters - `def`: the definition of the class, which may depend on the parameters """ class_ty = pi(params, Bool) class_def = abst(params, defn) c = defexpr(name, class_def, type=class_ty) c.info['is_class'] = True current_ctxt().classes[name] = c.type c_def = current_ctxt().defs[name] current_ctxt().class_def[name] = c_def return c
def definstance(name, ty, expr): """ Arguments: - `name`: a string - `ty`: a type of the form ClassName(t1,...,tn) """ root, _ = root_app(root_clause(ty)) if root.info.is_class: class_name = root.name c = defexpr(name, expr, type=ty, unfold=[class_name]) current_ctxt().class_instances[name] = c.type current_ctxt().hyps[name] = c.type return c else: raise Exception("Error in definition of {0!s}:"\ "expected {1!s} to be a class name"\ .format(name, root))
def defthm(name, prop, unfold=None): """Declare a theorem and call the default tactic to attempt to solve it. Add it as a hypothesis if it is solved. """ c = defexpr(name, triv(), prop, unfold=unfold) if not c.info['unsolved_tcc']: conf.current_ctxt().hyps[name] = c.type return c
def defthm(name, prop, unfold=None): """Declare a theorem and call the default tactic to attempt to solve it. Add it as a hypothesis if it is solved. """ c = defexpr(name, triv(), prop, unfold=unfold) if not c.info['unsolved_tcc']: current_ctxt().hyps[name] = c.type return c
def definstance(name, ty, expr): """ Arguments: - `name`: a string - `ty`: a type of the form ClassName(t1,...,tn) """ root, _ = root_app(root_clause(ty)) if root.info.is_class: class_name = root.name c = defexpr(name, expr, type=ty, unfold=[class_name]) conf.current_ctxt().class_instances[name] = c.type conf.current_ctxt().hyps[name] = c.type return c else: raise Exception("Error in definition of {0!s}:"\ "expected {1!s} to be a class name"\ .format(name, root))
def defconst(name, type, value=None, unfold=None, **kwargs): """Like defvar, but add the result to conf.current_ctxt before returning it. """ c = const(name, type, value=value, **kwargs) c, _, obl = elaborate(c, type, unfold) c.info['checked'] = True conf.current_ctxt().add_const(c) if obl.is_solved(): if conf.verbose: print "{0!s} : {1!s} is assumed.\n".format(c, c.type) else: conf.current_ctxt().goals[obl.name] = obl print "In the declaration:\n{0!s} : {1!s}".format(name, c.type) print "remaining type-checking constraints!" print obl return c
def defconst(name, type, value=None, unfold=None, **kwargs): """Like defvar, but add the result to current_ctxt before returning it. """ c = const(name, type, value=value, **kwargs) c, _, obl = elaborate(c, type, unfold) c.info['checked'] = True current_ctxt().add_const(c) if obl.is_solved(): if conf.verbose: print "{0!s} : {1!s} is assumed.\n".format(c, c.type) else: current_ctxt().goals[obl.name] = obl print "In the declaration:\n{0!s} : {1!s}".format(name, c.type) print "remaining type-checking constraints!" print obl return c
def tm_call(fun, *args): """Return the result of the application of fun to the arguments *args, using trivial conversion certificates. Arguments: - `fun`: an expression - `arg`: a list of expresstions """ fun_typ, _ = typing.infer(fun, ctxt=conf.current_ctxt()) conv = [triv()] * len(args) cast_args = map(to_expr, args) return app_expr(fun, fun_typ, conv, cast_args)
def tm_call(fun, *args): """Return the result of the application of fun to the arguments *args, using trivial conversion certificates. Arguments: - `fun`: an expression - `arg`: a list of expresstions """ fun_typ, _ = typing.infer(fun, ctxt=current_ctxt()) conv = [triv()] * len(args) cast_args = map(to_expr, args) return app_expr(fun, fun_typ, conv, cast_args)
def defexpr(name, expr, type=None, value=None, unfold=None, **kwargs): """Define an expression with a given type and value. Checks that the type of value is correct, and adds the defining equation to the context. Arguments: - `name`: a string - `expr`: an expression - `type`: an expression designating the type of expr - `value` : a value, which should agree with that of the body of the definition - `unfold` : a list of names to unfold in the type-inference process """ val, ty, obl = elaborate(expr, type, unfold) c = const(name, ty, value=value, **kwargs) c.info['defined'] = True c.info['checked'] = True current_ctxt().add_const(c) # TODO: add the equality to the context? # eq_c = equals(c, val) # def_name = "{0!s}_def".format(name) # c_def = const(def_name, eq_c) # current_ctxt.add_const(c_def) current_ctxt().defs[name] = val if obl.is_solved(): c.info['unsolved_tcc'] = False if conf.verbose: print "{0!s} : {1!s} := {2!s} is defined.\n".format(c, ty, val) else: current_ctxt().goals[obl.name] = obl c.info['unsolved_tcc'] = True print "In the definition\n"\ " {0!s} = {1!s} : {2!s}".format(name, val, ty) print "remaining type-checking constraints!" print obl return c
def defexpr(name, expr, type=None, value=None, unfold=None, **kwargs): """Define an expression with a given type and value. Checks that the type of value is correct, and adds the defining equation to the context. Arguments: - `name`: a string - `expr`: an expression - `type`: an expression designating the type of expr - `value` : a value, which should agree with that of the body of the definition - `unfold` : a list of names to unfold in the type-inference process """ val, ty, obl = elaborate(expr, type, unfold) c = const(name, ty, value=value, **kwargs) c.info['defined'] = True c.info['checked'] = True conf.current_ctxt().add_const(c) # TODO: add the equality to the context? # eq_c = equals(c, val) # def_name = "{0!s}_def".format(name) # c_def = const(def_name, eq_c) # conf.current_ctxt.add_const(c_def) conf.current_ctxt().defs[name] = val if obl.is_solved(): c.info['unsolved_tcc'] = False if conf.verbose: print "{0!s} : {1!s} := {2!s} is defined.\n".format(c, ty, val) else: conf.current_ctxt().goals[obl.name] = obl c.info['unsolved_tcc'] = True print "In the definition\n"\ " {0!s} = {1!s} : {2!s}".format(name, val, ty) print "remaining type-checking constraints!" print obl return c
def defsub(name, prop): """Declare a hypothesis of type A <= B Arguments: - `name`: the name of the hypothesis - `prop`: a proposition of the form A <= B """ if prop.is_sub(): c = defhyp(name, prop) conf.current_ctxt().sub[name] = c.type return c else: raise Exception("Error in definition {0!s}:"\ "expected a proposition of the form A <= B"\ .format(name))
def defsub(name, prop): """Declare a hypothesis of type A <= B Arguments: - `name`: the name of the hypothesis - `prop`: a proposition of the form A <= B """ if prop.is_sub(): c = defhyp(name, prop) current_ctxt().sub[name] = c.type return c else: raise Exception("Error in definition {0!s}:"\ "expected a proposition of the form A <= B"\ .format(name))
def root_app_implicit(expr): """If a term is of the form (..(f a0).. an), return the pair (f, [ai,..., ak]) where the ai...ak are the non-implicit arguments of f. Arguments: - `expr`: an expression """ r, args = root_app(expr) ty, _ = mvar_infer(r, ctxt=current_ctxt()) non_implicit = [] i = 0 while ty.is_pi() and i < len(args): if not ty.info.implicit: non_implicit.append(args[i]) i += 1 ty = ty.body return (r, non_implicit)
def root_app_implicit(expr): """If a term is of the form (..(f a0).. an), return the pair (f, [ai,..., ak]) where the ai...ak are the non-implicit arguments of f. Arguments: - `expr`: an expression """ r, args = root_app(expr) ty, _ = mvar_infer(r, ctxt=conf.current_ctxt()) non_implicit = [] i = 0 while ty.is_pi() and i < len(args): if not ty.info.implicit: non_implicit.append(args[i]) i += 1 ty = ty.body return (r, non_implicit)
def check(expr, type=None, unfold=None): """Elaborates the expression if necessary, and shows the type. Returns the elaborated expression Arguments: - `expr`: the expression to be checked - `type`: it's putative type - `tactic`: a tactic to use in the elaboration """ val, ty, obl = elaborate(expr, type, unfold) if obl.is_solved(): if conf.verbose: print "{0!s} : {1!s}.\n".format(val, ty) else: current_ctxt().goals[obl.name] = obl print "In checking the expression\n"\ "{0!s} : {1!s}".format(val, ty) print "remaining type-checking constraints!" print obl return val
def check(expr, type=None, unfold=None): """Elaborates the expression if necessary, and shows the type. Returns the elaborated expression Arguments: - `expr`: the expression to be checked - `type`: it's putative type - `unfold`: a list of names to unfold """ val, ty, obl = elaborate(expr, type, unfold) if obl.is_solved(): if conf.verbose: print "{0!s} : {1!s}.\n".format(val, ty) else: conf.current_ctxt().goals[obl.name] = obl print "In checking the expression\n"\ "{0!s} : {1!s}".format(val, ty) print "remaining type-checking constraints!" print obl return val
def elaborate(expr, type, unfold): """Elaborate an expression and (optionally) its type. Returns the elaborated expression and its type, and any remaining obligations. It also marks the expression and its type as elaborated. Arguments: - `expr`: the expression to be elaborated - `type`: it's putative type - `unfold`: a list of defined constant names to unfold when type-checking """ if unfold is None: unfold_tac = tac.idtac else: unfold_tac = tac.par(tac.unfold(*unfold)) if expr.info.elaborated and type is None: ty, obl = typing.infer(expr, ctxt=conf.current_ctxt()) obl.solve_with(unfold_tac >> type_tac) return (expr, ty, obl) _, obl = mvar_infer(expr, ctxt=conf.current_ctxt()) u.mvar_stack.clear() u.mvar_stack.new() obl.solve_with(unfold_tac >> elab_tac) try: val = sub_mvar(expr, undef=True) except Exception: print obl raise #Only call infer if the substitution did not find values for # the mvars in the type if not (type is None): try: ty = sub_mvar(type, undef=True) except e.ExprError: _, obl = mvar_infer(type, ctxt=conf.current_ctxt()) u.mvar_stack.clear() u.mvar_stack.new() obl.solve_with(unfold_tac >> elab_tac) ty = sub_mvar(type, undef=True) if type is None: ty, obl = typing.infer(val, ctxt=conf.current_ctxt()) else: ty, obl = typing.infer(val, type=ty, ctxt=conf.current_ctxt()) obl.solve_with(unfold_tac >> type_tac) val.info['elaborated'] = True if type is None and ty.info.name == "default": #TODO: this should be st_typ, but pis are not printed #correctly at the type level. ty.info.update(st_term) return (val, ty, obl)
def elaborate(expr, type, unfold): """Elaborate an expression and (optionally) its type. Returns the elaborated expression and its type, and any remaining obligations. It also marks the expression and its type as elaborated. Arguments: - `expr`: the expression to be elaborated - `type`: it's putative type - `unfold`: a list of defined constant names to unfold when type-checking """ if unfold is None: unfold_tac = tac.idtac else: unfold_tac = tac.par(tac.unfold(*unfold)) if expr.info.elaborated and type is None: ty, obl = typing.infer(expr, ctxt=current_ctxt()) obl.solve_with(unfold_tac >> type_tac) return (expr, ty, obl) _, obl = mvar_infer(expr, ctxt=current_ctxt()) u.mvar_stack.clear() u.mvar_stack.new() obl.solve_with(unfold_tac >> elab_tac) try: val = sub_mvar(expr, undef=True) except Exception: print obl raise #Only call infer if the substitution did not find values for # the mvars in the type if not (type is None): try: ty = sub_mvar(type, undef=True) except e.ExprError: _, obl = mvar_infer(type, ctxt=current_ctxt()) u.mvar_stack.clear() u.mvar_stack.new() obl.solve_with(unfold_tac >> elab_tac) ty = sub_mvar(type, undef=True) if type is None: ty, obl = typing.infer(val, ctxt=current_ctxt()) else: ty, obl = typing.infer(val, type=ty, ctxt=current_ctxt()) obl.solve_with(unfold_tac >> type_tac) val.info['elaborated'] = True if type is None and ty.info.name == "default": #TODO: this should be st_typ, but pis are not printed #correctly at the type level. ty.info.update(st_term) return (val, ty, obl)