Neat! Nicely done.
fwiw, I wrote a Lisp in Python whose sexprs ended up looking similar: https://github.com/shawwn/pymen
That’s the runtime for it, which is self hosted, so it supports that dot syntax but doesn’t actually use it in its own code. (If you add a new feature like dot syntax to a self hosted lisp, then you start using the feature, and later decide it was a bad idea, it becomes incredibly difficult to revert — So the compiler sticks to a minimal subset.
But it can run code almost exactly as you’ve written, minus the backslashes. It also has:
(for x in (list 1 2 3 4)
(print x))
(for k, v in ((globals) (.items))
(print k v))
That was a fun one to get working… k, v is read as (, k v) which then compiles to k, v in the output code. Also shows method call syntax there; (globals) compiles to globals(), and (.items) compiles to .items(), so it becomes globals().items(). You can’t use dot syntax in a normal way when the functional position isn’t a symbol — it’s the result of a function call. Curious whether you solved that; I don’t really like my solution, but it’s the best I could think of.
List comprehensions
(list i for i in (range 10) if (% i 2))
Compiles to
[i for i in range(10) if i % 2]
Async functions
(async def foo (x)
(async for k in x
(yield k)))
Uhh.. what else..
with statements:
(with (open “foo.txt”) as f
(f.read))
Exceptions, though I forget the exact implementation. It’s something like
(try (f)
(except ValueError as e (print e))
(finally (print 1)))
classes
(class (MyDict dict)
(def find (self k)
(get self k)))
(get self k) compiles to self[k]
And countless other small details. Notice there’s no return statements anywhere; you can write those manually if you want to, but by default they get automatically inserted due to the lowering pass.
Etc etc. I’m depressed and writing this on an iPad, so I’ll try to go sleep. But I hope your project helps make python more accessible from lisp — it’s a near and dear problem to me, so I love seeing people solving it!