Value.hs (3093B)
1 -- Canonical runtime value encodings. Keep demand behavior explicit. 2 module Runtime.Value where 3 4 import Runtime.Tree 5 import Data.Word (Word8) 6 import qualified Data.ByteString as BS 7 import qualified Data.IntMap.Strict as IM 8 9 -- | Encode a single byte (Word8) as a Tree Calculus number (0..255). 10 ofByte :: Word8 -> T 11 ofByte byte = byteTrees IM.! fromIntegral byte 12 13 -- Immutable canonical values: host byte buffers have only 256 possible 14 -- elements. Share their numeral trees rather than retaining a conversion 15 -- computation (and eventually a fresh bit spine) for every input byte. 16 -- Tree equality/encoding is unchanged; no pointer identity is exposed. 17 {-# NOINLINE byteTrees #-} 18 byteTrees :: IM.IntMap T 19 byteTrees = IM.fromDistinctAscList [(n, ofNumber (toInteger n)) | n <- [0..255]] 20 21 -- | Decode a Tree Calculus number as a single byte (Word8). 22 -- Rejects values outside the range 0..255. 23 toByte :: T -> Either String Word8 24 toByte t = case toNumber t of 25 Left err -> Left err 26 Right n 27 | n >= 0 && n <= 255 -> Right (fromIntegral n) 28 | otherwise -> Left ("Byte value out of range: " ++ show n) 29 30 -- | Encode a ByteString as a Tree Calculus list of Byte trees. 31 ofBytes :: BS.ByteString -> T 32 ofBytes = BS.foldr consByte Leaf 33 where 34 -- Force the bounded table lookup when the list cell is demanded, so an 35 -- unexamined body does not retain one lookup closure per byte. Input is 36 -- already a finite strict ByteString, not arbitrary language computations. 37 consByte byte rest = let value = ofByte byte in value `seq` Fork value rest 38 39 -- | Decode a Tree Calculus list of Byte trees as a ByteString. 40 -- Rejects non-list trees and elements that are not valid byte values (0..255). 41 toBytes :: T -> Either String BS.ByteString 42 toBytes t = case toList t of 43 Left err -> Left err 44 Right bs -> BS.pack <$> mapM toByte bs 45 46 -- Marshalling 47 ofString :: String -> T 48 ofString str = ofList $ map (ofNumber . toInteger . fromEnum) str 49 50 ofNumber :: Integer -> T 51 ofNumber 0 = Leaf 52 ofNumber n = 53 Fork 54 (if odd n then Stem Leaf else Leaf) 55 (ofNumber (n `div` 2)) 56 57 ofList :: [T] -> T 58 ofList = foldr Fork Leaf 59 60 toNumber :: T -> Either String Integer 61 toNumber Leaf = Right 0 62 toNumber (Fork Leaf rest) = case toNumber rest of 63 Right n -> Right (2 * n) 64 Left err -> Left err 65 toNumber (Fork (Stem Leaf) rest) = case toNumber rest of 66 Right n -> Right (1 + 2 * n) 67 Left err -> Left err 68 toNumber _ = Left "Invalid Tree Calculus number" 69 70 toChar :: Integer -> Either String Char 71 toChar n 72 | n < 0 = Left "Negative character code" 73 | n > 0x10FFFF = Left "Character code out of Unicode range" 74 | n >= 0xD800 && n <= 0xDFFF = Left "Surrogate character code not allowed" 75 | otherwise = Right (toEnum (fromInteger n)) 76 77 toString :: T -> Either String String 78 toString tc = do 79 list <- toList tc 80 nums <- mapM toNumber list 81 mapM toChar nums 82 83 toList :: T -> Either String [T] 84 toList Leaf = Right [] 85 toList (Fork x rest) = case toList rest of 86 Right xs -> Right (x : xs) 87 Left err -> Left err 88 toList _ = Left "Invalid Tree Calculus list" 89