DreamLisp is a Lisp dialect with modules, lazy collections and is a Lisp-2 with an unhygienic macro system. DreamLisp interpreter is implemented in Objective-C and as such can run on macOS and iOS. It is tail recursive, uses ARC instead of garbage collection, has asynchronous communication using notifications taking advantage of the underlying Objective-C runtime and Foundation library. In the experimental version objc-rt-1 branch, we can define classes and create objects at runtime from the REPL. At present, the language runs in interpreted mode.
DreamLisp is single-threaded for the most part, have a few built-in modules core
, network
, test
. core
module contains the native functions implemented in Objective-C and exposed to DreamLisp. The network
module has functions to make simple REST based HTTP requests. The test
module contains macros and functions to write unit tests which resembles Clojure tests.
The main goal of the project was to have a working Lisp that can use all the Objective-C runtime capabilities and thereby develop software that runs on Apple devices using Lisp. In that front, we need a Lisp language, REPL and there is nothing better than having the language itself be written in Objective-C. This helps to use Objective-C internal functions without having to resort to FFIs. The language part is ready, i.e, the specification and the implementation. Even though it is Lisp, it is not Common Lisp and is a dialect of its own. Next is the Objective-C interop, which is partial. These built-in functions for Object-Oriented Programming follow ideas from CLOS. Currently, we can dynamically create classes, add methods, create objects of the classes, invoke methods for a certain set use cases. We can also create objects of the built-in classes and invoke methods on it. It's not robust yet and interop between native Objective-C types and DLisp types are not fully functional.
The dialect is based on Lisp Flavoured Erlang (LFE) and Clojure. I used MAL as a starting point for the implementation. Currently, the language is fully interpreted and as such works for simple use cases, embedding in an existing app for scripting etc. For full-fledged app development, having the language to compile to native code is required.