Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support GHC JS backend #135

Merged
merged 54 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
db50683
Fix build with JS backend
hsyl20 May 12, 2023
9770bc4
Convert GHCJS foreign import syntax to GHC JavaScript backend syntax
JoshMeredith Jun 5, 2023
15b2c00
Testsuite fixes
JoshMeredith Jul 17, 2023
d58f439
WIP github actions
JoshMeredith Jul 18, 2023
3c1262e
WIP github actions
JoshMeredith Jul 18, 2023
05841cb
Test to trigger PR action
JoshMeredith Jul 18, 2023
c0d1526
WIP github actions
JoshMeredith Jul 19, 2023
34d3211
WIP github actions
JoshMeredith Jul 19, 2023
42bf064
WIP github actions
JoshMeredith Jul 19, 2023
1a9d233
WIP github actions
JoshMeredith Jul 19, 2023
4550276
WIP github actions
JoshMeredith Jul 19, 2023
97e24ad
WIP github actions
JoshMeredith Jul 19, 2023
69d5450
WIP github actions
JoshMeredith Jul 19, 2023
f6b9442
WIP github actions
JoshMeredith Jul 19, 2023
f1f3f98
WIP github actions
JoshMeredith Jul 19, 2023
adae93f
WIP github actions
JoshMeredith Jul 19, 2023
62674a4
WIP github actions
JoshMeredith Jul 19, 2023
3b527ce
WIP github actions
JoshMeredith Jul 19, 2023
83d341b
WIP github actions
JoshMeredith Jul 19, 2023
0020c49
WIP github actions
JoshMeredith Jul 19, 2023
c15a18d
WIP github actions
JoshMeredith Jul 19, 2023
1c1f9b8
WIP github actions
JoshMeredith Jul 19, 2023
6740746
WIP github actions
JoshMeredith Jul 19, 2023
559dd65
WIP github actions
JoshMeredith Jul 19, 2023
177fef1
WIP github actions
JoshMeredith Sep 27, 2023
4364ae8
Newer dependencies for ghcjs-base.
alaendle Oct 21, 2023
890cae6
Up to date QuickCheck provides Arbitrary instance for Newline/Newline…
alaendle Oct 21, 2023
5c166b6
First inlining (workaround haskellari/splitmix#75)
alaendle Oct 21, 2023
f3aa075
Solved - for "\$1\.(.*)"
alaendle Oct 21, 2023
be36c53
WIP github actions
JoshMeredith Oct 30, 2023
4ebdcbf
WIP github actions
JoshMeredith Oct 30, 2023
a061be1
Bump packages
JoshMeredith Nov 2, 2023
c5ef40a
Add tests/compat.js to ghc-options for the testsuite
JoshMeredith Nov 2, 2023
eda5ca7
Fix typo
JoshMeredith Nov 2, 2023
9322ce7
Fix typo
JoshMeredith Nov 2, 2023
819552c
Bump GHC version
JoshMeredith Nov 2, 2023
1dc1aca
Fixes
JoshMeredith Nov 2, 2023
2cb5651
Fixes
JoshMeredith Nov 2, 2023
144c1c8
Fix warnings
JoshMeredith Nov 6, 2023
5b4353a
Fix jsstringHexI64
JoshMeredith Nov 8, 2023
c64b07a
Fix `inidicies` function
JoshMeredith Nov 20, 2023
632ff5a
Fix callbacks
hamishmack Feb 4, 2024
067a344
Fix text
hamishmack Feb 4, 2024
103014d
Update version and set lower bound on base
hamishmack Feb 5, 2024
1be96e6
Remove callback module as it is in base
hamishmack Feb 5, 2024
b23aa44
Fix callback code
hamishmack Feb 5, 2024
6e0b978
Get OnBlocked from `base`
hamishmack Feb 5, 2024
4902019
Fix missing return
hamishmack Feb 7, 2024
1f9da3d
Remove unused code
hamishmack Feb 7, 2024
c37df4b
Fix missing return
hamishmack Feb 7, 2024
069c781
Bump containers upper bound
hamishmack Feb 7, 2024
dc9599b
Reenable j_snoc and fix unbound variable in FFI import
JoshMeredith Feb 12, 2024
ca5d478
Update jsbits/jsstring.js
JoshMeredith Feb 12, 2024
a684c4e
Set version to 0.8.0.0 so it does not look like stable release
hamishmack Feb 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/ghcjs-base.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: ghcjs-base

on:
pull_request:

jobs:
build:
runs-on: ubuntu-latest

defaults:
run:
shell: devx {0}

steps:
- uses: actions/checkout@v3
# - uses: mymindstorm/setup-emsdk@v11
# - uses: cachix/install-nix-action@v22
# - uses: haskell/actions/setup@v2

# - name: Install GHC
# run: nix develop github:input-output-hk/devx#ghc962-js

- name: Install GHC
uses: input-output-hk/actions/devx@latest
with:
platform: x86_64-linux
target-platform: "-js"
minimal: true
compiler-nix-name: ghc98

- name: Cabal
run: file $(which cabal)

- name: Info
run: javascript-unknown-ghcjs-ghc --info

- name: Build
run: |
cabal update
cabal build all

- name: Test
run: cabal test test:tests
32 changes: 17 additions & 15 deletions Data/JSString.hs
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ import Data.Semigroup (Semigroup(..))

import Unsafe.Coerce

import GHCJS.Prim (JSVal)
import qualified GHCJS.Prim as Prim
import GHC.JS.Prim (JSVal)
import qualified GHC.JS.Prim as Prim

import Data.JSString.Internal.Type
import Data.JSString.Internal.Fusion (stream, unstream)
Expand Down Expand Up @@ -300,11 +300,13 @@ unpackCString# addr# = unstream (S.streamCString# addr#)
unstream (S.map safe (S.streamList [a]))
= singleton a #-}

#ifdef MIN_VERSION_ghcjs_prim
#if MIN_VERSION_ghcjs_prim(0,1,1)
{-# RULES "JSSTRING literal prim" [0] forall a.
unpackCString# a = JSString (Prim.unsafeUnpackJSStringUtf8# a)
#-}
#endif
#endif

-- | /O(1)/ Convert a character into a 'JSString'. Subject to fusion.
-- Performs replacement on invalid scalar values.
Expand Down Expand Up @@ -1813,16 +1815,16 @@ charWidth cp | isTrue# (cp >=# 0x10000#) = 2#
-- -----------------------------------------------------------------------------

foreign import javascript unsafe
"h$jsstringPack($1)" js_pack :: Exts.Any -> JSString
"h$jsstringPack" js_pack :: Exts.Any -> JSString
foreign import javascript unsafe
"$1===''" js_null :: JSString -> Bool
"((x) => { return x === ''; })" js_null :: JSString -> Bool
foreign import javascript unsafe
"$1===null" js_isNull :: JSVal -> Bool
"((x) => { return x === null; })" js_isNull :: JSVal -> Bool
foreign import javascript unsafe
"$1===$2" js_eq :: JSString -> JSString -> Bool
"((x,y) => { return x === y; })" js_eq :: JSString -> JSString -> Bool
foreign import javascript unsafe
-- "h$jsstringAppend" js_append :: JSString -> JSString -> JSString -- debug
"$1+$2" js_append :: JSString -> JSString -> JSString
"((x,y) => { return x + y; })" js_append :: JSString -> JSString -> JSString
foreign import javascript unsafe
"h$jsstringCompare" js_compare :: JSString -> JSString -> Int#
-- "($1<$2)?-1:(($1>$2)?1:0)" js_compare :: JSString -> JSString -> Int#
Expand All @@ -1839,15 +1841,15 @@ foreign import javascript unsafe
foreign import javascript unsafe
"h$jsstringUnsnoc" js_unsnoc :: JSString -> (# Int#, JSString #)
foreign import javascript unsafe
"$3.substr($1,$2)" js_substr :: Int# -> Int# -> JSString -> JSString
"((x,y,z) => { return z.substr(x,y); })" js_substr :: Int# -> Int# -> JSString -> JSString
foreign import javascript unsafe
"$2.substr($1)" js_substr1 :: Int# -> JSString -> JSString
"((x,y) => { return y.substr(x); })" js_substr1 :: Int# -> JSString -> JSString
foreign import javascript unsafe
"$3.substring($1,$2)" js_substring :: Int# -> Int# -> JSString -> JSString
"((x,y,z) => { return z.substring(x,y); })" js_substring :: Int# -> Int# -> JSString -> JSString
foreign import javascript unsafe
"$1.length" js_length :: JSString -> Int#
"((x) => { return x.length; })" js_length :: JSString -> Int#
foreign import javascript unsafe
"(($2.charCodeAt($1)|1023)===0xDBFF)?2:1" js_charWidthAt
"((x,y) => { return ((y.charCodeAt(x)|1023)===0xDBFF)?2:1; })" js_charWidthAt
:: Int# -> JSString -> Int#
foreign import javascript unsafe
"h$jsstringIndex" js_index :: Int# -> JSString -> Int#
Expand Down Expand Up @@ -1949,7 +1951,7 @@ foreign import javascript unsafe
foreign import javascript unsafe
"h$jsstringReplicateChar" js_replicateChar :: Int -> Char -> JSString
foreign import javascript unsafe
"var l=$1.length; $r=l==1||(l==2&&($1.charCodeAt(0)|1023)==0xDFFF);"
"((x) => { var l = x.length; return l==1 || (l==2 && (x.charCodeAt(0)|1023) == 0xDFFF); })"
js_isSingleton :: JSString -> Bool
foreign import javascript unsafe
"h$jsstringIntersperse"
Expand All @@ -1958,6 +1960,6 @@ foreign import javascript unsafe
"h$jsstringIntercalate"
js_intercalate :: JSString -> Exts.Any {- [JSString] -} -> JSString
foreign import javascript unsafe
"$1.toUpperCase()" js_toUpper :: JSString -> JSString
"((x) => { return x.toUpperCase(); })" js_toUpper :: JSString -> JSString
foreign import javascript unsafe
"$1.toLowerCase()" js_toLower :: JSString -> JSString
"((x) => { return x.toLowerCase(); })" js_toLower :: JSString -> JSString
114 changes: 59 additions & 55 deletions Data/JSString/Int.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE GHCForeignImportPrim #-}
{-# LANGUAGE LambdaCase #-}

module Data.JSString.Int
( decimal
Expand All @@ -16,14 +17,11 @@ import Data.Monoid

import GHC.Int
import GHC.Word
import GHC.Exts ( ByteArray#
, Int(..), Int#, Int64#
, Word(..), Word#, Word64#
, (<#), (<=#), isTrue# )

import GHC.Integer.GMP.Internals
import GHC.Exts hiding (Any)
import GHC.Num.Integer
import GHC.Num.Natural
import Unsafe.Coerce
import GHCJS.Prim
import GHC.JS.Prim

decimal :: Integral a => a -> JSString
decimal i = decimal' i
Expand All @@ -38,7 +36,9 @@ decimal i = decimal' i
{-# RULES "decimal/Word32" decimal = decimalW32 :: Word32 -> JSString #-}
{-# RULES "decimal/Word64" decimal = decimalW64 :: Word64 -> JSString #-}
{-# RULES "decimal/Integer" decimal = decimalInteger :: Integer -> JSString #-}
{-# RULES "decimal/Natural" decimal = decimalNatural :: Natural -> JSString #-}
{-# SPECIALIZE decimal :: Integer -> JSString #-}
{-# SPECIALIZE decimal :: Natural -> JSString #-}
{-# SPECIALIZE decimal :: Int -> JSString #-}
{-# SPECIALIZE decimal :: Int8 -> JSString #-}
{-# SPECIALIZE decimal :: Int16 -> JSString #-}
Expand All @@ -56,27 +56,27 @@ decimalI (I# x) = js_decI x
{-# INLINE decimalI #-}

decimalI8 :: Int8 -> JSString
decimalI8 (I8# x) = js_decI x
decimalI8 (I8# x) = js_decI (int8ToInt# x)
{-# INLINE decimalI8 #-}

decimalI16 :: Int16 -> JSString
decimalI16 (I16# x) = js_decI x
decimalI16 (I16# x) = js_decI (int16ToInt# x)
{-# INLINE decimalI16 #-}

decimalI32 :: Int32 -> JSString
decimalI32 (I32# x) = js_decI x
decimalI32 (I32# x) = js_decI (int32ToInt# x)
{-# INLINE decimalI32 #-}

decimalI64 :: Int64 -> JSString
decimalI64 (I64# x) = js_decI64 x
{-# INLINE decimalI64 #-}

decimalW8 :: Word8 -> JSString
decimalW8 (W8# x) = js_decW x
decimalW8 (W8# x) = js_decW (word8ToWord# x)
{-# INLINE decimalW8 #-}

decimalW16 :: Word16 -> JSString
decimalW16 (W16# x) = js_decW x
decimalW16 (W16# x) = js_decW (word16ToWord# x)
{-# INLINE decimalW16 #-}

decimalW32 :: Word32 -> JSString
Expand All @@ -88,16 +88,25 @@ decimalW64 (W64# x) = js_decW64 x
{-# INLINE decimalW64 #-}

decimalW :: Word -> JSString
decimalW (W# x) = js_decW32 x
decimalW (W# x) = js_decW x
{-# INLINE decimalW #-}

-- hack warning, we should really expose J# somehow
data MyI = MyS Int# | MyJ Int# ByteArray#

decimalInteger :: Integer -> JSString
decimalInteger !i = js_decInteger (unsafeCoerce i)
decimalInteger = \case
IS x -> js_decI x
IP x -> js_decBigNat True x
IN x -> js_decBigNat False x
{-# INLINE decimalInteger #-}

decimalNatural :: Natural -> JSString
decimalNatural = \case
NS x -> js_decW x
NB x -> js_decBigNat True x
{-# INLINE decimalNatural #-}

decimal' :: Integral a => a -> JSString
decimal' i = decimalInteger (toInteger i)
{-# NOINLINE decimal' #-}
Expand Down Expand Up @@ -130,7 +139,9 @@ hexadecimal i = hexadecimal' i
{-# RULES "hexadecimal/Word32" hexadecimal = hexW32 :: Word32 -> JSString #-}
{-# RULES "hexadecimal/Word64" hexadecimal = hexW64 :: Word64 -> JSString #-}
{-# RULES "hexadecimal/Integer" hexadecimal = hexInteger :: Integer -> JSString #-}
{-# RULES "hexadecimal/Natural" hexadecimal = hexNatural :: Natural -> JSString #-}
{-# SPECIALIZE hexadecimal :: Integer -> JSString #-}
{-# SPECIALIZE hexadecimal :: Natural -> JSString #-}
{-# SPECIALIZE hexadecimal :: Int -> JSString #-}
{-# SPECIALIZE hexadecimal :: Int8 -> JSString #-}
{-# SPECIALIZE hexadecimal :: Int16 -> JSString #-}
Expand All @@ -150,55 +161,48 @@ hexadecimal' i
{-# NOINLINE hexadecimal' #-}

hexInteger :: Integer -> JSString
hexInteger !i
| i < 0 = error hexErrMsg
| otherwise = js_hexInteger (unsafeCoerce i)
hexInteger = \case
IS x -> js_hexI x
IP x -> js_hexBigNat True x
IN x -> js_hexBigNat False x
{-# INLINE hexInteger #-}

hexNatural :: Natural -> JSString
hexNatural = \case
NS x -> js_hexW x
NB x -> js_hexBigNat True x
{-# INLINE hexNatural #-}

hexI :: Int -> JSString
hexI (I# x) = if isTrue# (x <# 0#)
then error hexErrMsg
else js_hexI x
hexI (I# x) = js_hexI x
{-# INLINE hexI #-}

hexI8 :: Int8 -> JSString
hexI8 (I8# x) =
if isTrue# (x <# 0#)
then error hexErrMsg
else js_hexI x
hexI8 (I8# x) = js_hexI (int8ToInt# x)
{-# INLINE hexI8 #-}

hexI16 :: Int16 -> JSString
hexI16 (I16# x) =
if isTrue# (x <# 0#)
then error hexErrMsg
else js_hexI x
hexI16 (I16# x) = js_hexI (int16ToInt# x)
{-# INLINE hexI16 #-}

hexI32 :: Int32 -> JSString
hexI32 (I32# x) =
if isTrue# (x <# 0#)
then error hexErrMsg
else js_hexI x
hexI32 (I32# x) = js_hexI (int32ToInt# x)
{-# INLINE hexI32 #-}

hexI64 :: Int64 -> JSString
hexI64 i@(I64# x) =
if i < 0
then error hexErrMsg
else js_hexI64 x
hexI64 i@(I64# x) = js_hexI64 x
{-# INLINE hexI64 #-}

hexW :: Word -> JSString
hexW (W# x) = js_hexW32 x
hexW (W# x) = js_hexW x
{-# INLINE hexW #-}

hexW8 :: Word8 -> JSString
hexW8 (W8# x) = js_hexW x
hexW8 (W8# x) = js_hexW (word8ToWord# x)
{-# INLINE hexW8 #-}

hexW16 :: Word16 -> JSString
hexW16 (W16# x) = js_hexW x
hexW16 (W16# x) = js_hexW (word16ToWord# x)
{-# INLINE hexW16 #-}

hexW32 :: Word32 -> JSString
Expand All @@ -215,50 +219,50 @@ hexErrMsg = "Data.JSString.Int.hexadecimal: applied to negative number"
-- ----------------------------------------------------------------------------

foreign import javascript unsafe
"''+$1"
"((x) => { return '' + x; })"
js_decI :: Int# -> JSString
foreign import javascript unsafe
"h$jsstringDecI64"
js_decI64 :: Int64# -> JSString
foreign import javascript unsafe
"''+$1"
"((x) => { return '' + x; })"
js_decW :: Word# -> JSString
foreign import javascript unsafe
"''+(($1>=0)?$1:($1+4294967296))"
js_decW32 :: Word# -> JSString
"((x) => { return '' + x; })"
js_decW32 :: Word32# -> JSString
foreign import javascript unsafe
"h$jsstringDecW64($1_1, $1_2)"
"h$jsstringDecW64"
js_decW64 :: Word64# -> JSString
foreign import javascript unsafe
"h$jsstringDecInteger($1)"
js_decInteger :: Any -> JSString
"h$jsstringDecBigNat"
js_decBigNat :: Bool -> ByteArray# -> JSString

-- these are expected to be only applied to nonnegative integers
foreign import javascript unsafe
"$1.toString(16)"
"((x) => { return x.toString(16); })"
js_hexI :: Int# -> JSString
foreign import javascript unsafe
"h$jsstringHexI64"
js_hexI64 :: Int64# -> JSString

foreign import javascript unsafe
"$1.toString(16)"
"((x) => { return x.toString(16); })"
js_hexW :: Word# -> JSString
foreign import javascript unsafe
"(($1>=0)?$1:($1+4294967296)).toString(16)"
js_hexW32 :: Word# -> JSString
"((x) => { return x.toString(16); })"
js_hexW32 :: Word32# -> JSString
foreign import javascript unsafe
"h$jsstringHexW64($1_1, $1_2)"
"h$jsstringHexW64"
js_hexW64 :: Word64# -> JSString
foreign import javascript unsafe
"h$jsstringHexInteger($1)"
js_hexInteger :: Any -> JSString
"h$jsstringHexBigNat"
js_hexBigNat :: Bool -> ByteArray# -> JSString

foreign import javascript unsafe
"'-'+$1+(-$2)"
"((x,y) => { return '-'+x+(-y); })"
js_minusDigit :: JSString -> Int# -> JSString
foreign import javascript unsafe
"'-'+$1"
"((x) => { return '-'+x; })"
js_minus :: JSString -> JSString

--
Expand Down
Loading
Loading