(;module: [lux #- char] (lux (control [monad #+ do] ["p" parser]) (concurrency ["A" atom]) (data ["R" result] [text] (text format ["l" lexer]) (coll [list "list/" Fold] [array #+ Array] ["d" dict])) [macro #+ Monad] [type] (type ["TC" check]) [host]) (luxc ["&" base] ["&;" host] (lang ["la" analysis #+ Analysis]) (analyser ["&;" common])) ["@" ../common] ) (do-template [ ] [(def: #export Type (#;Host (list)))] ## Boxes [Boolean "java.lang.Boolean"] [Byte "java.lang.Byte"] [Short "java.lang.Short"] [Integer "java.lang.Integer"] [Long "java.lang.Long"] [Float "java.lang.Float"] [Double "java.lang.Double"] [Character "java.lang.Character"] [String "java.lang.String"] ## Primitives [boolean "boolean"] [byte "byte"] [short "short"] [int "int"] [long "long"] [float "float"] [double "double"] [char "char"] ) (def: conversion-procs @;Bundle (<| (@;prefix "convert") (|> (d;new text;Hash) (@;install "double-to-float" (@;unary Double Float)) (@;install "double-to-int" (@;unary Double Integer)) (@;install "double-to-long" (@;unary Double Long)) (@;install "float-to-double" (@;unary Float Double)) (@;install "float-to-int" (@;unary Float Integer)) (@;install "float-to-long" (@;unary Float Long)) (@;install "int-to-byte" (@;unary Integer Byte)) (@;install "int-to-char" (@;unary Integer Character)) (@;install "int-to-double" (@;unary Integer Double)) (@;install "int-to-float" (@;unary Integer Float)) (@;install "int-to-long" (@;unary Integer Long)) (@;install "int-to-short" (@;unary Integer Short)) (@;install "long-to-double" (@;unary Long Double)) (@;install "long-to-float" (@;unary Long Float)) (@;install "long-to-int" (@;unary Long Integer)) (@;install "long-to-short" (@;unary Long Short)) (@;install "long-to-byte" (@;unary Long Byte)) (@;install "char-to-byte" (@;unary Character Byte)) (@;install "char-to-short" (@;unary Character Short)) (@;install "char-to-int" (@;unary Character Integer)) (@;install "char-to-long" (@;unary Character Long)) (@;install "byte-to-long" (@;unary Byte Long)) (@;install "short-to-long" (@;unary Short Long)) ))) (do-template [ ] [(def: @;Bundle (<| (@;prefix ) (|> (d;new text;Hash) (@;install "+" (@;binary )) (@;install "-" (@;binary )) (@;install "*" (@;binary )) (@;install "/" (@;binary )) (@;install "%" (@;binary )) (@;install "=" (@;binary Boolean)) (@;install "<" (@;binary Boolean)) (@;install ">" (@;binary Boolean)) (@;install "and" (@;binary )) (@;install "or" (@;binary )) (@;install "xor" (@;binary )) (@;install "shl" (@;binary Integer )) (@;install "shr" (@;binary Integer )) (@;install "ushr" (@;binary Integer )) )))] [int-procs "int" Integer] [long-procs "long" Long] ) (do-template [ ] [(def: @;Bundle (<| (@;prefix ) (|> (d;new text;Hash) (@;install "+" (@;binary )) (@;install "-" (@;binary )) (@;install "*" (@;binary )) (@;install "/" (@;binary )) (@;install "%" (@;binary )) (@;install "=" (@;binary Boolean)) (@;install "<" (@;binary Boolean)) (@;install ">" (@;binary Boolean)) )))] [float-procs "float" Float] [double-procs "double" Double] ) (def: char-procs @;Bundle (<| (@;prefix "char") (|> (d;new text;Hash) (@;install "=" (@;binary Character Character Boolean)) (@;install "<" (@;binary Character Character Boolean)) (@;install ">" (@;binary Character Character Boolean)) ))) (def: #export boxes (d;Dict Text Text) (|> (list ["boolean" "java.lang.Boolean"] ["byte" "java.lang.Byte"] ["short" "java.lang.Short"] ["int" "java.lang.Integer"] ["long" "java.lang.Long"] ["float" "java.lang.Float"] ["double" "java.lang.Double"] ["char" "java.lang.Character"]) (d;from-list text;Hash))) (def: (array-length proc) (-> Text @;Proc) (function [analyse args] (&common;with-var (function [[var-id varT]] (case args (^ (list arrayC)) (do Monad [arrayA (&;with-expected-type (type (Array varT)) (analyse arrayC)) expectedT macro;expected-type _ (&;within-type-env (TC;check expectedT Nat))] (wrap (#la;Procedure proc (list arrayA)))) _ (&;fail (@;wrong-amount-error proc +1 (list;size args)))))))) (def: (invalid-array-type arrayT) (-> Type Text) (format "Invalid type for array: " (%type arrayT))) (def: (array-new proc) (-> Text @;Proc) (function [analyse args] (case args (^ (list lengthC)) (do Monad [lengthA (&;with-expected-type Nat (analyse lengthC)) expectedT macro;expected-type [level elem-class] (: (Lux [Nat Text]) (loop [analysisT expectedT level +0] (case analysisT (#;Apply inputT funcT) (case (type;apply (list inputT) funcT) (#;Some outputT) (recur outputT level) #;None (&;fail (invalid-array-type expectedT))) (^ (#;Host "#Array" (list elemT))) (recur elemT (n.inc level)) (#;Host class _) (wrap [level class]) _ (&;fail (invalid-array-type expectedT))))) _ (&;assert "Must have at least 1 level of nesting in array type." (n.> +0 level))] (wrap (#la;Procedure proc (list (#la;Nat level) (#la;Text elem-class) lengthA)))) _ (&;fail (@;wrong-amount-error proc +1 (list;size args)))))) (def: (check-object objectT) (-> Type (Lux Text)) (case objectT (#;Host name _) (if (d;contains? name boxes) (&;fail (format "Primitives are not objects: " name)) (:: Monad wrap name)) _ (&;fail (format "Non-object type: " (%type objectT))))) (def: (box-array-element-type elemT) (-> Type (Lux [Type Text])) (do Monad [] (case elemT (#;Host name #;Nil) (let [boxed-name (|> (d;get name boxes) (default name))] (wrap [(#;Host boxed-name #;Nil) boxed-name])) (#;Host name _) (if (d;contains? name boxes) (&;fail (format "Primitives cannot be parameterized: " name)) (:: Monad wrap [elemT name])) _ (&;fail (format "Invalid type for array element: " (%type elemT)))))) (def: (array-read proc) (-> Text @;Proc) (function [analyse args] (&common;with-var (function [[var-id varT]] (case args (^ (list arrayC idxC)) (do Monad [arrayA (&;with-expected-type (type (Array varT)) (analyse arrayC)) elemT (&;within-type-env (TC;read-var var-id)) [elemT elem-class] (box-array-element-type elemT) idxA (&;with-expected-type Nat (analyse idxC)) expectedT macro;expected-type _ (&;within-type-env (TC;check expectedT elemT))] (wrap (#la;Procedure proc (list (#la;Text elem-class) arrayA idxA)))) _ (&;fail (@;wrong-amount-error proc +2 (list;size args)))))))) (def: (array-write proc) (-> Text @;Proc) (function [analyse args] (&common;with-var (function [[var-id varT]] (case args (^ (list arrayC idxC valueC)) (do Monad [arrayA (&;with-expected-type (type (Array varT)) (analyse arrayC)) elemT (&;within-type-env (TC;read-var var-id)) [valueT elem-class] (box-array-element-type elemT) idxA (&;with-expected-type Nat (analyse idxC)) valueA (&;with-expected-type valueT (analyse valueC)) expectedT macro;expected-type _ (&;within-type-env (TC;check expectedT (type (Array elemT))))] (wrap (#la;Procedure proc (list (#la;Text elem-class) arrayA idxA valueA)))) _ (&;fail (@;wrong-amount-error proc +3 (list;size args)))))))) (def: array-procs @;Bundle (<| (@;prefix "array") (|> (d;new text;Hash) (@;install "length" array-length) (@;install "new" array-new) (@;install "read" array-read) (@;install "write" array-write) ))) (def: (object-null proc) (-> Text @;Proc) (function [analyse args] (case args (^ (list)) (do Monad [expectedT macro;expected-type _ (check-object expectedT)] (wrap (#la;Procedure proc (list)))) _ (&;fail (@;wrong-amount-error proc +0 (list;size args)))))) (def: (object-null? proc) (-> Text @;Proc) (function [analyse args] (&common;with-var (function [[var-id varT]] (case args (^ (list objectC)) (do Monad [objectA (&;with-expected-type (type varT) (analyse objectC)) objectT (&;within-type-env (TC;read-var var-id)) _ (check-object objectT) expectedT macro;expected-type _ (&;within-type-env (TC;check expectedT Bool))] (wrap (#la;Procedure proc (list objectA)))) _ (&;fail (@;wrong-amount-error proc +1 (list;size args)))))))) (def: (object-synchronized proc) (-> Text @;Proc) (function [analyse args] (&common;with-var (function [[var-id varT]] (case args (^ (list monitorC exprC)) (do Monad [monitorA (&;with-expected-type (type varT) (analyse monitorC)) monitorT (&;within-type-env (TC;read-var var-id)) _ (check-object monitorT) exprA (analyse exprC)] (wrap (#la;Procedure proc (list monitorA exprA)))) _ (&;fail (@;wrong-amount-error proc +2 (list;size args)))))))) (host;import java.lang.Object) (host;import java.lang.ClassLoader) (host;import (java.lang.Class c) (#static forName [String boolean ClassLoader] #try (Class Object)) (isAssignableFrom [(Class Object)] boolean)) (def: (load-class name) (-> Text (Lux (Class Object))) (do Monad [class-loader &host;class-loader] (case (Class.forName [name false class-loader]) (#R;Success [class]) (wrap class) (#R;Error error) (&;fail (format "Unknown class: " name))))) (def: (sub-class? super sub) (-> Text Text (Lux Bool)) (do Monad [super (load-class super) sub (load-class sub)] (wrap (Class.isAssignableFrom [sub] super)))) (def: (object-throw proc) (-> Text @;Proc) (function [analyse args] (&common;with-var (function [[var-id varT]] (case args (^ (list exceptionC)) (do Monad [exceptionA (&;with-expected-type (type varT) (analyse exceptionC)) exceptionT (&;within-type-env (TC;read-var var-id)) exception-class (check-object exceptionT) ? (sub-class? "java.lang.Throwable" exception-class) _ (: (Lux Unit) (if ? (wrap []) (&;fail (format "Must throw a sub-class of java.lang.Throwable: " exception-class)))) expectedT macro;expected-type _ (&;within-type-env (TC;check expectedT Bottom))] (wrap (#la;Procedure proc (list exceptionA)))) _ (&;fail (@;wrong-amount-error proc +1 (list;size args)))))))) (def: (object-class proc) (-> Text @;Proc) (function [analyse args] (&common;with-var (function [[var-id varT]] (case args (^ (list classC)) (case classC [_ (#;Text class)] (do Monad [_ (load-class class) expectedT macro;expected-type _ (&;within-type-env (TC;check expectedT (#;Host "java.lang.Class" (list (#;Host class (list))))))] (wrap (#la;Procedure proc (list (#la;Text class))))) _ (&;fail (format "Wrong syntax for '" proc "'."))) _ (&;fail (@;wrong-amount-error proc +1 (list;size args)))))))) (def: object-procs @;Bundle (<| (@;prefix "object") (|> (d;new text;Hash) (@;install "null" object-null) (@;install "null?" object-null?) (@;install "synchronized" object-synchronized) (@;install "throw" object-throw) (@;install "class" object-class) ))) (def: #export procedures @;Bundle (<| (@;prefix "jvm") (|> (d;new text;Hash) (d;merge conversion-procs) (d;merge int-procs) (d;merge long-procs) (d;merge float-procs) (d;merge double-procs) (d;merge char-procs) (d;merge array-procs) (d;merge object-procs) )))