on master help sign in
Properly handle enums in kernel code
commit01ff2a9ae6a4757e2289903c166155114405ec2f authorEvan Czaplicki <evancz@users.noreply.github.com> dateTue 23 May 2017, 13:40 (9 years ago) parent3dcae17
2 files changed+81−37
src/Parse/Kernel.hs+43−9 src/Parse/Primitives.hs+38−28
src/Parse/Kernel.hs+43−9
@@ -6,10 +6,14 @@ module Parse.Kernel
66 where
77
88
9+import qualified Data.ByteString as BS
10+import qualified Data.ByteString.Builder as BS
11+import qualified Data.ByteString.Lazy as LBS
912import qualified Data.Map as Map
1013import Data.Monoid ((<>))
1114import Data.Text (Text)
1215import qualified Data.Text as Text
16+import Data.Word (Word8)
1317
1418import qualified AST.Exposing as Exposing
1519import qualified AST.Kernel as Kernel
@@ -29,24 +33,54 @@ parser :: Parser Kernel.Info
2933parser =
3034 do imports <- Parse.kernelHeader
3135 let table = Map.unions (map importToTable imports)
32− chunks <- parserHelp table []
36+ chunks <- parserHelp table Map.empty []
3337 return (Kernel.Info (Map.elems table) chunks)
3438
3539
36−parserHelp :: Table -> [Kernel.Chunk] -> Parser [Kernel.Chunk]
37−parserHelp table chunks =
38− do chunk <- Parse.kernelChunk
39− case chunk of
40− Left js ->
41− return (Kernel.JS js : chunks)
40+type Enums =
41+ Map.Map Word8 (Map.Map Text BS.ByteString)
4242
43− Right (js, var) ->
43+
44+parserHelp :: Table -> Enums -> [Kernel.Chunk] -> Parser [Kernel.Chunk]
45+parserHelp table enums chunks =
46+ do (javascript, maybeMore) <- Parse.kernelChunk
47+ case maybeMore of
48+ Nothing ->
49+ return (Kernel.JS javascript : chunks)
50+
51+ Just (Parse.KernelImport, var) ->
4452 case Map.lookup var table of
4553 Nothing ->
4654 error $ show $ "could not find " <> var <> " when parsing kernel code"
4755
4856 Just (home, name) ->
49− parserHelp table (Kernel.Var home name : Kernel.JS js : chunks)
57+ parserHelp table enums (Kernel.Var home name : Kernel.JS javascript : chunks)
58+
59+ Just (Parse.KernelEnum n, var) ->
60+ let
61+ (bytes, newEnums) =
62+ lookupEnum n var enums
63+ in
64+ parserHelp table newEnums (Kernel.JS bytes : Kernel.JS javascript : chunks)
65+
66+
67+lookupEnum :: Word8 -> Text -> Enums -> (BS.ByteString, Enums)
68+lookupEnum word var allEnums =
69+ case Map.lookup word allEnums of
70+ Nothing ->
71+ ( "0", Map.insert word (Map.singleton var "0") allEnums )
72+
73+ Just enums ->
74+ case Map.lookup var enums of
75+ Just bytes ->
76+ ( bytes, allEnums )
77+
78+ Nothing ->
79+ let
80+ number =
81+ LBS.toStrict $ BS.toLazyByteString $ BS.word8Dec $ fromIntegral (Map.size enums)
82+ in
83+ ( number, Map.insert word (Map.insert var number enums) allEnums )
5084
5185
5286
src/Parse/Primitives.hs+38−28
@@ -15,7 +15,7 @@ module Parse.Primitives
1515 , string, character
1616 , digit, number
1717 , shaderSource, shaderFailure
18− , kernelChunk
18+ , kernelChunk, ChunkTag(..)
1919 )
2020 where
2121
@@ -36,7 +36,7 @@ import qualified Data.Text.Lazy as LT
3636import qualified Data.Text.Lazy.Builder as LB
3737import Data.Text.Internal.Encoding.Utf16 (chr2)
3838import Data.Text.Internal.Unsafe.Char (unsafeChr)
39−import GHC.Word (Word16(..))
39+import GHC.Word (Word8, Word16)
4040
4141import qualified AST.Helpers as Help (isSymbol)
4242import qualified AST.Literal as L
@@ -1029,7 +1029,7 @@ digit =
10291029 in
10301030 if isDigit word then
10311031 cok
1032− (fromIntegral (word - 0x0030))
1032+ (fromIntegral (word - 0x0030 {- 0 -}))
10331033 (State array (offset + 1) (length - 1) indent row (col + 1) ctx)
10341034 noError
10351035 else
@@ -1307,50 +1307,52 @@ eatShader array offset length row col =
13071307-- KERNEL CHOMP
13081308
13091309
1310−kernelChunk :: Parser (Either BS.ByteString (BS.ByteString, Text))
1310+data ChunkTag = KernelEnum Word8 | KernelImport
1311+
1312+
1313+kernelChunk :: Parser (BS.ByteString, Maybe (ChunkTag, Text))
13111314kernelChunk =
13121315 Parser $ \(State array offset length indent row col ctx) cok _ _ _ ->
13131316 let
1314− (# isAtUnderscores, newOffset, newLength, newRow, newCol #) =
1317+ (# maybeChunkTag, newOffset, newLength, newRow, newCol #) =
13151318 kernelChunkHelp array offset length row col
13161319
13171320 javascript =
13181321 Text.encodeUtf8 (Text.Text array offset (newOffset - offset))
13191322 in
1320− if not isAtUnderscores then
1321−
1322− let
1323− !newState =
1324− State array newOffset newLength indent newRow newCol ctx
1325− in
1326− cok (Left javascript) newState noError
1327−
1328− else
1323+ case maybeChunkTag of
1324+ Nothing ->
1325+ let
1326+ !newState =
1327+ State array newOffset newLength indent newRow newCol ctx
1328+ in
1329+ cok (javascript, Nothing) newState noError
13291330
1330− let
1331− (# newerOffset, newerLength, newerCol #) =
1332− varPrimHelp array newOffset newLength newCol
1331+ Just tag ->
1332+ let
1333+ (# newerOffset, newerLength, newerCol #) =
1334+ varPrimHelp array newOffset newLength newCol
13331335
1334− !newState =
1335− State array newerOffset newerLength indent newRow newerCol ctx
1336+ !newState =
1337+ State array newerOffset newerLength indent newRow newerCol ctx
13361338
1337− !kernelSymbol =
1338− Text.Text array newOffset (newerOffset - newOffset)
1339− in
1340− cok (Right (javascript, kernelSymbol)) newState noError
1339+ !kernelSymbol =
1340+ Text.Text array newOffset (newerOffset - newOffset)
1341+ in
1342+ cok (javascript, Just (tag, kernelSymbol)) newState noError
13411343
13421344
1343−kernelChunkHelp :: Text.Array -> Int -> Int -> Int -> Int -> (# Bool, Int, Int, Int, Int #)
1345+kernelChunkHelp :: Text.Array -> Int -> Int -> Int -> Int -> (# Maybe ChunkTag, Int, Int, Int, Int #)
13441346kernelChunkHelp array offset length row col =
1345− if length < 2 then
1346− (# False, offset, length, row, col #)
1347+ if length == 0 then
1348+ (# Nothing, offset, length, row, col #)
13471349
13481350 else
13491351 let
13501352 !word = Text.unsafeIndex array offset
13511353 in
1352− if word == 0x005F {- _ -} && Text.unsafeIndex array (offset + 1) == 0x005F {- _ -} then
1353− (# True, offset, length, row, col #)
1354+ if word == 0x005F {- _ -} && length > 3 && Text.unsafeIndex array (offset + 1) == 0x005F {- _ -} then
1355+ (# Just (toChunkTag (Text.unsafeIndex array (offset + 2))), offset, length, row, col #)
13541356
13551357 else if word == 0x000A {- \n -} then
13561358 kernelChunkHelp array (offset + 1) (length - 1) (row + 1) 1
@@ -1360,3 +1362,11 @@ kernelChunkHelp array offset length row col =
13601362
13611363 else
13621364 kernelChunkHelp array (offset + 2) (length - 2) row (col + 1)
1365+
1366+
1367+toChunkTag :: Word16 -> ChunkTag
1368+toChunkTag word =
1369+ if isDigit word then
1370+ KernelEnum (fromIntegral (word - 0x0030 {- 0 -}))
1371+ else
1372+ KernelImport