aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/tool/compiler/phase/statement.lux
blob: 2f3c68f7bd5283a37b7bc29a67b15f1408264de9 (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
(.module:
  [lux #*
   [abstract
    ["." monad (#+ do)]]
   [control
    ["." exception (#+ exception:)]]
   [data
    [text
     format]
    [collection
     ["." list ("#;." fold monoid)]]]
   ["." macro]]
  ["." //
   ["#." macro (#+ Expander)]
   ["#." extension]
   [".P" analysis
    ["." type]]
   ["#/" // #_
    [reference (#+)]
    ["#." analysis]
    ["/" statement (#+ Phase)]]])

(exception: #export (not-a-statement {code Code})
  (exception.report
   ["Statement" (%code code)]))

(exception: #export (invalid-macro-call {code Code})
  (exception.report
   ["Code" (%code code)]))

(exception: #export (macro-was-not-found {name Name})
  (exception.report
   ["Name" (%name name)]))

(with-expansions [<lux_def_module> (as-is [|form-cursor| (#.Form (list& [|text-cursor| (#.Text "lux def module")] annotations))])]
  (def: #export (phase expander)
    (-> Expander Phase)
    (let [analyze (analysisP.phase expander)]
      (function (compile code)
        (case code
          (^ [_ (#.Form (list& [_ (#.Text name)] inputs))])
          (do //.monad
            [requirements (//extension.apply compile [name inputs])]
            (wrap requirements))

          (^ [_ (#.Form (list& macro inputs))])
          (do //.monad
            [expansion (/.lift-analysis
                        (do @
                          [macroA (type.with-type Macro
                                    (analyze macro))]
                          (case macroA
                            (^ (///analysis.constant macro-name))
                            (do @
                              [?macro (//extension.lift (macro.find-macro macro-name))
                               macro (case ?macro
                                       (#.Some macro)
                                       (wrap macro)
                                       
                                       #.None
                                       (//.throw macro-was-not-found macro-name))]
                              (//extension.lift (//macro.expand expander macro-name macro inputs)))
                            
                            _
                            (//.throw invalid-macro-call code))))
             requirements (case expansion
                            (^ (list& <lux_def_module> referrals))
                            (do @
                              [requirements (compile <lux_def_module>)]
                              (wrap (update@ #/.referrals (list;compose referrals) requirements)))

                            _
                            (|> expansion
                                (monad.map @ compile)
                                (:: @ map (list;fold /.merge-requirements /.no-requirements))))]
            (wrap requirements))

          _
          (//.throw not-a-statement code))))))