[m-rev.] for review: refactor mlds_to_il.m

Tyson Dowd trd at cs.mu.OZ.AU
Tue Jul 10 00:54:34 AEST 2001


On 09-Jul-2001, Peter Ross <peter.ross at miscrit.be> wrote:
> Hi,
> 
> For Tyson or Fergus to review.
> 
> 
> ===================================================================
> 
> 
> Estimated hours taken: 40
> Branches: main
> 
> Refactor the top level of mlds_to_il so that we only do one pass over
> the MLDS to generate the ILDS.  As a side effect of this change nondet
> code now works again.

Thanks Pete, here's your review:

> compiler/mlds.m:
>     Add a new field to mlds__class_defn which is the list of
>     defns which are constructors for this class.
>     Add the functions mlds__append_mercury_code and mlds__append_name
>     which append either "mercury_code" or an arbitary string to the
>     module qualifier of a name.

These new functions should almost certainly go in ml_util.m

> Index: ml_elim_nested.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/ml_elim_nested.m,v
> retrieving revision 1.29
> diff -u -r1.29 ml_elim_nested.m
> --- ml_elim_nested.m	27 Jun 2001 13:41:30 -0000	1.29
> +++ ml_elim_nested.m	9 Jul 2001 13:08:58 -0000
> @@ -373,8 +373,30 @@
>  	EnvTypeEntityName = type(EnvClassName, 0),
>  	EnvTypeFlags = env_type_decl_flags,
>  	Fields = list__map(convert_local_to_field, LocalVars),
> +	( Target = il ->
> +		ThisPtr = self(mlds__commit_type),
> +		FieldType = mlds__commit_type,
> +		CtorType = mlds__commit_type,
> +		PtrType = mlds__commit_type,	% XXX
> +		FieldName = qual(mlds__append_name(ModuleName,
> +				EnvClassName ++ "_0"), "commit_1"),

The XXX isn't explained.

> @@ -548,7 +570,7 @@
>  	% type declaration.
>  :- func env_type_decl_flags = mlds__decl_flags.
>  env_type_decl_flags = MLDS_DeclFlags :-
> -	Access = private,
> +	Access = public,
>  	PerInstance = one_copy,
>  	Virtuality = non_virtual,
>  	Finality = overridable,

I'm not 100% clear on why this change needs to be made.  An explanation
would be good.

> -
>  %-----------------------------------------------------------------------------%
> +%-----------------------------------------------------------------------------%
> +
> +generate_il(MLDS, AssemblyDecls ++ [assembly(IlInfo ^ assembly_name),
> +		namespace(NamespaceName, ILDecls)], set__init, IO0, IO) :-
> +	transform_mlds(MLDS) = mlds(MercuryModuleName, _, Imports, Defns),
>  

I'd prefer to have the LHS contain the output of the function, but
maybe this is just my inflexible brain...

> +	% Move all the top level methods and data definitions into the
> +	% mercury_code class, and then rename all the definitions as
> +	% necessary to reflect this new hierachy.
> +:- func transform_mlds(mlds) = mlds.
> +
> +transform_mlds(mlds(MercuryModuleName, ForeignCode, Imports, Defns))
> +	= mlds(
> +		MercuryModuleName,
> +		ForeignCode,
> +		Imports,
> +		[mercury_code_class(list__map(rename_defn, Members)) | Others]
> +	) :-
> +	list__filter((pred(D::in) is semidet :-
> +			( D = mlds__defn(_, _, _, mlds__function(_, _, _))
> +				% XXX we need to place all the RTTI
> +				% datastructures inside this class, so
> +				% they are generated as fields.
> +				% Maybe what we should do is make all
> +				% the RTTI data structures nested
> +				% classes.  I think that would work
> +				% better.
> +			; D = mlds__defn(_, _, _, mlds__data(_, _))

Agreed, this is a nice idea, but it's a bit more work.
I would possibly reduce startup time, but increase the number of
classes.  Worth investigating in future.

> +:- func rename_defn(mlds__defn) = mlds__defn.
> +
> +rename_defn(defn(Name, Context, Flags, Entity0))
> +	= defn(Name, Context, Flags, Entity) :-
> +	( Entity0 = data(Type, Initializer),
> +		Entity = data(Type, rename_initializer(Initializer))
> +	; Entity0 = function(MaybePredProcId, Params, MaybeStmt0),
> +		( MaybeStmt0 = yes(Stmt),
> +			MaybeStmt = yes(rename_statement(Stmt))
> +		; MaybeStmt0 = no,
> +			MaybeStmt = no
>  		),
> +		Entity = function(MaybePredProcId, Params, MaybeStmt)
> +	; Entity0 = class(_),
> +		sorry(this_file, "renaming nested classes")
> +	).

We're going to need nested classes, they are generated in --grade il.
(high-level data).

> +
> +:- func rename_statement(mlds__statement) = mlds__statement.
> +
> +rename_statement(statement(block(Defns, Stmts), Context))
> +	= statement(block(list__map(rename_defn, Defns),
> +			list__map(rename_statement, Stmts)), Context).
> +rename_statement(statement(while(Rval, Loop, IterateOnce), Context))
> +	= statement(while(rename_rval(Rval),
> +			rename_statement(Loop), IterateOnce), Context).
> +rename_statement(statement(if_then_else(Rval, Then, MaybeElse0), Context))
> +	= statement(if_then_else(rename_rval(Rval),
> +			rename_statement(Then), MaybeElse), Context) :-
> +	( MaybeElse0 = no,
> +		MaybeElse = no
> +	; MaybeElse0 = yes(Else),
> +		MaybeElse = yes(rename_statement(Else))
> +	).
> +rename_statement(statement(switch(_, _, _, _, _), _Context))
> +	= _ :- sorry(this_file, "rename switch").

This isn't good, we should process switches, because they are used for
string switches, which Fergus has recently made work.

> +:- func mlds_defn_to_ilasm_decl(il_info, mlds__defn) = ilasm__decl.
> +
> +mlds_defn_to_ilasm_decl(_, defn(_Name, _Context, _Flags, data(_Type, _Init)))
> +	= _ :- sorry(this_file, "top level data definition!").
> +mlds_defn_to_ilasm_decl(_, defn(_Name, _Context, _Flags,
> +		function(_MaybePredProcId, _Params, _MaybeStmts)))
> +	= _ :- sorry(this_file, "top level function definition!").
> +mlds_defn_to_ilasm_decl(Info0, defn(Name, _Context, Flags, class(ClassDefn)))
> +	= class(
> +		decl_flags_to_classattrs(Flags),
> +		EntityName,
> +		Extends,
> +		Interfaces,
> +		MethodDecls
> +	) :-
> +	EntityName = entity_name_to_ilds_id(Name),
> +	ClassDefn = class_defn(_Kind, _Imports, Inherits, Implements,
> +			Ctors, Members),
> +	( Inherits = [],
> +		Extends = extends_nothing,
> +		Parent = structured_name("mscorlib", ["System", "Object"])

It's preferable to use 
		Parent = il_generic_class_name
for this.

> -			% Retrieve the locals, put them in the enclosing
> -			% scope.
> -		il_info_get_locals_list(Locals),
> -		{ InstrsTree = tree__list([
> -			context_node(Context),
> -			instr_node(start_block(scope(Locals), BlockId)),
> -			InstrsTree1, 
> -			MaybeRet,
> -			instr_node(end_block(scope(Locals), BlockId))
> -			])
> -		},
> +	Interfaces = implements(
> +			list__map(interface_id_to_class_name, Implements)),
> +
> +	ClassName = class_name(Info0 ^ module_name, EntityName),
> +	list__map_foldl(generate_method(ClassName, no), Members,
> +			MethodsAndFields, Info0, Info1),
> +	list__map_foldl(generate_method(ClassName, yes(Parent)), Ctors,
> +			IlCtors, Info1, Info),
> +	MethodsAndFieldsAndCtors = IlCtors ++ MethodsAndFields,
> +
> +		% XXX Maybe it would be better to just check to see
> +		% whether or not there are any init instructions then
> +		% explicitly checking for the name mercury_code.

s/then/than

And yes, this would be nicer I think, but you don't have to do it now.

> +:- func decl_flags_to_methattrs(mlds__decl_flags) = list(ilasm__methattr).
> +
> +decl_flags_to_methattrs(Flags)
> +	= list__condense([Access, PerInstance, Virtuality,
> +			Finality, Abstractness]) :-
> +	AccessFlag = access(Flags),
> +	( AccessFlag = public,
> +		Access = [public]
> +	; AccessFlag = protected,
> +			% XXX is this correct?
> +		Access = [family]

Family seems to be right.

> -generate_method_defn(DataDefn) --> 
> -	{ DataDefn = defn(data(DataName), Context, _DeclsFlags, Entity) },
>  	il_info_get_module_name(ModuleName),
> -	{ ClassName = mlds_module_name_to_class_name(ModuleName, yes) },
>  
> +	/*
>  		% Generate a term (we use it to emit the complete
>  		% method definition as a comment, which is nice
>  		% for debugging).
> -	{ term__type_to_term(DataDefn, MLDSDefnTerm) },
> +	{ term__type_to_term(defn(Name, Context, Flags, Entity),
> +			_MLDSDefnTerm) },
> +	*/

This is commented out but not explained.

> -%-----------------------------------------------------------------------------
> +	{ ClassDecl = ilasm__method(methodhead(Attrs, MemberName,
> +			ILSignature, []), MethodContents)}.
> +
> +generate_method(_, _, defn(_Name, _Context, _Flags, Entity), _ClassDecl) -->
> +	{ Entity = class(_ClassDefn) },
> +	{ sorry(this_file, "nested classes") }.

Nested classes were implemented previously, you have deleted their
implementation:

> -defn_to_class_decl(mlds__defn(EntityName, _Context, _DeclFlags,
> -		mlds__class(ClassDefn)), ILClassDecl) -->
> -	DataRep =^ il_data_rep,
> -	( { EntityName = type(TypeName0, Arity) } ->
> -		{ TypeName = string__format("%s_%d",
> -			[s(TypeName0), i(Arity)]) },
> -		{ ClassDefn = mlds__class_defn(_ClassType, _Imports, 
> -			Inherits, _Implements, Defns) },
> -		{ FullClassName = structured_name("", [TypeName]) },
> -		list__map_foldl(defn_to_class_decl, Defns, ILDefns),
> -		{ make_constructor(DataRep, FullClassName, ClassDefn,
> -			ConstructorILDefn) },
> -		{ Extends = mlds_inherits_to_ilds_inherits(DataRep, Inherits) },
> -		{ ILClassDecl = nested_class([public], TypeName, Extends,
> -			implements([]), [ConstructorILDefn | ILDefns]) }
> -	;
> -		{ error("expected type entity name for a nested class") }
> -	).
> -

This should *not* be removed, they are required for --grade il.

> @@ -2745,7 +2987,9 @@
>  make_method_defn(InstrTree) = MethodDecls :-
>  	Instrs = list__condense(tree__flatten(InstrTree)),
>  	MethodDecls = [
> -		maxstack(int32(calculate_max_stack(Instrs))),
> +			% XXX The + 1 is needed for when the --debug-il-asm
> +			% flag is enabled.
> +		maxstack(int32(calculate_max_stack(Instrs) + 1)),
>  			% note that we only need .zeroinit to ensure
>  			% verifiability; for nonverifiable code,

This + 1 should be conditional on --debug-il-asm which can be looked up
in the globals.

I'd prefer all the hacks that --debug-il-asm requires to be conditional
so that when we get a decent .NET debugger (and therefore don't need
--debug-il-asm anymore) we can easily remove it.


Apart from this the change is fine.  However you definitely need to put
back the code for nested classes.

-- 
       Tyson Dowd           # 
                            #  Surreal humour isn't everyone's cup of fur.
     trd at cs.mu.oz.au        # 
http://www.cs.mu.oz.au/~trd #
--------------------------------------------------------------------------
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