2021-07-21 07:40:40 +00:00
|
|
|
# MOROS Lisp
|
|
|
|
|
|
|
|
A minimalist Lisp interpreter is available in MOROS to extend the capabilities
|
|
|
|
of the Shell.
|
|
|
|
|
2022-06-06 14:02:34 +00:00
|
|
|
MOROS Lisp is a Lisp-1 dialect inspired by Scheme and Clojure.
|
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
## Changelog
|
|
|
|
|
|
|
|
### 0.1.0 (2021-07-21)
|
|
|
|
MOROS Lisp started from [Risp](https://github.com/stopachka/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
|
2021-07-21 07:40:40 +00:00
|
|
|
Computation by Machine" (1960) and "The Roots of Lisp" (2002) by Paul Graham.
|
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
### 0.2.0 (2021-12-04)
|
|
|
|
The whole implementation was refactored and the parser was rewritten to use
|
|
|
|
[Nom](https://github.com/Geal/nom). This allowed the addition of strings to the
|
|
|
|
language and reading from the filesystem.
|
|
|
|
|
|
|
|
### 0.3.0 (2022-12-12)
|
|
|
|
Rewrite the evaluation code, add new functions and a core library.
|
|
|
|
|
|
|
|
### 0.3.1 (2022-06-06)
|
|
|
|
Rewrite parts of the code and add new functions and examples.
|
|
|
|
|
|
|
|
### 0.3.2 (2022-07-02)
|
|
|
|
- Add new functions
|
2021-12-12 10:43:57 +00:00
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
### 0.3.2 (2022-08-25)
|
|
|
|
- Add new functions
|
2022-10-17 18:58:08 +00:00
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
### 0.4.0 (2022-08-25)
|
|
|
|
- Rewrite a lot of the code
|
|
|
|
- Add integer and big integer support
|
|
|
|
- Add tail call optimization (TCO)
|
|
|
|
- Add macro support
|
|
|
|
|
|
|
|
## Overview
|
|
|
|
|
|
|
|
### Types
|
2022-10-17 18:58:08 +00:00
|
|
|
- Basics: `bool`, `list`, `symbol`, `string`
|
|
|
|
- Numbers: `float`, `int`, `bigint`
|
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
### Built-in Operators
|
2021-07-21 07:40:40 +00:00
|
|
|
- `quote` (with the `'` syntax)
|
2022-11-01 10:02:50 +00:00
|
|
|
- `quasiquote` (with the `` ` ``)
|
|
|
|
- `unquote` (with the `,` syntax)
|
|
|
|
- `unquote-splicing` (with the `,@` syntax)
|
2021-07-21 07:40:40 +00:00
|
|
|
- `atom` (aliased to `atom?`)
|
|
|
|
- `eq` (aliased to `eq?`)
|
|
|
|
- `car` (aliased to `first`)
|
|
|
|
- `cdr` (aliased to `rest`)
|
|
|
|
- `cons`
|
2022-11-01 10:02:50 +00:00
|
|
|
- `if`
|
2021-07-21 07:40:40 +00:00
|
|
|
- `cond`
|
2022-10-21 08:10:14 +00:00
|
|
|
- `while`
|
2022-11-01 10:02:50 +00:00
|
|
|
- `set`
|
|
|
|
- `define` (aliased to `def` and `label`)
|
|
|
|
- `function` (aliased to `fun` and `lambda`)
|
|
|
|
- `macro` (aliased to `mac`)
|
|
|
|
- `define-function` (aliased to `def-fun`)
|
|
|
|
- `define-macro` (aliased to `def-mac`)
|
2022-09-15 18:50:23 +00:00
|
|
|
- `apply`
|
2022-11-01 10:02:50 +00:00
|
|
|
- `eval`
|
|
|
|
- `expand`
|
|
|
|
- `do` (aliased to `begin` and `progn`)
|
|
|
|
- `load`
|
|
|
|
|
|
|
|
### Primitive Operators
|
|
|
|
- `append`
|
2022-07-02 13:24:30 +00:00
|
|
|
- `type`
|
2022-08-25 06:48:19 +00:00
|
|
|
- `string`
|
2022-09-20 17:57:55 +00:00
|
|
|
- `string->number`
|
|
|
|
- `string->bytes` and `bytes->string`
|
|
|
|
- `number->bytes` and `bytes->number`
|
2022-08-25 06:48:19 +00:00
|
|
|
- `regex-find`
|
2022-07-02 13:24:30 +00:00
|
|
|
- `system`
|
|
|
|
|
|
|
|
- Arithmetic operations: `+`, `-`, `*`, `/`, `%`, `^`
|
|
|
|
- Trigonometric functions: `acos`, `asin`, `atan`, `cos`, `sin`, `tan`
|
|
|
|
- Comparisons: `>`, `<`, `>=`, `<=`, `=`
|
2022-09-15 18:50:23 +00:00
|
|
|
- String operations: `lines`
|
2022-08-25 06:48:19 +00:00
|
|
|
- File IO: `read-file`, `read-file-bytes`, `write-file-bytes`, `append-file-bytes`
|
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
### Core Library
|
2022-09-20 17:57:55 +00:00
|
|
|
- `nil`, `nil?`, `eq?`
|
2022-11-01 10:02:50 +00:00
|
|
|
- `atom?`, `string?`, `boolean?`, `symbol?`, `number?`, `list?`, `function?`, `macro?`
|
|
|
|
- `caar`, `cadr`, `cdar`, `cddr`, `first`, `second`, `third`, `rest`
|
|
|
|
- `map`, `reduce`, `reverse`, `range`
|
|
|
|
- `let`
|
2022-09-15 18:50:23 +00:00
|
|
|
- `string-join`
|
2022-08-25 06:48:19 +00:00
|
|
|
- `read-line`, `read-char`
|
|
|
|
- `print`, `println`
|
|
|
|
- `write-file`, `append-file`
|
|
|
|
- `uptime`, `realtime`
|
|
|
|
- `regex-match?`
|
2021-07-21 07:40:40 +00:00
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
- Boolean operations: `not`, `and`, `or`
|
|
|
|
|
2021-07-21 07:40:40 +00:00
|
|
|
## Usage
|
|
|
|
|
|
|
|
The interpreter can be invoked from the shell:
|
|
|
|
|
|
|
|
```
|
|
|
|
> lisp
|
2022-09-20 17:57:55 +00:00
|
|
|
MOROS Lisp v0.4.0
|
2021-07-21 07:40:40 +00:00
|
|
|
|
2022-09-20 17:57:55 +00:00
|
|
|
> (+ 1 2 3)
|
|
|
|
6
|
2021-07-21 07:40:40 +00:00
|
|
|
|
2022-06-26 08:00:54 +00:00
|
|
|
> (quit)
|
2021-07-21 07:40:40 +00:00
|
|
|
```
|
|
|
|
|
2022-08-25 06:48:19 +00:00
|
|
|
And it can execute a file. For example a file located in `/tmp/lisp/fibonacci.lsp`
|
2021-12-12 10:43:57 +00:00
|
|
|
with the following content:
|
2021-07-21 07:40:40 +00:00
|
|
|
|
|
|
|
```lisp
|
2022-08-27 11:07:32 +00:00
|
|
|
(load "/lib/lisp/core.lsp")
|
2022-08-25 06:48:19 +00:00
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
(define (fibonacci n)
|
2022-10-21 08:10:14 +00:00
|
|
|
(if (< n 2) n
|
|
|
|
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
|
2021-07-21 07:40:40 +00:00
|
|
|
|
2022-08-25 06:48:19 +00:00
|
|
|
(println
|
2022-10-21 08:10:14 +00:00
|
|
|
(if (nil? args) "Usage: fibonacci <num>"
|
|
|
|
(fibonacci (string->number (car args)))))
|
2021-07-21 07:40:40 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
Would produce the following output:
|
|
|
|
|
|
|
|
```
|
2022-08-25 06:48:19 +00:00
|
|
|
> lisp /tmp/lisp/fibonacci.lsp 20
|
|
|
|
6755
|
2021-07-21 07:40:40 +00:00
|
|
|
```
|
2022-10-21 08:10:14 +00:00
|
|
|
|
|
|
|
## Examples
|
|
|
|
|
|
|
|
```lisp
|
|
|
|
(load "/lib/lisp/core.lsp")
|
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
(define foo 42) # Variable definition
|
2022-10-21 08:10:14 +00:00
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
(define double (fun (x) (* x 2))) # Function definition
|
|
|
|
(define (double x) (* x 2)) # Shortcut
|
2022-10-21 08:10:14 +00:00
|
|
|
|
|
|
|
(double foo) # => 84
|
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
(define (map f ls)
|
2022-10-21 08:10:14 +00:00
|
|
|
(if (nil? ls) nil
|
|
|
|
(cons
|
|
|
|
(f (first ls))
|
|
|
|
(map f (rest ls)))))
|
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
(define bar (quote (1 2 3)))
|
|
|
|
(define bar '(1 2 3)) # Shortcut
|
2022-10-21 08:10:14 +00:00
|
|
|
|
|
|
|
(map double bar) # => (2 4 6)
|
|
|
|
|
|
|
|
(map (fun (x) (+ x 1)) '(4 5 6)) # => (5 6 7)
|
|
|
|
|
|
|
|
(set foo 0) # Variable assignment
|
|
|
|
|
|
|
|
(= foo 10) # => false
|
|
|
|
|
|
|
|
(while (< foo 10)
|
|
|
|
(set foo (+ foo 1)))
|
|
|
|
|
|
|
|
(= foo 10) # => true
|
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
(define name "Alice")
|
2022-10-21 08:10:14 +00:00
|
|
|
|
|
|
|
(string "Hello, " name) # => "Hello, Alice"
|
|
|
|
|
|
|
|
(^ 2 128) # => 340282366920938463463374607431768211456
|
|
|
|
```
|