commit 97b8cb9233805976bb2e91d36dd42b3799f3a160
parent c100c7a77d1bb443010b63572a8b045dcf9c35e9
Author: Demonstrandum <samuel@knutsen.co>
Date: Mon, 9 Dec 2024 22:50:25 +0000
Added %symbol and %number literal conversion macros.
Diffstat:
2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
@@ -93,10 +93,10 @@ seam --sexp <<< '(hello (%define subject world) %subject)'
## Checklist
- [ ] User `(%error msg)` macro for aborting compilation.
- [x] List reverse macro `(%reverse (...))`.
- - [ ] Literal/atomic conversion macros: `(%symbol lit)`, `(%number lit)`, `(%string lit)`, `(%raw lit)`.
+ - [x] Literal/atomic conversion macros: `(%symbol lit)`, `(%number lit)`, `(%string lit)`, `(%raw lit)`.
- [x] Sorting macro `(%sort (...))` which sorts alphanumerically on literals.
Allow providing a `:key` to sort "by field": e.g. sort by title name `(%sort :key (%lambda ((:title _ &&_)) %title) %posts)`
- - [ ] Extend the strftime-style `(%date)` to be able to read UNIX numeric timestamps and display relative to timezones.
+ - [x] Extend the strftime-style `(%date)` to be able to read UNIX numeric timestamps and display relative to timezones.
Add complementary strptime-style utility `(%timestamp)` to convert date-strings to timestamps (relative to a timezone).
- [x] Pattern-matching `(%match expr (pat1 ...) (pat2 ...))` macro.
Pattern matching is already implemented for `%define` internally.
diff --git a/crates/seam/src/parse/expander.rs b/crates/seam/src/parse/expander.rs
@@ -1344,6 +1344,32 @@ impl<'a> Expander<'a> {
]))
}
+ fn expand_number_macro(&self, node: &ParseNode<'a>, params: ParseTree<'a>)
+ -> Result<ParseTree<'a>, ExpansionError<'a>> {
+ let params = self.expand_nodes(params)?; // Eager.
+ let (_parser, args) = arguments! { [¶ms]
+ rest: literal,
+ }?;
+ let mut expanded = Vec::with_capacity(args.rest.len());
+ for node in args.rest {
+ expanded.push(ParseNode::Number(node));
+ }
+ Ok(expanded.into_boxed_slice())
+ }
+
+ fn expand_symbol_macro(&self, node: &ParseNode<'a>, params: ParseTree<'a>)
+ -> Result<ParseTree<'a>, ExpansionError<'a>> {
+ let params = self.expand_nodes(params)?; // Eager.
+ let (_parser, args) = arguments! { [¶ms]
+ rest: literal,
+ }?;
+ let mut expanded = Vec::with_capacity(args.rest.len());
+ for node in args.rest {
+ expanded.push(ParseNode::Symbol(node));
+ }
+ Ok(expanded.into_boxed_slice())
+ }
+
fn expand_reverse_macro(&self, node: &ParseNode<'a>, params: ParseTree<'a>)
-> Result<ParseTree<'a>, ExpansionError<'a>> {
let params = self.expand_nodes(params)?; // Eager.
@@ -1708,6 +1734,8 @@ impl<'a> Expander<'a> {
"get" => self.expand_get_macro(node, params),
"raw" => self.expand_raw_macro(node, params),
"string" => self.expand_string_macro(node, params),
+ "number" => self.expand_number_macro(node, params),
+ "symbol" => self.expand_symbol_macro(node, params),
"include" => self.expand_include_macro(node, params),
"embed" => self.expand_embed_macro(node, params),
"namespace" => self.expand_namespace_macro(node, params),