📓 dial-interpreter-third-implementation.md by @ryan ☆

Dial interpreter third implementation

tags : [[Dial implementation]] [[language design]]

I have now attempted to implement Dial twice, both as spins on the Make A Lisp project. For my third and hopefully final attempt, I’m going to try a different approach, using lessons taken from [[Lisp in Small Pieces]].

Dial will once again be written in [[Rust]].

Plan

Syntax

Dial’s syntax will mostly be [[Clojure]]-like S-expressions, with some exceptions. It will use Clojure’s def and fn keywords. List and vector syntax will be interchangeable, as in [[Racket]].

(let (a 1
      b 2
      c 3)
  (+ a b c))

Bindings may optionally be bracketed.

(let ((a 1)
      [b 2]
      c 3)
  (+ a b c))

Scoping rules

All named values are immutable. let bindings, function parameters, etc. cannot be mutated.

Types

Dial’s types will mostly be Clojure-like as well. We will not define cons cells, since linked lists in Rust are superfluous.

Primitives

Deferable

These types may come after v1, since they could be articulated with lists.

Parser (read)

I have largely already figured out how the parser should work thanks to nom. The only forms I don’t support at the moment are quoted expressions and a handful of special syntax types like hash maps.

A valid program that’s outputted by read will return a quoted expression.

eval

The interpreter should be thought of as a function that, given a program, an environment, and a [[continuation]], should result in a value.

Should I implement continuations?

Pros

Cons