exceptions
David Farber
dfarber at numenor.com
Mon Mar 9 22:12:14 UTC 1998
i've coded up an exception mechanism for squeak. it is a port of Bob Hinkle
and Ralph Johnson's exception mechanism for V286. one of the big points of
this setup is that it is supposed to mimic the ParcPlace (and even Tek)
exceptions.
is this useful to anyone from the compatibility standpoint? i don't have
access to a PP environment, so i can't tell for certain that i haven't
introduced some incompatibilty in the translation.
it all *seems* to work, but i haven't hammered on it too hard. i am going to
wait a bit before i throw it up on UIUC; give it a week or two to let the
(inevitable) bugs crawl out.
if you are not already familiar with PP's exception mechanism, i don't know
how useful this will be to you. 'print' the one-liner examples in the
ExceptionCollection class comments to to get a basic idea of what is going
on. i'll put together some better documentation before i put it onto UIUC.
dave
Exceptions.cs
----
Object classPool
at: 'ErrorSignal'
ifAbsent: [
Object classPool at: 'ErrorSignal' put: nil]!
'From Squeak 1.31 of Feb 4, 1998 on 9 March 1998 at 5:21:33 pm'!
Object subclass: #Exception
instanceVariableNames: 'signal parameter extraString proceedBlock
handlerContext signalContext process '
classVariableNames: 'EmergencyHandler '
poolDictionaries: ''
category: 'Exceptions'!
OrderedCollection variableSubclass: #ExceptionCollection
instanceVariableNames: ''
classVariableNames: 'OutOfBoundsError '
poolDictionaries: ''
category: 'Exceptions'!
Object subclass: #Signal
instanceVariableNames: 'parent mayProceed notifierString nameClass
nameMessage '
classVariableNames: 'GenericSignal NoHandlerSignal ProceedErrorSignal
TimeoutSignal WrongProceedabilitySignal '
poolDictionaries: ''
category: 'Exceptions'!
!Object methodsFor: 'as yet unclassified'!
errorSignal
^self class errorSignal! !
!Exception methodsFor: 'handling' stamp: 'df 3/7/98 16:04'!
proceed
"Return nil as the value of the raised signal. Unwind the stack
up to that point and resume execution in the context that raised
the signal."
^self proceedWith: nil! !
!Exception methodsFor: 'handling' stamp: 'df 3/9/98 16:34'!
proceedDoing: aBlock
| answer |
"Return the value of aBlock as the value of the raised signal.
Unwind the stack
up to that point and resume execution in the context that raised
the signal.
The comment for the PP version says that 'the block is executed in
the handler
context of the signaller, so (for example) it can raise a different
signal in place
of the original one.' I'm not sure exactly what that means, but I
think the code
below has the effect they're (trying to) describe."
proceedBlock isNil
ifTrue: [
"If proceedBlock is nil, we're not supposed to
proceed on this
Signal, so raise a new error."
Signal proceedErrorSignal raiseWith: self]
ifFalse: [
answer := aBlock value.
self unwindLaterContextsFrom: handlerContext.
proceedBlock value: answer
"The next line is how this branch was implemented
originally, but
with my implementation it would return *out* of the
signalling context (rather
than in to it). I don't think I've done anything
that would affect this
behavior--maybe it was a bug in the original version?"
"signalContext returnDoing: aBlock"]! !
!Exception methodsFor: 'handling' stamp: 'df 3/5/98 17:46'!
proceedWith: aValue
"Return aValue as the value of the raised signal. Unwind the stack
up to that point and resume execution in the context that raised
the signal."
self proceedDoing: [aValue]! !
!Exception methodsFor: 'handling' stamp: 'df 3/4/98 22:59'!
reject
"Pass the exception on to the next handler."
| |
self propagatePrivateFrom: handlerContext.! !
!Exception methodsFor: 'handling' stamp: 'df 3/9/98 16:39'!
restart
"Restart the #handle:do: context."
self unwindLaterContextsFrom: handlerContext.
handlerContext restart.
process := Processor activeProcess.
[
"Transcript show: process printString; cr.
Transcript show: process suspendedContext printString; cr.
Transcript show: handlerContext printString; cr.
Transcript show: handlerContext sender printString; cr."
process popTo: handlerContext.
"Transcript show: process printString; cr.
Transcript show: process suspendedContext printString; cr.
Transcript show: handlerContext sender printString; cr; cr."
process resume.] fork.
process suspend.
! !
!Exception methodsFor: 'handling' stamp: 'df 3/9/98 16:07'!
restartDo: aBlock
"Restart the #handle:do: context, but replace the value of the doBlock
(ie, second parameter) with aBlock."
handlerContext tempAt: 2 put: aBlock.
self restart.
! !
!Exception methodsFor: 'handling' stamp: 'df 3/7/98 16:09'!
return
"Return nil as the value of the handle:do: message that
caught this Exception."
self returnWith: nil! !
!Exception methodsFor: 'handling' stamp: 'df 3/9/98 16:40'!
returnDoing: aBlock
"The stack is unwound to he context of the handle:do
message that caught this Exception, at which point
aBlock is evaluated and its value returned as the
value of the handle:do: message."
| answer |
answer := aBlock value.
self unwindLaterContextsFrom: handlerContext.
(handlerContext at: 3) value: answer.! !
!Exception methodsFor: 'handling' stamp: 'df 3/5/98 17:10'!
returnWith: aValue
"Return aValue as the value of the handle:do: message that
caught this Exception."
self returnDoing: [aValue].
! !
!Exception methodsFor: 'public' stamp: 'df 3/7/98 16:02'!
defaultHandlerAction: parm
"Choose the default handler response."
^self returnWith: parm! !
!Exception methodsFor: 'public' stamp: 'df 3/7/98 16:03'!
errorString
"Return the error string for this Exception, which is generated
by its Signal."
^signal errorStringExtra: extraString with: parameter! !
!Exception methodsFor: 'public' stamp: 'df 3/5/98 16:24'!
fetchHandlerBlock: startContext
"Find the context of the exception handler block"
| aContext |
aContext := startContext.
[aContext notNil]
whileTrue:
[(aContext selector == #handle:do:)
ifTrue:
[handlerContext := aContext.
^aContext tempAt: 1].
aContext := aContext sender].
^nil! !
!Exception methodsFor: 'public' stamp: 'df 3/7/98 16:04'!
parameter
^parameter! !
!Exception methodsFor: 'public' stamp: 'df 3/5/98 17:03'!
propagateFrom: startContext
"Starting below startContext, look down the call stack to find a
handler for this
Exception, and execute the handler once you've found it.
In the original Tek version this would have been an infinite loop,
allowing handlers
to pass on control to others without explicitly doing a reject. In
PP, though, any
handler that doesn't take a positive action is assumed to take a
default action,
which at this point is a #returnWith:."
signalContext := startContext.
^self propagatePrivateFrom: startContext! !
!Exception methodsFor: 'public' stamp: 'df 3/7/98 16:10'!
signal
"This is the signal whose raising created this exception."
^signal! !
!Exception methodsFor: 'public' stamp: 'df 3/5/98 17:48'!
signal: sig parameter: par extraString: str proceedBlock: pb
"Initialize the Exception's instance variables.
sig is the Signal whose raising created this Exception.
par and str are used to generate this Exception's error string.
pb is either a block used to proceed or nil, indicating that
proceeding isn't allowed."
signal := sig.
parameter := par.
extraString := str.
proceedBlock := pb! !
!Exception methodsFor: 'public' stamp: 'df 3/9/98 16:43'!
unwindLaterContextsFrom: exContext
""
| aContext |
aContext := signalContext.
[aContext == exContext]
whileFalse:
[(aContext selector == #valueOnUnwindDo:)
ifTrue:
[(aContext tempAt:1 ) value]
ifFalse:
[(aContext selector == #valueNowOrOnUnwindDo:)
ifTrue: [(aContext tempAt:1 ) value]].
aContext := aContext sender].
^nil! !
!Exception methodsFor: 'private' stamp: 'df 3/7/98 16:03'!
handlerContext
"Return the context of the #handle:do: message that will
handle this Exception."
^handlerContext! !
!Exception methodsFor: 'private' stamp: 'df 3/7/98 16:04'!
initialContext
"Return the context passed into this Exception via the #propagateFrom:
message. This is the context where signal was first raised."
^signalContext! !
!Exception methodsFor: 'private' stamp: 'df 3/5/98 17:09'!
propagatePrivateFrom: startContext
"Starting below startContext, look down the call stack to find a
handler for this
Exception, and execute the handler once you've found it. This is
called from
#propagateFrom: and also after a #reject."
| result handlerBlock unhandledExc |
handlerBlock := self fetchHandlerBlock: startContext.
handlerBlock isNil
ifFalse: [result := handlerBlock value: self]
ifTrue: [(Signal noHandlerSignal accepts: signal)
ifTrue: [
"This exception represents an unhandled
exception already. It must
have been rejected to get down the call
stack below Signal>>noHandlerSignal,
so just use the EmergencyHandler--that's
what it's there for. For an
unhandled exception, parameter should be the
exception that couldn't be
handled originally."
^EmergencyHandler value: parameter value:
parameter initialContext]
ifFalse: [
"There's no handler for this exception, so
raise an unhandled-exception exception.
Note that we pass self as the parameter to
the new exception, which is why we
knew what the value of parameter would be in
the comment above."
unhandledExc := self class new
signal: Signal noHandlerSignal
parameter: self
extraString: nil
proceedBlock: nil.
(handlerBlock := unhandledExc
fetchHandlerBlock: signalContext) isNil
ifTrue: [
"We got trouble!!!! Use the
EmergencyHandler again, and tell someone
to get an
unhandled-exception handler together."
^EmergencyHandler value:
self value: signalContext]
ifFalse: [result := handlerBlock
value: unhandledExc]]].
"If we get here, the selected handler didn't choose a specific
option between proceeding, returning, and rejecting, so choose
the default response."
^self defaultHandlerAction: result! !
!Exception methodsFor: 'private' stamp: 'df 3/7/98 16:10'!
willProceed
"This exception can proceed if proceedBlock isn't nil; otherwise
proceeding isn't allowed."
^proceedBlock notNil! !
!ExceptionCollection commentStamp: 'df 3/9/98 17:21' prior: 0!
Examples:
({1. 2. 3. 4. 5} as: ExceptionCollection) getFifthElement
({1. 2. 3. 4} as: ExceptionCollection) getFifthElement
({1. 2. 3. 4} as: ExceptionCollection) getDoubledFifthElement
({1. 2. 3. 4} as: ExceptionCollection) getForcedFifthElement
!
!ExceptionCollection methodsFor: 'as yet unclassified' stamp: 'df 3/5/98 17:41'!
at: anIndex
""
(self size < anIndex)
ifTrue: [^OutOfBoundsError raise]
ifFalse: [^super at: anIndex].! !
!ExceptionCollection methodsFor: 'as yet unclassified' stamp: 'df 3/7/98 17:35'!
doubledAt: anIndex
""
| value |
value := (self size < anIndex)
ifTrue: [OutOfBoundsError raiseRequest]
ifFalse: [super at: anIndex].
^value * 2
! !
!ExceptionCollection methodsFor: 'as yet unclassified' stamp: 'df 3/7/98 17:36'!
getDoubledFifthElement
^OutOfBoundsError
handle: [:exception | exception proceedWith: 5]
do: [self doubledAt: 5]
! !
!ExceptionCollection methodsFor: 'as yet unclassified' stamp: 'df 3/7/98 15:45'!
getFifthElement
^OutOfBoundsError
handle: [:exception | exception returnWith: 'Bob']
do: [self at: 5]
! !
!ExceptionCollection methodsFor: 'as yet unclassified' stamp: 'df 3/9/98 09:41'!
getForcedFifthElement
^OutOfBoundsError
handle:
[:exception |
self add: 'Bob'.
exception restart]
do: [self at: 5]
! !
!Object class methodsFor: 'as yet unclassified'!
errorSignal
^ErrorSignal! !
!Exception class methodsFor: 'as yet unclassified' stamp: 'df 3/7/98 16:01'!
emergency: exception from: context
"Define a default emergency handler.
This one is appropriate for development
environments, but not for runtime."
self halt! !
!Exception class methodsFor: 'as yet unclassified' stamp: 'df 3/7/98 16:01'!
emergencyHandler: aBlock
"Define an emergency handler
for unhandled exceptions."
EmergencyHandler := aBlock! !
!Exception class methodsFor: 'as yet unclassified' stamp: 'df 3/7/98 16:02'!
initialize
"Install the emergency handler"
"Exception initialize"
self emergencyHandler: [:exception :context | self emergency:
exception from: context]! !
!ExceptionCollection class methodsFor: 'as yet unclassified' stamp: 'df
3/5/98 17:37'!
initialize
"comment stating purpose of message"
| |
OutOfBoundsError := Signal genericSignal newSignal.! !
!Signal methodsFor: 'public-creation' stamp: 'df 3/5/98 17:35'!
newSignal
"Create a new signal, whose parent is self and whose proceedability
is false.
Note that basicNew has to be used below, since Signal>>new
creates a signal whose parent is Object>>errorSignal."
^self class basicNew parent: self! !
!Signal methodsFor: 'public-creation' stamp: 'df 3/5/98 17:22'!
newSignalMayProceed: proceedBoolean
"Create a new signal, whose parent is self and whose proceedability
is equal to proceedBoolean.
Note that basicNew has to be used below, since Signal>>new
creates a signal whose parent is Object>>errorSignal."
^self class basicNew parent: self mayProceed: proceedBoolean! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/5/98 19:39'!
accepts: aSignal
"Answer true if a handler for this Signal should be run
to handle aSignal. A Signal will handle any exception
raised on itself *or* on one of its children, so accept
if self == aSignal, or if aSignal equals one of this Signal's
children."
| p |
^aSignal == self or:
[(p := aSignal parent) notNil and: [self accepts: p]]! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/5/98 19:39'!
deepCopy
"According to the PP implementation, deepCopying a Signal
'doesn't make any sense.' I'm not sure why, so I'll allow
deepCopying for now."
"^super deepCopyError"
^super deepCopy! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/5/98 19:40'!
errorString
"Build the error string from notifierString. Prepend my parent's
errorString if notifierString starts with a blank."
^notifierString isNil
ifTrue: [parent errorString]
ifFalse: [(notifierString isEmpty not and: [
notifierString first = Character space])
ifTrue: [parent errorString, notifierString]
ifFalse: [notifierString]]! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/5/98 19:40'!
errorStringExtra: aString
"Build the error string from aString. Prepend my
errorString if aString starts with a blank."
^aString isNil
ifTrue: [self errorString]
ifFalse: [(aString isEmpty not and:
[aString first = Character space])
ifTrue: [self errorString, aString]
ifFalse: [aString]]! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/5/98 19:42'!
errorStringExtra: aString with: parameter
"Build the error string from aString. Append parameter's
printString if my error string ends with a blank.
They didn't have the check for isEmpty not in the PP version,
but it seems necessary to me."
| errorString |
errorString := self errorStringExtra: aString.
^(errorString isEmpty not and:
[errorString last = Character space])
ifTrue: [errorString, parameter printString]
ifFalse: [errorString]! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/8/98 21:46'!
handle: handlerBlock do: doBlock
"Evaluate doBlock. If all goes well, return its value.
If an exception occurs than the returned value could
be generated by evaluating returnBlock."
| returnBlock |
thisContext push: nil.
thisContext pop.
returnBlock := [:value | ^value].
^doBlock value! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/5/98 19:42'!
isClassSignal
"Return true if this Signal belongs to a class, which means
that it's stored in one of nameClass' class variables and
returned (statically) via the method nameMessage.
In the PP version they test whether this method returnsStaticVariable;
for Tek the closest equivalent seems to be isReturnField. For
Digitalk, I just check that nameClass supports nameMessage and
that the return from sending nameMessage is this signal."
| assoc |
^nameClass notNil and:
[(nameClass class includesSelector: nameMessage) and:
[(nameClass perform: nameMessage) == self]]! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/5/98 17:39'!
mayProceed
"Answer true if execution can proceed from this signal's context."
^mayProceed! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/5/98 17:22'!
nameClass: aClass message: aSymbol
"nameClass and nameMessage are used in printOn:."
nameClass := aClass.
nameMessage := aSymbol! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/5/98 17:33'!
newException
"Create a new Exception object.
Provided as a method for over-riding."
^Exception new! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/5/98 17:23'!
notifierString: aString
"notifierString is used to generate this Signal's error string, and
for printOn:.
If aString starts with a blank, this Signal will build its error
string by appending aString to this Signal's parent's error string."
notifierString := aString! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/5/98 19:43'!
parent
^parent! !
!Signal methodsFor: 'public-misc' stamp: 'df 3/5/98 19:44'!
printOn: aStream
self isClassSignal
ifTrue: [aStream nextPutAll: nameClass printString, ' ',
nameMessage]
ifFalse: [super printOn: aStream.
notifierString isNil
ifTrue: [aStream nextPutAll: ' with parent: '.
parent printOn: aStream]
ifFalse: [aStream nextPutAll: ' with
notifierString: '.
notifierString printOn: aStream]]! !
!Signal methodsFor: 'public-raises' stamp: 'df 3/5/98 19:41'!
raise
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender.
The Exception may not proceed back into this signaller."
^self
raiseWith: nil
startAbove: thisContext
extraString: nil
proceed: false! !
!Signal methodsFor: 'public-raises' stamp: 'df 3/5/98 19:46'!
raiseErrorString: aString
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender.
Pass aString to the Exception for its error message.
The Exception may not proceed back into this signaller."
^self
raiseWith: nil
startAbove: thisContext
extraString: aString
proceed: false! !
!Signal methodsFor: 'public-raises' stamp: 'df 3/7/98 17:09'!
raiseReturn
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender's home's
sender.
The Exception may not proceed back into this signaller."
^self
raiseReturnWith: nil
startAbove: thisContext
extraString: nil
proceed: false! !
!Signal methodsFor: 'public-raises' stamp: 'df 3/7/98 17:09'!
raiseReturnErrorString: aString
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender's home's
sender.
Pass aString to the Exception for its error message.
The Exception may not proceed back into this signaller."
^self
raiseReturnWith: nil
startAbove: thisContext
extraString: aString
proceed: false! !
!Signal methodsFor: 'public-raises' stamp: 'df 3/7/98 17:09'!
raiseReturnWith: parameter
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender's home's
sender.
Pass parameter to the Exception to use as its parameter.
The Exception may not proceed back into this signaller."
^self
raiseReturnWith: parameter
startAbove: thisContext
extraString: nil
proceed: false! !
!Signal methodsFor: 'public-raises' stamp: 'df 3/7/98 17:09'!
raiseReturnWith: parameter errorString: aString
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender's home's
sender.
Pass parameter to the Exception to use as its parameter.
Pass aString to the Exception for its error message.
The Exception may not proceed back into this signaller."
^self
raiseReturnWith: parameter
startAbove: thisContext
extraString: aString
proceed: false! !
!Signal methodsFor: 'public-raises' stamp: 'df 3/7/98 17:09'!
raiseWith: parameter
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender.
Pass parameter to the Exception to use as its parameter.
The Exception may not proceed back into this signaller."
^self
raiseWith: parameter
startAbove: thisContext
extraString: nil
proceed: false! !
!Signal methodsFor: 'public-raises' stamp: 'df 3/7/98 17:09'!
raiseWith: parameter errorString: aString
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender.
Pass parameter to the Exception to use as its parameter.
Pass aString to the Exception for its error message.
The Exception may not proceed back into this signaller."
^self
raiseWith: parameter
startAbove: thisContext
extraString: aString
proceed: false! !
!Signal methodsFor: 'public-raise requests' stamp: 'df 3/5/98 19:46'!
raiseRequest
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender.
The Exception may proceed back into this signaller."
^self
raiseWith: nil
startAbove: thisContext
extraString: nil
proceed: true! !
!Signal methodsFor: 'public-raise requests' stamp: 'df 3/5/98 19:46'!
raiseRequestErrorString: aString
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender.
Pass aString to the Exception for its error message.
The Exception may proceed back into this signaller."
^self
raiseWith: nil
startAbove: thisContext
extraString: aString
proceed: true! !
!Signal methodsFor: 'public-raise requests' stamp: 'df 3/5/98 19:45'!
raiseRequestReturn
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender's home's
sender.
The Exception may proceed back into this signaller."
^self
raiseReturnWith: nil
startAbove: self thisContext
extraString: nil
proceed: true! !
!Signal methodsFor: 'public-raise requests' stamp: 'df 3/5/98 19:47'!
raiseRequestReturnErrorString: aString
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender's home's
sender.
Pass aString to the Exception for its error message.
The Exception may proceed back into this signaller."
^self
raiseReturnWith: nil
startAbove: self thisContext
extraString: aString
proceed: true! !
!Signal methodsFor: 'public-raise requests' stamp: 'df 3/5/98 19:47'!
raiseRequestReturnWith: parameter
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender's home's
sender.
Pass parameter to the Exception to use as its parameter.
The Exception may proceed back into this signaller."
^self
raiseReturnWith: parameter
startAbove: self thisContext
extraString: nil
proceed: true! !
!Signal methodsFor: 'public-raise requests' stamp: 'df 3/5/98 19:48'!
raiseRequestReturnWith: parameter errorString: aString
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender's home's
sender.
Pass parameter to the Exception to use as its parameter.
Pass aString to the Exception for its error message.
The Exception may proceed back into this signaller."
^self
raiseReturnWith: parameter
startAbove: self thisContext
extraString: aString
proceed: true! !
!Signal methodsFor: 'public-raise requests' stamp: 'df 3/5/98 19:48'!
raiseRequestWith: parameter
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender.
Pass parameter to the Exception to use as its parameter.
The Exception may proceed back into this signaller."
^self
raiseWith: parameter
startAbove: self thisContext
extraString: nil
proceed: true! !
!Signal methodsFor: 'public-raise requests' stamp: 'df 3/7/98 17:08'!
raiseRequestWith: parameter errorString: string
"Create an Exception on the receiver and search for a handler.
Search for a handler starting at self thisContext's sender.
Pass parameter to the Exception to use as its parameter.
The Exception may proceed back into this signaller."
^self
raiseWith: parameter
startAbove: self thisContext
extraString: string
proceed: true! !
!Signal methodsFor: 'private' stamp: 'df 3/5/98 17:39'!
parent: aSignal
"Set this Signal's parent to aSignal. This may only be done once.
If this Signal is raised, it can be handled by any handler for it *or*
one of its ancestors."
self parent: aSignal mayProceed: aSignal mayProceed! !
!Signal methodsFor: 'private' stamp: 'df 3/5/98 17:23'!
parent: aSignal mayProceed: aBoolean
"Set this Signal's parent to aSignal. This may only be done once.
If this Signal is raised, it can be handled by any handler for it
*or* one of its ancestors."
parent notNil
ifTrue: [self error: 'Tried to reset a Signal''s parent.'.
^self].
parent := aSignal.
mayProceed := aBoolean! !
!Signal methodsFor: 'private' stamp: 'df 3/5/98 19:50'!
raiseReturnWith: parameter startAbove: context extraString: str proceed:
aBoolean
"Create an exception on the receiver. Start looking for a
handler in the sender of context's sender's home. Ie, if context
is a BlockContext, start looking for a handler in the sender of
the method that defines the block executing in context."
"In the PP version, they checked to see whether
context sender home == nil.
This could happen if the block was optimized. Check whether
this is possible in Tektronix-land."
^self
raiseWith: parameter
startingAt: context sender home sender
extraString: str
proceed: aBoolean! !
!Signal methodsFor: 'private' stamp: 'df 3/4/98 23:27'!
raiseWith: parameter startAbove: context extraString: str proceed: aBoolean
"Create an exception on the receiver. Start looking for a
handler in the sender of context."
^self
raiseWith: parameter
startingAt: context sender
extraString: str
proceed: aBoolean! !
!Signal methodsFor: 'private' stamp: 'df 3/4/98 22:15'!
raiseWith: parameter startingAt: context extraString: str proceed: aBoolean
"Create a new exception and have it look for handlers starting at <context>"
| exception |
exception := self newException
signal: self
parameter: parameter
extraString: str
proceedBlock:
(aBoolean
ifTrue: [[:value | ^value]]
ifFalse: [nil]).
^exception propagateFrom: context! !
!Signal class methodsFor: 'as yet unclassified' stamp: 'df 3/5/98 17:19'!
genericSignal
^GenericSignal! !
!Signal class methodsFor: 'as yet unclassified' stamp: 'df 3/5/98 19:36'!
initialize
"Initialize the Signals provided through this class' instance
variables.
Signal initialize"
| signal |
"Create the generic Signal."
signal := self basicNew
notifierString: 'An unknown Signal with: ';
nameClass: self message: #genericSignal.
signal parent: nil mayProceed: true.
GenericSignal isNil
ifTrue: [GenericSignal := signal]
ifFalse: [GenericSignal become: signal].
"Create the Signal to handle unhandled exceptions."
NoHandlerSignal := GenericSignal newSignal
notifierString: 'No handler was found for an Exception: ';
nameClass: self message: #noHandlerSignal.
"The next Signals will inherit from Object>>errorSignal."
signal := Object errorSignal.
"The PP version doesn't have this, but it's not clear to me where
Object>>errorSignal ever gets initialized!!!!"
signal isNil ifTrue: [
ErrorSignal := GenericSignal newSignal
notifierString: 'Error - ';
nameClass: Object message: #errorSignal.
signal := ErrorSignal].
"Create the Signal to handle a proceed in an Exception that can't
proceed."
ProceedErrorSignal := signal newSignal
notifierString: 'A handler tried to proceed from a
non-proceedable Exception: ';
nameClass: self message: #proceedErrorSignal.
"Create the Signal to handle mismatched proceedability."
WrongProceedabilitySignal := signal newSignal
notifierString: 'The raiser and the Signal do not agree
about proceedability: ';
nameClass: self message: #wrongProceedabilitySignal.
"Create the Signal to handle time-out errors."
TimeoutSignal := signal newSignal
notifierString: 'Timeout: ';
nameClass: self message: #timeoutSignal.! !
!Signal class methodsFor: 'as yet unclassified' stamp: 'df 3/5/98 19:36'!
new
"Return a new signal whose parent is Object>>errorSignal.
If you want a signal with some other parent, use
Signal class>>basicNew and Signal>>parent:."
^Object errorSignal newSignal! !
!Signal class methodsFor: 'as yet unclassified' stamp: 'df 3/5/98 19:37'!
noHandlerSignal
"This Signal catches unhandled exceptions."
^NoHandlerSignal! !
!Signal class methodsFor: 'as yet unclassified' stamp: 'df 3/5/98 19:37'!
proceedErrorSignal
"This signal catches the event that a handler tries to
proceed through a non-proceedable exception."
^ProceedErrorSignal! !
!Signal class methodsFor: 'as yet unclassified' stamp: 'df 3/5/98 19:37'!
timeoutSignal
"This Signal catches timeouts."
^TimeoutSignal! !
!Signal class methodsFor: 'as yet unclassified' stamp: 'df 3/5/98 19:38'!
wrongProceedabilitySignal
"This signal catches the event when a non-proceedable signal
is raised via one of the Signal>>raiseRequest* messages."
^WrongProceedabilitySignal! !
Exception initialize!
Signal initialize!
ExceptionCollection initialize!
--
--
j. david farber
oo architect+mentor
numenor labs incorporated
in sunny boulder colorado
dfarber at numenor.com
www.numenor.com
More information about the Squeak-dev
mailing list
|