(.module: [lux (#- function) ["_" test (#+ Test)] [abstract [monad (#+ do)] ["." enum]] [control [pipe (#+ case>)] ["." maybe]] [data [number ["n" nat]] [collection ["." list ("#\." functor)]]] [math ["r" random (#+ Random) ("#\." monad)]] [tool [compiler [analysis (#+ Arity)] ["." reference (#+ Register)] ["." synthesis (#+ Synthesis)]]]] ["." // #_ ["#." case] [// [common (#+ Runner)]]]) (def: max_arity Arity 10) (def: arity (Random Arity) (|> r.nat (r\map (|>> (n.% max_arity) (n.max 1))))) (def: (local arity) (-> Arity (Random Register)) (|> r.nat (r\map (|>> (n.% arity) inc)))) (def: function (Random [Arity Register Synthesis]) (do r.monad [arity ..arity local (..local arity)] (in [arity local (synthesis.function/abstraction {#synthesis.environment (list) #synthesis.arity arity #synthesis.body (synthesis.variable/local local)})]))) (def: .public (spec run) (-> Runner Test) (do {! r.monad} [[arity local functionS] ..function partial_arity (|> r.nat (\ ! map (|>> (n.% arity) (n.max 1)))) inputs (r.list arity r.safe_frac) .let [expectation (maybe.assume (list.item (dec local) inputs)) inputsS (list\map (|>> synthesis.f64) inputs)]] ($_ _.and (_.test "Can read arguments." (|> (synthesis.function/apply {#synthesis.function functionS #synthesis.arguments inputsS}) (run "with_local") (//case.verify expectation))) (_.test "Can partially apply functions." (or (n.= 1 arity) (let [preS (list.first partial_arity inputsS) postS (list.after partial_arity inputsS) partialS (synthesis.function/apply {#synthesis.function functionS #synthesis.arguments preS})] (|> (synthesis.function/apply {#synthesis.function partialS #synthesis.arguments postS}) (run "partial_application") (//case.verify expectation))))) (_.test "Can read environment." (or (n.= 1 arity) (let [environment (|> partial_arity (enum.range n.enum 1) (list\map (|>> #reference.Local))) variableS (if (n.<= partial_arity local) (synthesis.variable/foreign (dec local)) (synthesis.variable/local (|> local (n.- partial_arity)))) inner_arity (n.- partial_arity arity) innerS (synthesis.function/abstraction {#synthesis.environment environment #synthesis.arity inner_arity #synthesis.body variableS}) outerS (synthesis.function/abstraction {#synthesis.environment (list) #synthesis.arity partial_arity #synthesis.body innerS})] (|> (synthesis.function/apply {#synthesis.function outerS #synthesis.arguments inputsS}) (run "with_foreign") (//case.verify expectation))))) )))