(.module: lux (lux [io] (control [monad #+ do] pipe) (data [maybe] ["e" error] [bit] [bit "bit/" Eq] [number "int/" Number Codec] [text "text/" Eq] text/format (coll [list])) ["r" math/random "r/" Monad] [macro] (macro [code]) [host] test) (luxc [lang] (lang [".L" host] ["ls" synthesis] (translation (jvm [".T" expression] [".T" eval] [".T" runtime])))) (test/luxc common)) (context: "Conversions [Part 1]" (<| (times +100) (do @ [int-sample (|> r.int (:: @ map (i/% 128))) #let [frac-sample (int-to-frac int-sample)]] (with-expansions [<2step> (template [ ] [(test (format " / " ) (|> (do macro.Monad [sampleI (expressionT.translate (|> (~ ( )) (`)))] (evalT.eval sampleI)) (lang.with-current-module "") (macro.run (io.run init-jvm)) (case> (#e.Success valueT) ( (:coerce valueT)) (#e.Error error) #0)))] ["jvm convert double-to-float" "jvm convert float-to-double" code.frac frac-sample Frac f/=] ["jvm convert double-to-int" "jvm convert int-to-double" code.frac frac-sample Frac f/=] ["jvm convert double-to-long" "jvm convert long-to-double" code.frac frac-sample Frac f/=] ["jvm convert long-to-float" "jvm convert float-to-long" code.int int-sample Int i/=] ["jvm convert long-to-int" "jvm convert int-to-long" code.int int-sample Int i/=] ["jvm convert long-to-short" "jvm convert short-to-long" code.int int-sample Int i/=] ["jvm convert long-to-byte" "jvm convert byte-to-long" code.int int-sample Int i/=] )] ($_ seq <2step> ))))) (context: "Conversions [Part 2]" (<| (times +100) (do @ [int-sample (|> r.int (:: @ map (|>> (i/% 128) int/abs))) #let [frac-sample (int-to-frac int-sample)]] (`` ($_ seq (~~ (template [ ] [(test (format " / " " / " ) (|> (do macro.Monad [sampleI (expressionT.translate (|> (~ ( )) (`)))] (evalT.eval sampleI)) (lang.with-current-module "") (macro.run (io.run init-jvm)) (case> (#e.Success valueT) ( (:coerce valueT)) (#e.Error error) #0)))] ["jvm convert long-to-int" "jvm convert int-to-char" "jvm convert char-to-long" code.int int-sample Int i/=] ["jvm convert long-to-int" "jvm convert int-to-byte" "jvm convert byte-to-long" code.int int-sample Int i/=] ["jvm convert long-to-int" "jvm convert int-to-short" "jvm convert short-to-long" code.int int-sample Int i/=] ["jvm convert long-to-float" "jvm convert float-to-int" "jvm convert int-to-long" code.int int-sample Int i/=] ["jvm convert long-to-int" "jvm convert int-to-float" "jvm convert float-to-long" code.int int-sample Int i/=] )) ))))) (context: "Conversions [Part 3]" (<| (times +100) (do @ [int-sample (|> r.int (:: @ map (|>> (i/% 128) int/abs))) #let [frac-sample (int-to-frac int-sample)]] (`` ($_ seq (~~ (template [ ] [(test (format " / " " / " ) (|> (do macro.Monad [sampleI (expressionT.translate (|> (~ ( )) (`)))] (evalT.eval sampleI)) (lang.with-current-module "") (macro.run (io.run init-jvm)) (case> (#e.Success valueT) ( (:coerce valueT)) (#e.Error error) #0)))] ["jvm convert long-to-int" "jvm convert int-to-char" "jvm convert char-to-byte" "jvm convert byte-to-long" code.int int-sample Int i/=] ["jvm convert long-to-int" "jvm convert int-to-char" "jvm convert char-to-short" "jvm convert short-to-long" code.int int-sample Int i/=] ["jvm convert long-to-int" "jvm convert int-to-char" "jvm convert char-to-int" "jvm convert int-to-long" code.int int-sample Int i/=] )) ))))) (def: gen-nat (r.Random Nat) (|> r.nat (r/map (n/% +128)) (r.filter (|>> (n/= +0) not)))) (def: gen-int (r.Random Int) (|> gen-nat (r/map nat-to-int))) (def: gen-frac (r.Random Frac) (|> gen-int (r/map int-to-frac))) (template [ <+> <-> <*> <%>
 ]
  [(context: (format "Arithmetic ["  "]")
     (<| (times +100)
         (do @
           [param 
            #let [subject ( param)]]
           (with-expansions [ (template [ ]
                                       [(test 
                                              (|> (do macro.Monad
                                                    [sampleI (expressionT.translate ( ((code.text )
                                                                                             (
 ( subject))
                                                                                             (
 ( param)))))]
                                                    (evalT.eval sampleI))
                                                  (lang.with-current-module "")
                                                  (macro.run (io.run init-jvm))
                                                  (case> (#e.Success valueT)
                                                         ( ( param subject)
                                                                 (:coerce  valueT))

                                                         (#e.Error error)
                                                         #0)))]

                                       [(format "jvm "  " +") <+>]
                                       [(format "jvm "  " -") <->]
                                       [(format "jvm "  " *") <*>]
                                       [(format "jvm "  " /") ]
                                       [(format "jvm "  " %") <%>]
                                       )]
             ($_ seq
                 
                 )))))]

  ["int" gen-int code.int Int i/= (i/* 10) i/+ i/- i/* i// i/% "jvm convert long-to-int" "jvm convert int-to-long"]
  ["long" gen-int code.int Int i/= (i/* 10) i/+ i/- i/* i// i/% id id]
  ["float" gen-frac code.frac Frac f/= (f/* 10.0) f/+ f/- f/* f// f/% "jvm convert double-to-float" "jvm convert float-to-double"]
  ["double" gen-frac code.frac Frac f/= (f/* 10.0) f/+ f/- f/* f// f/% id id]
  )

(template [  ]
  [(context: (format "Bit-wise ["  "] { Combiners ]")
     (<| (times +100)
         (do @
           [param gen-nat
            subject gen-nat]
           (`` ($_ seq
                   (~~ (template [ ]
                         [(test 
                                (|> (do macro.Monad
                                      [sampleI (expressionT.translate ( ((code.text )
                                                                               ( (code.nat subject))
                                                                               ( (code.nat param)))))]
                                      (evalT.eval sampleI))
                                    (lang.with-current-module "")
                                    (macro.run (io.run init-jvm))
                                    (case> (#e.Success valueT)
                                           (n/= ( param subject)
                                                (:coerce Nat valueT))

                                           (#e.Error error)
                                           #0)))]

                         [(format "jvm "  " and") bit.and]
                         [(format "jvm "  " or") bit.or]
                         [(format "jvm "  " xor") bit.xor]
                         ))
                   )))))]

  ["int" "jvm convert int-to-long" "jvm convert long-to-int"]
  ["long" id id]
  )

(template [  ]
  [(context: (format "Bit-wise ["  "] { Shifters }")
     (<| (times +100)
         (do @
           [param gen-nat
            subject gen-nat
            #let [shift (n/% +10 param)]]
           (`` ($_ seq
                   (~~ (template [     
]
                         [(test 
                                (|> (do macro.Monad
                                      [sampleI (expressionT.translate ( ((code.text )
                                                                               ( (
 subject))
                                                                               ("jvm convert long-to-int" (code.nat shift)))))]
                                      (evalT.eval sampleI))
                                    (lang.with-current-module "")
                                    (macro.run (io.run init-jvm))
                                    (case> (#e.Success valueT)
                                           ( ( shift ( subject))
                                                   (:coerce  valueT))

                                           (#e.Error error)
                                           #0)))]

                         [(format "jvm "  " shl") bit.left-shift Nat n/= id code.nat]
                         [(format "jvm "  " shr") bit.arithmetic-right-shift Int i/= nat-to-int (|>> nat-to-int code.int)]
                         [(format "jvm "  " ushr") bit.logical-right-shift Nat n/= id code.nat]
                         ))
                   )))))]

  ["int" "jvm convert int-to-long" "jvm convert long-to-int"]
  ["long" id id]
  )

(template [   <=> <<> 
]
  [(context: (format "Order ["  "]")
     (<| (times +100)
         (do @
           [param 
            subject ]
           (with-expansions [ (template [ ]
                                       [(test 
                                              (|> (do macro.Monad
                                                    [sampleI (expressionT.translate ((code.text )
                                                                                     (
 ( subject))
                                                                                     (
 ( param))))]
                                                    (evalT.eval sampleI))
                                                  (lang.with-current-module "")
                                                  (macro.run (io.run init-jvm))
                                                  (case> (#e.Success valueT)
                                                         (bit/= ( param subject)
                                                                (:coerce Bit valueT))

                                                         (#e.Error error)
                                                         #0)))]

                                       [(format "jvm "  " =") <=>]
                                       [(format "jvm "  " <") <<>]
                                       )]
             ($_ seq
                 
                 )))))]

  ["int" gen-int code.int i/= i/< "jvm convert long-to-int"]
  ["long" gen-int code.int i/= i/< id]
  ["float" gen-frac code.frac f/= f/< "jvm convert double-to-float"]
  ["double" gen-frac code.frac f/= f/< id]
  ["char" gen-int code.int i/= i/< "jvm convert long-to-char"]
  )

(def: (jvm//array//new dimension class size)
  (-> Nat Text Nat ls.Synthesis)
  (` ("jvm array new" (~ (code.nat dimension)) (~ (code.text class)) (~ (code.nat size)))))

(def: (jvm//array//write class idx inputS arrayS)
  (-> Text Nat ls.Synthesis ls.Synthesis ls.Synthesis)
  (` ("jvm array write" (~ (code.text class)) (~ (code.nat idx)) (~ inputS) (~ arrayS))))

(def: (jvm//array//read class idx arrayS)
  (-> Text Nat ls.Synthesis ls.Synthesis)
  (` ("jvm array read" (~ (code.text class)) (~ (code.nat idx)) (~ arrayS))))

(context: "Array [Part 1]"
  (<| (times +100)
      (do @
        [size (|> r.nat (:: @ map (|>> (n/% +10) (n/max +1))))
         idx (|> r.nat (:: @ map (n/% size)))
         valueZ r.bit
         valueB gen-int
         valueS gen-int
         valueI gen-int
         valueL r.int
         valueF gen-frac
         valueD r.frac
         valueC gen-int]
        (with-expansions [ (template [     ]
                                    [(test 
                                           (|> (do macro.Monad
                                                 [sampleI (expressionT.translate (|> (jvm//array//new +0  size)
                                                                                     (jvm//array//write  idx )
                                                                                     (jvm//array//read  idx)
                                                                                     ))]
                                                 (evalT.eval sampleI))
                                               (lang.with-current-module "")
                                               (macro.run (io.run init-jvm))
                                               (case> (#e.Success outputZ)
                                                      (  (:coerce  outputZ))

                                                      (#e.Error error)
                                                      #0)))]

                                    ["boolean" Bit valueZ bit/= (code.bit valueZ)
                                     id]
                                    ["byte" Int valueB i/= (|> (code.int valueB) (~) "jvm convert long-to-byte" (`))
                                     "jvm convert byte-to-long"]
                                    ["short" Int valueS i/= (|> (code.int valueS) (~) "jvm convert long-to-short" (`))
                                     "jvm convert short-to-long"]
                                    ["int" Int valueI i/= (|> (code.int valueI) (~) "jvm convert long-to-int" (`))
                                     "jvm convert int-to-long"]
                                    ["long" Int valueL i/= (code.int valueL)
                                     id]
                                    ["float" Frac valueF f/= (|> (code.frac valueF) (~) "jvm convert double-to-float" (`))
                                     "jvm convert float-to-double"]
                                    ["double" Frac valueD f/= (code.frac valueD)
                                     id]
                                    )]
          ($_ seq
              
              )))))

(context: "Array [Part 2]"
  (<| (times +100)
      (do @
        [size (|> r.nat (:: @ map (|>> (n/% +10) (n/max +1))))
         idx (|> r.nat (:: @ map (n/% size)))
         valueZ r.bit
         valueB gen-int
         valueS gen-int
         valueI gen-int
         valueL r.int
         valueF gen-frac
         valueD r.frac
         valueC gen-int]
        (with-expansions [ (template [     ]
                                    [(test 
                                           (|> (do macro.Monad
                                                 [sampleI (expressionT.translate (|> (jvm//array//new +0  size)
                                                                                     (jvm//array//write  idx )
                                                                                     (jvm//array//read  idx)
                                                                                     ))]
                                                 (evalT.eval sampleI))
                                               (lang.with-current-module "")
                                               (macro.run (io.run init-jvm))
                                               (case> (#e.Success outputT)
                                                      (  (:coerce  outputT))

                                                      (#e.Error error)
                                                      #0)))]

                                    ["char" Int valueC i/=
                                     (|> (code.int valueC) (~) "jvm convert long-to-int" "jvm convert int-to-char" (`))
                                     "jvm convert char-to-long"]
                                    ["java.lang.Long" Int valueL i/=
                                     (code.int valueL)
                                     id]
                                    )]
          ($_ seq
              
              (test "java.lang.Double (level 1)"
                    (|> (do macro.Monad
                          [#let [inner (|> ("jvm array new" +0 "java.lang.Double" (~ (code.nat size)))
                                           ("jvm array write" "java.lang.Double" (~ (code.nat idx)) (~ (code.frac valueD)))
                                           (`))]
                           sampleI (expressionT.translate (|> ("jvm array new" +1 "java.lang.Double" (~ (code.nat size)))
                                                              ("jvm array write" "#Array" (~ (code.nat idx)) (~ inner))
                                                              ("jvm array read" "#Array" (~ (code.nat idx)))
                                                              ("jvm array read" "java.lang.Double" (~ (code.nat idx)))
                                                              (`)))]
                          (evalT.eval sampleI))
                        (lang.with-current-module "")
                        (macro.run (io.run init-jvm))
                        (case> (#e.Success outputT)
                               (f/= valueD (:coerce Frac outputT))

                               (#e.Error error)
                               #0)))
              (test "jvm array length"
                    (|> (do macro.Monad
                          [sampleI (expressionT.translate (` ("jvm array length" ("jvm array new" +0 "java.lang.Object" (~ (code.nat size))))))]
                          (evalT.eval sampleI))
                        (lang.with-current-module "")
                        (macro.run (io.run init-jvm))
                        (case> (#e.Success outputT)
                               (n/= size (:coerce Nat outputT))

                               (#e.Error error)
                               #0)))
              )))))

(host.import: java/lang/Class
  (getName [] String))

(def: classes
  (List Text)
  (list "java.lang.Object" "java.lang.Class"
        "java.lang.String" "java.lang.Number"))

(def: instances
  (List [Text (r.Random ls.Synthesis)])
  (let [gen-boolean (|> r.bit (:: r.Functor map code.bit))
        gen-integer (|> r.int (:: r.Functor map code.int))
        gen-double (|> r.frac (:: r.Functor map code.frac))
        gen-string (|> (r.text +5) (:: r.Functor map code.text))]
    (list ["java.lang.Boolean" gen-boolean]
          ["java.lang.Long" gen-integer]
          ["java.lang.Double" gen-double]
          ["java.lang.String" gen-string]
          ["java.lang.Object" (r.either (r.either gen-boolean
                                                  gen-integer)
                                        (r.either gen-double
                                                  gen-string))])))

(context: "Object."
  (<| (times +100)
      (do @
        [#let [num-classes (list.size classes)]
         #let [num-instances (list.size instances)]
         class-idx (|> r.nat (:: @ map (n/% num-classes)))
         instance-idx (|> r.nat (:: @ map (n/% num-instances)))
         exception-message (r.text +5)
         #let [class (maybe.assume (list.nth class-idx classes))
               [instance-class instance-gen] (maybe.assume (list.nth instance-idx instances))
               exception-message$ (` ["java.lang.String" (~ (code.text exception-message))])]
         sample r.int
         monitor r.int
         instance instance-gen]
        ($_ seq
            (test "jvm object null"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate (` ("jvm object null?" ("jvm object null"))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (:coerce Bit outputT)

                             (#e.Error error)
                             #0)))
            (test "jvm object null?"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate (` ("jvm object null?" (~ (code.int sample)))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (not (:coerce Bit outputT))

                             (#e.Error error)
                             #0)))
            (test "jvm object synchronized"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate (` ("jvm object synchronized" (~ (code.int monitor)) (~ (code.int sample)))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (i/= sample (:coerce Int outputT))

                             (#e.Error error)
                             #0)))
            (test "jvm object throw"
                  (|> (do macro.Monad
                        [_ runtimeT.translate
                         sampleI (expressionT.translate (` ("lux try" ("lux function" +1 []
                                                                       ("jvm object throw" ("jvm member invoke constructor"
                                                                                            "java.lang.Throwable"
                                                                                            (~ exception-message$)))))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (case (:coerce (e.Error Any) outputT)
                               (#e.Error error)
                               (text.contains? exception-message error)

                               (#e.Success outputT)
                               #0)

                             (#e.Error error)
                             #0)))
            (test "jvm object class"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate (` ("jvm object class" (~ (code.text class)))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (|> outputT (:coerce Class) (Class::getName []) (text/= class))

                             (#e.Error error)
                             #0)))
            (test "jvm object instance?"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate (` ("jvm object instance?" (~ (code.text instance-class)) (~ instance))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (:coerce Bit outputT)

                             (#e.Error error)
                             #0)))
            ))))

(host.import: java/util/GregorianCalendar
  (#static AD int))

(context: "Member [Field]"
  (<| (times +100)
      (do @
        [sample-short (|> r.int (:: @ map (|>> int/abs (i/% 100))))
         sample-string (r.text +5)
         other-sample-string (r.text +5)
         #let [shortS (` ["short" ("jvm object cast" "java.lang.Short" "short"
                                   ("jvm convert long-to-short" (~ (code.int sample-short))))])
               stringS (` ["java.lang.String" (~ (code.text sample-string))])
               type-codeS (` ["org.omg.CORBA.TypeCode" ("jvm object null")])
               idl-typeS (` ["org.omg.CORBA.IDLType" ("jvm object null")])
               value-memberS (` ("jvm member invoke constructor"
                                 "org.omg.CORBA.ValueMember"
                                 (~ stringS) (~ stringS) (~ stringS) (~ stringS)
                                 (~ type-codeS) (~ idl-typeS) (~ shortS)))]]
        ($_ seq
            (test "jvm member static get"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate (` ("jvm convert int-to-long" ("jvm member static get" "java.util.GregorianCalendar" "AD" "int"))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (i/= GregorianCalendar::AD (:coerce Int outputT))

                             (#e.Error error)
                             #0)))
            (test "jvm member static put"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate (` ("jvm member static put" "java.awt.datatransfer.DataFlavor" "allHtmlFlavor" "java.awt.datatransfer.DataFlavor"
                                                            ("jvm member static get" "java.awt.datatransfer.DataFlavor" "allHtmlFlavor" "java.awt.datatransfer.DataFlavor"))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (is? hostL.unit (:coerce Text outputT))

                             (#e.Error error)
                             #0)))
            (test "jvm member virtual get"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate (` ("jvm member virtual get" "org.omg.CORBA.ValueMember" "name" "java.lang.String" (~ value-memberS))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (text/= sample-string (:coerce Text outputT))

                             (#e.Error error)
                             #0)))
            (test "jvm member virtual put"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate (` ("jvm member virtual get" "org.omg.CORBA.ValueMember" "name" "java.lang.String"
                                                            ("jvm member virtual put" "org.omg.CORBA.ValueMember" "name" "java.lang.String"
                                                             (~ (code.text other-sample-string)) (~ value-memberS)))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (text/= other-sample-string (:coerce Text outputT))

                             (#e.Error error)
                             #0)))
            ))))

(host.import: java/lang/Object)

(host.import: (java/util/ArrayList a))

(context: "Member [Method]"
  (<| (times +100)
      (do @
        [sample (|> r.int (:: @ map (|>> int/abs (i/% 100))))
         #let [object-longS (` ["java.lang.Object" (~ (code.int sample))])
               intS (` ["int" ("jvm object cast" "java.lang.Integer" "int"
                               ("jvm convert long-to-int" (~ (code.int sample))))])
               coded-intS (` ["java.lang.String" (~ (code.text (int/encode sample)))])
               array-listS (` ("jvm member invoke constructor" "java.util.ArrayList" (~ intS)))]]
        ($_ seq
            (test "jvm member invoke static"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate (` ("jvm member invoke static" "java.lang.Long"
                                                            "decode" "java.lang.Long"
                                                            (~ coded-intS))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (i/= sample (:coerce Int outputT))

                             (#e.Error error)
                             #0)))
            (test "jvm member invoke virtual"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate (` ("jvm object cast" "boolean" "java.lang.Boolean"
                                                            ("jvm member invoke virtual" "java.lang.Object" "equals" "boolean"
                                                             (~ (code.int sample)) (~ object-longS)))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (:coerce Bit outputT)

                             (#e.Error error)
                             #0)))
            (test "jvm member invoke interface"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate (` ("jvm object cast" "boolean" "java.lang.Boolean"
                                                            ("jvm member invoke interface" "java.util.Collection" "add" "boolean"
                                                             (~ array-listS) (~ object-longS)))))]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (:coerce Bit outputT)

                             (#e.Error error)
                             #0)))
            (test "jvm member invoke constructor"
                  (|> (do macro.Monad
                        [sampleI (expressionT.translate array-listS)]
                        (evalT.eval sampleI))
                      (lang.with-current-module "")
                      (macro.run (io.run init-jvm))
                      (case> (#e.Success outputT)
                             (host.instance? ArrayList (:coerce Object outputT))

                             (#e.Error error)
                             #0)))
            ))))