Fix: Improve series type handling and coercions
This commit enhances the series type handling in `src/ast/rtl/series.rs` by introducing helper methods `as_float` and `as_int` in `src/ast/types.rs` to manage type conversions more robustly. It also updates the function overload resolution in `src/ast/types.rs` to prioritize exact parameter matches before falling back to implicit coercions. Finally, the example `err.myc` has been updated to reflect a more accurate implementation of a Simple Moving Average (SMA) calculation.
This commit is contained in:
+32
-4
@@ -1,6 +1,34 @@
|
||||
;; Output: 0
|
||||
(do
|
||||
(def history (series :float))
|
||||
(push history 0.0)
|
||||
(history 0)
|
||||
(def SMA
|
||||
(fn [length]
|
||||
(do
|
||||
(def history (series :float))
|
||||
(def sum 0.0)
|
||||
|
||||
(fn [val]
|
||||
(do
|
||||
(def hist_len (len history))
|
||||
(if (>= hist_len length)
|
||||
(assign sum (- sum (history (- hist_len 1))))
|
||||
...)
|
||||
|
||||
(push history val)
|
||||
(assign sum (+ sum val))
|
||||
(/ sum (len history))
|
||||
)))))
|
||||
|
||||
(def sma10 (SMA 10))
|
||||
|
||||
(sma10 1)
|
||||
(sma10 2)
|
||||
(sma10 3)
|
||||
(sma10 4)
|
||||
(sma10 5)
|
||||
(sma10 6)
|
||||
(sma10 7)
|
||||
(sma10 8)
|
||||
(sma10 9)
|
||||
(sma10 10)
|
||||
(sma10 11)
|
||||
|
||||
)
|
||||
+22
-23
@@ -1,25 +1,24 @@
|
||||
(do
|
||||
(def SMA
|
||||
(fn [length]
|
||||
(do
|
||||
(def history (series :float))
|
||||
(push history 0)
|
||||
|
||||
(fn [val]
|
||||
(do
|
||||
(def sum (+ val (history 0)))
|
||||
(push history sum)
|
||||
(/ sum length)
|
||||
(history 0)
|
||||
))
|
||||
)))
|
||||
|
||||
(def sma20 (SMA 20))
|
||||
|
||||
(def n 100)
|
||||
(while (> n 0)
|
||||
(do
|
||||
(print "val=" n " sma20=" (sma20 n))
|
||||
(assign n (- n 1))
|
||||
))
|
||||
(def SMA
|
||||
(fn [length]
|
||||
(do
|
||||
(def history (series :float))
|
||||
(push history 0)
|
||||
|
||||
(fn [val]
|
||||
(do
|
||||
(def sum (+ val (history 0)))
|
||||
(push history sum)
|
||||
(/ sum length)
|
||||
))
|
||||
)))
|
||||
|
||||
(def sma20 (SMA 20))
|
||||
|
||||
(def n 100)
|
||||
(while (> n 0)
|
||||
(do
|
||||
(print "val=" n " sma20=" (sma20 n))
|
||||
(assign n (- n 1))
|
||||
))
|
||||
)
|
||||
@@ -218,19 +218,16 @@ pub trait SeriesMember: Object + Series {
|
||||
|
||||
impl SeriesMember for ScalarSeries<f64> {
|
||||
fn push_value(&self, value: Value, limit: Option<usize>) {
|
||||
match value {
|
||||
Value::Float(v) => self.data.borrow_mut().push(v, limit),
|
||||
Value::Int(v) => self.data.borrow_mut().push(v as f64, limit),
|
||||
_ => {}
|
||||
if let Some(v) = value.as_float() {
|
||||
self.data.borrow_mut().push(v, limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SeriesMember for ScalarSeries<i64> {
|
||||
fn push_value(&self, value: Value, limit: Option<usize>) {
|
||||
match value {
|
||||
Value::Int(v) | Value::DateTime(v) => self.data.borrow_mut().push(v, limit),
|
||||
_ => {}
|
||||
if let Some(v) = value.as_int() {
|
||||
self.data.borrow_mut().push(v, limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+25
-1
@@ -394,6 +394,12 @@ impl StaticType {
|
||||
}
|
||||
|
||||
match (self, other) {
|
||||
// Implicit Coercions
|
||||
(StaticType::Float, StaticType::Int) => true,
|
||||
(StaticType::Int, StaticType::Bool) => true,
|
||||
(StaticType::Int, StaticType::DateTime) => true,
|
||||
(StaticType::DateTime, StaticType::Int) => true,
|
||||
|
||||
// Optional(T) is assignable from T or Void
|
||||
(StaticType::Optional(inner), other) => {
|
||||
matches!(other, StaticType::Void) || inner.is_assignable_from(other)
|
||||
@@ -471,7 +477,8 @@ impl StaticType {
|
||||
}
|
||||
StaticType::FunctionOverloads(sigs) => sigs
|
||||
.iter()
|
||||
.find(|sig| sig.params.is_assignable_from(args_ty))
|
||||
.find(|sig| sig.params == *args_ty) // 1. Try exact match first
|
||||
.or_else(|| sigs.iter().find(|sig| sig.params.is_assignable_from(args_ty))) // 2. Fallback to implicit coercion
|
||||
.map(|sig| sig.ret.clone()),
|
||||
_ => None,
|
||||
}
|
||||
@@ -490,6 +497,23 @@ impl StaticType {
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn as_float(&self) -> Option<f64> {
|
||||
match self {
|
||||
Value::Float(f) => Some(*f),
|
||||
Value::Int(i) => Some(*i as f64),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_int(&self) -> Option<i64> {
|
||||
match self {
|
||||
Value::Int(i) => Some(*i),
|
||||
Value::DateTime(d) => Some(*d),
|
||||
Value::Bool(b) => Some(if *b { 1 } else { 0 }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_truthy(&self) -> bool {
|
||||
match self {
|
||||
Value::Void => false,
|
||||
|
||||
Reference in New Issue
Block a user