| 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"). |
This actually teaches me that one thing I should make it clear is this was essentially a weekend experiment from someone who has never used, let alone written a Lisp before.
There's no way it's a production grade software, there are places where the evaluator just borks for valid expressions.
I learned a lot when writing it, so I can probably do a large-ish refactor that would simplify many things and fix the inconsistencies.
> this uses lazy evaluation, because most Lisps use strict evaluation.
The evaluation semantics are pretty weird. It's lazy-ish mostly, but when evaluating there are a lot of places where I unnecessarily force evaluation of things. So I should make the semantics clearer and document them.
> The behaviour of the top-level forms changes when they are wrapped in `begin`
This is a bug, you are right .
> Since this dialect is pure (no side effects)
It's mostly pure. There are a couple of constructs like `assert` and `log` that perform side effects. And also as you mentioned the expressions in a begin can be macros that end up modifying the environment.
> The way `if` handles values other than true/false is backwards compared to most Lisps
You are likely correct and this is a bug!
---
Thanks again of your comments, I'll try to find some time to either rewrite the project, or at least document it better.