WIP: use HdlOption[the_type_var] or UInt[123 + n] for creating types

This commit is contained in:
Jacob Lifshay 2024-08-07 03:16:29 -07:00
parent cd99dbc849
commit 5835b995a9
Signed by: programmerjake
SSH key fingerprint: SHA256:B1iRVvUJkvd7upMIiMqn6OyxvD2SgJkAH3ZnUOj6z+c
63 changed files with 13500 additions and 13210 deletions

View file

@ -2,11 +2,14 @@
// See Notices.txt for copyright information
use crate::{
fold::{impl_fold, DoFold},
hdl_type_common::{
known_items, ParseFailed, ParseTypes, ParsedGenerics, ParsedType, TypesParser,
},
is_hdl_attr, kw,
module::{check_name_conflicts_with_module_builder, ModuleIO, ModuleIOKind, ModuleKind},
options, Errors, HdlAttr,
};
use num_bigint::{BigInt, Sign};
use num_bigint::BigInt;
use proc_macro2::{Span, TokenStream};
use quote::{quote, quote_spanned, ToTokens};
use std::{borrow::Borrow, convert::Infallible};
@ -87,9 +90,9 @@ macro_rules! with_debug_clone_and_fold {
pub(crate) use with_debug_clone_and_fold;
with_debug_clone_and_fold! {
pub(crate) struct HdlLetKindIO<Kind = ModuleIOKind> {
pub(crate) struct HdlLetKindIO<Kind = ModuleIOKind, Ty = ParsedType> {
pub(crate) colon_token: Token![:],
pub(crate) ty: Box<Type>,
pub(crate) ty: Box<Ty>,
pub(crate) m: kw::m,
pub(crate) dot_token: Token![.],
pub(crate) kind: Kind,
@ -98,6 +101,32 @@ with_debug_clone_and_fold! {
}
}
impl<Kind: Clone, T: ParseTypes<I>, I> ParseTypes<HdlLetKindIO<Kind, I>> for HdlLetKindIO<Kind, T> {
fn parse_types(
input: &mut HdlLetKindIO<Kind, I>,
parser: &mut TypesParser<'_>,
) -> Result<Self, ParseFailed> {
let HdlLetKindIO {
colon_token,
ty,
m,
dot_token,
kind,
paren,
ty_expr,
} = input;
Ok(Self {
colon_token: *colon_token,
ty: ParseTypes::parse_types(ty, parser)?,
m: *m,
dot_token: *dot_token,
kind: kind.clone(),
paren: *paren,
ty_expr: ty_expr.clone(),
})
}
}
pub(crate) fn parse_single_fn_arg(input: ParseStream) -> syn::Result<Box<Expr>> {
let retval = input.parse()?;
let _: Option<Token![,]> = input.parse()?;
@ -145,17 +174,19 @@ impl<Kind: ToTokens> HdlLetKindToTokens for HdlLetKindIO<Kind> {
#[derive(Clone, Debug)]
pub(crate) struct HdlLetKindInstance {
pub(crate) m: kw::m,
pub(crate) dot_token: Token![.],
pub(crate) instance: kw::instance,
pub(crate) paren: Paren,
pub(crate) module: Box<Expr>,
}
impl ParseTypes<Self> for HdlLetKindInstance {
fn parse_types(input: &mut Self, _parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
Ok(input.clone())
}
}
impl_fold! {
struct HdlLetKindInstance<> {
m: kw::m,
dot_token: Token![.],
instance: kw::instance,
paren: Paren,
module: Box<Expr>,
@ -167,14 +198,10 @@ impl HdlLetKindToTokens for HdlLetKindInstance {
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
let Self {
m,
dot_token,
instance,
paren,
module,
} = self;
m.to_tokens(tokens);
dot_token.to_tokens(tokens);
instance.to_tokens(tokens);
paren.surround(tokens, |tokens| module.to_tokens(tokens));
}
@ -381,19 +408,21 @@ make_builder_method_enum! {
#[derive(Clone, Debug)]
pub(crate) struct HdlLetKindRegBuilder {
pub(crate) ty: Option<(Token![:], Box<Type>)>,
pub(crate) m: kw::m,
pub(crate) dot_token: Token![.],
pub(crate) reg_builder: kw::reg_builder,
pub(crate) reg_builder_paren: Paren,
pub(crate) clock_domain: Option<RegBuilderClockDomain>,
pub(crate) reset: RegBuilderReset,
}
impl ParseTypes<Self> for HdlLetKindRegBuilder {
fn parse_types(input: &mut Self, _parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
Ok(input.clone())
}
}
impl_fold! {
struct HdlLetKindRegBuilder<> {
ty: Option<(Token![:], Box<Type>)>,
m: kw::m,
dot_token: Token![.],
reg_builder: kw::reg_builder,
reg_builder_paren: Paren,
clock_domain: Option<RegBuilderClockDomain>,
@ -406,10 +435,10 @@ impl HdlLetKindRegBuilder {
input: ParseStream,
parsed_ty: Option<(Token![:], Box<Type>)>,
_after_ty: Token![=],
m: kw::m,
dot_token: Token![.],
m_dot: Option<(kw::m, Token![.])>,
reg_builder: kw::reg_builder,
) -> syn::Result<Self> {
check_empty_m_dot(m_dot, reg_builder)?;
let _reg_builder_paren_inner;
let reg_builder_paren = parenthesized!(_reg_builder_paren_inner in input);
let mut clock_domain = None;
@ -430,8 +459,6 @@ impl HdlLetKindRegBuilder {
}
Ok(Self {
ty: parsed_ty,
m,
dot_token,
reg_builder,
reg_builder_paren,
clock_domain,
@ -451,15 +478,11 @@ impl HdlLetKindToTokens for HdlLetKindRegBuilder {
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
let Self {
ty: _,
m,
dot_token,
reg_builder,
reg_builder_paren,
clock_domain,
reset,
} = self;
m.to_tokens(tokens);
dot_token.to_tokens(tokens);
reg_builder.to_tokens(tokens);
reg_builder_paren.surround(tokens, |_tokens| {});
clock_domain.to_tokens(tokens);
@ -470,18 +493,20 @@ impl HdlLetKindToTokens for HdlLetKindRegBuilder {
#[derive(Clone, Debug)]
pub(crate) struct HdlLetKindWire {
pub(crate) ty: Option<(Token![:], Box<Type>)>,
pub(crate) m: kw::m,
pub(crate) dot_token: Token![.],
pub(crate) wire: kw::wire,
pub(crate) paren: Paren,
pub(crate) ty_expr: Option<Box<Expr>>,
}
impl ParseTypes<Self> for HdlLetKindWire {
fn parse_types(input: &mut Self, _parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
Ok(input.clone())
}
}
impl_fold! {
struct HdlLetKindWire<> {
ty: Option<(Token![:], Box<Type>)>,
m: kw::m,
dot_token: Token![.],
wire: kw::wire,
paren: Paren,
ty_expr: Option<Box<Expr>>,
@ -499,14 +524,10 @@ impl HdlLetKindToTokens for HdlLetKindWire {
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
let Self {
ty: _,
m,
dot_token,
wire,
paren,
ty_expr,
} = self;
m.to_tokens(tokens);
dot_token.to_tokens(tokens);
wire.to_tokens(tokens);
paren.surround(tokens, |tokens| ty_expr.to_tokens(tokens));
}
@ -627,16 +648,18 @@ impl ToTokens for MemoryFn {
#[derive(Clone, Debug)]
pub(crate) struct HdlLetKindMemory {
pub(crate) ty: Option<(Token![:], Box<Type>)>,
pub(crate) m: kw::m,
pub(crate) dot_token: Token![.],
pub(crate) memory_fn: MemoryFn,
}
impl ParseTypes<Self> for HdlLetKindMemory {
fn parse_types(input: &mut Self, _parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
Ok(input.clone())
}
}
impl_fold! {
struct HdlLetKindMemory<> {
ty: Option<(Token![:], Box<Type>)>,
m: kw::m,
dot_token: Token![.],
memory_fn: MemoryFn,
}
}
@ -650,14 +673,7 @@ impl HdlLetKindToTokens for HdlLetKindMemory {
}
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
let Self {
ty: _,
m,
dot_token,
memory_fn,
} = self;
m.to_tokens(tokens);
dot_token.to_tokens(tokens);
let Self { ty: _, memory_fn } = self;
memory_fn.to_tokens(tokens);
}
}
@ -667,22 +683,20 @@ impl HdlLetKindMemory {
input: ParseStream,
parsed_ty: Option<(Token![:], Box<Type>)>,
_after_ty: Token![=],
m: kw::m,
dot_token: Token![.],
m_dot: Option<(kw::m, Token![.])>,
memory_fn_name: MemoryFnName,
) -> syn::Result<Self> {
check_empty_m_dot(m_dot, memory_fn_name)?;
Ok(Self {
ty: parsed_ty,
m,
dot_token,
memory_fn: MemoryFn::parse_rest(input, memory_fn_name)?,
})
}
}
#[derive(Clone, Debug)]
pub(crate) enum HdlLetKind {
IO(HdlLetKindIO),
pub(crate) enum HdlLetKind<IOType = ParsedType> {
IO(HdlLetKindIO<ModuleIOKind, IOType>),
Instance(HdlLetKindInstance),
RegBuilder(HdlLetKindRegBuilder),
Wire(HdlLetKindWire),
@ -690,8 +704,8 @@ pub(crate) enum HdlLetKind {
}
impl_fold! {
enum HdlLetKind<> {
IO(HdlLetKindIO),
enum HdlLetKind<IOType,> {
IO(HdlLetKindIO<ModuleIOKind, IOType>),
Instance(HdlLetKindInstance),
RegBuilder(HdlLetKindRegBuilder),
Wire(HdlLetKindWire),
@ -699,6 +713,27 @@ impl_fold! {
}
}
impl<T: ParseTypes<I>, I> ParseTypes<HdlLetKind<I>> for HdlLetKind<T> {
fn parse_types(
input: &mut HdlLetKind<I>,
parser: &mut TypesParser<'_>,
) -> Result<Self, ParseFailed> {
match input {
HdlLetKind::IO(input) => ParseTypes::parse_types(input, parser).map(HdlLetKind::IO),
HdlLetKind::Instance(input) => {
ParseTypes::parse_types(input, parser).map(HdlLetKind::Instance)
}
HdlLetKind::RegBuilder(input) => {
ParseTypes::parse_types(input, parser).map(HdlLetKind::RegBuilder)
}
HdlLetKind::Wire(input) => ParseTypes::parse_types(input, parser).map(HdlLetKind::Wire),
HdlLetKind::Memory(input) => {
ParseTypes::parse_types(input, parser).map(HdlLetKind::Memory)
}
}
}
}
fn parsed_ty_or_err(
parsed_ty: Option<(Token![:], Box<Type>)>,
after_ty: Token![=],
@ -710,15 +745,15 @@ fn parsed_ty_or_err(
}
}
impl HdlLetKindIO {
impl HdlLetKindIO<ModuleIOKind, Type> {
fn rest_of_parse(
input: ParseStream,
parsed_ty: Option<(Token![:], Box<Type>)>,
after_ty: Token![=],
m: kw::m,
dot_token: Token![.],
m_dot: Option<(kw::m, Token![.])>,
kind: ModuleIOKind,
) -> syn::Result<Self> {
let (m, dot_token) = unwrap_m_dot(m_dot, kind)?;
let (colon_token, ty) = parsed_ty_or_err(parsed_ty, after_ty)?;
let paren_contents;
Ok(Self {
@ -733,7 +768,36 @@ impl HdlLetKindIO {
}
}
impl HdlLetKindParse for HdlLetKind {
fn check_empty_m_dot(m_dot: Option<(kw::m, Token![.])>, kind: impl ToTokens) -> syn::Result<()> {
if let Some((m, dot_token)) = m_dot {
Err(Error::new_spanned(
quote! {#m #dot_token #kind},
format_args!(
"{} is a free function, not a method of ModuleBuilder: try removing the `m.`",
kind.to_token_stream()
),
))
} else {
Ok(())
}
}
fn unwrap_m_dot(
m_dot: Option<(kw::m, Token![.])>,
kind: impl ToTokens,
) -> syn::Result<(kw::m, Token![.])> {
m_dot.ok_or_else(|| {
Error::new_spanned(
&kind,
format_args!(
"{} is a ModuleBuilder method, not a free function: try prefixing it with `m.`",
kind.to_token_stream()
),
)
})
}
impl HdlLetKindParse for HdlLetKind<Type> {
type ParsedTy = Option<(Token![:], Box<Type>)>;
fn parse_ty(input: ParseStream) -> syn::Result<Self::ParsedTy> {
@ -753,16 +817,20 @@ impl HdlLetKindParse for HdlLetKind {
after_ty: Token![=],
input: ParseStream,
) -> syn::Result<Self> {
let m = input.parse()?;
let dot_token = input.parse()?;
let m_dot = if input.peek(kw::m) && input.peek2(Token![.]) {
let m = input.parse()?;
let dot_token = input.parse()?;
Some((m, dot_token))
} else {
None
};
let kind: LetFnKind = input.parse()?;
match kind {
LetFnKind::Input(input_token) => HdlLetKindIO::rest_of_parse(
input,
parsed_ty,
after_ty,
m,
dot_token,
m_dot,
ModuleIOKind::Input(input_token),
)
.map(Self::IO),
@ -770,8 +838,7 @@ impl HdlLetKindParse for HdlLetKind {
input,
parsed_ty,
after_ty,
m,
dot_token,
m_dot,
ModuleIOKind::Output(output),
)
.map(Self::IO),
@ -782,30 +849,23 @@ impl HdlLetKindParse for HdlLetKind {
"type annotation not allowed for instance",
));
}
check_empty_m_dot(m_dot, kind)?;
let paren_contents;
Ok(Self::Instance(HdlLetKindInstance {
m,
dot_token,
instance,
paren: parenthesized!(paren_contents in input),
module: paren_contents.call(parse_single_fn_arg)?,
}))
}
LetFnKind::RegBuilder((reg_builder,)) => HdlLetKindRegBuilder::rest_of_parse(
input,
parsed_ty,
after_ty,
m,
dot_token,
reg_builder,
)
.map(Self::RegBuilder),
LetFnKind::RegBuilder((reg_builder,)) => {
HdlLetKindRegBuilder::rest_of_parse(input, parsed_ty, after_ty, m_dot, reg_builder)
.map(Self::RegBuilder)
}
LetFnKind::Wire((wire,)) => {
check_empty_m_dot(m_dot, wire)?;
let paren_contents;
Ok(Self::Wire(HdlLetKindWire {
ty: parsed_ty,
m,
dot_token,
wire,
paren: parenthesized!(paren_contents in input),
ty_expr: paren_contents.call(parse_optional_fn_arg)?,
@ -815,8 +875,7 @@ impl HdlLetKindParse for HdlLetKind {
input,
parsed_ty,
after_ty,
m,
dot_token,
m_dot,
MemoryFnName::Memory(fn_name),
)
.map(Self::Memory),
@ -824,8 +883,7 @@ impl HdlLetKindParse for HdlLetKind {
input,
parsed_ty,
after_ty,
m,
dot_token,
m_dot,
MemoryFnName::MemoryArray(fn_name),
)
.map(Self::Memory),
@ -833,8 +891,7 @@ impl HdlLetKindParse for HdlLetKind {
input,
parsed_ty,
after_ty,
m,
dot_token,
m_dot,
MemoryFnName::MemoryWithInit(fn_name),
)
.map(Self::Memory),
@ -878,6 +935,34 @@ with_debug_clone_and_fold! {
}
}
impl<T: ParseTypes<I>, I> ParseTypes<HdlLet<I>> for HdlLet<T> {
fn parse_types(
input: &mut HdlLet<I>,
parser: &mut TypesParser<'_>,
) -> Result<Self, ParseFailed> {
let HdlLet {
attrs,
hdl_attr,
let_token,
mut_token,
name,
eq_token,
kind,
semi_token,
} = input;
Ok(Self {
attrs: attrs.clone(),
hdl_attr: hdl_attr.clone(),
let_token: *let_token,
mut_token: *mut_token,
name: name.clone(),
eq_token: *eq_token,
kind: T::parse_types(kind, parser)?,
semi_token: *semi_token,
})
}
}
impl<Kind> HdlLet<Kind> {
pub(crate) fn try_map<Kind2, E>(
self,
@ -1006,7 +1091,7 @@ fn wrap_ty_with_expr(ty: impl ToTokens) -> Type {
fn unwrap_or_static_type(expr: Option<impl ToTokens>, span: Span) -> TokenStream {
expr.map(ToTokens::into_token_stream).unwrap_or_else(|| {
quote_spanned! {span=>
::fayalite::ty::StaticType::static_type()
::fayalite::ty::StaticType::TYPE
}
})
}
@ -1026,14 +1111,15 @@ impl<T: ToString> ToTokens for ImplicitName<T> {
}
}
struct Visitor {
struct Visitor<'a> {
module_kind: ModuleKind,
errors: Errors,
io: Vec<ModuleIO>,
block_depth: usize,
parsed_generics: &'a ParsedGenerics,
}
impl Visitor {
impl Visitor<'_> {
fn take_hdl_attr<T: Parse>(&mut self, attrs: &mut Vec<Attribute>) -> Option<HdlAttr<T>> {
self.errors.unwrap_or(
HdlAttr::parse_and_take_attr(attrs),
@ -1086,7 +1172,7 @@ impl Visitor {
parse_quote_spanned! {if_token.span=>
#(#attrs)*
{
let mut __scope = m.if_(#cond);
let mut __scope = ::fayalite::module::if_(#cond);
let _: () = #then_branch;
let mut __scope = __scope.else_();
let _: () = #else_expr;
@ -1096,7 +1182,7 @@ impl Visitor {
parse_quote_spanned! {if_token.span=>
#(#attrs)*
{
let mut __scope = m.if_(#cond);
let mut __scope = ::fayalite::module::if_(#cond);
let _: () = #then_branch;
}
}
@ -1157,8 +1243,6 @@ impl Visitor {
eq_token,
kind:
HdlLetKindInstance {
m,
dot_token,
instance,
paren,
module,
@ -1166,7 +1250,7 @@ impl Visitor {
semi_token,
} = hdl_let;
self.require_normal_module(instance);
let mut expr = quote! {#m #dot_token #instance};
let mut expr = instance.to_token_stream();
paren.surround(&mut expr, |expr| {
let name_str = ImplicitName {
name: &name,
@ -1191,11 +1275,9 @@ impl Visitor {
}
fn process_hdl_let_reg_builder(&mut self, hdl_let: HdlLet<HdlLetKindRegBuilder>) -> Local {
let name = &hdl_let.name;
let m = hdl_let.kind.m;
let dot = hdl_let.kind.dot_token;
let reg_builder = hdl_let.kind.reg_builder;
self.require_normal_module(reg_builder);
let mut expr = quote! {#m #dot #reg_builder};
let mut expr = reg_builder.to_token_stream();
hdl_let.kind.reg_builder_paren.surround(&mut expr, |expr| {
let name_str = ImplicitName {
name,
@ -1244,12 +1326,10 @@ impl Visitor {
}
fn process_hdl_let_wire(&mut self, hdl_let: HdlLet<HdlLetKindWire>) -> Local {
let name = &hdl_let.name;
let m = hdl_let.kind.m;
let dot = hdl_let.kind.dot_token;
let wire = hdl_let.kind.wire;
self.require_normal_module(wire);
let ty_expr = unwrap_or_static_type(hdl_let.kind.ty_expr.as_ref(), wire.span());
let mut expr = quote! {#m #dot #wire};
let mut expr = wire.to_token_stream();
hdl_let.kind.paren.surround(&mut expr, |expr| {
let name_str = ImplicitName {
name,
@ -1279,18 +1359,19 @@ impl Visitor {
}
fn process_hdl_let_memory(&mut self, hdl_let: HdlLet<HdlLetKindMemory>) -> Local {
let name = &hdl_let.name;
let m = hdl_let.kind.m;
let dot = hdl_let.kind.dot_token;
let memory_fn = hdl_let.kind.memory_fn;
let memory_fn_name = memory_fn.name();
self.require_normal_module(memory_fn_name);
let mut expr = quote! {#m #dot #memory_fn_name};
let mut expr = memory_fn_name.to_token_stream();
let (paren, arg) = match memory_fn {
MemoryFn::Memory {
memory,
paren,
ty_expr,
} => (paren, unwrap_or_static_type(ty_expr.as_ref(), memory.span())),
} => (
paren,
unwrap_or_static_type(ty_expr.as_ref(), memory.span()),
),
MemoryFn::MemoryArray {
memory_array,
paren,
@ -1377,16 +1458,17 @@ impl Visitor {
let value: BigInt = self
.errors
.ok(base10_digits.parse().map_err(|e| Error::new(span, e)))?;
let (negative, bytes) = match value.sign() {
Sign::Minus => (true, value.magnitude().to_bytes_le()),
Sign::NoSign => (false, vec![]),
Sign::Plus => (false, value.magnitude().to_bytes_le()),
let bytes = value.to_signed_bytes_le();
let path = if signed {
known_items::SInt(span).path
} else {
known_items::UInt(span).path
};
Some(parse_quote_spanned! {span=>
::fayalite::int::make_int_literal::<#signed, #width>(
#negative,
<#path<#width> as ::fayalite::int::BoolOrIntType>::le_bytes_to_expr_wrapping(
&[#(#bytes,)*],
).to_int_expr()
#width,
)
})
}
fn process_literal(&mut self, literal: ExprLit) -> Expr {
@ -1449,7 +1531,7 @@ fn empty_let() -> Local {
}
}
impl Fold for Visitor {
impl Fold for Visitor<'_> {
fn fold_item(&mut self, item: Item) -> Item {
// don't process item interiors
item
@ -1521,8 +1603,6 @@ impl Fold for Visitor {
Repeat => process_hdl_repeat,
Struct => process_hdl_struct,
Tuple => process_hdl_tuple,
Call => process_hdl_call,
Path => process_hdl_path,
}
}
}
@ -1536,11 +1616,16 @@ impl Fold for Visitor {
Some(None) => return fold_local(self, let_stmt),
Some(Some(HdlAttr { .. })) => {}
};
let hdl_let = syn::parse2::<HdlLet>(let_stmt.into_token_stream());
let hdl_let = syn::parse2::<HdlLet<HdlLetKind<Type>>>(let_stmt.into_token_stream());
let Some(hdl_let) = self.errors.ok(hdl_let) else {
return empty_let();
};
let hdl_let = hdl_let.do_fold(self);
let mut hdl_let = hdl_let.do_fold(self);
let Ok(hdl_let) =
TypesParser::run_with_errors(self.parsed_generics, &mut hdl_let, &mut self.errors)
else {
return empty_let();
};
self.process_hdl_let(hdl_let)
}
@ -1563,12 +1648,14 @@ impl Fold for Visitor {
pub(crate) fn transform_body(
module_kind: ModuleKind,
mut body: Box<Block>,
parsed_generics: &ParsedGenerics,
) -> syn::Result<(Box<Block>, Vec<ModuleIO>)> {
let mut visitor = Visitor {
module_kind,
errors: Errors::new(),
io: vec![],
block_depth: 0,
parsed_generics,
};
*body = syn::fold::fold_block(&mut visitor, *body);
visitor.errors.finish()?;