floats iter 4.2 fixup: 3-tuple return for builtin_binop_typed + classifier helper
This commit is contained in:
@@ -57,6 +57,20 @@ use synth::{
|
||||
fn_sig_from_type, ll_string_literal, llvm_type,
|
||||
};
|
||||
|
||||
/// Floats iter 4.2 fixup: classify a builtin name as a polymorphic
|
||||
/// arithmetic or comparison op (the set `+`, `-`, `*`, `/`, `%`,
|
||||
/// `!=`, `<`, `<=`, `>`, `>=`). `==` is NOT in this set — it goes
|
||||
/// through `lower_eq` separately. Used by `lower_app` to decide
|
||||
/// whether to call `builtin_binop_typed`, and by `is_static_callee`
|
||||
/// (in combination with `==` and `not`) to recognise built-in
|
||||
/// callees during the global-resolution pass.
|
||||
fn is_arithmetic_or_comparison_op(name: &str) -> bool {
|
||||
matches!(
|
||||
name,
|
||||
"+" | "-" | "*" | "/" | "%" | "!=" | "<" | "<=" | ">" | ">="
|
||||
)
|
||||
}
|
||||
|
||||
/// Failure modes of [`emit_ir`] / [`lower_workspace`].
|
||||
///
|
||||
/// Most variants signal a compiler invariant violation rather than a
|
||||
@@ -1739,14 +1753,14 @@ impl<'a> Emitter<'a> {
|
||||
// Comparison ops are matched here in iter 4.2 with Int-only
|
||||
// dispatch (preserving pre-iter-4 behaviour) so the workspace
|
||||
// stays green; iter 4.3 adds the Float comparison arms.
|
||||
if matches!(name, "+" | "-" | "*" | "/" | "%" | "!=" | "<" | "<=" | ">" | ">=") {
|
||||
if is_arithmetic_or_comparison_op(name) {
|
||||
if args.len() != 2 {
|
||||
return Err(CodegenError::Internal(format!(
|
||||
"builtin `{name}` expected 2 args"
|
||||
)));
|
||||
}
|
||||
let arg_ty = self.synth_arg_type(&args[0])?;
|
||||
let (instr, ll_ty) = builtin_binop_typed(name, &arg_ty)
|
||||
let (instr, operand_ll_ty, result_ll_ty) = builtin_binop_typed(name, &arg_ty)
|
||||
.ok_or_else(|| CodegenError::Internal(format!(
|
||||
"`{name}` not supported for type `{}`",
|
||||
ailang_core::pretty::type_to_string(&arg_ty)
|
||||
@@ -1755,20 +1769,14 @@ impl<'a> Emitter<'a> {
|
||||
let (b, _) = self.lower_term(&args[1])?;
|
||||
let dst = self.fresh_ssa();
|
||||
self.body.push_str(&format!(
|
||||
" {dst} = {instr} {ll_ty} {a}, {b}\n"
|
||||
" {dst} = {instr} {operand_ll_ty} {a}, {b}\n"
|
||||
));
|
||||
// Builtins are not function calls in LLVM (they're inline
|
||||
// arithmetic); `tail` annotation has nothing to act on.
|
||||
// The typechecker accepts the marker but it is a no-op
|
||||
// here. (Iter 14e survey: no fixture marks a builtin tail.)
|
||||
let _ = tail;
|
||||
// Comparison ops return i1; arithmetic returns the operand type.
|
||||
let result_ll_ty = if matches!(name, "!=" | "<" | "<=" | ">" | ">=") {
|
||||
"i1".into()
|
||||
} else {
|
||||
ll_ty.into()
|
||||
};
|
||||
return Ok((dst, result_ll_ty));
|
||||
return Ok((dst, result_ll_ty.into()));
|
||||
}
|
||||
if name == "not" {
|
||||
if args.len() != 1 {
|
||||
@@ -2090,7 +2098,7 @@ impl<'a> Emitter<'a> {
|
||||
/// `prefix.def`. Locals shadow this — the caller checks for
|
||||
/// that first.
|
||||
fn is_static_callee(&self, name: &str) -> bool {
|
||||
if matches!(name, "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<" | "<=" | ">" | ">=") || name == "not" {
|
||||
if is_arithmetic_or_comparison_op(name) || name == "==" || name == "not" {
|
||||
return true;
|
||||
}
|
||||
if name.matches('.').count() == 1 {
|
||||
|
||||
Reference in New Issue
Block a user