minihasklisp
is a tiny lisp interpreter with minimal dependencies.
minihasklisp: [-i] [-h] [-e] [file]
-i
: starts a REPL-e
: print the current symbol table after each statementfile
: parse and interpret the file then print the result of the final statement-h
: print the help message
minihasklisp
needs to be called with at least one of the two options:
-i
or file
.
The language is a lisp variant which supports the following types:
- atoms:
- 64 bits signed integers
- booleans:
#t
or#f
- strings
- S-expressions
Create a new pair of two values. Usually used to create linked lists.
> (cons 1 2)
(1 . 2)
> (cons 1 (cons 2 '()))
(1 2)
> (cons 1 (cons 2 (cons 3 '())))
(1 2 3)
As a convention, '()
is the last element of a linked list. See also, the
quote
function.
Return its argument as data, without trying to evaluate it. A leading '
is
syntaxic sugar for (quote ...)
.
> (quote (1 2 3))
(1 2 3)
> 'a-string
a-string
> (+ 1 2)
3
> '(+ 1 2)
(+ 1 2)
Return the first element of a pair.
> (car (cons 1 2))
1
> (car '(1 2 3))
1
Return the second element of a pair.
> (cdr (cons 1 2))
2
> (cdr '(1 2 3))
(2 3)
Test for equality. It works only for atoms, comparing a list to anything always
returns #f
.
> (eq? 1 1)
#t
> (eq? 2 (+ 1 1))
#t
> (eq? 1 2)
#f
> (eq? 'yes 'yes)
#t
> (eq? '(1 2) '(1 2))
#f
Test if the parameter is an atom.
> (atom? #t)
#t
> (atom? 'an-atom)
#t
> (atom? '())
#t
> (atom? (+ 1 2))
#t
> (atom? '(1 2))
#f
cond
takes any number of arguments. Each argument is a list of two
expressions, if the first expression evaluates to true, it evaluates the second
expression and returns the result. If not it moves to the next argument.
> (cond ((eq? 2 (+ 1 1)) 'if-branch) (#t 'else-branch))
if-branch
> (cond (#f 'first-condition) ((eq? 0 1) 'second-condition) (#t 'catch-all-condition))
catch-all-condition
The following arithmetic functions are supported: +
, -
, *
, div
, mod
and <
.
> (+ 1 (- 2 (* 3 4)))
-9
> (div 9 2)
4
> (mod 9 2)
1
> (< 0 1)
#t
Lambda functions can be defined with the following syntax:
> (lambda (x y) (+ x y))
(lambda (x y) (+ x y))
> ((lambda (x y) (+ x y)) 1 2)
3
define
lets you affect any value to a symbol. It can be be used to define
functions as well.
> (define a 1)
1
> a
1
> (define add (lambda (x y) (+ x y)))
(lambda (x y) (+ x y))
> (add 1 2)
3
> (define (sub x y) (- x y))
(lambda (x y) (- x y))
> (sub 1 2)
-1
let
takes a list of symbols and values as it first argument and an expression
as its second argument. It evaluates the expression looking up symbols in its
first argument if needed.
> (let ((one 1) (twice (lambda (x) (* x 2)))) (twice one))
2
Some code examples can be found in the test suite or in the following files:
examples.scm
: some basic functions and a few higher order functions such asmap
,filter
,fold-left
andfold-right
fact.scm
: compute the factorial of a numberfib.scm
: get the nth fibonacci numberqsort3.scm
: quicksort implementationsort.scm
: another sorting algorithm
The project can be build with nix.
Install with:
$ nix profile install
Build with:
$ nix build
Both binaries are then created in ./result/bin
Hack with:
$ nix develop
You will be dropped in a shell with all the needed tools in scope: cabal
to
build the project and haskell-language-server
for a better developer
experience.