Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update lisp doc and examples #428

Merged
merged 12 commits into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 63 additions & 30 deletions doc/lisp.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,66 +5,99 @@ of the Shell.

MOROS Lisp is a Lisp-1 dialect inspired by Scheme and Clojure.

It 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
## 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
Computation by Machine" (1960) and "The Roots of Lisp" (2002) by Paul Graham.

In version 0.2.0 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.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

### 0.3.2 (2022-08-25)
- Add new functions

## Types
### 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
- Basics: `bool`, `list`, `symbol`, `string`
- Numbers: `float`, `int`, `bigint`

## Seven Primitive Operators
### Built-in Operators
- `quote` (with the `'` syntax)
- `quasiquote` (with the `` ` ``)
- `unquote` (with the `,` syntax)
- `unquote-splicing` (with the `,@` syntax)
- `atom` (aliased to `atom?`)
- `eq` (aliased to `eq?`)
- `car` (aliased to `first`)
- `cdr` (aliased to `rest`)
- `cons`
- `if`
- `cond`

## Two Special Forms
- `label` (aliased to `define` and `def`)
- `lambda` (aliased to `function`, `fun`, and `fn`)

## Additional Builtins
- `defun` (aliased to `defn`)
- `set`
- `while`
- `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`)
- `apply`
- `eval`
- `expand`
- `do` (aliased to `begin` and `progn`)
- `load`

### Primitive Operators
- `append`
- `type`
- `string`
- `string->number`
- `string->bytes` and `bytes->string`
- `number->bytes` and `bytes->number`
- `regex-find`
- `system`
- `load`

- Arithmetic operations: `+`, `-`, `*`, `/`, `%`, `^`
- Trigonometric functions: `acos`, `asin`, `atan`, `cos`, `sin`, `tan`
- Comparisons: `>`, `<`, `>=`, `<=`, `=`
- Boolean operations: `not`, `and`, `or`
- String operations: `lines`
- File IO: `read-file`, `read-file-bytes`, `write-file-bytes`, `append-file-bytes`

## Core Library
### Core Library
- `nil`, `nil?`, `eq?`
- `atom?`, `string?`, `boolean?`, `symbol?`, `number?`, `list?`, `function?`, `lambda?`
- `first`, `second`, `third`, `rest`
- `map`, `reduce`, `append`, `reverse`
- `atom?`, `string?`, `boolean?`, `symbol?`, `number?`, `list?`, `function?`, `macro?`
- `caar`, `cadr`, `cdar`, `cddr`, `first`, `second`, `third`, `rest`
- `map`, `reduce`, `reverse`, `range`
- `let`
- `string-join`
- `read-line`, `read-char`
- `print`, `println`
- `write-file`, `append-file`
- `uptime`, `realtime`
- `regex-match?`

- Boolean operations: `not`, `and`, `or`

## Usage

The interpreter can be invoked from the shell:
Expand All @@ -85,7 +118,7 @@ with the following content:
```lisp
(load "/lib/lisp/core.lsp")

(def (fibonacci n)
(define (fibonacci n)
(if (< n 2) n
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))))

Expand All @@ -106,21 +139,21 @@ Would produce the following output:
```lisp
(load "/lib/lisp/core.lsp")

(def foo 42) # Variable definition
(define foo 42) # Variable definition

(def double (fun (x) (* x 2))) # Function definition
(def (double x) (* x 2)) # Shortcut
(define double (fun (x) (* x 2))) # Function definition
(define (double x) (* x 2)) # Shortcut

(double foo) # => 84

(def (map f ls)
(define (map f ls)
(if (nil? ls) nil
(cons
(f (first ls))
(map f (rest ls)))))

(def bar (quote (1 2 3)))
(def bar '(1 2 3)) # Shortcut
(define bar (quote (1 2 3)))
(define bar '(1 2 3)) # Shortcut

(map double bar) # => (2 4 6)

Expand All @@ -135,7 +168,7 @@ Would produce the following output:

(= foo 10) # => true

(def name "Alice")
(define name "Alice")

(string "Hello, " name) # => "Hello, Alice"

Expand Down
28 changes: 28 additions & 0 deletions dsk/lib/lisp/alias.lsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
(define def
(macro args `(define ,@args)))

(define mac
(macro args `(macro ,@args)))

(define fun
(macro args `(function ,@args)))

(define def-mac
(macro args `(define-macro ,@args)))

(define def-fun
(macro args `(define-function ,@args)))


(define label
(macro args `(define ,@args)))

(define lambda
(macro args `(function ,@args)))

(define progn
(macro args `(do ,@args)))


(define begin
(macro args `(do ,@args)))
90 changes: 55 additions & 35 deletions dsk/lib/lisp/core.lsp
Original file line number Diff line number Diff line change
@@ -1,99 +1,119 @@
(def (eq? x y)
(load "/lib/lisp/alias.lsp")

(define (eq? x y)
(eq x y))

(def (atom? x)
(define (atom? x)
(atom x))

(def (string? x)
(define (string? x)
(eq? (type x) "string"))

(def (boolean? x)
(define (boolean? x)
(eq? (type x) "boolean"))

(def (symbol? x)
(define (symbol? x)
(eq? (type x) "symbol"))

(def (number? x)
(define (number? x)
(eq? (type x) "number"))

(def (list? x)
(define (list? x)
(eq? (type x) "list"))

(def (function? x)
(define (function? x)
(eq? (type x) "function"))

(def nil '())
(define (macro? x)
(eq? (type x) "macro"))

(define nil '())

(def (nil? x)
(define (nil? x)
(eq? x nil))

(def (not x)
(define (not x)
(if x false true))

(def (or x y)
(if x true (if y true false)))
(define-macro (or x y)
`(if ,x true (if ,y true false)))

(define-macro (and x y)
`(if ,x (if ,y true false) false))

(define-macro (let params values body)
`((function ,params ,body) ,@values))

(define (caar x)
(car (car x)))

(define (cadr x)
(car (cdr x)))

(def (and x y)
(if x (if y true false) false))
(define (cdar x)
(cdr (car x)))

(def (rest x)
(define (cddr x)
(cdr (cdr x)))

(define (rest x)
(cdr x))

(def (first x)
(define (first x)
(car x))

(def (second x)
(define (second x)
(first (rest x)))

(def (third x)
(define (third x)
(second (rest x)))

(def (reduce f ls)
(define (reduce f ls)
(if (nil? (rest ls)) (first ls)
(f (first ls) (reduce f (rest ls)))))

(def (string-join ls s)
(reduce (fn (x y) (string x s y)) ls))

(def (map f ls)
(define (map f ls)
(if (nil? ls) nil
(cons
(f (first ls))
(map f (rest ls)))))

(def (reverse x)
(define (reverse x)
(if (nil? x) x
(append (reverse (rest x)) (cons (first x) '()))))

(def (range i n)
(define (range i n)
(if (= i n) nil
(append (list i) (range (+ i 1) n))))

(def (read-line)
(define (string-join ls s)
(reduce (fn (x y) (string x s y)) ls))

(define (read-line)
(bytes->string (reverse (rest (reverse (read-file-bytes "/dev/console" 256))))))

(def (read-char)
(define (read-char)
(bytes->string (read-file-bytes "/dev/console" 4)))

(def (print exp)
(define (print exp)
(do
(append-file-bytes "/dev/console" (string->bytes (string exp)))
'()))

(def (println exp)
(define (println exp)
(print (string exp "\n")))

(def (uptime)
(define (uptime)
(bytes->number (read-file-bytes "/dev/clk/uptime" 8) "float"))

(def (realtime)
(define (realtime)
(bytes->number (read-file-bytes "realtime" 8) "float"))

(def (write-file path str)
(define (write-file path str)
(write-file-bytes path (string->bytes str)))

(def (append-file path str)
(define (append-file path str)
(append-file-bytes path (string->bytes str)))

(def (regex-match? pattern str)
(define (regex-match? pattern str)
(not (nil? (regex-find pattern str))))
4 changes: 2 additions & 2 deletions dsk/tmp/lisp/factorial.lsp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
(load "/lib/lisp/core.lsp")

(def (factorial-helper n acc)
(define (factorial-helper n acc)
(if (< n 2) acc
(factorial-helper (- n 1) (* acc n))))

(def (factorial n)
(define (factorial n)
(factorial-helper n 1))

(println
Expand Down
2 changes: 1 addition & 1 deletion dsk/tmp/lisp/fibonacci.lsp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(load "/lib/lisp/core.lsp")

(def (fibonacci n)
(define (fibonacci n)
(if (< n 2) n
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))))

Expand Down
Loading