use crate::effects::{Effect, EffectSet};
use crate::stage::property::Property;
use crate::stage::{Stage, StageBuilder};
use crate::types::{NType, Refinement};
use ed25519_dalek::SigningKey;
use serde_json::json;
pub fn stages(key: &SigningKey) -> Vec<Stage> {
vec![
StageBuilder::new("identity")
.input(NType::var("T"))
.output(NType::var("T"))
.pure()
.description("Return the input unchanged. Polymorphic: <T> -> <T>.")
.example(json!("hello"), json!("hello"))
.example(json!(42), json!(42))
.example(json!(true), json!(true))
.example(json!([1, 2, 3]), json!([1, 2, 3]))
.example(json!({ "a": 1 }), json!({ "a": 1 }))
.tag("generic")
.tag("polymorphic")
.tag("pure")
.alias("id")
.alias("pass_through")
.alias("no_op")
.build_stdlib(key)
.unwrap(),
StageBuilder::new("head")
.input(NType::List(Box::new(NType::var("T"))))
.output(NType::var("T"))
.effects(EffectSet::new([Effect::Pure, Effect::Fallible]))
.description("Return the first element of a list. Empty list is a Fallible error.")
.example(json!([1, 2, 3]), json!(1))
.example(json!(["a"]), json!("a"))
.example(json!([true, false]), json!(true))
.example(json!([[1, 2], [3, 4]]), json!([1, 2]))
.example(json!([null, 1]), json!(null))
.tag("generic")
.tag("polymorphic")
.tag("list")
.tag("fallible")
.tag("pure")
.alias("first")
.alias("car")
.alias("list_head")
.build_stdlib(key)
.unwrap(),
StageBuilder::new("tail")
.input(NType::List(Box::new(NType::var("T"))))
.output(NType::List(Box::new(NType::var("T"))))
.pure()
.description(
"Return every element of a list except the first. Empty list -> empty list.",
)
.property(Property::FieldLengthMax {
subject_field: "output".into(),
bound_field: "input".into(),
})
.property(Property::SubsetOf {
subject_field: "output".into(),
super_field: "input".into(),
})
.example(json!([1, 2, 3]), json!([2, 3]))
.example(json!(["a", "b"]), json!(["b"]))
.example(json!([true]), json!([]))
.example(json!([]), json!([]))
.example(json!([1, 2, 3, 4, 5]), json!([2, 3, 4, 5]))
.tag("generic")
.tag("polymorphic")
.tag("list")
.tag("pure")
.alias("rest")
.alias("cdr")
.alias("list_tail")
.build_stdlib(key)
.unwrap(),
StageBuilder::new("mark_done")
.input(NType::record_with(Vec::<(String, NType)>::new(), "R"))
.output(NType::record_with([("done", NType::Bool)], "R"))
.pure()
.description("Return the input record with `done: true` added; preserves any other fields via row polymorphism.")
.example(json!({}), json!({ "done": true }))
.example(json!({ "a": 1 }), json!({ "a": 1, "done": true }))
.example(
json!({ "name": "alice", "age": 30 }),
json!({ "name": "alice", "age": 30, "done": true }),
)
.example(json!({ "done": false }), json!({ "done": true }))
.example(
json!({ "a": [1, 2], "b": null }),
json!({ "a": [1, 2], "b": null, "done": true }),
)
.tag("generic")
.tag("polymorphic")
.tag("record")
.tag("row")
.tag("pure")
.alias("mark_visited")
.alias("set_done")
.build_stdlib(key)
.unwrap(),
StageBuilder::new("clamp_percent")
.input(NType::refined(
NType::Number,
Refinement::Range {
min: Some(0.0),
max: Some(100.0),
},
))
.output(NType::refined(
NType::Number,
Refinement::Range {
min: Some(0.0),
max: Some(100.0),
},
))
.pure()
.property(Property::Range {
field: "input".into(),
min: Some(0.0),
max: Some(100.0),
})
.property(Property::Range {
field: "output".into(),
min: Some(0.0),
max: Some(100.0),
})
.description(
"Pass through a percentage value. Input and output are refined to Number in [0, 100].",
)
.example(json!(0), json!(0))
.example(json!(50), json!(50))
.example(json!(100), json!(100))
.example(json!(42.5), json!(42.5))
.example(json!(1), json!(1))
.tag("generic")
.tag("polymorphic")
.tag("refinement")
.tag("pure")
.alias("pct_identity")
.alias("percentage_pass")
.build_stdlib(key)
.unwrap(),
]
}