aboutsummaryrefslogtreecommitdiff
path: root/lux-jvm/source/luxc/lang/translation/jvm/loop.lux
blob: 92b8c02864e1e7a3a99366e18d4762ce19899b5a (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
(.using
 [library
  [lux "*"
   [abstract
    ["[0]" monad {"+" do}]]
   [control
    ["[0]" function]]
   [data
    [collection
     ["[0]" list ("[1]@[0]" functor monoid)]]]
   [math
    [number
     ["n" nat]]]
   [tool
    [compiler
     ["[0]" phase]
     [reference
      [variable {"+" Register}]]
     [language
      [lux
       ["[0]" synthesis {"+" Synthesis}]
       ["[0]" generation]]]]]]]
 [luxc
  [lang
   [host
    [jvm {"+" Inst Operation Phase Generator}
     ["_" inst]]]]]
 ["[0]" //])

(def: (invariant? expected actual)
  (-> Register Synthesis Bit)
  (case actual
    (pattern (synthesis.variable/local actual))
    (n.= expected actual)

    _
    false))

(def: .public (again translate archive argsS)
  (Generator (List Synthesis))
  (do [@ phase.monad]
    [[@begin start] generation.anchor
     .let [pairs (|> argsS
                     list.enumeration
                     (list@each (function (_ [register argument])
                                  [(n.+ start register) argument])))]
     ... It may look weird that first I compile the values separately,
     ... and then I compile the stores/allocations.
     ... It must be done that way in order to avoid a potential bug.
     ... Let's say that you'll recur with 2 expressions: X and Y.
     ... If Y depends on the value of X, and you don't compile values
     ... and stores separately, then by the time Y is evaluated, it
     ... will refer to the new value of X, instead of the old value, and
     ... shouldn't be the case.
     valuesI+ (monad.each @ (function (_ [register argS])
                              (: (Operation Inst)
                                 (if (invariant? register argS)
                                   (in function.identity)
                                   (translate archive argS))))
                          pairs)
     .let [storesI+ (list@each (function (_ [register argS])
                                 (: Inst
                                    (if (invariant? register argS)
                                      function.identity
                                      (_.ASTORE register))))
                               (list.reversed pairs))]]
    (in (|>> (_.fuse valuesI+)
             (_.fuse storesI+)
             (_.GOTO @begin)))))

(def: .public (scope translate archive [start initsS+ iterationS])
  (Generator [Nat (List Synthesis) Synthesis])
  (do [@ phase.monad]
    [@begin _.make_label
     initsI+ (monad.each @ (translate archive) initsS+)
     iterationI (generation.with_anchor [@begin start]
                  (translate archive iterationS))
     .let [initializationI (|> (list.enumeration initsI+)
                               (list@each (function (_ [register initI])
                                            (|>> initI
                                                 (_.ASTORE (n.+ start register)))))
                               _.fuse)]]
    (in (|>> initializationI
             (_.label @begin)
             iterationI))))