Skip to content

Commit c491ce1

Browse files
committed
feat: switched from single number value to integer and float
1 parent 8e080b0 commit c491ce1

10 files changed

Lines changed: 678 additions & 249 deletions

File tree

crates/core/src/context/argument.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ use crate::context::signal::Signal;
22
use crate::runtime::error::RuntimeError;
33
use std::convert::Infallible;
44
use tucana::shared::value::Kind;
5-
use tucana::shared::{ListValue, Struct, Value};
5+
use tucana::shared::{ListValue, NumberValue, Struct, Value};
66

7+
use crate::value::number_to_f64;
78
#[derive(Clone, Debug)]
89
pub enum Argument {
910
// Eval => Evaluated Value
@@ -40,12 +41,23 @@ impl TryFromArgument for Value {
4041
}
4142
}
4243

44+
impl TryFromArgument for NumberValue {
45+
fn try_from_argument(a: &Argument) -> Result<Self, Signal> {
46+
match a {
47+
Argument::Eval(Value {
48+
kind: Some(Kind::NumberValue(n)),
49+
}) => Ok(n.clone()),
50+
_ => Err(type_err("Expected number", a)),
51+
}
52+
}
53+
}
54+
4355
impl TryFromArgument for f64 {
4456
fn try_from_argument(a: &Argument) -> Result<Self, Signal> {
4557
match a {
4658
Argument::Eval(Value {
4759
kind: Some(Kind::NumberValue(n)),
48-
}) => Ok(*n),
60+
}) => number_to_f64(n).ok_or_else(|| type_err("Expected number", a)),
4961
_ => Err(type_err("Expected number", a)),
5062
}
5163
}

crates/core/src/context/executor.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,17 @@ fn preview_value(value: &Value) -> String {
371371

372372
fn format_value_json(value: &Value) -> String {
373373
match value.kind.as_ref() {
374-
Some(Kind::NumberValue(v)) => v.to_string(),
374+
Some(Kind::NumberValue(v)) => {
375+
match v.number {
376+
Some(kind) => {
377+
match kind {
378+
tucana::shared::number_value::Number::Integer(i) => i.to_string(),
379+
tucana::shared::number_value::Number::Float(f) => f.to_string(),
380+
}
381+
}
382+
_ => "null".to_string(),
383+
}
384+
},
375385
Some(Kind::BoolValue(v)) => v.to_string(),
376386
Some(Kind::StringValue(v)) => format!("{:?}", v),
377387
Some(Kind::NullValue(_)) | None => "null".to_string(),

crates/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod context;
22
pub mod debug;
33
pub mod runtime;
4+
pub mod value;

crates/core/src/runtime/functions/array.rs

Lines changed: 118 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::context::macros::args;
1010
use crate::context::registry::{HandlerFn, HandlerFunctionEntry, IntoFunctionEntry};
1111
use crate::context::signal::Signal;
1212
use crate::runtime::error::RuntimeError;
13+
use crate::value::{number_to_f64, number_to_string, value_from_f64, value_from_i64};
1314

1415
pub 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

447446
fn 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

618615
fn 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

9701038
fn join(
@@ -989,6 +1057,7 @@ fn join(
9891057
mod 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

Comments
 (0)