(;module: {#;doc "Codecs for values in the JSON format. For more information, please see: http://www.json.org/"} lux (lux (control functor applicative [monad #+ do Monad] [eq #+ Eq] codec ["p" parser "p/" Monad]) (data [bool] [bit] [text "text/" Eq Monoid] (text ["l" lexer]) [number "real/" Codec "nat/" Codec] maybe ["R" result] [sum] [product] (coll [list "L/" Fold Monad] [vector #+ Vector vector "Vector/" Monad] ["d" dict])) (time ["i" instant] ["du" duration] ["da" date]) [macro #+ Monad with-gensyms] (macro ["s" syntax #+ syntax:] [code] [poly #+ poly:]) [type] ) [.. #+ JSON] [../reader]) ## [Values] (def: #hidden (show-null _) (-> ..;Null Text) "null") (do-template [ ] [(def: (-> Text) )] [show-boolean ..;Boolean (:: bool;Codec encode)] [show-number ..;Number (:: number;Codec encode)] [show-string ..;String text;encode]) (def: (show-array show-json elems) (-> (-> JSON Text) (-> ..;Array Text)) ($_ text/append "[" (|> elems (Vector/map show-json) vector;to-list (text;join-with ",")) "]")) (def: (show-object show-json object) (-> (-> JSON Text) (-> ..;Object Text)) ($_ text/append "{" (|> object d;entries (L/map (function [[key value]] ($_ text/append (show-string key) ":" (show-json value)))) (text;join-with ",")) "}")) (def: (show-json json) (-> JSON Text) (case json (^template [ ] ( value) ( value)) ([#..;Null show-null] [#..;Boolean show-boolean] [#..;Number show-number] [#..;String show-string] [#..;Array (show-array show-json)] [#..;Object (show-object show-json)]) )) (def: space~ (l;Lexer Text) (l;some l;space)) (def: data-sep (l;Lexer [Text Unit Text]) ($_ p;seq space~ (l;this ",") space~)) (def: null~ (l;Lexer ..;Null) (do p;Monad [_ (l;this "null")] (wrap []))) (do-template [ ] [(def: (l;Lexer ..;Boolean) (do p;Monad [_ (l;this )] (wrap )))] [t~ "true" true] [f~ "false" false] ) (def: boolean~ (l;Lexer ..;Boolean) (p;either t~ f~)) (def: number~ (l;Lexer ..;Number) (do p;Monad [signed? (l;this? "-") digits (l;many l;decimal) decimals (p;default "0" (do @ [_ (l;this ".")] (l;many l;decimal))) exp (p;default "" (do @ [mark (l;one-of "eE") signed?' (l;this? "-") offset (l;many l;decimal)] (wrap ($_ text/append mark (if signed?' "-" "") offset))))] (case (real/decode ($_ text/append (if signed? "-" "") digits "." decimals exp)) (#R;Error message) (p;fail message) (#R;Success value) (wrap value)))) (def: escaped~ (l;Lexer Text) ($_ p;either (p;after (l;this "\\t") (p/wrap "\t")) (p;after (l;this "\\b") (p/wrap "\b")) (p;after (l;this "\\n") (p/wrap "\n")) (p;after (l;this "\\r") (p/wrap "\r")) (p;after (l;this "\\f") (p/wrap "\f")) (p;after (l;this "\\\"") (p/wrap "\"")) (p;after (l;this "\\\\") (p/wrap "\\")))) (def: string~ (l;Lexer ..;String) (<| (l;enclosed ["\"" "\""]) (loop [_ []]) (do p;Monad [chars (l;some (l;none-of "\\\"")) stop l;peek]) (if (text/= "\\" stop) (do @ [escaped escaped~ next-chars (recur [])] (wrap ($_ text/append chars escaped next-chars))) (wrap chars)))) (def: (kv~ json~) (-> (-> Unit (l;Lexer JSON)) (l;Lexer [..;String JSON])) (do p;Monad [key string~ _ space~ _ (l;this ":") _ space~ value (json~ [])] (wrap [key value]))) (do-template [ ] [(def: ( json~) (-> (-> Unit (l;Lexer JSON)) (l;Lexer )) (do p;Monad [_ (l;this ) _ space~ elems (p;sep-by data-sep ) _ space~ _ (l;this )] (wrap ( elems))))] [array~ ..;Array "[" "]" (json~ []) vector;from-list] [object~ ..;Object "{" "}" (kv~ json~) (d;from-list text;Hash)] ) (def: (json~' _) (-> Unit (l;Lexer JSON)) ($_ p;alt null~ boolean~ number~ string~ (array~ json~') (object~ json~'))) (struct: #export _ (Codec Text JSON) (def: encode show-json) (def: decode (function [input] (l;run input (json~' []))))) ## [Polytypism] (def: #hidden _map_ (All [a b] (-> (-> a b) (List a) (List b))) L/map) (def: tag (-> Nat Real) (|>. nat-to-int int-to-real)) (def: #hidden (rec-encode non-rec) (All [a] (-> (-> (-> a JSON) (-> a JSON)) (-> a JSON))) (function [input] (non-rec (rec-encode non-rec) input))) (def: low-mask Nat (|> +1 (bit;shift-left +32) n.dec)) (def: high-mask Nat (|> low-mask (bit;shift-left +32))) (struct: #hidden _ (Codec JSON Nat) (def: (encode input) (let [high (|> input (bit;and high-mask) (bit;unsigned-shift-right +32)) low (bit;and low-mask input)] (..;array (vector (|> high nat-to-int int-to-real #..;Number) (|> low nat-to-int int-to-real #..;Number))))) (def: (decode input) (<| (../reader;run input) (do p;Monad [high ../reader;number low ../reader;number]) (wrap (n.+ (|> high real-to-int int-to-nat (bit;shift-left +32)) (|> low real-to-int int-to-nat)))))) (struct: #hidden _ (Codec JSON Int) (def: encode (|>. int-to-nat (:: Codec encode))) (def: decode (|>. (:: Codec decode) (:: R;Functor map nat-to-int)))) (poly: #hidden Codec//encode (with-expansions [ (do-template [ ] [(do @ [_ ] (wrap (` (: (~ (@JSON//encode inputT)) ))))] [Unit poly;unit (function [(~ (code;symbol ["" "0"]))] #..;Null)] [Bool poly;bool ..;boolean] [Nat poly;nat (:: ;;Codec (~' encode))] [Int poly;int (:: ;;Codec (~' encode))] [Real poly;real ..;number] [Text poly;text ..;string])