forked from libre-chip/fayalite
		
	add validation of connects and matches when validating module
this is useful for catching errors in transformation passes
This commit is contained in:
		
							parent
							
								
									d2ba313f0f
								
							
						
					
					
						commit
						1e2831da47
					
				
					 1 changed files with 56 additions and 31 deletions
				
			
		|  | @ -185,6 +185,40 @@ pub struct StmtConnect { | |||
|     pub source_location: SourceLocation, | ||||
| } | ||||
| 
 | ||||
| impl StmtConnect { | ||||
|     #[track_caller] | ||||
|     fn assert_validity_with_original_types(&self, lhs_orig_ty: impl Type, rhs_orig_ty: impl Type) { | ||||
|         let Self { | ||||
|             lhs, | ||||
|             rhs, | ||||
|             source_location, | ||||
|         } = *self; | ||||
|         assert!( | ||||
|             Expr::ty(lhs).can_connect(Expr::ty(rhs)), | ||||
|             "can't connect types that are not equivalent:\nlhs type:\n{lhs_orig_ty:?}\nrhs type:\n{rhs_orig_ty:?}\nat: {source_location}", | ||||
|         ); | ||||
|         assert!( | ||||
|             matches!(Expr::flow(lhs), Flow::Sink | Flow::Duplex), | ||||
|             "can't connect to source, connect lhs must have sink or duplex flow\nat: {source_location}" | ||||
|         ); | ||||
|         assert!( | ||||
|             lhs.target().is_some(), | ||||
|             "can't connect to non-target\nat: {source_location}" | ||||
|         ); | ||||
|         match Expr::flow(rhs) { | ||||
|             Flow::Source | Flow::Duplex => {} | ||||
|             Flow::Sink => assert!( | ||||
|                 Expr::ty(rhs).is_passive(), | ||||
|                 "can't connect from sink with non-passive type\nat: {source_location}" | ||||
|             ), | ||||
|         } | ||||
|     } | ||||
|     #[track_caller] | ||||
|     fn assert_validity(&self) { | ||||
|         self.assert_validity_with_original_types(Expr::ty(self.lhs), Expr::ty(self.rhs)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl fmt::Debug for StmtConnect { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||
|         let Self { | ||||
|  | @ -283,6 +317,13 @@ pub struct StmtMatch<S: ModuleBuildingStatus = ModuleBuilt> { | |||
|     pub blocks: Interned<[S::Block]>, | ||||
| } | ||||
| 
 | ||||
| impl StmtMatch { | ||||
|     #[track_caller] | ||||
|     fn assert_validity(&self) { | ||||
|         assert_eq!(Expr::ty(self.expr).variants().len(), self.blocks.len()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<S: ModuleBuildingStatus> fmt::Debug for StmtMatch<S> { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||
|         let Self { | ||||
|  | @ -1657,11 +1698,13 @@ impl AssertValidityState { | |||
|         } | ||||
|         for stmt in stmts { | ||||
|             match stmt { | ||||
|                 Stmt::Connect(StmtConnect { | ||||
|                     lhs, | ||||
|                     rhs, | ||||
|                     source_location, | ||||
|                 }) => { | ||||
|                 Stmt::Connect(connect) => { | ||||
|                     connect.assert_validity(); | ||||
|                     let StmtConnect { | ||||
|                         lhs, | ||||
|                         rhs, | ||||
|                         source_location, | ||||
|                     } = connect; | ||||
|                     self.set_connect_side_written(lhs, source_location, true, block); | ||||
|                     self.set_connect_side_written(rhs, source_location, false, block); | ||||
|                 } | ||||
|  | @ -1671,6 +1714,7 @@ impl AssertValidityState { | |||
|                     self.process_conditional_sub_blocks(block, sub_blocks) | ||||
|                 } | ||||
|                 Stmt::Match(match_stmt) => { | ||||
|                     match_stmt.assert_validity(); | ||||
|                     let sub_blocks = Vec::from_iter( | ||||
|                         match_stmt | ||||
|                             .blocks | ||||
|  | @ -2517,24 +2561,12 @@ pub fn connect_any_with_loc<Lhs: ToExpr, Rhs: ToExpr>( | |||
|     let rhs_orig = rhs.to_expr(); | ||||
|     let lhs = Expr::canonical(lhs_orig); | ||||
|     let rhs = Expr::canonical(rhs_orig); | ||||
|     assert!( | ||||
|         Expr::ty(lhs).can_connect(Expr::ty(rhs)), | ||||
|         "can't connect types that are not equivalent:\nlhs type:\n{:?}\nrhs type:\n{:?}", | ||||
|         Expr::ty(lhs_orig), | ||||
|         Expr::ty(rhs_orig) | ||||
|     ); | ||||
|     assert!( | ||||
|         matches!(Expr::flow(lhs), Flow::Sink | Flow::Duplex), | ||||
|         "can't connect to source, connect lhs must have sink or duplex flow" | ||||
|     ); | ||||
|     assert!(lhs.target().is_some(), "can't connect to non-target"); | ||||
|     match Expr::flow(rhs) { | ||||
|         Flow::Source | Flow::Duplex => {} | ||||
|         Flow::Sink => assert!( | ||||
|             Expr::ty(rhs).is_passive(), | ||||
|             "can't connect from sink with non-passive type" | ||||
|         ), | ||||
|     } | ||||
|     let connect = StmtConnect { | ||||
|         lhs, | ||||
|         rhs, | ||||
|         source_location, | ||||
|     }; | ||||
|     connect.assert_validity_with_original_types(Expr::ty(lhs_orig), Expr::ty(rhs_orig)); | ||||
|     ModuleBuilder::with(|m| { | ||||
|         m.impl_ | ||||
|             .borrow_mut() | ||||
|  | @ -2542,14 +2574,7 @@ pub fn connect_any_with_loc<Lhs: ToExpr, Rhs: ToExpr>( | |||
|             .builder_normal_body() | ||||
|             .block(m.block_stack.top()) | ||||
|             .stmts | ||||
|             .push( | ||||
|                 StmtConnect { | ||||
|                     lhs, | ||||
|                     rhs, | ||||
|                     source_location, | ||||
|                 } | ||||
|                 .into(), | ||||
|             ); | ||||
|             .push(connect.into()); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue