mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-23 13:23:47 +00:00
compiler/elds.m:
compiler/elds_to_erlang.m:
compiler/erl_backend.m:
compiler/erl_call_gen.m:
compiler/erl_code_gen.m:
compiler/erl_code_util.m:
compiler/erl_rtti.m:
compiler/erl_unify_gen.m:
compiler/erlang_rtti.m:
compiler/mercury_compile_erl_back_end.m:
Delete these modules, which together constitute the Erlang backend.
compiler/notes/compiler_design.html:
Delete references to the deleted modules.
compiler/parse_tree_out_type_repn.m:
Update the format we use to represent the sets of foreign_type and
foreign_enum declarations for a type as part of its item_type_repn_info,
now that Erlang is no longer a target language.
compiler/parse_type_repn.m:
Accept both the updated version of the item_type_repn_info and the
immediately previous version, since the installed compiler will
initially generate that previous version. However, stop accepting
an even older version that we stopped generating several months ago.
compiler/parse_pragma_foreign.m:
When the compiler finds a reference to Erlang as a foreign language,
add a message about support for Erlang being discontinued to the error
message.
Make the code parsing foreign_decls handle the term containing
the foreign language the same way as the codes parsing foreign
codes, procs, types and enums.
Add a mechanism to help parse_mutable.m to do the same.
compiler/parse_mutable.m:
When the compiler finds a reference to Erlang as a foreign language,
print an error message about support for Erlang being discontinued.
compiler/compute_grade.m:
When the compiler finds a reference to Erlang as a grade component,
print an informational message about support for Erlang being discontinued.
compiler/pickle.m:
compiler/make.build.m:
Delete Erlang foreign procs and types.
compiler/add_foreign_enum.m:
compiler/add_mutable_aux_preds.m:
compiler/add_pred.m:
compiler/add_solver.m:
compiler/add_type.m:
compiler/check_libgrades.m:
compiler/check_parse_tree_type_defns.m:
compiler/code_gen.m:
compiler/compile_target_code.m:
compiler/compute_grade.m:
compiler/const_struct.m:
compiler/convert_parse_tree.m:
compiler/dead_proc_elim.m:
compiler/decide_type_repn.m:
compiler/deps_map.m:
compiler/du_type_layout.m:
compiler/export.m:
compiler/foreign.m:
compiler/globals.m:
compiler/granularity.m:
compiler/handle_options.m:
compiler/hlds_code_util.m:
compiler/hlds_data.m:
compiler/hlds_module.m:
compiler/inlining.m:
compiler/int_emu.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/lambda.m:
compiler/lco.m:
compiler/llds_out_file.m:
compiler/make.dependencies.m:
compiler/make.m:
compiler/make.module_dep_file.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make.util.m:
compiler/make_hlds_separate_items.m:
compiler/make_hlds_warn.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_compile_main.m:
compiler/mercury_compile_middle_passes.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/ml_code_util.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_target_util.m:
compiler/ml_top_gen.m:
compiler/mlds.m:
compiler/mlds_dump.m:
compiler/mlds_to_c_export.m:
compiler/mlds_to_c_file.m:
compiler/mlds_to_cs_data.m:
compiler/mlds_to_cs_export.m:
compiler/mlds_to_cs_file.m:
compiler/mlds_to_cs_type.m:
compiler/mlds_to_java_export.m:
compiler/mlds_to_java_file.m:
compiler/mlds_to_java_type.m:
compiler/module_imports.m:
compiler/parse_pragma_foreign.m:
compiler/parse_tree_out.m:
compiler/polymorphism.m:
compiler/pragma_c_gen.m:
compiler/prog_data.m:
compiler/prog_data_foreign.m:
compiler/prog_foreign.m:
compiler/prog_item.m:
compiler/simplify_goal_scope.m:
compiler/special_pred.m:
compiler/string_encoding.m:
compiler/top_level.m:
compiler/uint_emu.m:
compiler/write_deps_file.m:
Remove references to Erlang as a backend or as a target language.
tests/invalid/bad_foreign_code.{m,err_exp}:
tests/invalid/bad_foreign_decl.{m,err_exp}:
tests/invalid/bad_foreign_enum.{m,err_exp}:
tests/invalid/bad_foreign_export.{m,err_exp}:
tests/invalid/bad_foreign_export_enum.{m,err_exp}:
tests/invalid/bad_foreign_import_module.{m,err_exp}:
tests/invalid/bad_foreign_proc.{m,err_exp}:
tests/invalid/bad_foreign_type.{m,err_exp}:
Add a test for Erlang as an invalid foreign language. Expect both the
new error message for this new error, and the updated list of now-valid
foreign languages on all errors.
551 lines
16 KiB
Mathematica
551 lines
16 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2008, 2010-2011 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: pickle.m
|
|
% Main authors: petdr, wangp.
|
|
%
|
|
% This file contains routines to serialise arbitrary data structures into some
|
|
% unspecified binary format which can be restored quickly.
|
|
%
|
|
% We don't preserve sharing in the pickled data structure. This would be
|
|
% possible but would introduce slowdowns in both the pickling and unpickling
|
|
% processes.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module libs.pickle.
|
|
:- interface.
|
|
|
|
:- import_module io.
|
|
:- import_module type_desc.
|
|
:- import_module univ.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% A type which holds custom pickling predicates.
|
|
%
|
|
:- type picklers.
|
|
|
|
:- type pickler_pred == pred(picklers, univ, io, io).
|
|
:- inst pickler_pred == (pred(in, in, di, uo) is det).
|
|
|
|
% Initialize the custom pickling predicates.
|
|
%
|
|
:- func init_picklers = picklers.
|
|
|
|
% For the type described by the type_ctor_desc, add the supplied custom
|
|
% pickle predicate to the set of registered pickle predicates.
|
|
%
|
|
:- pred register_pickler(type_ctor_desc::in, pickler_pred::in(pickler_pred),
|
|
picklers::in, picklers::out) is det.
|
|
|
|
% Serialise an arbitrary data structure into the current binary output
|
|
% stream, using the picklers given to override the default pickling method.
|
|
%
|
|
% Existential, foreign and higher-order types are not supported
|
|
% generically. Register custom handlers to handle those types.
|
|
%
|
|
:- pred pickle(picklers::in, T::in, io::di, io::uo) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% A type which holds the custom unpickling predicates.
|
|
%
|
|
:- type unpicklers.
|
|
|
|
:- type unpickle_handle.
|
|
|
|
:- type unpickle_state.
|
|
|
|
:- type unpickler_pred == pred(unpicklers, unpickle_handle, type_desc, univ,
|
|
unpickle_state, unpickle_state).
|
|
:- inst unpickler_pred == (pred(in, in, in, out, di, uo) is det).
|
|
|
|
% Initialize the custom unpickling predicates.
|
|
%
|
|
:- func init_unpicklers = unpicklers.
|
|
|
|
% For the type described by the type_ctor_desc, add the supplied custom
|
|
% unpickle predicate to the set of registered unpickle predicates.
|
|
%
|
|
:- pred register_unpickler(type_ctor_desc::in,
|
|
unpickler_pred::in(unpickler_pred), unpicklers::in, unpicklers::out)
|
|
is det.
|
|
|
|
% Get a pickled type back out from the file, using the unpicklers to
|
|
% override the default unpickling method.
|
|
%
|
|
:- pred unpickle_from_file(unpicklers::in, string::in, io.res(T)::out,
|
|
io::di, io::uo) is det.
|
|
|
|
% Unpickle a single value.
|
|
%
|
|
:- pred unpickle(unpicklers::in, unpickle_handle::in, T::out,
|
|
unpickle_state::di, unpickle_state::uo) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module bitmap.
|
|
:- import_module bool.
|
|
:- import_module char.
|
|
:- import_module construct.
|
|
:- import_module deconstruct.
|
|
:- import_module exception.
|
|
:- import_module int.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module require.
|
|
:- import_module string.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- type picklers
|
|
---> picklers(
|
|
map(type_ctor_desc, pickler_pred)
|
|
).
|
|
|
|
:- type unpicklers
|
|
---> unpicklers(
|
|
map(type_ctor_desc, unpickler_pred)
|
|
).
|
|
|
|
:- type unpickle_handle == bitmap.
|
|
:- type unpickle_state == int. % offset into bitmap
|
|
|
|
:- type get_byte_out_of_range
|
|
---> get_byte_out_of_range(string).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Pickling
|
|
%
|
|
|
|
init_picklers = picklers(map.init).
|
|
|
|
register_pickler(TypeCtorDesc, Pickle, Pickles0, Pickles) :-
|
|
Pickles0 = picklers(Map0),
|
|
map.det_insert(TypeCtorDesc, Pickle, Map0, Map),
|
|
Pickles = picklers(Map).
|
|
|
|
pickle(Pickles, T, !IO) :-
|
|
( if
|
|
dynamic_cast(T, String)
|
|
then
|
|
pickle_string(String, !IO)
|
|
else if
|
|
dynamic_cast(T, Int)
|
|
then
|
|
pickle_int32(Int, !IO)
|
|
else if
|
|
dynamic_cast(T, Float)
|
|
then
|
|
pickle_float(Float, !IO)
|
|
else if
|
|
dynamic_cast(T, Char)
|
|
then
|
|
pickle_char(Char, !IO)
|
|
else if
|
|
TypeDesc = type_of(T),
|
|
TypeCtorDesc = type_ctor(TypeDesc),
|
|
user_defined_pickler(Pickles, TypeCtorDesc, Pickle)
|
|
then
|
|
Pickle(Pickles, univ(T), !IO)
|
|
else
|
|
deconstruct.functor(T, do_not_allow, Functor, Arity),
|
|
pickle_string(Functor, !IO),
|
|
pickle_int32(Arity, !IO),
|
|
pickle_args(Pickles, 0, Arity, T, !IO)
|
|
).
|
|
|
|
:- pred pickle_args(picklers::in, int::in, int::in, T::in, io::di, io::uo)
|
|
is det.
|
|
|
|
pickle_args(Pickles, N, Arity, T, !IO) :-
|
|
( if N = Arity then
|
|
true
|
|
else
|
|
( if deconstruct.arg(T, do_not_allow, N, Arg) then
|
|
pickle(Pickles, Arg, !IO),
|
|
pickle_args(Pickles, N + 1, Arity, T, !IO)
|
|
else
|
|
unexpected($pred, "unable to deconstruct arg")
|
|
)
|
|
).
|
|
|
|
:- pred user_defined_pickler(picklers::in, type_ctor_desc::in,
|
|
pickler_pred::out(pickler_pred)) is semidet.
|
|
|
|
user_defined_pickler(picklers(Pickles), TypeCtorDesc, Pickle) :-
|
|
map.search(Pickles, TypeCtorDesc, Pickle0),
|
|
pickler_inst_cast(Pickle0, Pickle).
|
|
|
|
:- pred pickler_inst_cast(pickler_pred::in, pickler_pred::out(pickler_pred))
|
|
is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
pickler_inst_cast(A::in, B::out(pickler_pred)),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
B = A;
|
|
").
|
|
|
|
:- pragma foreign_proc("Java",
|
|
pickler_inst_cast(A::in, B::out(pickler_pred)),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
B = A;
|
|
").
|
|
|
|
:- pragma foreign_proc("C#",
|
|
pickler_inst_cast(A::in, B::out(pickler_pred)),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
B = A;
|
|
").
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Unpickling
|
|
%
|
|
|
|
init_unpicklers = unpicklers(map.init).
|
|
|
|
register_unpickler(TypeCtorDesc, Unpickle, Unpicklers0, Unpicklers) :-
|
|
Unpicklers0 = unpicklers(Map0),
|
|
map.det_insert(TypeCtorDesc, Unpickle, Map0, Map),
|
|
Unpicklers = unpicklers(Map).
|
|
|
|
unpickle_from_file(Unpicklers, FileName, Result, !IO) :-
|
|
io.see_binary(FileName, SeeResult, !IO),
|
|
(
|
|
SeeResult = ok,
|
|
% Perform unpickling from an intermediate memory buffer, as it seems to
|
|
% be faster.
|
|
io.read_binary_file_as_bitmap(ReadResult, !IO),
|
|
io.seen_binary(!IO),
|
|
(
|
|
ReadResult = ok(Bitmap),
|
|
promise_equivalent_solutions [TryResult] (
|
|
try((pred(T0::out) is det :-
|
|
unpickle(Unpicklers, Bitmap, T0, 0, _State)
|
|
), TryResult)
|
|
),
|
|
(
|
|
TryResult = succeeded(T),
|
|
Result = ok(T)
|
|
;
|
|
TryResult = exception(Excp),
|
|
( if univ_to_type(Excp, get_byte_out_of_range(Msg)) then
|
|
Result = error(io.make_io_error(Msg))
|
|
else
|
|
rethrow(TryResult)
|
|
)
|
|
)
|
|
;
|
|
ReadResult = error(Error),
|
|
Result = error(Error)
|
|
)
|
|
;
|
|
SeeResult = error(Error),
|
|
Result = error(Error)
|
|
).
|
|
|
|
unpickle(Unpicklers, Handle, T, !State) :-
|
|
unpickle_2(Unpicklers, Handle, type_of(T), Univ, !State),
|
|
det_univ_to_type(Univ, T).
|
|
|
|
:- pred unpickle_2(unpicklers::in, unpickle_handle::in,
|
|
type_desc::in, univ::out, unpickle_state::di, unpickle_state::uo)
|
|
is det.
|
|
|
|
unpickle_2(Unpicklers, Handle, TypeDesc, Univ, !State) :-
|
|
( if
|
|
TypeDesc = type_of(_ : string)
|
|
then
|
|
unpickle_string(Handle, String, !State),
|
|
Univ = univ(String)
|
|
else if
|
|
TypeDesc = type_of(_ : int)
|
|
then
|
|
unpickle_int32(Handle, Int, !State),
|
|
Univ = univ(Int)
|
|
else if
|
|
TypeDesc = type_of(_ : float)
|
|
then
|
|
unpickle_float(Handle, Float, !State),
|
|
Univ = univ(Float)
|
|
else if
|
|
TypeDesc = type_of(_ : character)
|
|
then
|
|
unpickle_char(Handle, Char, !State),
|
|
Univ = univ(Char)
|
|
else if
|
|
user_defined_unpickler(Unpicklers, type_ctor(TypeDesc), Unpickle)
|
|
then
|
|
Unpickle(Unpicklers, Handle, TypeDesc, Univ, !State)
|
|
else
|
|
unpickle_string(Handle, Functor, !State),
|
|
unpickle_int32(Handle, Arity, !State),
|
|
( if
|
|
( if Functor = "{}" then
|
|
IsTuple = yes,
|
|
type_ctor_and_args(TypeDesc, _, ArgTypes),
|
|
N = 0
|
|
else
|
|
IsTuple = no,
|
|
% XXX consider tabling this call
|
|
find_functor(TypeDesc, Functor, Arity, N, ArgTypes)
|
|
)
|
|
then
|
|
list.map_foldl(unpickle_2(Unpicklers, Handle), ArgTypes, ArgUnivs,
|
|
!State),
|
|
(
|
|
IsTuple = yes,
|
|
Univ = construct_tuple(ArgUnivs)
|
|
;
|
|
IsTuple = no,
|
|
( if Univ0 = construct(TypeDesc, N, ArgUnivs) then
|
|
Univ = Univ0
|
|
else
|
|
unexpected($pred, "unable to construct")
|
|
)
|
|
)
|
|
else
|
|
unexpected($pred, "unable to unpickle")
|
|
)
|
|
).
|
|
|
|
:- pred user_defined_unpickler(unpicklers::in, type_ctor_desc::in,
|
|
unpickler_pred::out(unpickler_pred)) is semidet.
|
|
|
|
user_defined_unpickler(unpicklers(Unpicklers), TypeCtorDesc, Unpickle) :-
|
|
map.search(Unpicklers, TypeCtorDesc, Unpickle0),
|
|
unpickler_inst_cast(Unpickle0, Unpickle).
|
|
|
|
:- pred unpickler_inst_cast(unpickler_pred::in,
|
|
unpickler_pred::out(unpickler_pred)) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
unpickler_inst_cast(A::in, B::out(unpickler_pred)),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
B = A;
|
|
").
|
|
|
|
:- pragma foreign_proc("Java",
|
|
unpickler_inst_cast(A::in, B::out(unpickler_pred)),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
B = A;
|
|
").
|
|
|
|
:- pragma foreign_proc("C#",
|
|
unpickler_inst_cast(A::in, B::out(unpickler_pred)),
|
|
[will_not_call_mercury, thread_safe, promise_pure],
|
|
"
|
|
B = A;
|
|
").
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Basic types picklers/unpicklers
|
|
%
|
|
|
|
:- pred pickle_int32(int::in, io::di, io::uo) is det.
|
|
|
|
pickle_int32(Int, !IO) :-
|
|
A = (Int >> 24) /\ 0xff,
|
|
B = (Int >> 16) /\ 0xff,
|
|
C = (Int >> 8) /\ 0xff,
|
|
D = (Int >> 0) /\ 0xff,
|
|
io.write_byte(A, !IO),
|
|
io.write_byte(B, !IO),
|
|
io.write_byte(C, !IO),
|
|
io.write_byte(D, !IO).
|
|
|
|
:- pred unpickle_int32(unpickle_handle::in, int::out,
|
|
unpickle_state::di, unpickle_state::uo) is det.
|
|
|
|
unpickle_int32(Handle, Int, !State) :-
|
|
get_byte(Handle, A, !State),
|
|
get_byte(Handle, B, !State),
|
|
get_byte(Handle, C, !State),
|
|
get_byte(Handle, D, !State),
|
|
Int0 = (A `unchecked_left_shift` 24)
|
|
\/ (B `unchecked_left_shift` 16)
|
|
\/ (C `unchecked_left_shift` 8)
|
|
\/ (D `unchecked_left_shift` 0),
|
|
Int = sign_extend_32(Int0).
|
|
|
|
:- func sign_extend_32(int) = int.
|
|
|
|
sign_extend_32(X) = R :-
|
|
% http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend
|
|
Mask = 1 `unchecked_left_shift` 31,
|
|
R = (X `xor` Mask) - Mask.
|
|
|
|
:- pred pickle_char(char::in, io::di, io::uo) is det.
|
|
|
|
pickle_char(Char, !IO) :-
|
|
% XXX handle non-ASCII characters
|
|
char.to_int(Char, Int),
|
|
io.write_byte(Int, !IO).
|
|
|
|
:- pred unpickle_char(unpickle_handle::in, char::out,
|
|
unpickle_state::di, unpickle_state::uo) is det.
|
|
|
|
unpickle_char(Handle, Char, !State) :-
|
|
get_byte(Handle, Byte, !State),
|
|
char.det_from_int(Byte, Char).
|
|
|
|
:- pred pickle_string(string::in, io::di, io::uo) is det.
|
|
|
|
pickle_string(String, !IO) :-
|
|
Length = string.length(String),
|
|
pickle_int32(Length, !IO),
|
|
string.foldl(pickle_char, String, !IO).
|
|
|
|
:- pred unpickle_string(unpickle_handle::in, string::uo,
|
|
unpickle_state::di, unpickle_state::uo) is det.
|
|
|
|
unpickle_string(Handle, String, !State) :-
|
|
unpickle_int32(Handle, Length, !State),
|
|
allocate_string(Length, String0),
|
|
unpickle_string_2(Handle, 0, Length, String0, String, !State).
|
|
|
|
:- pred unpickle_string_2(unpickle_handle::in, int::in, int::in,
|
|
string::di, string::uo, unpickle_state::di, unpickle_state::uo) is det.
|
|
|
|
unpickle_string_2(Handle, Index, Length, !String, !State) :-
|
|
( if Index = Length then
|
|
true
|
|
else
|
|
unpickle_char(Handle, Char, !State),
|
|
local_unsafe_set_char(Char, Index, !String),
|
|
unpickle_string_2(Handle, Index + 1, Length, !String, !State)
|
|
).
|
|
|
|
:- pred allocate_string(int::in, string::uo) is det.
|
|
:- pragma no_determinism_warning(allocate_string/2).
|
|
|
|
:- pragma foreign_proc("C",
|
|
allocate_string(Length::in, Str::uo),
|
|
[will_not_call_mercury, promise_pure, thread_safe],
|
|
"
|
|
MR_allocate_aligned_string_msg(Str, Length, MR_ALLOC_ID);
|
|
Str[Length] = '\\0';
|
|
").
|
|
|
|
allocate_string(_, _) :-
|
|
sorry($file, $pred).
|
|
|
|
% string.unsafe_set_char is disabled in the standard library so we need our
|
|
% own copy.
|
|
:- pred local_unsafe_set_char(char::in, int::in, string::di, string::uo)
|
|
is det.
|
|
:- pragma no_determinism_warning(local_unsafe_set_char/4).
|
|
|
|
:- pragma foreign_proc("C",
|
|
local_unsafe_set_char(Chr::in, Index::in, Str0::di, Str::uo),
|
|
[will_not_call_mercury, promise_pure, thread_safe],
|
|
"
|
|
Str0[Index] = Chr;
|
|
Str = Str0;
|
|
").
|
|
|
|
local_unsafe_set_char(_, _, _, _) :-
|
|
sorry($file, $pred).
|
|
|
|
:- pred pickle_float(float::in, io::di, io::uo) is det.
|
|
|
|
pickle_float(Float, !IO) :-
|
|
reinterpret_float_as_ints(Float, A, B),
|
|
% We always write floats using 64 bits. Single precision floats are not
|
|
% the default and the compiler hardly uses floats anyhow.
|
|
pickle_int32(A, !IO),
|
|
pickle_int32(B, !IO).
|
|
|
|
:- pred reinterpret_float_as_ints(float::in, int::out, int::out) is det.
|
|
:- pragma no_determinism_warning(reinterpret_float_as_ints/3).
|
|
|
|
:- pragma foreign_proc("C",
|
|
reinterpret_float_as_ints(Flt::in, A::out, B::out),
|
|
[will_not_call_mercury, promise_pure, thread_safe],
|
|
"
|
|
if (sizeof(MR_Float) == sizeof(float)) {
|
|
MR_uint_least32_t *p;
|
|
|
|
p = (MR_uint_least32_t *) &Flt;
|
|
A = *p;
|
|
B = 0;
|
|
} else {
|
|
MR_uint_least64_t *p;
|
|
|
|
p = (MR_uint_least64_t *) &Flt;
|
|
A = (*p >> 32) & 0xffffffff;
|
|
B = (*p >> 0) & 0xffffffff;
|
|
}
|
|
").
|
|
|
|
reinterpret_float_as_ints(_, _, _) :-
|
|
sorry($file, $pred).
|
|
|
|
:- pred unpickle_float(unpickle_handle::in, float::out,
|
|
unpickle_state::di, unpickle_state::uo) is det.
|
|
|
|
unpickle_float(Handle, Float, !State) :-
|
|
unpickle_int32(Handle, A, !State),
|
|
unpickle_int32(Handle, B, !State),
|
|
reinterpret_ints_as_float(A, B, Float).
|
|
|
|
:- pred reinterpret_ints_as_float(int::in, int::in, float::out) is det.
|
|
:- pragma no_determinism_warning(reinterpret_ints_as_float/3).
|
|
|
|
:- pragma foreign_proc("C",
|
|
reinterpret_ints_as_float(A::in, B::in, Flt::out),
|
|
[will_not_call_mercury, promise_pure, thread_safe],
|
|
"
|
|
if (sizeof(MR_Float) == sizeof(float)) {
|
|
MR_Float *p;
|
|
|
|
p = (MR_Float *) &A;
|
|
Flt = *p;
|
|
(void) B;
|
|
} else {
|
|
MR_uint_least64_t tmp;
|
|
MR_Float *p;
|
|
|
|
tmp = (((MR_uint_least64_t) A) << 32) |
|
|
(((MR_uint_least64_t) B) & 0xffffffff);
|
|
p = (MR_Float *) &tmp;
|
|
Flt = *p;
|
|
}
|
|
").
|
|
|
|
reinterpret_ints_as_float(_, _, _) :-
|
|
sorry($file, $pred).
|
|
|
|
:- pred get_byte(unpickle_handle::in, int::out,
|
|
unpickle_state::di, unpickle_state::uo) is det.
|
|
|
|
get_byte(Bitmap, Byte, Index, Index + 1) :-
|
|
( if bitmap.byte_in_range(Bitmap, Index) then
|
|
Byte = Bitmap ^ unsafe_byte(Index)
|
|
else
|
|
Msg = "byte " ++ string.from_int(Index) ++ " is out of range",
|
|
throw(get_byte_out_of_range(Msg))
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module libs.pickle.
|
|
%-----------------------------------------------------------------------------%
|