20.2.4 Continuation from errors
The restart mechanism just described is exceedingly general, and may provide several different ways to recover from exceptional situations. Sometimes, however, there is just one main way to recover. Under certain circumstances, Dylan provides a way for handlers simply to return to their callers, allowing execution to continue after the signaler. Here, we present a simpler (but less flexible) implementation for recovering from the time-of-day overflow exception:
define method return-24-hour-modulus
(condition :: <time-error>, next-handler :: <function>)
=> (corrected-time :: <time>)
make(type-for-copy(condition.invalid-time),
total-seconds: modulo(condition.invalid-time.total-seconds,
$seconds-per-day));
end method return-24-hour-modulus;
define method return-allowed? (condition :: <time-error>) #t; end method return-allowed?;
define method return-description (condition :: <time-error>) "Returns the invalid time modulo 24 hours."; end;
define method say-corrected-time
(arrival-time :: <time-of-day>,
#key weather-delay :: <time-offset> = $no-time,
traffic-delay :: <time-offset> = $no-time)
=> ()
let handler (<time-error>) = return-24-hour-modulus;
say(correct-arrival-time(arrival-time, weather-delay, traffic-delay));
end method say-corrected-time;
define method \+ (offset :: <time-offset>, time-of-day :: <time-of-day>)
=> (sum :: <time-of-day>)
let sum
= make(<time-of-day>,
total-seconds: offset.total-seconds + time-of-day.total-seconds);
block ()
if (sum >= $midnight & sum < $tomorrow)
sum;
else
// If a handler returns, it must return a valid <time-offset>
signal(make(<time-boundary-error>, invalid-time: sum,
min-time: $midnight, time-limit: $tomorrow));
end if;
end block;
end method \+;
The return-allowed? and return-description generic functions are provided by Dylan. When the generic function return-allowed? returns true for a given condition, introspective handlers know that they can return successfully back to the signaler. When returning is allowed, such introspective handlers may call the return-description generic function to find out what values to return, if there are any. This description can be especially useful for interactive handlers, such as debuggers.
The return-24-hour-modulus method has been generalized compared to the exception-specific restart defined in Section 20.2.3. This method may return either an instance of <time-of-day> or <time-offset>, depending on the class of time that overflowed. Thus, it could be reused for exception handling in other parts of the application.
In this implementation approach, there is an implicit contract between the signaler in the \+ method and any handler that matches and accepts <time-boundary-errors>. The contract is that the handler will always return a valid <time> value, or will never return at all. If any handler violates this implicit contract, then the reliability of the program will be placed at risk. It is important to document these error-handling contracts.
Note that, in the \+ method, we must use the signal function to signal the exception, because it is illegal for a handler to return from exceptions signaled with the error function.




