A minimalist Lisp interpreter is available in MOROS to extend the capabilities of the Shell.
MOROS Lisp is a Lisp-1 dialect inspired by Scheme, Clojure, and Ruby!
bool
, list
, symbol
, string
float
, int
, bigint
2.5
, -25
, 255
, 0xFF
, 0xDEAD_C0DE
, 0b101010
"Hello, World!"
\b
, \e
, \n
, \r
, \t
, \"
, \\
quote
(abbreviated with '
)quasiquote
(abbreviated with `
)unquote
(abbreviated with ,
)unquote-splice
(abbreviated with ,@
)splice
(abbreviated with @
)atom?
equal?
(aliased to eq?
)head
tail
cons
if
cond
while
variable
(aliased to var
)function
(aliased to fun
)macro
(aliased to mac
)set
define
(aliased to def
and equivalent to define-function
)define-function
(aliased to def-fun
)define-macro
(aliased to def-mac
)apply
do
doc
eval
expand
load
type
, number/type
(aliased to num/type
), parse
string
(aliased to str
)string->number
and number->string
(aliased to str->num
and num->str
)string->binary
and binary->string
(aliased to str->bin
and bin->str
)number->binary
and binary->number
(aliased to num->bin
and bin->num
)regex/find
shell
(aliased to sh
)+
, -
, *
, /
, ^
, rem
(aliased to %
), trunc
acos
, asin
, atan
, cos
, sin
, tan
>
, <
, >=
, <=
, =
length
(aliased to len
), put
, get
, slice
, contains?
string/trim
and string/split
(aliased to str/trim
and str/split
)list
, concat
, chunks
, sort
, unique
(aliased to uniq
)dict
file/exists?
, file/size
, file/open
, file/close
, file/read
, file/write
host
, socket/connect
, socket/listen
, socket/accept
nil
, nil?
, list?
, empty?
boolean?
(aliased to bool?
), string?
(aliased to str?
), symbol?
(aliased to sym?
), number?
(aliased to num?
)function?
(aliased to fun?
), macro?
(aliased to mac?
)abs
, mod
, min
, max
first
, second
, third
, last
, rest
, push
map
, reduce
, reverse
(aliased to rev
), range
, filter
, reject
, intersection
not
, and
, or
let
string/join
(aliased to str/join
), lines
, words
, chars
regex/match?
read
, write
, append
read-binary
, write-binary
, append-binary
read-line
, read-char
uptime
, realtime
p
, print
floor
, ceil
, round
atom
, eq
, label
, lambda
, progn
, begin
car
, cdr
, caar
, cadr
, cdar
, cddr
The interpreter can be invoked from the shell:
> lisp
MOROS Lisp v0.7.0
> (+ 1 2 3)
6
> (quit)
And it can execute a file. For example a file located in /tmp/lisp/fibonacci.lsp
with the following content:
(load "/lib/lisp/core.lsp")
(def (fibonacci n)
(if (< n 2) n
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
(print
(if (nil? args) "Usage: fibonacci <num>"
(fibonacci (str->num (head args)))))
Would produce the following output:
> lisp /tmp/lisp/fibonacci.lsp 20
6755
(load "/lib/lisp/core.lsp")
(print "Hello, World!")
(var foo 42) # Variable definition
(set foo (+ 40 2)) # Variable assignement
(var double (fun (x) (* x 2))) # Function definition
(def (double x) (* x 2)) # Shortcut
(double foo) # => 84
(def-mac (++ x) # Macro definition
`(set ,x (+ ,x 1)))
(var i 0)
(while (< i 10)
(++ i))
(= i 10) # => true
(def (map f ls)
"Apply function to list"
(if (nil? ls) nil
(cons
(f (first ls))
(map f (rest ls)))))
(doc map) # => "Apply function to list"
(var bar (quote (1 2 3)))
(var bar '(1 2 3)) # Shortcut
(map double bar) # => (2 4 6)
(map (fun (x) (+ x 1)) '(4 5 6)) # => (5 6 7)
(var name "Alice")
(str "Hello, " name) # => "Hello, Alice"
(^ 2 64) # => 18446744073709551616
floor
, ceil
, and round
functionsfalse
nor nil
) in conditions of if
and while
nth
to get
empty?
, reject
, put
, push
, and host
functions`dict
type/
instead of .
as namespace separatornumber->string
(aliased to num->str
) with an optional radix argumentThe whole implementation was refactored and the parser was rewritten to use Nom. This allowed the addition of strings to the language and reading from the filesystem.
MOROS Lisp started from Risp and was extended to include the seven primitive operators and the two special forms of John McCarthy's paper "Recursive Functions of Symbolic Expressions and Their Computation by Machine" (1960) and "The Roots of Lisp" (2002) by Paul Graham.