"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
DynamicVariable
class. - Unit tests done.
- Implemented in the
- Dynamic variable class
- Control flow
-
tagbody
/go
- Implemented in the
Tagbody
class. - Unit tests done.
- Implemented in the
-
block
/return-from
- Implemented in the
Block
class. - Unit tests done.
- Implemented in the
-
throw
/catch
- Because of Java naming conflicts,
catch
/throw
are renamed tograsp
/fling
. - Implemented in the
Grasp
class. - Unit tests done.
throw
/catch
are 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
Condtion
class. - Subtype of
RuntimeException
. - Do not fill in the stack trace when instantiated; see the
superFillInStackTrace()
method.
- Implemented in the
- Warning class
- Implemented in the
Warning
class. - Subtype of
Condition
.
- Implemented in the
- Error class
- Implemented in the
Error
class. - Subtype of
Condition
.
- Implemented in the
- Condition class
- Handlers
- Handler class
- Implemented in the
Handler
class. - Tested elsewhere.
- Implemented in the
-
signal
- Implemented in the
Handler
class as a static method. - Tested elsewhere.
- Implemented in the
-
warn
- Implemented in the
Handler
class as a static method. - Unit tests done.
- Implemented in the
-
error
- Implemented in the
Handler
class as a static method. - Unit tests done.
- Implemented in the
-
*break-on-signals*
- Implemented in the
Handler
class as a dynamic variable. - Unit tests done.
- Implemented in the
-
handler-bind
- Implemented in the
HandlerBind
class. - Unit tests done.
- Implemented in the
-
handler-case
- Implemented in the
HandlerCase
class. - Unit tests done.
- Implemented in the
-
ignore-errors
- Implemented in the
HandlerCase
class as a static method. - Unit tests done.
- Implemented in the
- Handler class
- Restarts
- Restart class
- Implemented in the
Restart
class. - Unit tests done.
- Implemented in the
-
restart-bind
- Implemented in the
RestartBind
class. - Unit tests done.
- Implemented in the
-
restart-case
- Implemented in the
RestartCase
class. - Unit tests done.
- Implemented in the
-
with-simple-restart
- Implemented in the
RestartCase
class as a static method. - Unit tests done.
- Implemented in the
- Restart class
- Debugger
- Debugger interface
- Defined in the
Debugger
class.
- Defined in the
-
*debugger-hook*
- Implemented in the
Debugger
class as a dynamic variable. - Unit tests done.
- Implemented in the
-
break
- Implemented in the
Debugger
class as a static method. - Unit tests done.
- Because of Java naming conflicts,
break
is renamed tobreakIntoDebugger
.
- Implemented in the
- No debugger
- Implemented in the
NoDebugger
class. - Tested along with the
Error
class by means of calling the staticerror
method.
- Implemented in the
- Debugger interface
- Condition reports
- Should map nicely to the standard Java exception
toString
mechanism.
- Should map nicely to the standard Java exception
- Restart reports
- Should map nicely to the standard Java exception
toString
mechanism.
- Should map nicely to the standard Java exception
- Interactive debugger
- JShell as debugger REPL
-
unwind-protect
- Java hastry
/finally
that is fully equivalent.