seam

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

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:
MREADME.md | 4++--
Mcrates/seam/src/parse/expander.rs | 28++++++++++++++++++++++++++++
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! { [&params] + 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! { [&params] + 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),