"We were not out to win over the Lisp programmers; we were after the C++ programmers. We managed to drag a lot of them about halfway to Lisp."
--- Guy Steele, Java spec co-author
"Notice that no one mentions that this way they also managed to drag a lot of Lisp programmers about halfway back to C++."
--- Michał "phoe" Herda, angry Internet rando
This is an implementation of Common Lisp dynamic variables, control flow operators, and condition system in plain Java.
If Portable Conditon System is a proof that a Common Lisp condition system can be implemented on a Common Lisp implementation without a condition system of its own, then Cafe Latte is a proof that a Common Lisp-inspired condition system can be implemented even on top of a non-Lisp language that has only automatic memory management and a primitive unwinding operator (in this case, throw), but does not support dynamic variables or non-local returns by default.
It should be possible to use it, or parts of it, in other projects, and its source code should be readable enough to understand the underlying mechanics of each Lisp control flow operator.
This library is not yet documented, but the respective implementations should behave analogously to their Common Lisp counterparts; see the Common Lisp HyperSpec for their descriptions.
Example uses of the various constructs implemented here are present in the test directory, containing unit tests for all the present mechanisms.
A stable release of this library will be made when the authors are satisfied enough with its functioning.
AGPLv3. (Unless you are @easye, at which point it's whatever license suits you the best.)
- Dynamic variables
- Dynamic variable class
- Implemented in the
DynamicVariableclass. - Unit tests done.
- Implemented in the
- Dynamic variable class
- Control flow
-
tagbody/go- Implemented in the
Tagbodyclass. - Unit tests done.
- Implemented in the
-
block/return-from- Implemented in the
Blockclass. - Unit tests done.
- Implemented in the
-
throw/catch- Because of Java naming conflicts,
catch/throware renamed tograsp/fling. - Implemented in the
Graspclass. - Unit tests done.
throw/catchare not required for implementing a condition system, but their implementations are nonetheless included here for completeness.
- Because of Java naming conflicts,
-
- Conditions
- Condition class
- Implemented in the
Condtionclass. - Subtype of
RuntimeException. - Do not fill in the stack trace when instantiated; see the
superFillInStackTrace()method.
- Implemented in the
- Warning class
- Implemented in the
Warningclass. - Subtype of
Condition.
- Implemented in the
- Error class
- Implemented in the
Errorclass. - Subtype of
Condition.
- Implemented in the
- Condition class
- Handlers
- Handler class
- Implemented in the
Handlerclass. - Tested elsewhere.
- Implemented in the
-
signal- Implemented in the
Handlerclass as a static method. - Tested elsewhere.
- Implemented in the
-
warn- Implemented in the
Handlerclass as a static method. - Unit tests done.
- Implemented in the
-
error- Implemented in the
Handlerclass as a static method. - Unit tests done.
- Implemented in the
-
*break-on-signals*- Implemented in the
Handlerclass as a dynamic variable. - Unit tests done.
- Implemented in the
-
handler-bind- Implemented in the
HandlerBindclass. - Unit tests done.
- Implemented in the
-
handler-case- Implemented in the
HandlerCaseclass. - Unit tests done.
- Implemented in the
-
ignore-errors- Implemented in the
HandlerCaseclass as a static method. - Unit tests done.
- Implemented in the
- Handler class
- Restarts
- Restart class
- Implemented in the
Restartclass. - Unit tests done.
- Implemented in the
-
restart-bind- Implemented in the
RestartBindclass. - Unit tests done.
- Implemented in the
-
restart-case- Implemented in the
RestartCaseclass. - Unit tests done.
- Implemented in the
-
with-simple-restart- Implemented in the
RestartCaseclass as a static method. - Unit tests done.
- Implemented in the
- Restart class
- Debugger
- Debugger interface
- Defined in the
Debuggerclass.
- Defined in the
-
*debugger-hook*- Implemented in the
Debuggerclass as a dynamic variable. - Unit tests done.
- Implemented in the
-
break- Implemented in the
Debuggerclass as a static method. - Unit tests done.
- Because of Java naming conflicts,
breakis renamed tobreakIntoDebugger.
- Implemented in the
- No debugger
- Implemented in the
NoDebuggerclass. - Tested along with the
Errorclass by means of calling the staticerrormethod.
- Implemented in the
- Debugger interface
- Condition reports
- Should map nicely to the standard Java exception
toStringmechanism.
- Should map nicely to the standard Java exception
- Restart reports
- Should map nicely to the standard Java exception
toStringmechanism.
- Should map nicely to the standard Java exception
- Interactive debugger
- JShell as debugger REPL
-
unwind-protect- Java hastry/finallythat is fully equivalent.