aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/lang/analysis/expression.lux
blob: a22e3d32b55b37310e811008de1b9be4e390f541 (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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
(.module:
  lux
  (lux (control [monad #+ do]
                ["ex" exception #+ exception:])
       (data ["e" error]
             [product]
             text/format)
       [macro]
       [lang #+ Eval]
       (lang [type]
             (type ["tc" check])
             [".L" analysis #+ Analysis Analyser]
             (analysis [".A" type]
                       [".A" primitive]
                       [".A" structure]
                       ## [".A" function]
                       ## [".A" reference]
                       )
             ## [".L" macro]
             ## [".L" extension]
             )))

(exception: #export (macro-expansion-failed {message Text})
  message)

(do-template [<name>]
  [(exception: #export (<name> {code Code})
     (%code code))]

  [macro-call-must-have-single-expansion]
  [unrecognized-syntax]
  )

(def: #export (analyser eval)
  (-> Eval Analyser)
  (: (-> Code (Meta Analysis))
     (function (analyse code)
       (do macro.Monad<Meta>
         [expectedT macro.expected-type]
         (let [[cursor code'] code]
           ## The cursor must be set in the compiler for the sake
           ## of having useful error messages.
           (lang.with-cursor cursor
             (case code'
               (^template [<tag> <analyser>]
                 (<tag> value)
                 (<analyser> value))
               ([#.Bool primitiveA.bool]
                [#.Nat  primitiveA.nat]
                [#.Int  primitiveA.int]
                [#.Deg  primitiveA.deg]
                [#.Frac primitiveA.frac]
                [#.Text primitiveA.text])

               (^template [<tag> <analyser>]
                 (^ (#.Form (list& [_ (<tag> tag)]
                                   values)))
                 (case values
                   (#.Cons value #.Nil)
                   (<analyser> analyse tag value)

                   _
                   (<analyser> analyse tag (` [(~+ values)]))))
               ([#.Nat structureA.sum]
                [#.Tag structureA.tagged-sum])

               (#.Tag tag)
               (structureA.tagged-sum analyse tag (' []))

               (^ (#.Tuple (list)))
               primitiveA.unit

               (^ (#.Tuple (list singleton)))
               (analyse singleton)

               (^ (#.Tuple elems))
               (structureA.product analyse elems)

               (^ (#.Record pairs))
               (structureA.record analyse pairs)

               ## (#.Symbol reference)
               ## (referenceA.analyse-reference reference)

               ## (^ (#.Form (list& [_ (#.Text proc-name)] proc-args)))
               ## (do macro.Monad<Meta>
               ##   [procedure (extensionL.find-analysis proc-name)]
               ##   (procedure analyse eval proc-args))

               ## (^ (#.Form (list& func args)))
               ## (do macro.Monad<Meta>
               ##   [[funcT funcA] (typeA.with-inference
               ##                    (analyse func))]
               ##   (case funcA
               ##     [_ (#.Symbol def-name)]
               ##     (do @
               ##       [?macro (lang.with-error-tracking
               ##                 (macro.find-macro def-name))]
               ##       (case ?macro
               ##         (#.Some macro)
               ##         (do @
               ##           [expansion (: (Meta (List Code))
               ##                         (function (_ compiler)
               ##                           (case (macroL.expand macro args compiler)
               ##                             (#e.Error error)
               ##                             ((lang.throw macro-expansion-failed error) compiler)

               ##                             output
               ##                             output)))]
               ##           (case expansion
               ##             (^ (list single))
               ##             (analyse single)

               ##             _
               ##             (lang.throw macro-call-must-have-single-expansion code)))

               ##         _
               ##         (functionA.analyse-apply analyse funcT funcA args)))

               ##     _
               ##     (functionA.analyse-apply analyse funcT funcA args)))

               _
               (lang.throw unrecognized-syntax code)
               )))))))