Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!unmvax!pprg.unm.edu!hc!lll-winken!uunet!tektronix!percival!parsely!agora!ihf1!bobd From: bobd@ihf1.UUCP (Bob Dietrich) Newsgroups: comp.lang.pascal Subject: Dynamic exception handling for Extended Pascal (long) Keywords: Extended Pascal exception handling Message-ID: <592@ihf1.UUCP> Date: 27 Mar 89 21:45:37 GMT Organization: Intel Corp., Hillsboro, Oregon Lines: 240 Here is a simplistic proposal for dynamic exception handling that I included as part of my public comment on Extended Pascal. It was not accepted nor dealt with in detail (as I expected), but it was retained for future study. The basic approach is to define a required (module) interface that allows you to dynamically push and pop exception handlers. An exception handler is really just a user-defined procedure which receives information about the exception that caused the procedure to be invoked. Before the handler is invoked, it is removed from the handler stack, so exiting the handler causes the previous (or default) handler to be activated for the same exception. No ability to "retry" a failed operation is provided since it was felt too difficult to provide in a machine-independent manner. Beware, all Ye who enter here: Standardese lies ahead. There is an example at the end, however. Bob Dietrich Intel Corporation, Hillsboro, Oregon (503) 696-2092 usenet: uunet!littlei!intelhf!ihf1!bobd or tektronix!tessi!agora!ihf1!bobd or tektronix!ogccse!omepd!ihf1!bobd or tektronix!psu-cs!omepd!ihf1!bobd =================== Simplistic Dynamic Exception Handling This proposal draws heavily from JPC/84-151 Exception Handling Report, which details a static scheme that JPC chose to exclude from Extended Pascal. As a dynamic facility, this proposal does exhibit many of the drawbacks cited in the Exception Handling Report, but this proposal might have a slightly higher chance of approval. Dynamic exception handling has also be written as a required interface so that at some time in the future it can be replaced by the static proposal without too many headaches. Text to be modified [based on the current draft proposed Extended Pascal document JPC/88-151]: (1) Add the following clause to 5.1(f): (5) the processor shall cause an exception (see 6.2.5) corresponding to the violation; (2) Add a third note to 6.2.2.19: (3) The required identifier Dynamic_Exceptions and its constituent-identifiers are not included, since Dynamic_Exceptions denotes a required interface (see 6.11.4.3). (3) Add a new section 6.2.5: 6.2.5 Exceptions. An exception shall be a state of execution that occurs when an error is detected during execution of a program. An exception shall be designated raised when the processor detects the corresponding error or by invocation of a procedure that causes the processor to go into a state similar to that of detecting an error. An exception handler is a procedure that is activated by the processor as a result of an exception being raised. Normal execution shall resume when an exception handler for the associated exception is activated (see 6.11.4.3). The exception names and the errors causing the exception shall be as follows: Insert here section 6.6.X from 84-151, changing "state of execution" to "error" throughout. Note that as they exist in 84-151, the statements of error are not complete; they need to be updated to indicate some additional errors and the newer I/O procedures and functions. [For those who have never seen this document, it essentially enumerates an exception for each error, such as Divide_By_Zero. Also, 84-151 was not based on Extended Pascal, which adds some errors to those of Pascal.] Continuing the text to be added: Notes: (1) Because the detection of errors may vary from processor to processor, so may the invocation of an exception handler. (2) An implementation may cause an exception when an implementation-defined limit is exceeded. (4) Add a new section 6.11.4.3: 6.11.4.3 Dynamic_Exceptions. 6.11.4.3.1 General. The required interface-identifier Dynamic_Exceptions shall denote the required interface composed of the required constituents Push_Handler, Pop_Handler, Raise_Exception, Handler_Exists, Exception_Codes, Exception_Set, Exception_Info, and the exceptions named in section 6.2.5. The constituent-identifiers shall denote a procedure, procedure, procedure, function, type, type, type, and values, respectively. 6.11.4.3.2 Interface Constituents. The required type-identifier Exception_Codes shall denote the enumeration-type whose values are denoted by the exception names as specified in section 6.2.5. The ordering of the values shall be implementation-defined. The required type-identifier Exception_Set shall denote a set-type designated packed whose base-type is the type Exception_Codes. The required type-identifier Exception_Info shall denote a record-type designated packed. The required field-identifier cause shall denote an associated required field of the record-type, and that field shall have the type denoted by the required type-identifier Exception_Codes. Note: A processor may provide additional fields as an extension. The required procedure-identifier Push_Handler shall denote the corresponding required procedure possessing a procedure-heading equivalent to: procedure Push_Handler(eset: Exception_Set; procedure handler( var i: Exception_Info)); The effect of invoking the required procedure Push_Handler shall be to save the current exception handler, if any, for the exceptions designated by eset, and the procedure denoted by the procedural parameter shall become the exception handler for the designated exceptions. The current exception handler prior to any invocations of Push_Handler shall be implementation-defined. The required procedure-identifier Pop_Handler shall denote the corresponding required procedure possessing a single value parameter. The type of the formal parameter associated with the value parameter shall be denoted by the required-type Exception_Set. The effect of invoking Pop_Handler shall be to replace the current exception handler for the exceptions designated by the value parameter with the previously-current exception handler for those exceptions. It shall be an error if there is no previous exception handler for the designated exceptions. The required procedure-identifier Raise_Exception shall denote the corresponding required procedure possessing a single value parameter. The type of the formal parameter associated with the value parameter shall be denoted by the required-type Exception_Set. The effect of invoking Raise_Exception shall be to raise the exception designated by the cause field of the value parameter, and to pass the value parameter as the actual parameter to the current exception handler for the designated exception. The required function-identifier Handler_Exists shall denote the corresponding required function returning a value of type Boolean and possessing a single value parameter. The type of the formal parameter associated with the value parameter shall be denoted by the required-type Exception_Set. The result of invoking Handler_Exists shall be true if there exists a current exception handler for the exceptions designated by the value parameter, and false otherwise. 6.11.4.3.3 Exception Handlers. Prior to the activation of the block of an exception handler made current by Push_Handler, the equivalent of invoking Pop_Handler shall be performed for the exception that has been raised, and the cause field of the actual parameter to the exception handler shall be attributed a value of type Error_Codes that designates the raised exception. If no exception handler is currently associated with the exception that has been raised, the processor shall report the lack of an exception handler and terminate the program. The activation of an exception handler shall terminate in one of the following ways. (1) Execution of the halt procedure (see 6.7.5.7). (2) Execution of a goto-statement (see 6.9.2.4) to a program-point not contained by the block of the exception handler. (3) Completion of the algorithm of the exception handler. Completion of the algorithm of the exception handler shall cause the exception that caused the activation of the exception handler to be raised again. 6.11.4.3.4 Exception Handling Example. program average( input, output); import Dynamic_Exceptions; label 9999; { When input finished } var sum: integer value 0; count: 0..maxint; function GetInteger: integer; label 1; { To retry read operation } var number: integer; procedure BadInput( var info: Exception_Info); begin writeln(output, 'The number was incorrectly formatted.'); writeln(output, 'Please try again'); goto 1; end; begin 1: Push_Handler( [Conversion_Error], BadInput); read(input, number); GetInteger := number; Pop_Handler( [Conversion_Error]); end; procedure Unexpected_EOF( var info: Exception_Info ); begin goto 9999 { Treat as normal eof } end; procedure BadComputation( var info: Exception_Info ); begin write(output, 'Error in computation due to '); case info.cause of Overflow: write(output, 'overflow'); Divide_By_Zero: write(output, 'division by zero'); Undefined_Result: write(output, 'invalid function call'); otherwise write(output, 'program bug') end; writeln( output); writeln( output, 'Cannot continue: Good bye'); halt; end; begin Push_Handler( [End_of_File], Unexpected_EOF); { Note the following set is equivalent to [Overflow, Divide_By_Zero, Invalid_Operand, Invalid_Argument, Incompatible _Argument, Undefined_Result, Nonexistent_Result] } Push_Handler( [Operator_Error, Activation_Error], BadComputation); count := 0; while not eof(input) do begin count := count + 1; write(output, 'Please enter a number: '); sum := sum + GetInteger; end; 9999: writeln(output, 'The average is ', sum div count); end.