summaryrefslogtreecommitdiff
path: root/macros/src/castable.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-03-07 15:17:13 +0100
committerLaurenz <laurmaedje@gmail.com>2023-03-07 15:17:13 +0100
commit25b5bd117529cd04bb789e1988eb3a3db8025a0e (patch)
tree2fbb4650903123da047a1f1f11a0abda95286e12 /macros/src/castable.rs
parent6ab7760822ccd24b4ef126d4737d41f1be15fe19 (diff)
Fully untyped model
Diffstat (limited to 'macros/src/castable.rs')
-rw-r--r--macros/src/castable.rs135
1 files changed, 74 insertions, 61 deletions
diff --git a/macros/src/castable.rs b/macros/src/castable.rs
index c39df90a..c0d0c1ad 100644
--- a/macros/src/castable.rs
+++ b/macros/src/castable.rs
@@ -1,11 +1,7 @@
-use syn::parse::{Parse, ParseStream};
-use syn::punctuated::Punctuated;
-use syn::Token;
-
use super::*;
-/// Expand the `castable!` macro.
-pub fn castable(stream: TokenStream) -> Result<TokenStream> {
+/// Expand the `cast_from_value!` macro.
+pub fn cast_from_value(stream: TokenStream) -> Result<TokenStream> {
let castable: Castable = syn::parse2(stream)?;
let ty = &castable.ty;
@@ -41,6 +37,77 @@ pub fn castable(stream: TokenStream) -> Result<TokenStream> {
})
}
+/// Expand the `cast_to_value!` macro.
+pub fn cast_to_value(stream: TokenStream) -> Result<TokenStream> {
+ let cast: Cast = syn::parse2(stream)?;
+ let Pattern::Ty(pat, ty) = &cast.pattern else {
+ bail!(callsite, "expected pattern");
+ };
+
+ let expr = &cast.expr;
+ Ok(quote! {
+ impl ::std::convert::From<#ty> for ::typst::eval::Value {
+ fn from(#pat: #ty) -> Self {
+ #expr
+ }
+ }
+ })
+}
+
+struct Castable {
+ ty: syn::Type,
+ name: Option<syn::LitStr>,
+ casts: Punctuated<Cast, Token![,]>,
+}
+
+struct Cast {
+ attrs: Vec<syn::Attribute>,
+ pattern: Pattern,
+ expr: syn::Expr,
+}
+
+enum Pattern {
+ Str(syn::LitStr),
+ Ty(syn::Pat, syn::Type),
+}
+
+impl Parse for Castable {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let ty = input.parse()?;
+ let mut name = None;
+ if input.peek(Token![:]) {
+ let _: syn::Token![:] = input.parse()?;
+ name = Some(input.parse()?);
+ }
+ let _: syn::Token![,] = input.parse()?;
+ let casts = Punctuated::parse_terminated(input)?;
+ Ok(Self { ty, name, casts })
+ }
+}
+
+impl Parse for Cast {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(syn::Attribute::parse_outer)?;
+ let pattern = input.parse()?;
+ let _: syn::Token![=>] = input.parse()?;
+ let expr = input.parse()?;
+ Ok(Self { attrs, pattern, expr })
+ }
+}
+
+impl Parse for Pattern {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(syn::LitStr) {
+ Ok(Pattern::Str(input.parse()?))
+ } else {
+ let pat = input.parse()?;
+ let _: syn::Token![:] = input.parse()?;
+ let ty = input.parse()?;
+ Ok(Pattern::Ty(pat, ty))
+ }
+ }
+}
+
/// Create the castable's `is` function.
fn create_is_func(castable: &Castable) -> TokenStream {
let mut string_arms = vec![];
@@ -163,7 +230,7 @@ fn create_describe_func(castable: &Castable) -> TokenStream {
if let Some(name) = &castable.name {
infos.push(quote! {
- CastInfo::Type(#name)
+ ::typst::eval::CastInfo::Type(#name)
});
}
@@ -173,57 +240,3 @@ fn create_describe_func(castable: &Castable) -> TokenStream {
}
}
}
-
-struct Castable {
- ty: syn::Type,
- name: Option<syn::LitStr>,
- casts: Punctuated<Cast, Token![,]>,
-}
-
-impl Parse for Castable {
- fn parse(input: ParseStream) -> Result<Self> {
- let ty = input.parse()?;
- let mut name = None;
- if input.peek(Token![:]) {
- let _: syn::Token![:] = input.parse()?;
- name = Some(input.parse()?);
- }
- let _: syn::Token![,] = input.parse()?;
- let casts = Punctuated::parse_terminated(input)?;
- Ok(Self { ty, name, casts })
- }
-}
-
-struct Cast {
- attrs: Vec<syn::Attribute>,
- pattern: Pattern,
- expr: syn::Expr,
-}
-
-impl Parse for Cast {
- fn parse(input: ParseStream) -> Result<Self> {
- let attrs = input.call(syn::Attribute::parse_outer)?;
- let pattern = input.parse()?;
- let _: syn::Token![=>] = input.parse()?;
- let expr = input.parse()?;
- Ok(Self { attrs, pattern, expr })
- }
-}
-
-enum Pattern {
- Str(syn::LitStr),
- Ty(syn::Pat, syn::Type),
-}
-
-impl Parse for Pattern {
- fn parse(input: ParseStream) -> Result<Self> {
- if input.peek(syn::LitStr) {
- Ok(Pattern::Str(input.parse()?))
- } else {
- let pat = input.parse()?;
- let _: syn::Token![:] = input.parse()?;
- let ty = input.parse()?;
- Ok(Pattern::Ty(pat, ty))
- }
- }
-}