"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.
It started out as a proof that a condition system can be implemented even on top of a language that has only automatic memory management and a primitive unwinding operator (throw
), but does not have 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
makeReadyToThrow()
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
-
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
- Throwing debugger
- Implemented in the
ThrowingDebugger
class. - Tested along with
Error
class.
- Implemented in the
- Debugger interface
-
*debugger-hook*
-
break
-
*break-on-signals*
- Interactive debugger
- JShell as debugger REPL
-
unwind-protect
- Java hasfinally
that is fully equivalent.