summaryrefslogtreecommitdiff
path: root/macros/src/util.rs
diff options
context:
space:
mode:
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() }
+ }
+}