[m-rev.] for review: implement RTTI for io__write on .NET
Mark Brown
dougl at cs.mu.OZ.AU
Wed Sep 26 03:50:08 AEST 2001
Hi Tyson,
Aside from the things mentioned below, this diff looks okay to me.
Cheers,
Mark.
On Thu, Sep 20, 2001 at 02:56:30PM +0200, Tyson Dowd wrote:
> Hi,
>
> Most of the time spent on this was actually spent grappling with the
> problem that generated structs were being generated as nested arrays,
> and not nested structures.
>
> I attribute that debugging time to this change because the behaviour
> might be considered correct, only that for the purposes of RTTI it isn't
> what we want to be able to effectively use these data structures.
>
> As a side effect of this change uncaught exceptions are now printed
> correctly.
This comment would be useful in the log message, I think.
>
> ===================================================================
>
>
> Estimated hours taken: 50
> Branches: main
>
> Implement most of the RTTI required for io__write to work in the .NET
> backend. With this code most of tests/hard_coded/write.m work (up until
> the point where we try to write a univ).
>
> We don't yet handle higher-order terms or existentially quantified type
> variables.
>
> library/io.m:
> Prepend an "_" to some unused variables.
> Move unsafe_cast from io.m into rtti_implementation.m -- it is
> useful in rtti_implementation (and possibly elsewhere), and it's
> better to have io depend on rtti_implementation than vice-versa.
>
> library/rtti_implementation.m:
> Implement type_ctor_name_and_arity for commonly occuring data
> representations.
>
> Add type_ctor_is_variable_arity to simplfy this test.
> Rename index as type_info_index to make it clear what we are
> indexing into.
>
> library/std_util.m:
> Improve some of the error messages to make it easier to track
> down unimplemented code.
> Call into rtti_implementation for type_ctor_and_args.
> Use pragma export to generate ML_call_rtti_compare_type_infos
> (it wasn't available before so we jumped through a few more
> hoops to call into rtti_implementation).
>
>
>
> Index: library/io.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/library/io.m,v
> retrieving revision 1.231
> diff -u -r1.231 io.m
> --- library/io.m 12 Sep 2001 10:34:45 -0000 1.231
> +++ library/io.m 20 Sep 2001 10:23:28 -0000
> @@ -1120,6 +1120,7 @@
> :- import_module map, dir, term, term_io, varset, require, benchmarking, array.
> :- import_module bool, int, parser, exception.
> :- use_module table_builtin.
> +:- use_module rtti_implementation.
>
> :- type io__state ---> io__state(c_pointer).
> % Values of type `io__state' are never really used:
> @@ -1594,7 +1595,7 @@
> MR_PROC_LABEL, RetStr);
> }").
>
> -:- pragma foreign_proc("MC++", ferror(Stream::in, RetVal::out, RetStr::out,
> +:- pragma foreign_proc("MC++", ferror(_Stream::in, RetVal::out, _RetStr::out,
> IO0::di, IO::uo),
> [will_not_call_mercury, thread_safe],
> "{
> @@ -2410,23 +2411,9 @@
> :- pred io__write_private_builtin_type_info(private_builtin__type_info(T)::in,
> io__state::di, io__state::uo) is det.
> io__write_private_builtin_type_info(PrivateBuiltinTypeInfo) -->
> - { TypeInfo = unsafe_cast(PrivateBuiltinTypeInfo) },
> + { TypeInfo = rtti_implementation__unsafe_cast(PrivateBuiltinTypeInfo) },
> io__write_type_desc(TypeInfo).
>
> -:- func unsafe_cast(T1::in) = (T2::out) is det.
> -:- pragma foreign_proc("C",
> - unsafe_cast(VarIn::in) = (VarOut::out),
> - [will_not_call_mercury, thread_safe],
> -"
> - VarOut = VarIn;
> -").
> -:- pragma foreign_proc("C#",
> - unsafe_cast(VarIn::in) = (VarOut::out),
> - [will_not_call_mercury, thread_safe],
> -"
> - VarOut = VarIn;
> -").
> -
> %-----------------------------------------------------------------------------%
>
> io__write_list([], _Separator, _OutputPred) --> [].
> @@ -3621,7 +3608,7 @@
> }").
>
> :- pragma foreign_proc("MC++",
> - io__putback_byte(File::in, Character::in, IO0::di, IO::uo),
> + io__putback_byte(File::in, _Character::in, IO0::di, IO::uo),
> may_call_mercury, "{
>
> MR_MercuryFile mf = ML_DownCast(MR_MercuryFile,
> Index: library/rtti_implementation.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/library/rtti_implementation.m,v
> retrieving revision 1.4
> diff -u -r1.4 rtti_implementation.m
> --- library/rtti_implementation.m 22 Aug 2001 12:29:01 -0000 1.4
> +++ library/rtti_implementation.m 20 Sep 2001 10:23:29 -0000
> @@ -28,6 +28,10 @@
>
> :- interface.
>
> +:- import_module list.
> +
> +:- use_module std_util.
> +
> % Our type_info and type_ctor_info implementations are both
> % abstract types.
> :- type type_info.
> @@ -42,12 +46,26 @@
> :- pred compare_type_infos(comparison_result::out,
> type_info::in, type_info::in) is det.
>
> +:- pred type_ctor_and_args(type_info::in,
> + type_ctor_info::out,
> + list(type_info)::out) is det.
> +
> +:- pred type_ctor_name_and_arity(type_ctor_info::in,
> + string::out, string::out, int::out) is det.
> +
> +:- pred deconstruct(T::in, string::out, int::out,
> + list(std_util__univ)::out) is det.
The log message should mention all of these additions.
> +
> + % This is useful in a few places, so we'd like to share the code, but
> + % it's better to put it into an implementation module such as this one.
> +:- func unsafe_cast(T1::in) = (T2::out) is det.
> +
> %-----------------------------------------------------------------------------%
> %-----------------------------------------------------------------------------%
>
> :- implementation.
>
> -:- import_module require, string.
> +:- import_module require, string, int.
>
> % std_util has a lot of types and functions with the same names,
> % so we prefer to keep the namespace separate.
> @@ -80,7 +98,7 @@
> ; array
> ; succip
> ; hp
> - ; currfr
> + ; curfr
The log message doesn't mention this change.
> ; maxfr
> ; redofr
> ; redoip
> @@ -135,26 +153,32 @@
> result_call_4(ComparePred, Res, X, Y)
> ; Arity = 1 ->
> result_call_5(ComparePred, Res,
> - TypeInfo ^ index(1), X, Y)
> + TypeInfo ^ type_info_index(1), X, Y)
> ; Arity = 2 ->
> result_call_6(ComparePred, Res,
> - TypeInfo ^ index(1), TypeInfo ^ index(2),
> + TypeInfo ^ type_info_index(1),
> + TypeInfo ^ type_info_index(2),
> X, Y)
> ; Arity = 3 ->
> result_call_7(ComparePred, Res,
> - TypeInfo ^ index(1), TypeInfo ^ index(2),
> - TypeInfo ^ index(3),
> + TypeInfo ^ type_info_index(1),
> + TypeInfo ^ type_info_index(2),
> + TypeInfo ^ type_info_index(3),
> X, Y)
> ; Arity = 4 ->
> result_call_8(ComparePred, Res,
> - TypeInfo ^ index(1), TypeInfo ^ index(2),
> - TypeInfo ^ index(3), TypeInfo ^ index(4),
> + TypeInfo ^ type_info_index(1),
> + TypeInfo ^ type_info_index(2),
> + TypeInfo ^ type_info_index(3),
> + TypeInfo ^ type_info_index(4),
> X, Y)
> ; Arity = 5 ->
> result_call_9(ComparePred, Res,
> - TypeInfo ^ index(1), TypeInfo ^ index(2),
> - TypeInfo ^ index(3), TypeInfo ^ index(4),
> - TypeInfo ^ index(5),
> + TypeInfo ^ type_info_index(1),
> + TypeInfo ^ type_info_index(2),
> + TypeInfo ^ type_info_index(3),
> + TypeInfo ^ type_info_index(4),
> + TypeInfo ^ type_info_index(5),
> X, Y)
> ;
> error("compare/3: type arity > 5 not supported")
> @@ -180,26 +204,33 @@
> ( Arity = 0 ->
> semidet_call_3(UnifyPred, X, Y)
> ; Arity = 1 ->
> - semidet_call_4(UnifyPred, TypeInfo ^ index(1), X, Y)
> + semidet_call_4(UnifyPred,
> + TypeInfo ^ type_info_index(1), X, Y)
> ; Arity = 2 ->
> semidet_call_5(UnifyPred,
> - TypeInfo ^ index(1), TypeInfo ^ index(2),
> + TypeInfo ^ type_info_index(1),
> + TypeInfo ^ type_info_index(2),
> X, Y)
> ; Arity = 3 ->
> semidet_call_6(UnifyPred,
> - TypeInfo ^ index(1), TypeInfo ^ index(2),
> - TypeInfo ^ index(3),
> + TypeInfo ^ type_info_index(1),
> + TypeInfo ^ type_info_index(2),
> + TypeInfo ^ type_info_index(3),
> X, Y)
> ; Arity = 4 ->
> semidet_call_7(UnifyPred,
> - TypeInfo ^ index(1), TypeInfo ^ index(2),
> - TypeInfo ^ index(3), TypeInfo ^ index(4),
> + TypeInfo ^ type_info_index(1),
> + TypeInfo ^ type_info_index(2),
> + TypeInfo ^ type_info_index(3),
> + TypeInfo ^ type_info_index(4),
> X, Y)
> ; Arity = 5 ->
> semidet_call_8(UnifyPred,
> - TypeInfo ^ index(1), TypeInfo ^ index(2),
> - TypeInfo ^ index(3), TypeInfo ^ index(4),
> - TypeInfo ^ index(5),
> + TypeInfo ^ type_info_index(1),
> + TypeInfo ^ type_info_index(2),
> + TypeInfo ^ type_info_index(3),
> + TypeInfo ^ type_info_index(4),
> + TypeInfo ^ type_info_index(5),
> X, Y)
> ;
> error("unify/2: type arity > 5 not supported")
> @@ -414,11 +445,7 @@
> TypeCtorInfo2 ^ type_ctor_module_name),
> (
> Res = (=),
> - TypeCtorInfo1 ^ type_ctor_module_name = "builtin",
> - ( TypeCtorInfo1 ^ type_ctor_name = "tuple"
> - ; TypeCtorInfo1 ^ type_ctor_name = "pred"
> - ; TypeCtorInfo1 ^ type_ctor_name = "func"
> - )
> + type_ctor_is_variable_arity(TypeCtorInfo1)
> ->
> % XXX code to handle tuples and higher order
> error("rtti_implementation.m: unimplemented: tuples and higher order type comparisons")
> @@ -429,6 +456,12 @@
> Res = NameRes
> ).
>
> +:- pred type_ctor_is_variable_arity(type_ctor_info::in) is semidet.
> +type_ctor_is_variable_arity(TypeCtorInfo) :-
> + ( TypeCtorInfo ^ type_ctor_rep = (pred)
> + ; TypeCtorInfo ^ type_ctor_rep = tuple
> + ).
> +
> %-----------------------------------------------------------------------------%
> %-----------------------------------------------------------------------------%
>
> @@ -455,6 +488,471 @@
>
> %-----------------------------------------------------------------------------%
> %-----------------------------------------------------------------------------%
> +
> +type_ctor_name_and_arity(TypeCtorInfo, ModuleName, Name, Arity) :-
> + ModuleName = type_ctor_module_name(TypeCtorInfo),
> + Name = type_ctor_name(TypeCtorInfo),
> + Arity = type_ctor_arity(TypeCtorInfo).
> +
> +type_ctor_and_args(TypeInfo0, TypeCtorInfo, TypeArgs) :-
> + TypeInfo = collapse_equivalences(TypeInfo0),
> + TypeCtorInfo = get_type_ctor_info(TypeInfo),
> + (
> + type_ctor_is_variable_arity(TypeCtorInfo)
> + ->
> + error("rtti_implementation.m: unimplemented: tuples and higher order type comparisons")
> + ;
> + Arity = type_ctor_arity(TypeCtorInfo),
> + TypeArgs = iterate(1, Arity,
> + (func(X) = Y :-
> + Y = TypeInfo ^ type_info_index(X)
> + )
> + )
> + ).
> +
> +:- func iterate(int, int, func(int, T)) = list(T).
> +iterate(Start, Max, Func) = Results :-
> + ( Start =< Max ->
> + Res = Func(Start),
> + Results = [Res | iterate(Start + 1, Max, Func)]
> + ;
> + Results = []
> + ).
> +
> +:- pred iterate_foldl(int, int, pred(int, T, T), T, T).
> +:- mode iterate_foldl(in, in, pred(in, in, out) is det, in, out) is det.
> +iterate_foldl(Start, Max, Pred) -->
> + ( { Start =< Max } ->
> + Pred(Start),
> + iterate_foldl(Start + 1, Max, Pred)
> + ;
> + []
> + ).
> +
> +%-----------------------------------------------------------------------------%
> +%-----------------------------------------------------------------------------%
> +
> +
> + % Code to perform deconstructions (not yet complete).
> + %
> + % There are many cases to implement here, only the ones that were
> + % immediately useful (e.g. called by io__write) have been implemented
> + % so far.
> +
> +deconstruct(Term, Functor, Arity, Arguments) :-
> + TypeInfo = get_type_info(Term),
> + TypeCtorInfo = get_type_ctor_info(TypeInfo),
> + TypeCtorRep = type_ctor_rep(TypeCtorInfo),
> + (
> + TypeCtorRep = enum_usereq,
> + Functor = "some_enum_usereq",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = enum,
> + Functor = "some_enum",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = du_usereq,
> + Functor = "some_du_usereq",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = du,
> +
> + LayoutInfo = type_layout(TypeCtorInfo),
> + PTag = get_primary_tag(Term),
> + PTagEntry = LayoutInfo ^ ptag_index(PTag),
> + SecTagLocn = PTagEntry ^ sectag_locn,
> + (
> + SecTagLocn = none,
> + FunctorDesc = PTagEntry ^ du_sectag_alternatives(0),
> + Functor = FunctorDesc ^ functor_name,
> + Arity = FunctorDesc ^ functor_arity,
> + Arguments = iterate(0, Arity - 1,
> + (func(X) = std_util__univ(
> + get_arg(Term, X, SecTagLocn,
> + FunctorDesc, TypeInfo))
> + ))
> + ;
> + SecTagLocn = local,
> + Functor = "some_du_local_sectag",
> + Arity = 0,
> + Arguments = []
> + ;
> + SecTagLocn = remote,
> + SecTag = get_remote_secondary_tag(Term),
> + FunctorDesc = PTagEntry ^
> + du_sectag_alternatives(SecTag),
> + Functor = FunctorDesc ^ functor_name,
> + Arity = FunctorDesc ^ functor_arity,
> + Arguments = iterate(0, Arity - 1,
> + (func(X) = std_util__univ(
> + get_arg(Term, X, SecTagLocn,
> + FunctorDesc, TypeInfo))
> + ))
> + ;
> + SecTagLocn = variable,
> + Functor = "some_du_variable_sectag",
> + Arity = 0,
> + Arguments = []
> + )
> + ;
> + TypeCtorRep = notag_usereq,
> + Functor = "some_notag_usereq",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = notag,
> + Functor = "some_notag",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = notag_ground_usereq,
> + Functor = "some_notag_ground_usereq",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = notag_ground,
> + Functor = "some_notag_ground",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = equiv_ground,
> + Functor = "some_equiv_ground",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = equiv_var,
> + Functor = "some_equiv_var",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = equiv,
> + Functor = "some_equiv",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = int,
> + Functor = "some_int",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = char,
> + Functor = "some_char",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = float,
> + Functor = "some_float",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = string,
> + Functor = "some_string",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = (pred),
> + Functor = "some_pred",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = tuple,
> + Functor = "some_tuple",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = univ,
> + Functor = "some_univ",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = void,
> + Functor = "some_void",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = c_pointer,
> + Functor = "some_c_pointer",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = typeinfo,
> + Functor = "some_typeinfo",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = typeclassinfo,
> + Functor = "some_typeclassinfo",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = array,
> + Functor = "some_array",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = succip,
> + Functor = "some_succip",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = hp,
> + Functor = "some_hp",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = curfr,
> + Functor = "some_curfr",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = maxfr,
> + Functor = "some_maxfr",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = redofr,
> + Functor = "some_redofr",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = redoip,
> + Functor = "some_redoip",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = trail_ptr,
> + Functor = "some_trail_ptr",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = ticket,
> + Functor = "some_ticket",
> + Arity = 0,
> + Arguments = []
> + ;
> + TypeCtorRep = unknown,
> + Functor = "some_unknown",
> + Arity = 0,
> + Arguments = []
> + ).
> +
> +
> +
> + % Retrieve an argument number from a term, given the functor
> + % descriptor.
> +
> +:- some [T] func get_arg(
> + U, int, sectag_locn, du_functor_descriptor, type_info) = T.
> +
> +get_arg(Term, Index, SecTagLocn, FunctorDesc, TypeInfo) = (Arg) :-
> + ArgTypes = FunctorDesc ^ functor_arg_types,
> + PseudoTypeInfo = get_pti_from_arg_types(ArgTypes, Index),
> + ( SecTagLocn = none ->
> + TagOffset = 0
> + ;
> + TagOffset = 1
> + ),
> + ArgTypeInfo = get_type(TypeInfo, PseudoTypeInfo, Term, FunctorDesc),
> + Arg = get_subterm(ArgTypeInfo, Term, Index, TagOffset).
> +
> +:- func get_type(type_info, P, T, du_functor_descriptor) = type_info.
> +
> +get_type(TypeInfoParams, PseudoTypeInfo, Term, FunctorDesc) = (ArgTypeInfo) :-
> + (
> + typeinfo_is_variable(PseudoTypeInfo, VarNum)
> + ->
> + ExpandedTypeInfo = get_type_info_for_var(TypeInfoParams,
> + VarNum, Term, FunctorDesc),
> + ( typeinfo_is_variable(ExpandedTypeInfo, _) ->
> + error("unbound type variable")
It would be better if this error string mentioned the function.
> + ;
> + ArgTypeInfo = ExpandedTypeInfo
> + )
> + ;
> + CastTypeInfo = type_info_cast(PseudoTypeInfo),
> + TypeCtorInfo = get_type_ctor_info(CastTypeInfo),
> + (
> + type_ctor_is_variable_arity(TypeCtorInfo)
> + ->
> + Arity = pseudotypeinfo_get_higher_order_arity(
> + CastTypeInfo),
> + StartRegionSize = 2
> + ;
> + Arity = TypeCtorInfo ^ type_ctor_arity,
> + StartRegionSize = 1
> + ),
> + ArgTypeInfo0 = std_util__no,
> + UpperBound = Arity + StartRegionSize - 1,
> +
> + iterate_foldl(StartRegionSize, UpperBound,
> + (pred(I::in, TI0::in, TI::out) is det :-
> +
> + PTI = get_pti_from_type_info(CastTypeInfo, I),
> + ETypeInfo = get_type(
> + TypeInfoParams, PTI, Term, FunctorDesc),
> + % this comparison is not
> + % right...???
I'm not sure what this comment means. Is this supposed to be an XXX?
> + (
> + same_pointer_value_untyped(
> + ETypeInfo, PTI)
> + ->
> + TI = TI0
> + ;
> + TI0 = std_util__yes(TypeInfo)
> + ->
> + update_type_info_index(I,
> + TypeInfo, ETypeInfo),
> + TI = std_util__yes(TypeInfo)
> + ;
> + NewTypeInfo = new_type_info(
> + CastTypeInfo, UpperBound),
> + update_type_info_index(I,
> + NewTypeInfo, ETypeInfo),
> + TI = std_util__yes(NewTypeInfo)
> + )
> + ), ArgTypeInfo0, MaybeArgTypeInfo),
> + ( MaybeArgTypeInfo = std_util__yes(ArgTypeInfo1) ->
> + ArgTypeInfo = ArgTypeInfo1
> + ;
> + ArgTypeInfo = CastTypeInfo
> + )
> + ).
> +
> +
> + % XXX this is completely unimplemented.
> +:- func pseudotypeinfo_get_higher_order_arity(type_info) = int.
> +pseudotypeinfo_get_higher_order_arity(_) = 1 :-
> + det_unimplemented("pseudotypeinfo_get_higher_order_arity").
> +
Why not give the "unimplemented" predicate a determinism of erroneous?
That way you wouldn't have to supply a dummy return value. (I realise
it wasn't added as part of this change, but I thought I'd mention it
here anyway.)
> +
> + % Make a new type-info with the given arity, using the given type_info
> + % as the basis.
> +
> +:- func new_type_info(type_info, int) = type_info.
> +new_type_info(TypeInfo::in, _::in) = (TypeInfo::out) :-
> + det_unimplemented("new_type_info").
> +
> +:- pragma foreign_proc("C#",
> + new_type_info(OldTypeInfo::in, Arity::in) = (NewTypeInfo::out), [], "
> + NewTypeInfo = new object[Arity + 1];
> + System.Array.Copy(OldTypeInfo, NewTypeInfo, OldTypeInfo.Length);
> +").
> +
> +
> + % Get the pseudo-typeinfo at the given index from the argument types.
> +
> +:- some [T] func get_pti_from_arg_types(arg_types, int) = T.
> +
> +get_pti_from_arg_types(_::in, _::in) = (42::out) :-
> + det_unimplemented("get_pti_from_arg_types").
> +
> +:- pragma foreign_proc("C#",
> + get_pti_from_arg_types(ArgTypes::in, Index::in) =
> + (ArgTypeInfo::out), [], "
> + ArgTypeInfo = ArgTypes[Index];
> +").
> +
> +
> + % Get the pseudo-typeinfo at the given index from a type-info.
> +
> +:- some [T] func get_pti_from_type_info(type_info, int) = T.
> +
> +get_pti_from_type_info(_::in, _::in) = (42::out) :-
> + det_unimplemented("get_pti_from_type_info").
> +
> +:- pragma foreign_proc("C#",
> + get_pti_from_type_info(TypeInfo::in, Index::in) = (PTI::out), [], "
> + PTI = TypeInfo[Index];
> +").
> +
> +
> +
> + % Get the type info for a particular type variable number
> + % (it might be in the type_info or in the term itself).
> + %
> + % XXX existentially quantified vars are not yet handled.
> +
> +:- func get_type_info_for_var(
> + type_info, int, T, du_functor_descriptor) = type_info.
> +
> +get_type_info_for_var(TypeInfo, VarNum, _Term, _FunctorDesc) = ArgTypeInfo :-
> + (
> + type_variable_is_univ_quant(VarNum)
> + ->
> + ArgTypeInfo = TypeInfo ^ type_info_index(VarNum)
> + ;
> + error("get_type_info_for_var for exist quant vars")
> + ).
> +
> +
> + % An unchecked cast to type_info (for pseudo-typeinfos).
> +
> +:- func type_info_cast(T) = type_info.
> +
> +type_info_cast(X::in) = (unsafe_cast(X)::out) :-
> + det_unimplemented("type_info_cast").
It looks implemented to me. What else needs to be done other than call
unsafe_cast?
> +
> +:- pragma foreign_proc("C#",
> + type_info_cast(PseudoTypeInfo::in) = (TypeInfo::out), [], "
> +
> + TypeInfo = (object[]) PseudoTypeInfo;
> +").
If you can use the previous clause, then this clause won't be needed at all.
The C# code in the implementation of unsafe_cast will be used instead.
> +
> +
> + % Get a subterm term, given its type_info, the original term, its
> + % index and the start region size.
> +
> +:- some [T] func get_subterm(type_info, U, int, int) = T.
> +
> +get_subterm(_::in, _::in, _::in, _::in) = (42::out) :-
> + det_unimplemented("get_subterm").
> +
> +:- pragma foreign_proc("C#",
> + get_subterm(TypeInfo::in, Term::in, Index::in,
> + TagOffset::in) = (Arg::out), [], "
> + Arg = ((object[]) Term)[Index + TagOffset];
> + TypeInfo_for_T = TypeInfo;
> +").
> +
> +
> + % Test whether a type info is variable.
> +
> +:- pred typeinfo_is_variable(T::in, int::out) is semidet.
> +
> +typeinfo_is_variable(_::in, 42::out) :-
> + std_util__semidet_succeed,
> + det_unimplemented("typeinfo_is_variable").
That would be like calling semidet_unimplemented. ;-)
> +
> +:- pragma foreign_proc("MC++",
> + typeinfo_is_variable(TypeInfo::in, VarNum::out), [], "
> + SUCCESS_INDICATOR = (dynamic_cast<MR_Word>(TypeInfo) == NULL);
> + if (SUCCESS_INDICATOR) {
> + VarNum = System::Convert::ToInt32(TypeInfo);
> + }
> +").
> +
> +
> + % Tests for universal and existentially quantified variables.
> +
> +:- pred type_variable_is_univ_quant(int::in) is semidet.
> +:- pred type_variable_is_exist_quant(int::in) is semidet.
> +
> +type_variable_is_exist_quant(X) :- X > pseudotypeinfo_exist_var_base.
> +type_variable_is_univ_quant(X) :- X =< pseudotypeinfo_exist_var_base.
> +
> +:- func pseudotypeinfo_exist_var_base = int.
> +:- func pseudotypeinfo_max_var = int.
> +
> +pseudotypeinfo_exist_var_base = 512.
> +pseudotypeinfo_max_var = 1024.
> +
> +
> +%-----------------------------------------------------------------------------%
> +%-----------------------------------------------------------------------------%
> %
> % XXX we have only implemented the .NET backend for the low-level data case.
>
> @@ -466,16 +964,34 @@
> // Fill this in as you add new field accessors.
>
> enum type_ctor_info_field_nums {
> - type_ctor_arity = 0,
> - type_ctor_unify_pred = 1,
> - type_ctor_compare_pred = 3,
> - type_ctor_rep = 4,
> - type_ctor_module_name = 7,
> - type_ctor_name = 8,
> - type_functors = 10,
> - type_layout = 11,
> - type_ctor_num_functors = 12,
> - type_ctor_num_ptags = 13
> + type_ctor_arity = 0,
> + type_ctor_unify_pred = 1,
> + type_ctor_compare_pred = 3,
> + type_ctor_rep = 4,
> + type_ctor_module_name = 7,
> + type_ctor_name = 8,
> + type_functors = 10,
> + type_layout = 11,
> + type_ctor_num_functors = 12,
> + type_ctor_num_ptags = 13
> + }
> +
> + enum ptag_layout_field_nums {
> + sectag_sharers = 0,
> + sectag_locn = 1,
> + sectag_alternatives = 2
> + }
> +
> + enum du_functor_field_nums {
> + du_functor_name = 0,
> + du_functor_orig_arity = 1,
> + du_functor_arg_type_contains_var = 2,
> + du_functor_sectag_locn = 3,
> + du_functor_primary = 4,
> + du_functor_secondary = 5,
> + du_functor_ordinal = 6,
> + du_functor_arg_types = 7,
> + du_functor_exist_info = 8
> }
>
> ").
> @@ -499,30 +1015,156 @@
>
>
> :- pred same_pointer_value(T::in, T::in) is semidet.
> +:- pred same_pointer_value_untyped(T::in, U::in) is semidet.
> +
> +same_pointer_value(X, Y) :- same_pointer_value_untyped(X, Y).
>
> :- pragma foreign_proc("MC++",
> - same_pointer_value(T1::in, T2::in), [], "
> + same_pointer_value_untyped(T1::in, T2::in), [], "
> SUCCESS_INDICATOR = (T1 == T2);
> ").
> :- pragma foreign_proc("C",
> - same_pointer_value(T1::in, T2::in), [], "
> + same_pointer_value_untyped(T1::in, T2::in), [], "
> SUCCESS_INDICATOR = (T1 == T2);
> ").
>
> %-----------------------------------------------------------------------------%
> %-----------------------------------------------------------------------------%
>
> -:- func index(int, type_info) = type_info.
> +
> +:- func get_primary_tag(T) = int.
> +:- func get_remote_secondary_tag(T) = int.
> +
> +get_primary_tag(_::in) = (0::out) :-
> + det_unimplemented("get_primary_tag").
> +
> +get_remote_secondary_tag(_::in) = (0::out) :-
> + det_unimplemented("get_remote_secondary_tag").
> +
> :- pragma foreign_proc("C#",
> - index(X::in, TypeInfo::in) = (TypeInfoAtIndex::out), [], "
> - TypeInfoAtIndex = (object[]) TypeInfo[X];
> + get_primary_tag(X::in) = (Tag::out), [], "
> + // We don't look at X to find the tag, for .NET low-level data
> + // there is no primary tag, so we always return zero.
> + Tag = 0;
> ").
>
> +:- pragma foreign_proc("C#",
> + get_remote_secondary_tag(X::in) = (Tag::out), [], "
> + object[] data = (object[]) X;
> + Tag = (int) data[0];
> +").
> +
> +
> +
> +:- type sectag_locn ---> none ; local ; remote ; variable.
> +
> +:- type du_sectag_alternatives ---> du_sectag_alternatives(c_pointer).
> +
> +:- type ptag_entry ---> ptag_entry(c_pointer).
> +
> +:- type du_functor_descriptor ---> du_functor_descriptor(c_pointer).
> +
> +:- type arg_types ---> arg_types(c_pointer).
> +
> +:- func ptag_index(int, type_layout) = ptag_entry.
> +
> % This is an "unimplemented" definition in Mercury, which will be
> % used by default.
>
> -index(_::in, TypeInfo::in) = (TypeInfo::out) :-
> - det_unimplemented("index").
> +ptag_index(_::in, TypeLayout::in) = (unsafe_cast(TypeLayout)::out) :-
> + det_unimplemented("ptag_index").
> +
> +:- pragma foreign_proc("C#",
> + ptag_index(X::in, TypeLayout::in) = (PtagEntry::out), [], "
> + PtagEntry = (object[]) TypeLayout[X];
> +").
> +
> +:- func sectag_locn(ptag_entry) = sectag_locn.
> +
> +sectag_locn(PTagEntry::in) = (unsafe_cast(PTagEntry)::out) :-
> + det_unimplemented("sectag_locn").
> +
> +:- pragma foreign_proc("C#",
> + sectag_locn(PTagEntry::in) = (SectagLocn::out), [], "
> + SectagLocn = mercury.runtime.LowLevelData.make_enum((int)
> + PTagEntry[(int) ptag_layout_field_nums.sectag_locn]);
> +").
> +
> +:- func du_sectag_alternatives(int, ptag_entry) = du_functor_descriptor.
> +
> +du_sectag_alternatives(_::in, PTagEntry::in) = (unsafe_cast(PTagEntry)::out) :-
> + det_unimplemented("sectag_alternatives").
> +
> +:- pragma foreign_proc("C#",
> + du_sectag_alternatives(X::in, PTagEntry::in) =
> + (FunctorDescriptor::out), [], "
> + object[] sectag_alternatives;
> + sectag_alternatives = (object [])
> + PTagEntry[(int) ptag_layout_field_nums.sectag_alternatives];
> + FunctorDescriptor = (object []) sectag_alternatives[X];
> +").
> +
> +:- func functor_name(du_functor_descriptor) = string.
> +
> +functor_name(FunctorDescriptor::in) = (unsafe_cast(FunctorDescriptor)::out) :-
> + det_unimplemented("functor_name").
> +
> +:- pragma foreign_proc("C#",
> + functor_name(FunctorDescriptor::in) = (Name::out), [], "
> + Name = (string)
> + FunctorDescriptor[(int) du_functor_field_nums.du_functor_name];
> +").
> +
> +:- func functor_arity(du_functor_descriptor) = int.
> +
> +functor_arity(FunctorDescriptor::in) = (unsafe_cast(FunctorDescriptor)::out) :-
> + det_unimplemented("functor_arity").
> +
> +:- pragma foreign_proc("C#",
> + functor_arity(FunctorDescriptor::in) = (Name::out), [], "
> + Name = (int)
> + FunctorDescriptor[(int)
> + du_functor_field_nums.du_functor_orig_arity];
> +
> +").
> +
> +:- func functor_arg_types(du_functor_descriptor) = arg_types.
> +
> +functor_arg_types(X::in) = (unsafe_cast(X)::out) :-
> + det_unimplemented("functor_arg_types").
> +
> +:- pragma foreign_proc("C#",
> + functor_arg_types(FunctorDescriptor::in) = (ArgTypes::out), [], "
> + ArgTypes = (object[])
> + FunctorDescriptor[(int)
> + du_functor_field_nums.du_functor_arg_types];
> +
> +").
> +%-----------------------------------------------------------------------------%
> +%-----------------------------------------------------------------------------%
> +
> +:- func type_info_index(int, type_info) = type_info.
> +
> + % This is an "unimplemented" definition in Mercury, which will be
> + % used by default.
> +
> +type_info_index(_::in, TypeInfo::in) = (TypeInfo::out) :-
> + det_unimplemented("type_info_index").
> +
> +:- pragma foreign_proc("C#",
> + type_info_index(X::in, TypeInfo::in) = (TypeInfoAtIndex::out), [], "
> + TypeInfoAtIndex = (object[]) TypeInfo[X];
> +").
> +
> +update_type_info_index(_::in, _::in, _::in) :-
> + det_unimplemented("type_info_index").
> +
> +:- pred update_type_info_index(int::in, type_info::in, type_info::in) is det.
> +:- pragma foreign_proc("C#",
> + update_type_info_index(X::in, OldTypeInfo::in, NewValue::in), [], "
> + OldTypeInfo[X] = NewValue;
> +").
> +
This implementation performs destructive update on the type info, so you
should thread it through the predicate using unique modes to ensure that
the compiler can't optimize away calls to the predicate, and to ensure that
no attempts are made to use the previous value.
>
>
> :- pred semidet_unimplemented(string::in) is semidet.
> @@ -638,8 +1280,23 @@
> :- pragma foreign_proc("C",
> type_layout(TypeCtorInfo::in) = (TypeLayout::out), [], "
> MR_TypeCtorInfo tci = (MR_TypeCtorInfo) TypeCtorInfo;
> - TypeLayout = tci->type_layout;
> + TypeLayout = (MR_Word) &(tci->type_layout);
> +").
This is not mentioned in the log message.
> +
> +:- pragma foreign_proc("C",
> + unsafe_cast(VarIn::in) = (VarOut::out),
> + [will_not_call_mercury, thread_safe],
> +"
> + VarOut = VarIn;
> ").
> +:- pragma foreign_proc("C#",
> + unsafe_cast(VarIn::in) = (VarOut::out),
> + [will_not_call_mercury, thread_safe],
> +"
> + VarOut = VarIn;
> +").
> +
> +
>
> %-----------------------------------------------------------------------------%
> %-----------------------------------------------------------------------------%
> Index: library/std_util.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/library/std_util.m,v
> retrieving revision 1.240
> diff -u -r1.240 std_util.m
> --- library/std_util.m 24 Aug 2001 09:31:25 -0000 1.240
> +++ library/std_util.m 20 Sep 2001 10:23:31 -0000
> @@ -881,7 +881,7 @@
>
> #ifdef MR_USE_TRAIL
> /* XXX trailing not yet implemented for the MLDS back-end */
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> + mercury::runtime::Errors::SORRY(""foreign code for get_registers"");
> #else
> TrailPtr = 0
> #endif
> @@ -902,7 +902,7 @@
> check_for_floundering(_TrailPtr::in), [will_not_call_mercury],
> "
> #ifdef MR_USE_TRAIL
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> + mercury::runtime::Errors::SORRY(""foreign code for check_for_floundering"");
> #endif
> ").
>
> @@ -921,7 +921,7 @@
> discard_trail_ticket, [will_not_call_mercury],
> "
> #ifdef MR_USE_TRAIL
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> + mercury::runtime::Errors::SORRY(""foreign code for discard_trail_ticket"");
> #endif
> ").
>
> @@ -1414,16 +1414,18 @@
>
> % We need to call the rtti_implementation module -- so that we get the
> % dependencies right it's easiest to do it from Mercury.
> -:- interface.
> -:- use_module rtti_implementation.
> +
> +:- pragma export(call_rtti_compare_type_infos(out, in, in),
> + "ML_call_rtti_compare_type_infos").
> +
> :- pred call_rtti_compare_type_infos(comparison_result::out,
> rtti_implementation__type_info::in, rtti_implementation__type_info::in) is det.
> -:- implementation.
> +
> +:- use_module rtti_implementation.
>
> call_rtti_compare_type_infos(Res, T1, T2) :-
> rtti_implementation__compare_type_infos(Res, T1, T2).
>
> -
> :- pragma foreign_code("MC++", "
>
> MR_DEFINE_BUILTIN_TYPE_CTOR_INFO(std_util, type_desc, 0,
> @@ -1432,7 +1434,7 @@
> static int MR_compare_type_info(MR_Word t1, MR_Word t2) {
> MR_Word res;
>
> - mercury::std_util::mercury_code::call_rtti_compare_type_infos_3(
> + mercury::std_util::mercury_code::ML_call_rtti_compare_type_infos(
> &res, t1, t2);
> return System::Convert::ToInt32(res[0]);
> }
> @@ -1441,7 +1443,7 @@
> __Compare____type_desc_0_0(
> MR_Word_Ref result, MR_Word x, MR_Word y)
> {
> - mercury::std_util::mercury_code::call_rtti_compare_type_infos_3(
> + mercury::std_util::mercury_code::ML_call_rtti_compare_type_infos(
> result, x, y);
> }
>
> @@ -1455,7 +1457,7 @@
> special___Compare___type_desc_0_0(
> MR_Word_Ref result, MR_Word x, MR_Word y)
> {
> - mercury::std_util::mercury_code::call_rtti_compare_type_infos_3(
> + mercury::std_util::mercury_code::ML_call_rtti_compare_type_infos(
> result, x, y);
> }
>
> @@ -1892,12 +1894,13 @@
> }
> ").
>
> -:- pragma foreign_proc("MC++", type_ctor_and_args(_TypeDesc::in,
> - _TypeCtorDesc::out, _ArgTypes::out), will_not_call_mercury, "
> -{
> - mercury::runtime::Errors::SORRY(""type_ctor_and_args"");
> -}
> -").
> +
> +type_ctor_and_args(TypeDesc::in, TypeCtorDesc::out, ArgTypes::out) :-
> + rtti_implementation__type_ctor_and_args(
> + rtti_implementation__unsafe_cast(TypeDesc),
> + TypeCtorDesc0, ArgTypes0),
> + TypeCtorDesc = rtti_implementation__unsafe_cast(TypeCtorDesc0),
> + ArgTypes = rtti_implementation__unsafe_cast(ArgTypes0).
>
> /*
> ** This is the forwards mode of make_type/2:
> @@ -2300,26 +2303,24 @@
> make_type(_TypeCtorDesc::out, _ArgTypes::out) = (_TypeDesc::in),
> will_not_call_mercury, "
> {
> - mercury.runtime.Errors.SORRY(""foreign code for this function"");
> + mercury.runtime.Errors.SORRY(""foreign code for make_type"");
> // XXX this is required to keep the C# compiler quiet, but we should
> // really fix the interface to semidet C#
> succeeded = 1;
> }
> ").
>
> -:- pragma foreign_proc("MC++", type_ctor_name_and_arity(_TypeCtorDesc::in,
> - _TypeCtorModuleName::out, _TypeCtorName::out,
> - _TypeCtorArity::out),
> - will_not_call_mercury, "
> -{
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> -}
> -").
> +type_ctor_name_and_arity(TypeCtorDesc0::in, TypeCtorModuleName::out,
> + TypeCtorName::out, TypeCtorArity::out) :-
> + TypeCtorDesc = rtti_implementation__unsafe_cast(TypeCtorDesc0),
> + rtti_implementation__type_ctor_name_and_arity(TypeCtorDesc,
> + TypeCtorModuleName, TypeCtorName, TypeCtorArity).
> +
>
> :- pragma foreign_proc("MC++", num_functors(_TypeInfo::in) = (_Functors::out),
> will_not_call_mercury, "
> {
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> + mercury::runtime::Errors::SORRY(""foreign code for num_functors"");
> }
> ").
>
> @@ -2327,7 +2328,7 @@
> _FunctorName::out, _Arity::out, _TypeInfoList::out),
> will_not_call_mercury, "
> {
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> + mercury::runtime::Errors::SORRY(""foreign code for get_functor"");
> }
> ").
>
> @@ -2335,7 +2336,7 @@
> get_functor_ordinal(_TypeDesc::in, _FunctorNumber::in,
> _Ordinal::out), will_not_call_mercury, "
> {
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> + mercury::runtime::Errors::SORRY(""foreign code for get_functor_ordinal"");
> }
> ").
>
> @@ -2343,7 +2344,7 @@
> construct(_TypeDesc::in, _FunctorNumber::in,
> _ArgList::in) = (_Term::out), will_not_call_mercury, "
> {
> - mercury.runtime.Errors.SORRY(""foreign code for this function"");
> + mercury.runtime.Errors.SORRY(""foreign code for construct"");
> _Term = null;
> // XXX this is required to keep the C# compiler quiet, but we should
> // really fix the interface to semidet C#
> @@ -3310,7 +3311,7 @@
> :- pragma foreign_proc("MC++", functor(_Term::in, _Functor::out, _Arity::out),
> will_not_call_mercury, "
> {
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> + mercury::runtime::Errors::SORRY(""foreign code for functor"");
> }").
>
> /*
> @@ -3322,7 +3323,7 @@
> arg(_Term::in, _ArgumentIndex::in) = (_Argument::out),
> will_not_call_mercury, "
> {
> - mercury.runtime.Errors.SORRY(""foreign code for this function"");
> + mercury.runtime.Errors.SORRY(""foreign code for arg"");
> // XXX this is required to keep the C# compiler quiet, but we should
> // really fix the interface to semidet C#
> succeeded = 1;
> @@ -3332,7 +3333,7 @@
> argument(_Term::in, _ArgumentIndex::in) = (_ArgumentUniv::out),
> will_not_call_mercury, "
> {
> - mercury.runtime.Errors.SORRY(""foreign code for this function"");
> + mercury.runtime.Errors.SORRY(""foreign code for argument"");
> // XXX this is required to keep the C# compiler quiet, but we should
> // really fix the interface to semidet C#
> succeeded = 1;
> @@ -3407,20 +3408,16 @@
> }
> }").
>
> -:- pragma foreign_proc("MC++",
> - deconstruct(_Term::in, _Functor::out, _Arity::out,
> - _Arguments::out),
> - [will_not_call_mercury], "
> -{
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> -}").
> +deconstruct(Term::in, Functor::out, Arity::out, Arguments::out) :-
> + rtti_implementation__deconstruct(Term, Functor, Arity, Arguments).
>
> :- pragma foreign_proc("MC++",
> limited_deconstruct(_Term::in, _MaxArity::in, _Functor::out,
> _Arity::out, _Arguments::out),
> [will_not_call_mercury], "
> {
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> + mercury::runtime::Errors::SORRY(""foreign code for limited_deconstruct"");
> + SUCCESS_INDICATOR = FALSE;
> }").
>
> get_functor_info(Univ, FunctorInfo) :-
> @@ -3495,7 +3492,7 @@
> get_notag_functor_info(_Univ::in, _ExpUniv::out),
> will_not_call_mercury, "
> {
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> + mercury::runtime::Errors::SORRY(""foreign code for get_notag_functor_info"");
> }").
>
> % Given a value of an arbitrary type, succeed if its type is defined
> @@ -3541,7 +3538,7 @@
> get_equiv_functor_info(_Univ::in, _ExpUniv::out),
> will_not_call_mercury, "
> {
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> + mercury::runtime::Errors::SORRY(""foreign code for get_equiv_functor_info"");
> }").
>
> % Given a value of an arbitrary type, succeed if it is an enum type,
> @@ -3575,7 +3572,7 @@
> get_enum_functor_info(_Univ::in, _Enum::out),
> will_not_call_mercury, "
> {
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> + mercury::runtime::Errors::SORRY(""foreign code for get_enum_functor_info"");
> }").
>
> % Given a value of an arbitrary type, succeed if it is a general du type
> @@ -3677,7 +3674,7 @@
> :- pragma foreign_proc("MC++", get_du_functor_info(_Univ::in, _Where::out,
> _Ptag::out, _Sectag::out, _Args::out), will_not_call_mercury, "
> {
> - mercury::runtime::Errors::SORRY(""foreign code for this function"");
> + mercury::runtime::Errors::SORRY(""foreign code for get_du_functor_info"");
> }").
>
> %-----------------------------------------------------------------------------%
> --------------------------------------------------------------------------
> mercury-reviews mailing list
> post: mercury-reviews at cs.mu.oz.au
> administrative address: owner-mercury-reviews at cs.mu.oz.au
> unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
> subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
> --------------------------------------------------------------------------
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list