Some comments in case the author is here:
1. You should make it clear in the README that this uses lazy evaluation, because most Lisps use strict evaluation.
2. `lambda` should have an implicit `begin` around its body to allow multiple forms, e.g.
(lambda ()
(define x 1)
(+ x x))
(as of commit 4e0eec383363, calling this lambda fails with "list too long").
3. The behaviour of the top-level forms changes when they are wrapped in `begin`. For example, the program
(car 1)
2
succeeds (due to lazy evaluation), but wrapping it in `(begin ...)` causes it to fail with "expecting a cons". If the intent is to use lazy evaluation, then both versions should succeed.
4. Since this dialect is pure (no side effects), it should be a syntax error if a non-final form in a `begin` expression expands to some expression which is not a declaration. For example,
(defun f (x)
(g x)
(h x))
should be a syntax error, because the call to `g` is useless (unless it's a macro that expands to `define`).
In the same vein, you could make it a syntax error if the final form in a `begin` expression is `define` (and likewise for the forms in an `if`).
5. The way `if` handles values other than true/false is backwards compared to most Lisps (and based on the comments in the code I think it's an accident). For example
(if "foo" "first" "second")
evaluates to "second", but in most Lisps it would evaluate to "first" (because strings are considered "truthy").