mirror of
https://github.com/gren-lang/compiler.git
synced 2024-08-16 12:00:22 +03:00
First attempt at implementing VLQ encoding, fails for large negative numbers when Int > 32 bits.
This commit is contained in:
parent
56dc275d6f
commit
5f9c114b4b
@ -2,6 +2,55 @@ module Generate.VLQ
|
||||
( encode
|
||||
) where
|
||||
|
||||
import Data.Bits ((.|.), (.&.))
|
||||
import Data.Bits qualified as Bit
|
||||
import Data.List qualified as List
|
||||
import Data.Map (Map, (!))
|
||||
import Data.Map qualified as Map
|
||||
import Data.Function ((&))
|
||||
import Data.Foldable.WithIndex (ifoldr)
|
||||
|
||||
|
||||
{- Ported from the Elm package Janiczek/elm-vlq
|
||||
-}
|
||||
|
||||
encode :: Int -> String
|
||||
encode _num =
|
||||
""
|
||||
encode num =
|
||||
let
|
||||
numWithSign =
|
||||
if num < 0
|
||||
then (negate num `Bit.shiftL` 1) .|. 1
|
||||
else num `Bit.shiftL` 1
|
||||
in
|
||||
encodeHelp numWithSign ""
|
||||
|
||||
encodeHelp :: Int -> String -> String
|
||||
encodeHelp num acc =
|
||||
let
|
||||
clamped =
|
||||
num .&. 31
|
||||
|
||||
newNum =
|
||||
num `Bit.shiftR` 5
|
||||
|
||||
newClamped =
|
||||
if newNum > 0 then
|
||||
clamped .|. 32
|
||||
|
||||
else
|
||||
clamped
|
||||
|
||||
newAcc =
|
||||
base64Table ! newClamped : acc
|
||||
in
|
||||
if newNum > 0 then
|
||||
encodeHelp newNum newAcc
|
||||
|
||||
else
|
||||
List.reverse newAcc
|
||||
|
||||
|
||||
base64Table :: Map Int Char
|
||||
base64Table =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='"
|
||||
& ifoldr Map.insert Map.empty
|
||||
|
@ -225,7 +225,8 @@ Common gren-common
|
||||
utf8-string,
|
||||
vector,
|
||||
text >= 2 && < 3,
|
||||
base64-bytestring >= 1.2 && < 2
|
||||
base64-bytestring >= 1.2 && < 2,
|
||||
indexed-traversable
|
||||
|
||||
Executable gren
|
||||
Import:
|
||||
|
@ -16,4 +16,4 @@ spec = do
|
||||
encode 123456789 `shouldBe` "qxmvrH"
|
||||
-- limits:
|
||||
encode (-2147483648) `shouldBe` "B"
|
||||
encode 2147483647 `shouldBe` "+/////D"
|
||||
encode 2147483647 `shouldBe` "+/////D"
|
||||
|
Loading…
Reference in New Issue
Block a user