use myc::ast::environment::Environment; use myc::ast::types::Value; /// Verifies that bidirectional type inference correctly propagates stream inner types /// into lambda parameters for `pipe` calls with a single stream in a vector `[src]`. /// The lambda parameter should be inferred as the stream's Record type, not `Any`. #[test] fn test_pipe_infers_lambda_param_from_vector_input() { let env = Environment::new(); let source = "(do (def src (create-random-ohlc 42 5)) (pipe [src] (fn [tick] (.close tick))) )"; let dump = env.dump_ast(source).expect("dump_ast failed"); // The lambda parameter `tick` should be inferred as the OHLC Record type, // NOT as `Any`. This validates the Vector → Stream → T hint resolution. assert!( !dump.contains("params: Tuple([Any])"), "Lambda params should NOT be Any — bidirectional inference failed.\nDump:\n{dump}" ); // The pipe call should return Stream(Float), not Stream(Any) assert!( dump.contains("Stream(Float)"), "Pipe should produce Stream(Float), not Stream(Any).\nDump:\n{dump}" ); // Also verify it runs correctly let res = env.run_script(source); assert!(res.is_ok(), "Script failed: {:?}", res.err()); } /// Verifies bidirectional inference for pipe with multiple stream inputs in a tuple. #[test] fn test_pipe_infers_lambda_params_from_tuple_inputs() { let env = Environment::new(); let source = "(do (def src1 (create-random-ohlc 42 5)) (def src2 (create-random-ohlc 99 5)) (pipe [src1 src2] (fn [t1 t2] (+ (.close t1) (.close t2)))) )"; let res = env.run_script(source); assert!(res.is_ok(), "Script failed: {:?}", res.err()); } /// Verifies that pipe with Optional return (filter pattern) still produces Stream(Float). #[test] fn test_pipeline_optional_type() { let env = Environment::new(); // The lambda uses an `if` without an `else` returning a float constant. // The TypeChecker should deduce `Optional(Float)` for the lambda body, // and correctly unwrap it to `Series(Float)` for the pipeline output. let source = "(do (def src (create-random-ohlc 42 10)) (def filtered (pipe [src] (fn [tick] (if true 42.0 ) ) ) ) filtered )"; let res = env.run_script(source); if let Err(e) = &res { panic!("Script failed to compile/run: {:?}", e); } let val = res.unwrap(); if let Value::Object(obj) = val { assert_eq!(obj.type_name(), "StreamNode"); } else { panic!("Expected an Object(StreamNode)"); } }