[m-dev.] for review: MLDS code generator design

Fergus Henderson fjh at cs.mu.OZ.AU
Tue Aug 3 06:48:31 AEST 1999


The following comments document the algorithms that I intend
to use for generating conjunction, disjunction, if-then-else,
and commits in the HLDS->MLDS code generator.

This algorithm generates nice high-level code;
apart from the throw or longjmp used for commits,
the generated code does not contain any gotos ;-)

I'd appreciate it if someone (Zoltan, Tom, and Tyson spring to mind ;-)
could review this before I get too far down the track of implementing it.  

Thanks,
	Fergus.

%-----------------------------------------------------------------------------%

% File: ml_code_gen.m
% Main author: fjh

% MLDS code generation -- convert from HLDS to MLDS.

% This module is an alternative to the original code generator.
% The original code generator compiles from HLDS to LLDS, generating
% very low-level code.  This code generator instead compiles to MLDS,
% generating much higher-level code than the original code generator.

% For nondeterministic predicates, we generate code using an explicit
% continuation passing style: on success, a function calls its continuation,
% and on failure it returns.  To keep things easy, this pass generates
% code which may contain nested functions; if the target language doesn't
% support nested functions (or doesn't support them _efficiently_) then
% a later MLDS->MLDS simplification pass will convert it to a form that
% does not use nested functions.

%-----------------------------------------------------------------------------%
% CODE GENERATION SUMMARY
%-----------------------------------------------------------------------------%
%
% The calling convention for sub-goals is as follows.
%
%	model_det goal:
%		On success, fall through.
%		(May clobber `succeeded'.)
%	model_semi goal:
%		On success, set `succeeded' to TRUE and fall through.
%		On failure, set `succeeded' to FALSE and fall through.
%	model_non goal:
%		On success, call the success continuation.
%		On failure, fall through.
%		(May clobber `succeeded' in either case.)
%
% In comments, we use the following notation to distinguish between
% these three.
%
%	model_det goal:
%		<do Goal>
%	model_semi goal:
%		<succeeded = Goal>
%	model_non goal:
%		<Goal && CONT()>
%
% The notation 
%
%	[situation]:
%		<[construct]>
%	===>
%		[code]
%
% means that in the situation described by [situation],
% for the the specified [construct] we will generate the specified [code].

%-----------------------------------------------------------------------------%
%
% Code for commits
%

%	model_non in semi context: (using catch/throw)
%		<succeeded = Goal>
% 	===>
%		bool succeeded;
%		void success() {
%			throw COMMIT;
%		}
%		try {
%		   <Goal && success()>
%		   succeeded = FALSE;
%		} catch (COMMIT) {
%		   succeeded = TRUE;
%		}

%	model_non in semi context: (using setjmp/longjmp)
%		<succeeded = Goal>
% 	===>
%		bool succeeded;
%		jmp_buf buf;
%		void success() {
%			longjmp(buf, TRUE);
%		}
%		if (setjmp(buf)) {
%			succeeded = TRUE;
%		} else {
%			<Goal && success()>
%			succeeded = FALSE;
%		}

%	model_non in det context (using catch/throw):
%		<do Goal>
%	===>
%		void success() {
%			throw COMMIT;
%		}
%		try {
%		   <Goal && success()>
%		} catch (COMMIT) {}

%	model_non in det context (using setjmp/longjmp):
%		<do Goal>
% 	===>
%		jmp_buf buf;
%		void success() {
%			longjmp(buf, TRUE);
%		}
%		if (setjmp(buf) == 0) {
%			<Goal && success()>
%		}

%-----------------------------------------------------------------------------%
%
% Code for conjunctions
%

%	model_det goal:
%		<Goal, Goals>
% 	===>
%		<do Goal>
%		<Goals>
%	

%	model_semi goal:
%		<Goal, Goals>
% 	===>
%	{
%		bool succeeded;
%
%		<succeeded = Goal>;
%		if (succeeded) {
%		    <Goals>;
%		}
%	}

%	model_non goal (unoptimized)
%		<Goal, Goals>
% 	===>
%	{
%		entry_func() {
%			<Goal && succ_func()>;
%		}
%		succ_func() {
%			<Goals && SUCCEED()>;
%	 	}
%
%		entry_func();
%	}
%
%	model_non goal (optimized):
%		<Goal, Goals>
% 	===>
%	{
%	        succ_func() {
%			<Goals && SUCCEED()>;
%	        }
%
%	        <Goal && succ_func()>;
%	}

%	model_non goals (unoptimized):
%		<Goal1, Goal2, Goal3, Goals>
% 	===>
%	{
%	        label0_func() {
%		        <Goal1 && label1_func()>;
%	        }
%	        label1_func() {
%		        <Goal2 && label2_func()>;
%	        }
%	        label2_func() {
%		        <Goal3 && label3_func()>;
%	        }
%	        label3_func() {
%		        <Goals && SUCCEED()>;
%	        }
%
%	        label0_func();
%	}

%	model_non goals (optimized):
%		<Goal1, Goal2, Goal3, Goals>
% 	===>
%	{
%	        label3_func() {
%		        <Goals && SUCCEED()>;
%	        }
%	        label2_func() {
%		        <Goal3 && label3_func()>;
%	        }
%	        label1_func() {
%		        <Goal2 && label2_func()>;
%	        }
%
%	        <Goal1 && label1_func()>;
%	}

%-----------------------------------------------------------------------------%
%
% Code for disjunctions
%

% model_det disj:

%	model_det goal:
%		<do (Goal ; Goals)>
%	===>
%		<do Goal>
%		/* <Goals> will never be reached */

%	model_semi goal:
%		<do (Goal ; Goals)>
%	===>
%	{
%		bool succeeded;
%	
%		<succeeded = Goal>;
%		if (!succeeded) {
%		    <do Goals>;
%		}
%	}

% model_semi disj:

%	model_det goal:
%		<succeeded = (Goal ; Goals)>
%	===>
%	{
%		bool succeeded;
%
%		<do Goal>
%		succeeded = TRUE
%		/* <Goals> will never be reached */
%	}

%	model_semi goal:
%		<succeeded = (Goal ; Goals)>
%	===>
%	{
%		bool succeeded;
%
%		<succeeded = Goal>;
%		if (!succeeded) {
%		    <succeeded = Goals>;
%		}
%	}

% model_non disj:
%
%	model_det goal:
%		<(Goal ; Goals) && SUCCEED()>
%	===>
%		<Goal>
%		SUCCEED();
%		<Goals && SUCCEED()>
%
%	model_semi goal:
%		<(Goal ; Goals) && SUCCEED()>
%	===>
%	{
%		bool succeeded;
%	
%		<succeeded = Goal>
%		if (succeeded) SUCCEED();
%		<Goals && SUCCEED()>
%	}
%
%	model_non goal:
%		<(Goal ; Goals) && SUCCEED()>
%	===>
%		<Goal && SUCCEED()>
%		<Goals && SUCCEED()>

%-----------------------------------------------------------------------------%
%
% Code for if-then-else
%

%	model_semi cond:
%		<(Cond -> Then ; Else)>
%	===>
%	{
%		bool succeeded;
%	
%		<succeeded = Cond>
%		if (succeeded) {
%			<Then>
%		} else {
%			<Else>
%		}
%	}

%	/*
%	** XXX The following transformation does not do as good a job of GC
%	**     as it could.  Ideally we ought to ensure that stuff used only
%	**     in the `Else' part will be reclaimed if a GC occurs during
%	**     the `Then' part.  But that is a bit tricky to achieve.
%	*/
%
%	model_non cond:
%		<(Cond -> Then ; Else)>
%	===>
%	{
%		bool succeeded;
%
%		void then_func() {
%			succeeded = TRUE;
%			<Then>
%		}
%
%		succeeded = FALSE;
%		<Cond && then_func()>
%		if (!succeeded) {
%			<Else>
%		}
%	}

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list