forked from norm2782/uhc-jscript
/
import_wrapper.hs
71 lines (52 loc) · 2.46 KB
/
import_wrapper.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import Language.UHC.JS.ECMA.String
import Language.UHC.JS.Assorted
import Language.UHC.JS.Primitives
import Language.UHC.JS.JQuery.JQuery
foreign import jscript "some_function(%*)"
someFun :: Int -> Int -> JSFunPtr (Int -> IO ()) -> IO ()
foreign import jscript "wrapper"
wrap :: (Int -> IO ()) -> IO (JSFunPtr (Int -> IO ()))
myCB :: Int -> Int -> IO ()
myCB n m = alert (show $ m + n)
main :: IO ()
main =
putStrLn "data_export_wrapper"
>>= \_ -> wrap (myCB 2)
>>= \sf -> someFun 2 3 sf
{- main = do-}
{- putStrLn "data_export_wrapper"-}
{- sf <- wrap myCB-}
{- someFun 2 3 sf-}
{-
In this particular case, alert is actually the culprit. It requires two
arguments, because it is in IO. The current hardcoding is correct in the sense
that we're passing the right argument (the monad), but obviously we can't rely
on hardcoding (it won't work with pure functions, for example).
We now require all functions in an exported constructor to be wrapped in an
IO JSFunPtr construction. To enforce this, we need to modify the type-checker.
We then also need to implement wrapper support in the FFI and do lambda lifting
for lambda functions based on the wrappers
Why do we want to wrap functions in IO JSFunPtr?
Because otherwise a plain JS function would get a Haskell representation of a
function, i.e., a: new _A_(new _F_(...)) etc. Regular JS functions do not know
how to deal with these, so we need to wrap them in a regular JS function, which
takes as many arguments as the Haskell function. The Haskell function is then
applied to the arguments and the result is returned. This also explains the
name wrapper....
$import_wrapper.$wrap=
new _F_("import_wrapper.wrap",function($__,$__2)
{trace(">$import_wrapper.$wrap"," <- "+$__+", "+$__2);
var $__3=
_e_($__);
var $__4=
_e_(function(vr1)
{return _e_(new _A_($__3,[vr1]));});
var _=
[$__2,$__4];
trace("<$import_wrapper.$wrap"," -> "+_);
return _;});
This is an example of the code that's generated for the wrap import. Would the
$__2 represent the IO monad? So in case our callback is in IO, we require the
callback function to be also applied to $__2, whereas we don't require this if
it's pure.
-}