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 ensure_fun_closure(self, fun): if fun.name in self.closure_preds.keys(): return self.closure_preds[fun.name] else: etype, _ = ty.infer(fun) codom, doms = root_pi_implicit(etype) # We state that the output of the function satisfies the # codomain predicate. codom_pred = self.ladr_sort_pred(codom) d_n = len(doms) v_block = self.ladr_var_block(d_n) q_open = '' for v in v_block: q_open += "(all " + v + ' ' vs = ", ".join(v_block) q_close = ')' * d_n f = self.ladr_fun_name(fun) if len(vs) == 0: s = q_open + codom_pred + '(' + f + ')' + q_close elif fun.info.infix and len(vs) == 2: s = q_open + codom_pred + '(' + vs[0] + f + vs[ 1] + ')' + q_close else: s = q_open + codom_pred + '(' + f + '(' + vs + '))' + q_close print "\n--\nClosure axiom for function: \n\n" + s + "\n--" self.closure_preds[fun.name] = s return s
def ensure_fun_closure(self, fun): if fun.name in self.closure_preds.keys(): return self.closure_preds[fun.name] else: etype, _ = ty.infer(fun) codom, doms = root_pi_implicit(etype) # We state that the output of the function satisfies the # codomain predicate. codom_pred = self.ladr_sort_pred(codom) d_n = len(doms) v_block = self.ladr_var_block(d_n) q_open = '' for v in v_block: q_open += "(all " + v + ' ' vs = ", ".join(v_block) q_close = ')'*d_n f = self.ladr_fun_name(fun) if len(vs) == 0: s = q_open + codom_pred + '(' + f + ')' + q_close elif fun.info.infix and len(vs) == 2: s = q_open + codom_pred + '(' + vs[0] + f + vs[1] + ')' + q_close else: s = q_open + codom_pred + '(' + f + '(' + vs + '))' + q_close print "\n--\nClosure axiom for function: \n\n" + s + "\n--" self.closure_preds[fun.name] = s return s
def is_bool_or_real(expr): """checks that the expression has type bool or real, without generating obligations. Arguments: - `expr`: """ t, _ = ty.infer(expr) return (t.equals(Real)) or (t.equals(Bool))
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 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 __call__(self, expr, vars_lst=[], var=False): if expr.is_const(): etype, _ = ty.infer(expr) if self.is_predicate(etype): if expr.name[0] == 'P': return expr.name else: return ("P" + expr.name) else: if var or expr.name in vars_lst: # LADR vars must begin with chars 'u'-'z'. if expr.name[0] in ['u', 'v', 'w', 'x', 'y', 'z']: return expr.name else: return ("x" + expr.name) else: # LADR consts must begin with chars 'a'-'t' if ord(expr.name[0]) < 117: # chr(117) == 'u' return expr.name else: return ("c" + expr.name) elif expr.is_app(): fun, args = root_app_implicit(expr) args = [self.__call__(a, vars_lst=vars_lst) for a in args] return self.handle_function(fun, args) elif expr.is_forall(): vlist, body = open_bound_fresh_consts(expr) ladr_vars = [v.name for v in vlist] # ladr_vars_strs is needed to convert all Boole vars into # a syntactic format supported by LADR. ladr_vars_strs = [self(v, var=True) for v in vlist] ladr_body = self(body, vars_lst = ladr_vars) ladr_sorting = self.ladr_sort_conj(zip(vlist, ladr_vars_strs)) #print ladr_sorting return ("all " + (" all ".join(ladr_vars_strs)) + " " \ + '((' + ladr_sorting + ") -> " + ladr_body + ')') elif expr.is_exists(): vlist, body = open_bound_fresh_consts(expr) ladr_vars = [v.name for v in vlist] ladr_vars_strs = [self(v, var=True) for v in vlist] ladr_body = self(body, vars_lst=ladr_vars) ladr_sorting = self.ladr_sort_conj(zip(vlist, ladr_vars_strs)) return ("exists " + (" exists ".join(ladr_vars_strs)) + " " \ + '((' + ladr_sorting + ') & ' + ladr_body + ')') else: raise LADR_Unexpected_Expression
def __call__(self, expr, vars_lst=[], var=False): if expr.is_const(): etype, _ = ty.infer(expr) if self.is_predicate(etype): if expr.name[0] == 'P': return expr.name else: return ("P" + expr.name) else: if var or expr.name in vars_lst: # LADR vars must begin with chars 'u'-'z'. if expr.name[0] in ['u', 'v', 'w', 'x', 'y', 'z']: return expr.name else: return ("x" + expr.name) else: # LADR consts must begin with chars 'a'-'t' if ord(expr.name[0]) < 117: # chr(117) == 'u' return expr.name else: return ("c" + expr.name) elif expr.is_app(): fun, args = root_app_implicit(expr) args = [self.__call__(a, vars_lst=vars_lst) for a in args] return self.handle_function(fun, args) elif expr.is_forall(): vlist, body = open_bound_fresh_consts(expr) ladr_vars = [v.name for v in vlist] # ladr_vars_strs is needed to convert all Boole vars into # a syntactic format supported by LADR. ladr_vars_strs = [self(v, var=True) for v in vlist] ladr_body = self(body, vars_lst=ladr_vars) ladr_sorting = self.ladr_sort_conj(zip(vlist, ladr_vars_strs)) #print ladr_sorting return ("all " + (" all ".join(ladr_vars_strs)) + " " \ + '((' + ladr_sorting + ") -> " + ladr_body + ')') elif expr.is_exists(): vlist, body = open_bound_fresh_consts(expr) ladr_vars = [v.name for v in vlist] ladr_vars_strs = [self(v, var=True) for v in vlist] ladr_body = self(body, vars_lst=ladr_vars) ladr_sorting = self.ladr_sort_conj(zip(vlist, ladr_vars_strs)) return ("exists " + (" exists ".join(ladr_vars_strs)) + " " \ + '((' + ladr_sorting + ') & ' + ladr_body + ')') else: raise LADR_Unexpected_Expression
def get_z3_const(self, c): if c.name in self.symbol_dict.keys(): # defined constant return self.symbol_dict[c.name] elif c.value != None: # interpreted constant etype = c.type if etype.name in _built_in_z3_sort_values.keys(): val_trans = _built_in_z3_sort_values[etype.name] return val_trans(c.value.pyval, self.context) elif etype.value and etype.value.desc == "enumtype_val": self.get_z3_sort(etype) # creates the enum type if not there return self.symbol_dict[c.value.pyval] else: raise Z3_Unexpected_Expression(c) else: # new constant etype, _ = ty.infer(c) return self.make_z3_const(etype, c.name)
def handle_function(self, fun, args): """ fun: Boole function symbol to apply args: z3 expressions, already translated """ # note the different calling conventions if fun.name in self.symbol_dict.keys(): # defined function symbol z3_fun = self.symbol_dict[fun.name] return z3_fun(*args) elif fun.name in _built_in_z3_funs.keys(): # built-in function symbol z3_fun = _built_in_z3_funs[fun.name] return z3_fun(args, self.context) else: # new function symbol etype, _ = ty.infer(fun) z3_fun = self.make_z3_const(etype, fun.name) return z3_fun(*args)
def handle_function(self, fun, args): """ fun: Boole function symbol to apply args: LADR expressions, already translated """ # note the different calling conventions if fun.name in _built_in_ladr_funs.keys(): # built-in function symbol (a logical connective) ladr_fun = _built_in_ladr_funs[fun.name] return ladr_fun(args) else: # an LADR function symbol etype, _ = ty.infer(fun) if self.is_predicate(etype): def fun_app(a): f = self.ladr_fun_name(fun, predicate=True) if len(a) == 0: return f elif fun.info.infix and len(a) == 2: return '(' + a[0] + f + a[1] + ')' else: args = ",".join(a) return f + "(" + args + ")" ladr_fun = fun_app else: # We must make sure to construct a `closure' statement # for this function w.r.t. its domain (represented as # an LADR predicate). self.ensure_fun_closure(fun) def fun_app_f(a): f = self.ladr_fun_name(fun, predicate=False) if len(a) == 0: return f else: args = ",".join(a) return f + "(" + args + ")" ladr_fun = fun_app_f return ladr_fun(args)
def handle_function(self, fun, args): """ fun: Boole function symbol to apply args: LADR expressions, already translated """ # note the different calling conventions if fun.name in _built_in_ladr_funs.keys(): # built-in function symbol (a logical connective) ladr_fun = _built_in_ladr_funs[fun.name] return ladr_fun(args) else: # an LADR function symbol etype, _ = ty.infer(fun) if self.is_predicate(etype): ladr_fun = (lambda a: self.ladr_fun_name(fun, predicate=True) \ + "(" + ",".join(a) + ")") else: # We must make sure to construct a `closure' statement # for this function w.r.t. its domain (represented as # an LADR predicate). self.ensure_fun_closure(fun) ladr_fun = (lambda a: self.ladr_fun_name(fun) + "(" + ",".join(a) + ")") return ladr_fun(args)
def handle_function(self, fun, args): """ fun: Boole function symbol to apply args: LADR expressions, already translated """ # note the different calling conventions if fun.name in _built_in_ladr_funs.keys(): # built-in function symbol (a logical connective) ladr_fun = _built_in_ladr_funs[fun.name] return ladr_fun(args) else: # an LADR function symbol etype, _ = ty.infer(fun) if self.is_predicate(etype): ladr_fun = (lambda a: self.ladr_fun_name(fun, predicate=True) \ + "(" + ",".join(a) + ")") else: # We must make sure to construct a `closure' statement # for this function w.r.t. its domain (represented as # an LADR predicate). self.ensure_fun_closure(fun) ladr_fun = (lambda a: self.ladr_fun_name(fun) + "(" + ",".join( a) + ")") return ladr_fun(args)
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)