summaryrefslogtreecommitdiff
path: root/macros/src/util.rs
diff options
context:
space:
mode:
authorPg Biel <9021226+PgBiel@users.noreply.github.com>2023-05-03 09:20:53 -0300
committerGitHub <noreply@github.com>2023-05-03 14:20:53 +0200
commitf88ef45ee6e285df59c7aa5cec935de331b4b6e0 (patch)
treeeab5481d4b50d1d57adb4d122d7fa023dee2dcec /macros/src/util.rs
parentdb6a710638cf26ddcd09b8fba74b9d1caf6cb4b8 (diff)
Function scopes (#1032)
Diffstat (limited to 'macros/src/util.rs')
-rw-r--r--macros/src/util.rs34
1 files changed, 34 insertions, 0 deletions
diff --git a/macros/src/util.rs b/macros/src/util.rs
index 53a8354e..6b683e5d 100644
--- a/macros/src/util.rs
+++ b/macros/src/util.rs
@@ -18,6 +18,27 @@ macro_rules! bail {
};
}
+/// For parsing attributes of the form:
+/// #[attr(
+/// statement;
+/// statement;
+/// returned_expression
+/// )]
+pub struct BlockWithReturn {
+ pub prefix: Vec<syn::Stmt>,
+ pub expr: syn::Stmt,
+}
+
+impl Parse for BlockWithReturn {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut stmts = syn::Block::parse_within(input)?;
+ let Some(expr) = stmts.pop() else {
+ return Err(input.error("expected at least one expression"));
+ };
+ Ok(Self { prefix: stmts, expr })
+ }
+}
+
/// Whether an attribute list has a specified attribute.
pub fn has_attr(attrs: &mut Vec<syn::Attribute>, target: &str) -> bool {
take_attr(attrs, target).is_some()
@@ -88,3 +109,16 @@ pub fn meta_line<'a>(lines: &mut Vec<&'a str>, key: &str) -> Result<&'a str> {
None => bail!(callsite, "missing metadata key: {}", key),
}
}
+
+/// Creates a block responsible for building a Scope.
+pub fn create_scope_builder(scope_block: Option<&BlockWithReturn>) -> TokenStream {
+ if let Some(BlockWithReturn { prefix, expr }) = scope_block {
+ quote! { {
+ let mut scope = ::typst::eval::Scope::deduplicating();
+ #(#prefix);*
+ #expr
+ } }
+ } else {
+ quote! { ::typst::eval::Scope::new() }
+ }
+}