on master help sign in
start using D.customString in Elm.ModuleName
ba74f3bEvan Czaplicki
compiler/src/Elm/ModuleName.hs+63−32
@@ -1,13 +1,13 @@
1−{-# LANGUAGE OverloadedStrings #-}
1+{-# LANGUAGE BangPatterns, OverloadedStrings, UnboxedTuples #-}
2module Elm.ModuleName
2module Elm.ModuleName
3 ( Raw
3 ( Raw
4 , toChars
4 , toChars
5− , toString
6 , toFilePath
5 , toFilePath
7 , toHyphenPath
6 , toHyphenPath
8− , fromHyphenPath
7+ --
9 , encode
8 , encode
10 , decoder
9 , decoder
10+ --
11 , Canonical(..)
11 , Canonical(..)
12 , basics, char, string
12 , basics, char, string
13 , maybe, result, list, array, dict, tuple
13 , maybe, result, list, array, dict, tuple
@@ -25,12 +25,17 @@ import Data.Binary (Binary(..))
25import qualified Data.Char as Char
25import qualified Data.Char as Char
26import qualified Data.Name as Name
26import qualified Data.Name as Name
27import qualified Data.Utf8 as Utf8
27import qualified Data.Utf8 as Utf8
28+import Data.Word (Word8)
29+import Foreign.Ptr (Ptr, plusPtr, minusPtr)
28import Prelude hiding (maybe)
30import Prelude hiding (maybe)
29import qualified System.FilePath as FP
31import qualified System.FilePath as FP
30
32
31import qualified Elm.Package as Pkg
33import qualified Elm.Package as Pkg
32−import qualified Json.Decode as Decode
34+import qualified Json.Decode as D
33−import qualified Json.Encode as Encode
35+import qualified Json.Encode as E
36+import qualified Parse.Variable as Var
37+import qualified Parse.Primitives as P
38+import Parse.Primitives (Row, Col)
34
39
35
40
36
41
@@ -45,11 +50,6 @@ toChars =
45 Name.toChars
50 Name.toChars
46
51
47
52
48−toString :: Raw -> Utf8.String
49−toString =
50− Name.toUtf8
51−
52−
53toFilePath :: Raw -> FilePath
53toFilePath :: Raw -> FilePath
54toFilePath name =
54toFilePath name =
55 map (\c -> if c == '.' then FP.pathSeparator else c) (Name.toChars name)
55 map (\c -> if c == '.' then FP.pathSeparator else c) (Name.toChars name)
@@ -60,38 +60,68 @@ toHyphenPath name =
60 map (\c -> if c == '.' then '-' else c) (Name.toChars name)
60 map (\c -> if c == '.' then '-' else c) (Name.toChars name)
61
61
62
62
63−fromHyphenPath :: Utf8.String -> Maybe Raw
64−fromHyphenPath str =
65− let
66− chunks =
67− Utf8.split 0x2D {- - -} str
68− in
69− if all isGoodChunk chunks
70− then Just (Name.fromUtf8 (Utf8.join 0x2E {- . -} chunks))
71− else Nothing
72−
73−
74
63
75-- JSON
64-- JSON
76
65
77
66
78−encode :: Raw -> Encode.Value
67+encode :: Raw -> E.Value
79encode =
68encode =
80− Encode.name
69+ E.name
81
70
82
71
83−decoder :: Decode.Decoder Utf8.String Raw
72+decoder :: D.Decoder (Row, Col) Raw
84decoder =
73decoder =
85− do str <- Decode.string
74+ D.customString parser (,)
86− if all isGoodChunk (Utf8.split 0x2E {- . -} str)
75+
87− then return (Name.fromUtf8 str)
76+
88− else Decode.failure str
89
77
78+-- PARSER
90
79
91−isGoodChunk :: Utf8.String -> Bool
80+
92−isGoodChunk chunk =
81+parser :: P.Parser (Row, Col) Raw
93− Utf8.startsWithChar Char.isUpper chunk
82+parser =
94− && Utf8.all (\c -> Char.isAlphaNum c || c == '_') chunk
83+ P.Parser $ \(P.State src pos end indent row col) cok _ cerr eerr ->
84+ let
85+ (# isGood, newPos, newCol #) = chompStart pos end col
86+ in
87+ if isGood && minusPtr newPos pos < 256 then
88+ let !newState = P.State src newPos end indent row newCol in
89+ cok (Utf8.fromPtr pos newPos) newState
90+
91+ else if col == newCol then
92+ eerr row newCol (,)
93+
94+ else
95+ cerr row newCol (,)
96+
97+
98+chompStart :: Ptr Word8 -> Ptr Word8 -> Col -> (# Bool, Ptr Word8, Col #)
99+chompStart pos end col =
100+ let
101+ !width = Var.getUpperWidth pos end
102+ in
103+ if width == 0 then
104+ (# False, pos, col #)
105+ else
106+ chompInner (plusPtr pos width) end (col + 1)
107+
108+
109+chompInner :: Ptr Word8 -> Ptr Word8 -> Col -> (# Bool, Ptr Word8, Col #)
110+chompInner pos end col =
111+ if pos >= end then
112+ (# True, pos, col #)
113+ else
114+ let
115+ !word = P.unsafeIndex pos
116+ !width = Var.getInnerWidthHelp pos end word
117+ in
118+ if width == 0 then
119+ if word == 0x2E {-.-} then
120+ chompStart (plusPtr pos 1) end (col + 1)
121+ else
122+ (# True, pos, col #)
123+ else
124+ chompInner (plusPtr pos width) end (col + 1)
95
125
96
126
97
127
@@ -105,6 +135,7 @@ data Canonical =
105 }
135 }
106
136
107
137
138+
108-- INSTANCES
139-- INSTANCES
109
140
110
141