[m-rev.] for review: smart recompilation

Fergus Henderson fjh at cs.mu.OZ.AU
Mon Jun 4 23:42:45 AEST 2001


On 28-May-2001, Simon Taylor <stayl at cs.mu.OZ.AU> wrote:
> Index: compiler/equiv_type.m
> -	% equiv_type__expand_eqv_types(Items0, Items, CircularTypes, EqvMap).
> +	% equiv_type__expand_eqv_types(ModuleName, Items0, Items,
> +	%	CircularTypes, EqvMap, MaybeRecompInfo0, MaybeRecompInfo).
>  	%
>  	% First it builds up a map from type_id to the equivalent type.
>  	% Then it traverses through the list of items, expanding all types. 
>  	% This has the effect of eliminating all the equivalence types
>  	% from the source code. Error messages are generated for any
>  	% circular equivalence types.
> +	%
> +	% For items not defined in the current module, record the
> +	% equivalence types expanded while processing each item
> +	% in the recompilation_info.

It might be useful to mention here that this is done because it is needed
for the --smart-recompilation option.

> Index: compiler/error_util.m
...
> +	% Convert a list of lists of format_components into a list of
> +	% format_components, suitable for displaying as an error message.
> +:- func error_util__component_lists_to_pieces(list(list(format_component))) =
> +		list(format_component).

That comment doesn't give enough information about the semantics of
this function to understand what it does without looking at the code.
How does it differ from list__condense?

The name of this routine is rather long and it would be nice if we could
think of something more concise that clearly conveyed what it does.

> +:- func error_util__append_punctuation(list(format_component), char) =
> +		list(format_component).

A comment explaining what this routine does would help.
How does it differ from say `func(L,C) = append(L, [words(C)])'?

> +error_util__append_punctuation([], _) = _ :-
> +	error(
> +	"error_util__append_full_stop: appending punctuation after nothing").

The procedure name in the call to error/1 is wrong.

> Index: compiler/handle_options.m
> +++ compiler/handle_options.m	2001/05/28 05:38:52

> +	%
> +	% Disable `--smart-recompilation' for compilation options
> +	% which either do not produce a compiled output file or
> +	% for which smart recompilation will not work.
> +	%
> +	option_implies(generate_dependencies, smart_recompilation, bool(no)),
> +	option_implies(convert_to_mercury, smart_recompilation, bool(no)),
> +	option_implies(make_private_interface, smart_recompilation, bool(no)),
> +	option_implies(make_interface, smart_recompilation, bool(no)),
> +	option_implies(make_short_interface, smart_recompilation, bool(no)),
> +	option_implies(make_short_interface, smart_recompilation, bool(no)),

The line above is duplicated.

In the long run it would be nice to support --smart-recompilation for
--make-interface.

> +	% XXX Smart recompilation does not yet work with
> +	% `--no-target-code-only'. With `--no-target-code-only'
> +	% it becomes difficult to work out what all the target
> +	% files are and check whether they are up-to-date.
> +	% By default, mmake always enables `--target-code-only' and
> +	% processes the object file itself, so this isn't a problem.

s/object file/target code file/

> Index: compiler/intermod.m
>  add_item_clause(module_defn(_, Defn), Status0, Status, _,
> -		Module, Module, Info0, Info) --> 
> -	{ module_defn_update_import_status(Defn, ItemStatus1) ->
> +		Module0, Module, Info0, Info) --> 
> +	{ Defn = version_numbers(ModuleName, ModuleVersionNumbers) ->
> +		apply_to_recompilation_info(
> +		    (pred(RecompInfo0::in, RecompInfo::out) is det :-
> +			map__set(RecompInfo0 ^ version_numbers, ModuleName,
> +				ModuleVersionNumbers, VersionNumbers),
> +			RecompInfo = RecompInfo0 ^ version_numbers
> +					:= VersionNumbers
> +		    ),
> +		    transform_info(Module0, Info0),
> +		    transform_info(Module, Info)),

I found that code a little hard to read. 
I suggest using `map__elem' rather than map__set:

		    (pred(RecompInfo0::in, RecompInfo::out) is det :-
			RecompInfo = RecompInfo0 ^ version_numbers ^
				map__elem(ModuleName) := ModuleVersionNumbers
		    ),

Adding a comment might help too.

> @@ -958,8 +962,10 @@
>  		goal_info_set_nonlocals(GoalInfo0, NonLocals, GoalInfo1),
>  		goal_info_set_context(GoalInfo1, Context, GoalInfo),
>  
> -		construct_pred_or_func_call(PredId, PredOrFunc, SymName, Args,
> -			GoalInfo, Goal),
> +		% We don't record the called predicate as used --
> +		% it is only used if there is some other call.
> +		do_construct_pred_or_func_call(PredId, PredOrFunc, SymName,
> +			Args, GoalInfo, Goal),

I think it would be helpful if you could elaborate on that comment a bit.
Why doesn't this use count?

> @@ -3871,7 +3782,7 @@
>  
>  add_annotation(empty, no, none).
>  add_annotation(empty, yes(Mode), modes([Mode])).
> -add_annotation(modes(_), no, mixed).
> +add_annotation(modes(_ `with_type` list(mode)), no, mixed).
>  add_annotation(modes(Modes), yes(Mode), modes(Modes ++ [Mode])).
>  add_annotation(none, no, none).
>  add_annotation(none, yes(_), mixed).

Why is the explicit type annotation needed here?

> Index: compiler/mercury_compile.m

> +:- pred read_module(file_or_module, bool, module_name, file_name,
> +		maybe(time_t), item_list, module_error,
> +		read_modules, read_modules, io__state, io__state).
> +:- mode read_module(in, in, out, out, out, out, out, in, out, di, uo) is det.
>  
> -process_module_name(ModuleName, ModulesToLink) -->
> +read_module(module(ModuleName), ReturnTimestamp, ModuleName, FileName,
> +		MaybeTimestamp, Items, Error, ReadModules0, ReadModules) -->

What's the meaning of the `ReadModules0' and `ReadModules' arguments here?

> +:- pred process_module_2(file_or_module, modules_to_recompile,
> +		read_modules, list(string), io__state, io__state).
> +:- mode process_module_2(in, in, in, out, di, uo) is det.
> +
> +process_module_2(FileOrModule, MaybeModulesToRecompile, ReadModules0,
> +		ModulesToLink) -->
> +	read_module(FileOrModule, yes, ModuleName, FileName,
> +		MaybeTimestamp, Items, Error, ReadModules0, ReadModules),
> +	globals__io_lookup_bool_option(halt_at_syntax_errors, HaltSyntax),
> +	( { halt_at_module_error(HaltSyntax, Error) } ->
> +		{ ModulesToLink = [] }
> +	;
> +		split_into_submodules(ModuleName, Items, SubModuleList0),
> +		{ MaybeModulesToRecompile = some(ModulesToRecompile) ->
> +			list__filter(
> +				(pred((SubModule - _)::in) is semidet :-
> +					list__member(SubModule,
> +						ModulesToRecompile)
> +				),
> +				SubModuleList0, SubModuleList)
> +		;
> +				SubModuleList = SubModuleList0	
> +		},

Hmm... this isn't going to work for the `--target asm' back-end, I think.
For that back-end, you need to recompile all of the sub-modules if you
recompile any of them, since they get compiled into a single object file.

> +		{ assoc_list__keys(SubModuleList, InlineSubModules0) },
> +		{ list__delete_all(InlineSubModules0,
> +			ModuleName, InlineSubModules) },

I suggest s/InlineSubModules/NestedSubModules/g, here and elsewhere,
to be consistent with the terminology used in the language reference
manual and elsewhere in the compiler.

> @@ -656,15 +888,27 @@
>  		globals__io_lookup_bool_option(target_code_only, 
>  				TargetCodeOnly),
>  
> +		%
> +		% Remove any existing `.used' file before writing the
> +		% output file file. This avoids leaving the old `used'
> +		% file lying around if compilation is interrupted after
> +		% the new output file is written but before the new
> +		% `.used' file is written.
> +		%
> +		module_name_to_file_name(ModuleName, ".used", no,
> +			UsageFileName),
> +		invoke_system_command("rm -f " ++ UsageFileName, _),

You should use io__remove_file rather than invoke_system_command.

> Index: compiler/modules.m
...
> +:- pred read_mod_if_changed(module_name, string, string, bool, time_t,
> +		item_list, module_error, file_name, maybe(time_t),
> +		io__state, io__state).
> +:- mode read_mod_if_changed(in, in, in, in, in,
> +		out, out, out, out, di, uo) is det.

There should be a comment for that procedure.

Also you should minimize the number of places which assume that file
timestamps have type time_t; use an abstract type here.

> Index: compiler/options.m

There should probably be a shorter alternative name for the
`--smart-recompilation' option, e.g. `--sr', for interactive use.

> Index: compiler/prog_data.m

You should document the new invariants for the `prog_data__type'
type here.

...
> @@ -44,42 +45,31 @@
>  :- type item_and_context ==	pair(item, prog_context).
>  
>  :- type item		
...
> +	; 	type_defn(tvarset, sym_name, list(type_param),
> +			type_defn, condition)
> +		%	VarNames, Name, Args, TypeDefn, Condition

I suggest s/Name, Args/TypeName, Args/

> +:- type item_warning
> +	--->	item_warning(
> +			maybe(option),	% Option controlling whether the
> +					% warning should be reported.
> +			string,		% The warning.
> +			term		% The term to which it relates.
> +		).

Why do you include the maybe(option) here?
Is that because the globals isn't being passed into the place which
produces the warning?

> Index: compiler/prog_io.m
> @@ -246,11 +267,44 @@
>  		{ dir__this_directory(CurrentDir) },
>  		{ Dirs = [CurrentDir] }
>  	),
> +	io__input_stream(OldInputStream),
>  	search_for_file(Dirs, FileName, R),
>  	( { R = yes } ->
> -		read_all_items(DefaultModuleName, ModuleName,
> -			Messages, Items, Error),
> -		io__seen
> +		( { ReturnTimestamp = yes } ->
> +			io__input_stream(InputStream),
> +			io__input_stream_file_modification_time(InputStream,
> +				TimestampResult),
> +			(
> +				{ TimestampResult = ok(Timestamp) },
> +				{ MaybeModuleTimestamp = yes(Timestamp) } 
> +			;
> +				{ TimestampResult = error(_) },
> +				{ MaybeModuleTimestamp = no }

You shouldn't throw away the error status (`_') here, if this is going
to result in an error message or warning message later.

At very least that warrants an XXX comment.

[... to be continued ...]

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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