add support for incomplete_wire -- a wire that you can supply the type of later
This commit is contained in:
		
							parent
							
								
									ff94dda922
								
							
						
					
					
						commit
						df55a514e4
					
				
					 5 changed files with 231 additions and 8 deletions
				
			
		|  | @ -65,6 +65,7 @@ mod kw { | ||||||
|     custom_keyword!(hdl); |     custom_keyword!(hdl); | ||||||
|     custom_keyword!(hdl_module); |     custom_keyword!(hdl_module); | ||||||
|     custom_keyword!(input); |     custom_keyword!(input); | ||||||
|  |     custom_keyword!(incomplete_wire); | ||||||
|     custom_keyword!(instance); |     custom_keyword!(instance); | ||||||
|     custom_keyword!(m); |     custom_keyword!(m); | ||||||
|     custom_keyword!(memory); |     custom_keyword!(memory); | ||||||
|  |  | ||||||
|  | @ -34,6 +34,7 @@ options! { | ||||||
|         Instance(instance), |         Instance(instance), | ||||||
|         RegBuilder(reg_builder), |         RegBuilder(reg_builder), | ||||||
|         Wire(wire), |         Wire(wire), | ||||||
|  |         IncompleteWire(incomplete_wire), | ||||||
|         Memory(memory), |         Memory(memory), | ||||||
|         MemoryArray(memory_array), |         MemoryArray(memory_array), | ||||||
|         MemoryWithInit(memory_with_init), |         MemoryWithInit(memory_with_init), | ||||||
|  | @ -533,6 +534,41 @@ impl HdlLetKindToTokens for HdlLetKindWire { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | options! { | ||||||
|  |     pub(crate) enum LetFnKindIncomplete { | ||||||
|  |         IncompleteWire(incomplete_wire), | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug)] | ||||||
|  | pub(crate) struct HdlLetKindIncomplete { | ||||||
|  |     pub(crate) kind: LetFnKindIncomplete, | ||||||
|  |     pub(crate) paren: Paren, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl ParseTypes<Self> for HdlLetKindIncomplete { | ||||||
|  |     fn parse_types(input: &mut Self, _parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> { | ||||||
|  |         Ok(input.clone()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl_fold! { | ||||||
|  |     struct HdlLetKindIncomplete<> { | ||||||
|  |         kind: LetFnKindIncomplete, | ||||||
|  |         paren: Paren, | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl HdlLetKindToTokens for HdlLetKindIncomplete { | ||||||
|  |     fn ty_to_tokens(&self, _tokens: &mut TokenStream) {} | ||||||
|  | 
 | ||||||
|  |     fn expr_to_tokens(&self, tokens: &mut TokenStream) { | ||||||
|  |         let Self { kind, paren } = self; | ||||||
|  |         kind.to_tokens(tokens); | ||||||
|  |         paren.surround(tokens, |_| {}); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| options! { | options! { | ||||||
|     pub(crate) enum MemoryFnName { |     pub(crate) enum MemoryFnName { | ||||||
|         Memory(memory), |         Memory(memory), | ||||||
|  | @ -697,6 +733,7 @@ impl HdlLetKindMemory { | ||||||
| #[derive(Clone, Debug)] | #[derive(Clone, Debug)] | ||||||
| pub(crate) enum HdlLetKind<IOType = ParsedType> { | pub(crate) enum HdlLetKind<IOType = ParsedType> { | ||||||
|     IO(HdlLetKindIO<ModuleIOKind, IOType>), |     IO(HdlLetKindIO<ModuleIOKind, IOType>), | ||||||
|  |     Incomplete(HdlLetKindIncomplete), | ||||||
|     Instance(HdlLetKindInstance), |     Instance(HdlLetKindInstance), | ||||||
|     RegBuilder(HdlLetKindRegBuilder), |     RegBuilder(HdlLetKindRegBuilder), | ||||||
|     Wire(HdlLetKindWire), |     Wire(HdlLetKindWire), | ||||||
|  | @ -706,6 +743,7 @@ pub(crate) enum HdlLetKind<IOType = ParsedType> { | ||||||
| impl_fold! { | impl_fold! { | ||||||
|     enum HdlLetKind<IOType,> { |     enum HdlLetKind<IOType,> { | ||||||
|         IO(HdlLetKindIO<ModuleIOKind, IOType>), |         IO(HdlLetKindIO<ModuleIOKind, IOType>), | ||||||
|  |         Incomplete(HdlLetKindIncomplete), | ||||||
|         Instance(HdlLetKindInstance), |         Instance(HdlLetKindInstance), | ||||||
|         RegBuilder(HdlLetKindRegBuilder), |         RegBuilder(HdlLetKindRegBuilder), | ||||||
|         Wire(HdlLetKindWire), |         Wire(HdlLetKindWire), | ||||||
|  | @ -720,6 +758,9 @@ impl<T: ParseTypes<I>, I> ParseTypes<HdlLetKind<I>> for HdlLetKind<T> { | ||||||
|     ) -> Result<Self, ParseFailed> { |     ) -> Result<Self, ParseFailed> { | ||||||
|         match input { |         match input { | ||||||
|             HdlLetKind::IO(input) => ParseTypes::parse_types(input, parser).map(HdlLetKind::IO), |             HdlLetKind::IO(input) => ParseTypes::parse_types(input, parser).map(HdlLetKind::IO), | ||||||
|  |             HdlLetKind::Incomplete(input) => { | ||||||
|  |                 ParseTypes::parse_types(input, parser).map(HdlLetKind::Incomplete) | ||||||
|  |             } | ||||||
|             HdlLetKind::Instance(input) => { |             HdlLetKind::Instance(input) => { | ||||||
|                 ParseTypes::parse_types(input, parser).map(HdlLetKind::Instance) |                 ParseTypes::parse_types(input, parser).map(HdlLetKind::Instance) | ||||||
|             } |             } | ||||||
|  | @ -871,6 +912,20 @@ impl HdlLetKindParse for HdlLetKind<Type> { | ||||||
|                     ty_expr: paren_contents.call(parse_optional_fn_arg)?, |                     ty_expr: paren_contents.call(parse_optional_fn_arg)?, | ||||||
|                 })) |                 })) | ||||||
|             } |             } | ||||||
|  |             LetFnKind::IncompleteWire(incomplete_wire) => { | ||||||
|  |                 if let Some(parsed_ty) = parsed_ty { | ||||||
|  |                     return Err(Error::new_spanned( | ||||||
|  |                         parsed_ty.1, | ||||||
|  |                         "type annotation not allowed for incomplete_wire", | ||||||
|  |                     )); | ||||||
|  |                 } | ||||||
|  |                 check_empty_m_dot(m_dot, kind)?; | ||||||
|  |                 let _paren_contents; | ||||||
|  |                 Ok(Self::Incomplete(HdlLetKindIncomplete { | ||||||
|  |                     kind: LetFnKindIncomplete::IncompleteWire(incomplete_wire), | ||||||
|  |                     paren: parenthesized!(_paren_contents in input), | ||||||
|  |                 })) | ||||||
|  |             } | ||||||
|             LetFnKind::Memory(fn_name) => HdlLetKindMemory::rest_of_parse( |             LetFnKind::Memory(fn_name) => HdlLetKindMemory::rest_of_parse( | ||||||
|                 input, |                 input, | ||||||
|                 parsed_ty, |                 parsed_ty, | ||||||
|  | @ -903,6 +958,7 @@ impl HdlLetKindToTokens for HdlLetKind { | ||||||
|     fn ty_to_tokens(&self, tokens: &mut TokenStream) { |     fn ty_to_tokens(&self, tokens: &mut TokenStream) { | ||||||
|         match self { |         match self { | ||||||
|             HdlLetKind::IO(v) => v.ty_to_tokens(tokens), |             HdlLetKind::IO(v) => v.ty_to_tokens(tokens), | ||||||
|  |             HdlLetKind::Incomplete(v) => v.ty_to_tokens(tokens), | ||||||
|             HdlLetKind::Instance(v) => v.ty_to_tokens(tokens), |             HdlLetKind::Instance(v) => v.ty_to_tokens(tokens), | ||||||
|             HdlLetKind::RegBuilder(v) => v.ty_to_tokens(tokens), |             HdlLetKind::RegBuilder(v) => v.ty_to_tokens(tokens), | ||||||
|             HdlLetKind::Wire(v) => v.ty_to_tokens(tokens), |             HdlLetKind::Wire(v) => v.ty_to_tokens(tokens), | ||||||
|  | @ -913,6 +969,7 @@ impl HdlLetKindToTokens for HdlLetKind { | ||||||
|     fn expr_to_tokens(&self, tokens: &mut TokenStream) { |     fn expr_to_tokens(&self, tokens: &mut TokenStream) { | ||||||
|         match self { |         match self { | ||||||
|             HdlLetKind::IO(v) => v.expr_to_tokens(tokens), |             HdlLetKind::IO(v) => v.expr_to_tokens(tokens), | ||||||
|  |             HdlLetKind::Incomplete(v) => v.expr_to_tokens(tokens), | ||||||
|             HdlLetKind::Instance(v) => v.expr_to_tokens(tokens), |             HdlLetKind::Instance(v) => v.expr_to_tokens(tokens), | ||||||
|             HdlLetKind::RegBuilder(v) => v.expr_to_tokens(tokens), |             HdlLetKind::RegBuilder(v) => v.expr_to_tokens(tokens), | ||||||
|             HdlLetKind::Wire(v) => v.expr_to_tokens(tokens), |             HdlLetKind::Wire(v) => v.expr_to_tokens(tokens), | ||||||
|  | @ -1369,6 +1426,31 @@ impl Visitor<'_> { | ||||||
|             semi_token: hdl_let.semi_token, |             semi_token: hdl_let.semi_token, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     fn process_hdl_let_incomplete(&mut self, hdl_let: HdlLet<HdlLetKindIncomplete>) -> Local { | ||||||
|  |         let name = &hdl_let.name; | ||||||
|  |         let kind = hdl_let.kind.kind; | ||||||
|  |         self.require_normal_module_or_fn(kind); | ||||||
|  |         let mut expr = kind.to_token_stream(); | ||||||
|  |         hdl_let.kind.paren.surround(&mut expr, |expr| { | ||||||
|  |             ImplicitName { | ||||||
|  |                 name, | ||||||
|  |                 span: name.span(), | ||||||
|  |             } | ||||||
|  |             .to_tokens(expr); | ||||||
|  |         }); | ||||||
|  |         let mut_token = &hdl_let.mut_token; | ||||||
|  |         Local { | ||||||
|  |             attrs: hdl_let.attrs.clone(), | ||||||
|  |             let_token: hdl_let.let_token, | ||||||
|  |             pat: parse_quote! { #mut_token #name }, | ||||||
|  |             init: Some(LocalInit { | ||||||
|  |                 eq_token: hdl_let.eq_token, | ||||||
|  |                 expr: parse_quote! { #expr }, | ||||||
|  |                 diverge: None, | ||||||
|  |             }), | ||||||
|  |             semi_token: hdl_let.semi_token, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|     fn process_hdl_let_memory(&mut self, hdl_let: HdlLet<HdlLetKindMemory>) -> Local { |     fn process_hdl_let_memory(&mut self, hdl_let: HdlLet<HdlLetKindMemory>) -> Local { | ||||||
|         let name = &hdl_let.name; |         let name = &hdl_let.name; | ||||||
|         let memory_fn = hdl_let.kind.memory_fn; |         let memory_fn = hdl_let.kind.memory_fn; | ||||||
|  | @ -1438,6 +1520,7 @@ impl Visitor<'_> { | ||||||
|         } |         } | ||||||
|         the_match! { |         the_match! { | ||||||
|             IO => process_hdl_let_io, |             IO => process_hdl_let_io, | ||||||
|  |             Incomplete => process_hdl_let_incomplete, | ||||||
|             Instance => process_hdl_let_instance, |             Instance => process_hdl_let_instance, | ||||||
|             RegBuilder => process_hdl_let_reg_builder, |             RegBuilder => process_hdl_let_reg_builder, | ||||||
|             Wire => process_hdl_let_wire, |             Wire => process_hdl_let_wire, | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ use crate::{ | ||||||
|     source_location::SourceLocation, |     source_location::SourceLocation, | ||||||
|     ty::{CanonicalType, Type}, |     ty::{CanonicalType, Type}, | ||||||
|     util::ScopedRef, |     util::ScopedRef, | ||||||
|     wire::Wire, |     wire::{IncompleteWire, Wire}, | ||||||
| }; | }; | ||||||
| use hashbrown::{hash_map::Entry, HashMap, HashSet}; | use hashbrown::{hash_map::Entry, HashMap, HashSet}; | ||||||
| use num_bigint::BigInt; | use num_bigint::BigInt; | ||||||
|  | @ -118,9 +118,35 @@ pub trait BlockRef: 'static + Send + Sync + Copy + Eq + Hash + fmt::Debug {} | ||||||
| 
 | 
 | ||||||
| impl BlockRef for BlockId {} | impl BlockRef for BlockId {} | ||||||
| 
 | 
 | ||||||
|  | pub(crate) enum IncompleteDeclaration { | ||||||
|  |     Incomplete { | ||||||
|  |         name: ScopedNameId, | ||||||
|  |         source_location: SourceLocation, | ||||||
|  |     }, | ||||||
|  |     Complete(StmtDeclaration<ModuleBuilding>), | ||||||
|  |     Taken, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl fmt::Debug for IncompleteDeclaration { | ||||||
|  |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||||
|  |         match self { | ||||||
|  |             Self::Incomplete { | ||||||
|  |                 name, | ||||||
|  |                 source_location: _, | ||||||
|  |             } => f | ||||||
|  |                 .debug_struct("Incomplete") | ||||||
|  |                 .field("name", name) | ||||||
|  |                 .finish_non_exhaustive(), | ||||||
|  |             Self::Complete(v) => v.fmt(f), | ||||||
|  |             Self::Taken => f.write_str("Taken"), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct BuilderBlock { | pub struct BuilderBlock { | ||||||
|     memories: Vec<Rc<RefCell<MemBuilderTarget>>>, |     memories: Vec<Rc<RefCell<MemBuilderTarget>>>, | ||||||
|  |     incomplete_declarations: Vec<Rc<RefCell<IncompleteDeclaration>>>, | ||||||
|     stmts: Vec<Stmt<ModuleBuilding>>, |     stmts: Vec<Stmt<ModuleBuilding>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -831,13 +857,34 @@ impl From<NormalModuleBody<ModuleBuilding>> for NormalModuleBody { | ||||||
|             annotations_map: &mut HashMap<StmtDeclaration<ModuleBuilding>, Vec<TargetedAnnotation>>, |             annotations_map: &mut HashMap<StmtDeclaration<ModuleBuilding>, Vec<TargetedAnnotation>>, | ||||||
|             block_id: BlockId, |             block_id: BlockId, | ||||||
|         ) -> Block { |         ) -> Block { | ||||||
|             let BuilderBlock { memories, stmts } = &mut blocks[block_id.as_usize()]; |             let BuilderBlock { | ||||||
|  |                 memories, | ||||||
|  |                 incomplete_declarations, | ||||||
|  |                 stmts, | ||||||
|  |             } = &mut blocks[block_id.as_usize()]; | ||||||
|             let memories = Interned::from_iter( |             let memories = Interned::from_iter( | ||||||
|                 memories |                 memories | ||||||
|                     .drain(..) |                     .drain(..) | ||||||
|                     .filter_map(|memory| memory.borrow().make_memory()), |                     .filter_map(|memory| memory.borrow().make_memory()), | ||||||
|             ); |             ); | ||||||
|             let stmts = std::mem::take(stmts); |             let stmts = Vec::from_iter( | ||||||
|  |                 incomplete_declarations | ||||||
|  |                     .drain(..) | ||||||
|  |                     .map(|decl| { | ||||||
|  |                         match std::mem::replace( | ||||||
|  |                             &mut *decl.borrow_mut(), | ||||||
|  |                             IncompleteDeclaration::Taken, | ||||||
|  |                         ) { | ||||||
|  |                             IncompleteDeclaration::Incomplete { | ||||||
|  |                                 name, | ||||||
|  |                                 source_location, | ||||||
|  |                             } => panic!("incomplete declaration: {name:?}\nat: {source_location}"), | ||||||
|  |                             IncompleteDeclaration::Complete(v) => Stmt::Declaration(v), | ||||||
|  |                             IncompleteDeclaration::Taken => unreachable!(), | ||||||
|  |                         } | ||||||
|  |                     }) | ||||||
|  |                     .chain(stmts.drain(..)), | ||||||
|  |             ); | ||||||
|             let stmts = Interned::from_iter(stmts.into_iter().map(|stmt| { |             let stmts = Interned::from_iter(stmts.into_iter().map(|stmt| { | ||||||
|                 match stmt { |                 match stmt { | ||||||
|                     Stmt::Connect(stmt) => stmt.into(), |                     Stmt::Connect(stmt) => stmt.into(), | ||||||
|  | @ -908,6 +955,7 @@ impl NormalModuleBody<ModuleBuilding> { | ||||||
|         let index = self.body.blocks.len(); |         let index = self.body.blocks.len(); | ||||||
|         self.body.blocks.push(BuilderBlock { |         self.body.blocks.push(BuilderBlock { | ||||||
|             memories: vec![], |             memories: vec![], | ||||||
|  |             incomplete_declarations: vec![], | ||||||
|             stmts: vec![], |             stmts: vec![], | ||||||
|         }); |         }); | ||||||
|         BlockId(index) |         BlockId(index) | ||||||
|  | @ -1943,6 +1991,7 @@ impl ModuleBuilder { | ||||||
|                 body: BuilderModuleBody { |                 body: BuilderModuleBody { | ||||||
|                     blocks: vec![BuilderBlock { |                     blocks: vec![BuilderBlock { | ||||||
|                         memories: vec![], |                         memories: vec![], | ||||||
|  |                         incomplete_declarations: vec![], | ||||||
|                         stmts: vec![], |                         stmts: vec![], | ||||||
|                     }], |                     }], | ||||||
|                     annotations_map: HashMap::new(), |                     annotations_map: HashMap::new(), | ||||||
|  | @ -2156,6 +2205,42 @@ pub fn wire<T: Type>(implicit_name: ImplicitName<'_>, ty: T) -> Expr<T> { | ||||||
|     wire_with_loc(implicit_name.0, SourceLocation::caller(), ty) |     wire_with_loc(implicit_name.0, SourceLocation::caller(), ty) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[track_caller] | ||||||
|  | fn incomplete_declaration( | ||||||
|  |     name: &str, | ||||||
|  |     source_location: SourceLocation, | ||||||
|  | ) -> Rc<RefCell<IncompleteDeclaration>> { | ||||||
|  |     ModuleBuilder::with(|m| { | ||||||
|  |         let mut impl_ = m.impl_.borrow_mut(); | ||||||
|  |         let scoped_name = ScopedNameId(m.name, impl_.name_id_gen.gen(name.intern())); | ||||||
|  |         drop(impl_); | ||||||
|  |         let retval = Rc::new(RefCell::new(IncompleteDeclaration::Incomplete { | ||||||
|  |             name: scoped_name, | ||||||
|  |             source_location, | ||||||
|  |         })); | ||||||
|  |         let mut impl_ = m.impl_.borrow_mut(); | ||||||
|  |         impl_ | ||||||
|  |             .body | ||||||
|  |             .builder_normal_body() | ||||||
|  |             .block(m.block_stack.top()) | ||||||
|  |             .incomplete_declarations | ||||||
|  |             .push(retval.clone()); | ||||||
|  |         retval | ||||||
|  |     }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[track_caller] | ||||||
|  | pub fn incomplete_wire_with_loc(name: &str, source_location: SourceLocation) -> IncompleteWire { | ||||||
|  |     IncompleteWire { | ||||||
|  |         declaration: incomplete_declaration(name, source_location), | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[track_caller] | ||||||
|  | pub fn incomplete_wire(implicit_name: ImplicitName<'_>) -> IncompleteWire { | ||||||
|  |     incomplete_wire_with_loc(implicit_name.0, SourceLocation::caller()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[track_caller] | #[track_caller] | ||||||
| pub fn reg_builder_with_loc(name: &str, source_location: SourceLocation) -> RegBuilder<(), (), ()> { | pub fn reg_builder_with_loc(name: &str, source_location: SourceLocation) -> RegBuilder<(), (), ()> { | ||||||
|     ModuleBuilder::with(|m| { |     ModuleBuilder::with(|m| { | ||||||
|  |  | ||||||
|  | @ -9,8 +9,8 @@ pub use crate::{ | ||||||
|     int::{Bool, DynSize, IntCmp, KnownSize, SInt, SIntType, Size, UInt, UIntType}, |     int::{Bool, DynSize, IntCmp, KnownSize, SInt, SIntType, Size, UInt, UIntType}, | ||||||
|     memory::{Mem, MemBuilder, ReadUnderWrite}, |     memory::{Mem, MemBuilder, ReadUnderWrite}, | ||||||
|     module::{ |     module::{ | ||||||
|         annotate, connect, connect_any, instance, memory, memory_array, memory_with_init, |         annotate, connect, connect_any, incomplete_wire, instance, memory, memory_array, | ||||||
|         reg_builder, wire, Instance, Module, ModuleBuilder, |         memory_with_init, reg_builder, wire, Instance, Module, ModuleBuilder, | ||||||
|     }, |     }, | ||||||
|     reg::Reg, |     reg::Reg, | ||||||
|     reset::{AsyncReset, Reset, SyncReset, ToAsyncReset, ToReset, ToSyncReset}, |     reset::{AsyncReset, Reset, SyncReset, ToAsyncReset, ToReset, ToSyncReset}, | ||||||
|  |  | ||||||
|  | @ -1,13 +1,13 @@ | ||||||
| // 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::{ | ||||||
|     expr::Flow, |     expr::{Expr, Flow, ToExpr}, | ||||||
|     intern::Interned, |     intern::Interned, | ||||||
|     module::{NameId, ScopedNameId}, |     module::{IncompleteDeclaration, NameId, ScopedNameId, StmtDeclaration, StmtWire}, | ||||||
|     source_location::SourceLocation, |     source_location::SourceLocation, | ||||||
|     ty::{CanonicalType, Type}, |     ty::{CanonicalType, Type}, | ||||||
| }; | }; | ||||||
| use std::fmt; | use std::{cell::RefCell, fmt, rc::Rc}; | ||||||
| 
 | 
 | ||||||
| #[derive(Copy, Clone, Eq, PartialEq, Hash)] | #[derive(Copy, Clone, Eq, PartialEq, Hash)] | ||||||
| pub struct Wire<T: Type> { | pub struct Wire<T: Type> { | ||||||
|  | @ -76,3 +76,57 @@ impl<T: Type> Wire<T> { | ||||||
|         true |         true | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone)] | ||||||
|  | pub struct IncompleteWire { | ||||||
|  |     pub(crate) declaration: Rc<RefCell<IncompleteDeclaration>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl IncompleteWire { | ||||||
|  |     #[track_caller] | ||||||
|  |     pub fn complete<T: Type>(&mut self, ty: T) -> Expr<T> { | ||||||
|  |         let canonical_type = ty.canonical(); | ||||||
|  |         let mut declaration = self.declaration.borrow_mut(); | ||||||
|  |         if let IncompleteDeclaration::Incomplete { | ||||||
|  |             name, | ||||||
|  |             source_location, | ||||||
|  |         } = *declaration | ||||||
|  |         { | ||||||
|  |             *declaration = IncompleteDeclaration::Complete( | ||||||
|  |                 StmtWire { | ||||||
|  |                     annotations: (), | ||||||
|  |                     wire: Wire { | ||||||
|  |                         name, | ||||||
|  |                         source_location, | ||||||
|  |                         ty: canonical_type, | ||||||
|  |                     }, | ||||||
|  |                 } | ||||||
|  |                 .into(), | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |         match *declaration { | ||||||
|  |             IncompleteDeclaration::Complete(StmtDeclaration::Wire(StmtWire { | ||||||
|  |                 wire: | ||||||
|  |                     Wire { | ||||||
|  |                         name, | ||||||
|  |                         source_location, | ||||||
|  |                         ty: wire_ty, | ||||||
|  |                     }, | ||||||
|  |                 .. | ||||||
|  |             })) => { | ||||||
|  |                 drop(declaration); | ||||||
|  |                 assert_eq!(wire_ty, canonical_type, "type mismatch"); | ||||||
|  |                 Wire { | ||||||
|  |                     name, | ||||||
|  |                     source_location, | ||||||
|  |                     ty, | ||||||
|  |                 } | ||||||
|  |                 .to_expr() | ||||||
|  |             } | ||||||
|  |             IncompleteDeclaration::Taken => panic!("can't use wire outside of containing module"), | ||||||
|  |             IncompleteDeclaration::Complete(_) | IncompleteDeclaration::Incomplete { .. } => { | ||||||
|  |                 unreachable!() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue