A lisp-like language that runs on node, written in Purescript (which is written in Haskell).
First make sure you have purescript (>= 0.8.5) and pulp (>= 8.1.0) installed, as well as node, npm and bower.
Run bower install
then pulp run --interactive
to get a REPL.
Alternatively, you can interpret a file with pulp run $(cat <filename>)
.
pulp build --optimise --to ssc.js
sed -i '1s/^/#!\/usr\/bin\/env node\n/' ssc.js
chmod +x ssc.js
Everything is an S-expression. Quoted lists are supported.
Values are immutable.
Defining variables is done with def
: (def x 3)
Defining functions is similar:
(def (f x y) (+ x y)
(def (compose f g)
(lambda (x) (f (g x))))
Primitive types come in the following flavors:
- Atoms => 'atom
- Strings => "hello world"
- Bools => True, False
- Ints => 2, -2
There's one type of collection, a linked list. List literals can be made as follows: '(1 True "string")
.
+
add 2 or more numbers-
subtract 2 or more numbers*
multiply 2 or more numbers/
divide 2 or more numbers%
mod 2 or more numbers=
check equality between numbers<
check if the first number is less than the second>
check if the first number is greater than the second<=
check if the first number is greater than the second>=
check if the first number is less than the second/=
check equality between numbers&&
truth-functional and||
truth-functional orstring=?
check equality between stringsstring>?
check if the first string is greater than the secondstring<?
check if the first string is less than the secondstring>=?
check if the first string is less than the secondstring<=?
check if the first string is greater than the secondhead
get the first element in a nonempty listtail
get the tail of a listcons
add an element to the front of the given listeqv
check equality of two terms of the same type==
same aseqv
While based on Write Yourself A Scheme, there are quite a few differences:
- Instead of using Refs to store the environment, the environment is stored in a StateT transformer monad.
- Instead of using an association list as the environment, StrMaps are used
- No support for dotted lists
- "IO primitives" are handled by the REPL as directives instead of given as language primitives.
In particular, the base monad for the transformer stack is left polymorphic: The REPL uses Aff to deal with user input, and the source-code file interpreter uses Eff. In principle this means one could use, for example, the Trampoline monad at the base to handle stack overflows in the language (which were a serious problem in a previous version), though I haven't tested this yet.