seam

Symbolic-Expressions As Markup.
git clone git://git.knutsen.co/seam
Log | Files | Refs | README | LICENSE

commit 058b03c670ed178b1024902ac8d390067a7bacf8
parent 97b8cb9233805976bb2e91d36dd42b3799f3a160
Author: Demonstrandum <samuel@knutsen.co>
Date:   Fri, 13 Dec 2024 23:25:12 +0000

fix: expand symbol macros recursively.

Diffstat:
MCargo.lock | 2+-
MREADME.md | 17++++++++++++++++-
Mcrates/seam/Cargo.toml | 2+-
Mcrates/seam/src/parse/expander.rs | 2+-
4 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -337,7 +337,7 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "seam" -version = "0.4.2" +version = "0.4.3" dependencies = [ "chrono", "colored", diff --git a/README.md b/README.md @@ -91,6 +91,22 @@ seam --sexp <<< '(hello (%define subject world) %subject)' ``` ## Checklist + - [ ] Literate mode for parser+lexer, where string nodes are not escaped and parentheses are converted to symbols. + The only time strings are escaped and parentheses make lists is inside a `(%` and `)` pair, i.e. when calling a macro. + So `hello world (earth) (%do (p letter "\x61")) "\x61"` turns in to (in HTML mode) + `hello world <earth></earth> <p>hi a</p> a` normally, but in *literate* (HTML) mode turns into + `hello world (earth) <p>letter a</p> "\x61"`. Parentheses and quotes have been preserved. + Markdown source in `(%markdown ...)` should be parsed as literate files by default. + Provide command line `--literate` option; `%include` and `%embed` should also have options for enabling literate mode. + - [ ] Way to match on unknown keywords in attributes, examples when `(%define dict (:a 1 :b 2 :c 3))`: + - `(%for (kw val) in (%items %dict) (%log %kw = %val))` + - `(%for kw in (%keys %dict) (%log %kw = (%get %kw %dict)))` + - `(%for val in (%values %dict) (%log ___ = %val))` + - [ ] Extend `%get` to work with slicing `(%get (1 3) (a b c d e))` becomes `b c d`; negative indices `(%get -1 (a b c))` becomes `c`. + - [ ] Shell-style `${var:...}` string manipulation. + - [ ] `%while`, `%take`, `%drop`, `%split` on symbols in lists, `%intercalate`. + - [ ] `(%basename :suffix "txt" /path/file.txt)` (-> `file`), `(%dirname /path/file.txt)` (-> `/path`) and `(%extension /path/file.txt)` (-> `txt`), macros for paths. + - [ ] Math operators: `+`, `-`, `*`, `/`, `mod`, `pow`, `exp`, `sqrt`, `log`, `ln`, `hypot`. - [ ] User `(%error msg)` macro for aborting compilation. - [x] List reverse macro `(%reverse (...))`. - [x] Literal/atomic conversion macros: `(%symbol lit)`, `(%number lit)`, `(%string lit)`, `(%raw lit)`. @@ -124,7 +140,6 @@ seam --sexp <<< '(hello (%define subject world) %subject)' used by applying `%apply`, e.g. `(%apply (%lambda (a b) b a) x y)` becomes `y x` - [x] `(%string ...)`, `(%join ...)`, `(%map ...)`, `(%filter ...)` macros. - [x] `(%concat ...)` which is just `(%join "" ...)`. - - [ ] `(%basename)`, `(%dirname)` and `(%extension)` macros for paths. - [x] Add options to `%glob` for sorting by type, date(s), name, etc. - [x] `(%format "{}")` macro with Rust's `format` syntax. e.g. `(%format "Hello {}, age {age:0>2}" "Sam" :age 9)` - [x] Add `(%raw ...)` macro which takes a string and leaves it unchanged in the final output. diff --git a/crates/seam/Cargo.toml b/crates/seam/Cargo.toml @@ -5,7 +5,7 @@ keywords = ["markup", "lisp", "macro", "symbolic-expression", "sexp"] license-file = "../../LICENSE" readme = "../../README.md" homepage = "https://git.knutsen.co/seam" -version = "0.4.2" +version = "0.4.3" authors = ["Demonstrandum <samuel@knutsen.co>"] edition = "2021" diff --git a/crates/seam/src/parse/expander.rs b/crates/seam/src/parse/expander.rs @@ -1780,7 +1780,7 @@ impl<'a> Expander<'a> { and cannot be used as a variable.", name), &sym.site)) } - let mut expanded = def.body.clone(); + let mut expanded = self.expand_nodes(def.body.clone())?; // Inherit the whitespace of the call-site. if let Some(first) = expanded.first_mut() { first.set_leading_whitespace(sym.leading_whitespace.to_owned());