Skip to content

Instantly share code, notes, and snippets.

@acrylic-origami
Created June 18, 2020 11:13
Show Gist options
  • Save acrylic-origami/c253e062a1e9b508e685bb2650dee89f to your computer and use it in GitHub Desktop.
Save acrylic-origami/c253e062a1e9b508e685bb2650dee89f to your computer and use it in GitHub Desktop.
Asterius Haskell exported function issue: difference between ahc-cabal+ahc-dist and ahc-link
{-# OPTIONS_GHC -Wall -ddump-to-file -ddump-rn -ddump-foreign -ddump-stg -ddump-cmm-raw -ddump-asm #-}
module AsteriusPrim
( emptyJSString,
concatJSString,
indexJSString,
toJSString,
fromJSString,
emptyJSArray,
concatJSArray,
indexJSArray,
toJSArray,
fromJSArray,
emptyJSObject,
indexJSObject,
callJSObjectMethod,
json,
callJSFunction,
)
where
import Asterius.Types (JSVal (..))
import Data.List
{-# INLINEABLE emptyJSString #-}
emptyJSString :: JSVal
emptyJSString = js_string_empty
{-# INLINEABLE concatJSString #-}
concatJSString :: JSVal -> JSVal -> JSVal
concatJSString = js_concat
{-# INLINEABLE indexJSString #-}
indexJSString :: JSVal -> Int -> Char
indexJSString = js_string_tochar
{-# INLINEABLE toJSString #-}
toJSString :: String -> JSVal
toJSString =
foldl' (\s c -> js_concat s (js_string_fromchar c)) js_string_empty
{-# INLINEABLE fromJSString #-}
fromJSString :: JSVal -> String
fromJSString s = [js_string_tochar s i | i <- [0 .. js_length s - 1]]
{-# INLINEABLE emptyJSArray #-}
emptyJSArray :: JSVal
emptyJSArray = js_array_empty
{-# INLINEABLE concatJSArray #-}
concatJSArray :: JSVal -> JSVal -> JSVal
concatJSArray = js_concat
{-# INLINEABLE indexJSArray #-}
indexJSArray :: JSVal -> Int -> JSVal
indexJSArray = js_index_by_int
{-# INLINEABLE toJSArray #-}
toJSArray :: [JSVal] -> JSVal
toJSArray = foldl' js_concat js_array_empty
{-# INLINEABLE fromJSArray #-}
fromJSArray :: JSVal -> [JSVal]
fromJSArray arr = [js_index_by_int arr i | i <- [0 .. js_length arr - 1]]
{-# INLINEABLE emptyJSObject #-}
emptyJSObject :: JSVal
emptyJSObject = js_object_empty
{-# INLINEABLE indexJSObject #-}
indexJSObject :: JSVal -> String -> JSVal
indexJSObject obj k = js_index_by_jsref obj (toJSString k)
{-# INLINEABLE callJSObjectMethod #-}
callJSObjectMethod :: JSVal -> String -> [JSVal] -> JSVal
callJSObjectMethod obj f args =
js_function_apply (js_index_by_jsref obj (toJSString f)) obj (toJSArray args)
{-# INLINEABLE json #-}
json :: JSVal
json = js_json
{-# INLINEABLE callJSFunction #-}
callJSFunction :: JSVal -> [JSVal] -> JSVal
callJSFunction f args = js_function_apply f js_object_empty (toJSArray args)
foreign import javascript "\"\"" js_string_empty :: JSVal
foreign import javascript "$1.concat($2)"
js_concat :: JSVal -> JSVal -> JSVal
foreign import javascript "$1.length" js_length :: JSVal -> Int
foreign import javascript "String.fromCodePoint($1)"
js_string_fromchar :: Char -> JSVal
foreign import javascript "$1.codePointAt($2)"
js_string_tochar :: JSVal -> Int -> Char
foreign import javascript "[]" js_array_empty :: JSVal
foreign import javascript "$1[$2]" js_index_by_int :: JSVal -> Int -> JSVal
foreign import javascript "{}" js_object_empty :: JSVal
foreign import javascript "$1[$2]"
js_index_by_jsref :: JSVal -> JSVal -> JSVal
foreign import javascript "JSON" js_json :: JSVal
foreign import javascript "$1.apply($2, $3)"
js_function_apply :: JSVal -> JSVal -> JSVal -> JSVal
#!/usr/bin/env bash
set -e
ahc-cabal build
rm bin || true
ln -s dist-newstyle/build/x86_64-linux/ghc-8.8.3/jsffi-0.1.0.0/x/jsffi/build/jsffi/ bin
ahc-dist --input-exe bin/jsffi --input-mjs jsffi.mjs --export-function=mult_hs_int --export-function=mult_hs_double --export-function=putchar --run
cabal-version: >=1.10
-- Initial package description 'workspace.cabal' generated by 'cabal init'.
-- For further documentation, see http://haskell.org/cabal/users-guide/
name: jsffi
version: 0.1.0.0
-- synopsis:
-- description:
-- bug-reports:
-- license:
license-file: LICENSE
-- author:
-- maintainer:
-- copyright:
-- category:
build-type: Simple
extra-source-files: CHANGELOG.md
executable jsffi
main-is: jsffi.hs
other-modules: AsteriusPrim
-- other-extensions:
build-depends: base, asterius-prelude
-- hs-source-dirs:
default-language: Haskell2010
{-# OPTIONS_GHC -Wall -ddump-to-file -ddump-rn -ddump-foreign -ddump-stg -ddump-cmm-raw -ddump-asm #-}
import Asterius.Types (JSVal (..))
import AsteriusPrim
import Foreign.StablePtr
foreign import javascript "new Date()" current_time :: IO JSVal
foreign import javascript "console.log($1)" js_print :: JSVal -> IO ()
foreign import javascript "console.log(String.fromCodePoint($1))"
js_putchar :: Char -> IO ()
foreign import javascript "$1 * $2" js_mult :: Int -> Int -> Int
foreign import javascript "console.log($1)" print_int :: Int -> IO ()
foreign import javascript "$1"
js_stableptr_id :: StablePtr Int -> IO (StablePtr Int)
foreign import javascript "false" js_false :: Bool
foreign import javascript "true" js_true :: Bool
foreign import javascript "Math.random()" js_random :: IO Double
foreign import javascript "console.log($1)" js_print_double :: Double -> IO ()
foreign export javascript "mult_hs_int" (*) :: Int -> Int -> Int
foreign export javascript "mult_hs_double" (*) :: Double -> Double -> Double
foreign export javascript "putchar" js_putchar :: Char -> IO ()
main :: IO ()
main = do
t <- current_time
js_print t
js_putchar 'H'
let x = js_mult 6 7
print_int x
x' <- newStablePtr 233 >>= js_stableptr_id >>= deRefStablePtr
print_int x'
js_print $ toJSString $ fromJSString $
toJSString
"I AM A STRING THAT LEAPS BETWEEN HEAPS"
js_print $ toJSArray $ fromJSArray $ toJSArray [t, t, t]
js_print $ callJSObjectMethod json "parse" [toJSString "{}"]
print_int $ fromEnum js_false
print_int $ fromEnum js_true
js_random >>= js_print_double
js_random >>= js_print_double
import * as rts from "./rts.mjs";
import module from "./jsffi.wasm.mjs";
import jsffi from "./jsffi.req.mjs";
process.on("unhandledRejection", err => {
throw err;
});
module
.then(m => rts.newAsteriusInstance(Object.assign(jsffi, { module: m })))
.then(async i => {
await i.exports.main();
console.log(await i.exports.mult_hs_int(9, 9));
console.log(await i.exports.mult_hs_double(9, 9));
await i.exports.putchar("H".codePointAt(0));
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment