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