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
39import Control.Exception (assert)
40import Data.Binary (Binary(..), Get, getWord8, putWord8)
41import Data.Binary.Put (putBuilder)
42import Data.Binary.Get.Internal (readN)
43import qualified Data.ByteString.Internal as B
44import qualified Data.ByteString.Builder.Internal as B
45import qualified Data.List as List
46import Data.String (IsString(..))
47import qualified Data.Text as Text
48import qualified Data.Utf8 as Utf8
49import Foreign.ForeignPtr (ForeignPtr, touchForeignPtr)
50import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
51import Foreign.Ptr (minusPtr, plusPtr)
53 ( Int(I#), Ptr(Ptr), Char(C#)
55 , ByteArray#, MutableByteArray#
57 , newByteArray#, unsafeFreezeByteArray#
59 , writeCharArray#, writeWord8OffAddr#
60 , copyAddrToByteArray#, copyByteArrayToAddr#
63import GHC.ST (ST(ST), runST)
65import GHC.Word (Word8(W8#))
66import Prelude hiding (length, maybe, negate)
83 I# (sizeofByteArray# ba#)
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
106instance 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
126instance IsString Name where
130 do mba <- newByteArray (List.length str)
136writeChars :: MBA s -> Int -> [Char] -> ST s ()
137writeChars !mba !i chars =
143 do writeChar8 mba i c
144 writeChars mba (i+1) cs
151instance Binary Name where
152 put name@(Name ba#) =
153 putWord8 (W8# (int2Word# (sizeofByteArray# ba#)))
154 >> putBuilder (toBuilder name)
159{-# INLINE getName #-}
160getName :: Word8 -> Get Name
162 let !n = fromIntegral w in
163 readN n (copyFromByteString n)
166{-# INLINE copyFromByteString #-}
167copyFromByteString :: Int -> B.ByteString -> Name
168copyFromByteString len (B.PS fptr offset _) =
169 unsafeDupablePerformIO
171 do mba <- stToIO (newByteArray len)
172 stToIO (copyFromPtr (unsafeForeignPtrToPtr fptr `plusPtr` offset) mba 0 len)
174 stToIO (unsafeFreeze mba)
182fromByteString :: ForeignPtr Word8 -> Int -> Int -> Name
183fromByteString fptr offset len =
184 unsafeDupablePerformIO
186 do mba <- stToIO (newByteArray len)
187 stToIO (copyFromPtr (unsafeForeignPtrToPtr fptr `plusPtr` offset) mba 0 len)
189 stToIO (unsafeFreeze mba)
198toUtf8 :: Name -> Utf8.Utf8
207{-# INLINE toBuilder #-}
208toBuilder :: Name -> B.Builder
210 \name -> B.builder (toBuilderHelp name)
213{-# INLINE toBuilderHelp #-}
214toBuilderHelp :: Name -> B.BuildStep a -> B.BuildStep a
215toBuilderHelp !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)
237{-# INLINE toEscapedBuilder #-}
238toEscapedBuilder :: Word8 -> Word8 -> Name -> B.Builder
239toEscapedBuilder before after =
240 \name -> B.builder (toEscapedBuilderHelp before after name)
243{-# INLINE toEscapedBuilderHelp #-}
244toEscapedBuilderHelp :: Word8 -> Word8 -> Name -> B.BuildStep a -> B.BuildStep a
245toEscapedBuilderHelp 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)
266escape :: Word8 -> Word8 -> Ptr a -> Name -> Int -> Int -> ST RealWorld ()
267escape 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
284toString :: Name -> String
286 Utf8.toString (toUtf8 name)
293hasDot :: Name -> Bool
296 !len# = sizeofByteArray# ba#
298 hasDotHelp ba# 0# len#
301hasDotHelp :: ByteArray# -> Int# -> Int# -> Bool
302hasDotHelp ba# !offset# end# =
303 if isTrue# (offset# <# end#) then
304 if isTrue# (eqWord# 0x2E## {- . -} (indexWord8Array# ba# offset#))
306 else hasDotHelp ba# (offset# +# 1#) end#
316toText :: Name -> Text.Text
318 Text.pack (toString name) -- TODO get rid of this?
325getKernel :: Name -> Name
326getKernel 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 #-}
350startsWith :: Name -> Name -> Bool
351startsWith (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#)
361isKernel :: Name -> Bool
362isKernel = startsWith prefix_kernel
364isNumberType :: Name -> Bool
365isNumberType = startsWith prefix_number
367isComparableType :: Name -> Bool
368isComparableType = startsWith prefix_comparable
370isAppendableType :: Name -> Bool
371isAppendableType = startsWith prefix_appendable
373isCompappendType :: Name -> Bool
374isCompappendType = startsWith prefix_compappend
376{-# NOINLINE prefix_kernel #-}
378prefix_kernel = "Elm.Kernel."
380{-# NOINLINE prefix_number #-}
382prefix_number = "number"
384{-# NOINLINE prefix_comparable #-}
385prefix_comparable :: Name
386prefix_comparable = "comparable"
388{-# NOINLINE prefix_appendable #-}
389prefix_appendable :: Name
390prefix_appendable = "appendable"
392{-# NOINLINE prefix_compappend #-}
393prefix_compappend :: Name
394prefix_compappend = "compappend"
401fromVarIndex :: 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 #-}
415getIndexSize :: Int -> Int
419 | True = 2 + ceiling (logBase 10 (fromIntegral n + 1) :: Float)
423writeNumbers :: MBA s -> Int -> Int -> ST s ()
424writeNumbers !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
432fromTypeVariable :: Name -> Int -> Name
433fromTypeVariable 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
462fromTypeVariableScheme :: Int -> Name
463fromTypeVariableScheme 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
484fromManyNames :: [Name] -> Name
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# #)
501writeNames :: MutableByteArray# s -> Int# -> [Name] -> State# s -> State# s
502writeNames 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
524fromWords :: [Word8] -> Name
528 do mba <- newByteArray (List.length words)
529 writeWords mba 0 words
534writeWords :: MBA s -> Int -> [Word8] -> ST s ()
535writeWords !mba !i words =
541 do writeWord8 mba i w
542 writeWords mba (i+1) ws
549sepBy :: Word8 -> Name -> Name -> Name
550sepBy (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 #-}
580newByteArray :: Int -> ST s (MBA s)
581newByteArray (I# len#) =
583 case newByteArray# len# s of
584 (# s, mba# #) -> (# s, MBA# mba# #)
587{-# INLINE unsafeFreeze #-}
588unsafeFreeze :: MBA s -> ST s Name
589unsafeFreeze (MBA# mba#) =
591 case unsafeFreezeByteArray# mba# s of
592 (# s, ba# #) -> (# s, Name ba# #)
595{-# INLINE writeChar8 #-}
596writeChar8 :: MBA s -> Int -> Char -> ST s ()
597writeChar8 (MBA# mba#) (I# offset#) (C# char#) =
599 case writeCharArray# mba# offset# char# s of
603{-# INLINE writeWord8 #-}
604writeWord8 :: MBA s -> Int -> Word8 -> ST s ()
605writeWord8 (MBA# mba#) (I# offset#) (W8# w#) =
607 case writeWord8Array# mba# offset# w# s of
611{-# INLINE writeWordToPtr #-}
612writeWordToPtr :: Ptr a -> Int -> Word8 -> ST s ()
613writeWordToPtr (Ptr addr#) (I# offset#) (W8# word#) =
615 case writeWord8OffAddr# addr# offset# word# s of
619{-# INLINE copyFromPtr #-}
620copyFromPtr :: Ptr a -> MBA RealWorld -> Int -> Int -> ST RealWorld ()
621copyFromPtr (Ptr addr#) (MBA# mba#) (I# offset#) (I# len#) =
623 case copyAddrToByteArray# addr# mba# offset# len# s of
627{-# INLINE copyToPtr #-}
628copyToPtr :: Name -> Int -> Ptr a -> Int -> ST RealWorld ()
629copyToPtr (Name ba#) (I# offset#) (Ptr addr#) (I# len#) =
631 case copyByteArrayToAddr# ba# offset# addr# len# s of
635{-# INLINE copyToMBA #-}
636copyToMBA :: Name -> MBA s -> ST s ()
637copyToMBA (Name ba#) (MBA# mba#) =
639 case copyByteArray# ba# 0# mba# 0# (sizeofByteArray# ba#) s of
652{-# NOINLINE float #-}
667{-# NOINLINE string #-}
672{-# NOINLINE maybe #-}
677{-# NOINLINE result #-}
687{-# NOINLINE array #-}
697{-# NOINLINE tuple #-}
702{-# NOINLINE jsArray #-}
712{-# NOINLINE router #-}
727{-# NOINLINE platform #-}
732{-# NOINLINE virtualDom #-}
734virtualDom = "VirtualDom"
737{-# NOINLINE shader #-}
742{-# NOINLINE debug #-}
747{-# NOINLINE debugger #-}
752{-# NOINLINE bitwise #-}
757{-# NOINLINE basics #-}
762{-# NOINLINE utils #-}
767{-# NOINLINE negate #-}
777{-# NOINLINE false #-}
782{-# NOINLINE value #-}
792{-# NOINLINE program #-}
802{-# NOINLINE dollar #-}
807{-# NOINLINE identity #-}
812{-# NOINLINE replModule #-}
814replModule = "Elm_Repl"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list