Snail: A programming language with no semantics

Hello!

Lately, I have been interested in implementing programming languages from Types and Programming Languages (TAPL) and Essentials of Compilation (EOC). Neither of these books use Haskell to implement the language and give you parsers in OCaml or Racket. I have also seen a bunch of “Implement You A Scheme” tutorials with S-Expression parsers that don’t handle (1a) and (1 a) as different things. In fact, Haskell’s parser has this issue: https://twitter.com/chiroptical/status/1471568781906518018

So, welcome Snail to the world! Snail is a programming language with no semantics (for gastropods). Here is an example Snail program,

-- An example comment
(let [x 10] (print x))

It is essentially ASCII Fennel with Haskell’s line and block comments right now. Note: this program does nothing! However, you can use snail to get an AST which you can convert into the AST of your programming language! It isn’t really meant as anything serious but hopefully takes one step out of the process of implementing languages from books where the implementation language is not Haskell.

Some examples include https://github.com/chiroptical/snail-arith/blob/main/src/Lib.hs where I implemented arith from TAPL as an interpreter (using Except). I am also actively working on EOC here: GitHub - chiroptical/essentials-of-compilation: A gastropod approaches https://mitpress.mit.edu/9780262047760/essentials-of-compilation (using MonadError).

Links:

8 Likes

Is the name s-cargot inspired or just a coincidence?

I love the idea.

It is 100% inspired. It was suggested to me in Twitch chat when I was working on this live.
I might change the name now.

edit: I totally misread this and missed s-cargot: A flexible, extensible s-expression library.. I’ll need to add a comparison section in the future. At a quick glance, I could have written snail with s-cargot unless it has the same “issue” mentioned above.

1 Like

I’m lost. Why is that behaviour an “issue”? It’s what I expect for parsing/lexing Haskell. A token beginning with a digit is ipso facto a number; so ends where there’s a char that can’t be part of the number.

I agree it’s bad Haskell style: use plenty of whitespace for human readability. But it’s still Haskell; consistent with the lack of whitespace in 1+a.

Fair point. It is my opinion that it is an issue. Snail apparently prefers human readability. Luckily, it doesn’t have infix operators to worry about.

That seems – um – not helpful. Take this snippet from the hackage page:

(print (+ 1 2))

That’s not human-readable for this human – I’m expecting (+ ...) to herald here comes a partial application.

Why have operators (lexemes spelled +) at all if you can’t use them infix? IOW prefer

(print (plus 1 2))

Well OK you want to follow LISP rather than Haskell. Then the basis of your complaint seems to be that Haskell lexing is not LISP lexing. Are you allowing variadic operators (like LISP (+ 1 2 3 4))? Then how to represent Haskell partial application like (+ 1)? And how to distinguish (/ 2) (half) vs (2 /) (inverse doubled)?

Treating numbers as ending at the first non-digit [**] has been usual in programming languages since at least ALGOL – which tried to make whitespace completely optional.

[**] I mean at the first Char that couldn’t be part of the number. So decimal . or exponential e is ok.

I am honestly a bit confused by your comments here. Snail doesn’t define any semantics for programs.

(1 + 2), (+ 1 2), (+ 1 2 3 4), (1 + 2 3 4). Snail doesn’t care at all. You implement the semantics for your programs. That is the whole point.

I’ll reiterate that I prefer human readability and the fact that this is valid Haskell is funny to me

{-# LANGUAGE NoImplicitPrelude #-}
module Example where
import Prelude ((+))
(.) = (+)
a = 1.2.1.2
1 Like

This looks like a very useful project. I’ve been toying around with compilers in Haskell for years and the most annoying part is always syntax. Having a drop-in lisp parser is a great way to skip this step and focus on more interesting parts. Thanks for sharing!

Btw I really like the approach taken by Essentials of Compilation and it was the first time compilers education clicked for me. I wanted to mention two other courses that use the same approach: cs4410, cse131. I found both very useful when learning compilers.

4 Likes