From 02a201322fe69da06025b2e5ae1e7521a1e45da8 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Fri, 27 Jun 2025 22:20:17 +0200 Subject: [PATCH 01/10] Update example comment --- doc/lisp.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/lisp.md b/doc/lisp.md index c9429820..2b043ed3 100644 --- a/doc/lisp.md +++ b/doc/lisp.md @@ -134,8 +134,8 @@ Would produce the following output: (print "Hello, World!") -(var foo 42) # Variable definition -(set foo (+ 40 2)) # Variable assignement +(var foo 42) # Variable binding +(set foo (+ 40 2)) # Variable rebinding (var double (fun (x) (* x 2))) # Function definition (def (double x) (* x 2)) # Shortcut From 4f91e1393e0c657bd6c7d651f0b82d35218bd851 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sun, 29 Jun 2025 22:57:18 +0200 Subject: [PATCH 02/10] Rename set to mutate or mut --- dsk/lib/lisp/alias.lsp | 3 +++ src/usr/lisp/eval.rs | 8 ++++---- src/usr/lisp/mod.rs | 20 ++++++++++++-------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/dsk/lib/lisp/alias.lsp b/dsk/lib/lisp/alias.lsp index 75f42fd8..1f6df4b2 100644 --- a/dsk/lib/lisp/alias.lsp +++ b/dsk/lib/lisp/alias.lsp @@ -1,6 +1,9 @@ (variable var (macro args `(variable ,@args))) +(var mut + (macro args `(mutate ,@args))) + (var mac (macro args `(macro ,@args))) diff --git a/src/usr/lisp/eval.rs b/src/usr/lisp/eval.rs index 310de1c8..bf340401 100644 --- a/src/usr/lisp/eval.rs +++ b/src/usr/lisp/eval.rs @@ -106,7 +106,7 @@ pub fn eval_variable_args( } } -fn eval_set_args( +fn eval_mutate_args( args: &[Exp], env: &mut Rc> ) -> Result { @@ -277,9 +277,6 @@ pub fn eval(exp: &Exp, env: &mut Rc>) -> Result { 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); } @@ -301,6 +298,9 @@ pub fn eval(exp: &Exp, env: &mut Rc>) -> Result { 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); } diff --git a/src/usr/lisp/mod.rs b/src/usr/lisp/mod.rs index d67d008c..66f8c081 100644 --- a/src/usr/lisp/mod.rs +++ b/src/usr/lisp/mod.rs @@ -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"); @@ -512,6 +506,16 @@ fn test_lisp() { (if (< n 2) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))))"); assert_eq!(eval!("(fibonacci 6)"), "8"); + // 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"); @@ -695,8 +699,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 From 28340f74cdeaef2e0576a95e38b13aba00606e47 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sun, 29 Jun 2025 22:57:44 +0200 Subject: [PATCH 03/10] Add variable? or var? function --- dsk/lib/lisp/alias.lsp | 3 +++ src/usr/lisp/eval.rs | 16 ++++++++++++++++ src/usr/lisp/mod.rs | 4 ++++ 3 files changed, 23 insertions(+) diff --git a/dsk/lib/lisp/alias.lsp b/dsk/lib/lisp/alias.lsp index 1f6df4b2..fc44d0e0 100644 --- a/dsk/lib/lisp/alias.lsp +++ b/dsk/lib/lisp/alias.lsp @@ -1,6 +1,9 @@ (variable var (macro args `(variable ,@args))) +(var var? + (macro args `(variable? ,@args))) + (var mut (macro args `(mutate ,@args))) diff --git a/src/usr/lisp/eval.rs b/src/usr/lisp/eval.rs index bf340401..1123a3fc 100644 --- a/src/usr/lisp/eval.rs +++ b/src/usr/lisp/eval.rs @@ -91,6 +91,19 @@ fn eval_cons_args( } } +fn eval_is_variable_args( + args: &[Exp], + env: &mut Rc> +) -> Result { + 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> @@ -295,6 +308,9 @@ pub fn eval(exp: &Exp, env: &mut Rc>) -> Result { 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); } diff --git a/src/usr/lisp/mod.rs b/src/usr/lisp/mod.rs index 66f8c081..5d5e3abb 100644 --- a/src/usr/lisp/mod.rs +++ b/src/usr/lisp/mod.rs @@ -506,6 +506,10 @@ 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"); From bf77770583920364f64b93b4935566050b7bffdc Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sun, 29 Jun 2025 22:59:14 +0200 Subject: [PATCH 04/10] Update builtin list --- src/usr/lisp/eval.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/usr/lisp/eval.rs b/src/usr/lisp/eval.rs index 1123a3fc..92333fe9 100644 --- a/src/usr/lisp/eval.rs +++ b/src/usr/lisp/eval.rs @@ -228,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", @@ -241,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", From 8aad81b7b4d4cff77f919f92f49c12a484c96305 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sun, 29 Jun 2025 22:59:39 +0200 Subject: [PATCH 05/10] Add set macro that does either var or mut --- dsk/lib/lisp/core.lsp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dsk/lib/lisp/core.lsp b/dsk/lib/lisp/core.lsp index d0e8239a..2aa4ef5e 100644 --- a/dsk/lib/lisp/core.lsp +++ b/dsk/lib/lisp/core.lsp @@ -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)) From dda8ef196c9c564c95c57898c59c8cf59a7c6847 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sun, 29 Jun 2025 22:59:55 +0200 Subject: [PATCH 06/10] Add lib to package --- dsk/var/pkg/lisp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dsk/var/pkg/lisp b/dsk/var/pkg/lisp index 9af1bd4e..01417f0b 100644 --- a/dsk/var/pkg/lisp +++ b/dsk/var/pkg/lisp @@ -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 From 74df480ba2f4557af65975793e8499e19ad622f5 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Mon, 30 Jun 2025 21:33:09 +0200 Subject: [PATCH 07/10] Update doc --- doc/lisp.md | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/doc/lisp.md b/doc/lisp.md index 2b043ed3..fc9cf96a 100644 --- a/doc/lisp.md +++ b/doc/lisp.md @@ -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`) @@ -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?` @@ -134,8 +135,11 @@ Would produce the following output: (print "Hello, World!") +(set bar 10) # Variable binding +(set bar (+ bar 10)) # Variable rebinding + (var foo 42) # Variable binding -(set foo (+ 40 2)) # Variable rebinding +(mut foo (+ 40 2)) # Variable rebinding (var double (fun (x) (* x 2))) # Function definition (def (double x) (* x 2)) # Shortcut @@ -145,7 +149,7 @@ Would produce the following output: (def-mac (++ x) # Macro definition `(set ,x (+ ,x 1))) -(var i 0) +(set i 0) (while (< i 10) (++ i)) (= i 10) # => true @@ -159,14 +163,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" @@ -176,6 +180,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) From fed0dddbdc03c7209af0b7b33f20e11f9941c0fc Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Tue, 1 Jul 2025 08:45:54 +0200 Subject: [PATCH 08/10] Use set instead of var in scripts --- dsk/tmp/lisp/doc.lsp | 6 +++--- dsk/tmp/lisp/pi.lsp | 20 ++++++++++---------- dsk/tmp/lisp/timer.lsp | 36 ++++++++++++++++++------------------ 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/dsk/tmp/lisp/doc.lsp b/dsk/tmp/lisp/doc.lsp index 74e4378b..cc9dfe6e 100644 --- a/dsk/tmp/lisp/doc.lsp +++ b/dsk/tmp/lisp/doc.lsp @@ -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 @@ -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)))) diff --git a/dsk/tmp/lisp/pi.lsp b/dsk/tmp/lisp/pi.lsp index 89f1f202..670f9925 100644 --- a/dsk/tmp/lisp/pi.lsp +++ b/dsk/tmp/lisp/pi.lsp @@ -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)) diff --git a/dsk/tmp/lisp/timer.lsp b/dsk/tmp/lisp/timer.lsp index b4a0246f..0500b4b0 100644 --- a/dsk/tmp/lisp/timer.lsp +++ b/dsk/tmp/lisp/timer.lsp @@ -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))) @@ -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))) @@ -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) From 6f4c4e9f613c7b404eebb85e21272aacdb0224d6 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Tue, 1 Jul 2025 08:49:27 +0200 Subject: [PATCH 09/10] Simplify doc --- doc/lisp.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc/lisp.md b/doc/lisp.md index fc9cf96a..706fd4a4 100644 --- a/doc/lisp.md +++ b/doc/lisp.md @@ -138,10 +138,7 @@ Would produce the following output: (set bar 10) # Variable binding (set bar (+ bar 10)) # Variable rebinding -(var foo 42) # Variable binding -(mut foo (+ 40 2)) # 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 From 668c58b540940d9562deac4ff1ce5b3ed4585c55 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Tue, 1 Jul 2025 08:49:55 +0200 Subject: [PATCH 10/10] Regenerate HTML doc --- www/lisp.html | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/www/lisp.html b/www/lisp.html index c3f8315f..956d568f 100644 --- a/www/lisp.html +++ b/www/lisp.html @@ -46,10 +46,11 @@

Built-in Operators

  • 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)
  • @@ -93,7 +94,7 @@

    Core Library

  • 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?
  • @@ -161,10 +162,10 @@

    Examples

    (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 @@ -172,7 +173,7 @@

    Examples

    (def-mac (++ x) # Macro definition `(set ,x (+ ,x 1))) -(var i 0) +(set i 0) (while (< i 10) (++ i)) (= i 10) # => true @@ -186,14 +187,14 @@

    Examples

    (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" @@ -205,6 +206,9 @@

    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