Codegen for/while loops

This commit is contained in:
Sofia 2025-07-23 21:07:12 +03:00
parent a251be2715
commit c4017715d2
4 changed files with 66 additions and 4 deletions

View File

@ -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> {

View File

@ -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)
}
}
}
}

View File

@ -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

View File

@ -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);
}