Skip to content

jecaro/minihasklisp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

57 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

minihasklisp

CI

minihasklisp

minihasklisp is a tiny lisp interpreter with minimal dependencies.

Options

minihasklisp: [-i] [-h] [-e] [file]

  • -i: starts a REPL
  • -e: print the current symbol table after each statement
  • file: 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.

Language

The language is a lisp variant which supports the following types:

  • atoms:
    • 64 bits signed integers
    • booleans: #t or #f
    • strings
  • S-expressions

Builtins

Functions on pairs

cons

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.

quote

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)

car

Return the first element of a pair.

> (car (cons 1 2))
1
> (car '(1 2 3))
1

cdr

Return the second element of a pair.

> (cdr (cons 1 2))
2
> (cdr '(1 2 3))
(2 3)

Predicates and branching

eq?

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

atom?

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

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

Arithmetic functions

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

Functions definition

lambda

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

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

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

Examples

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 as map, filter, fold-left and fold-right
  • fact.scm: compute the factorial of a number
  • fib.scm: get the nth fibonacci number
  • qsort3.scm: quicksort implementation
  • sort.scm: another sorting algorithm

Hacking

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.

About

A small yet fully functional lisp interpreter

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published