use crate::run;
use anyhow::{bail, Result};
use netidx::publisher::Value;
const LAMBDA: &str = r#"
{
let y = 10;
let f = |x| x + y;
f(10)
}
"#;
run!(lambda, LAMBDA, |v: Result<&Value>| match v {
Ok(Value::I64(20)) => true,
_ => false,
});
const FIRST_CLASS_LAMBDAS: &str = r#"
{
let doit = |x: Number| x + 1;
let g = |f: fn<'a: Number>('a) -> 'a, y| f(y) + 1;
g(doit, 1)
}
"#;
run!(first_class_lambdas, FIRST_CLASS_LAMBDAS, |v: Result<&Value>| match v {
Ok(Value::I64(3)) => true,
_ => false,
});
const LABELED_ARGS: &str = r#"
{
let f = |#foo: Number, #bar: Number = 42| foo + bar;
f(#foo: 0)
}
"#;
run!(labeled_args, LABELED_ARGS, |v: Result<&Value>| match v {
Ok(Value::I64(42)) => true,
_ => false,
});
const REQUIRED_ARGS: &str = r#"
{
let f = |#foo: Number, #bar: Number = 42| foo + bar;
f(#bar: 0)
}
"#;
run!(required_args, REQUIRED_ARGS, |v: Result<&Value>| match v {
Err(_) => true,
_ => false,
});
const MIXED_ARGS: &str = r#"
{
let f = |#foo: Number, #bar: Number = 42, baz| foo + bar + baz;
f(#foo: 0, 0)
}
"#;
run!(mixed_args, MIXED_ARGS, |v: Result<&Value>| match v {
Ok(Value::I64(42)) => true,
_ => false,
});
const ARG_SUBTYPING: &str = r#"
{
let f = |#foo: Number, #bar: Number = 42| foo + bar;
let g = |f: fn(#foo: Number) -> Number| f(#foo: 3);
g(f)
}
"#;
run!(arg_subtyping, ARG_SUBTYPING, |v: Result<&Value>| match v {
Ok(Value::I64(45)) => true,
_ => false,
});
const ARG_NAME_SHORT: &str = r#"
{
let f = |#foo: Number, #bar: Number = 42| foo + bar;
let foo = 3;
f(#foo)
}
"#;
run!(arg_name_short, ARG_NAME_SHORT, |v: Result<&Value>| match v {
Ok(Value::I64(45)) => true,
_ => false,
});
const LATE_BINDING0: &str = r#"
{
type T = { foo: string, bar: i64, f: fn(#x: i64, #y: i64) -> i64 };
let t: T = { foo: "hello world", bar: 3, f: |#x: i64, #y: i64| x - y };
let u: T = { foo: "hello foo", bar: 42, f: |#c: i64 = 1, #y: i64, #x: i64| x - y + c };
let f = t.f;
f(#y: 3, #x: 4)
}
"#;
run!(late_binding0, LATE_BINDING0, |v: Result<&Value>| match v {
Ok(Value::I64(1)) => true,
_ => false,
});
const LATE_BINDING1: &str = r#"
{
type F = fn(#x: i64, #y: i64) -> i64;
type T = { foo: string, bar: i64, f: F };
let t: T = { foo: "hello world", bar: 3, f: |#x: i64, #y: i64| x - y };
let u: T = { foo: "hello foo", bar: 42, f: |#c: i64 = 1, #y: i64, #x: i64| (x - y) + c };
let f: F = select array::iter([0, 1]) {
0 => t.f,
1 => u.f,
_ => never()
};
array::group(f(#y: 3, #x: 4), |n, _| n == 2)
}
"#;
run!(late_binding1, LATE_BINDING1, |v: Result<&Value>| match v {
Ok(Value::Array(a)) => match &a[..] {
[Value::I64(1), Value::I64(2)] => true,
_ => false,
},
_ => false,
});
const LATE_BINDING2: &str = r#"
{
type T = { foo: string, bar: i64, f: fn(#x: i64, #y: i64) -> i64 };
let t: T = { foo: "hello world", bar: 3, f: |#x: i64, #y: i64| x - y };
(t.f)(#y: 3, #x: 4)
}
"#;
run!(late_binding2, LATE_BINDING2, |v: Result<&Value>| match v {
Ok(Value::I64(1)) => true,
_ => false,
});
const LATE_BINDING3: &str = r#"
{
let f: fn(i64) -> i64 = never();
let res = f(1);
f <- |i: i64| i + 1;
res
}
"#;
run!(late_binding3, LATE_BINDING3, |v: Result<&Value>| match v {
Ok(Value::I64(2)) => true,
_ => false,
});
const LATE_BINDING4: &str = r#"
{
let f = |#foo: i64 = 0, #bar: i64 = 1, baz| (foo - bar) + baz;
let g = |#bar: i64 = 1, #foo: i64 = 0, baz| (foo - bar) + baz;
let h = |#bar: i64 = 1, #zam: i64 = 55, #foo: i64 = 0, baz| (foo - bar) + baz + zam;
let fs = [f, g, h];
let f: fn(i64) -> i64 = never();
f <- array::iter(fs);
array::group(f(1), |n, _| n == 3)
}
"#;
run!(late_binding4, LATE_BINDING4, |v: Result<&Value>| match v {
Ok(v) => match v.clone().cast_to::<[i64; 3]>() {
Ok([0, 0, 55]) => true,
Ok(_) | Err(_) => false,
},
_ => false,
});
const RECURSIVE_LAMBDA0: &str = r#"
{
let rec f = |x: i64| select x { x if x < 10 => f(x + 1), x => x };
f(0)
}
"#;
run!(recursive_lambda0, RECURSIVE_LAMBDA0, |v: Result<&Value>| match v {
Ok(Value::I64(10)) => true,
_ => false,
});
const LAMBDAMATCH0: &str = r#"
{
type T = { foo: Array<f64>, bar: i64, baz: f64 };
let x = { foo: [ 1.0, 2.0, 4.3, 55.23 ], bar: 42, baz: 84.0 };
let f = |{bar, ..}: T| bar + bar;
f(x)
}
"#;
run!(lambdamatch0, LAMBDAMATCH0, |v: Result<&Value>| match v {
Ok(Value::I64(84)) => true,
_ => false,
});
const LAMBDAMATCH1: &str = r#"
{
type T = { foo: Array<f64>, bar: i64, baz: f64 };
let x = { foo: [ 1.0, 2.0, 4.3, 55.23 ], bar: 42, baz: 84.0 };
let f = |{bar, ..}| bar + bar;
f(x)
}
"#;
run!(lambdamatch1, LAMBDAMATCH1, |v: Result<&Value>| match v {
Err(_) => true,
_ => false,
});
const LAMBDAMATCH2: &str = r#"
{
let x = { foo: [ 1.0, 2.0, 4.3, 55.23 ], bar: 42, baz: 84.0 };
let f = |{foo: _, bar, baz: _}| bar + bar;
f(x)
}
"#;
run!(lambdamatch2, LAMBDAMATCH2, |v: Result<&Value>| match v {
Ok(Value::I64(84)) => true,
_ => false,
});
const LAMBDAMATCH3: &str = r#"
{
let f = |{foo: _, bar, baz: _}| bar + bar;
f({bar: 42, baz: 1})
}
"#;
run!(lambdamatch3, LAMBDAMATCH3, |v: Result<&Value>| match v {
Err(_) => true,
_ => false,
});
const LAMBDAMATCH4: &str = r#"
{
let f = |(i, _)| i * 2;
f((42, "foo"))
}
"#;
run!(lambdamatch4, LAMBDAMATCH4, |v: Result<&Value>| match v {
Ok(Value::I64(84)) => true,
_ => false,
});
const LAMBDAMATCH5: &str = r#"
{
let f = |(i, _)| i * 2;
f("foo")
}
"#;
run!(lambdamatch5, LAMBDAMATCH5, |v: Result<&Value>| match v {
Err(_) => true,
_ => false,
});
const NESTED_OPTIONAL0: &str = r#"
{
type T = { foo: i64, bar: i64 };
let f = |#foo: i64 = 42, #bar: i64 = 42| -> T { foo, bar };
type U = { f: T, baz: i64 };
let g = |#f: T = f(), baz: i64| -> U { f, baz };
let r = g(42);
r.baz
}
"#;
run!(nested_optional0, NESTED_OPTIONAL0, |v: Result<&Value>| match v {
Ok(Value::I64(42)) => true,
_ => false,
});