16 | import JS.Inheritance
24 | data Object : Type where [external]
27 | ToFFI Object Object where toFFI = id
30 | FromFFI Object Object where fromFFI = Just
41 | %foreign "javascript:lambda:() => {return {}}"
42 | prim__new : () -> Object
44 | %foreign "javascript:lambda:(o,str) => o[str]"
45 | prim__get : Object -> String -> AnyPtr
47 | %foreign "javascript:lambda:(u,o,str,v) => { o[str] = v; return o }"
48 | prim__set : forall a . Object -> String -> a -> Object
50 | %foreign "javascript:lambda:(u,o) => JSON.stringify(o)"
51 | prim__stringify : forall a . a -> String
53 | %foreign "javascript:lambda:s => JSON.parse(s)"
54 | prim__parse : String -> AnyPtr
62 | record LinObject where
63 | constructor MkLinObject
67 | newObj : (1 f : (1 _ : LinObject) -> a) -> a
68 | newObj f = f (MkLinObject (prim__new ()))
71 | thaw : (1 _ : LinObject) -> IO Object
72 | thaw (MkLinObject obj) = pure obj
75 | lset : (1 _ : LinObject) -> (fld : String) -> a -> LinObject
76 | lset (MkLinObject o) f a = MkLinObject $
prim__set o f a
79 | lget : (1 _ : LinObject) -> (fld : String) -> Res AnyPtr (const $
LinObject)
80 | lget (MkLinObject obj) fld = prim__get obj fld # MkLinObject obj
87 | record IObject where
88 | constructor MkIObject
92 | freeze : (1 _ : LinObject) -> IObject
93 | freeze (MkLinObject obj) = MkIObject obj
96 | get : SafeCast a => IObject -> String -> Maybe a
97 | get (MkIObject obj) str = safeCast $
prim__get obj str
104 | data Value : Type where
105 | Arr : IArray Value -> Value
106 | Boolean : Bool -> Value
108 | Num : Double -> Value
109 | Obj : IObject -> Value
110 | Str : String -> Value
112 | toAny : Value -> Any
113 | toAny (Obj x) = MkAny x
114 | toAny (Boolean x) = MkAny $
toFFI x
115 | toAny (Arr x) = MkAny $
assert_total (map toAny x)
116 | toAny (Str x) = MkAny x
117 | toAny (Num x) = MkAny x
118 | toAny Null = MkAny (null {a = ()})
125 | stringify : Value -> String
126 | stringify = prim__stringify . toFFI . toAny
129 | obj : (1 _ : LinObject) -> Value
130 | obj (MkLinObject o) = Obj $
MkIObject o
133 | lsetVal : (1 _ : LinObject) -> (fld : String) -> Value -> LinObject
134 | lsetVal o f v = lset o f (toFFI $
toAny v)
137 | withPairs : List (String,Value) -> ((1 _ : LinObject) -> a) -> a
138 | withPairs ps f = newObj (run ps)
141 | run : List (String,Value) -> (1 _ : LinObject) -> a
143 | run ((s,v) :: ps) o = run ps (lsetVal o s v)
146 | pairs : List (String,Value) -> Value
147 | pairs ps = withPairs ps obj
150 | vals : List Value -> Value
151 | vals = Arr . fromList
157 | toVal : Any -> Maybe Value
158 | toVal (MkAny ptr) =
159 | (Str <$> safeCast ptr)
160 | <|> (Boolean <$> (safeCast ptr >>= fromFFI))
161 | <|> (if isArray ptr then array ptr else Nothing)
162 | <|> (if isNull ptr then Just Null else Nothing)
163 | <|> (Num <$> safeCast ptr)
164 | <|> (Obj . MkIObject <$> unsafeCastOnTypeof "object" ptr)
167 | array : a -> Maybe Value
169 | let arr := the (IArray Any) (believe_me a)
170 | in assert_total $
Arr <$> traverse toVal arr
173 | parse : String -> Either JSErr Value
175 | ptr <- try prim__parse s
177 | (Left $
Caught #"Unable to decode JSON: \#{s}"#)
179 | (toVal (MkAny ptr))
182 | parseMaybe : String -> Maybe Value
183 | parseMaybe = either (const Nothing) Just . parse
186 | getObject : Value -> Maybe IObject
187 | getObject (Obj x) = Just x
188 | getObject _ = Nothing
191 | getBool : Value -> Maybe Bool
192 | getBool (Boolean x) = Just x
193 | getBool _ = Nothing
196 | getStr : Value -> Maybe String
197 | getStr (Str x) = Just x
201 | getNum : Value -> Maybe Double
202 | getNum (Num x) = Just x
206 | getArray : Value -> Maybe (IArray Value)
207 | getArray (Arr x) = Just x
208 | getArray _ = Nothing
211 | valueAt : IObject -> String -> Maybe Value
212 | valueAt (MkIObject obj) = toVal . MkAny . prim__get obj