aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/test/lux/macro/local.lux
blob: b360943996b63b8733b2b725ac8406208cfe7cc9 (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
(.module:
  [library
   [lux "*"
    ["_" test {"+" [Test]}]
    ["[0]" meta]
    [abstract
     [monad {"+" [do]}]]
    [control
     ["[0]" try]
     ["[0]" exception]
     ["<>" parser
      ["<[0]>" code]]]
    [data
     [text
      ["%" format]]
     [collection
      ["[0]" list]
      [dictionary
       ["[0]" plist]]]]
    ["[0]" macro
     [syntax {"+" [syntax:]}]
     ["[0]" code]]
    [math
     ["[0]" random {"+" [Random]}]
     [number
      ["n" nat]]]]]
  [\\library
   ["[0]" /]])

(syntax: (macro_error [macro <code>.any])
  (function (_ compiler)
    (case ((macro.expansion macro) compiler)
      {#try.Failure error}
      {#try.Success [compiler (list (code.text error))]}
      
      {#try.Success _}
      {#try.Failure "OOPS!"})))

(def: (constant output)
  (-> Code Macro)
  ("lux macro"
   (function (_ inputs lux)
     {#try.Success [lux (list output)]})))

(syntax: (with [name (<code>.tuple (<>.and <code>.text <code>.text))
                constant <code>.any
                pre_remove <code>.bit
                body <code>.any])
  (macro.with_identifiers [g!output]
    (do meta.monad
      [pop! (/.push (list [name (..constant constant)]))
       [module short] (meta.normal name)
       _ (if pre_remove
           (let [remove_macro! (: (-> .Module .Module)
                                  (revised@ #.definitions (plist.lacks short)))]
             (function (_ lux)
               {#try.Success [(revised@ #.modules (plist.revised module remove_macro!) lux)
                              []]}))
           (in []))]
      (let [pre_expansion (` (let [(~ g!output) (~ body)]
                               (exec (~ pop!)
                                 (~ g!output))))]
        (if pre_remove
          (macro.full_expansion pre_expansion)
          (in (list pre_expansion)))))))

(def: .public test
  Test
  (<| (_.covering /._)
      (do [! random.monad]
        [expected random.nat]
        ($_ _.and
            (_.cover [/.push]
                     (..with ["" "actual"] expected #0
                       (n.= expected (..actual))))
            (_.cover [/.unknown_module]
                     (exception.match? /.unknown_module
                                       (..macro_error
                                        (..with ["123yolo456" "actual"] expected #0
                                          (n.= expected (..actual))))))
            (_.cover [/.cannot_shadow_definition]
                     (exception.match? /.cannot_shadow_definition
                                       (..macro_error
                                        (..with ["" "with"] expected #0
                                          (n.= expected (..actual))))))
            (_.cover [/.unknown_definition]
                     (exception.match? /.unknown_definition
                                       (<| ..macro_error
                                           (..with ["" "actual"] expected #1)
                                           (n.= expected (..actual)))))
            ))))