blob: ae1300cf949a4251dde745d1d4a709ac33f35349 (
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
|
(.module:
[library
[lux #*
[abstract
["." monad (#+ do)]]
[control
["." function]]
[data
[collection
["." list ("#@." functor monoid)]]]
[math
[number
["n" nat]]]
[tool
[compiler
["." phase]
[reference
[variable (#+ Register)]]
[language
[lux
["." synthesis (#+ Synthesis)]
["." generation]]]]]]]
[luxc
[lang
[host
[jvm (#+ Inst Operation Phase Generator)
["_" inst]]]]]
["." //])
(def: (invariant? expected actual)
(-> Register Synthesis Bit)
(case actual
(^ (synthesis.variable/local actual))
(n.= expected actual)
_
false))
(def: .public (recur 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))))
|