From 9ba4f795d148569b4ef03455755ddbe35d2a1423 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Thu, 5 Mar 2026 15:07:31 +0100 Subject: [PATCH] Change series field type from :msg to :text Update example to use :text for string fields in series. This aligns with the new :text type support in the series implementation. --- examples/soa_series.myc | 2 +- src/ast/rtl/series.rs | 75 +++++++++++++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 15 deletions(-) diff --git a/examples/soa_series.myc b/examples/soa_series.myc index 0c7de63..8c8cb30 100644 --- a/examples/soa_series.myc +++ b/examples/soa_series.myc @@ -2,7 +2,7 @@ ;; Benchmark: 1.0us ;; Benchmark-Repeat: 1944 (do - (def my_ticks (series {:price :float :volume :int :msg :string})) + (def my_ticks (series {:price :float :volume :int :msg :text})) (push my_ticks {:price 10.5 :volume 100 :msg "A"}) (push my_ticks {:price 11.2 :volume 200 :msg "B"}) diff --git a/src/ast/rtl/series.rs b/src/ast/rtl/series.rs index 005a659..e4ee932 100644 --- a/src/ast/rtl/series.rs +++ b/src/ast/rtl/series.rs @@ -313,7 +313,12 @@ impl RecordSeries { impl Debug for RecordSeries { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "RecordSeries[fields: {}, len: {}]", self.fields.len(), Series::len(self)) + write!( + f, + "RecordSeries[fields: {}, len: {}]", + self.fields.len(), + Series::len(self) + ) } } @@ -337,7 +342,10 @@ impl Series for RecordSeries { self.fields.first().map(|f| f.borrow().len()).unwrap_or(0) } fn total_count(&self) -> u64 { - self.fields.first().map(|f| f.borrow().total_count()).unwrap_or(0) + self.fields + .first() + .map(|f| f.borrow().total_count()) + .unwrap_or(0) } } @@ -359,7 +367,12 @@ impl SeriesView { impl Debug for SeriesView { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "SeriesView[field: {}, len: {}]", self.field_name.name(), Series::len(self)) + write!( + f, + "SeriesView[field: {}, len: {}]", + self.field_name.name(), + Series::len(self) + ) } } @@ -428,8 +441,12 @@ impl Series for SharedSeries { .get(index) .map(|&v| (self.converter)(v)) } - fn len(&self) -> usize { self.buffer.borrow().len() } - fn total_count(&self) -> u64 { self.buffer.borrow().total_count() } + fn len(&self) -> usize { + self.buffer.borrow().len() + } + fn total_count(&self) -> u64 { + self.buffer.borrow().total_count() + } } #[derive(Clone)] @@ -459,8 +476,12 @@ impl Series for SharedValueSeries { fn get_item(&self, index: usize) -> Option { self.buffer.borrow().get(index).cloned() } - fn len(&self) -> usize { self.buffer.borrow().len() } - fn total_count(&self) -> u64 { self.buffer.borrow().total_count() } + fn len(&self) -> usize { + self.buffer.borrow().len() + } + fn total_count(&self) -> u64 { + self.buffer.borrow().total_count() + } } #[derive(Clone)] @@ -509,10 +530,16 @@ impl Series for SharedRecordSeries { Some(Value::Record(self.layout.clone(), Rc::new(vals))) } fn len(&self) -> usize { - self.field_buffers.first().map(|f| f.borrow().len()).unwrap_or(0) + self.field_buffers + .first() + .map(|f| f.borrow().len()) + .unwrap_or(0) } fn total_count(&self) -> u64 { - self.field_buffers.first().map(|f| f.borrow().total_count()).unwrap_or(0) + self.field_buffers + .first() + .map(|f| f.borrow().total_count()) + .unwrap_or(0) } } @@ -532,17 +559,37 @@ pub fn register(env: &Environment) { |args: &[Value]| { let arg = &args[0]; match arg { - Value::Record(layout, _) => Value::Object(Rc::new(RecordSeries::new(layout.clone()))), Value::Keyword(k) => { match k.name().to_lowercase().as_str() { "float" => Value::Object(Rc::new(ScalarSeries::::new("FloatSeries"))), "int" | "datetime" => Value::Object(Rc::new(ScalarSeries::::new("IntSeries"))), "bool" => Value::Object(Rc::new(ScalarSeries::::new("BoolSeries"))), - "any" => Value::Object(Rc::new(ValueSeries::new())), - _ => panic!("Unknown series type keyword: :{}", k.name()), + "text" => Value::Object(Rc::new(ValueSeries::new())), + _ => panic!("Unknown or unsupported series type keyword: :{}", k.name()), } } - _ => panic!("series expects a record template or a type keyword (e.g., :float, :int, :bool, :any)"), + Value::Record(schema_layout, schema_values) => { + // Interpret the record as a schema: { :field :type_keyword } + let mut fields = Vec::with_capacity(schema_layout.fields.len()); + for (i, (name, _)) in schema_layout.fields.iter().enumerate() { + let type_keyword = match &schema_values[i] { + Value::Keyword(tk) => tk.name().to_lowercase(), + _ => panic!("Field :{} in series schema must be a type keyword (e.g., :float, :int)", name.name()), + }; + let ty = match type_keyword.as_str() { + "float" => StaticType::Float, + "int" => StaticType::Int, + "bool" => StaticType::Bool, + "datetime" => StaticType::DateTime, + "text" => StaticType::Text, + _ => panic!("Unsupported type keyword :{} for series field :{}", type_keyword, name.name()), + }; + fields.push((*name, ty)); + } + let final_layout = RecordLayout::get_or_create(fields); + Value::Object(Rc::new(RecordSeries::new(final_layout))) + } + _ => panic!("series expects a type keyword (:float, :int...) or a schema record (e.g., {{:price :float}})"), } }, ); @@ -560,7 +607,7 @@ pub fn register(env: &Environment) { if let Value::Object(obj) = series_val { let any = obj.as_any(); - + // Polymorphic push logic if let Some(rs) = any.downcast_ref::() { if let Value::Record(_, values) = val {