diff --git a/examples/err.myc b/examples/err.myc index ab2b37b..2d57995 100644 --- a/examples/err.myc +++ b/examples/err.myc @@ -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) + ) \ No newline at end of file diff --git a/examples/sma.myc b/examples/sma.myc index fd43f66..4047f6d 100644 --- a/examples/sma.myc +++ b/examples/sma.myc @@ -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)) + )) ) \ No newline at end of file diff --git a/src/ast/rtl/series.rs b/src/ast/rtl/series.rs index 1a4548a..f0f802c 100644 --- a/src/ast/rtl/series.rs +++ b/src/ast/rtl/series.rs @@ -218,19 +218,16 @@ pub trait SeriesMember: Object + Series { impl SeriesMember for ScalarSeries { fn push_value(&self, value: Value, limit: Option) { - 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 { fn push_value(&self, value: Value, limit: Option) { - 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); } } } diff --git a/src/ast/types.rs b/src/ast/types.rs index fa51f46..977dd14 100644 --- a/src/ast/types.rs +++ b/src/ast/types.rs @@ -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 { + match self { + Value::Float(f) => Some(*f), + Value::Int(i) => Some(*i as f64), + _ => None, + } + } + + pub fn as_int(&self) -> Option { + 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,