aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/meta/macro/vocabulary.lux
blob: ce47d7f96d027e4146862bd0880941e5ffb1d32f (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
... [Not everything is an expression](https://codewords.recurse.com/issues/two/not-everything-is-an-expression)

(.require
 [library
  [lux (.except local)
   [abstract
    [monad (.only do)]]
   [control
    ["?" parser (.use "[1]#[0]" functor)]
    ["[0]" exception (.only Exception)]]]]
 ["[0]" // (.only)
  [syntax (.only syntax)
   ["[0]" export]]
  ["/[1]" // (.only)
   ["[0]" code (.only)
    ["?[1]" \\parser (.only Parser)]]
   ["[0]" type (.only)
    [primitive (.except)]]]])

(exception.def .public (invalid_type [expected actual])
  (Exception [Type Type])
  (exception.report
   (list ["Expected" (type.format expected)]
         ["Actual" (type.format actual)])))

(def local
  (Parser [Code Code])
  (?code.tuple (export.parser (?#each code.local ?code.local))))

(def .public vocabulary
  (syntax (_ [[public|private@type type] ..local
              [public|private@micro micro] ..local
              [public|private@macro macro] ..local
              [public|private@by_name by_name] ..local])
    (//.with_symbols [g!_ g!type g!value]
      (in (list (` (primitive (, public|private@type) (, type)
                     Macro

                     (def (, public|private@micro) (, micro)
                       (-> Macro (, type))
                       (|>> abstraction))

                     (def (, public|private@macro) (, macro)
                       (-> (, type) Macro)
                       (|>> representation))))

                (` (def (, public|private@by_name) ((, by_name) (, g!_))
                     (-> Symbol (Meta Macro))
                     (do ///.monad
                       [[(, g!_) (, g!type) (, g!value)] (///.export (, g!_))]
                       (if (at type.equivalence (,' =) (, type) (, g!type))
                         ((,' in) ((, macro) (as (, type) (, g!value))))
                         (///.failure (exception.error ..invalid_type [(, type) (, g!type)])))))))))))