[m-rev.] for review: implement det exceptions on the .NET backend.

Peter Ross peter.ross at miscrit.be
Fri Aug 24 22:40:05 AEST 2001


On Thu, Aug 23, 2001 at 06:42:03PM +0200, Tyson Dowd wrote:
> Hi,
> 
> 
> ===================================================================
> 
> 
> Estimated hours taken: 16
> Branches: main
> 
> Implement exceptions in the .NET backend.
> (sorry, model_det exceptions only at the moment).
> 
> compiler/mlds_to_il.m:
> 	Wrap two exception handlers around the Mercury code -- one that
> 	prints out any uncaught user exceptions using
> 	ML_report_uncaught_exception, and one that catches any system
> 	exceptions and prints them using the system exception printing
> 	mechanism.
> 
I think it would be nice to make clearer that a user exception is an
exception that the Mercury runtime system understands and a system
exception is any other exception.

> library/exception.m:
> 	Implement exceptions in C#.
> 	try and catch call try_impl and catch_impl, which by default
> 	call builtin_trd and builtin_catch, but we provide a
> 	foreign_proc definition that implements them in C# on the .NET
> 	backend.
> 	We also implement ML_call_goal in Mercury, renaming the 
> 	hand-coded versions appropriately.
> 
> library/math.m:
> 	Throw mercury.runtime.SystemException for domain errors.
> 
Why?

> runtime/mercury_mcpp.cpp:
> 	Fix the implementation of mercury.runtime.Exception -- now we
> 	store the Mercury exception so you can retrieve it later.
> 
> 	Create a new class for Mercury runtime system exceptions, which
> 	are generated by SORRY and fatal_error.  We can't expect to
> 	print these exceptions using ML_report_uncaught_exception (at
> 	the moment ML_report_uncaught_exception generates such
> 	exceptions!) so we print them as normal .NET exceptions instead.
> 
> 
> Index: compiler/mlds_to_il.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_il.m,v
> retrieving revision 1.77
> diff -u -r1.77 mlds_to_il.m
> --- compiler/mlds_to_il.m	23 Aug 2001 09:28:03 -0000	1.77
> +++ compiler/mlds_to_il.m	23 Aug 2001 16:37:50 -0000
> @@ -990,7 +990,10 @@
>  		il_info_add_init_instructions(runtime_initialization_instrs),
>  		^ has_main := yes,
>  
> -		il_info_get_next_block_id(TryBlockId),
> +		il_info_get_next_block_id(InnerTryBlockId),
> +		il_info_get_next_block_id(OuterTryBlockId),
> +		il_info_get_next_block_id(InnerCatchBlockId),
> +		il_info_get_next_block_id(OuterCatchBlockId),
>  		il_info_make_next_label(DoneLabel),
>  
>  			% Replace all the returns with leave instructions;
> @@ -1006,43 +1009,123 @@
>  				I
>  			)
>  		)},
> +
> +		{ UnivMercuryType = term__functor(term__atom("univ"), [], 
> +			context("", 0)) },
> +		{ UnivMLDSType = mercury_type(UnivMercuryType, user_type) },
> +		{ UnivType = mlds_type_to_ilds_type(DataRep, UnivMLDSType) },
> +
>  		{ RenameNode = (func(N) = list__map(RenameRets, N)) },
>  
> -		{ ExceptionClassName = structured_name(assembly("mscorlib"),
> +		{ MercuryExceptionClassName = structured_name(
> +				assembly("mercury"),
> +				["mercury", "runtime", "Exception"], []) },
> +
You should add a il_mercury_library_assembly_name function, and use that
instead.

> +		{ ExceptionClassName = structured_name(il_system_assembly_name,
>  				["System", "Exception"], []) },
>  
> +		{ FieldRef = make_fieldref(UnivType, MercuryExceptionClassName,
> +			"mercury_exception") },
> +
>  		{ ConsoleWriteName = class_member_name(
>  				structured_name(il_system_assembly_name,
>  					["System", "Console"], []),
>  				id("Write")) },
> +
> +		{ UncaughtExceptionName = class_member_name(
> +				structured_name(assembly("mercury"),
> +					["mercury", "exception",
> +						"mercury_code"], []),
> +				id("ML_report_uncaught_exception")) },
> +
>  		{ WriteString = methoddef(call_conv(no, default),
>  					void, ConsoleWriteName,
>  					[il_string_type]) },
> +		{ WriteUncaughtException = methoddef(call_conv(no, default),
> +					void, UncaughtExceptionName,
> +					[UnivType]) },
>  		{ WriteObject = methoddef(call_conv(no, default),
>  					void, ConsoleWriteName,
>  					[il_generic_type]) },
>  
> +
> +			% A code block to catch any exception at all.
> +	
> +		{ CatchAnyException = tree__list([
> +			instr_node(start_block(
> +				catch(ExceptionClassName),
> +				OuterCatchBlockId)),
> +			instr_node(ldstr("\nUncaught system exception: \n")),
> +			instr_node(call(WriteString)),
> +			instr_node(call(WriteObject)),
> +			instr_node(leave(label_target(DoneLabel))),
> +			instr_node(end_block(catch(ExceptionClassName),
> +				OuterCatchBlockId))
> +			])
> +		},
> +
> +			% Code to catch Mercury exceptions.
> +		{ CatchUserException = tree__list([
> +			instr_node(start_block(
> +				catch(MercuryExceptionClassName),
> +				InnerCatchBlockId)),
> +			instr_node(ldfld(FieldRef)),
> +
> +			instr_node(call(WriteUncaughtException)),
> +
> +			instr_node(leave(label_target(DoneLabel))),
> +			instr_node(end_block(
> +				catch(MercuryExceptionClassName),
> +				InnerCatchBlockId))
> +			])
> +		},
> +
>  			% Wrap an exception handler around the main
>  			% code.  This allows us to debug programs
>  			% remotely without a window popping up asking
>  			% how you wish to debug.  Pressing the cancel
>  			% button on this window is a bit difficult
>  			% remotely.
> +			%
> +			% Inside this exception handler, we catch any user
> +			% exceptions and pass them 
> +			%
s/user/mercury/

pass them where?

> +			% We nest the Mercury exception handler so that any
> +			% exceptions thrown in ML_report_uncaught_exception
> +			% will be caught by the outer (more general) exception
> +			% handler.
> +			%
> +			% try {
> +			%	try {
> +			%		... main instructions ...
> +			%	}
> +			%	catch (mercury.runtime.Exception me) {
> +			%		ML_report_uncaught_exception(me);
> +			%	}
> +			% } 
> +			% catch (System.Exception e) {
> +			%	System.Console.Write(e);
> +			% }
> +
>  		{ InstrsTree = tree__list([
> -				instr_node(start_block(try, TryBlockId)),
> +
> +					% outer try block
> +				instr_node(start_block(try, OuterTryBlockId)),
> +
> +					% inner try block
> +				instr_node(start_block(try, InnerTryBlockId)),
>  				tree__map(RenameNode, InstrsTree2),
>  				instr_node(leave(label_target(DoneLabel))),
> -				instr_node(end_block(try, TryBlockId)),
> +				instr_node(end_block(try, InnerTryBlockId)),
> +				
> +					% inner catch block
> +				CatchUserException,
>  
> -				instr_node(start_block(
> -						catch(ExceptionClassName),
> -						TryBlockId)),
> -				instr_node(ldstr("\nException Caught: \n")),
> -				instr_node(call(WriteString)),
> -				instr_node(call(WriteObject)),
>  				instr_node(leave(label_target(DoneLabel))),
> -				instr_node(end_block(catch(ExceptionClassName),
> -						TryBlockId)),
> +				instr_node(end_block(try, OuterTryBlockId)),
> +
> +					% outer catch block
> +				CatchAnyException,
>  
>  				instr_node(label(DoneLabel)),
>  				instr_node(ret)

> Index: runtime/mercury_mcpp.cpp
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/runtime/mercury_mcpp.cpp,v
> retrieving revision 1.8
> diff -u -r1.8 mercury_mcpp.cpp
> --- runtime/mercury_mcpp.cpp	16 Aug 2001 15:04:14 -0000	1.8
> +++ runtime/mercury_mcpp.cpp	23 Aug 2001 16:37:53 -0000
> @@ -25,17 +25,29 @@
>  
>  namespace runtime {
>  
> -	// XXX Exception support is utterly incomplete.
> +	// A user exception -- really just a wrapper for the exception
> +	// data.
> +
>  __gc public class Exception : public System::Exception
>  {
>  public:
> -	// XXX there should be a Mercury object here.
> -    Exception(MR_String Msg) : System::Exception(Msg)
> -    { 
> -	// XXX this should set the exception message
> -    }
> +   Exception(MR_Word data) 
> +   {
> +   	mercury_exception = data;	
> +   }
> +   MR_Word mercury_exception;
>  };
>  
> +__gc public class SystemException : public System::Exception
> +{
> +public:
> +	SystemException(MR_String Msg) : System::Exception(Msg)
> +	{	
> +		// XXX this should set the exception message
> +	}
> +};

What happens now if you call SORRY or fatal_error,
do you still get the message?  If not I think you should fix this.

> +
> +
>  __gc public class LowLevelData
>  {
>  
> @@ -75,14 +87,14 @@
>      {
>          MR_String msg;
>          msg = System::String::Concat("Sorry, unimplemented: ", s);
> -        throw new mercury::runtime::Exception(msg);
> +        throw new mercury::runtime::SystemException(msg);
>      }
>  
>      static void fatal_error(MR_String s)
>      {
>          MR_String msg;
>          msg = System::String::Concat("Fatal error: ", s);
> -        throw new mercury::runtime::Exception(msg);
> +        throw new mercury::runtime::SystemException(msg);
>      }
>  };
>  
--------------------------------------------------------------------------
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