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