From 97b8cb9233805976bb2e91d36dd42b3799f3a160 Mon Sep 17 00:00:00 2001 From: Demonstrandum Date: Mon, 9 Dec 2024 22:50:25 +0000 Subject: [PATCH] Added %symbol and %number literal conversion macros. --- README.md | 4 ++-- crates/seam/src/parse/expander.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c4f1b24..c100c02 100644 --- 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 index bb67574..a169371 100644 --- 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, 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, 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, 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),