#[hdl] match works!
This commit is contained in:
parent
9887d70f41
commit
2d293ae87b
|
@ -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);
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue