diff --git a/crates/ailang-check/src/builtins.rs b/crates/ailang-check/src/builtins.rs index 7997185..e2060bc 100644 --- a/crates/ailang-check/src/builtins.rs +++ b/crates/ailang-check/src/builtins.rs @@ -51,7 +51,9 @@ pub fn install(env: &mut crate::Env) { // Iter 22-floats.3: arithmetic and comparison ops are polymorphic. // Same shape as `==` below — the {Int, Float}-restriction is // enforced at codegen, not at typecheck. `%` stays Int-only - // (no fmod yet — see spec section A3). + // (no fmod yet — `%` semantics for Float require an explicit + // decision on sign-of-result and ±0/±Inf edge cases that has + // not been made). let poly_a_a_to_a = || Type::Forall { vars: vec!["a".into()], constraints: vec![], @@ -95,12 +97,15 @@ pub fn install(env: &mut crate::Env) { env.globals.insert(op.into(), poly_a_a_to_bool()); } - // Iter 16e: `==` is polymorphic — `forall a. (a, a) -> Bool`. - // Codegen dispatches on the resolved arg type at the call site: + // `==` is polymorphic — `forall a. (a, a) -> Bool`. Codegen + // dispatches on the resolved arg type at the call site: // `Int` → `icmp eq i64`, `Bool` → `icmp eq i1`, `Str` → `@strcmp`, - // `Unit` → constant `i1 1`. ADT/Fn equality is rejected at codegen - // with a clear "== not supported for type X" error. The other - // comparison ops (`<`, `<=`, `>`, `>=`, `!=`) stay Int-only. + // `Unit` → constant `i1 1`, `Float` → `fcmp oeq double`. ADT/Fn + // equality is rejected at codegen with a clear "== not supported + // for type X" error. The ordering ops (`<`, `<=`, `>`, `>=`, `!=`) + // share the same polymorphic shape but with `Bool` return; `==` + // stays in its own arm only because the codegen-side dispatch + // table has historically been per-op. env.globals.insert( "==".into(), Type::Forall { @@ -278,8 +283,9 @@ mod tests { /// happens in iter 4. #[test] fn widen_plus_accepts_float_float_float() { - let bits = 1.5_f64.to_bits(); - let ty = synth_in_builtins_env(&app("+", vec![lit_float(bits), lit_float(bits)])); + let bits_a = 1.5_f64.to_bits(); + let bits_b = 2.5_f64.to_bits(); + let ty = synth_in_builtins_env(&app("+", vec![lit_float(bits_a), lit_float(bits_b)])); assert_eq!(ty, Type::float(), "(+ 1.5 2.5) must type as Float"); } @@ -298,8 +304,9 @@ mod tests { /// typecheck cleanly; codegen lowers to `fcmp olt double` in iter 4. #[test] fn widen_lt_accepts_float_float_bool() { - let bits = 1.5_f64.to_bits(); - let ty = synth_in_builtins_env(&app("<", vec![lit_float(bits), lit_float(bits)])); - assert_eq!(ty, Type::bool_(), "(< 1.5 1.5) must type as Bool"); + let bits_a = 1.5_f64.to_bits(); + let bits_b = 2.5_f64.to_bits(); + let ty = synth_in_builtins_env(&app("<", vec![lit_float(bits_a), lit_float(bits_b)])); + assert_eq!(ty, Type::bool_(), "(< 1.5 2.5) must type as Bool"); } }