5 | import Control.Monad.Reader
6 | import Control.Monad.RWS
7 | import Control.Monad.State
8 | import Control.Monad.Writer
9 | import public Control.Monad.Either
14 | %foreign "javascript:lambda:v=>typeof(v)"
15 | prim__typeOf : AnyPtr -> String
20 | typeof : a -> String
21 | typeof v = prim__typeOf (believe_me v)
23 | %foreign "javascript:lambda:(a,b)=>a === b?1:0"
24 | prim__eqv : AnyPtr -> AnyPtr -> Bool
29 | eqv : a -> b -> Bool
30 | eqv x y = prim__eqv (believe_me x) (believe_me y)
32 | %foreign "javascript:lambda:x=>String(x)"
33 | prim__show : AnyPtr -> String
37 | jsShow : a -> String
38 | jsShow v = prim__show (believe_me v)
44 | %foreign "javascript:lambda:x=>console.log(x)"
45 | prim__consoleLog : String -> PrimIO ()
48 | consoleLog : HasIO io => String -> io ()
49 | consoleLog s = primIO $
prim__consoleLog s
52 | data JSErr : Type where
53 | Caught : (msg : String) -> JSErr
54 | CastErr : (inFunction : String) -> (value : a) -> JSErr
55 | IsNothing : (callSite : String) -> JSErr
58 | dispErr : JSErr -> String
59 | dispErr (CastErr inFunction value) = #"""
60 | Error when casting a Javascript value in function \#{inFunction}.
61 | The value was: \#{jsShow value}.
62 | The value's type was \#{typeof value}.
65 | dispErr (IsNothing callSite) =
66 | #"Trying to extract a value from Nothing at \#{callSite}"#
68 | dispErr (Caught msg) = msg
73 | JSIO = EitherT JSErr IO
76 | interface HasIO io => LiftJSIO io where
77 | liftJSIO : JSIO a -> io a
84 | LiftJSIO m => LiftJSIO (StateT s m) where
85 | liftJSIO m = ST $
\st => (st,) <$> liftJSIO m
88 | LiftJSIO m => LiftJSIO (ReaderT e m) where
89 | liftJSIO m = MkReaderT $
\_ => liftJSIO m
92 | LiftJSIO m => LiftJSIO (WriterT w m) where
93 | liftJSIO m = MkWriterT $
\vw => (,vw) <$> liftJSIO m
96 | LiftJSIO m => LiftJSIO (RWST r w w m) where
97 | liftJSIO m = MkRWST $
\_,vs,vw => (,vs,vw) <$> liftJSIO m
100 | runJSWith : Lazy (JSErr -> IO a) -> JSIO a -> IO a
101 | runJSWith f (MkEitherT io) = io >>= either f pure
104 | runJS : JSIO () -> IO ()
105 | runJS = runJSWith (consoleLog . dispErr)
108 | runJSWithDefault : Lazy a -> JSIO a -> IO a
109 | runJSWithDefault a = runJSWith (\e => consoleLog (dispErr e) $> a)
112 | primJS : PrimIO a -> JSIO a
116 | unMaybe : (callSite : String) -> JSIO (Maybe a) -> JSIO a
117 | unMaybe callSite io = do
118 | Just a <- io | Nothing => throwError $
IsNothing callSite
125 | %foreign "javascript:lambda:(u,io) => {try { return [1,io()]; } catch (e) { return [0,String(e)] }}"
126 | prim__tryIO : forall a . IO a -> PrimIO AnyPtr
128 | %foreign "javascript:lambda:(x,y,f,v) => {try { return [1,f(v)]; } catch (e) { return [0,String(e)] }}"
129 | prim__try : forall a,b . (a -> b) -> a -> AnyPtr
131 | %foreign "javascript:lambda:x => x[0]"
132 | prim__errTag : AnyPtr -> Double
134 | %foreign "javascript:lambda:x => x[1]"
135 | prim__errVal : AnyPtr -> AnyPtr
137 | toEither : AnyPtr -> Either JSErr a
139 | if 1 == prim__errTag ptr
140 | then Right (believe_me (prim__errVal ptr))
141 | else Left $
Caught (believe_me (prim__errVal ptr))
146 | tryIO : IO a -> JSIO a
148 | ptr <- primIO $
prim__tryIO io
149 | if 1 == prim__errTag ptr
150 | then pure (believe_me (prim__errVal ptr))
151 | else throwError $
Caught (believe_me (prim__errVal ptr))
157 | try : (a -> b) -> a -> Either JSErr b
158 | try f a = toEither $
prim__try f a
166 | data WindowProxy : Type where [external]