Codegen for/while loops
This commit is contained in:
		
							parent
							
								
									a251be2715
								
							
						
					
					
						commit
						c4017715d2
					
				| @ -696,7 +696,7 @@ impl Parse for BlockLevelStatement { | ||||
| pub struct ForStatement(String, TokenRange, Expression, Expression, Block); | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct WhileStatement(Expression, Block); | ||||
| pub struct WhileStatement(pub Expression, pub Block); | ||||
| 
 | ||||
| impl Parse for ForStatement { | ||||
|     fn parse(mut stream: TokenStream) -> Result<Self, Error> { | ||||
|  | ||||
| @ -19,6 +19,7 @@ use crate::{ | ||||
|     mir::{ | ||||
|         self, implement::TypeCategory, CustomTypeKey, Metadata, NamedVariableRef, SourceModuleId, | ||||
|         StructField, StructType, TypeDefinition, TypeDefinitionKind, TypeKind, VagueLiteral, | ||||
|         WhileStatement, | ||||
|     }, | ||||
|     util::try_all, | ||||
| }; | ||||
| @ -598,7 +599,54 @@ impl mir::Statement { | ||||
|             } | ||||
|             mir::StmtKind::Import(_) => todo!(), | ||||
|             mir::StmtKind::Expression(expression) => expression.codegen(scope, state), | ||||
|             mir::StmtKind::While(_) => todo!(), | ||||
|             mir::StmtKind::While(WhileStatement { | ||||
|                 condition, block, .. | ||||
|             }) => { | ||||
|                 let condition_block = scope.function.ir.block("condition_block"); | ||||
|                 let condition_true_block = scope.function.ir.block("condition_true"); | ||||
|                 let condition_failed_block = scope.function.ir.block("condition_failed"); | ||||
| 
 | ||||
|                 scope | ||||
|                     .block | ||||
|                     .terminate(Term::Br(condition_block.value())) | ||||
|                     .unwrap(); | ||||
|                 let mut condition_scope = scope.with_block(condition_block); | ||||
|                 let condition_res = condition.codegen(&mut condition_scope, state)?.unwrap(); | ||||
|                 let true_instr = condition_scope | ||||
|                     .block | ||||
|                     .build(Instr::Constant(ConstValue::Bool(true))) | ||||
|                     .unwrap(); | ||||
|                 let check = condition_scope | ||||
|                     .block | ||||
|                     .build(Instr::ICmp( | ||||
|                         CmpPredicate::EQ, | ||||
|                         condition_res.instr(), | ||||
|                         true_instr, | ||||
|                     )) | ||||
|                     .unwrap(); | ||||
| 
 | ||||
|                 condition_scope | ||||
|                     .block | ||||
|                     .terminate(Term::CondBr( | ||||
|                         check, | ||||
|                         condition_true_block.value(), | ||||
|                         condition_failed_block.value(), | ||||
|                     )) | ||||
|                     .unwrap(); | ||||
| 
 | ||||
|                 let mut condition_true_scope = scope.with_block(condition_true_block); | ||||
|                 block.codegen(&mut condition_true_scope, state)?; | ||||
| 
 | ||||
|                 condition_true_scope | ||||
|                     .block | ||||
|                     .terminate(Term::Br(condition_scope.block.value())) | ||||
|                     // Can hard return inside the condition_true_scope
 | ||||
|                     .ok(); | ||||
| 
 | ||||
|                 scope.swap_block(condition_failed_block); | ||||
| 
 | ||||
|                 Ok(None) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -336,9 +336,19 @@ impl Block { | ||||
|                     } | ||||
|                 } | ||||
|                 StmtKind::While(WhileStatement { | ||||
|                     condition, block, .. | ||||
|                     condition, | ||||
|                     block, | ||||
|                     meta, | ||||
|                 }) => { | ||||
|                     condition.typecheck(&mut state, typerefs, Some(&TypeKind::Bool))?; | ||||
|                     let condition_ty = | ||||
|                         condition.typecheck(&mut state, typerefs, Some(&TypeKind::Bool))?; | ||||
|                     if condition_ty.assert_known(typerefs, &state)? != TypeKind::Bool { | ||||
|                         state.note_errors( | ||||
|                             &vec![ErrorKind::TypesIncompatible(condition_ty, TypeKind::Bool)], | ||||
|                             *meta, | ||||
|                         ); | ||||
|                     } | ||||
| 
 | ||||
|                     block.typecheck(&mut state, typerefs, None)?; | ||||
| 
 | ||||
|                     None | ||||
|  | ||||
| @ -120,3 +120,7 @@ fn strings_compiles_well() { | ||||
| fn struct_compiles_well() { | ||||
|     test(include_str!("../../examples/struct.reid"), "test", 17); | ||||
| } | ||||
| #[test] | ||||
| fn loops_compiles_well() { | ||||
|     test(include_str!("../../examples/loops.reid"), "test", 10); | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user