aboutsummaryrefslogtreecommitdiff
path: root/new-luxc/source/luxc/generator/runtime.jvm.lux
blob: e6a12d6fa0af48cf503214bf996fe222669bef1c (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
(;module:
  lux
  (lux (control monad)
       (data ["R" result]
             text/format)
       [macro #+ Monad<Lux> "Lux/" Monad<Lux>]
       [host #+ jvm-import do-to])
  (luxc ["&" base]
        (lang ["la" analysis]
              ["ls" synthesis])
        ["&;" analyser]
        ["&;" synthesizer]
        (generator ["&;" common]
                   (host ["$" jvm]
                         (jvm ["$t" type]
                              ["$d" def]
                              ["$i" inst])))))

(jvm-import java.lang.Object)
(jvm-import java.lang.String)

(jvm-import java.lang.reflect.Field
  (get [Object] #try Object))

(jvm-import (java.lang.Class a)
  (getField [String] Field))

(jvm-import org.objectweb.asm.Opcodes
  (#static ACC_PUBLIC int)
  (#static ACC_SUPER int)
  (#static ACC_FINAL int)
  (#static ACC_STATIC int)
  (#static V1_6 int))

(jvm-import org.objectweb.asm.ClassWriter
  (#static COMPUTE_MAXS int)
  (new [int])
  (visit [int int String String String (Array String)] void)
  (visitEnd [] void)
  (toByteArray [] Byte-Array))

(def: #export runtime-name Text "LuxRuntime")
(def: #export function-name Text "LuxFunction")
(def: #export unit Text "\u0000")

(def: $Object $;Type ($t;class "java.lang.Object" (list)))

(def: logI
  $;Inst
  (let [outI ($i;GETSTATIC "java.lang.System" "out" ($t;class "java.io.PrintStream" (list)))
        printI (function [method] ($i;INVOKEVIRTUAL "java.io.PrintStream" method ($t;method (list $Object) #;None (list)) false))]
    (|>. outI ($i;string "LOG: ") (printI "print")
         outI $i;SWAP (printI "println"))))

(def: add-adt-methods
  $;Def
  (let [store-tag (|>. $i;DUP ($i;int 0) ($i;ILOAD +0) $i;wrap-int $i;AASTORE)
        store-flag (|>. $i;DUP ($i;int 1) ($i;ALOAD +1) $i;AASTORE)
        store-value (|>. $i;DUP ($i;int 2) ($i;ALOAD +2) $i;AASTORE)]
    (|>. ($d;method #$;Public $;staticM "sum_make"
                    ($t;method (list $t;int $Object $Object)
                               (#;Some ($t;array +1 $Object))
                               (list))
                    (|>. ($i;array $Object +3)
                         store-tag
                         store-flag
                         store-value
                         $i;ARETURN)))))

(def: add-nat-methods
  $;Def
  (let [compare-nat-method ($t;method (list $t;long $t;long) (#;Some $t;int) (list))
        less-thanI (function [@where] (|>. ($i;INVOKESTATIC runtime-name "compare_nat" compare-nat-method false) ($i;IFLT @where)))
        $BigInteger ($t;class "java.math.BigInteger" (list))
        upcast-method ($t;method (list $t;long) (#;Some $BigInteger) (list))
        div-method ($t;method (list $t;long $t;long) (#;Some $t;long) (list))
        upcastI ($i;INVOKESTATIC runtime-name "_toUnsignedBigInteger" upcast-method false)
        downcastI ($i;INVOKEVIRTUAL "java.math.BigInteger" "longValue" ($t;method (list) (#;Some $t;long) (list)) false)]
    ## http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Long.java#215
    (|>. ($d;method #$;Public $;staticM "_toUnsignedBigInteger" upcast-method
                    (let [upcastI ($i;INVOKESTATIC "java.math.BigInteger" "valueOf" upcast-method false)
                          discernI (function [@where] (|>. ($i;LLOAD +0) ($i;long 0) $i;LCMP ($i;IFGE @where)))
                          prepare-upperI (|>. ($i;LLOAD +0) ($i;int 32) $i;LUSHR
                                              upcastI
                                              ($i;int 32) ($i;INVOKEVIRTUAL "java.math.BigInteger" "shiftLeft" ($t;method (list $t;int) (#;Some $BigInteger) (list)) false))
                          prepare-lowerI (|>. ($i;LLOAD +0) ($i;int 32) $i;LSHL
                                              ($i;int 32)   $i;LUSHR
                                              upcastI)]
                      (<| $i;with-label (function [@simple])
                          (|>. (discernI @simple)
                               ## else
                               prepare-upperI
                               prepare-lowerI
                               ($i;INVOKEVIRTUAL "java.math.BigInteger" "add" ($t;method (list $BigInteger) (#;Some $BigInteger) (list)) false)
                               $i;ARETURN
                               ## then
                               ($i;label @simple)
                               ($i;LLOAD +0)
                               upcastI
                               $i;ARETURN))))
         ## http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Long.java?av=f#1267
         ($d;method #$;Public $;staticM "compare_nat" compare-nat-method
                    (let [shiftI (|>. ($i;GETSTATIC "java.lang.Long" "MIN_VALUE" $t;long) $i;LADD)]
                      (|>. ($i;LLOAD +0) shiftI
                           ($i;LLOAD +2) shiftI
                           $i;LCMP
                           $i;IRETURN)))
         ## http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Long.java#1290
         ($d;method #$;Public $;staticM "div_nat" div-method
                    (let [is-param-largeI (function [@where] (|>. ($i;LLOAD +2) ($i;long 0) $i;LCMP ($i;IFLT @where)))
                          is-subject-smallI (function [@where] (|>. ($i;LLOAD +0) ($i;long 0) $i;LCMP ($i;IFGT @where)))
                          small-division (|>. ($i;LLOAD +0) ($i;LLOAD +2) $i;LDIV $i;LRETURN)
                          big-divisionI ($i;INVOKEVIRTUAL "java.math.BigInteger" "divide" ($t;method (list $BigInteger) (#;Some $BigInteger) (list)) false)]
                      (<| $i;with-label (function [@is-zero])
                          $i;with-label (function [@param-is-large])
                          $i;with-label (function [@subject-is-small])
                          (|>. (is-param-largeI @param-is-large)
                               ## Param is not too large
                               (is-subject-smallI @subject-is-small)
                               ## Param is small, but subject is large
                               ($i;LLOAD +0) upcastI
                               ($i;LLOAD +2) upcastI
                               big-divisionI downcastI $i;LRETURN
                               ## Both param and subject are small,
                               ## and can thus be divided normally.
                               ($i;label @subject-is-small)
                               small-division
                               ## Param is too large. Cannot simply divide.
                               ## Depending on the result of the
                               ## comparison, a result will be determined.
                               ($i;label @param-is-large)
                               ($i;LLOAD +0) ($i;LLOAD +2) (less-thanI @is-zero)
                               ## Greater-than or equals
                               ($i;long 1) $i;LRETURN
                               ## Less than
                               ($i;label @is-zero)
                               ($i;long 0) $i;LRETURN))))
         ## http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Long.java#1323
         ($d;method #$;Public $;staticM "rem_nat" div-method
                    (let [is-subject-largeI (function [@where] (|>. ($i;LLOAD +0) ($i;long 0) $i;LCMP ($i;IFLE @where)))
                          is-param-largeI (function [@where] (|>. ($i;LLOAD +2) ($i;long 0) $i;LCMP ($i;IFLE @where)))
                          small-remainderI (|>. ($i;LLOAD +0) ($i;LLOAD +2) $i;LREM $i;LRETURN)
                          big-remainderI ($i;INVOKEVIRTUAL "java.math.BigInteger" "remainder" ($t;method (list $BigInteger) (#;Some $BigInteger) (list)) false)]
                      (<| $i;with-label (function [@large-number])
                          $i;with-label (function [@subject-is-smaller-than-param])
                          (|>. (is-subject-largeI @large-number)
                               (is-param-largeI @large-number)
                               small-remainderI

                               ($i;label @large-number)
                               ($i;LLOAD +0) ($i;LLOAD +2) (less-thanI @subject-is-smaller-than-param)
                               
                               ($i;LLOAD +0) upcastI
                               ($i;LLOAD +2) upcastI
                               big-remainderI downcastI $i;LRETURN
                               
                               ($i;label @subject-is-smaller-than-param)
                               ($i;LLOAD +0)
                               $i;LRETURN))))
         )))

(def: init-method $;Method ($t;method (list) #;None (list)))

(def: #export generate
  (Lux &common;Bytecode)
  (do Monad<Lux>
    [_ (wrap [])
     #let [bytecode ($d;class #$;V1.6 #$;Public $;finalC runtime-name (list) ["java.lang.Object" (list)] (list)
                              (|>. add-adt-methods
                                   add-nat-methods
                                   ))]
     _ (&common;store-class runtime-name bytecode)]
    (wrap bytecode)))