mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-14 13:23:53 +00:00
Estimated hours taken: 3 Branches: main Clean up in unused module imports in the Mercury system detected by --warn-unused-imports. analysis/*.m: browser/*.m: deep_profiler/*.m: compiler/*.m: library/*.m: mdbcomp/*.m: profiler/*.m: slice/*.m: Remove unused module imports. Fix some minor departures from our coding standards. analysis/Mercury.options: browser/Mercury.options: deep_profiler/Mercury.options: compiler/Mercury.options: library/Mercury.options: mdbcomp/Mercury.options: profiler/Mercury.options: slice/Mercury.options: Set --no-warn-unused-imports for those modules that are used as packages or otherwise break --warn-unused-imports, e.g. because they contain predicates with both foreign and Mercury clauses and some of the imports only depend on the latter.
183 lines
7.3 KiB
Mathematica
183 lines
7.3 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1999-2002, 2005-2006 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU Library General
|
|
% Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: collect_lib.m.
|
|
% Author: jahier.
|
|
% Purpose:
|
|
% This module defines functions that are needed to implement the
|
|
% `collect' primitive.
|
|
%
|
|
% `collect' collects runtime information from Mercury program executions.
|
|
% It is intended to let users easily implement their own monitors with
|
|
% acceptable performances.
|
|
%
|
|
% To use it, users just need to define 4 things in a file, using the
|
|
% Mercury syntax:
|
|
% 1) `accumulator_type' which is the type of the accumulator.
|
|
% 2) The predicate initialize/1 which initializes the
|
|
% collecting variable. initialize/1 should respect the
|
|
% following declarations:
|
|
% :- pred initialize(accumulator_type).
|
|
% :- mode initialize(out) is det.
|
|
% 3) The predicate filter/4 which updates the collecting
|
|
% variable at each execution event. filter/4 also outputs
|
|
% a variable that indicates whether to stop collecting.
|
|
% If this variable is set to `stop', the collect process
|
|
% stops; if it is set to `continue', it continues. If this
|
|
% variable is always set to `continue', the collecting will
|
|
% process until the last event is reached. filter/4 should
|
|
% respect the following declarations:
|
|
% :- pred filter(event, accumulator_type, accumulator_type,
|
|
% stop_or_continue).
|
|
% :- mode filter(in, di, uo, out) is det.
|
|
% 4) Optionally, a `post_process/2' function that lets
|
|
% one post-process the final value of the
|
|
% accumulator. `post_process/2' should respect the
|
|
% following declarations:
|
|
% :- pred post_process(accumulator_type, collected_type).
|
|
% :- mode post_process(in, out) is det.
|
|
% If `collected_type' is different from `accumulator_type',
|
|
% the `accumulator_type' should also be defined; otherwise
|
|
% by default, `accumulator_type' is automatically defined as
|
|
% being the same type as `collected_type'.
|
|
% 5) And optionally the mode definition of the second and the
|
|
% third arguments of filter/4: `acc_in' and `acc_out'. Those
|
|
% mode have `di' and `uo' respectively as default values.
|
|
%
|
|
% Then, this file is used to generate the Mercury module `collect.m',
|
|
% which is compiled and dynamically linked with the current execution.
|
|
% When a `collect' request is made from the external debugger, a variable
|
|
% of type accumulator_type is first initialized (with initialize/1) and
|
|
% then updated (with filter/4) for all the events of the remaining
|
|
% execution. When the end of the execution is reached, the last value of
|
|
% the collecting variable is send to the debugger.
|
|
|
|
:- module mdb.collect_lib.
|
|
:- interface.
|
|
|
|
:- pred dummy_pred_to_avoid_warning_about_nothing_exported is det.
|
|
|
|
%------------------------------------------------------------------------------%
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module mdb.dl.
|
|
|
|
:- import_module char.
|
|
:- import_module io.
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
dummy_pred_to_avoid_warning_about_nothing_exported.
|
|
|
|
:- pragma foreign_export("C",
|
|
link_collect(in, out, out, out, out, out, out, out, di, uo),
|
|
"ML_CL_link_collect").
|
|
|
|
:- pragma foreign_export("C", unlink_collect(in, di, uo),
|
|
"ML_CL_unlink_collect").
|
|
|
|
% We need Handle to be able to close the shared object (dl.close) later on.
|
|
% When the link failed, we output NULL pointers instead of maybe pointers
|
|
% for performance reasons; indeed, filter will be called at every event
|
|
% so we don't want to pay the price of the maybe variable de-construction
|
|
% at each event.
|
|
|
|
% dynamically link the collect module;
|
|
:- pred link_collect(string::in, c_pointer::out, c_pointer::out,
|
|
c_pointer::out, c_pointer::out, c_pointer::out, dl_result(handle)::out,
|
|
char::out, io::di, io::uo) is det.
|
|
|
|
link_collect(ObjectFile, Filter, Initialize, PostProcess, SendResult,
|
|
GetCollectType, MaybeHandle, Result, !IO) :-
|
|
%
|
|
% Link in the object code for the module `collect' from ObjectFile.
|
|
%
|
|
dl.open(ObjectFile, lazy, local, MaybeHandle, !IO),
|
|
(
|
|
MaybeHandle = dl_error(Msg),
|
|
print("dlopen failed: ", !IO),
|
|
print(Msg, !IO),
|
|
nl(!IO),
|
|
set_to_null_pointer(Initialize),
|
|
set_to_null_pointer(Filter),
|
|
set_to_null_pointer(PostProcess),
|
|
set_to_null_pointer(SendResult),
|
|
set_to_null_pointer(GetCollectType),
|
|
Result = 'n'
|
|
;
|
|
MaybeHandle = dl_ok(Handle),
|
|
%
|
|
% Look up the address of the C functions corresponding to the
|
|
% initialize/1 and filter/15 predicates in the collect module.
|
|
%
|
|
dl.sym(Handle, "ML_COLLECT_initialize", MaybeInitialize, !IO),
|
|
dl.sym(Handle, "ML_COLLECT_filter", MaybeFilter, !IO),
|
|
dl.sym(Handle, "ML_COLLECT_post_process", MaybePostProcess, !IO),
|
|
dl.sym(Handle, "ML_COLLECT_send_collect_result", MaybeSendResult, !IO),
|
|
dl.sym(Handle, "ML_COLLECT_collected_variable_type", MaybeType, !IO),
|
|
(
|
|
MaybeInitialize = dl_ok(Initialize0),
|
|
MaybeFilter = dl_ok(Filter0),
|
|
MaybePostProcess = dl_ok(PostProcess0),
|
|
MaybeSendResult = dl_ok(SendResult0),
|
|
MaybeType = dl_ok(Type0)
|
|
->
|
|
Result = 'y',
|
|
Initialize = Initialize0,
|
|
Filter = Filter0,
|
|
PostProcess = PostProcess0,
|
|
GetCollectType = Type0,
|
|
SendResult = SendResult0
|
|
;
|
|
set_to_null_pointer(Initialize),
|
|
set_to_null_pointer(Filter),
|
|
set_to_null_pointer(PostProcess),
|
|
set_to_null_pointer(SendResult),
|
|
set_to_null_pointer(GetCollectType),
|
|
Result = 'n'
|
|
)
|
|
).
|
|
|
|
:- pred set_to_null_pointer(c_pointer::out) is det.
|
|
:- pragma foreign_proc("C",
|
|
set_to_null_pointer(Pointer::out),
|
|
[will_not_call_mercury, promise_pure, thread_safe],
|
|
"
|
|
(Pointer = (MR_Word) NULL)
|
|
").
|
|
|
|
set_to_null_pointer(_) :-
|
|
private_builtin.sorry("collect_lib.set_to_null_pointer").
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
% Dynamically unlink a module that was dynamically linked in
|
|
% using `link_collect'.
|
|
%
|
|
:- pred unlink_collect(dl_result(handle)::in, io::di, io::uo) is det.
|
|
|
|
unlink_collect(MaybeHandle, !IO) :-
|
|
(
|
|
MaybeHandle = dl_error(_)
|
|
% There is nothing to close since an error(_) here means that
|
|
% the dlopen failed.
|
|
;
|
|
MaybeHandle = dl_ok(Handle),
|
|
dl.close(Handle, Result, !IO),
|
|
display_close_result(Result, !IO)
|
|
).
|
|
|
|
:- pred display_close_result(dl_result::in, io::di, io::uo) is det.
|
|
|
|
display_close_result(dl_ok, !IO).
|
|
display_close_result(dl_error(String), !IO) :-
|
|
print(String, !IO),
|
|
nl(!IO).
|