forked from libre-chip/fayalite
		
	expand SimValue support
This commit is contained in:
		
							parent
							
								
									5028401a5a
								
							
						
					
					
						commit
						a40eaaa2da
					
				
					 13 changed files with 864 additions and 342 deletions
				
			
		|  | @ -692,6 +692,12 @@ impl ToTokens for ParsedBundle { | |||
|                 v.field_to_bits(&value.#ident); | ||||
|             } | ||||
|         })); | ||||
|         let to_sim_value_fields = Vec::from_iter(fields.named().into_iter().map(|field| { | ||||
|             let ident: &Ident = field.ident().as_ref().unwrap(); | ||||
|             quote_spanned! {span=> | ||||
|                 #ident: ::fayalite::sim::value::SimValue::ty(&self.#ident), | ||||
|             } | ||||
|         })); | ||||
|         let fields_len = fields.named().into_iter().len(); | ||||
|         quote_spanned! {span=> | ||||
|             #[automatically_derived] | ||||
|  | @ -797,6 +803,51 @@ impl ToTokens for ParsedBundle { | |||
|                 } | ||||
|             } | ||||
|             #[automatically_derived] | ||||
|             impl #impl_generics ::fayalite::sim::value::ToSimValue for #mask_type_sim_value_ident #type_generics | ||||
|             #where_clause | ||||
|             { | ||||
|                 type Type = #mask_type_ident #type_generics; | ||||
| 
 | ||||
|                 fn to_sim_value( | ||||
|                     &self, | ||||
|                 ) -> ::fayalite::sim::value::SimValue< | ||||
|                     <Self as ::fayalite::sim::value::ToSimValue>::Type, | ||||
|                 > { | ||||
|                     let ty = #mask_type_ident { | ||||
|                         #(#to_sim_value_fields)* | ||||
|                     }; | ||||
|                     ::fayalite::sim::value::SimValue::from_value(ty, ::fayalite::__std::clone::Clone::clone(self)) | ||||
|                 } | ||||
|                 fn into_sim_value( | ||||
|                     self, | ||||
|                 ) -> ::fayalite::sim::value::SimValue< | ||||
|                     <Self as ::fayalite::sim::value::ToSimValue>::Type, | ||||
|                 > { | ||||
|                     let ty = #mask_type_ident { | ||||
|                         #(#to_sim_value_fields)* | ||||
|                     }; | ||||
|                     ::fayalite::sim::value::SimValue::from_value(ty, self) | ||||
|                 } | ||||
|             } | ||||
|             #[automatically_derived] | ||||
|             impl #impl_generics ::fayalite::sim::value::ToSimValueWithType<#mask_type_ident #type_generics> | ||||
|             for #mask_type_sim_value_ident #type_generics | ||||
|             #where_clause | ||||
|             { | ||||
|                 fn to_sim_value_with_type( | ||||
|                     &self, | ||||
|                     ty: #mask_type_ident #type_generics, | ||||
|                 ) -> ::fayalite::sim::value::SimValue<#mask_type_ident #type_generics> { | ||||
|                     ::fayalite::sim::value::SimValue::from_value(ty, ::fayalite::__std::clone::Clone::clone(self)) | ||||
|                 } | ||||
|                 fn into_sim_value_with_type( | ||||
|                     self, | ||||
|                     ty: #mask_type_ident #type_generics, | ||||
|                 ) -> ::fayalite::sim::value::SimValue<#mask_type_ident #type_generics> { | ||||
|                     ::fayalite::sim::value::SimValue::from_value(ty, self) | ||||
|                 } | ||||
|             } | ||||
|             #[automatically_derived] | ||||
|             impl #impl_generics ::fayalite::ty::Type for #target #type_generics | ||||
|             #where_clause | ||||
|             { | ||||
|  | @ -900,6 +951,51 @@ impl ToTokens for ParsedBundle { | |||
|                     ::fayalite::intern::Interned::into_inner(::fayalite::intern::Intern::intern_sized(__retval)) | ||||
|                 } | ||||
|             } | ||||
|             #[automatically_derived] | ||||
|             impl #impl_generics ::fayalite::sim::value::ToSimValue for #sim_value_ident #type_generics | ||||
|             #where_clause | ||||
|             { | ||||
|                 type Type = #target #type_generics; | ||||
| 
 | ||||
|                 fn to_sim_value( | ||||
|                     &self, | ||||
|                 ) -> ::fayalite::sim::value::SimValue< | ||||
|                     <Self as ::fayalite::sim::value::ToSimValue>::Type, | ||||
|                 > { | ||||
|                     let ty = #target { | ||||
|                         #(#to_sim_value_fields)* | ||||
|                     }; | ||||
|                     ::fayalite::sim::value::SimValue::from_value(ty, ::fayalite::__std::clone::Clone::clone(self)) | ||||
|                 } | ||||
|                 fn into_sim_value( | ||||
|                     self, | ||||
|                 ) -> ::fayalite::sim::value::SimValue< | ||||
|                     <Self as ::fayalite::sim::value::ToSimValue>::Type, | ||||
|                 > { | ||||
|                     let ty = #target { | ||||
|                         #(#to_sim_value_fields)* | ||||
|                     }; | ||||
|                     ::fayalite::sim::value::SimValue::from_value(ty, self) | ||||
|                 } | ||||
|             } | ||||
|             #[automatically_derived] | ||||
|             impl #impl_generics ::fayalite::sim::value::ToSimValueWithType<#target #type_generics> | ||||
|             for #sim_value_ident #type_generics | ||||
|             #where_clause | ||||
|             { | ||||
|                 fn to_sim_value_with_type( | ||||
|                     &self, | ||||
|                     ty: #target #type_generics, | ||||
|                 ) -> ::fayalite::sim::value::SimValue<#target #type_generics> { | ||||
|                     ::fayalite::sim::value::SimValue::from_value(ty, ::fayalite::__std::clone::Clone::clone(self)) | ||||
|                 } | ||||
|                 fn into_sim_value_with_type( | ||||
|                     self, | ||||
|                     ty: #target #type_generics, | ||||
|                 ) -> ::fayalite::sim::value::SimValue<#target #type_generics> { | ||||
|                     ::fayalite::sim::value::SimValue::from_value(ty, self) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         .to_tokens(tokens); | ||||
|         if let Some((cmp_eq,)) = cmp_eq { | ||||
|  |  | |||
|  | @ -866,6 +866,24 @@ impl ToTokens for ParsedEnum { | |||
|                     ][..]) | ||||
|                 } | ||||
|             } | ||||
|             #[automatically_derived] | ||||
|             impl #impl_generics ::fayalite::sim::value::ToSimValueWithType<#target #type_generics> | ||||
|             for #sim_value_ident #type_generics | ||||
|             #where_clause | ||||
|             { | ||||
|                 fn to_sim_value_with_type( | ||||
|                     &self, | ||||
|                     ty: #target #type_generics, | ||||
|                 ) -> ::fayalite::sim::value::SimValue<#target #type_generics> { | ||||
|                     ::fayalite::sim::value::SimValue::from_value(ty, ::fayalite::__std::clone::Clone::clone(self)) | ||||
|                 } | ||||
|                 fn into_sim_value_with_type( | ||||
|                     self, | ||||
|                     ty: #target #type_generics, | ||||
|                 ) -> ::fayalite::sim::value::SimValue<#target #type_generics> { | ||||
|                     ::fayalite::sim::value::SimValue::from_value(ty, self) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         .to_tokens(tokens); | ||||
|         if let (None, MaybeParsed::Parsed(generics)) = (no_static, &self.generics) { | ||||
|  | @ -921,6 +939,34 @@ impl ToTokens for ParsedEnum { | |||
|                     const MASK_TYPE_PROPERTIES: ::fayalite::ty::TypeProperties = | ||||
|                         <::fayalite::int::Bool as ::fayalite::ty::StaticType>::TYPE_PROPERTIES; | ||||
|                 } | ||||
|                 #[automatically_derived] | ||||
|                 impl #static_impl_generics ::fayalite::sim::value::ToSimValue | ||||
|                 for #sim_value_ident #static_type_generics | ||||
|                 #static_where_clause | ||||
|                 { | ||||
|                     type Type = #target #static_type_generics; | ||||
| 
 | ||||
|                     fn to_sim_value( | ||||
|                         &self, | ||||
|                     ) -> ::fayalite::sim::value::SimValue< | ||||
|                         <Self as ::fayalite::sim::value::ToSimValue>::Type, | ||||
|                     > { | ||||
|                         ::fayalite::sim::value::SimValue::from_value( | ||||
|                             ::fayalite::ty::StaticType::TYPE, | ||||
|                             ::fayalite::__std::clone::Clone::clone(self), | ||||
|                         ) | ||||
|                     } | ||||
|                     fn into_sim_value( | ||||
|                         self, | ||||
|                     ) -> ::fayalite::sim::value::SimValue< | ||||
|                         <Self as ::fayalite::sim::value::ToSimValue>::Type, | ||||
|                     > { | ||||
|                         ::fayalite::sim::value::SimValue::from_value( | ||||
|                             ::fayalite::ty::StaticType::TYPE, | ||||
|                             self, | ||||
|                         ) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             .to_tokens(tokens); | ||||
|         } | ||||
|  |  | |||
|  | @ -93,6 +93,7 @@ mod kw { | |||
|     custom_keyword!(output); | ||||
|     custom_keyword!(reg_builder); | ||||
|     custom_keyword!(reset); | ||||
|     custom_keyword!(sim); | ||||
|     custom_keyword!(skip); | ||||
|     custom_keyword!(target); | ||||
|     custom_keyword!(wire); | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ use std::{borrow::Borrow, convert::Infallible}; | |||
| use syn::{ | ||||
|     fold::{fold_expr, fold_expr_lit, fold_expr_unary, fold_local, fold_stmt, Fold}, | ||||
|     parenthesized, | ||||
|     parse::{Nothing, Parse, ParseStream}, | ||||
|     parse::{Parse, ParseStream}, | ||||
|     parse_quote, parse_quote_spanned, | ||||
|     spanned::Spanned, | ||||
|     token::Paren, | ||||
|  | @ -27,6 +27,13 @@ use syn::{ | |||
| mod expand_aggregate_literals; | ||||
| mod expand_match; | ||||
| 
 | ||||
| options! { | ||||
|     #[options = ExprOptions] | ||||
|     pub(crate) enum ExprOption { | ||||
|         Sim(sim), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| options! { | ||||
|     pub(crate) enum LetFnKind { | ||||
|         Input(input), | ||||
|  | @ -952,7 +959,7 @@ with_debug_clone_and_fold! { | |||
|     #[allow(dead_code)] | ||||
|     pub(crate) struct HdlLet<Kind = HdlLetKind> { | ||||
|         pub(crate) attrs: Vec<Attribute>, | ||||
|         pub(crate) hdl_attr: HdlAttr<Nothing, kw::hdl>, | ||||
|         pub(crate) hdl_attr: HdlAttr<syn::parse::Nothing, kw::hdl>, | ||||
|         pub(crate) let_token: Token![let], | ||||
|         pub(crate) mut_token: Option<Token![mut]>, | ||||
|         pub(crate) name: Ident, | ||||
|  | @ -1173,7 +1180,7 @@ impl Visitor<'_> { | |||
|             Some(_) => {} | ||||
|         } | ||||
|     } | ||||
|     fn process_hdl_if(&mut self, hdl_attr: HdlAttr<Nothing, kw::hdl>, expr_if: ExprIf) -> Expr { | ||||
|     fn process_hdl_if(&mut self, hdl_attr: HdlAttr<ExprOptions, kw::hdl>, expr_if: ExprIf) -> Expr { | ||||
|         let ExprIf { | ||||
|             attrs, | ||||
|             if_token, | ||||
|  | @ -1181,10 +1188,10 @@ impl Visitor<'_> { | |||
|             then_branch, | ||||
|             else_branch, | ||||
|         } = expr_if; | ||||
|         self.require_normal_module_or_fn(if_token); | ||||
|         let else_expr = else_branch.unzip().1.map(|else_expr| match *else_expr { | ||||
|             Expr::If(expr_if) => self.process_hdl_if(hdl_attr.clone(), expr_if), | ||||
|             expr => expr, | ||||
|         let (else_token, else_expr) = else_branch.unzip(); | ||||
|         let else_expr = else_expr.map(|else_expr| match *else_expr { | ||||
|             Expr::If(expr_if) => Box::new(self.process_hdl_if(hdl_attr.clone(), expr_if)), | ||||
|             _ => else_expr, | ||||
|         }); | ||||
|         if let Expr::Let(ExprLet { | ||||
|             attrs: let_attrs, | ||||
|  | @ -1206,7 +1213,19 @@ impl Visitor<'_> { | |||
|                 }, | ||||
|             ); | ||||
|         } | ||||
|         if let Some(else_expr) = else_expr { | ||||
|         let ExprOptions { sim } = hdl_attr.body; | ||||
|         if sim.is_some() { | ||||
|             ExprIf { | ||||
|                 attrs, | ||||
|                 if_token, | ||||
|                 cond: parse_quote_spanned! {if_token.span=> | ||||
|                     *::fayalite::sim::value::SimValue::<::fayalite::int::Bool>::value(&::fayalite::sim::value::ToSimValue::into_sim_value(#cond)) | ||||
|                 }, | ||||
|                 then_branch, | ||||
|                 else_branch: else_token.zip(else_expr), | ||||
|             } | ||||
|             .into() | ||||
|         } else if let Some(else_expr) = else_expr { | ||||
|             parse_quote_spanned! {if_token.span=> | ||||
|                 #(#attrs)* | ||||
|                 { | ||||
|  | @ -1675,7 +1694,7 @@ impl Fold for Visitor<'_> { | |||
|     fn fold_local(&mut self, mut let_stmt: Local) -> Local { | ||||
|         match self | ||||
|             .errors | ||||
|             .ok(HdlAttr::<Nothing, kw::hdl>::parse_and_leave_attr( | ||||
|             .ok(HdlAttr::<ExprOptions, kw::hdl>::parse_and_leave_attr( | ||||
|                 &let_stmt.attrs, | ||||
|             )) { | ||||
|             None => return empty_let(), | ||||
|  | @ -1694,10 +1713,11 @@ impl Fold for Visitor<'_> { | |||
|             subpat: None, | ||||
|         }) = pat | ||||
|         else { | ||||
|             let hdl_attr = HdlAttr::<Nothing, kw::hdl>::parse_and_take_attr(&mut let_stmt.attrs) | ||||
|                 .ok() | ||||
|                 .flatten() | ||||
|                 .expect("already checked above"); | ||||
|             let hdl_attr = | ||||
|                 HdlAttr::<ExprOptions, kw::hdl>::parse_and_take_attr(&mut let_stmt.attrs) | ||||
|                     .ok() | ||||
|                     .flatten() | ||||
|                     .expect("already checked above"); | ||||
|             let let_stmt = fold_local(self, let_stmt); | ||||
|             return self.process_hdl_let_pat(hdl_attr, let_stmt); | ||||
|         }; | ||||
|  |  | |||
|  | @ -1,45 +1,97 @@ | |||
| // SPDX-License-Identifier: LGPL-3.0-or-later
 | ||||
| // See Notices.txt for copyright information
 | ||||
| use crate::{kw, module::transform_body::Visitor, HdlAttr}; | ||||
| use crate::{ | ||||
|     kw, | ||||
|     module::transform_body::{ExprOptions, Visitor}, | ||||
|     HdlAttr, | ||||
| }; | ||||
| use quote::{format_ident, quote_spanned}; | ||||
| use syn::{ | ||||
|     parse::Nothing, parse_quote, parse_quote_spanned, spanned::Spanned, Expr, ExprArray, ExprPath, | ||||
|     ExprRepeat, ExprStruct, ExprTuple, FieldValue, TypePath, | ||||
|     parse_quote_spanned, spanned::Spanned, Expr, ExprArray, ExprPath, ExprRepeat, ExprStruct, | ||||
|     ExprTuple, FieldValue, TypePath, | ||||
| }; | ||||
| 
 | ||||
| impl Visitor<'_> { | ||||
|     pub(crate) fn process_hdl_array( | ||||
|         &mut self, | ||||
|         hdl_attr: HdlAttr<Nothing, kw::hdl>, | ||||
|         hdl_attr: HdlAttr<ExprOptions, kw::hdl>, | ||||
|         mut expr_array: ExprArray, | ||||
|     ) -> Expr { | ||||
|         self.require_normal_module_or_fn(hdl_attr); | ||||
|         for elem in &mut expr_array.elems { | ||||
|             *elem = parse_quote_spanned! {elem.span()=> | ||||
|                 ::fayalite::expr::ToExpr::to_expr(&(#elem)) | ||||
|             }; | ||||
|         let ExprOptions { sim } = hdl_attr.body; | ||||
|         let span = hdl_attr.kw.span; | ||||
|         if sim.is_some() { | ||||
|             for elem in &mut expr_array.elems { | ||||
|                 *elem = parse_quote_spanned! {elem.span()=> | ||||
|                     ::fayalite::sim::value::ToSimValue::to_sim_value(&(#elem)) | ||||
|                 }; | ||||
|             } | ||||
|             parse_quote_spanned! {span=> | ||||
|                 ::fayalite::sim::value::ToSimValue::into_sim_value(#expr_array) | ||||
|             } | ||||
|         } else { | ||||
|             for elem in &mut expr_array.elems { | ||||
|                 *elem = parse_quote_spanned! {elem.span()=> | ||||
|                     ::fayalite::expr::ToExpr::to_expr(&(#elem)) | ||||
|                 }; | ||||
|             } | ||||
|             parse_quote_spanned! {span=> | ||||
|                 ::fayalite::expr::ToExpr::to_expr(&#expr_array) | ||||
|             } | ||||
|         } | ||||
|         parse_quote! {::fayalite::expr::ToExpr::to_expr(&#expr_array)} | ||||
|     } | ||||
|     pub(crate) fn process_hdl_repeat( | ||||
|         &mut self, | ||||
|         hdl_attr: HdlAttr<Nothing, kw::hdl>, | ||||
|         hdl_attr: HdlAttr<ExprOptions, kw::hdl>, | ||||
|         mut expr_repeat: ExprRepeat, | ||||
|     ) -> Expr { | ||||
|         self.require_normal_module_or_fn(hdl_attr); | ||||
|         let repeated_value = &expr_repeat.expr; | ||||
|         *expr_repeat.expr = parse_quote_spanned! {repeated_value.span()=> | ||||
|             ::fayalite::expr::ToExpr::to_expr(&(#repeated_value)) | ||||
|         }; | ||||
|         parse_quote! {::fayalite::expr::ToExpr::to_expr(&#expr_repeat)} | ||||
|         let ExprOptions { sim } = hdl_attr.body; | ||||
|         let span = hdl_attr.kw.span; | ||||
|         if sim.is_some() { | ||||
|             *expr_repeat.expr = parse_quote_spanned! {repeated_value.span()=> | ||||
|                 ::fayalite::sim::value::ToSimValue::to_sim_value(&(#repeated_value)) | ||||
|             }; | ||||
|             parse_quote_spanned! {span=> | ||||
|                 ::fayalite::sim::value::ToSimValue::into_sim_value(#expr_repeat) | ||||
|             } | ||||
|         } else { | ||||
|             *expr_repeat.expr = parse_quote_spanned! {repeated_value.span()=> | ||||
|                 ::fayalite::expr::ToExpr::to_expr(&(#repeated_value)) | ||||
|             }; | ||||
|             parse_quote_spanned! {span=> | ||||
|                 ::fayalite::expr::ToExpr::to_expr(&#expr_repeat) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     pub(crate) fn process_hdl_struct( | ||||
|         &mut self, | ||||
|         hdl_attr: HdlAttr<Nothing, kw::hdl>, | ||||
|         expr_struct: ExprStruct, | ||||
|         hdl_attr: HdlAttr<ExprOptions, kw::hdl>, | ||||
|         mut expr_struct: ExprStruct, | ||||
|     ) -> Expr { | ||||
|         self.require_normal_module_or_fn(&hdl_attr); | ||||
|         let name_span = expr_struct.path.segments.last().unwrap().ident.span(); | ||||
|         let ExprOptions { sim } = hdl_attr.body; | ||||
|         if sim.is_some() { | ||||
|             let ty_path = TypePath { | ||||
|                 qself: expr_struct.qself.take(), | ||||
|                 path: expr_struct.path, | ||||
|             }; | ||||
|             expr_struct.path = parse_quote_spanned! {name_span=> | ||||
|                 __SimValue::<#ty_path> | ||||
|             }; | ||||
|             for field in &mut expr_struct.fields { | ||||
|                 let expr = &field.expr; | ||||
|                 field.expr = parse_quote_spanned! {field.member.span()=> | ||||
|                     ::fayalite::sim::value::ToSimValue::to_sim_value(&(#expr)) | ||||
|                 }; | ||||
|             } | ||||
|             return parse_quote_spanned! {name_span=> | ||||
|                 { | ||||
|                     type __SimValue<T> = <T as ::fayalite::ty::Type>::SimValue; | ||||
|                     let value: ::fayalite::sim::value::SimValue<#ty_path> = ::fayalite::sim::value::ToSimValue::into_sim_value(#expr_struct); | ||||
|                     value | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|         let builder_ident = format_ident!("__builder", span = name_span); | ||||
|         let empty_builder = if expr_struct.qself.is_some() | ||||
|             || expr_struct | ||||
|  | @ -91,12 +143,23 @@ impl Visitor<'_> { | |||
|     } | ||||
|     pub(crate) fn process_hdl_tuple( | ||||
|         &mut self, | ||||
|         hdl_attr: HdlAttr<Nothing, kw::hdl>, | ||||
|         expr_tuple: ExprTuple, | ||||
|         hdl_attr: HdlAttr<ExprOptions, kw::hdl>, | ||||
|         mut expr_tuple: ExprTuple, | ||||
|     ) -> Expr { | ||||
|         self.require_normal_module_or_fn(hdl_attr); | ||||
|         parse_quote_spanned! {expr_tuple.span()=> | ||||
|             ::fayalite::expr::ToExpr::to_expr(&#expr_tuple) | ||||
|         let ExprOptions { sim } = hdl_attr.body; | ||||
|         if sim.is_some() { | ||||
|             for element in &mut expr_tuple.elems { | ||||
|                 *element = parse_quote_spanned! {element.span()=> | ||||
|                     &(#element) | ||||
|                 }; | ||||
|             } | ||||
|             parse_quote_spanned! {expr_tuple.span()=> | ||||
|                 ::fayalite::sim::value::ToSimValue::into_sim_value(#expr_tuple) | ||||
|             } | ||||
|         } else { | ||||
|             parse_quote_spanned! {expr_tuple.span()=> | ||||
|                 ::fayalite::expr::ToExpr::to_expr(&#expr_tuple) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -3,7 +3,9 @@ | |||
| use crate::{ | ||||
|     fold::{impl_fold, DoFold}, | ||||
|     kw, | ||||
|     module::transform_body::{empty_let, with_debug_clone_and_fold, wrap_ty_with_expr, Visitor}, | ||||
|     module::transform_body::{ | ||||
|         empty_let, with_debug_clone_and_fold, wrap_ty_with_expr, ExprOptions, Visitor, | ||||
|     }, | ||||
|     Errors, HdlAttr, PairsIterExt, | ||||
| }; | ||||
| use proc_macro2::{Span, TokenStream}; | ||||
|  | @ -11,7 +13,6 @@ use quote::{format_ident, quote_spanned, ToTokens, TokenStreamExt}; | |||
| use std::collections::BTreeSet; | ||||
| use syn::{ | ||||
|     fold::{fold_arm, fold_expr_match, fold_local, fold_pat, Fold}, | ||||
|     parse::Nothing, | ||||
|     parse_quote_spanned, | ||||
|     punctuated::Punctuated, | ||||
|     spanned::Spanned, | ||||
|  | @ -981,7 +982,7 @@ impl<'a> VisitMatchPat<'a> for HdlLetPatVisitState<'a> { | |||
| impl Visitor<'_> { | ||||
|     pub(crate) fn process_hdl_let_pat( | ||||
|         &mut self, | ||||
|         _hdl_attr: HdlAttr<Nothing, kw::hdl>, | ||||
|         hdl_attr: HdlAttr<ExprOptions, kw::hdl>, | ||||
|         mut let_stmt: Local, | ||||
|     ) -> Local { | ||||
|         let span = let_stmt.let_token.span(); | ||||
|  | @ -996,7 +997,6 @@ impl Visitor<'_> { | |||
|             init, | ||||
|             semi_token, | ||||
|         } = let_stmt; | ||||
|         self.require_normal_module_or_fn(let_token); | ||||
|         let Some(syn::LocalInit { | ||||
|             eq_token, | ||||
|             expr, | ||||
|  | @ -1031,29 +1031,48 @@ impl Visitor<'_> { | |||
|             errors: _, | ||||
|             bindings, | ||||
|         } = state; | ||||
|         let retval = parse_quote_spanned! {span=> | ||||
|             let (#(#bindings,)* __scope,) = { | ||||
|                 type __MatchTy<T> = <T as ::fayalite::ty::Type>::MatchVariant; | ||||
|                 let __match_expr = ::fayalite::expr::ToExpr::to_expr(&(#expr)); | ||||
|                 ::fayalite::expr::check_match_expr(__match_expr, |__match_value, __infallible| { | ||||
|                     #[allow(unused_variables)] | ||||
|                     #check_let_stmt | ||||
|                     match __infallible {} | ||||
|                 }); | ||||
|                 let mut __match_iter = ::fayalite::module::match_(__match_expr); | ||||
|                 let ::fayalite::__std::option::Option::Some(__match_variant) = ::fayalite::__std::iter::Iterator::next(&mut __match_iter) else { | ||||
|                     ::fayalite::__std::unreachable!("#[hdl] let with uninhabited type"); | ||||
|         let ExprOptions { sim } = hdl_attr.body; | ||||
|         let retval = if sim.is_some() { | ||||
|             parse_quote_spanned! {span=> | ||||
|                 let (#(#bindings,)*) = { | ||||
|                     type __MatchTy<T> = <T as ::fayalite::ty::Type>::SimValue; | ||||
|                     let __match_value = ::fayalite::sim::value::ToSimValue::to_sim_value(&(#expr)); | ||||
|                     #let_token #pat #eq_token ::fayalite::sim::value::SimValue::into_value(__match_value) #semi_token | ||||
|                     (#(#bindings,)*) | ||||
|                 }; | ||||
|                 let ::fayalite::__std::option::Option::None = ::fayalite::__std::iter::Iterator::next(&mut __match_iter) else { | ||||
|                     ::fayalite::__std::unreachable!("#[hdl] let with refutable pattern"); | ||||
|                 }; | ||||
|                 let (__match_variant, __scope) = | ||||
|                     ::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope( | ||||
|                         __match_variant, | ||||
|             } | ||||
|         } else { | ||||
|             parse_quote_spanned! {span=> | ||||
|                 let (#(#bindings,)* __scope,) = { | ||||
|                     type __MatchTy<T> = <T as ::fayalite::ty::Type>::MatchVariant; | ||||
|                     let __match_expr = ::fayalite::expr::ToExpr::to_expr(&(#expr)); | ||||
|                     ::fayalite::expr::check_match_expr( | ||||
|                         __match_expr, | ||||
|                         |__match_value, __infallible| { | ||||
|                             #[allow(unused_variables)] | ||||
|                             #check_let_stmt | ||||
|                             match __infallible {} | ||||
|                         }, | ||||
|                     ); | ||||
|                 #let_token #pat #eq_token __match_variant #semi_token | ||||
|                 (#(#bindings,)* __scope,) | ||||
|             }; | ||||
|                     let mut __match_iter = ::fayalite::module::match_(__match_expr); | ||||
|                     let ::fayalite::__std::option::Option::Some(__match_variant) = | ||||
|                         ::fayalite::__std::iter::Iterator::next(&mut __match_iter) | ||||
|                     else { | ||||
|                         ::fayalite::__std::unreachable!("#[hdl] let with uninhabited type"); | ||||
|                     }; | ||||
|                     let ::fayalite::__std::option::Option::None = | ||||
|                         ::fayalite::__std::iter::Iterator::next(&mut __match_iter) | ||||
|                     else { | ||||
|                         ::fayalite::__std::unreachable!("#[hdl] let with refutable pattern"); | ||||
|                     }; | ||||
|                     let (__match_variant, __scope) = | ||||
|                         ::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope( | ||||
|                             __match_variant, | ||||
|                         ); | ||||
|                     #let_token #pat #eq_token __match_variant #semi_token | ||||
|                     (#(#bindings,)* __scope,) | ||||
|                 }; | ||||
|             } | ||||
|         }; | ||||
|         match retval { | ||||
|             syn::Stmt::Local(retval) => retval, | ||||
|  | @ -1062,7 +1081,7 @@ impl Visitor<'_> { | |||
|     } | ||||
|     pub(crate) fn process_hdl_match( | ||||
|         &mut self, | ||||
|         _hdl_attr: HdlAttr<Nothing, kw::hdl>, | ||||
|         hdl_attr: HdlAttr<ExprOptions, kw::hdl>, | ||||
|         expr_match: ExprMatch, | ||||
|     ) -> Expr { | ||||
|         let span = expr_match.match_token.span(); | ||||
|  | @ -1074,7 +1093,6 @@ impl Visitor<'_> { | |||
|             brace_token: _, | ||||
|             arms, | ||||
|         } = expr_match; | ||||
|         self.require_normal_module_or_fn(match_token); | ||||
|         let mut state = HdlMatchParseState { | ||||
|             match_span: span, | ||||
|             errors: &mut self.errors, | ||||
|  | @ -1083,24 +1101,37 @@ impl Visitor<'_> { | |||
|             arms.into_iter() | ||||
|                 .filter_map(|arm| MatchArm::parse(&mut state, arm).ok()), | ||||
|         ); | ||||
|         let expr = quote_spanned! {span=> | ||||
|             { | ||||
|                 type __MatchTy<T> = <T as ::fayalite::ty::Type>::MatchVariant; | ||||
|                 let __match_expr = ::fayalite::expr::ToExpr::to_expr(&(#expr)); | ||||
|                 ::fayalite::expr::check_match_expr(__match_expr, |__match_value, __infallible| { | ||||
|                     #[allow(unused_variables)] | ||||
|                     #check_match | ||||
|                 }); | ||||
|                 for __match_variant in ::fayalite::module::match_(__match_expr) { | ||||
|                     let (__match_variant, __scope) = | ||||
|                         ::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope( | ||||
|                             __match_variant, | ||||
|                         ); | ||||
|                     #match_token __match_variant { | ||||
|         let ExprOptions { sim } = hdl_attr.body; | ||||
|         let expr = if sim.is_some() { | ||||
|             quote_spanned! {span=> | ||||
|                 { | ||||
|                     type __MatchTy<T> = <T as ::fayalite::ty::Type>::SimValue; | ||||
|                     let __match_expr = ::fayalite::sim::value::ToSimValue::to_sim_value(&(#expr)); | ||||
|                     #match_token *__match_expr { | ||||
|                         #(#arms)* | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             quote_spanned! {span=> | ||||
|                 { | ||||
|                     type __MatchTy<T> = <T as ::fayalite::ty::Type>::MatchVariant; | ||||
|                     let __match_expr = ::fayalite::expr::ToExpr::to_expr(&(#expr)); | ||||
|                     ::fayalite::expr::check_match_expr(__match_expr, |__match_value, __infallible| { | ||||
|                         #[allow(unused_variables)] | ||||
|                         #check_match | ||||
|                     }); | ||||
|                     for __match_variant in ::fayalite::module::match_(__match_expr) { | ||||
|                         let (__match_variant, __scope) = | ||||
|                             ::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope( | ||||
|                                 __match_variant, | ||||
|                             ); | ||||
|                         #match_token __match_variant { | ||||
|                             #(#arms)* | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|         syn::parse2(expr).unwrap() | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue