on f4401ac help sign in
elk/compiler/src/Elm/Version.hs
196 lines 3.9 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE BangPatterns, UnboxedTuples #-}
3module Elm.Version
4 ( Version(..)
5 , one
6 , max
7 , compiler
8 , bumpPatch
9 , bumpMinor
10 , bumpMajor
11 , toChars
12 --
13 , decoder
14 , encode
15 --
16 , parser
17 )
18 where
21import Prelude hiding (max)
22import Control.Monad (liftM3)
23import Data.Binary (Binary, get, put, getWord8, putWord8)
24import qualified Data.Version as Version
25import Data.Word (Word8, Word16)
26import Foreign.Ptr (Ptr, plusPtr, minusPtr)
27import qualified Paths_elm
29import qualified Json.Decode as D
30import qualified Json.Encode as E
31import qualified Parse.Primitives as P
32import Parse.Primitives (Row, Col)
36-- VERSION
39data Version =
40 Version
41 { _major :: {-# UNPACK #-} !Word16
42 , _minor :: {-# UNPACK #-} !Word16
43 , _patch :: {-# UNPACK #-} !Word16
44 }
45 deriving (Eq, Ord)
48one :: Version
49one =
50 Version 1 0 0
53max :: Version
54max =
55 Version maxBound 0 0
58compiler :: Version
59compiler =
60 case map fromIntegral (Version.versionBranch Paths_elm.version) of
61 major : minor : patch : _ ->
62 Version major minor patch
64 [major, minor] ->
65 Version major minor 0
67 [major] ->
68 Version major 0 0
70 [] ->
71 error "could not detect version of elm-compiler you are using"
75-- BUMP
78bumpPatch :: Version -> Version
79bumpPatch (Version major minor patch) =
80 Version major minor (patch + 1)
83bumpMinor :: Version -> Version
84bumpMinor (Version major minor _patch) =
85 Version major (minor + 1) 0
88bumpMajor :: Version -> Version
89bumpMajor (Version major _minor _patch) =
90 Version (major + 1) 0 0
94-- TO CHARS
97toChars :: Version -> [Char]
98toChars (Version major minor patch) =
99 show major ++ '.' : show minor ++ '.' : show patch
103-- JSON
106decoder :: D.Decoder (Row, Col) Version
107decoder =
108 D.customString parser (,)
111encode :: Version -> E.Value
112encode version =
113 E.chars (toChars version)
117-- BINARY
120instance Binary Version where
121 get =
122 do word <- getWord8
123 if word == 255
124 then liftM3 Version get get get
125 else
126 do minor <- getWord8
127 patch <- getWord8
128 return (Version (fromIntegral word) (fromIntegral minor) (fromIntegral patch))
130 put (Version major minor patch) =
131 if major < 255 && minor < 256 && patch < 256 then
132 do putWord8 (fromIntegral major)
133 putWord8 (fromIntegral minor)
134 putWord8 (fromIntegral patch)
135 else
136 do putWord8 255
137 put major
138 put minor
139 put patch
143-- PARSER
146parser :: P.Parser (Row, Col) Version
147parser =
148 do major <- numberParser
149 P.word1 0x2E {-.-} (,)
150 minor <- numberParser
151 P.word1 0x2E {-.-} (,)
152 patch <- numberParser
153 return (Version major minor patch)
156numberParser :: P.Parser (Row, Col) Word16
157numberParser =
158 P.Parser $ \(P.State src pos end indent row col) cok _ _ eerr ->
159 if pos >= end then
160 eerr row col (,)
161 else
162 let !word = P.unsafeIndex pos in
163 if word == 0x30 {-0-} then
165 let
166 !newState = P.State src (plusPtr pos 1) end indent row (col + 1)
167 in
168 cok 0 newState
170 else if isDigit word then
172 let
173 (# total, newPos #) = chompWord16 (plusPtr pos 1) end (fromIntegral (word - 0x30))
174 !newState = P.State src newPos end indent row (col + fromIntegral (minusPtr newPos pos))
175 in
176 cok total newState
178 else
179 eerr row col (,)
182chompWord16 :: Ptr Word8 -> Ptr Word8 -> Word16 -> (# Word16, Ptr Word8 #)
183chompWord16 pos end total =
184 if pos >= end then
185 (# total, pos #)
186 else
187 let !word = P.unsafeIndex pos in
188 if isDigit word then
189 chompWord16 (plusPtr pos 1) end (10 * total + fromIntegral (word - 0x30))
190 else
191 (# total, pos #)
194isDigit :: Word8 -> Bool
195isDigit word =
196 0x30 {-0-} <= word && word <= 0x39 {-9-}