diff --git a/lib/edlang_ir/src/lib.rs b/lib/edlang_ir/src/lib.rs index c59db7692..a1b617815 100644 --- a/lib/edlang_ir/src/lib.rs +++ b/lib/edlang_ir/src/lib.rs @@ -125,10 +125,13 @@ impl Local { } } - pub const fn temp(ty: TypeInfo) -> Self { + pub const fn temp(ty: TypeKind) -> Self { Self { span: None, - ty, + ty: TypeInfo { + span: None, + kind: ty, + }, kind: LocalKind::Temp, debug_name: None, mutable: false, diff --git a/lib/edlang_lowering/src/common.rs b/lib/edlang_lowering/src/common.rs index 11d1df801..d962559b6 100644 --- a/lib/edlang_lowering/src/common.rs +++ b/lib/edlang_lowering/src/common.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use edlang_ir::{Body, DefId, Local, ModuleBody, ProgramBody, Statement, TypeInfo, TypeKind}; +use edlang_ir::{Body, DefId, Local, ModuleBody, ProgramBody, Statement, TypeKind}; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] pub struct IdGenerator { @@ -72,10 +72,7 @@ impl BodyBuilder { pub fn add_temp_local(&mut self, ty_kind: TypeKind) -> usize { let id = self.body.locals.len(); - self.body.locals.push(Local::temp(TypeInfo { - span: None, - kind: ty_kind, - })); + self.body.locals.push(Local::temp(ty_kind)); id } diff --git a/lib/edlang_lowering/src/lib.rs b/lib/edlang_lowering/src/lib.rs index 0ea2f2a1d..f607b1f6c 100644 --- a/lib/edlang_lowering/src/lib.rs +++ b/lib/edlang_lowering/src/lib.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use ast::{BinaryOp, ModuleStatement}; +use ast::{BinaryOp, ModuleStatement, WhileStmt}; use common::{BodyBuilder, BuildCtx}; use edlang_ast as ast; use edlang_ir as ir; @@ -155,7 +155,7 @@ fn lower_function(ctx: BuildCtx, func: &ast::Function, module_id: DefId) -> Buil } for stmt in &func.body.body { - lower_statement(&mut builder, stmt, &ret_ty); + lower_statement(&mut builder, stmt, &ret_ty.kind); } let (mut ctx, body) = (builder.ctx, builder.body); @@ -164,12 +164,12 @@ fn lower_function(ctx: BuildCtx, func: &ast::Function, module_id: DefId) -> Buil ctx } -fn lower_statement(builder: &mut BodyBuilder, info: &ast::Statement, ret_type: &TypeInfo) { +fn lower_statement(builder: &mut BodyBuilder, info: &ast::Statement, ret_type: &TypeKind) { match info { ast::Statement::Let(info) => lower_let(builder, info), ast::Statement::Assign(info) => lower_assign(builder, info), ast::Statement::For(_) => todo!(), - ast::Statement::While(_) => todo!(), + ast::Statement::While(info) => lower_while(builder, info, ret_type), ast::Statement::If(info) => lower_if_stmt(builder, info, ret_type), ast::Statement::Return(info) => lower_return(builder, info, ret_type), ast::Statement::FnCall(info) => { @@ -178,9 +178,80 @@ fn lower_statement(builder: &mut BodyBuilder, info: &ast::Statement, ret_type: & } } -fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeInfo) { +fn lower_while(builder: &mut BodyBuilder, info: &WhileStmt, ret_type: &TypeKind) { + let statements = std::mem::take(&mut builder.statements); + builder.body.blocks.push(BasicBlock { + statements: statements.into(), + terminator: Terminator::Target(builder.body.blocks.len() + 1), + }); + + let (discriminator, discriminator_type) = lower_expr(builder, &info.condition, None); + + let local = builder.add_temp_local(TypeKind::Bool); + let place = Place { + local, + projection: Default::default(), + }; + + builder.statements.push(Statement { + span: None, + kind: StatementKind::Assign(place.clone(), discriminator), + }); + + // keep idx to change terminator + let check_block_idx = builder.body.blocks.len(); + + let statements = std::mem::take(&mut builder.statements); + builder.body.blocks.push(BasicBlock { + statements: statements.into(), + terminator: Terminator::Unreachable, + }); + + // keep idx for switch targets + let first_then_block_idx = builder.body.blocks.len(); + + for stmt in &info.block.body { + lower_statement(builder, stmt, ret_type); + } + + // keet idx to change terminator if there is no return + let last_then_block_idx = if !matches!( + builder.body.blocks.last().unwrap().terminator, + Terminator::Return + ) { + builder.body.blocks.len(); + let statements = std::mem::take(&mut builder.statements); + let idx = builder.body.blocks.len(); + builder.body.blocks.push(BasicBlock { + statements: statements.into(), + terminator: Terminator::Unreachable, + }); + Some(idx) + } else { + None + }; + + let otherwise_block_idx = builder.body.blocks.len(); + + let targets = SwitchTarget { + values: vec![discriminator_type.get_falsy_value()], + targets: vec![otherwise_block_idx, first_then_block_idx], + }; + + let kind = Terminator::SwitchInt { + discriminator: Operand::Move(place), + targets, + }; + builder.body.blocks[check_block_idx].terminator = kind; + + if let Some(last_then_block_idx) = last_then_block_idx { + builder.body.blocks[last_then_block_idx].terminator = Terminator::Target(check_block_idx); + } +} + +fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeKind) { let cond_ty = find_expr_type(builder, &info.condition).expect("coouldnt find cond type"); - let condition = lower_expr(builder, &info.condition, Some(&cond_ty)); + let (condition, condition_ty) = lower_expr(builder, &info.condition, Some(&cond_ty)); let local = builder.add_temp_local(TypeKind::Bool); let place = Place { @@ -249,7 +320,7 @@ fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeI }; let targets = SwitchTarget { - values: vec![TypeKind::Bool.get_falsy_value()], + values: vec![condition_ty.get_falsy_value()], targets: vec![first_else_block_idx, first_then_block_idx], }; @@ -271,7 +342,7 @@ fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeI fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) { let ty = lower_type(&builder.ctx, &info.r#type); - let rvalue = lower_expr(builder, &info.value, Some(&ty)); + let (rvalue, _ty) = lower_expr(builder, &info.value, Some(&ty.kind)); let local_idx = builder.name_to_local.get(&info.name.name).copied().unwrap(); builder.statements.push(Statement { span: Some(info.name.span), @@ -292,8 +363,8 @@ fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) { fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) { let local = *builder.name_to_local.get(&info.name.first.name).unwrap(); let ty = builder.body.locals[local].ty.clone(); - let rvalue = lower_expr(builder, &info.value, Some(&ty)); - let place = lower_path(builder, &info.name); + let (rvalue, _ty) = lower_expr(builder, &info.value, Some(&ty.kind)); + let (place, _ty) = lower_path(builder, &info.name); builder.statements.push(Statement { span: Some(info.name.first.span), @@ -301,66 +372,67 @@ fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) { }) } -fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option { - Some(TypeInfo { - span: None, - kind: match info { - ast::Expression::Value(x) => match x { - ast::ValueExpr::Bool { .. } => TypeKind::Bool, - ast::ValueExpr::Char { .. } => TypeKind::Char, - ast::ValueExpr::Int { .. } => return None, - ast::ValueExpr::Float { .. } => return None, - ast::ValueExpr::Str { .. } => todo!(), - ast::ValueExpr::Path(path) => { - // todo: handle full path - builder.get_local(&path.first.name)?.ty.kind.clone() - } - }, - ast::Expression::FnCall(info) => { - let fn_id = { - let mod_body = builder.get_module_body(); - - if let Some(id) = mod_body.symbols.functions.get(&info.name.name) { - *id - } else { - *mod_body - .imports - .get(&info.name.name) - .expect("function call not found") - } - }; - - builder - .ctx - .body - .function_signatures - .get(&fn_id)? - .1 - .kind - .clone() - } - ast::Expression::Unary(_, info) => find_expr_type(builder, info)?.kind, - ast::Expression::Binary(lhs, op, rhs) => { - if matches!(op, BinaryOp::Logic(_, _)) { - TypeKind::Bool - } else { - find_expr_type(builder, lhs) - .or(find_expr_type(builder, rhs))? - .kind - } +fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option { + Some(match info { + ast::Expression::Value(x) => match x { + ast::ValueExpr::Bool { .. } => TypeKind::Bool, + ast::ValueExpr::Char { .. } => TypeKind::Char, + ast::ValueExpr::Int { .. } => return None, + ast::ValueExpr::Float { .. } => return None, + ast::ValueExpr::Str { .. } => todo!(), + ast::ValueExpr::Path(path) => { + // todo: handle full path + builder.get_local(&path.first.name)?.ty.kind.clone() } }, + ast::Expression::FnCall(info) => { + let fn_id = { + let mod_body = builder.get_module_body(); + + if let Some(id) = mod_body.symbols.functions.get(&info.name.name) { + *id + } else { + *mod_body + .imports + .get(&info.name.name) + .expect("function call not found") + } + }; + + builder + .ctx + .body + .function_signatures + .get(&fn_id)? + .1 + .kind + .clone() + } + ast::Expression::Unary(_, info) => find_expr_type(builder, info)?, + ast::Expression::Binary(lhs, op, rhs) => { + if matches!(op, BinaryOp::Logic(_, _)) { + TypeKind::Bool + } else { + find_expr_type(builder, lhs).or(find_expr_type(builder, rhs))? + } + } }) } fn lower_expr( builder: &mut BodyBuilder, info: &ast::Expression, - type_hint: Option<&TypeInfo>, -) -> ir::RValue { + type_hint: Option<&TypeKind>, +) -> (ir::RValue, TypeKind) { match info { - ast::Expression::Value(info) => ir::RValue::Use(lower_value(builder, info, type_hint)), - ast::Expression::FnCall(info) => ir::RValue::Use(lower_fn_call(builder, info)), + ast::Expression::Value(info) => { + let (value, ty) = lower_value(builder, info, type_hint); + (ir::RValue::Use(value), ty) + } + ast::Expression::FnCall(info) => { + let (value, ty) = lower_fn_call(builder, info); + (ir::RValue::Use(value), ty) + } ast::Expression::Unary(_, _) => todo!(), ast::Expression::Binary(lhs, op, rhs) => { lower_binary_expr(builder, lhs, op, rhs, type_hint) @@ -373,23 +445,24 @@ fn lower_binary_expr( lhs: &ast::Expression, op: &ast::BinaryOp, rhs: &ast::Expression, - type_hint: Option<&TypeInfo>, -) -> ir::RValue { + type_hint: Option<&TypeKind>, +) -> (ir::RValue, TypeKind) { let (lhs, lhs_ty) = if type_hint.is_none() { - let ty = find_expr_type(builder, lhs); - (lower_expr(builder, lhs, ty.as_ref()), ty) + let ty = find_expr_type(builder, lhs) + .unwrap_or(find_expr_type(builder, rhs).expect("cant find type")); + lower_expr(builder, lhs, Some(&ty)) } else { - (lower_expr(builder, lhs, type_hint), type_hint.cloned()) + lower_expr(builder, lhs, type_hint) }; let (rhs, rhs_ty) = if type_hint.is_none() { - let ty = find_expr_type(builder, rhs); - (lower_expr(builder, rhs, ty.as_ref()), ty) + let ty = find_expr_type(builder, rhs).unwrap_or(lhs_ty.clone()); + lower_expr(builder, rhs, Some(&ty)) } else { - (lower_expr(builder, rhs, type_hint), type_hint.cloned()) + lower_expr(builder, rhs, type_hint) }; - let lhs_local = builder.add_local(Local::temp(lhs_ty.unwrap().clone())); - let rhs_local = builder.add_local(Local::temp(rhs_ty.unwrap().clone())); + let lhs_local = builder.add_local(Local::temp(lhs_ty.clone())); + let rhs_local = builder.add_local(Local::temp(rhs_ty.clone())); let lhs_place = Place { local: lhs_local, projection: Default::default(), @@ -423,34 +496,46 @@ fn lower_binary_expr( let rhs = Operand::Move(rhs_place); match op { - ast::BinaryOp::Arith(op, _) => match op { - ast::ArithOp::Add => ir::RValue::BinOp(ir::BinOp::Add, lhs, rhs), - ast::ArithOp::Sub => ir::RValue::BinOp(ir::BinOp::Sub, lhs, rhs), - ast::ArithOp::Mul => ir::RValue::BinOp(ir::BinOp::Mul, lhs, rhs), - ast::ArithOp::Div => ir::RValue::BinOp(ir::BinOp::Div, lhs, rhs), - ast::ArithOp::Mod => ir::RValue::BinOp(ir::BinOp::Rem, lhs, rhs), - }, - ast::BinaryOp::Logic(op, _) => match op { - ast::LogicOp::And => ir::RValue::LogicOp(ir::LogicalOp::And, lhs, rhs), - ast::LogicOp::Or => ir::RValue::LogicOp(ir::LogicalOp::Or, lhs, rhs), - }, - ast::BinaryOp::Compare(op, _) => match op { - ast::CmpOp::Eq => ir::RValue::BinOp(ir::BinOp::Eq, lhs, rhs), - ast::CmpOp::NotEq => ir::RValue::BinOp(ir::BinOp::Ne, lhs, rhs), - ast::CmpOp::Lt => ir::RValue::BinOp(ir::BinOp::Lt, lhs, rhs), - ast::CmpOp::LtEq => ir::RValue::BinOp(ir::BinOp::Le, lhs, rhs), - ast::CmpOp::Gt => ir::RValue::BinOp(ir::BinOp::Gt, lhs, rhs), - ast::CmpOp::GtEq => ir::RValue::BinOp(ir::BinOp::Ge, lhs, rhs), - }, - ast::BinaryOp::Bitwise(op, _) => match op { - ast::BitwiseOp::And => ir::RValue::BinOp(ir::BinOp::BitAnd, lhs, rhs), - ast::BitwiseOp::Or => ir::RValue::BinOp(ir::BinOp::BitOr, lhs, rhs), - ast::BitwiseOp::Xor => ir::RValue::BinOp(ir::BinOp::BitXor, lhs, rhs), - }, + ast::BinaryOp::Arith(op, _) => ( + match op { + ast::ArithOp::Add => ir::RValue::BinOp(ir::BinOp::Add, lhs, rhs), + ast::ArithOp::Sub => ir::RValue::BinOp(ir::BinOp::Sub, lhs, rhs), + ast::ArithOp::Mul => ir::RValue::BinOp(ir::BinOp::Mul, lhs, rhs), + ast::ArithOp::Div => ir::RValue::BinOp(ir::BinOp::Div, lhs, rhs), + ast::ArithOp::Mod => ir::RValue::BinOp(ir::BinOp::Rem, lhs, rhs), + }, + lhs_ty, + ), + ast::BinaryOp::Logic(op, _) => ( + match op { + ast::LogicOp::And => ir::RValue::LogicOp(ir::LogicalOp::And, lhs, rhs), + ast::LogicOp::Or => ir::RValue::LogicOp(ir::LogicalOp::Or, lhs, rhs), + }, + TypeKind::Bool, + ), + ast::BinaryOp::Compare(op, _) => ( + match op { + ast::CmpOp::Eq => ir::RValue::BinOp(ir::BinOp::Eq, lhs, rhs), + ast::CmpOp::NotEq => ir::RValue::BinOp(ir::BinOp::Ne, lhs, rhs), + ast::CmpOp::Lt => ir::RValue::BinOp(ir::BinOp::Lt, lhs, rhs), + ast::CmpOp::LtEq => ir::RValue::BinOp(ir::BinOp::Le, lhs, rhs), + ast::CmpOp::Gt => ir::RValue::BinOp(ir::BinOp::Gt, lhs, rhs), + ast::CmpOp::GtEq => ir::RValue::BinOp(ir::BinOp::Ge, lhs, rhs), + }, + TypeKind::Bool, + ), + ast::BinaryOp::Bitwise(op, _) => ( + match op { + ast::BitwiseOp::And => ir::RValue::BinOp(ir::BinOp::BitAnd, lhs, rhs), + ast::BitwiseOp::Or => ir::RValue::BinOp(ir::BinOp::BitOr, lhs, rhs), + ast::BitwiseOp::Xor => ir::RValue::BinOp(ir::BinOp::BitXor, lhs, rhs), + }, + lhs_ty, + ), } } -fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> Operand { +fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> (Operand, TypeKind) { let fn_id = { let mod_body = builder.get_module_body(); @@ -493,11 +578,11 @@ fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> Operand { let mut args = Vec::new(); for (arg, arg_ty) in info.params.iter().zip(args_ty) { - let rvalue = lower_expr(builder, arg, Some(&arg_ty)); + let (rvalue, _rvalue_ty) = lower_expr(builder, arg, Some(&arg_ty.kind)); args.push(rvalue); } - let dest_local = builder.add_local(Local::temp(ret_ty)); + let dest_local = builder.add_local(Local::temp(ret_ty.kind.clone())); let dest_place = Place { local: dest_local, @@ -520,59 +605,62 @@ fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> Operand { terminator: kind, }); - Operand::Move(dest_place) + (Operand::Move(dest_place), ret_ty.kind.clone()) } fn lower_value( builder: &mut BodyBuilder, info: &ast::ValueExpr, - type_hint: Option<&TypeInfo>, -) -> Operand { + type_hint: Option<&TypeKind>, +) -> (Operand, TypeKind) { match info { - ast::ValueExpr::Bool { value, span } => ir::Operand::Constant(ir::ConstData { - span: Some(*span), - type_info: ir::TypeInfo { - span: None, - kind: ir::TypeKind::Bool, - }, - kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::Bool(*value))), - }), - ast::ValueExpr::Char { value, span } => ir::Operand::Constant(ir::ConstData { - span: Some(*span), - type_info: ir::TypeInfo { - span: None, - kind: ir::TypeKind::Char, - }, - kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::U32((*value) as u32))), - }), + ast::ValueExpr::Bool { value, span } => ( + ir::Operand::Constant(ir::ConstData { + span: Some(*span), + type_info: ir::TypeInfo { + span: None, + kind: ir::TypeKind::Bool, + }, + kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::Bool(*value))), + }), + TypeKind::Bool, + ), + ast::ValueExpr::Char { value, span } => ( + ir::Operand::Constant(ir::ConstData { + span: Some(*span), + type_info: ir::TypeInfo { + span: None, + kind: ir::TypeKind::Char, + }, + kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::U32( + (*value) as u32, + ))), + }), + TypeKind::Char, + ), ast::ValueExpr::Int { value, span } => { - let (ty, val, type_span) = match type_hint { - Some(type_hint) => match &type_hint.kind { + let (ty, val) = match type_hint { + Some(type_hint) => match &type_hint { ir::TypeKind::Int(int_type) => match int_type { ir::IntTy::I128 => ( ir::TypeKind::Int(ir::IntTy::I128), ir::ConstValue::I128((*value) as i128), - type_hint.span, ), ir::IntTy::I64 => ( ir::TypeKind::Int(ir::IntTy::I64), ir::ConstValue::I64((*value) as i64), - type_hint.span, ), ir::IntTy::I32 => ( ir::TypeKind::Int(ir::IntTy::I32), ir::ConstValue::I32((*value) as i32), - type_hint.span, ), ir::IntTy::I16 => ( ir::TypeKind::Int(ir::IntTy::I16), ir::ConstValue::I16((*value) as i16), - type_hint.span, ), ir::IntTy::I8 => ( ir::TypeKind::Int(ir::IntTy::I8), ir::ConstValue::I8((*value) as i8), - type_hint.span, ), ir::IntTy::Isize => todo!(), }, @@ -580,27 +668,22 @@ fn lower_value( ir::UintTy::U128 => ( ir::TypeKind::Uint(ir::UintTy::U128), ir::ConstValue::U128(*value), - type_hint.span, ), ir::UintTy::U64 => ( ir::TypeKind::Uint(ir::UintTy::U64), ir::ConstValue::U64((*value) as u64), - type_hint.span, ), ir::UintTy::U32 => ( ir::TypeKind::Uint(ir::UintTy::U32), ir::ConstValue::U32((*value) as u32), - type_hint.span, ), ir::UintTy::U16 => ( ir::TypeKind::Uint(ir::UintTy::U16), ir::ConstValue::U16((*value) as u16), - type_hint.span, ), ir::UintTy::U8 => ( ir::TypeKind::Uint(ir::UintTy::U8), ir::ConstValue::U8((*value) as u8), - type_hint.span, ), _ => todo!(), }, @@ -609,38 +692,47 @@ fn lower_value( None => todo!(), }; - ir::Operand::Constant(ir::ConstData { - span: Some(*span), - type_info: ir::TypeInfo { - span: type_span, - kind: ty, - }, - kind: ir::ConstKind::Value(ir::ValueTree::Leaf(val)), - }) + ( + ir::Operand::Constant(ir::ConstData { + span: Some(*span), + type_info: ir::TypeInfo { + span: None, + kind: ty.clone(), + }, + kind: ir::ConstKind::Value(ir::ValueTree::Leaf(val)), + }), + ty, + ) } ast::ValueExpr::Float { value, span } => match type_hint { - Some(type_hint) => match &type_hint.kind { + Some(type_hint) => match &type_hint { TypeKind::Float(float_ty) => match float_ty { - ir::FloatTy::F32 => ir::Operand::Constant(ir::ConstData { - span: Some(*span), - type_info: ir::TypeInfo { - span: type_hint.span, - kind: ir::TypeKind::Float(ir::FloatTy::F32), - }, - kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::F32( - value.parse().unwrap(), - ))), - }), - ir::FloatTy::F64 => ir::Operand::Constant(ir::ConstData { - span: Some(*span), - type_info: ir::TypeInfo { - span: type_hint.span, - kind: ir::TypeKind::Float(ir::FloatTy::F64), - }, - kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::F64( - value.parse().unwrap(), - ))), - }), + ir::FloatTy::F32 => ( + ir::Operand::Constant(ir::ConstData { + span: Some(*span), + type_info: ir::TypeInfo { + span: None, + kind: ir::TypeKind::Float(ir::FloatTy::F32), + }, + kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::F32( + value.parse().unwrap(), + ))), + }), + type_hint.clone(), + ), + ir::FloatTy::F64 => ( + ir::Operand::Constant(ir::ConstData { + span: Some(*span), + type_info: ir::TypeInfo { + span: None, + kind: ir::TypeKind::Float(ir::FloatTy::F64), + }, + kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::F64( + value.parse().unwrap(), + ))), + }), + type_hint.clone(), + ), }, _ => unreachable!(), }, @@ -649,14 +741,15 @@ fn lower_value( ast::ValueExpr::Str { value: _, span: _ } => todo!(), ast::ValueExpr::Path(info) => { // add deref info to path - Operand::Move(lower_path(builder, info)) + let (place, ty) = lower_path(builder, info); + (Operand::Move(place), ty) } } } -fn lower_return(builder: &mut BodyBuilder, info: &ast::ReturnStmt, return_type: &TypeInfo) { +fn lower_return(builder: &mut BodyBuilder, info: &ast::ReturnStmt, return_type: &TypeKind) { if let Some(value_expr) = &info.value { - let value = lower_expr(builder, value_expr, Some(return_type)); + let (value, _ty) = lower_expr(builder, value_expr, Some(return_type)); builder.statements.push(Statement { span: None, kind: StatementKind::Assign( @@ -676,16 +769,20 @@ fn lower_return(builder: &mut BodyBuilder, info: &ast::ReturnStmt, return_type: }); } -fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> ir::Place { +fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, TypeKind) { let local = *builder .name_to_local .get(&info.first.name) .expect("local not found"); + let ty = builder.body.locals[local].ty.kind.clone(); - Place { - local, - projection: Default::default(), // todo, field array deref - } + ( + Place { + local, + projection: Default::default(), // todo, field array deref + }, + ty, + ) } pub fn lower_type(_ctx: &BuildCtx, t: &ast::Type) -> ir::TypeInfo {