Refactor series types and value enum

This commit refactors the way series are represented and handled within
the AST.
Key changes include:

- Introducing `SeriesStorage` and `PushableStorage` traits to provide a
  more
  unified and type-safe interface for series data.
- Renaming `Object` trait and its methods to clarify that it's for RTL
  extensions
  other than series (like Streams).
- Updating the `Value` enum to have a distinct `Series` variant,
  separating it
  from `Object`.
- Adjusting various parts of the `VM` and `register` functions to work
  with the
  new series traits and `Value::Series` variant.

This change aims to improve the type system's clarity and safety when
dealing with
series data, aligning with Rust's best practices for trait design.
This commit is contained in:
2026-03-23 16:05:58 +01:00
parent a5c3f3da04
commit 6042415dfc
4 changed files with 227 additions and 225 deletions
+12 -14
View File
@@ -25,10 +25,10 @@ pub fn register(env: &Environment) {
match arg {
Value::Keyword(k) => {
match k.name().to_lowercase().as_str() {
"float" => Value::Object(Rc::new(ScalarSeries::<f64>::new("FloatSeries", lookback_limit))),
"int" | "datetime" => Value::Object(Rc::new(ScalarSeries::<i64>::new("IntSeries", lookback_limit))),
"bool" => Value::Object(Rc::new(ScalarSeries::<bool>::new("BoolSeries", lookback_limit))),
"text" => Value::Object(Rc::new(ValueSeries::new(lookback_limit))),
"float" => Value::Series(Rc::new(ScalarSeries::<f64>::new("FloatSeries", lookback_limit))),
"int" | "datetime" => Value::Series(Rc::new(ScalarSeries::<i64>::new("IntSeries", lookback_limit))),
"bool" => Value::Series(Rc::new(ScalarSeries::<bool>::new("BoolSeries", lookback_limit))),
"text" => Value::Series(Rc::new(ValueSeries::new(lookback_limit))),
_ => panic!("Unknown or unsupported series type keyword: :{}", k.name()),
}
}
@@ -51,7 +51,7 @@ pub fn register(env: &Environment) {
fields.push((*name, ty));
}
let final_layout = RecordLayout::get_or_create(fields);
Value::Object(Rc::new(RecordSeries::new(final_layout, lookback_limit)))
Value::Series(Rc::new(RecordSeries::new(final_layout, lookback_limit)))
}
_ => panic!("series expects a lookback_limit and a type keyword (:float, :int...) or a schema record (e.g., {{:price :float}})"),
}
@@ -69,14 +69,14 @@ pub fn register(env: &Environment) {
|args: &[Value]| {
let (series_val, val) = (&args[0], &args[1]);
if let Value::Object(obj) = series_val {
if let Some(p) = obj.as_pushable_series() {
p.push_value(val.clone());
return Value::Void;
if let Value::Series(s) = series_val {
match s.as_pushable() {
Some(p) => p.push_value(val.clone()),
None => panic!("push expects a mutable series, got read-only {}", s.series_type_name()),
}
panic!("push expects a pushable series, got: {}", obj.type_name());
return Value::Void;
}
panic!("push expects a series object as the first argument")
panic!("push expects a series as the first argument")
},
);
@@ -89,9 +89,7 @@ pub fn register(env: &Environment) {
})),
Purity::Pure,
|args: &[Value]| {
if let Value::Object(obj) = &args[0]
&& let Some(s) = obj.as_series()
{
if let Value::Series(s) = &args[0] {
return Value::Int(s.len() as i64);
}
Value::Int(0)