(;module: [lux #- char] (lux (control [monad #+ do] ["p" parser] ["ex" exception #+ exception:]) (concurrency ["A" atom]) (data ["R" result] [maybe] [product] [text "text/" Eq] (text format ["l" lexer]) (coll [list "list/" Fold Functor] [array #+ Array] [dict #+ Dict])) [macro "lux/" Monad] [type] (type ["tc" check]) [host]) (luxc ["&" base] ["&;" host] (lang ["la" analysis]) (analyser ["&;" common])) ["@" ../common] ) (def: null-class Text "#Null") (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") (|> (dict;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 ) (|> (dict;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 ) (|> (dict;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") (|> (dict;new text;Hash) (@;install "=" (@;binary Character Character Boolean)) (@;install "<" (@;binary Character Character Boolean)) (@;install ">" (@;binary Character Character Boolean)) ))) (def: #export boxes (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"]) (dict;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 macro;Monad [arrayA (&;with-expected-type (type (Array varT)) (analyse arrayC)) _ (&;infer Nat)] (wrap (#la;Procedure proc (list arrayA)))) _ (&;fail (@;wrong-arity 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 macro;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-arity proc +1 (list;size args)))))) (def: (not-object type) (-> Type Text) (format "Non-object type: " (%type type))) (def: (check-jvm objectT) (-> Type (Lux Text)) (case objectT (#;Host name _) (lux/wrap name) (#;Named name unnamed) (check-jvm unnamed) (^template [] ( env unquantified) (check-jvm unquantified)) ([#;UnivQ] [#;ExQ]) (#;Apply inputT funcT) (case (type;apply (list inputT) funcT) (#;Some outputT) (check-jvm outputT) #;None (&;fail (not-object objectT))) _ (&;fail (not-object objectT)))) (def: (check-object objectT) (-> Type (Lux Text)) (do macro;Monad [name (check-jvm objectT)] (if (dict;contains? name boxes) (&;fail (format "Primitives are not objects: " name)) (:: macro;Monad wrap name)))) (def: (box-array-element-type elemT) (-> Type (Lux [Type Text])) (do macro;Monad [] (case elemT (#;Host name #;Nil) (let [boxed-name (|> (dict;get name boxes) (maybe;default name))] (wrap [(#;Host boxed-name #;Nil) boxed-name])) (#;Host name _) (if (dict;contains? name boxes) (&;fail (format "Primitives cannot be parameterized: " name)) (:: macro;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 macro;Monad [arrayA (&;with-expected-type (type (Array varT)) (analyse arrayC)) elemT (&;with-type-env (tc;read var-id)) [elemT elem-class] (box-array-element-type elemT) idxA (&;with-expected-type Nat (analyse idxC)) _ (&;infer elemT)] (wrap (#la;Procedure proc (list (#la;Text elem-class) arrayA idxA)))) _ (&;fail (@;wrong-arity 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 macro;Monad [arrayA (&;with-expected-type (type (Array varT)) (analyse arrayC)) elemT (&;with-type-env (tc;read var-id)) [valueT elem-class] (box-array-element-type elemT) idxA (&;with-expected-type Nat (analyse idxC)) valueA (&;with-expected-type valueT (analyse valueC)) _ (&;infer (type (Array elemT)))] (wrap (#la;Procedure proc (list (#la;Text elem-class) arrayA idxA valueA)))) _ (&;fail (@;wrong-arity proc +3 (list;size args)))))))) (def: array-procs @;Bundle (<| (@;prefix "array") (|> (dict;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 macro;Monad [expectedT macro;expected-type _ (check-object expectedT)] (wrap (#la;Procedure proc (list)))) _ (&;fail (@;wrong-arity 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 macro;Monad [objectA (&;with-expected-type varT (analyse objectC)) objectT (&;with-type-env (tc;read var-id)) _ (check-object objectT) _ (&;infer Bool)] (wrap (#la;Procedure proc (list objectA)))) _ (&;fail (@;wrong-arity 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 macro;Monad [monitorA (&;with-expected-type varT (analyse monitorC)) monitorT (&;with-type-env (tc;read var-id)) _ (check-object monitorT) exprA (analyse exprC)] (wrap (#la;Procedure proc (list monitorA exprA)))) _ (&;fail (@;wrong-arity proc +2 (list;size args)))))))) (host;import java.lang.Object) (host;import java.lang.ClassLoader) (host;import #long java.lang.reflect.Type (getTypeName [] String)) (host;import java.lang.reflect.GenericArrayType (getGenericComponentType [] java.lang.reflect.Type)) (host;import java.lang.reflect.ParameterizedType (getRawType [] java.lang.reflect.Type) (getActualTypeArguments [] (Array java.lang.reflect.Type))) (host;import (java.lang.reflect.TypeVariable d) (getName [] String) (getBounds [] (Array java.lang.reflect.Type))) (host;import (java.lang.reflect.WildcardType d) (getLowerBounds [] (Array java.lang.reflect.Type)) (getUpperBounds [] (Array java.lang.reflect.Type))) (host;import java.lang.reflect.Modifier (#static isStatic [int] boolean) (#static isFinal [int] boolean)) (host;import java.lang.reflect.Field (getDeclaringClass [] (java.lang.Class Object)) (getModifiers [] int) (getGenericType [] java.lang.reflect.Type)) (host;import (java.lang.Class c) (getName [] String) (#static forName [String boolean ClassLoader] #try (Class Object)) (isAssignableFrom [(Class Object)] boolean) (getTypeParameters [] (Array (TypeVariable (Class c)))) (getGenericInterfaces [] (Array java.lang.reflect.Type)) (getGenericSuperclass [] java.lang.reflect.Type) (getDeclaredField [String] #try Field)) (def: (load-class name) (-> Text (Lux (Class Object))) (do macro;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 macro;Monad [super (load-class super) sub (load-class sub)] (wrap (Class.isAssignableFrom [sub] super)))) (exception: #export Not-Throwable) (def: (object-throw proc) (-> Text @;Proc) (function [analyse args] (&common;with-var (function [[var-id varT]] (case args (^ (list exceptionC)) (do macro;Monad [exceptionA (&;with-expected-type varT (analyse exceptionC)) exceptionT (&;with-type-env (tc;read var-id)) exception-class (check-object exceptionT) ? (sub-class? "java.lang.Throwable" exception-class) _ (: (Lux Unit) (if ? (wrap []) (&;throw Not-Throwable exception-class))) _ (&;infer Bottom)] (wrap (#la;Procedure proc (list exceptionA)))) _ (&;fail (@;wrong-arity proc +1 (list;size args)))))))) (def: (object-class proc) (-> Text @;Proc) (function [analyse args] (case args (^ (list classC)) (case classC [_ (#;Text class)] (do macro;Monad [_ (load-class class) _ (&;infer (#;Host "java.lang.Class" (list (#;Host class (list)))))] (wrap (#la;Procedure proc (list (#la;Text class))))) _ (&;fail (format "Wrong syntax for '" proc "'."))) _ (&;fail (@;wrong-arity proc +1 (list;size args)))))) (exception: #export Cannot-Be-Instance) (def: (object-instance? proc) (-> Text @;Proc) (function [analyse args] (&common;with-var (function [[var-id varT]] (case args (^ (list classC objectC)) (case classC [_ (#;Text class)] (do macro;Monad [objectA (&;with-expected-type varT (analyse objectC)) objectT (&;with-type-env (tc;read var-id)) object-class (check-object objectT) ? (sub-class? class object-class)] (if ? (do @ [_ (&;infer Bool)] (wrap (#la;Procedure proc (list (#la;Text class))))) (&;throw Cannot-Be-Instance (format object-class " !<= " class)))) _ (&;fail (format "Wrong syntax for '" proc "'."))) _ (&;fail (@;wrong-arity proc +2 (list;size args)))))))) (def: object-procs @;Bundle (<| (@;prefix "object") (|> (dict;new text;Hash) (@;install "null" object-null) (@;install "null?" object-null?) (@;install "synchronized" object-synchronized) (@;install "throw" object-throw) (@;install "class" object-class) (@;install "instance?" object-instance?) ))) (exception: #export Final-Field) (exception: #export Cannot-Convert-To-Class) (exception: #export Cannot-Convert-To-Lux-Type) (exception: #export Cannot-Cast-To-Primitive) (exception: #export JVM-Type-Is-Not-Class) (def: type-descriptor (-> java.lang.reflect.Type Text) (java.lang.reflect.Type.getTypeName [])) (def: (java-type-to-class type) (-> java.lang.reflect.Type (Lux Text)) (cond (host;instance? Class type) (lux/wrap (Class.getName [] (:! Class type))) (host;instance? ParameterizedType type) (java-type-to-class (ParameterizedType.getRawType [] (:! ParameterizedType type))) ## else (&;throw Cannot-Convert-To-Class (type-descriptor type)))) (exception: #export Unknown-Type-Var) (type: Mappings (Dict Text Type)) (def: fresh-mappings Mappings (dict;new text;Hash)) (def: (java-type-to-lux-type mappings java-type) (-> Mappings java.lang.reflect.Type (Lux Type)) (cond (host;instance? TypeVariable java-type) (let [var-name (TypeVariable.getName [] (:! TypeVariable java-type))] (case (dict;get var-name mappings) (#;Some var-type) (lux/wrap var-type) #;None (&;throw Unknown-Type-Var var-name))) (host;instance? WildcardType java-type) (let [java-type (:! WildcardType java-type)] (case [(array;get +0 (WildcardType.getUpperBounds [] java-type)) (array;get +0 (WildcardType.getLowerBounds [] java-type))] (^or [(#;Some bound) _] [_ (#;Some bound)]) (java-type-to-lux-type mappings bound) _ (lux/wrap Top))) (host;instance? Class java-type) (let [java-type (:! (Class Object) java-type) class-name (Class.getName [] java-type)] (lux/wrap (case (array;size (Class.getTypeParameters [] java-type)) +0 (#;Host class-name (list)) arity (|> (list;n.range +0 (n.dec arity)) list;reverse (list/map (|>. (n.* +2) n.inc #;Bound)) (#;Host class-name) (type;univ-q arity))))) (host;instance? ParameterizedType java-type) (let [java-type (:! ParameterizedType java-type) raw (ParameterizedType.getRawType [] java-type)] (if (host;instance? Class raw) (do macro;Monad [paramsT (|> java-type (ParameterizedType.getActualTypeArguments []) array;to-list (monad;map @ (java-type-to-lux-type mappings)))] (lux/wrap (#;Host (Class.getName [] (:! (Class Object) raw)) paramsT))) (&;throw JVM-Type-Is-Not-Class (type-descriptor raw)))) (host;instance? GenericArrayType java-type) (do macro;Monad [innerT (|> (:! GenericArrayType java-type) (GenericArrayType.getGenericComponentType []) (java-type-to-lux-type mappings))] (wrap (#;Host "#Array" (list innerT)))) ## else (&;throw Cannot-Convert-To-Lux-Type (type-descriptor java-type)))) (def: (cast to from) (-> Type Type (Lux [Text Type])) (do macro;Monad [to-name (check-jvm to) from-name (check-jvm from)] (cond (dict;contains? to-name boxes) (let [box (maybe;assume (dict;get to-name boxes))] (if (text/= box from-name) (wrap [box (#;Host to-name (list))]) (&;throw Cannot-Cast-To-Primitive (format from-name " => " to-name)))) (dict;contains? from-name boxes) (let [box (maybe;assume (dict;get from-name boxes))] (do @ [[_ castT] (cast to (#;Host box (list)))] (wrap [from-name castT]))) (text/= to-name from-name) (wrap ["" from]) (text/= null-class from-name) (wrap ["" to]) ## else (do @ [to-class (load-class to-name) from-class (load-class from-name) _ (&;assert (format "Class '" from-name "' is not a sub-class of class '" to-name "'.") (Class.isAssignableFrom [from-class] to-class)) candiate-parents (monad;map @ (function [java-type] (do @ [class-name (java-type-to-class java-type) class (load-class class-name)] (wrap [java-type (Class.isAssignableFrom [from-class] to-class)]))) (list& (Class.getGenericSuperclass [] from-class) (array;to-list (Class.getGenericInterfaces [] from-class))))] (case (|> candiate-parents (list;filter product;right) (list/map product;left)) (#;Cons parent _) (do @ [parentT (java-type-to-lux-type fresh-mappings parent)] (cast to parentT)) #;Nil (&;fail (format "No valid path between " (%type from) "and " (%type to) "."))))))) (def: (find-field class-name field-name) (-> Text Text (Lux [(Class Object) Field])) (do macro;Monad [class (load-class class-name)] (case (Class.getDeclaredField [field-name] class) (#R;Success field) (let [owner (Field.getDeclaringClass [] field)] (if (is owner class) (wrap [class field]) (&;fail (format "Field '" field-name "' does not belong to class '" class-name "'.\n" "Belongs to '" (Class.getName [] owner) "'.")))) (#R;Error _) (&;fail (format "Unknown field '" field-name "' for class '" class-name "'."))))) (def: (static-field class-name field-name) (-> Text Text (Lux [Type Bool])) (do macro;Monad [[class fieldJ] (find-field class-name field-name) #let [modifiers (Field.getModifiers [] fieldJ)]] (if (Modifier.isStatic [modifiers]) (let [fieldJT (Field.getGenericType [] fieldJ)] (do @ [fieldT (java-type-to-lux-type fresh-mappings fieldJT)] (wrap [fieldT (Modifier.isFinal [modifiers])]))) (&;fail (format "Field '" field-name "' of class '" class-name "' is not static."))))) (exception: #export Non-Object-Type) (def: (virtual-field class-name field-name objectT) (-> Text Text Type (Lux [Type Bool])) (do macro;Monad [[class fieldJ] (find-field class-name field-name) #let [modifiers (Field.getModifiers [] fieldJ)]] (if (not (Modifier.isStatic [modifiers])) (do @ [#let [fieldJT (Field.getGenericType [] fieldJ) var-names (|> class (Class.getTypeParameters []) array;to-list (list/map (TypeVariable.getName [])))] mappings (: (Lux Mappings) (case objectT (#;Host _class-name _class-params) (do @ [#let [num-params (list;size _class-params) num-vars (list;size var-names)] _ (&;assert (format "Number of paremeters in type does not match expected amount (" (%n num-vars) "): " (%type objectT)) (n.= num-params num-vars))] (wrap (|> (list;zip2 var-names _class-params) (dict;from-list text;Hash)))) _ (&;throw Non-Object-Type (%type objectT)))) fieldT (java-type-to-lux-type mappings fieldJT)] (wrap [fieldT (Modifier.isFinal [modifiers])])) (&;fail (format "Field '" field-name "' of class '" class-name "' is static."))))) (def: (analyse-object class analyse sourceC) (-> Text &;Analyser Code (Lux [Type la;Analysis])) (<| &common;with-var (function [[var-id varT]]) (do macro;Monad [target-class (load-class class) targetT (java-type-to-lux-type fresh-mappings (:! java.lang.reflect.Type target-class)) sourceA (&;with-expected-type varT (analyse sourceC)) sourceT (&;with-type-env (tc;read var-id)) [unboxed castT] (cast targetT sourceT) _ (&;assert (format "Object cannot be a primitive: " unboxed) (text;empty? unboxed))] (wrap [castT sourceA])))) (def: (analyse-input analyse targetT sourceC) (-> &;Analyser Type Code (Lux [Type Text la;Analysis])) (<| &common;with-var (function [[var-id varT]]) (do macro;Monad [sourceA (&;with-expected-type varT (analyse sourceC)) sourceT (&;with-type-env (tc;read var-id)) [unboxed castT] (cast targetT sourceT)] (wrap [castT unboxed sourceA])))) (def: (static-get proc) (-> Text @;Proc) (function [analyse args] (case args (^ (list classC fieldC)) (case [classC fieldC] [[_ (#;Text class)] [_ (#;Text field)]] (do macro;Monad [[fieldT final?] (static-field class field) expectedT macro;expected-type [unboxed castT] (cast expectedT fieldT) _ (&;with-type-env (tc;check expectedT castT))] (wrap (#la;Procedure proc (list (#la;Text class) (#la;Text field) (#la;Text unboxed))))) _ (&;fail (format "Wrong syntax for '" proc "'."))) _ (&;fail (@;wrong-arity proc +2 (list;size args)))))) (def: (static-put proc) (-> Text @;Proc) (function [analyse args] (case args (^ (list classC fieldC valueC)) (case [classC fieldC] [[_ (#;Text class)] [_ (#;Text field)]] (do macro;Monad [[fieldT final?] (static-field class field) _ (&;assert (Final-Field (format class "#" field)) (not final?)) [valueT unboxed valueA] (analyse-input analyse fieldT valueC) _ (&;with-type-env (tc;check fieldT valueT)) _ (&;infer Unit)] (wrap (#la;Procedure proc (list (#la;Text class) (#la;Text field) (#la;Text unboxed) valueA)))) _ (&;fail (format "Wrong syntax for '" proc "'."))) _ (&;fail (@;wrong-arity proc +3 (list;size args)))))) (def: (virtual-get proc) (-> Text @;Proc) (function [analyse args] (case args (^ (list classC fieldC objectC)) (case [classC fieldC] [[_ (#;Text class)] [_ (#;Text field)]] (do macro;Monad [[objectT objectA] (analyse-object class analyse objectC) [fieldT final?] (virtual-field class field objectT) expectedT macro;expected-type [unboxed castT] (cast expectedT fieldT) _ (&;with-type-env (tc;check expectedT castT))] (wrap (#la;Procedure proc (list (#la;Text class) (#la;Text field) (#la;Text unboxed) objectA)))) _ (&;fail (format "Wrong syntax for '" proc "'."))) _ (&;fail (@;wrong-arity proc +3 (list;size args)))))) (def: (virtual-put proc) (-> Text @;Proc) (function [analyse args] (case args (^ (list classC fieldC valueC objectC)) (case [classC fieldC] [[_ (#;Text class)] [_ (#;Text field)]] (do macro;Monad [[objectT objectA] (analyse-object class analyse objectC) [fieldT final?] (virtual-field class field objectT) _ (&;assert (Final-Field (format class "#" field)) (not final?)) [valueT unboxed valueA] (analyse-input analyse fieldT valueC) _ (&;with-type-env (tc;check fieldT valueT)) _ (&;infer Unit)] (wrap (#la;Procedure proc (list (#la;Text class) (#la;Text field) (#la;Text unboxed) valueA objectA)))) _ (&;fail (format "Wrong syntax for '" proc "'."))) _ (&;fail (@;wrong-arity proc +4 (list;size args)))))) (def: member-procs @;Bundle (<| (@;prefix "member") (|> (dict;new text;Hash) (dict;merge (<| (@;prefix "static") (|> (dict;new text;Hash) (@;install "get" static-get) (@;install "put" static-put) ))) (dict;merge (<| (@;prefix "virtual") (|> (dict;new text;Hash) (@;install "get" virtual-get) (@;install "put" virtual-put) ))) ))) (def: #export procedures @;Bundle (<| (@;prefix "jvm") (|> (dict;new text;Hash) (dict;merge conversion-procs) (dict;merge int-procs) (dict;merge long-procs) (dict;merge float-procs) (dict;merge double-procs) (dict;merge char-procs) (dict;merge array-procs) (dict;merge object-procs) (dict;merge member-procs) )))