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

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

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

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

(def: #export (phase code)
  Phase
  (case code
    (^ [_ (#.Form (list& [_ (#.Text name)] inputs))])
    (extension.apply phase [name inputs])

    (^ [_ (#.Form (list& macro inputs))])
    (do ///.monad
      [expansion (//.lift-analysis
                  (do @
                    [macroA (type.with-type Macro
                              (expression.compile 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 macro-name macro inputs)))
                      
                      _
                      (///.throw not-a-macro code))))]
      (monad.map @ phase expansion))

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