aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/test/lux/control/parser/synthesis.lux
blob: addb7c14960c33306cea4fd86bee5d01e3e31aa5 (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
(.using
 [library
  [lux "*"
   ["_" test {"+" Test}]
   [abstract
    ["[0]" monad {"+" do}]]
   [control
    ["<>" parser]
    ["[0]" try]
    ["[0]" exception]]
   [data
    ["[0]" bit]
    ["[0]" text]
    [collection
     ["[0]" list ("[1]#[0]" functor)]]]
   [macro
    ["^" pattern]]
   [math
    ["[0]" random {"+" Random}]
    [number
     ["n" nat]
     ["[0]" i64]
     ["[0]" frac]]]
   [meta
    ["[0]" symbol]]
   [tool
    [compiler
     [reference {"+" }
      ["[0]" variable {"+" Variable}]]
     [language
      [lux
       [analysis {"+" Environment}]
       ["[0]" synthesis {"+" Synthesis}]]]]]]]
 [\\library
  ["[0]" /]])

(template: (!expect <pattern> <value>)
  [(case <value>
     <pattern>
     true
     
     _
     false)])

(def: random_constant
  (Random Symbol)
  (random.and (random.unicode 1)
              (random.unicode 1)))

(def: random_variable
  (Random Variable)
  (random.or random.nat
             random.nat))

(def: random_environment
  (Random (Environment Synthesis))
  (do [! random.monad]
    [size (# ! each (n.% 5) random.nat)]
    (|> ..random_variable
        (# ! each (|>> synthesis.variable))
        (random.list size))))

(def: simple
  Test
  (`` (all _.and
           (~~ (template [<query> <check> <random> <synthesis> <equivalence>]
                 [(do [! random.monad]
                    [expected <random>
                     dummy (|> <random> (random.only (|>> (# <equivalence> = expected) not)))]
                    (all _.and
                         (_.cover [<query>]
                                  (|> (/.result <query> (list (<synthesis> expected)))
                                      (!expect (^.multi {try.#Success actual}
                                                        (# <equivalence> = expected actual)))))
                         (_.cover [<check>]
                                  (and (|> (/.result (<check> expected) (list (<synthesis> expected)))
                                           (!expect {try.#Success _}))
                                       (|> (/.result (<check> expected) (list (<synthesis> dummy)))
                                           (!expect (^.multi {try.#Failure error}
                                                             (exception.match? /.cannot_parse error))))))
                         ))]

                 [/.bit /.this_bit random.bit synthesis.bit bit.equivalence]
                 [/.i64 /.this_i64 random.i64 synthesis.i64 i64.equivalence]
                 [/.f64 /.this_f64 random.safe_frac synthesis.f64 frac.equivalence]
                 [/.text /.this_text (random.unicode 1) synthesis.text text.equivalence]
                 [/.local /.this_local random.nat synthesis.variable/local n.equivalence]
                 [/.foreign /.this_foreign random.nat synthesis.variable/foreign n.equivalence]
                 [/.constant /.this_constant ..random_constant synthesis.constant symbol.equivalence]
                 ))
           )))

(def: complex
  Test
  (all _.and
       (do [! random.monad]
         [expected_bit random.bit
          expected_i64 random.i64
          expected_f64 random.safe_frac
          expected_text (random.unicode 1)]
         (_.cover [/.tuple]
                  (and (|> (/.result (/.tuple (all <>.and /.bit /.i64 /.f64 /.text))
                                     (list (synthesis.tuple (list (synthesis.bit expected_bit)
                                                                  (synthesis.i64 expected_i64)
                                                                  (synthesis.f64 expected_f64)
                                                                  (synthesis.text expected_text)))))
                           (!expect (^.multi {try.#Success [actual_bit actual_i64 actual_f64 actual_text]}
                                             (and (# bit.equivalence = expected_bit actual_bit)
                                                  (# i64.equivalence = expected_i64 actual_i64)
                                                  (# frac.equivalence = expected_f64 actual_f64)
                                                  (# text.equivalence = expected_text actual_text)))))
                       (|> (/.result (/.tuple (all <>.and /.bit /.i64 /.f64 /.text))
                                     (list (synthesis.text expected_text)))
                           (!expect (^.multi {try.#Failure error}
                                             (exception.match? /.cannot_parse error)))))))
       (do [! random.monad]
         [arity random.nat
          expected_environment ..random_environment
          expected_body (random.unicode 1)]
         (_.cover [/.function]
                  (and (|> (/.result (/.function arity /.text)
                                     (list (synthesis.function/abstraction [expected_environment arity (synthesis.text expected_body)])))
                           (!expect (^.multi {try.#Success [actual_environment actual_body]}
                                             (and (# (list.equivalence synthesis.equivalence) =
                                                     expected_environment
                                                     actual_environment)
                                                  (# text.equivalence = expected_body actual_body)))))
                       (|> (/.result (/.function arity /.text)
                                     (list (synthesis.text expected_body)))
                           (!expect (^.multi {try.#Failure error}
                                             (exception.match? /.cannot_parse error)))))))
       (do [! random.monad]
         [arity random.nat
          expected_environment ..random_environment
          expected_body (random.unicode 1)]
         (_.cover [/.wrong_arity]
                  (|> (/.result (/.function (++ arity) /.text)
                                (list (synthesis.function/abstraction [expected_environment arity (synthesis.text expected_body)])))
                      (!expect (^.multi {try.#Failure error}
                                        (exception.match? /.wrong_arity error))))))
       (do [! random.monad]
         [arity (# ! each (|>> (n.% 10) ++) random.nat)
          expected_offset random.nat
          expected_inits (random.list arity random.bit)
          expected_body (random.unicode 1)]
         (_.cover [/.loop]
                  (and (|> (/.result (/.loop (<>.many /.bit) /.text)
                                     (list (synthesis.loop/scope [expected_offset
                                                                  (list#each (|>> synthesis.bit) expected_inits)
                                                                  (synthesis.text expected_body)])))
                           (!expect (^.multi {try.#Success [actual_offset actual_inits actual_body]}
                                             (and (# n.equivalence = expected_offset actual_offset)
                                                  (# (list.equivalence bit.equivalence) =
                                                     expected_inits
                                                     actual_inits)
                                                  (# text.equivalence = expected_body actual_body)))))
                       (|> (/.result (/.loop (<>.many /.bit) /.text)
                                     (list (synthesis.text expected_body)))
                           (!expect (^.multi {try.#Failure error}
                                             (exception.match? /.cannot_parse error)))))))
       ))

(def: .public test
  Test
  (<| (_.covering /._)
      (_.for [/.Parser])
      (all _.and
           (do [! random.monad]
             [expected (# ! each (|>> synthesis.i64) random.i64)]
             (_.cover [/.result /.any]
                      (|> (/.result /.any (list expected))
                          (!expect (^.multi {try.#Success actual}
                                            (# synthesis.equivalence = expected actual))))))
           (_.cover [/.empty_input]
                    (|> (/.result /.any (list))
                        (!expect (^.multi {try.#Failure error}
                                          (exception.match? /.empty_input error)))))
           (do [! random.monad]
             [expected (# ! each (|>> synthesis.i64) random.i64)]
             (_.cover [/.unconsumed_input]
                      (|> (/.result /.any (list expected expected))
                          (!expect (^.multi {try.#Failure error}
                                            (exception.match? /.unconsumed_input error))))))
           (do [! random.monad]
             [dummy (# ! each (|>> synthesis.i64) random.i64)]
             (_.cover [/.end /.expected_empty_input]
                      (and (|> (/.result /.end (list))
                               (!expect {try.#Success _}))
                           (|> (/.result /.end (list dummy))
                               (!expect (^.multi {try.#Failure error}
                                                 (exception.match? /.expected_empty_input error)))))))
           (do [! random.monad]
             [dummy (# ! each (|>> synthesis.i64) random.i64)]
             (_.cover [/.end?]
                      (and (|> (/.result /.end? (list))
                               (!expect {try.#Success #1}))
                           (|> (/.result (<>.before /.any /.end?) (list dummy))
                               (!expect {try.#Success #0})))))
           (_.for [/.cannot_parse]
                  (all _.and
                       ..simple
                       ..complex
                       ))
           )))