Skip to content
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
26 changes: 15 additions & 11 deletions doc/lisp.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ MOROS Lisp is a Lisp-1 dialect inspired by Scheme, Clojure, and Ruby!
- `if`
- `cond`
- `while`
- `variable` (aliased to `var`)
- `function` (aliased to `fun`)
- `macro` (aliased to `mac`)
- `set`
- `function` (aliased to `fun`)
- `variable` (aliased to `var`)
- `variable?` (aliased to `var?`)
- `mutate` (aliased to `mut`)
- `define` (aliased to `def` and equivalent to `define-function`)
- `define-function` (aliased to `def-fun`)
- `define-macro` (aliased to `def-mac`)
Expand Down Expand Up @@ -71,7 +72,7 @@ MOROS Lisp is a Lisp-1 dialect inspired by Scheme, Clojure, and Ruby!
- `first`, `second`, `third`, `last`, `rest`, `push`
- `map`, `reduce`, `reverse` (aliased to `rev`), `range`, `filter`, `reject`, `intersection`
- `not`, `and`, `or`
- `let`
- `set`, `let`
- `string/join` (aliased to `str/join`), `lines`, `words`, `chars`
- `regex/match?`

Expand Down Expand Up @@ -134,18 +135,18 @@ Would produce the following output:

(print "Hello, World!")

(var foo 42) # Variable definition
(set foo (+ 40 2)) # Variable assignement
(set bar 10) # Variable binding
(set bar (+ bar 10)) # Variable rebinding

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

(double foo) # => 84

(def-mac (++ x) # Macro definition
`(set ,x (+ ,x 1)))

(var i 0)
(set i 0)
(while (< i 10)
(++ i))
(= i 10) # => true
Expand All @@ -159,14 +160,14 @@ Would produce the following output:

(doc map) # => "Apply function to list"

(var bar (quote (1 2 3)))
(var bar '(1 2 3)) # Shortcut
(set bar (quote (1 2 3)))
(set bar '(1 2 3)) # Shortcut

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

(map (fun (x) (+ x 1)) '(4 5 6)) # => (5 6 7)

(var name "Alice")
(set name "Alice")

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

Expand All @@ -176,6 +177,9 @@ Would produce the following output:
## Changelog

### Unreleased
- Rename old `set` to `mutate` (aliased to `mut`)
- Add new `set` macro that does either `var` or `mut`
- Add `var?` function
- Add `sleep` function

### 0.8.0 (2024-12-21)
Expand Down
6 changes: 6 additions & 0 deletions dsk/lib/lisp/alias.lsp
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
(variable var
(macro args `(variable ,@args)))

(var var?
(macro args `(variable? ,@args)))

(var mut
(macro args `(mutate ,@args)))

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

Expand Down
5 changes: 5 additions & 0 deletions dsk/lib/lisp/core.lsp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
(equal? x nil)
(equal? x "")))

(def-mac (set k v)
`(if (var? ,k)
(mut ,k ,v)
(var ,k ,v)))

(def-mac (let params values body)
`((fun ,params ,body) ,@values))

Expand Down
6 changes: 3 additions & 3 deletions dsk/tmp/lisp/doc.lsp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
(load "/lib/lisp/core.lsp")

(def (print-doc f) (do
(var s (second (parse (str (eval f)))))
(var d (doc (eval f)))
(set s (second (parse (str (eval f)))))
(set d (doc (eval f)))
(print (str
"("
(if (function? (eval f)) "\e[96m" "\e[92m") f "\e[0m" # name
Expand All @@ -11,7 +11,7 @@
")"
"\e[90m" (if (empty? d) "" " # ") d "\e[0m")))) # desc

(var fs
(set fs
(filter
(fun (f) (or (fun? (eval f)) (mac? (eval f))))
(rev (env))))
Expand Down
20 changes: 10 additions & 10 deletions dsk/tmp/lisp/pi.lsp
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@

(def (pi-digits digits)
(do
(var i 0)
(var q 1)
(var r 0)
(var t 1)
(var k 1)
(var n 3)
(var l 3)
(set i 0)
(set q 1)
(set r 0)
(set t 1)
(set k 1)
(set n 3)
(set l 3)
(while (<= i digits)
(if (< (- (+ (* q 4) r) t) (* n t))
(do
(p (str n (if (= i 0) "." "")))
(set i (+ i 1))
(var nr (* 10 (- r (* n t))))
(set nr (* 10 (- r (* n t))))
(set n (- (/ (* 10 (+ (* 3 q) r)) t) (* 10 n)))
(set q (* q 10))
(set r nr))
(do
(var nr (* (+ (* 2 q) r) l))
(var nn (/ (+ 2 (* q k 7) (* r l)) (* t l)))
(set nr (* (+ (* 2 q) r) l))
(set nn (/ (+ 2 (* q k 7) (* r l)) (* t l)))
(set q (* q k))
(set t (* t l))
(set l (+ l 2))
Expand Down
36 changes: 18 additions & 18 deletions dsk/tmp/lisp/timer.lsp
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
(load "/lib/lisp/core.lsp")

(var bar-width 67)
(set bar-width 67)

(def (repeat ch n) (do
(var s "")
(var i 0)
(set s "")
(set i 0)
(while (< i n) (do
(set s (str s ch))
(set i (+ i 1))))
s))

(def (parse-duration d) (do
(var cs (chars d))
(var ns nil)
(var n 0)
(set cs (chars d))
(set ns nil)
(set n 0)
(while (not (empty? cs)) (do
(var c (first cs))
(set c (first cs))
(set cs (rest cs))
(if (contains? "0123456789" c)
(set n (+ (* n 10) (str->num c)))
Expand All @@ -31,22 +31,22 @@
(reduce + ns)))

(def (progress-bar elapsed total) (do
(var filled (trunc (* (/ elapsed total) bar-width)))
(var empty (- bar-width filled))
(set filled (trunc (* (/ elapsed total) bar-width)))
(set empty (- bar-width filled))
(str "[\e[92m" (repeat "#" filled) "\e[0m" (repeat "-" empty) "]")))

(def (format-time secs) (do
(var m (trunc (/ secs 60)))
(var s (trunc (rem secs 60)))
(var mm (if (< m 10) (str "0" (num->str m)) (num->str m)))
(var ss (if (< s 10) (str "0" (num->str s)) (num->str s)))
(set m (trunc (/ secs 60)))
(set s (trunc (rem secs 60)))
(set mm (if (< m 10) (str "0" (num->str m)) (num->str m)))
(set ss (if (< s 10) (str "0" (num->str s)) (num->str s)))
(str mm ":" ss)))

(def (timer label duration) (do
(var start (clock/epoch))
(set start (clock/epoch))
(while (< (clock/epoch) (+ start duration)) (do
(var elapsed (- (clock/epoch) start))
(var remaining (- duration elapsed))
(set elapsed (- (clock/epoch) start))
(set remaining (- duration elapsed))
(p (str "\e[2K\e[1G" label " "
(progress-bar elapsed duration) " "
(format-time remaining)))
Expand All @@ -55,7 +55,7 @@
(progress-bar duration duration) " "
(format-time 0)))))

(var l (if (> (len args) 0) (get args 0) "Wait"))
(var d (if (> (len args) 1) (parse-duration (get args 1)) 60))
(set l (if (> (len args) 0) (get args 0) "Wait"))
(set d (if (> (len args) 1) (parse-duration (get args 1)) 60))

(timer l d)
5 changes: 5 additions & 0 deletions dsk/var/pkg/lisp
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/lib/lisp/alias.lsp
/lib/lisp/core.lsp
/lib/lisp/file.lsp
/lib/lisp/legacy.lsp
/lib/lisp/math.lsp
/tmp/lisp/colors.lsp
/tmp/lisp/doc.lsp
/tmp/lisp/factorial.lsp
Expand Down
31 changes: 24 additions & 7 deletions src/usr/lisp/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,19 @@ fn eval_cons_args(
}
}

fn eval_is_variable_args(
args: &[Exp],
env: &mut Rc<RefCell<Env>>
) -> Result<Exp, Err> {
ensure_length_eq!(args, 1);
match &args[0] {
Exp::Sym(name) => {
Ok(Exp::Bool(env_get(name, env).is_ok()))
}
_ => expected!("first argument to be a symbol"),
}
}

pub fn eval_variable_args(
args: &[Exp],
env: &mut Rc<RefCell<Env>>
Expand All @@ -106,7 +119,7 @@ pub fn eval_variable_args(
}
}

fn eval_set_args(
fn eval_mutate_args(
args: &[Exp],
env: &mut Rc<RefCell<Env>>
) -> Result<Exp, Err> {
Expand Down Expand Up @@ -215,7 +228,7 @@ pub fn eval_args(
args.iter().map(|x| eval(x, env)).collect()
}

pub const BUILT_INS: [&str; 26] = [
pub const BUILT_INS: [&str; 27] = [
"quote",
"quasiquote",
"unquote",
Expand All @@ -228,13 +241,14 @@ pub const BUILT_INS: [&str; 26] = [
"if",
"cond",
"while",
"variable",
"function",
"variable",
"variable?",
"mutate",
"macro",
"define-function",
"define",
"define-macro",
"set",
"apply",
"eval",
"expand",
Expand Down Expand Up @@ -277,9 +291,6 @@ pub fn eval(exp: &Exp, env: &mut Rc<RefCell<Env>>) -> Result<Exp, Err> {
Exp::Sym(s) if s == "cons" => {
return eval_cons_args(args, env);
}
Exp::Sym(s) if s == "set" => {
return eval_set_args(args, env);
}
Exp::Sym(s) if s == "while" => {
return eval_while_args(args, env);
}
Expand All @@ -298,9 +309,15 @@ pub fn eval(exp: &Exp, env: &mut Rc<RefCell<Env>>) -> Result<Exp, Err> {
Exp::Sym(s) if s == "doc" => {
return eval_doc_args(args, env);
}
Exp::Sym(s) if s == "variable?" => {
return eval_is_variable_args(args, env);
}
Exp::Sym(s) if s == "variable" => {
return eval_variable_args(args, env);
}
Exp::Sym(s) if s == "mutate" => {
return eval_mutate_args(args, env);
}
Exp::Sym(s) if s == "env" => {
return eval_env_args(args, env);
}
Expand Down
24 changes: 16 additions & 8 deletions src/usr/lisp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,12 +497,6 @@ fn test_lisp() {
assert_eq!(eval!("(if 42 1 2)"), "1");
assert_eq!(eval!("(if \"\" 1 2)"), "1");

// while
assert_eq!(
eval!("(do (variable i 0) (while (< i 5) (set i (+ i 1))) i)"),
"5"
);

// variable
eval!("(variable a 2)");
assert_eq!(eval!("(+ a 1)"), "3");
Expand All @@ -512,6 +506,20 @@ fn test_lisp() {
(if (< n 2) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))))");
assert_eq!(eval!("(fibonacci 6)"), "8");

// variable?
assert_eq!(eval!("(variable? a)"), "true");
assert_eq!(eval!("(variable? b)"), "false");

// mutate
assert_eq!(eval!("(mutate a 3)"), "3");
assert_eq!(eval!("a"), "3");

// while
assert_eq!(
eval!("(do (variable i 0) (while (< i 5) (mutate i (+ i 1))) i)"),
"5"
);

// function
assert_eq!(eval!("((function (a) (+ 1 a)) 2)"), "3");
assert_eq!(eval!("((function (a) (* a a)) 2)"), "4");
Expand Down Expand Up @@ -695,8 +703,8 @@ fn test_lisp() {

// macro
eval!("(variable foo 42)");
eval!("(variable set-10 (macro (x) `(set ,x 10)))");
eval!("(set-10 foo)");
eval!("(variable mut-10 (macro (x) `(mutate ,x 10)))");
eval!("(mut-10 foo)");
assert_eq!(eval!("foo"), "10");

// args
Expand Down
Loading