aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/js/loop.lux
blob: 5747dfee978e80531d884683337e1458e4cc3bff (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
... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.

(.require
 [library
  [lux (.except Scope Synthesis)
   [abstract
    ["[0]" monad (.only do)]]
   [data
    ["[0]" product]
    ["[0]" text (.only)
     ["%" \\format (.only format)]]
    [collection
     ["[0]" list (.use "[1]#[0]" functor mix)]]]
   [math
    [number
     ["n" nat]]]
   [meta
    [compiler
     [target
      ["_" js (.only Computation Var Expression Statement)]]]]]]
 ["[0]" //
  [runtime (.only Operation Phase Phase! Translator Translator!)]
  ["[1][0]" when]
  ["///[1]" ////
   [synthesis (.only Scope Synthesis)]
   ["[0]" phase]
   ["[1][0]" translation]
   [///
    [reference
     [variable (.only Register)]]]]])

(def @scope
  (-> Nat Text)
  (|>> %.nat (format "scope")))

(def $iteration
  (-> Nat Var)
  (|>> %.nat (format "iteration") _.var))

(def (setup $iteration initial? offset bindings body)
  (-> Var Bit Register (List Expression) Statement Statement)
  (when bindings
    (list)
    body

    (list binding)
    (let [$binding (//when.register offset)]
      (all _.then
           (if initial?
             (_.define $binding binding)
             (_.statement (_.set $binding binding)))
           body
           ))

    _
    (|> bindings
        list.enumeration
        (list#each (function (_ [register _])
                     (let [variable (//when.register (n.+ offset register))]
                       (if initial?
                         (_.define variable (_.at (_.i32 (.int register)) $iteration))
                         (_.statement (_.set variable (_.at (_.i32 (.int register)) $iteration)))))))
        list.reversed
        (list#mix _.then body)
        (_.then (_.define $iteration (_.array bindings))))))

(def .public (scope! statement expression archive [start initsS+ bodyS])
  (Translator! (Scope Synthesis))
  (when initsS+
    ... function/false/non-independent loop
    {.#End}
    (statement expression archive bodyS)

    ... true loop
    _
    (do [! phase.monad]
      [@scope (of ! each ..@scope /////translation.next)
       initsO+ (monad.each ! (expression archive) initsS+)
       body! (/////translation.with_anchor [start @scope]
               (statement expression archive bodyS))
       $iteration (of ! each ..$iteration /////translation.next)]
      (in (..setup $iteration
                   true start
                   initsO+
                   (_.with_label (_.label @scope)
                     (_.do_while (_.boolean true)
                                 body!)))))))

(def .public (scope statement expression archive [start initsS+ bodyS])
  (-> Phase! (Translator (Scope Synthesis)))
  (when initsS+
    ... function/false/non-independent loop
    {.#End}
    (expression archive bodyS)

    ... true loop
    _
    (do [! phase.monad]
      [loop! (scope! statement expression archive [start initsS+ bodyS])]
      (in (_.apply (_.closure (list) loop!) (list))))))

(def @temp
  (_.var "lux_again_values"))

(def .public (again! statement expression archive argsS+)
  (Translator! (List Synthesis))
  (do [! phase.monad]
    [[offset @scope] /////translation.anchor
     argsO+ (monad.each ! (expression archive) argsS+)
     $iteration (of ! each ..$iteration /////translation.next)]
    (in (all _.then
             (_.define @temp (_.array argsO+))
             (..setup $iteration
                      false offset
                      (|> argsO+
                          list.enumeration
                          (list#each (function (_ [idx _])
                                       (_.at (_.i32 (.int idx)) @temp))))
                      (_.continue_at (_.label @scope)))))))