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.
|
|
|
|
|
2023-04-22 13:46:05 +00:00
|
|
|
MOROS Lisp is a Lisp-1 dialect inspired by Scheme, Clojure, and Ruby!
|
2022-06-06 14:02:34 +00:00
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
## Overview
|
|
|
|
|
|
|
|
### Types
|
2022-10-17 18:58:08 +00:00
|
|
|
- Basics: `bool`, `list`, `symbol`, `string`
|
2023-11-17 09:08:25 +00:00
|
|
|
- Number: `float`, `int`, `bigint`
|
|
|
|
|
|
|
|
### Literals
|
2023-12-17 16:24:55 +00:00
|
|
|
- Number: `2.5`, `-25`, `255`, `0xFF`, `0xDEAD_C0DE`, `0b101010`
|
2023-11-17 09:08:25 +00:00
|
|
|
- String: `"Hello, World!"`
|
2023-12-17 16:24:55 +00:00
|
|
|
- Escape: `\b`, `\e`, `\n`, `\r`, `\t`, `\"`, `\\`
|
2022-10-17 18:58:08 +00:00
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
### Built-in Operators
|
2023-07-03 07:28:37 +00:00
|
|
|
- `quote` (abbreviated with `'`)
|
|
|
|
- `quasiquote` (abbreviated with `` ` ``)
|
|
|
|
- `unquote` (abbreviated with `,`)
|
|
|
|
- `unquote-splice` (abbreviated with `,@`)
|
|
|
|
- `splice` (abbreviated with `@`)
|
2023-04-22 13:46:05 +00:00
|
|
|
- `atom?`
|
|
|
|
- `equal?` (aliased to `eq?`)
|
|
|
|
- `head`
|
|
|
|
- `tail`
|
2021-07-21 07:40:40 +00:00
|
|
|
- `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`
|
2023-04-22 13:46:05 +00:00
|
|
|
- `variable` (aliased to `var`)
|
|
|
|
- `function` (aliased to `fun`)
|
2022-11-01 10:02:50 +00:00
|
|
|
- `macro` (aliased to `mac`)
|
2023-04-22 13:46:05 +00:00
|
|
|
- `set`
|
|
|
|
- `define` (aliased to `def` and equivalent to `define-function`)
|
2022-11-01 10:02:50 +00:00
|
|
|
- `define-function` (aliased to `def-fun`)
|
|
|
|
- `define-macro` (aliased to `def-mac`)
|
2022-09-15 18:50:23 +00:00
|
|
|
- `apply`
|
2023-05-29 08:15:11 +00:00
|
|
|
- `do`
|
|
|
|
- `doc`
|
2022-11-01 10:02:50 +00:00
|
|
|
- `eval`
|
|
|
|
- `expand`
|
|
|
|
- `load`
|
|
|
|
|
|
|
|
### Primitive Operators
|
2023-12-17 16:24:55 +00:00
|
|
|
- `type`, `number/type` (aliased to `num/type`), `parse`
|
2023-04-22 13:46:05 +00:00
|
|
|
- `string` (aliased to `str`)
|
2023-12-19 21:51:13 +00:00
|
|
|
- `string->number` and `number->string` (aliased to `str->num` and `num->str`)
|
2023-04-22 13:46:05 +00:00
|
|
|
- `string->binary` and `binary->string` (aliased to `str->bin` and `bin->str`)
|
|
|
|
- `number->binary` and `binary->number` (aliased to `num->bin` and `bin->num`)
|
2023-12-17 16:24:55 +00:00
|
|
|
- `regex/find`
|
|
|
|
- `shell` (aliased to `sh`)
|
|
|
|
- Arithmetic operations: `+`, `-`, `*`, `/`, `^`, `rem` (aliased to `%`), `trunc`
|
2022-07-02 13:24:30 +00:00
|
|
|
- Trigonometric functions: `acos`, `asin`, `atan`, `cos`, `sin`, `tan`
|
|
|
|
- Comparisons: `>`, `<`, `>=`, `<=`, `=`
|
2023-12-17 16:24:55 +00:00
|
|
|
- Enumerable: `length` (aliased to `len`), `put`, `get`, `slice`, `contains?`
|
|
|
|
- String: `string/trim` and `string/split` (aliased to `str/trim` and `str/split`)
|
|
|
|
- List: `list`, `concat`, `chunks`, `sort`, `unique` (aliased to `uniq`)
|
|
|
|
- Dict: `dict`
|
|
|
|
- File: `file/size`, `file/open`, `file/close`, `file/read`, `file/write`
|
|
|
|
- Net: `host`, `socket/connect`, `socket/listen`, `socket/accept`
|
2022-08-25 06:48:19 +00:00
|
|
|
|
2022-11-01 10:02:50 +00:00
|
|
|
### Core Library
|
2023-12-17 16:24:55 +00:00
|
|
|
- `nil`, `nil?`, `list?`, `empty?`
|
2023-04-22 13:46:05 +00:00
|
|
|
- `boolean?` (aliased to `bool?`), `string?` (aliased to `str?`), `symbol?` (aliased to `sym?`), `number?` (aliased to `num?`)
|
|
|
|
- `function?` (aliased to `fun?`), `macro?` (aliased to `mac?`)
|
2023-12-17 16:24:55 +00:00
|
|
|
- `abs`, `mod`, `min`, `max`
|
|
|
|
- `first`, `second`, `third`, `last`, `rest`, `push`
|
|
|
|
- `map`, `reduce`, `reverse` (aliased to `rev`), `range`, `filter`, `reject`, `intersection`
|
2022-12-12 17:43:51 +00:00
|
|
|
- `not`, `and`, `or`
|
2022-11-01 10:02:50 +00:00
|
|
|
- `let`
|
2023-12-17 16:24:55 +00:00
|
|
|
- `string/join` (aliased to `str/join`), `lines`, `words`, `chars`
|
|
|
|
- `regex/match?`
|
2023-07-02 07:20:49 +00:00
|
|
|
|
|
|
|
### File Library
|
|
|
|
- `read`, `write`, `append`
|
|
|
|
- `read-binary`, `write-binary`, `append-binary`
|
2022-08-25 06:48:19 +00:00
|
|
|
- `read-line`, `read-char`
|
|
|
|
- `uptime`, `realtime`
|
2023-07-02 07:20:49 +00:00
|
|
|
- `p`, `print`
|
2021-07-21 07:40:40 +00:00
|
|
|
|
2023-04-22 13:46:05 +00:00
|
|
|
### Compatibility Library
|
|
|
|
|
|
|
|
- `atom`, `eq`, `label`, `lambda`, `progn`, `begin`
|
|
|
|
- `car`, `cdr`, `caar`, `cadr`, `cdar`, `cddr`
|
|
|
|
|
2021-07-21 07:40:40 +00:00
|
|
|
## Usage
|
|
|
|
|
|
|
|
The interpreter can be invoked from the shell:
|
|
|
|
|
|
|
|
```
|
|
|
|
> lisp
|
2024-03-15 18:08:10 +00:00
|
|
|
MOROS Lisp v0.7.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
|
|
|
|
2023-04-22 13:46:05 +00:00
|
|
|
(def (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
|
|
|
|
2023-04-22 13:46:05 +00:00
|
|
|
(print
|
2022-10-21 08:10:14 +00:00
|
|
|
(if (nil? args) "Usage: fibonacci <num>"
|
2023-04-22 13:46:05 +00:00
|
|
|
(fibonacci (str->num (head 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")
|
|
|
|
|
2023-04-22 13:46:05 +00:00
|
|
|
(print "Hello, World!")
|
|
|
|
|
|
|
|
(var foo 42) # Variable definition
|
|
|
|
(set foo (+ 40 2)) # Variable assignement
|
2022-10-21 08:10:14 +00:00
|
|
|
|
2023-04-22 13:46:05 +00:00
|
|
|
(var double (fun (x) (* x 2))) # Function definition
|
|
|
|
(def (double x) (* x 2)) # Shortcut
|
2022-10-21 08:10:14 +00:00
|
|
|
|
|
|
|
(double foo) # => 84
|
|
|
|
|
2023-04-22 13:46:05 +00:00
|
|
|
(def-mac (++ x) # Macro definition
|
|
|
|
`(set ,x (+ ,x 1)))
|
|
|
|
|
|
|
|
(var i 0)
|
|
|
|
(while (< i 10)
|
|
|
|
(++ i))
|
|
|
|
(= i 10) # => true
|
|
|
|
|
|
|
|
(def (map f ls)
|
2023-05-29 08:15:11 +00:00
|
|
|
"Apply function to list"
|
2022-10-21 08:10:14 +00:00
|
|
|
(if (nil? ls) nil
|
|
|
|
(cons
|
|
|
|
(f (first ls))
|
|
|
|
(map f (rest ls)))))
|
|
|
|
|
2023-05-29 08:15:11 +00:00
|
|
|
(doc map) # => "Apply function to list"
|
|
|
|
|
2023-04-22 13:46:05 +00:00
|
|
|
(var bar (quote (1 2 3)))
|
|
|
|
(var 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)
|
|
|
|
|
2023-04-22 13:46:05 +00:00
|
|
|
(var name "Alice")
|
2022-10-21 08:10:14 +00:00
|
|
|
|
2023-04-22 13:46:05 +00:00
|
|
|
(str "Hello, " name) # => "Hello, Alice"
|
2022-10-21 08:10:14 +00:00
|
|
|
|
2023-04-27 17:34:05 +00:00
|
|
|
(^ 2 64) # => 18446744073709551616
|
2022-10-21 08:10:14 +00:00
|
|
|
```
|
2023-04-27 17:34:05 +00:00
|
|
|
|
|
|
|
## Changelog
|
|
|
|
|
2024-03-15 18:08:10 +00:00
|
|
|
<!--
|
|
|
|
### Unreleased
|
|
|
|
-->
|
2023-04-27 17:34:05 +00:00
|
|
|
|
2024-03-15 18:08:10 +00:00
|
|
|
### 0.7.0 (2023-12-22)
|
|
|
|
- Add binary and hexadecimal number literals
|
|
|
|
- Test for truthiness (neither `false` nor `nil`) in conditions of `if` and `while`
|
|
|
|
- Rename `nth` to `get`
|
|
|
|
- Add `empty?`, `reject`, `put`, `push`, and `host` functions`
|
|
|
|
- Add `dict` type
|
|
|
|
- Use `/` instead of `.` as namespace separator
|
|
|
|
- Add `number->string` (aliased to `num->str`) with an optional radix argument
|
2023-04-27 17:34:05 +00:00
|
|
|
|
2024-03-15 18:08:10 +00:00
|
|
|
### 0.6.0 (2023-09-23)
|
|
|
|
- Add file, number, string, and regex namespaces
|
|
|
|
- Add socket functions
|
2023-04-27 17:34:05 +00:00
|
|
|
|
2024-03-15 18:08:10 +00:00
|
|
|
### 0.5.0 (2023-06-21)
|
|
|
|
- Rename or add aliases to many functions
|
|
|
|
- Add full support for line and inline comments
|
|
|
|
- Add params to function representations
|
|
|
|
- Add docstring to functions
|
2023-04-27 17:34:05 +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
|
|
|
|
|
2024-03-15 18:08:10 +00:00
|
|
|
### 0.3.2 (2022-07-02)
|
|
|
|
- Add new functions
|
2023-07-02 07:20:49 +00:00
|
|
|
|
2024-03-15 18:08:10 +00:00
|
|
|
### 0.3.1 (2022-06-06)
|
|
|
|
- Rewrite parts of the code
|
|
|
|
- Add new functions and examples
|
2023-09-23 07:09:31 +00:00
|
|
|
|
2024-03-15 18:08:10 +00:00
|
|
|
### 0.3.0 (2022-12-12)
|
|
|
|
- Rewrite the evaluation code
|
|
|
|
- Add new functions
|
|
|
|
- Add a core library
|
2023-12-22 10:52:47 +00:00
|
|
|
|
2024-03-15 18:08:10 +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.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
|
|
|
|
Computation by Machine" (1960) and "The Roots of Lisp" (2002) by Paul Graham.
|