Exemplo n.º 1
0
 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
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
    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()
Exemplo n.º 5
0
 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))