:- module construct.
:- use_module builtin, erlang_rtti_implementation, int, list, maybe, private_builtin, require, rtti_implementation, type_desc, univ.
:- pragma foreign_import_module("C", construct).
:- pragma foreign_import_module("C#", construct).
:- pragma foreign_import_module("Java", construct).
:- pragma foreign_import_module("Erlang", construct).
:- pragma foreign_import_module("Erlang", erlang_rtti_implementation).
:- pragma foreign_import_module("Erlang", erlang_rtti_implementation).
:- pragma foreign_import_module("C#", rtti_implementation).
:- pragma foreign_import_module("Java", rtti_implementation).
:- pragma foreign_import_module("C#", rtti_implementation).
:- pragma foreign_import_module("Java", rtti_implementation).
:- pragma foreign_import_module("C", io).
:- pragma foreign_import_module("C#", io).
:- pragma foreign_import_module("Java", io).
:- pragma foreign_import_module("IL", io).
:- pragma foreign_import_module("Erlang", io).
:- pragma foreign_import_module("C", io).
:- pragma foreign_import_module("C#", io).
:- pragma foreign_import_module("Java", io).
:- pragma foreign_import_module("IL", io).
:- pragma foreign_import_module("Erlang", io).
:- pragma foreign_import_module("C", time).
:- pragma foreign_import_module("C", string).
:- pragma foreign_import_module("C", bitmap).
:- pragma foreign_import_module("C#", bitmap).
:- pragma foreign_import_module("Java", bitmap).
:- pragma foreign_import_module("IL", bitmap).
:- pragma foreign_import_module("Erlang", bitmap).
:- pragma foreign_import_module("C", bitmap).
:- pragma foreign_import_module("C#", bitmap).
:- pragma foreign_import_module("Java", bitmap).
:- pragma foreign_import_module("IL", bitmap).
:- pragma foreign_import_module("Erlang", bitmap).
:- pragma foreign_import_module("C", time).
:- pragma foreign_import_module("C#", time).
:- pragma foreign_import_module("Java", time).
:- pragma foreign_import_module("IL", time).
:- pragma foreign_import_module("Erlang", time).
:- pragma foreign_import_module("C", time).
:- pragma foreign_import_module("C#", time).
:- pragma foreign_import_module("Java", time).
:- pragma foreign_import_module("IL", time).
:- pragma foreign_import_module("Erlang", time).
:- pragma foreign_import_module("C", array).
:- pragma foreign_import_module("C#", array).
:- pragma foreign_import_module("Java", array).
:- pragma foreign_import_module("IL", array).
:- pragma foreign_import_module("Erlang", array).
:- pragma foreign_import_module("C", array).
:- pragma foreign_import_module("C#", array).
:- pragma foreign_import_module("Java", array).
:- pragma foreign_import_module("IL", array).
:- pragma foreign_import_module("Erlang", array).
:- pred construct.get_functor_internal(type_desc.type_desc, int, string, int, list.list(type_desc.pseudo_type_desc)).
:- mode construct.get_functor_internal((builtin.in), (builtin.in), (builtin.out), (builtin.out), (builtin.out)) is semidet.
:- pred construct.get_functor_with_names_internal(type_desc.type_desc, int, string, int, list.list(type_desc.pseudo_type_desc), list.list(string)).
:- mode construct.get_functor_with_names_internal((builtin.in), (builtin.in), (builtin.out), (builtin.out), (builtin.out), (builtin.out)) is semidet.
:- func construct.null_to_no(string) = maybe.maybe(string).
:- mode construct.null_to_no((builtin.in)) = (builtin.out) is det.
:- pred construct.null(string).
:- mode construct.null((builtin.in)) is semidet.
:- pred construct.find_functor_2(type_desc.type_desc, string, int, int, int, list.list(type_desc.type_desc)).
:- mode construct.find_functor_2((builtin.in), (builtin.in), (builtin.in), (builtin.in), (builtin.out), (builtin.out)) is semidet.
:- func construct.construct_tuple_2(list.list(univ.univ), list.list(type_desc.type_desc), int) = univ.univ.
:- mode construct.construct_tuple_2((builtin.in), (builtin.in), (builtin.in)) = (builtin.out) is det.
:- pragma foreign_proc("C", construct.num_functors(TypeInfo :: (builtin.in)) = (Functors :: (builtin.out)), [will_not_call_mercury, thread_safe, not_tabled_for_io, promise_pure, may_modify_trail], "{
    MR_save_transient_registers();
    Functors = MR_get_num_functors((MR_TypeInfo) TypeInfo);
    MR_restore_transient_registers();
    SUCCESS_INDICATOR = (Functors >= 0);
}").
construct.det_num_functors(TypeInfo_3) = HeadVar__2_2 :-
    (if
      N_4 = construct.num_functors(TypeInfo_3)
    then
      HeadVar__2_2 = N_4
    else
      HeadVar__2_2 = require.func_error(V_5),
      V_5 = "construct.det_num_functors: type does not have functors" : string
    ).
construct.get_functor(TypeDesc_6, FunctorNumber_7, FunctorName_8, Arity_9, PseudoTypeInfoList_10) :-
    construct.get_functor_internal(TypeDesc_6, FunctorNumber_7, FunctorName_8, Arity_9, PseudoTypeInfoList_10).
construct.get_functor_with_names(TypeDesc_7, I_8, Functor_9, Arity_10, PseudoTypeInfoList_11, ArgNameList_12) :-
    construct.get_functor_with_names_internal(TypeDesc_7, I_8, Functor_9, Arity_10, PseudoTypeInfoList_11, ArgNameList0_13),
    ArgNameList_12 = list.map(V_14, ArgNameList0_13),
    V_14 = construct.null_to_no : ((func string) = maybe.maybe(string)).
construct.get_functor_ordinal(TypeDesc_4, FunctorNumber_5) = Ordinal_6 :-
    construct.get_functor_ordinal(TypeDesc_4, FunctorNumber_5, Ordinal_6).
:- pragma foreign_proc("C", construct.get_functor_ordinal(TypeDesc :: (builtin.in), FunctorNumber :: (builtin.in), Ordinal :: (builtin.out)), [will_not_call_mercury, thread_safe, not_tabled_for_io, promise_pure, may_modify_trail], "{
    MR_TypeInfo         type_info;
    MR_Construct_Info   construct_info;
    MR_bool             success;

    type_info = (MR_TypeInfo) TypeDesc;

    /*
    ** Get information for this functor number and store in construct_info.
    ** If this is a discriminated union type and if the functor number is
    ** in range, we succeed.
    */
    MR_save_transient_registers();
    success = MR_get_functors_check_range(FunctorNumber, type_info,
        &construct_info);
    MR_restore_transient_registers();

    if (success) {
        switch (construct_info.type_ctor_rep) {

        case MR_TYPECTOR_REP_ENUM:
        case MR_TYPECTOR_REP_ENUM_USEREQ:
            Ordinal = construct_info.functor_info.
                enum_functor_desc->MR_enum_functor_ordinal;
            break;
        
        case MR_TYPECTOR_REP_FOREIGN_ENUM:
        case MR_TYPECTOR_REP_FOREIGN_ENUM_USEREQ:
            Ordinal = construct_info.functor_info.
                foreign_enum_functor_desc->MR_foreign_enum_functor_ordinal;
            break;

        case MR_TYPECTOR_REP_DUMMY:
        case MR_TYPECTOR_REP_NOTAG:
        case MR_TYPECTOR_REP_NOTAG_USEREQ:
        case MR_TYPECTOR_REP_NOTAG_GROUND:
        case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
        case MR_TYPECTOR_REP_TUPLE:
            Ordinal = 0;
            break;

        case MR_TYPECTOR_REP_DU:
        case MR_TYPECTOR_REP_DU_USEREQ:
        case MR_TYPECTOR_REP_RESERVED_ADDR:
        case MR_TYPECTOR_REP_RESERVED_ADDR_USEREQ:
            Ordinal = construct_info.functor_info.
                du_functor_desc->MR_du_functor_ordinal;
            break;

        case MR_TYPECTOR_REP_EQUIV:
        case MR_TYPECTOR_REP_EQUIV_GROUND:
        case MR_TYPECTOR_REP_FUNC:
        case MR_TYPECTOR_REP_PRED:
        case MR_TYPECTOR_REP_INT:
        case MR_TYPECTOR_REP_FLOAT:
        case MR_TYPECTOR_REP_CHAR:
        case MR_TYPECTOR_REP_STRING:
        case MR_TYPECTOR_REP_BITMAP:
        case MR_TYPECTOR_REP_SUBGOAL:
        case MR_TYPECTOR_REP_VOID:
        case MR_TYPECTOR_REP_C_POINTER:
        case MR_TYPECTOR_REP_STABLE_C_POINTER:
        case MR_TYPECTOR_REP_TYPEINFO:
        case MR_TYPECTOR_REP_TYPECTORINFO:
        case MR_TYPECTOR_REP_TYPECLASSINFO:
        case MR_TYPECTOR_REP_BASETYPECLASSINFO:
        case MR_TYPECTOR_REP_TYPEDESC:
        case MR_TYPECTOR_REP_TYPECTORDESC:
        case MR_TYPECTOR_REP_PSEUDOTYPEDESC:
        case MR_TYPECTOR_REP_ARRAY:
        case MR_TYPECTOR_REP_REFERENCE:
        case MR_TYPECTOR_REP_SUCCIP:
        case MR_TYPECTOR_REP_HP:
        case MR_TYPECTOR_REP_CURFR:
        case MR_TYPECTOR_REP_MAXFR:
        case MR_TYPECTOR_REP_REDOFR:
        case MR_TYPECTOR_REP_REDOIP:
        case MR_TYPECTOR_REP_TRAIL_PTR:
        case MR_TYPECTOR_REP_TICKET:
        case MR_TYPECTOR_REP_FOREIGN:
        case MR_TYPECTOR_REP_STABLE_FOREIGN:
        case MR_TYPECTOR_REP_UNKNOWN:
            success = MR_FALSE;

        }
    }
    SUCCESS_INDICATOR = success;
}").
:- pragma foreign_proc("C", construct.get_functor_lex(TypeDesc :: (builtin.in), Ordinal :: (builtin.in)) = (FunctorNumber :: (builtin.out)), [will_not_call_mercury, thread_safe, not_tabled_for_io, promise_pure, may_modify_trail], "{
    MR_TypeInfo         type_info;
    MR_TypeCtorInfo     type_ctor_info;
    MR_Construct_Info   construct_info;
    int                 num_functors;

    type_info = (MR_TypeInfo) TypeDesc;

    /*
    ** Get information for this functor number and store in construct_info.
    ** If this is a discriminated union type and if the functor number is
    ** in range, we succeed.
    */
    MR_save_transient_registers();
    type_info = MR_collapse_equivalences(type_info);
    num_functors = MR_get_num_functors(type_info);
    MR_restore_transient_registers();
    type_ctor_info = MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info);
    if (Ordinal < 0 || Ordinal >= num_functors
            || !type_ctor_info->MR_type_ctor_functor_number_map)
    {
        SUCCESS_INDICATOR = MR_FALSE; 
    } else {
        FunctorNumber =
            type_ctor_info->MR_type_ctor_functor_number_map[Ordinal];
        SUCCESS_INDICATOR = MR_TRUE; 
    }
}").
construct.find_functor(Type_6, Functor_7, Arity_8, FunctorNumber_9, ArgTypes_10) :-
    N_11 = construct.num_functors(Type_6),
    construct.find_functor_2(Type_6, Functor_7, Arity_8, N_11, FunctorNumber_9, ArgTypes_10).
construct.construct_tuple(Args_3) = HeadVar__2_2 :-
    HeadVar__2_2 = construct.construct_tuple_2(Args_3, V_4, V_6),
    V_4 = list.map(V_5, Args_3),
    V_5 = univ.univ_type : ((func univ.univ) = type_desc.type_desc),
    V_6 = list.length(Args_3).
construct.null_to_no(S_3) = HeadVar__2_2 :-
    (if
      construct.null(S_3)
    then
      HeadVar__2_2 = maybe.no : maybe.maybe(string)
    else
      HeadVar__2_2 = maybe.yes(S_3) : maybe.maybe(string)
    ).
:- pragma foreign_proc("C", construct.null(S :: (builtin.in)), [will_not_call_mercury, thread_safe, not_tabled_for_io, promise_pure, may_modify_trail], "
    SUCCESS_INDICATOR = (S == NULL);
").
:- pragma exceptions(function, (construct.num_functors), 2, 0, will_not_throw).
:- pragma exceptions(function, (construct.det_num_functors), 2, 0, may_throw(user_exception)).
:- pragma exceptions(predicate, (construct.get_functor), 5, 0, will_not_throw).
:- pragma exceptions(predicate, (construct.get_functor_with_names), 6, 0, may_throw(user_exception)).
:- pragma exceptions(function, (construct.get_functor_ordinal), 3, 0, will_not_throw).
:- pragma exceptions(predicate, (construct.get_functor_ordinal), 3, 0, will_not_throw).
:- pragma exceptions(function, (construct.get_functor_lex), 3, 0, will_not_throw).
:- pragma exceptions(predicate, (construct.find_functor), 5, 0, may_throw(user_exception)).
:- pragma exceptions(function, (construct.construct), 4, 0, will_not_throw).
:- pragma exceptions(function, (construct.construct_tuple), 2, 0, may_throw(user_exception)).
:- pragma exceptions(predicate, (construct.get_functor_internal), 5, 0, will_not_throw).
:- pragma exceptions(predicate, (construct.get_functor_with_names_internal), 6, 0, will_not_throw).
:- pragma exceptions(function, (construct.null_to_no), 2, 0, will_not_throw).
:- pragma exceptions(predicate, (construct.null), 1, 0, will_not_throw).
:- pragma exceptions(predicate, (construct.find_functor_2), 6, 0, may_throw(user_exception)).
:- pragma exceptions(function, (construct.construct_tuple_2), 4, 0, will_not_throw).
:- pragma termination_info(construct.num_functors((builtin.in)) = (builtin.out), infinite, cannot_loop).
:- pragma termination_info(construct.det_num_functors((builtin.in)) = (builtin.out), infinite, can_loop).
:- pragma termination_info(construct.get_functor((builtin.in), (builtin.in), (builtin.out), (builtin.out), (builtin.out)), infinite, cannot_loop).
:- pragma termination_info(construct.get_functor_with_names((builtin.in), (builtin.in), (builtin.out), (builtin.out), (builtin.out), (builtin.out)), infinite, can_loop).
:- pragma termination_info(construct.get_functor_ordinal((builtin.in), (builtin.in)) = (builtin.out), infinite, cannot_loop).
:- pragma termination_info(construct.get_functor_ordinal((builtin.in), (builtin.in), (builtin.out)), infinite, cannot_loop).
:- pragma termination_info(construct.get_functor_lex((builtin.in), (builtin.in)) = (builtin.out), infinite, cannot_loop).
:- pragma termination_info(construct.find_functor((builtin.in), (builtin.in), (builtin.in), (builtin.out), (builtin.out)), infinite, can_loop).
:- pragma termination_info(construct.construct((builtin.in), (builtin.in), (builtin.in)) = (builtin.out), infinite, cannot_loop).
:- pragma termination_info(construct.construct_tuple((builtin.in)) = (builtin.out), infinite, can_loop).
:- pragma termination_info(construct.get_functor_internal((builtin.in), (builtin.in), (builtin.out), (builtin.out), (builtin.out)), infinite, cannot_loop).
:- pragma termination_info(construct.get_functor_with_names_internal((builtin.in), (builtin.in), (builtin.out), (builtin.out), (builtin.out), (builtin.out)), infinite, cannot_loop).
:- pragma termination_info(construct.null_to_no((builtin.in)) = (builtin.out), finite(1, [yes, no]), cannot_loop).
:- pragma termination_info(construct.null((builtin.in)), finite(0, [no]), cannot_loop).
:- pragma termination_info(construct.find_functor_2((builtin.in), (builtin.in), (builtin.in), (builtin.in), (builtin.out), (builtin.out)), infinite, can_loop).
:- pragma termination_info(construct.construct_tuple_2((builtin.in), (builtin.in), (builtin.in)) = (builtin.out), infinite, cannot_loop).
