@@ -0,0 +1,814 @@
1+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
2+{-# LANGUAGE BangPatterns, MagicHash, OverloadedStrings, UnboxedTuples #-}
25+ , fromTypeVariableScheme
28+ , int, float, bool, char, string
29+ , maybe, result, list, array, dict, tuple, jsArray
30+ , task, router, cmd, sub, platform, virtualDom
31+ , shader, debug, debugger, bitwise, basics
32+ , utils, negate, true, false, value
33+ , node, program, main, dollar, identity
39+import Control.Exception (assert)
40+import Data.Binary (Binary(..), Get, getWord8, putWord8)
41+import Data.Binary.Put (putBuilder)
42+import Data.Binary.Get.Internal (readN)
43+import qualified Data.ByteString.Internal as B
44+import qualified Data.ByteString.Builder.Internal as B
45+import qualified Data.List as List
46+import Data.String (IsString(..))
47+import qualified Data.Text as Text
48+import qualified Data.Utf8 as Utf8
49+import Foreign.ForeignPtr (ForeignPtr, touchForeignPtr)
50+import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
51+import Foreign.Ptr (minusPtr, plusPtr)
53+ ( Int(I#), Ptr(Ptr), Char(C#)
55+ , ByteArray#, MutableByteArray#
57+ , newByteArray#, unsafeFreezeByteArray#
59+ , writeCharArray#, writeWord8OffAddr#
60+ , copyAddrToByteArray#, copyByteArrayToAddr#
63+import GHC.ST (ST(ST), runST)
65+import GHC.Word (Word8(W8#))
66+import Prelude hiding (length, maybe, negate)
83+ I# (sizeofByteArray# ba#)
90+instance Eq Name where
91+ (==) (Name ba1#) (Name ba2#) =
93+ !len1# = sizeofByteArray# ba1#
94+ !len2# = sizeofByteArray# ba2#
96+ isTrue# (len1# ==# len2#)
98+ isTrue# (0# ==# compareByteArrays# ba1# 0# ba2# 0# len1#)
105+-- TODO see if this can be written any faster
106+instance Ord Name where
107+ compare (Name ba1#) (Name ba2#) =
109+ !len1# = sizeofByteArray# ba1#
110+ !len2# = sizeofByteArray# ba2#
111+ !len# = if isTrue# (len1# <# len2#) then len1# else len2#
112+ !cmp# = compareByteArrays# ba1# 0# ba2# 0# len#
115+ _ | isTrue# (cmp# <# 0#) -> LT
116+ | isTrue# (cmp# ># 0#) -> GT
117+ | isTrue# (len1# <# len2#) -> LT
118+ | isTrue# (len1# ># len2#) -> GT
123+-- STRING OVERLOADING
126+instance IsString Name where
130+ do mba <- newByteArray (List.length str)
131+ writeChars mba 0 str
136+writeChars :: MBA s -> Int -> [Char] -> ST s ()
137+writeChars !mba !i chars =
143+ do writeChar8 mba i c
144+ writeChars mba (i+1) cs
151+instance Binary Name where
152+ put name@(Name ba#) =
153+ putWord8 (W8# (int2Word# (sizeofByteArray# ba#)))
154+ >> putBuilder (toBuilder name)
156+ getWord8 >>= getName
159+{-# INLINE getName #-}
160+getName :: Word8 -> Get Name
162+ let !n = fromIntegral w in
163+ readN n (copyFromByteString n)
166+{-# INLINE copyFromByteString #-}
167+copyFromByteString :: Int -> B.ByteString -> Name
168+copyFromByteString len (B.PS fptr offset _) =
169+ unsafeDupablePerformIO
171+ do mba <- stToIO (newByteArray len)
172+ stToIO (copyFromPtr (unsafeForeignPtrToPtr fptr `plusPtr` offset) mba 0 len)
173+ touchForeignPtr fptr
174+ stToIO (unsafeFreeze mba)
182+fromByteString :: ForeignPtr Word8 -> Int -> Int -> Name
183+fromByteString fptr offset len =
184+ unsafeDupablePerformIO
186+ do mba <- stToIO (newByteArray len)
187+ stToIO (copyFromPtr (unsafeForeignPtrToPtr fptr `plusPtr` offset) mba 0 len)
188+ touchForeignPtr fptr
189+ stToIO (unsafeFreeze mba)
197+{-# INLINE toUtf8 #-}
198+toUtf8 :: Name -> Utf8.Utf8
207+{-# INLINE toBuilder #-}
208+toBuilder :: Name -> B.Builder
210+ \name -> B.builder (toBuilderHelp name)
213+{-# INLINE toBuilderHelp #-}
214+toBuilderHelp :: Name -> B.BuildStep a -> B.BuildStep a
215+toBuilderHelp !name@(Name ba#) k =
216+ go 0 (I# (sizeofByteArray# ba#))
218+ go !offset !end !(B.BufferRange bOffset bEnd) =
220+ !bLen = minusPtr bEnd bOffset
224+ do stToIO (copyToPtr name offset bOffset len)
225+ let !newBufferRange = B.BufferRange (plusPtr bOffset len) bEnd
228+ do stToIO (copyToPtr name offset bOffset bLen)
229+ let !newOffset = offset + bLen
230+ return $ B.bufferFull 1 bEnd (go newOffset end)
234+-- TO ESCAPED BUILDER
237+{-# INLINE toEscapedBuilder #-}
238+toEscapedBuilder :: Word8 -> Word8 -> Name -> B.Builder
239+toEscapedBuilder before after =
240+ \name -> B.builder (toEscapedBuilderHelp before after name)
243+{-# INLINE toEscapedBuilderHelp #-}
244+toEscapedBuilderHelp :: Word8 -> Word8 -> Name -> B.BuildStep a -> B.BuildStep a
245+toEscapedBuilderHelp before after !name@(Name ba#) k =
246+ go 0 (I# (sizeofByteArray# ba#))
248+ go !offset !len !(B.BufferRange bOffset bEnd) =
250+ !bLen = minusPtr bEnd bOffset
253+ do -- TODO test if writing word-by-word is faster
254+ stToIO (copyToPtr name offset bOffset len)
255+ stToIO (escape before after bOffset name offset len)
256+ let !newBufferRange = B.BufferRange (plusPtr bOffset len) bEnd
259+ do stToIO (copyToPtr name offset bOffset bLen)
260+ stToIO (escape before after bOffset name offset bLen)
261+ let !newOffset = offset + bLen
262+ let !newLength = len - bLen
263+ return $ B.bufferFull 1 bEnd (go newOffset newLength)
266+escape :: Word8 -> Word8 -> Ptr a -> Name -> Int -> Int -> ST RealWorld ()
267+escape before@(W8# before#) after ptr name@(Name ba#) offset@(I# offset#) end@(I# end#) =
268+ if isTrue# (offset# <# end#) then
269+ if isTrue# (eqWord# before# (indexWord8Array# ba# offset#))
271+ do writeWordToPtr ptr offset after
272+ escape before after ptr name (offset + 1) end
274+ do escape before after ptr name (offset + 1) end
284+toString :: Name -> String
286+ Utf8.toString (toUtf8 name)
293+hasDot :: Name -> Bool
296+ !len# = sizeofByteArray# ba#
298+ hasDotHelp ba# 0# len#
301+hasDotHelp :: ByteArray# -> Int# -> Int# -> Bool
302+hasDotHelp ba# !offset# end# =
303+ if isTrue# (offset# <# end#) then
304+ if isTrue# (eqWord# 0x2E## {- . -} (indexWord8Array# ba# offset#))
306+ else hasDotHelp ba# (offset# +# 1#) end#
316+toText :: Name -> Text.Text
318+ Text.pack (toString name) -- TODO get rid of this?
325+getKernel :: Name -> Name
326+getKernel name@(Name ba#) =
327+ assert (isKernel name)
332+ !size# = sizeofByteArray# ba# -# 11#
335+ case newByteArray# size# s of
337+ case copyByteArray# ba# 11# mba# 0# size# s of
339+ case unsafeFreezeByteArray# mba# s of
340+ (# s, ba# #) -> (# s, Name ba# #)
349+{-# INLINE startsWith #-}
350+startsWith :: Name -> Name -> Bool
351+startsWith (Name ba1#) (Name ba2#) =
353+ !len1# = sizeofByteArray# ba1#
354+ !len2# = sizeofByteArray# ba2#
356+ isTrue# (len1# <=# len2#)
358+ isTrue# (0# ==# compareByteArrays# ba1# 0# ba2# 0# len1#)
361+isKernel :: Name -> Bool
362+isKernel = startsWith prefix_kernel
364+isNumberType :: Name -> Bool
365+isNumberType = startsWith prefix_number
367+isComparableType :: Name -> Bool
368+isComparableType = startsWith prefix_comparable
370+isAppendableType :: Name -> Bool
371+isAppendableType = startsWith prefix_appendable
373+isCompappendType :: Name -> Bool
374+isCompappendType = startsWith prefix_compappend
376+{-# NOINLINE prefix_kernel #-}
377+prefix_kernel :: Name
378+prefix_kernel = "Elm.Kernel."
380+{-# NOINLINE prefix_number #-}
381+prefix_number :: Name
382+prefix_number = "number"
384+{-# NOINLINE prefix_comparable #-}
385+prefix_comparable :: Name
386+prefix_comparable = "comparable"
388+{-# NOINLINE prefix_appendable #-}
389+prefix_appendable :: Name
390+prefix_appendable = "appendable"
392+{-# NOINLINE prefix_compappend #-}
393+prefix_compappend :: Name
394+prefix_compappend = "compappend"
401+fromVarIndex :: Int -> Name
405+ do let !size = getIndexSize n
406+ mba <- newByteArray size
407+ writeWord8 mba 0 0x5F {- _ -}
408+ writeWord8 mba 1 0x76 {- v -}
409+ writeNumbers mba (size - 1) n
414+{-# INLINE getIndexSize #-}
415+getIndexSize :: Int -> Int
419+ | True = 2 + ceiling (logBase 10 (fromIntegral n + 1) :: Float)
423+writeNumbers :: MBA s -> Int -> Int -> ST s ()
424+writeNumbers !mba !offset !n =
425+ do let (q,r) = quotRem n 10
426+ writeWord8 mba offset (0x30 + fromIntegral r)
429+ else writeNumbers mba (offset-1) q
432+fromTypeVariable :: Name -> Int -> Name
433+fromTypeVariable name@(Name ba#) index =
438+ len# = sizeofByteArray# ba#
439+ end# = indexWord8Array# ba# (len# -# 1#)
441+ if isTrue# (leWord# 0x30## end#) && isTrue# (leWord# end# 0x39##) then
444+ do let !size = length name + 1 + getIndexSize index
445+ mba <- newByteArray size
447+ writeWord8 mba (I# len#) 0x5F {- _ -}
448+ writeNumbers mba (size - 1) index
454+ do let !size = length name + getIndexSize index
455+ mba <- newByteArray size
457+ writeNumbers mba (size - 1) index
462+fromTypeVariableScheme :: Int -> Name
463+fromTypeVariableScheme scheme =
467+ do mba <- newByteArray 1
468+ writeWord8 mba 0 (0x61 + fromIntegral scheme)
471+ do let (extra, letter) = quotRem scheme 26
472+ let !size = getIndexSize extra
473+ mba <- newByteArray size
474+ writeWord8 mba 0 (0x61 + fromIntegral letter)
475+ writeNumbers mba (size - 1) extra
484+fromManyNames :: [Name] -> Name
485+fromManyNames names =
487+ !(I# size#) = sum (map (\(Name ba#) -> I# (sizeofByteArray# ba# +# 1#)) names)
492+ case newByteArray# size# s of
494+ case writeNames mba# 0# names s of
496+ case unsafeFreezeByteArray# mba# s of
497+ (# s, ba# #) -> (# s, Name ba# #)
501+writeNames :: MutableByteArray# s -> Int# -> [Name] -> State# s -> State# s
502+writeNames mba# !offset# names s =
507+ (Name ba#) : names ->
508+ case writeWord8Array# mba# offset# 0x24## {- $ -} s of
511+ !offset1# = offset# +# 1#
512+ !len# = sizeofByteArray# ba#
513+ !newOffset# = offset1# +# len#
515+ case copyByteArray# ba# 0# mba# offset1# len# s of
517+ writeNames mba# newOffset# names s
524+fromWords :: [Word8] -> Name
528+ do mba <- newByteArray (List.length words)
529+ writeWords mba 0 words
534+writeWords :: MBA s -> Int -> [Word8] -> ST s ()
535+writeWords !mba !i words =
541+ do writeWord8 mba i w
542+ writeWords mba (i+1) ws
549+sepBy :: Word8 -> Name -> Name -> Name
550+sepBy (W8# sep#) (Name ba1#) (Name ba2#) =
552+ !len1# = sizeofByteArray# ba1#
553+ !len2# = sizeofByteArray# ba2#
558+ case newByteArray# (len1# +# len2# +# 1#) s of
560+ case copyByteArray# ba1# 0# mba# 0# len1# s of
562+ case writeWord8Array# mba# len1# sep# s of
564+ case copyByteArray# ba2# 0# mba# (len1# +# 1#) len2# s of
566+ case unsafeFreezeByteArray# mba# s of
567+ (# s, ba# #) -> (# s, Name ba# #)
576+ MBA# (MutableByteArray# s)
579+{-# INLINE newByteArray #-}
580+newByteArray :: Int -> ST s (MBA s)
581+newByteArray (I# len#) =
583+ case newByteArray# len# s of
584+ (# s, mba# #) -> (# s, MBA# mba# #)
587+{-# INLINE unsafeFreeze #-}
588+unsafeFreeze :: MBA s -> ST s Name
589+unsafeFreeze (MBA# mba#) =
591+ case unsafeFreezeByteArray# mba# s of
592+ (# s, ba# #) -> (# s, Name ba# #)
595+{-# INLINE writeChar8 #-}
596+writeChar8 :: MBA s -> Int -> Char -> ST s ()
597+writeChar8 (MBA# mba#) (I# offset#) (C# char#) =
599+ case writeCharArray# mba# offset# char# s of
603+{-# INLINE writeWord8 #-}
604+writeWord8 :: MBA s -> Int -> Word8 -> ST s ()
605+writeWord8 (MBA# mba#) (I# offset#) (W8# w#) =
607+ case writeWord8Array# mba# offset# w# s of
611+{-# INLINE writeWordToPtr #-}
612+writeWordToPtr :: Ptr a -> Int -> Word8 -> ST s ()
613+writeWordToPtr (Ptr addr#) (I# offset#) (W8# word#) =
615+ case writeWord8OffAddr# addr# offset# word# s of
619+{-# INLINE copyFromPtr #-}
620+copyFromPtr :: Ptr a -> MBA RealWorld -> Int -> Int -> ST RealWorld ()
621+copyFromPtr (Ptr addr#) (MBA# mba#) (I# offset#) (I# len#) =
623+ case copyAddrToByteArray# addr# mba# offset# len# s of
627+{-# INLINE copyToPtr #-}
628+copyToPtr :: Name -> Int -> Ptr a -> Int -> ST RealWorld ()
629+copyToPtr (Name ba#) (I# offset#) (Ptr addr#) (I# len#) =
631+ case copyByteArrayToAddr# ba# offset# addr# len# s of
635+{-# INLINE copyToMBA #-}
636+copyToMBA :: Name -> MBA s -> ST s ()
637+copyToMBA (Name ba#) (MBA# mba#) =
639+ case copyByteArray# ba# 0# mba# 0# (sizeofByteArray# ba#) s of
652+{-# NOINLINE float #-}
657+{-# NOINLINE bool #-}
662+{-# NOINLINE char #-}
667+{-# NOINLINE string #-}
672+{-# NOINLINE maybe #-}
677+{-# NOINLINE result #-}
682+{-# NOINLINE list #-}
687+{-# NOINLINE array #-}
692+{-# NOINLINE dict #-}
697+{-# NOINLINE tuple #-}
702+{-# NOINLINE jsArray #-}
707+{-# NOINLINE task #-}
712+{-# NOINLINE router #-}
727+{-# NOINLINE platform #-}
729+platform = "Platform"
732+{-# NOINLINE virtualDom #-}
734+virtualDom = "VirtualDom"
737+{-# NOINLINE shader #-}
742+{-# NOINLINE debug #-}
747+{-# NOINLINE debugger #-}
749+debugger = "Debugger"
752+{-# NOINLINE bitwise #-}
757+{-# NOINLINE basics #-}
762+{-# NOINLINE utils #-}
767+{-# NOINLINE negate #-}
772+{-# NOINLINE true #-}
777+{-# NOINLINE false #-}
782+{-# NOINLINE value #-}
787+{-# NOINLINE node #-}
792+{-# NOINLINE program #-}
797+{-# NOINLINE main #-}
802+{-# NOINLINE dollar #-}
807+{-# NOINLINE identity #-}
809+identity = "identity"
812+{-# NOINLINE replModule #-}
814+replModule = "Elm_Repl"