From e30ec02037494734907af58bdaf797b70b65ff11 Mon Sep 17 00:00:00 2001 From: dak2 Date: Sat, 31 Jan 2026 11:02:13 +0900 Subject: [PATCH] Support Float --- rust/src/analyzer/literals.rs | 15 ++++- rust/src/analyzer/tests/integration_test.rs | 66 +++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/rust/src/analyzer/literals.rs b/rust/src/analyzer/literals.rs index ab641ce..2628fd4 100644 --- a/rust/src/analyzer/literals.rs +++ b/rust/src/analyzer/literals.rs @@ -1,7 +1,7 @@ //! Literal Handlers - Processing Ruby literal values //! //! This module is responsible for: -//! - String, Integer, Hash literals +//! - String, Integer, Float, Hash literals //! - nil, true, false, Symbol literals //! - Creating Source vertices with fixed types //! @@ -27,6 +27,11 @@ pub fn install_literal(genv: &mut GlobalEnv, node: &Node) -> Option { return Some(genv.new_source(Type::integer())); } + // 3.14 + if node.as_float_node().is_some() { + return Some(genv.new_source(Type::float())); + } + // {a: 1} if node.as_hash_node().is_some() { return Some(genv.new_source(Type::hash())); @@ -76,4 +81,12 @@ mod tests { let vtx = genv.new_source(Type::integer()); assert_eq!(genv.get_source(vtx).unwrap().ty.show(), "Integer"); } + + #[test] + fn test_install_float_literal() { + let mut genv = GlobalEnv::new(); + + let vtx = genv.new_source(Type::float()); + assert_eq!(genv.get_source(vtx).unwrap().ty.show(), "Float"); + } } diff --git a/rust/src/analyzer/tests/integration_test.rs b/rust/src/analyzer/tests/integration_test.rs index 770e796..c645123 100644 --- a/rust/src/analyzer/tests/integration_test.rs +++ b/rust/src/analyzer/tests/integration_test.rs @@ -21,6 +21,14 @@ fn analyze(source: &str) -> (GlobalEnv, LocalEnv) { genv.register_builtin_method(Type::string(), "upcase", Type::string()); genv.register_builtin_method(Type::string(), "downcase", Type::string()); + // Register Float methods + genv.register_builtin_method(Type::float(), "to_s", Type::string()); + genv.register_builtin_method(Type::float(), "to_i", Type::integer()); + genv.register_builtin_method(Type::float(), "round", Type::integer()); + genv.register_builtin_method(Type::float(), "ceil", Type::integer()); + genv.register_builtin_method(Type::float(), "floor", Type::integer()); + genv.register_builtin_method(Type::float(), "abs", Type::float()); + // Register iterator methods for block tests genv.register_builtin_method(Type::array(), "each", Type::array()); genv.register_builtin_method(Type::array(), "map", Type::array()); @@ -405,3 +413,61 @@ end // No type errors should occur assert_eq!(genv.type_errors.len(), 0); } + +// ============================================ +// Float Literal Tests +// ============================================ + +#[test] +fn test_float_literal_basic() { + let source = r#"x = 3.14"#; + + let (genv, lenv) = analyze(source); + + let x_vtx = lenv.get_var("x").unwrap(); + assert_eq!(genv.get_vertex(x_vtx).unwrap().show(), "Float"); +} + +#[test] +fn test_float_literal_type_error() { + let source = r#" +class Calculator + def compute + x = 3.14 + y = x.upcase + end +end +"#; + + let (genv, _lenv) = analyze(source); + + // Type error should be detected: Float doesn't have upcase method + assert_eq!(genv.type_errors.len(), 1); + assert_eq!(genv.type_errors[0].method_name, "upcase"); +} + +#[test] +fn test_float_specific_methods() { + let source = r#" +x = 3.14 +a = x.ceil +b = x.floor +c = x.abs +"#; + + let (genv, lenv) = analyze(source); + + // No type errors - ceil, floor, abs are valid Float methods + assert_eq!(genv.type_errors.len(), 0); + + // ceil and floor return Integer + let a_vtx = lenv.get_var("a").unwrap(); + assert_eq!(genv.get_vertex(a_vtx).unwrap().show(), "Integer"); + + let b_vtx = lenv.get_var("b").unwrap(); + assert_eq!(genv.get_vertex(b_vtx).unwrap().show(), "Integer"); + + // abs returns Float + let c_vtx = lenv.get_var("c").unwrap(); + assert_eq!(genv.get_vertex(c_vtx).unwrap().show(), "Float"); +}