Add Optional type for filter pipes

Introduces `StaticType::Optional` to represent values that can be either
of a specific type `T` or `Void`. This is crucial for handling
situations in filter pipes where an expression might not always produce
a value.

The type checker now correctly deduces and propagates this `Optional`
type, and the pipeline operator (`pipe`) is updated to unwrap
`Optional(T)` results, yielding `T`. This ensures that the type system
accurately reflects the potential absence of values in intermediate
pipeline steps.

Also includes a minor rename in the tuple-struct example from `pipe` to
`p` for clarity, and registers the `streams` module.
This commit is contained in:
Michael Schimmel
2026-03-01 23:19:00 +01:00
parent b177aa8854
commit 807903efbb
5 changed files with 50 additions and 6 deletions
+32
View File
@@ -360,6 +360,38 @@ mod tests {
}
}
#[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 crate::ast::types::Value::Object(obj) = val {
assert_eq!(obj.type_name(), "PipelineNode");
} else {
panic!("Expected an Object(PipelineNode)");
}
}
#[test]
fn test_multi_level_destructuring() {
let env = Environment::new();