#[hdl] match works!

This commit is contained in:
Jacob Lifshay 2024-09-19 23:51:49 -07:00
parent 9887d70f41
commit 2d293ae87b
Signed by: programmerjake
SSH key fingerprint: SHA256:B1iRVvUJkvd7upMIiMqn6OyxvD2SgJkAH3ZnUOj6z+c
4 changed files with 83 additions and 24 deletions

View file

@ -224,6 +224,7 @@ forward_fold!(syn::ExprPath => fold_expr_path);
forward_fold!(syn::ExprRepeat => fold_expr_repeat); forward_fold!(syn::ExprRepeat => fold_expr_repeat);
forward_fold!(syn::ExprStruct => fold_expr_struct); forward_fold!(syn::ExprStruct => fold_expr_struct);
forward_fold!(syn::ExprTuple => fold_expr_tuple); forward_fold!(syn::ExprTuple => fold_expr_tuple);
forward_fold!(syn::FieldPat => fold_field_pat);
forward_fold!(syn::Ident => fold_ident); forward_fold!(syn::Ident => fold_ident);
forward_fold!(syn::Member => fold_member); forward_fold!(syn::Member => fold_member);
forward_fold!(syn::Path => fold_path); forward_fold!(syn::Path => fold_path);

View file

@ -1,12 +1,12 @@
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
fold::impl_fold, fold::{impl_fold, DoFold},
module::transform_body::{with_debug_clone_and_fold, Visitor}, module::transform_body::{with_debug_clone_and_fold, Visitor},
Errors, HdlAttr, PairsIterExt, Errors, HdlAttr, PairsIterExt,
}; };
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::{format_ident, ToTokens, TokenStreamExt}; use quote::{format_ident, quote_spanned, ToTokens, TokenStreamExt};
use syn::{ use syn::{
fold::{fold_arm, fold_expr_match, fold_pat, Fold}, fold::{fold_arm, fold_expr_match, fold_pat, Fold},
parse::Nothing, parse::Nothing,
@ -130,6 +130,7 @@ impl MatchPatStructField {
with_debug_clone_and_fold! { with_debug_clone_and_fold! {
struct MatchPatStruct<> { struct MatchPatStruct<> {
match_span: Span,
path: Path, path: Path,
brace_token: Brace, brace_token: Brace,
fields: Punctuated<MatchPatStructField, Token![,]>, fields: Punctuated<MatchPatStructField, Token![,]>,
@ -140,12 +141,16 @@ with_debug_clone_and_fold! {
impl ToTokens for MatchPatStruct { impl ToTokens for MatchPatStruct {
fn to_tokens(&self, tokens: &mut TokenStream) { fn to_tokens(&self, tokens: &mut TokenStream) {
let Self { let Self {
match_span,
path, path,
brace_token, brace_token,
fields, fields,
rest, rest,
} = self; } = self;
path.to_tokens(tokens); quote_spanned! {*match_span=>
__MatchTy::<#path>
}
.to_tokens(tokens);
brace_token.surround(tokens, |tokens| { brace_token.surround(tokens, |tokens| {
fields.to_tokens(tokens); fields.to_tokens(tokens);
rest.to_tokens(tokens); rest.to_tokens(tokens);
@ -155,6 +160,7 @@ impl ToTokens for MatchPatStruct {
with_debug_clone_and_fold! { with_debug_clone_and_fold! {
struct MatchPatEnumVariant<> { struct MatchPatEnumVariant<> {
match_span: Span,
variant_path: Path, variant_path: Path,
enum_path: Path, enum_path: Path,
variant_name: Ident, variant_name: Ident,
@ -165,12 +171,16 @@ with_debug_clone_and_fold! {
impl ToTokens for MatchPatEnumVariant { impl ToTokens for MatchPatEnumVariant {
fn to_tokens(&self, tokens: &mut TokenStream) { fn to_tokens(&self, tokens: &mut TokenStream) {
let Self { let Self {
variant_path, match_span,
enum_path: _, variant_path: _,
variant_name: _, enum_path,
variant_name,
field, field,
} = self; } = self;
variant_path.to_tokens(tokens); quote_spanned! {*match_span=>
__MatchTy::<#enum_path>::#variant_name
}
.to_tokens(tokens);
if let Some((paren_token, field)) = field { if let Some((paren_token, field)) = field {
paren_token.surround(tokens, |tokens| field.to_tokens(tokens)); paren_token.surround(tokens, |tokens| field.to_tokens(tokens));
} }
@ -301,6 +311,7 @@ trait ParseMatchPat: Sized {
}) => Self::enum_variant( }) => Self::enum_variant(
state, state,
MatchPatEnumVariant { MatchPatEnumVariant {
match_span: state.match_span,
variant_path, variant_path,
enum_path, enum_path,
variant_name, variant_name,
@ -346,6 +357,7 @@ trait ParseMatchPat: Sized {
Self::enum_variant( Self::enum_variant(
state, state,
MatchPatEnumVariant { MatchPatEnumVariant {
match_span: state.match_span,
variant_path, variant_path,
enum_path, enum_path,
variant_name, variant_name,
@ -376,6 +388,7 @@ trait ParseMatchPat: Sized {
Self::struct_( Self::struct_(
state, state,
MatchPatStruct { MatchPatStruct {
match_span: state.match_span,
path, path,
brace_token, brace_token,
fields, fields,
@ -428,6 +441,7 @@ trait ParseMatchPat: Sized {
Self::enum_variant( Self::enum_variant(
state, state,
MatchPatEnumVariant { MatchPatEnumVariant {
match_span: state.match_span,
variant_path, variant_path,
enum_path, enum_path,
variant_name, variant_name,
@ -626,6 +640,44 @@ impl Fold for RewriteAsCheckMatch {
Pat::Ident(self.fold_pat_ident(pat_ident)) Pat::Ident(self.fold_pat_ident(pat_ident))
} }
}, },
Pat::Path(PatPath {
attrs: _,
qself,
path,
}) => match parse_enum_path(TypePath { qself, path }) {
Ok(EnumPath {
variant_path: _,
enum_path,
variant_name,
}) => parse_quote_spanned! {self.span=>
__MatchTy::<#enum_path>::#variant_name {}
},
Err(type_path) => parse_quote_spanned! {self.span=>
__MatchTy::<#type_path> {}
},
},
Pat::Struct(PatStruct {
attrs: _,
qself,
path,
brace_token,
fields,
rest,
}) => {
let type_path = TypePath { qself, path };
let path = parse_quote_spanned! {self.span=>
__MatchTy::<#type_path>
};
let fields = fields.do_fold(self);
Pat::Struct(PatStruct {
attrs: vec![],
qself: None,
path,
brace_token,
fields,
rest,
})
}
Pat::TupleStruct(PatTupleStruct { Pat::TupleStruct(PatTupleStruct {
attrs, attrs,
qself, qself,
@ -690,6 +742,7 @@ impl Fold for RewriteAsCheckMatch {
} }
struct HdlMatchParseState<'a> { struct HdlMatchParseState<'a> {
match_span: Span,
errors: &'a mut Errors, errors: &'a mut Errors,
} }
@ -710,13 +763,14 @@ impl Visitor<'_> {
} = expr_match; } = expr_match;
self.require_normal_module(match_token); self.require_normal_module(match_token);
let mut state = HdlMatchParseState { let mut state = HdlMatchParseState {
match_span: span,
errors: &mut self.errors, errors: &mut self.errors,
}; };
let arms = Vec::from_iter( let arms = Vec::from_iter(
arms.into_iter() arms.into_iter()
.filter_map(|arm| MatchArm::parse(&mut state, arm).ok()), .filter_map(|arm| MatchArm::parse(&mut state, arm).ok()),
); );
let expr = quote::quote_spanned! {span=> let expr = quote_spanned! {span=>
{ {
type __MatchTy<T> = <T as ::fayalite::ty::Type>::MatchVariant; type __MatchTy<T> = <T as ::fayalite::ty::Type>::MatchVariant;
let __match_expr = ::fayalite::expr::ToExpr::to_expr(&(#expr)); let __match_expr = ::fayalite::expr::ToExpr::to_expr(&(#expr));
@ -735,7 +789,6 @@ impl Visitor<'_> {
} }
} }
}; };
println!("{}", expr);
syn::parse2(expr).unwrap() syn::parse2(expr).unwrap()
} }
} }

View file

@ -21,7 +21,7 @@ use crate::{
wire::Wire, wire::Wire,
}; };
use bitvec::slice::BitSlice; use bitvec::slice::BitSlice;
use std::{fmt, ops::Deref}; use std::{convert::Infallible, fmt, ops::Deref};
pub mod ops; pub mod ops;
pub mod target; pub mod target;
@ -690,3 +690,10 @@ pub trait CastTo: ToExpr {
} }
impl<T: ToExpr + ?Sized> CastTo for T {} impl<T: ToExpr + ?Sized> CastTo for T {}
#[doc(hidden)]
pub fn check_match_expr<T: Type>(
_expr: Expr<T>,
_check_fn: impl FnOnce(T::MatchVariant, Infallible),
) {
}

View file

@ -662,7 +662,6 @@ circuit check_enum_literals:
}; };
} }
#[cfg(todo)]
#[hdl_module(outline_generated)] #[hdl_module(outline_generated)]
pub fn check_struct_enum_match() { pub fn check_struct_enum_match() {
#[hdl] #[hdl]
@ -688,7 +687,7 @@ pub fn check_struct_enum_match() {
match i2 { match i2 {
TestEnum::A => connect(o[2], 0_hdl_u8), TestEnum::A => connect(o[2], 0_hdl_u8),
TestEnum::B(v) => connect(o[2], v), TestEnum::B(v) => connect(o[2], v),
TestEnum::C(v) => connect_any(o[2], v[1]), TestEnum::C(v) => connect_any(o[2], v[1].cast_to(UInt[1])),
} }
#[hdl] #[hdl]
match i2 { match i2 {
@ -699,12 +698,11 @@ pub fn check_struct_enum_match() {
#[hdl] #[hdl]
match i2 { match i2 {
TestEnum::B(_) => connect(o[4], 1_hdl_u8), TestEnum::B(_) => connect(o[4], 1_hdl_u8),
TestEnum::C(v) => connect_any(o[4], v[2]), TestEnum::C(v) => connect_any(o[4], v[2].cast_to(UInt[1])),
_ => connect(o[4], 0_hdl_u8), _ => connect(o[4], 0_hdl_u8),
} }
} }
#[cfg(todo)]
#[test] #[test]
fn test_struct_enum_match() { fn test_struct_enum_match() {
let _n = SourceLocation::normalize_files_for_tests(); let _n = SourceLocation::normalize_files_for_tests();
@ -715,14 +713,14 @@ fn test_struct_enum_match() {
m => m =>
"/test/check_struct_enum_match.fir": r"FIRRTL version 3.2.0 "/test/check_struct_enum_match.fir": r"FIRRTL version 3.2.0
circuit check_struct_enum_match: circuit check_struct_enum_match:
type Ty0 = {|None, Some: UInt<8>|} type Ty0 = {|HdlNone, HdlSome: UInt<8>|}
type Ty1 = {|A, B: UInt<8>, C: UInt<1>[3]|} type Ty1 = {|A, B: UInt<8>, C: UInt<1>[3]|}
module check_struct_enum_match: @[module-XXXXXXXXXX.rs 1:1] module check_struct_enum_match: @[module-XXXXXXXXXX.rs 1:1]
input i1: Ty0 @[module-XXXXXXXXXX.rs 2:1] input i1: Ty0 @[module-XXXXXXXXXX.rs 2:1]
input i2: Ty1 @[module-XXXXXXXXXX.rs 3:1] input i2: Ty1 @[module-XXXXXXXXXX.rs 3:1]
output o: UInt<8>[5] @[module-XXXXXXXXXX.rs 4:1] output o: UInt<8>[5] @[module-XXXXXXXXXX.rs 4:1]
match i1: @[module-XXXXXXXXXX.rs 5:1] match i1: @[module-XXXXXXXXXX.rs 5:1]
None: HdlNone:
match i2: @[module-XXXXXXXXXX.rs 6:1] match i2: @[module-XXXXXXXXXX.rs 6:1]
A: A:
connect o[0], UInt<8>(0h17) @[module-XXXXXXXXXX.rs 7:1] connect o[0], UInt<8>(0h17) @[module-XXXXXXXXXX.rs 7:1]
@ -730,12 +728,12 @@ circuit check_struct_enum_match:
connect o[0], add(_match_arm_value, UInt<8>(0h2)) @[module-XXXXXXXXXX.rs 8:1] connect o[0], add(_match_arm_value, UInt<8>(0h2)) @[module-XXXXXXXXXX.rs 8:1]
C(_match_arm_value_1): C(_match_arm_value_1):
connect o[0], UInt<8>(0h17) @[module-XXXXXXXXXX.rs 7:1] connect o[0], UInt<8>(0h17) @[module-XXXXXXXXXX.rs 7:1]
Some(_match_arm_value_2): HdlSome(_match_arm_value_2):
connect o[0], _match_arm_value_2 @[module-XXXXXXXXXX.rs 9:1] connect o[0], _match_arm_value_2 @[module-XXXXXXXXXX.rs 9:1]
match i1: @[module-XXXXXXXXXX.rs 10:1] match i1: @[module-XXXXXXXXXX.rs 10:1]
None: HdlNone:
connect o[1], UInt<8>(0h0) @[module-XXXXXXXXXX.rs 11:1] connect o[1], UInt<8>(0h0) @[module-XXXXXXXXXX.rs 11:1]
Some(_match_arm_value_3): HdlSome(_match_arm_value_3):
connect o[1], UInt<8>(0h1) @[module-XXXXXXXXXX.rs 12:1] connect o[1], UInt<8>(0h1) @[module-XXXXXXXXXX.rs 12:1]
match i2: @[module-XXXXXXXXXX.rs 13:1] match i2: @[module-XXXXXXXXXX.rs 13:1]
A: A:
@ -768,7 +766,7 @@ circuit check_struct_enum_match:
m => m =>
"/test/check_struct_enum_match.fir": r"FIRRTL version 3.2.0 "/test/check_struct_enum_match.fir": r"FIRRTL version 3.2.0
circuit check_struct_enum_match: circuit check_struct_enum_match:
type Ty0 = {|None, Some|} type Ty0 = {|HdlNone, HdlSome|}
type Ty1 = {tag: Ty0, body: UInt<8>} type Ty1 = {tag: Ty0, body: UInt<8>}
type Ty2 = {|A, B, C|} type Ty2 = {|A, B, C|}
type Ty3 = {tag: Ty2, body: UInt<8>} type Ty3 = {tag: Ty2, body: UInt<8>}
@ -777,7 +775,7 @@ circuit check_struct_enum_match:
input i2: Ty3 @[module-XXXXXXXXXX.rs 3:1] input i2: Ty3 @[module-XXXXXXXXXX.rs 3:1]
output o: UInt<8>[5] @[module-XXXXXXXXXX.rs 4:1] output o: UInt<8>[5] @[module-XXXXXXXXXX.rs 4:1]
match i1.tag: @[module-XXXXXXXXXX.rs 5:1] match i1.tag: @[module-XXXXXXXXXX.rs 5:1]
None: HdlNone:
match i2.tag: @[module-XXXXXXXXXX.rs 6:1] match i2.tag: @[module-XXXXXXXXXX.rs 6:1]
A: A:
connect o[0], UInt<8>(0h17) @[module-XXXXXXXXXX.rs 7:1] connect o[0], UInt<8>(0h17) @[module-XXXXXXXXXX.rs 7:1]
@ -785,12 +783,12 @@ circuit check_struct_enum_match:
connect o[0], add(bits(i2.body, 7, 0), UInt<8>(0h2)) @[module-XXXXXXXXXX.rs 8:1] connect o[0], add(bits(i2.body, 7, 0), UInt<8>(0h2)) @[module-XXXXXXXXXX.rs 8:1]
C: C:
connect o[0], UInt<8>(0h17) @[module-XXXXXXXXXX.rs 7:1] connect o[0], UInt<8>(0h17) @[module-XXXXXXXXXX.rs 7:1]
Some: HdlSome:
connect o[0], bits(i1.body, 7, 0) @[module-XXXXXXXXXX.rs 9:1] connect o[0], bits(i1.body, 7, 0) @[module-XXXXXXXXXX.rs 9:1]
match i1.tag: @[module-XXXXXXXXXX.rs 10:1] match i1.tag: @[module-XXXXXXXXXX.rs 10:1]
None: HdlNone:
connect o[1], UInt<8>(0h0) @[module-XXXXXXXXXX.rs 11:1] connect o[1], UInt<8>(0h0) @[module-XXXXXXXXXX.rs 11:1]
Some: HdlSome:
connect o[1], UInt<8>(0h1) @[module-XXXXXXXXXX.rs 12:1] connect o[1], UInt<8>(0h1) @[module-XXXXXXXXXX.rs 12:1]
match i2.tag: @[module-XXXXXXXXXX.rs 13:1] match i2.tag: @[module-XXXXXXXXXX.rs 13:1]
A: A: