def get_priority(t): if nat.is_binary(t) or hol_list.is_literal_list(t): return 100 # Nat atom case elif t.is_comb(): op_data = get_info_for_operator(t) if op_data is not None: return op_data.priority elif t.is_all() or logic.is_exists(t) or logic.is_if(t): return 10 else: return 95 # Function application elif t.is_abs(): return 10 else: return 100 # Atom case
def get_priority_pair(t): """Obtain the binding priority of the top-most operation of t.""" if (t.is_number() and isinstance(t.dest_number(), int) and t.dest_number() >= 0) or \ list.is_literal_list(t): return 100, ATOM # Nat atom case elif t.is_comb(): op_data = operator.get_info_for_fun(t.head) binder_data = operator.get_binder_info_for_fun(t.head) if op_data is not None: if op_data.arity == operator.UNARY: return op_data.priority, UNARY else: return op_data.priority, BINARY elif binder_data is not None or logic.is_if(t): return 10, BINDER else: return 95, FUN_APPL # Function application elif t.is_abs(): return 10, BINDER else: return 100, ATOM # Atom case
def helper(t, bd_vars): """Main recursive function. Here bd_vars is the list of bound variables (represented by a list of AST Bound objects). """ # Some special cases: # Natural numbers: if t.is_zero() or t.is_one() or \ (t.is_comb('of_nat', 1) and t.arg.is_binary() and t.arg.dest_binary() >= 2): # First find the number n = t.dest_number() res = Number(n, t.get_type()) if (t.is_const() and hasattr(t, "print_type")) or \ (t.is_comb() and hasattr(t.fun, "print_type")): res = Bracket(ShowType(res, get_ast_type(res.T))) return res # Lists elif list.is_literal_list(t): items = list.dest_literal_list(t) res = List([helper(item, bd_vars) for item in items], t.get_type()) if hasattr(t, "print_type"): res = Bracket(ShowType(res, get_ast_type(res.T))) return res # Sets elif set.is_literal_set(t): items = set.dest_literal_set(t) if set.is_empty_set(t): res = Operator("∅", t.T, "empty_set") if settings.unicode else Operator( "{}", t.T, "empty_set") if hasattr(t, "print_type"): res = Bracket(ShowType(res, get_ast_type(res.T))) return res else: return Set([helper(item, bd_vars) for item in items], t.get_type()) # Chars and Strings elif string.is_char(t): return Char(string.dest_char(t)) elif string.is_string(t): return String(string.dest_string(t)) # Intervals elif interval.is_interval(t): return Interval(helper(t.arg1, bd_vars), helper(t.arg, bd_vars), t.get_type()) elif t.is_comb('collect', 1) and t.arg.is_abs(): nm = name.get_variant_name(t.arg.var_name, var_names) var_names.append(nm) bind_var = Bound(nm, t.arg.var_T) body_ast = helper(t.arg.body, [bind_var] + bd_vars) var_names.remove(nm) if hasattr(t.arg, "print_type"): bind_var = ShowType(bind_var, get_ast_type(bind_var.T)) return Collect(bind_var, body_ast, t.get_type()) elif logic.is_if(t): P, x, y = t.args return ITE(helper(P, bd_vars), helper(x, bd_vars), helper(y, bd_vars), t.get_type()) elif t.is_svar(): return SVarName(t.name, t.T) elif t.is_var(): return VarName(t.name, t.T) elif t.is_const(): link_name = theory.thy.get_overload_const_name(t.name, t.T) res = ConstName(t.name, t.T, link_name=link_name) if hasattr(t, "print_type"): res = Bracket(ShowType(res, get_ast_type(res.T))) return res elif t.is_comb(): op_data = operator.get_info_for_fun(t.head) binder_data = operator.get_binder_info_for_fun(t.head) # First, we take care of the case of operators if op_data and op_data.arity == operator.BINARY and t.is_binop(): arg1, arg2 = t.args # Obtain output for first argument, enclose in parenthesis # if necessary. arg1_ast = helper(arg1, bd_vars) if (op_data.assoc == operator.LEFT and get_priority(arg1) < op_data.priority or op_data.assoc == operator.RIGHT and get_priority(arg1) <= op_data.priority): arg1_ast = Bracket(arg1_ast) op_str = op_data.unicode_op if settings.unicode else op_data.ascii_op op_name = theory.thy.get_overload_const_name( op_data.fun_name, t.head.get_type()) op_ast = Operator(op_str, t.head.get_type(), op_name) # Obtain output for second argument, enclose in parenthesis # if necessary. arg2_ast = helper(arg2, bd_vars) if (op_data.assoc == operator.LEFT and get_priority(arg2) <= op_data.priority or op_data.assoc == operator.RIGHT and get_priority(arg2) < op_data.priority): arg2_ast = Bracket(arg2_ast) return BinaryOp(arg1_ast, op_ast, arg2_ast, t.get_type()) # Unary case elif op_data and op_data.arity == operator.UNARY: op_str = op_data.unicode_op if settings.unicode else op_data.ascii_op op_name = theory.thy.get_overload_const_name( op_data.fun_name, t.head.get_type()) op_ast = Operator(op_str, t.head.get_type(), op_name) arg_ast = helper(t.arg, bd_vars) arg_prior, arg_type = get_priority_pair(t.arg) if arg_prior < op_data.priority or arg_type == FUN_APPL: arg_ast = Bracket(arg_ast) return UnaryOp(op_ast, arg_ast, t.get_type()) # Next, the case of binders elif binder_data and t.arg.is_abs(): binder_str = binder_data.unicode_op if settings.unicode else binder_data.ascii_op op_ast = Binder(binder_str) nm = name.get_variant_name(t.arg.var_name, var_names) var_names.append(nm) bind_var = Bound(nm, t.arg.var_T) body_ast = helper(t.arg.body, [bind_var] + bd_vars) if hasattr(t.arg, "print_type"): bind_var = ShowType(bind_var, get_ast_type(bind_var.T)) var_names.remove(nm) return BinderAppl(op_ast, bind_var, body_ast) # Function update elif function.is_fun_upd(t): f, upds = function.strip_fun_upd(t) f_ast = helper(f, bd_vars) upds_ast = [(helper(a, bd_vars), helper(b, bd_vars)) for a, b in upds] return FunUpd(f_ast, upds_ast, t.get_type()) # Finally, usual function application else: fun_ast = helper(t.fun, bd_vars) fun_prior, fun_type = get_priority_pair(t.fun) if fun_prior < 95 or fun_type == UNARY: fun_ast = Bracket(fun_ast) arg_ast = helper(t.arg, bd_vars) if get_priority(t.arg) <= 95: arg_ast = Bracket(arg_ast) return FunAppl(fun_ast, arg_ast) elif t.is_abs(): op_ast = Binder("λ") if settings.unicode else Binder("%") nm = name.get_variant_name(t.var_name, var_names) var_names.append(nm) bind_var = Bound(nm, t.var_T) body_ast = helper(t.body, [bind_var] + bd_vars) if hasattr(t, "print_type"): bind_var = ShowType(bind_var, get_ast_type(bind_var.T)) var_names.remove(nm) return BinderAppl(op_ast, bind_var, body_ast) elif t.is_bound(): if t.n >= len(bd_vars): raise term.TermException("print_term: open term") else: return bd_vars[t.n] else: raise TypeError
def helper(t, bd_vars): LEFT, RIGHT = OperatorData.LEFT_ASSOC, OperatorData.RIGHT_ASSOC # Some special cases: # Natural numbers: if nat.is_binary(t): return N(str(nat.from_binary(t))) if hol_list.is_literal_list(t): items = hol_list.dest_literal_list(t) res = N('[') + commas_join( helper(item, bd_vars) for item in items) + N(']') if hasattr(t, "print_type"): return N("(") + res + N("::") + print_type(thy, t.T) + N(")") else: return res if set.is_literal_set(t): empty_set = "∅" if settings.unicode() else "{}" if hasattr(t, "print_type"): return N("(") + N(empty_set) + N("::") + print_type( thy, t.T) + N(")") else: return N(empty_set) if logic.is_if(t): P, x, y = t.args return N("if ") + helper(P, bd_vars) + N(" then ") + helper(x, bd_vars) + \ N(" else ") + helper(y, bd_vars) if t.is_var(): return V(t.name) elif t.is_const(): if hasattr(t, "print_type") and t.print_type: return N("(" + t.name + "::") + print_type(thy, t.T) + N(")") else: return N(t.name) elif t.is_comb(): op_data = get_info_for_operator(t) # First, we take care of the case of operators if op_data and op_data.arity == OperatorData.BINARY and t.is_binop( ): arg1, arg2 = t.args # Obtain output for first argument, enclose in parenthesis # if necessary. if (op_data.assoc == LEFT and get_priority(arg1) < op_data.priority or op_data.assoc == RIGHT and get_priority(arg1) <= op_data.priority): str_arg1 = N("(") + helper(arg1, bd_vars) + N(")") else: str_arg1 = helper(arg1, bd_vars) if settings.unicode() and op_data.unicode_op: str_op = N(' ' + op_data.unicode_op + ' ') else: str_op = N(' ' + op_data.ascii_op + ' ') # Obtain output for second argument, enclose in parenthesis # if necessary. if (op_data.assoc == LEFT and get_priority(arg2) <= op_data.priority or op_data.assoc == RIGHT and get_priority(arg2) < op_data.priority): str_arg2 = N("(") + helper(arg2, bd_vars) + N(")") else: str_arg2 = helper(arg2, bd_vars) return str_arg1 + str_op + str_arg2 # Unary case elif op_data and op_data.arity == OperatorData.UNARY: if settings.unicode() and op_data.unicode_op: str_op = N(op_data.unicode_op) else: str_op = N(op_data.ascii_op) if get_priority(t.arg) < op_data.priority: str_arg = N("(") + helper(t.arg, bd_vars) + N(")") else: str_arg = helper(t.arg, bd_vars) return str_op + str_arg # Next, the case of binders elif t.is_all(): all_str = "!" if not settings.unicode() else "∀" if hasattr(t.arg, "print_type"): var_str = B(t.arg.var_name) + N("::") + print_type( thy, t.arg.var_T) else: var_str = B(t.arg.var_name) body_repr = helper(t.arg.body, [t.arg.var_name] + bd_vars) return N(all_str) + var_str + N(". ") + body_repr elif logic.is_exists(t): exists_str = "?" if not settings.unicode() else "∃" if hasattr(t.arg, "print_type"): var_str = B(t.arg.var_name) + N("::") + print_type( thy, t.arg.var_T) else: var_str = B(t.arg.var_name) body_repr = helper(t.arg.body, [t.arg.var_name] + bd_vars) return N(exists_str) + var_str + N(". ") + body_repr # Function update elif function.is_fun_upd(t): f, upds = function.strip_fun_upd(t) upd_strs = [ helper(a, bd_vars) + N(" := ") + helper(b, bd_vars) for a, b in upds ] return N("(") + helper( f, bd_vars) + N(")(") + commas_join(upd_strs) + N(")") # Finally, usual function application else: if get_priority(t.fun) < 95: str_fun = N("(") + helper(t.fun, bd_vars) + N(")") else: str_fun = helper(t.fun, bd_vars) if get_priority(t.arg) <= 95: str_arg = N("(") + helper(t.arg, bd_vars) + N(")") else: str_arg = helper(t.arg, bd_vars) return str_fun + N(" ") + str_arg elif t.is_abs(): lambda_str = "%" if not settings.unicode() else "λ" if hasattr(t, "print_type"): var_str = B(t.var_name) + N("::") + print_type(thy, t.var_T) else: var_str = B(t.var_name) body_repr = helper(t.body, [t.var_name] + bd_vars) return N(lambda_str) + var_str + N(". ") + body_repr elif t.is_bound(): if t.n >= len(bd_vars): raise OpenTermException else: return B(bd_vars[t.n]) else: raise TypeError()
def rec(t): if t.is_var(): z3_t = convert_const(t.name, t.T, ctx) if t.T == NatType and t.name not in assms: assms[t.name] = z3_t >= 0 return z3_t elif t.is_forall(): nm = name.get_variant_name(t.arg.var_name, var_names) var_names.append(nm) v = Var(nm, t.arg.var_T) z3_v = convert_const(nm, t.arg.var_T, ctx) return z3.ForAll(z3_v, rec(t.arg.subst_bound(v))) elif t.is_exists(): nm = name.get_variant_name(t.arg.var_name, var_names) var_names.append(nm) v = Var(nm, t.arg.var_T) z3_v = convert_const(nm, t.arg.var_T, ctx) return z3.Exists(z3_v, rec(t.arg.subst_bound(v))) elif t.is_number(): return t.dest_number() elif t.is_implies(): return z3.Implies(rec(t.arg1), rec(t.arg)) elif t.is_equals(): return rec(t.arg1) == rec(t.arg) elif t.is_conj(): return z3.And(rec(t.arg1), rec(t.arg)) if ctx is None else z3.And( rec(t.arg1), rec(t.arg), ctx) elif t.is_disj(): return z3.Or(rec(t.arg1), rec(t.arg)) if ctx is None else z3.Or( rec(t.arg1), rec(t.arg), ctx) elif logic.is_if(t): b, t1, t2 = t.args return z3.If(rec(b), rec(t1), rec(t2), ctx) elif t.is_not(): return z3.Not(rec(t.arg), ctx) elif t.is_plus(): return rec(t.arg1) + rec(t.arg) elif t.is_minus(): m, n = rec(t.arg1), rec(t.arg) if t.arg1.get_type() == NatType: return z3.If(m >= n, m - n, 0, ctx) return m - n elif t.is_uminus(): return -rec(t.arg) elif t.is_times(): return rec(t.arg1) * rec(t.arg) elif t.is_less_eq(): return rec(t.arg1) <= rec(t.arg) elif t.is_less(): return rec(t.arg1) < rec(t.arg) elif t.is_greater_eq(): return rec(t.arg1) >= rec(t.arg) elif t.is_greater(): return rec(t.arg1) > rec(t.arg) elif t.is_divides(): return rec(t.arg1) / rec(t.arg) elif t.is_comb('of_nat', 1): if t.get_type() == RealType: if t.arg.is_var(): if t.arg.name not in to_real: nm = name.get_variant_name("r" + t.arg.name, var_names) var_names.append(nm) to_real[t.arg.name] = nm z3_t = convert_const(nm, RealType, ctx) assms[nm] = z3_t >= 0 return z3_t else: return convert_const(to_real[t.arg.name], RealType, ctx) return z3.ToReal(rec(t.arg)) else: raise Z3Exception("convert: unsupported of_nat " + repr(t)) elif t.is_comb('max', 2): a, b = rec(t.arg1), rec(t.arg) return z3.If(a >= b, a, b, ctx) elif t.is_comb('min', 2): a, b = rec(t.arg1), rec(t.arg) return z3.If(a <= b, a, b, ctx) elif t.is_comb('abs', 1): a = rec(t.arg) return z3.If(a >= 0, a, -a, ctx) elif t.is_comb('member', 2): a, S = rec(t.arg1), rec(t.arg) return S(a) elif t.is_comb(): return rec(t.fun)(rec(t.arg)) elif t.is_const(): if t == true: return z3.BoolVal(True, ctx) elif t == false: return z3.BoolVal(False, ctx) else: raise Z3Exception("convert: unsupported constant " + repr(t)) else: raise Z3Exception("convert: unsupported operation " + repr(t))