aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/specification/compositor/generation/function.lux
blob: 632f0db753d57f4332f12aa87a9848d84747754e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
(.require
 [lux (.except function)
  ["_" test (.only Test)]
  [abstract
   [monad (.only do)]
   ["[0]" enum]]
  [control
   ["[0]" maybe]]
  [data
   [number
    ["n" nat]]
   [collection
    ["[0]" list (.use "[1]#[0]" functor)]]]
  [math
   ["r" random (.only Random) (.use "[1]#[0]" monad)]]
  [tool
   [compiler
    [analysis (.only Arity)]
    ["[0]" reference (.only Register)]
    ["[0]" synthesis (.only Synthesis)]]]]
 ["[0]" //
  ["[1][0]" case]
  [//
   [common (.only Runner)]]])

(def max_arity
  Arity
  10)

(def arity
  (Random Arity)
  (|> r.nat (r#each (|>> (n.% max_arity) (n.max 1)))))

(def (local arity)
  (-> Arity (Random Register))
  (|> r.nat (r#each (|>> (n.% arity) ++))))

(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 (at ! each (|>> (n.% arity) (n.max 1))))
     inputs (r.list arity r.safe_frac)
     .let [expectation (maybe.trusted (list.item (-- local) inputs))
           inputsS (list#each (|>> synthesis.f64) inputs)]]
    (all _.and
         (_.property "Can read arguments."
           (|> (synthesis.function/apply [synthesis.#function functionS
                                          synthesis.#arguments inputsS])
               (run "with_local")
               (//case.verify expectation)))
         (_.property "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)))))
         (_.property "Can read environment."
           (or (n.= 1 arity)
               (let [environment (|> partial_arity
                                     (enum.range n.enum 1)
                                     (list#each (|>> {reference.#Local})))
                     variableS (if (n.<= partial_arity local)
                                 (synthesis.variable/foreign (-- 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)))))
         )))