@@ -10,6 +10,7 @@ use crate::context::macros::args;
1010use crate :: context:: registry:: { HandlerFn , HandlerFunctionEntry , IntoFunctionEntry } ;
1111use crate :: context:: signal:: Signal ;
1212use crate :: runtime:: error:: RuntimeError ;
13+ use crate :: value:: { number_to_f64, number_to_string, value_from_f64, value_from_i64} ;
1314
1415pub fn collect_array_functions ( ) -> Vec < ( & ' static str , HandlerFunctionEntry ) > {
1516 vec ! [
@@ -339,9 +340,7 @@ fn find_index(
339340 Signal :: Success ( v) => match as_bool ( & v) {
340341 Ok ( true ) => {
341342 ctx. clear_input_type ( input_type) ;
342- return Signal :: Success ( Value {
343- kind : Some ( Kind :: NumberValue ( idx as f64 ) ) ,
344- } ) ;
343+ return Signal :: Success ( value_from_i64 ( idx as i64 ) ) ;
345344 }
346345 Ok ( false ) => continue ,
347346 Err ( e) => {
@@ -446,7 +445,7 @@ fn preview_value(value: &Value) -> String {
446445
447446fn format_value_json ( value : & Value ) -> String {
448447 match value. kind . as_ref ( ) {
449- Some ( Kind :: NumberValue ( v) ) => v . to_string ( ) ,
448+ Some ( Kind :: NumberValue ( v) ) => number_to_string ( v ) ,
450449 Some ( Kind :: BoolValue ( v) ) => v. to_string ( ) ,
451450 Some ( Kind :: StringValue ( v) ) => format ! ( "{:?}" , v) ,
452451 Some ( Kind :: NullValue ( _) ) | None => "null" . to_string ( ) ,
@@ -610,9 +609,7 @@ fn size(
610609 "Expected an array as an argument" ,
611610 ) ) ;
612611 } ;
613- Signal :: Success ( Value {
614- kind : Some ( Kind :: NumberValue ( array. values . len ( ) as f64 ) ) ,
615- } )
612+ Signal :: Success ( value_from_i64 ( array. values . len ( ) as i64 ) )
616613}
617614
618615fn index_of (
@@ -629,9 +626,7 @@ fn index_of(
629626 } ;
630627
631628 match array. values . iter ( ) . position ( |x| * x == item) {
632- Some ( i) => Signal :: Success ( Value {
633- kind : Some ( Kind :: NumberValue ( i as f64 ) ) ,
634- } ) ,
629+ Some ( i) => Signal :: Success ( value_from_i64 ( i as i64 ) ) ,
635630 None => Signal :: Failure ( RuntimeError :: simple (
636631 "ValueNotFoundRuntimeError" ,
637632 format ! ( "Item {:?} not found in array" , item) ,
@@ -722,7 +717,19 @@ fn sort(
722717 kind : Some ( Kind :: NumberValue ( i) ) ,
723718 } = v
724719 {
725- out. push ( i) ;
720+ match number_to_f64 ( & i) {
721+ Some ( i) => out. push ( i) ,
722+ None => {
723+ ctx. clear_input_type ( input_type) ;
724+ return Signal :: Failure ( RuntimeError :: simple (
725+ "InvalidArgumentRuntimeError" ,
726+ format ! (
727+ "expected return value of comparator to be a number but was {:?}" ,
728+ v
729+ ) ,
730+ ) ) ;
731+ }
732+ }
726733 } else {
727734 ctx. clear_input_type ( input_type) ;
728735 return Signal :: Failure ( RuntimeError :: simple (
@@ -816,7 +823,19 @@ fn sort_reverse(
816823 kind : Some ( Kind :: NumberValue ( i) ) ,
817824 } = v
818825 {
819- out. push ( i) ;
826+ match number_to_f64 ( & i) {
827+ Some ( i) => out. push ( i) ,
828+ None => {
829+ ctx. clear_input_type ( input_type) ;
830+ return Signal :: Failure ( RuntimeError :: simple (
831+ "InvalidArgumentRuntimeError" ,
832+ format ! (
833+ "expected return value of comparator to be a number but was {:?}" ,
834+ v
835+ ) ,
836+ ) ) ;
837+ }
838+ }
820839 } else {
821840 ctx. clear_input_type ( input_type) ;
822841 return Signal :: Failure ( RuntimeError :: simple (
@@ -906,16 +925,30 @@ fn min(
906925 args ! ( args => array: ListValue ) ;
907926
908927 let mut nums: Vec < f64 > = Vec :: new ( ) ;
928+ let mut all_int = true ;
929+ let mut min_i64: Option < i64 > = None ;
909930 for v in & array. values {
910- if let Some ( Kind :: NumberValue ( n) ) = v. kind {
911- nums. push ( n) ;
931+ if let Some ( Kind :: NumberValue ( n) ) = & v. kind {
932+ match n. number {
933+ Some ( tucana:: shared:: number_value:: Number :: Integer ( i) ) => {
934+ min_i64 = Some ( match min_i64 {
935+ Some ( curr) => curr. min ( i) ,
936+ None => i,
937+ } ) ;
938+ nums. push ( i as f64 ) ;
939+ }
940+ Some ( tucana:: shared:: number_value:: Number :: Float ( f) ) => {
941+ all_int = false ;
942+ nums. push ( f) ;
943+ }
944+ None => { }
945+ }
912946 }
913947 }
914948
915949 match nums. iter ( ) . min_by ( |a, b| a. total_cmp ( b) ) {
916- Some ( m) => Signal :: Success ( Value {
917- kind : Some ( Kind :: NumberValue ( * m) ) ,
918- } ) ,
950+ Some ( m) if all_int => Signal :: Success ( value_from_i64 ( min_i64. unwrap_or ( * m as i64 ) ) ) ,
951+ Some ( m) => Signal :: Success ( value_from_f64 ( * m) ) ,
919952 None => Signal :: Failure ( RuntimeError :: simple_str (
920953 "ArrayEmptyRuntimeError" ,
921954 "Array is empty" ,
@@ -931,16 +964,30 @@ fn max(
931964 args ! ( args => array: ListValue ) ;
932965
933966 let mut nums: Vec < f64 > = Vec :: new ( ) ;
967+ let mut all_int = true ;
968+ let mut max_i64: Option < i64 > = None ;
934969 for v in & array. values {
935- if let Some ( Kind :: NumberValue ( n) ) = v. kind {
936- nums. push ( n) ;
970+ if let Some ( Kind :: NumberValue ( n) ) = & v. kind {
971+ match n. number {
972+ Some ( tucana:: shared:: number_value:: Number :: Integer ( i) ) => {
973+ max_i64 = Some ( match max_i64 {
974+ Some ( curr) => curr. max ( i) ,
975+ None => i,
976+ } ) ;
977+ nums. push ( i as f64 ) ;
978+ }
979+ Some ( tucana:: shared:: number_value:: Number :: Float ( f) ) => {
980+ all_int = false ;
981+ nums. push ( f) ;
982+ }
983+ None => { }
984+ }
937985 }
938986 }
939987
940988 match nums. iter ( ) . max_by ( |a, b| a. total_cmp ( b) ) {
941- Some ( m) => Signal :: Success ( Value {
942- kind : Some ( Kind :: NumberValue ( * m) ) ,
943- } ) ,
989+ Some ( m) if all_int => Signal :: Success ( value_from_i64 ( max_i64. unwrap_or ( * m as i64 ) ) ) ,
990+ Some ( m) => Signal :: Success ( value_from_f64 ( * m) ) ,
944991 None => Signal :: Failure ( RuntimeError :: simple_str (
945992 "ArrayEmptyRuntimeError" ,
946993 "Array is empty" ,
@@ -955,16 +1002,37 @@ fn sum(
9551002) -> Signal {
9561003 args ! ( args => array: ListValue ) ;
9571004
958- let mut s = 0.0 ;
1005+ let mut s_f = 0.0 ;
1006+ let mut s_i: i64 = 0 ;
1007+ let mut all_int = true ;
9591008 for v in & array. values {
960- if let Some ( Kind :: NumberValue ( n) ) = v. kind {
961- s += n;
1009+ if let Some ( Kind :: NumberValue ( n) ) = & v. kind {
1010+ match n. number {
1011+ Some ( tucana:: shared:: number_value:: Number :: Integer ( i) ) => {
1012+ if let Some ( next) = s_i. checked_add ( i) {
1013+ s_i = next;
1014+ s_f += i as f64 ;
1015+ } else {
1016+ all_int = false ;
1017+ if let Some ( f) = number_to_f64 ( n) {
1018+ s_f += f;
1019+ }
1020+ }
1021+ }
1022+ Some ( tucana:: shared:: number_value:: Number :: Float ( f) ) => {
1023+ all_int = false ;
1024+ s_f += f;
1025+ }
1026+ None => { }
1027+ }
9621028 }
9631029 }
9641030
965- Signal :: Success ( Value {
966- kind : Some ( Kind :: NumberValue ( s) ) ,
967- } )
1031+ if all_int {
1032+ Signal :: Success ( value_from_i64 ( s_i) )
1033+ } else {
1034+ Signal :: Success ( value_from_f64 ( s_f) )
1035+ }
9681036}
9691037
9701038fn join (
@@ -989,6 +1057,7 @@ fn join(
9891057mod tests {
9901058 use super :: * ;
9911059 use crate :: context:: context:: Context ;
1060+ use crate :: value:: { number_to_f64, number_value_from_f64, value_from_f64} ;
9921061 use tucana:: shared:: { ListValue , Value , value:: Kind } ;
9931062
9941063 // --- helpers -------------------------------------------------------------
@@ -999,9 +1068,7 @@ mod tests {
9991068 Argument :: Thunk ( id)
10001069 }
10011070 fn v_num ( n : f64 ) -> Value {
1002- Value {
1003- kind : Some ( Kind :: NumberValue ( n) ) ,
1004- }
1071+ value_from_f64 ( n)
10051072 }
10061073 fn v_str ( s : & str ) -> Value {
10071074 Value {
@@ -1018,12 +1085,15 @@ mod tests {
10181085 kind : Some ( Kind :: ListValue ( ListValue { values } ) ) ,
10191086 }
10201087 }
1088+ fn k_num ( n : f64 ) -> Option < Kind > {
1089+ Some ( Kind :: NumberValue ( number_value_from_f64 ( n) ) )
1090+ }
10211091
10221092 fn expect_num ( sig : Signal ) -> f64 {
10231093 match sig {
10241094 Signal :: Success ( Value {
10251095 kind : Some ( Kind :: NumberValue ( n) ) ,
1026- } ) => n ,
1096+ } ) => number_to_f64 ( & n ) . unwrap_or_default ( ) ,
10271097 x => panic ! ( "Expected NumberValue, got {:?}" , x) ,
10281098 }
10291099 }
@@ -1154,8 +1224,8 @@ mod tests {
11541224 let b = v_list ( vec ! [ v_num( 3.0 ) , v_num( 4.0 ) ] ) ;
11551225 let out = expect_list ( concat ( & [ a_val ( a) , a_val ( b) ] , & mut ctx, & mut run) ) ;
11561226 assert_eq ! ( out. len( ) , 4 ) ;
1157- assert_eq ! ( out[ 0 ] . kind, Some ( Kind :: NumberValue ( 1.0 ) ) ) ;
1158- assert_eq ! ( out[ 3 ] . kind, Some ( Kind :: NumberValue ( 4.0 ) ) ) ;
1227+ assert_eq ! ( out[ 0 ] . kind, k_num ( 1.0 ) ) ;
1228+ assert_eq ! ( out[ 3 ] . kind, k_num ( 4.0 ) ) ;
11591229 }
11601230
11611231 #[ test]
@@ -1189,8 +1259,8 @@ mod tests {
11891259 let mut run = run_from_bools ( vec ! [ true , false , true ] ) ;
11901260 let out = expect_list ( filter ( & [ a_val ( array) , a_thunk ( 1 ) ] , & mut ctx, & mut run) ) ;
11911261 assert_eq ! ( out. len( ) , 2 ) ;
1192- assert_eq ! ( out[ 0 ] . kind, Some ( Kind :: NumberValue ( 1.0 ) ) ) ;
1193- assert_eq ! ( out[ 1 ] . kind, Some ( Kind :: NumberValue ( 3.0 ) ) ) ;
1262+ assert_eq ! ( out[ 0 ] . kind, k_num ( 1.0 ) ) ;
1263+ assert_eq ! ( out[ 1 ] . kind, k_num ( 3.0 ) ) ;
11941264 }
11951265
11961266 #[ test]
@@ -1318,7 +1388,7 @@ mod tests {
13181388 & mut run,
13191389 ) ) ;
13201390 assert_eq ! ( out. len( ) , 3 ) ;
1321- assert_eq ! ( out[ 2 ] . kind, Some ( Kind :: NumberValue ( 3.0 ) ) ) ;
1391+ assert_eq ! ( out[ 2 ] . kind, k_num ( 3.0 ) ) ;
13221392 }
13231393
13241394 #[ test]
@@ -1349,8 +1419,8 @@ mod tests {
13491419 & mut run,
13501420 ) ) ;
13511421 assert_eq ! ( out. len( ) , 2 ) ;
1352- assert_eq ! ( out[ 0 ] . kind, Some ( Kind :: NumberValue ( 1.0 ) ) ) ;
1353- assert_eq ! ( out[ 1 ] . kind, Some ( Kind :: NumberValue ( 2.0 ) ) ) ;
1422+ assert_eq ! ( out[ 0 ] . kind, k_num ( 1.0 ) ) ;
1423+ assert_eq ! ( out[ 1 ] . kind, k_num ( 2.0 ) ) ;
13541424 }
13551425
13561426 #[ test]
@@ -1480,9 +1550,9 @@ mod tests {
14801550
14811551 let uniq = expect_list ( to_unique ( & [ a_val ( arr) ] , & mut ctx, & mut run) ) ;
14821552 assert_eq ! ( uniq. len( ) , 3 ) ;
1483- assert_eq ! ( uniq[ 0 ] . kind, Some ( Kind :: NumberValue ( 10.0 ) ) ) ;
1484- assert_eq ! ( uniq[ 1 ] . kind, Some ( Kind :: NumberValue ( 42.0 ) ) ) ;
1485- assert_eq ! ( uniq[ 2 ] . kind, Some ( Kind :: NumberValue ( 30.0 ) ) ) ;
1553+ assert_eq ! ( uniq[ 0 ] . kind, k_num ( 10.0 ) ) ;
1554+ assert_eq ! ( uniq[ 1 ] . kind, k_num ( 42.0 ) ) ;
1555+ assert_eq ! ( uniq[ 2 ] . kind, k_num ( 30.0 ) ) ;
14861556 }
14871557
14881558 #[ test]
@@ -1530,8 +1600,8 @@ mod tests {
15301600 & mut ctx,
15311601 & mut run,
15321602 ) ) ;
1533- assert_eq ! ( out[ 0 ] . kind, Some ( Kind :: NumberValue ( 3.0 ) ) ) ;
1534- assert_eq ! ( out[ 2 ] . kind, Some ( Kind :: NumberValue ( 1.0 ) ) ) ;
1603+ assert_eq ! ( out[ 0 ] . kind, k_num ( 3.0 ) ) ;
1604+ assert_eq ! ( out[ 2 ] . kind, k_num ( 1.0 ) ) ;
15351605
15361606 match reverse ( & [ a_val ( v_str ( "nope" ) ) ] , & mut ctx, & mut run) {
15371607 Signal :: Failure ( _) => { }
@@ -1555,10 +1625,10 @@ mod tests {
15551625 ] ) ;
15561626 let out = expect_list ( flat ( & [ a_val ( nested) ] , & mut ctx, & mut run) ) ;
15571627 assert_eq ! ( out. len( ) , 4 ) ;
1558- assert_eq ! ( out[ 0 ] . kind, Some ( Kind :: NumberValue ( 1.0 ) ) ) ;
1559- assert_eq ! ( out[ 1 ] . kind, Some ( Kind :: NumberValue ( 2.0 ) ) ) ;
1560- assert_eq ! ( out[ 2 ] . kind, Some ( Kind :: NumberValue ( 3.0 ) ) ) ;
1561- assert_eq ! ( out[ 3 ] . kind, Some ( Kind :: NumberValue ( 4.0 ) ) ) ;
1628+ assert_eq ! ( out[ 0 ] . kind, k_num ( 1.0 ) ) ;
1629+ assert_eq ! ( out[ 1 ] . kind, k_num ( 2.0 ) ) ;
1630+ assert_eq ! ( out[ 2 ] . kind, k_num ( 3.0 ) ) ;
1631+ assert_eq ! ( out[ 3 ] . kind, k_num ( 4.0 ) ) ;
15621632 }
15631633
15641634 // --- min / max / sum -----------------------------------------------------
0 commit comments