diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index 5102049..64df45e 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -1090,34 +1090,22 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>( Ok(Some(list.as_ptr_value().into())) } -/// Generates LLVM IR for a [binary operator expression][expr]. -/// -/// * `left` - The left-hand side of the binary operator. -/// * `op` - The operator applied on the operands. -/// * `right` - The right-hand side of the binary operator. -/// * `loc` - The location of the full expression. -/// * `is_aug_assign` - Whether the binary operator expression is also an assignment operator. -pub fn gen_binop_expr<'ctx, G: CodeGenerator>( +/// Generates LLVM IR for a binary operator expression using the [`Type`] and +/// [LLVM value][`BasicValueEnum`] of the operands. +pub fn gen_binop_expr_with_values<'ctx, G: CodeGenerator>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, - left: &Expr>, + left: (&Option, BasicValueEnum<'ctx>), op: &Operator, - right: &Expr>, + right: (&Option, BasicValueEnum<'ctx>), loc: Location, is_aug_assign: bool, ) -> Result>, String> { - let ty1 = ctx.unifier.get_representative(left.custom.unwrap()); - let ty2 = ctx.unifier.get_representative(right.custom.unwrap()); - let left_val = if let Some(v) = generator.gen_expr(ctx, left)? { - v.to_basic_value_enum(ctx, generator, left.custom.unwrap())? - } else { - return Ok(None) - }; - let right_val = if let Some(v) = generator.gen_expr(ctx, right)? { - v.to_basic_value_enum(ctx, generator, right.custom.unwrap())? - } else { - return Ok(None) - }; + let (left_ty, left_val) = left; + let (right_ty, right_val) = right; + + let ty1 = ctx.unifier.get_representative(left_ty.unwrap()); + let ty2 = ctx.unifier.get_representative(right_ty.unwrap()); // we can directly compare the types, because we've got their representatives // which would be unchanged until further unification, which we would never do @@ -1142,7 +1130,7 @@ pub fn gen_binop_expr<'ctx, G: CodeGenerator>( ); Ok(Some(res.into())) } else { - let left_ty_enum = ctx.unifier.get_ty_immutable(left.custom.unwrap()); + let left_ty_enum = ctx.unifier.get_ty_immutable(left_ty.unwrap()); let TypeEnum::TObj { fields, obj_id, .. } = left_ty_enum.as_ref() else { unreachable!("must be tobj") }; @@ -1162,7 +1150,7 @@ pub fn gen_binop_expr<'ctx, G: CodeGenerator>( let signature = if let Some(call) = ctx.calls.get(&loc.into()) { ctx.unifier.get_call_signature(*call).unwrap() } else { - let left_enum_ty = ctx.unifier.get_ty_immutable(left.custom.unwrap()); + let left_enum_ty = ctx.unifier.get_ty_immutable(left_ty.unwrap()); let TypeEnum::TObj { fields, .. } = left_enum_ty.as_ref() else { unreachable!("must be tobj") }; @@ -1187,13 +1175,51 @@ pub fn gen_binop_expr<'ctx, G: CodeGenerator>( generator .gen_call( ctx, - Some((left.custom.unwrap(), left_val.into())), + Some((left_ty.unwrap(), left_val.into())), (&signature, fun_id), vec![(None, right_val.into())], ).map(|f| f.map(Into::into)) } } +/// Generates LLVM IR for a [binary operator expression][expr]. +/// +/// * `left` - The left-hand side of the binary operator. +/// * `op` - The operator applied on the operands. +/// * `right` - The right-hand side of the binary operator. +/// * `loc` - The location of the full expression. +/// * `is_aug_assign` - Whether the binary operator expression is also an assignment operator. +pub fn gen_binop_expr<'ctx, G: CodeGenerator>( + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + left: &Expr>, + op: &Operator, + right: &Expr>, + loc: Location, + is_aug_assign: bool, +) -> Result>, String> { + let left_val = if let Some(v) = generator.gen_expr(ctx, left)? { + v.to_basic_value_enum(ctx, generator, left.custom.unwrap())? + } else { + return Ok(None) + }; + let right_val = if let Some(v) = generator.gen_expr(ctx, right)? { + v.to_basic_value_enum(ctx, generator, right.custom.unwrap())? + } else { + return Ok(None) + }; + + gen_binop_expr_with_values( + generator, + ctx, + (&left.custom, left_val), + op, + (&right.custom, right_val), + loc, + is_aug_assign, + ) +} + /// Generates code for a subscript expression on an `ndarray`. /// /// * `ty` - The `Type` of the `NDArray` elements.