aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/tool/compiler/phase/statement.lux
blob: 87736643cdc8d90fcb4d0a939429faec9f6bf7f1 (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
(.module:
  [lux #*
   [control
    ["." monad (#+ do)]
    ["." exception (#+ exception:)]]
   [data
    [text
     format]]
   ["." macro]]
  ["." //
   ["//." macro (#+ Expander)]
   ["//." extension]
   [".P" analysis
    ["." type]]
   [//
    ["/" statement (#+ Phase)]
    ["." analysis]]])

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

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

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

(def: #export (phase expander)
  (-> Expander Phase)
  (let [analyze (analysisP.phase expander)]
    (function (compile code)
      (case code
        (^ [_ (#.Form (list& [_ (#.Text name)] inputs))])
        (//extension.apply compile [name inputs])

        (^ [_ (#.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 not-a-macro-call code))))]
          (monad.map @ compile expansion))

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