Thursday, December 19, 2019

DreamLisp - A Lisp dialect in Objective-C

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.

The language takes inspiration from MAL which itself is heavily influenced by Clojure, LFE and Erlang. DreamLisp has unhygienic macros, is single-threaded for the most part has a bunch of 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 directly. 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's Lisp, it's not Common Lisp or any other Lisp. It's a dialect of its own. Next is the Objective-C interop, which is partial. These built-in functions 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, also the Lisp case to camel, Pascal casing and vice-versa. Once we have these, then we can use the same code to run through a transpiler written in DLisp, generate Objective-C or Swift code, then use xcodebuild to generate native code with no eval and the code will be just like handwritten code.

Currently, the language is fully interpreted and as such works for simple use cases, but with full-fledged app development, having a language that runs natively either using LLVM or at least JIT would provide a better development experience. In that regards, I find malc interesting, which is MAL to LLVM or targetting MMIX bytecode. MMIX is a RISC architecture by Donald Knuth and is really cool.

Sunday, December 15, 2019

dnet - An LFE OTP REST API Server

I have created a seed project which uses LFE OTP with Cowboy for as the webserver and Mnesia as the database. There is also a gen_server which does HTTP request using Cowboy Gun library and handles the response as a stream asynchronously. This allows finer control over the HTTP response and allows to pause, cancel the stream, as well as continue from partially left of streams. The project demonstrates the use of LFE with OTP for writing web services with rebar3 for build and dependency management. Also, there are scripts for loading project env into LFE REPL, giving a full modern development workflow experience.

The supervision tree for the app is given below.
               ┌──────┐
┌───▶│db-sup│
│ └──────┘

┌────┐ │ ┌────────────┐
│dnet│────┼───▶│dnet-svc-sup│
└────┘ │ └────────────┘

│ ┌────────┐
└───▶│http-sup│
└────────┘
The server listens on port 8080 and has two handlers, one for GET and another for POST. The GET handler returns JSON and the POST handler returns HTML generated using Exemplar.

LFE comes with an emacs mode. So I have Spacemacs configuration setup with LFE mode with Lisp and general editor enhancements like rainbow-delimiters, OS X keybindings and such. The LFE mode files are currently configured to load from ~/env/emacs/lfe directory.

Saturday, December 14, 2019

NSJSONSerialization of BOOL values

To serialize BOOL values using NSJSONSerialization, we can use the NSNumber form. i.e, @YES and @NO which represents the BOOL YES and NO respectively.