aboutsummaryrefslogtreecommitdiff
path: root/new-luxc/source/luxc/lang/synthesis/case.lux
blob: c35483dd82b7994918465ad04144eb496cc748ea (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
(;module:
  lux
  (lux (data [bool "bool/" Eq<Bool>]
             [text "text/" Eq<Text>]
             text/format
             [number]
             (coll [list "list/" Fold<List> Monoid<List>]))
       (macro [code "code/" Eq<Code>]))
  (luxc (lang [";L" variable #+ Variable]
              ["la" analysis]
              ["ls" synthesis]
              (synthesis [";S" function]))))

(def: popPS ls;Path (' ("lux case pop")))

(def: (path' arity num-locals pattern)
  (-> ls;Arity Nat la;Pattern [Nat (List ls;Path)])
  (case pattern
    (^code ("lux case tuple" [(~@ membersP)]))
    (case membersP
      #;Nil
      [num-locals
       (list popPS)]

      (#;Cons singletonP #;Nil)
      (path' arity num-locals singletonP)

      (#;Cons _)
      (let [last-idx (n.dec (list;size membersP))
            [_ output] (list/fold (: (-> la;Pattern [Nat [Nat (List ls;Path)]] [Nat [Nat (List ls;Path)]])
                                     (function [current-pattern [current-idx num-locals' next]]
                                       (let [[num-locals'' current-path] (path' arity num-locals' current-pattern)]
                                         [(n.dec current-idx)
                                          num-locals''
                                          (|> (list (if (n.= last-idx current-idx)
                                                      (` ("lux case tuple right" (~ (code;nat current-idx))))
                                                      (` ("lux case tuple left" (~ (code;nat current-idx))))))
                                              (list/compose current-path)
                                              (list/compose next))])))
                                  [last-idx num-locals (list popPS)]
                                  (list;reverse membersP))]
        output))

    (^code ("lux case variant" (~ [_ (#;Nat tag)]) (~ [_ (#;Nat num-tags)]) (~ memberP)))
    (let [[num-locals' member-path] (path' arity num-locals memberP)]
      [num-locals' (|> (list (if (n.= (n.dec num-tags) tag)
                               (` ("lux case variant right" (~ (code;nat tag))))
                               (` ("lux case variant left" (~ (code;nat tag))))))
                       (list/compose member-path)
                       (list& popPS))])

    (^code ("lux case bind" (~ [_ (#;Nat register)])))
    [(n.inc num-locals)
     (list popPS
           (` ("lux case bind" (~ (code;nat (if (functionS;nested? arity)
                                              (n.+ (n.dec arity) register)
                                              register))))))]

    _
    [num-locals
     (list popPS pattern)]))

(def: (clean-unnecessary-pops paths)
  (-> (List ls;Path) (List ls;Path))
  (case paths
    (#;Cons path paths')
    (if (is popPS path)
      (clean-unnecessary-pops paths')
      paths)

    #;Nil
    paths))

(def: #export (path arity num-locals synthesize pattern bodyA)
  (->  ls;Arity Nat (-> Nat la;Analysis ls;Synthesis) la;Pattern la;Analysis ls;Path)
  (let [[num-locals' pieces] (path' arity num-locals pattern)]
    (|> pieces
        clean-unnecessary-pops
        (list/fold (function [pre post]
                     (` ("lux case seq" (~ pre) (~ post))))
                   (` ("lux case exec" (~ (synthesize num-locals' bodyA))))))))

(def: #export (weave leftP rightP)
  (-> ls;Path ls;Path ls;Path)
  (with-expansions [<default> (as-is (` ("lux case alt" (~ leftP) (~ rightP))))]
    (case [leftP rightP]
      (^ [(^code ("lux case seq" (~ preL) (~ postL)))
          (^code ("lux case seq" (~ preR) (~ postR)))])
      (case (weave preL preR)
        (^code ("lux case alt" (~ thenP) (~ elseP)))
        <default>

        weavedP
        (` ("lux case seq" (~ weavedP) (~ (weave postL postR)))))

      _
      (if (code/= leftP rightP)
        rightP
        <default>))))