Skip to content

Commit

Permalink
fix: expand symbol macros recursively.
Browse files Browse the repository at this point in the history
  • Loading branch information
Demonstrandum committed Dec 13, 2024
1 parent 97b8cb9 commit 058b03c
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)`.
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion crates/seam/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
2 changes: 1 addition & 1 deletion crates/seam/src/parse/expander.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down

0 comments on commit 058b03c

Please sign in to comment.