Skip to content

Commit

Permalink
Merge pull request #108 from lambdaclass/for-lowering
Browse files Browse the repository at this point in the history
For lowering
  • Loading branch information
igaray authored Apr 25, 2024
2 parents 9b50130 + fbe93b2 commit b493c13
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 13 deletions.
2 changes: 2 additions & 0 deletions crates/concrete_driver/tests/examples.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ mod common;
#[test_case(include_str!("../../../examples/malloc.con"), "malloc", false, 5 ; "malloc.con")]
#[test_case(include_str!("../../../examples/while_if_false.con"), "while_if_false", false, 7 ; "while_if_false.con")]
#[test_case(include_str!("../../../examples/if_if_false.con"), "if_if_false", false, 7 ; "if_if_false.con")]
#[test_case(include_str!("../../../examples/for.con"), "for", false, 10 ; "for.con")]
#[test_case(include_str!("../../../examples/for_while.con"), "for_while", false, 10 ; "for_while.con")]
fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) {
assert_eq!(
status_code,
Expand Down
126 changes: 124 additions & 2 deletions crates/concrete_ir/src/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use concrete_ast::{
},
functions::{FunctionDecl, FunctionDef},
modules::{Module, ModuleDefItem},
statements::{self, AssignStmt, LetStmt, LetStmtTarget, ReturnStmt, WhileStmt},
statements::{self, AssignStmt, ForStmt, LetStmt, LetStmtTarget, ReturnStmt, WhileStmt},
structs::StructDecl,
types::{TypeQualifier, TypeSpec},
Program,
Expand Down Expand Up @@ -291,6 +291,24 @@ fn lower_func(
}
LetStmtTarget::Destructure(_) => todo!(),
}
} else if let statements::Statement::For(info) = stmt {
if let Some(info) = &info.init {
match &info.target {
LetStmtTarget::Simple { name, r#type } => {
let ty = lower_type(&builder.ctx, r#type, builder.local_module)?;
builder
.name_to_local
.insert(name.name.clone(), builder.body.locals.len());
builder.body.locals.push(Local::new(
Some(name.span),
LocalKind::Temp,
ty,
Some(name.name.clone()),
));
}
LetStmtTarget::Destructure(_) => todo!(),
}
}
}
}

Expand Down Expand Up @@ -363,7 +381,10 @@ fn lower_statement(
match info {
statements::Statement::Assign(info) => lower_assign(builder, info)?,
statements::Statement::Match(_) => todo!(),
statements::Statement::For(_) => todo!(),
statements::Statement::For(info) => {
lower_for(builder, info)?;
assert!(builder.statements.is_empty());
}
statements::Statement::If(info) => {
lower_if_statement(builder, info)?;
assert!(builder.statements.is_empty());
Expand Down Expand Up @@ -460,6 +481,107 @@ fn lower_while(builder: &mut FnBodyBuilder, info: &WhileStmt) -> Result<(), Lowe
Ok(())
}

fn lower_for(builder: &mut FnBodyBuilder, info: &ForStmt) -> Result<(), LoweringError> {
if let Some(init) = &info.init {
lower_let(builder, init)?;
}

let statements = std::mem::take(&mut builder.statements);
builder.body.basic_blocks.push(BasicBlock {
statements,
terminator: Box::new(Terminator {
span: None,
kind: TerminatorKind::Goto {
target: builder.body.basic_blocks.len() + 1,
},
}),
});

let (discriminator, discriminator_type, _disc_span) = if let Some(condition) = &info.condition {
let (discriminator, discriminator_type, span) = lower_expression(builder, condition, None)?;

(discriminator, discriminator_type, Some(span))
} else {
// todo: don't use discriminator when no loop condition
let discriminator_type = Ty {
span: None,
kind: TyKind::Bool,
};

let discriminator = Rvalue::Use(Operand::Const(ConstData {
ty: discriminator_type.clone(),
data: ConstKind::Value(ValueTree::Leaf(ConstValue::Bool(true))),
}));

(discriminator, discriminator_type, None)
};

let local = builder.add_temp_local(TyKind::Bool);
let place = Place {
local,
projection: vec![],
};

builder.statements.push(Statement {
span: None,
kind: StatementKind::Assign(place.clone(), discriminator),
});

// keep idx to change terminator
let check_block_idx = builder.body.basic_blocks.len();

let statements = std::mem::take(&mut builder.statements);
builder.body.basic_blocks.push(BasicBlock {
statements,
terminator: Box::new(Terminator {
span: None,
kind: TerminatorKind::Unreachable,
}),
});

// keep idx for switch targets
let first_then_block_idx = builder.body.basic_blocks.len();

for stmt in &info.contents {
lower_statement(
builder,
stmt,
builder.body.locals[builder.ret_local].ty.clone(),
)?;
}

if let Some(post) = &info.post {
lower_assign(builder, post)?;
}

builder.body.basic_blocks.len();
let statements = std::mem::take(&mut builder.statements);
builder.body.basic_blocks.push(BasicBlock {
statements,
terminator: Box::new(Terminator {
span: None,
kind: TerminatorKind::Goto {
target: check_block_idx,
},
}),
});

let otherwise_block_idx = builder.body.basic_blocks.len();

let targets = SwitchTargets {
values: vec![discriminator_type.kind.get_falsy_value()],
targets: vec![otherwise_block_idx, first_then_block_idx],
};

let kind = TerminatorKind::SwitchInt {
discriminator: Operand::Place(place),
targets,
};
builder.body.basic_blocks[check_block_idx].terminator.kind = kind;

Ok(())
}

fn lower_if_statement(builder: &mut FnBodyBuilder, info: &IfExpr) -> Result<(), LoweringError> {
let (discriminator, discriminator_type, _disc_span) =
lower_expression(builder, &info.value, None)?;
Expand Down
5 changes: 0 additions & 5 deletions examples/for_loop.con
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ mod Example {
let mut result: i64 = 0;

let n: i64 = 1;
for (;;) {
result = result + n;
n = n + 1;
}

for {
result = result + n;
n = n + 1;
Expand Down
6 changes: 0 additions & 6 deletions examples/for_while.con
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@ mod Example {
let mut result: i64 = 0;

let n: i64 = 1;
for (; n <= limit ;) {
result = result + n;
n = n + 1;
}

n = 1;
for (n <= limit) {
result = result + n;
n = n + 1;
Expand Down

0 comments on commit b493c13

Please sign in to comment.