[m-rev.] Add `:- initialise' directive to the language.

Julien Fischer juliensf at cs.mu.OZ.AU
Wed Aug 17 16:18:34 AEST 2005


On Wed, 17 Aug 2005, Ralph Becket wrote:

> Estimated hours taken: 16
> Branches: main
>
> Add support for initialisation predicates to be called before main/2 is
> invoked.  The new directive is `:- initialise initpredname.'
>
> NEWS:
> 	Mention the new functionality.
>
> compiler/export.m:
> 	`:- pragma export' also adds a C function declaration in the
> 	generated C wrapper code to avoid C compiler warnings about
> 	missing declarations.
>
> compiler/hlds_module.m:
> 	Added a new user_init_preds field to the module_info to
> 	record the preds named in `initialise' directives.
> 	Added predicates to access and update the new field.
> 	The exported names are generated automatically.
>
> compiler/llds.m:
> 	Added a new field cfile_num_user_inits to c_file structure.
>
> compiler/llds_out.m:
> 	Add code to include the `REQUIRED_INIT initpredexportname' lines
> 	in the comment section of the generated C that is recognised
> 	by mkinit.
>
> compiler/make_hlds_passes.m:
> 	Handle the new `initialise' directives.
>
> compiler/mercury_compile.m:
> 	Make sure the number of user defined init preds is passed
> 	to the C code construction preds.
>
> compiler/mercury_to_mercury.m:
> 	Handle the output of `initialise' directives.
>
> compiler/module_qual.m:
> compiler/modules.m:
> compiler/recompilation.check.m:
> compiler/recompilation.version.m:
> 	Handle the new `initialise' item.
>
> compiler/prog_data.m:
> 	Add a new `initialise(sym_name)' item.
>
> compiler/prog_io.m:
> 	Add code to parse `initialise' directives.
>
> compiler/prog_mode.m:
> 	Add di_mode pred and func.
>
> compiler/transform_llds.m:
> 	Handle the extra field in c_file.
>
> doc/reference_manual.texi:
> 	Update the operator table in the reference manual.
> 	Document the new `initialise' directive.
>
> library/list.m:
> 	Added index[01]_of_first_occurrence preds and
> 	index[01]_of_first_occurrence_det funcs.  I've often
> 	had a need for these and they are used in looking up
> 	initprednames in the new module_info field.
>
> library/ops.m:
> 	Add `initialise' as a prefix operator.
>
> runtime/mercury_wrapper.c:
> runtime/mercury_wrapper.h:
> 	Add a new exported variable, MR_address_of_init_modules_required.
> 	Call the function pointed to by this variable at the right point
> 	during module initialisation.
>
> test/hard_coded/Mmakefile:
> test/hard_coded/initialise_decl.exp:
> test/hard_coded/initialise_decl.m:
> 	Added a test case.
>
> util/mkinit.c:
> 	Now always checks C files for extra inits (previously you had to
> 	explicitly supply the -x flag).
>
...

>  :- implementation
> @@ -4219,6 +4236,7 @@
>  * The module system::
>  * An example module::
>  * Sub-modules::
> +* Optional module initialisation::
>  @end menu
>
>  @node The module system
> @@ -4537,6 +4555,32 @@
>  (The work-around is to use separate sub-modules instead of nested
>  sub-modules, i.e.@: to put the sub-modules in separate source files.)
>  @end itemize
> +
> + at node Optional module initialisation
> + at section Optional module initialisation
>
> +Some modules that interact with foreign libraries or services
> +require special initialisation before use.

I suggest: Modules that interact ... may require ...

> +Such modules may include any number of @samp{initialise} directives
> +in their implementation sections.
> +An @samp{initialise} directive takes the following form:
> +
> + at example
> +:- initialise initpredname.
> + at end example
> +
> +where the predicate @samp{initpredname} must be declared with the following
> +signature:
> +
> + at example
> +:- pred initpredname(io::di, io::uo) is det.
> + at end example
> +
> +The effect of the @samp{initialise} declaration is to ensure that
> + at samp{initpredname} is invoked before the program's @samp{main}
> +predicate.  Initialisation predicates within a module are executed in the
> +order in which they are specified, although no order may be assumed between
> +different modules or submodules.

It's probably worth mentioning that duplicate initialisation predicate
are executed twice.  (Actually, I'm not convinced that this is such
a good idea - I can think of some (foreign) libraries that should
only be initialised once and it would be preferable if the compiler
could pick up accidental attempts to do it twice).

> Index: runtime/mercury_wrapper.c
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
> retrieving revision 1.149
> diff -u -r1.149 mercury_wrapper.c
> --- runtime/mercury_wrapper.c	1 Aug 2005 02:26:18 -0000	1.149
> +++ runtime/mercury_wrapper.c	17 Aug 2005 03:10:36 -0000
> @@ -339,6 +339,7 @@
>  #ifdef	MR_DEEP_PROFILING
>  void	(*MR_address_of_write_out_proc_statics)(FILE *fp);
>  #endif
> +void	(*MR_address_of_init_modules_required)(void);
>
>  MR_TypeCtorInfo	MR_type_ctor_info_for_univ;
>  MR_TypeInfo	MR_type_info_for_type_info;
> @@ -609,6 +610,9 @@
>
>  	/* initialize the Mercury library */
>  	(*MR_library_initializer)();
> +
> +	/* run any ...*/
> +	(*MR_address_of_init_modules_required)();
>
What's the ellipses for?

>  #ifndef MR_HIGHLEVEL_CODE
>    #ifndef __LCC__
> Index: runtime/mercury_wrapper.h
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.h,v
> retrieving revision 1.68
> diff -u -r1.68 mercury_wrapper.h
> --- runtime/mercury_wrapper.h	1 Aug 2005 02:26:18 -0000	1.68
> +++ runtime/mercury_wrapper.h	16 Aug 2005 08:13:08 -0000
> @@ -102,6 +102,7 @@
>  #ifdef	MR_DEEP_PROFILING
>  extern	void		(*MR_address_of_write_out_proc_statics)(FILE *fp);
>  #endif
> +extern	void		(*MR_address_of_init_modules_required)(void);
>
>  extern	MR_TypeCtorInfo	MR_type_ctor_info_for_univ;
>  extern	MR_TypeInfo	MR_type_info_for_type_info;
> Index: tests/hard_coded/Mmakefile
> ===================================================================
> RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
> retrieving revision 1.261
> diff -u -r1.261 Mmakefile
> --- tests/hard_coded/Mmakefile	10 Aug 2005 09:21:50 -0000	1.261
> +++ tests/hard_coded/Mmakefile	17 Aug 2005 04:28:11 -0000
> @@ -97,6 +97,7 @@
>  	impure_foreign2 \
>  	impure_foreign3 \
>  	impure_prune \
> +	initialise_decl \
>  	integer_test \
>  	intermod_c_code \
>  	intermod_foreign_type \
> Index: tests/hard_coded/initialise_decl.exp
> ===================================================================
> RCS file: tests/hard_coded/initialise_decl.exp
> diff -N tests/hard_coded/initialise_decl.exp
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ tests/hard_coded/initialise_decl.exp	17 Aug 2005 04:27:58 -0000
> @@ -0,0 +1,3 @@
> +This is the first initialise pred, i1/2.
> +This is the second initialise pred, i2/2.
> +This is main/2.
> Index: tests/hard_coded/initialise_decl.m
> ===================================================================
> RCS file: tests/hard_coded/initialise_decl.m
> diff -N tests/hard_coded/initialise_decl.m
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ tests/hard_coded/initialise_decl.m	17 Aug 2005 04:27:10 -0000
> @@ -0,0 +1,38 @@
> +%-----------------------------------------------------------------------------%
> +% initialise_decl.m
> +% Ralph Becket <rafe at cs.mu.oz.au>
> +% Wed Aug 17 14:25:01 EST 2005
> +% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
> +%
> +% Test the `:- initialise initpred' directive.
> +%
> +%-----------------------------------------------------------------------------%
> +
> +:- module initialise_decl.
> +
> +:- interface.
> +
> +:- import_module io.
> +
> +
> +
> +:- pred main(io :: di, io :: uo) is det.
> +
> +%-----------------------------------------------------------------------------%
> +%-----------------------------------------------------------------------------%
> +
> +:- implementation.
> +
> +:- initialise i1.
> +:- initialise i2.
> +
> +:- pred i1(io::di, io::uo) is det.
> +i1(!IO) :- io.print("This is the first initialise pred, i1/2.\n", !IO).
> +
> +:- pred i2(io::di, io::uo) is det.
> +i2(!IO) :- io.print("This is the second initialise pred, i2/2.\n", !IO).
> +
> +main(!IO) :- io.print("This is main/2.\n", !IO).
> +
> +%-----------------------------------------------------------------------------%
> +%-----------------------------------------------------------------------------%

If we're going to support multiple instances of the same intialiser then
you should test that here as well.

You should add a test to tests/invalid to test what happens when the
predicate in the initialise declaration doesn't exist.

There should be a similar test case for when an :- initialise declartion
occurs in the interface of a module.

Julien.
--------------------------------------------------------------------------
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