core/codegen/expr: WIP - Split cmpop
This commit is contained in:
parent
5450147007
commit
d457e6c986
|
@ -1379,6 +1379,127 @@ pub fn gen_unaryop_expr<'ctx, G: CodeGenerator>(
|
||||||
gen_unaryop_expr_with_values(generator, ctx, op, (&operand.custom, val))
|
gen_unaryop_expr_with_values(generator, ctx, op, (&operand.custom, val))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn gen_cmpop_expr_with_values<'ctx, G: CodeGenerator>(
|
||||||
|
_generator: &mut G,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
left: (Option<Type>, BasicValueEnum<'ctx>),
|
||||||
|
ops: &[ast::Cmpop],
|
||||||
|
comparators: &[(Option<Type>, BasicValueEnum<'ctx>)],
|
||||||
|
) -> Result<Option<ValueEnum<'ctx>>, String> {
|
||||||
|
let cmp_val = izip!(chain(once(&left), comparators.iter()), comparators.iter(), ops.iter(),)
|
||||||
|
.fold(Ok(None), |prev: Result<Option<_>, String>, (lhs, rhs, op)| {
|
||||||
|
let (left_ty, lhs) = lhs;
|
||||||
|
let (right_ty, rhs) = rhs;
|
||||||
|
|
||||||
|
let left_ty = ctx.unifier.get_representative(left_ty.unwrap());
|
||||||
|
let right_ty = ctx.unifier.get_representative(right_ty.unwrap());
|
||||||
|
|
||||||
|
let current =
|
||||||
|
if [ctx.primitives.int32, ctx.primitives.int64, ctx.primitives.uint32, ctx.primitives.uint64, ctx.primitives.bool]
|
||||||
|
.contains(&left_ty)
|
||||||
|
{
|
||||||
|
assert!(ctx.unifier.unioned(left_ty, right_ty));
|
||||||
|
|
||||||
|
let use_unsigned_ops = [
|
||||||
|
ctx.primitives.uint32,
|
||||||
|
ctx.primitives.uint64,
|
||||||
|
].contains(&left_ty);
|
||||||
|
|
||||||
|
let lhs = lhs.into_int_value();
|
||||||
|
let rhs = rhs.into_int_value();
|
||||||
|
|
||||||
|
let op = match op {
|
||||||
|
ast::Cmpop::Eq | ast::Cmpop::Is => IntPredicate::EQ,
|
||||||
|
ast::Cmpop::NotEq => IntPredicate::NE,
|
||||||
|
_ if left_ty == ctx.primitives.bool => unreachable!(),
|
||||||
|
ast::Cmpop::Lt => if use_unsigned_ops {
|
||||||
|
IntPredicate::ULT
|
||||||
|
} else {
|
||||||
|
IntPredicate::SLT
|
||||||
|
},
|
||||||
|
ast::Cmpop::LtE => if use_unsigned_ops {
|
||||||
|
IntPredicate::ULE
|
||||||
|
} else {
|
||||||
|
IntPredicate::SLE
|
||||||
|
},
|
||||||
|
ast::Cmpop::Gt => if use_unsigned_ops {
|
||||||
|
IntPredicate::UGT
|
||||||
|
} else {
|
||||||
|
IntPredicate::SGT
|
||||||
|
},
|
||||||
|
ast::Cmpop::GtE => if use_unsigned_ops {
|
||||||
|
IntPredicate::UGE
|
||||||
|
} else {
|
||||||
|
IntPredicate::SGE
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.builder.build_int_compare(op, lhs, rhs, "cmp").unwrap()
|
||||||
|
} else if left_ty == ctx.primitives.float {
|
||||||
|
assert!(ctx.unifier.unioned(left_ty, right_ty));
|
||||||
|
|
||||||
|
let lhs = lhs.into_float_value();
|
||||||
|
let rhs = rhs.into_float_value();
|
||||||
|
|
||||||
|
let op = match op {
|
||||||
|
ast::Cmpop::Eq | ast::Cmpop::Is => inkwell::FloatPredicate::OEQ,
|
||||||
|
ast::Cmpop::NotEq => inkwell::FloatPredicate::ONE,
|
||||||
|
ast::Cmpop::Lt => inkwell::FloatPredicate::OLT,
|
||||||
|
ast::Cmpop::LtE => inkwell::FloatPredicate::OLE,
|
||||||
|
ast::Cmpop::Gt => inkwell::FloatPredicate::OGT,
|
||||||
|
ast::Cmpop::GtE => inkwell::FloatPredicate::OGE,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
ctx.builder.build_float_compare(op, lhs, rhs, "cmp").unwrap()
|
||||||
|
} else {
|
||||||
|
unimplemented!()
|
||||||
|
};
|
||||||
|
Ok(prev?.map(|v| ctx.builder.build_and(v, current, "cmp").unwrap()).or(Some(current)))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(Some(match cmp_val {
|
||||||
|
Some(v) => v.into(),
|
||||||
|
None => return Ok(None),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen_cmpop_expr<'ctx, G: CodeGenerator>(
|
||||||
|
generator: &mut G,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
left: &Expr<Option<Type>>,
|
||||||
|
ops: &[ast::Cmpop],
|
||||||
|
comparators: &[Expr<Option<Type>>],
|
||||||
|
) -> Result<Option<ValueEnum<'ctx>>, 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 comparators = {
|
||||||
|
let mut new_comparators = Vec::new();
|
||||||
|
new_comparators.reserve(comparators.len());
|
||||||
|
|
||||||
|
for cmptor in comparators {
|
||||||
|
if let Some(v) = generator.gen_expr(ctx, cmptor)? {
|
||||||
|
new_comparators.push((cmptor.custom, v.to_basic_value_enum(ctx, generator, cmptor.custom.unwrap())?))
|
||||||
|
} else {
|
||||||
|
return Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new_comparators
|
||||||
|
};
|
||||||
|
|
||||||
|
gen_cmpop_expr_with_values(
|
||||||
|
generator,
|
||||||
|
ctx,
|
||||||
|
(left.custom, left_val),
|
||||||
|
ops,
|
||||||
|
comparators.as_slice(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Generates code for a subscript expression on an `ndarray`.
|
/// Generates code for a subscript expression on an `ndarray`.
|
||||||
///
|
///
|
||||||
/// * `ty` - The `Type` of the `NDArray` elements.
|
/// * `ty` - The `Type` of the `NDArray` elements.
|
||||||
|
@ -1758,87 +1879,7 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
|
||||||
return gen_unaryop_expr(generator, ctx, op, operand)
|
return gen_unaryop_expr(generator, ctx, op, operand)
|
||||||
}
|
}
|
||||||
ExprKind::Compare { left, ops, comparators } => {
|
ExprKind::Compare { left, ops, comparators } => {
|
||||||
let cmp_val = izip!(chain(once(left.as_ref()), comparators.iter()), comparators.iter(), ops.iter(),)
|
return gen_cmpop_expr(generator, ctx, left, &ops, &comparators)
|
||||||
.fold(Ok(None), |prev: Result<Option<_>, String>, (lhs, rhs, op)| {
|
|
||||||
let ty = ctx.unifier.get_representative(lhs.custom.unwrap());
|
|
||||||
let current =
|
|
||||||
if [ctx.primitives.int32, ctx.primitives.int64, ctx.primitives.uint32, ctx.primitives.uint64, ctx.primitives.bool]
|
|
||||||
.contains(&ty)
|
|
||||||
{
|
|
||||||
let use_unsigned_ops = [
|
|
||||||
ctx.primitives.uint32,
|
|
||||||
ctx.primitives.uint64,
|
|
||||||
].contains(&ty);
|
|
||||||
|
|
||||||
let BasicValueEnum::IntValue(lhs) = (match generator.gen_expr(ctx, lhs)? {
|
|
||||||
Some(v) => v.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?,
|
|
||||||
None => return Ok(None),
|
|
||||||
}) else { unreachable!() };
|
|
||||||
|
|
||||||
let BasicValueEnum::IntValue(rhs) = (match generator.gen_expr(ctx, rhs)? {
|
|
||||||
Some(v) => v.to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?,
|
|
||||||
None => return Ok(None),
|
|
||||||
}) else { unreachable!() };
|
|
||||||
|
|
||||||
let op = match op {
|
|
||||||
ast::Cmpop::Eq | ast::Cmpop::Is => IntPredicate::EQ,
|
|
||||||
ast::Cmpop::NotEq => IntPredicate::NE,
|
|
||||||
_ if ty == ctx.primitives.bool => unreachable!(),
|
|
||||||
ast::Cmpop::Lt => if use_unsigned_ops {
|
|
||||||
IntPredicate::ULT
|
|
||||||
} else {
|
|
||||||
IntPredicate::SLT
|
|
||||||
},
|
|
||||||
ast::Cmpop::LtE => if use_unsigned_ops {
|
|
||||||
IntPredicate::ULE
|
|
||||||
} else {
|
|
||||||
IntPredicate::SLE
|
|
||||||
},
|
|
||||||
ast::Cmpop::Gt => if use_unsigned_ops {
|
|
||||||
IntPredicate::UGT
|
|
||||||
} else {
|
|
||||||
IntPredicate::SGT
|
|
||||||
},
|
|
||||||
ast::Cmpop::GtE => if use_unsigned_ops {
|
|
||||||
IntPredicate::UGE
|
|
||||||
} else {
|
|
||||||
IntPredicate::SGE
|
|
||||||
},
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
ctx.builder.build_int_compare(op, lhs, rhs, "cmp").unwrap()
|
|
||||||
} else if ty == ctx.primitives.float {
|
|
||||||
let BasicValueEnum::FloatValue(lhs) = (match generator.gen_expr(ctx, lhs)? {
|
|
||||||
Some(v) => v.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?,
|
|
||||||
None => return Ok(None),
|
|
||||||
}) else { unreachable!() };
|
|
||||||
|
|
||||||
let BasicValueEnum::FloatValue(rhs) = (match generator.gen_expr(ctx, rhs)? {
|
|
||||||
Some(v) => v.to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?,
|
|
||||||
None => return Ok(None),
|
|
||||||
}) else { unreachable!() };
|
|
||||||
|
|
||||||
let op = match op {
|
|
||||||
ast::Cmpop::Eq | ast::Cmpop::Is => inkwell::FloatPredicate::OEQ,
|
|
||||||
ast::Cmpop::NotEq => inkwell::FloatPredicate::ONE,
|
|
||||||
ast::Cmpop::Lt => inkwell::FloatPredicate::OLT,
|
|
||||||
ast::Cmpop::LtE => inkwell::FloatPredicate::OLE,
|
|
||||||
ast::Cmpop::Gt => inkwell::FloatPredicate::OGT,
|
|
||||||
ast::Cmpop::GtE => inkwell::FloatPredicate::OGE,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
ctx.builder.build_float_compare(op, lhs, rhs, "cmp").unwrap()
|
|
||||||
} else {
|
|
||||||
unimplemented!()
|
|
||||||
};
|
|
||||||
Ok(prev?.map(|v| ctx.builder.build_and(v, current, "cmp").unwrap()).or(Some(current)))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
match cmp_val {
|
|
||||||
Some(v) => v.into(),
|
|
||||||
None => return Ok(None),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ExprKind::IfExp { test, body, orelse } => {
|
ExprKind::IfExp { test, body, orelse } => {
|
||||||
let test = match generator.gen_expr(ctx, test)? {
|
let test = match generator.gen_expr(ctx, test)? {
|
||||||
|
|
Loading…
Reference in New Issue