Skip to content

Commit 34e095f

Browse files
committed
Classfile parser now sorta kinda works
1 parent 43c9245 commit 34e095f

File tree

5 files changed

+682
-340
lines changed

5 files changed

+682
-340
lines changed

src/Data/Prickler.hs

Lines changed: 148 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ import Control.Applicative
1313

1414
import Data.Maybe
1515
import Data.Monoid hiding (Sum, Product, All)
16-
import Data.Binary.Get hiding (Done)
16+
import Data.Binary.Get hiding (Done, Partial, skip)
17+
import qualified Data.Binary.Get as Get
1718
import Data.Binary.Builder
18-
import qualified Data.IntMap as IM
19+
import qualified Data.Map as M
1920
import Data.ByteString.Base16
2021
import qualified Data.ByteString.Lazy as BL
22+
import qualified Data.Vector.Generic as G
23+
import Control.Monad
2124

2225
import Data.Int
2326
import Data.Word
@@ -28,8 +31,8 @@ newtype K a b = K { unK :: a }
2831
data (:*:) f g x = f x :*: g x
2932
data Exists f = forall a. Exists { getValue :: f a }
3033

31-
newtype Flip r t = Flip { runFlip :: t -> r }
32-
newtype NFlip r ts = NFlip { runNFlip :: ts @-> r }
34+
newtype (:<-) r t = Flip { runFlip :: t -> r }
35+
newtype (:<-@) r ts = NFlip { runNFlip :: ts @-> r }
3336

3437
type family (@->) (ts :: [*]) (r :: *) :: *
3538
type instance '[] @-> r = r
@@ -55,23 +58,14 @@ mapAllF :: (forall a. f a -> b) -> All f ts -> [b]
5558
mapAllF f Nil = []
5659
mapAllF f (a :> as) = f a : mapAllF f as
5760

58-
foldlAll :: (a -> b -> a) -> a -> All (Flip b) ts -> (ts @-> a)
61+
foldlAll :: (a -> b -> a) -> a -> All ((:<-) b) ts -> (ts @-> a)
5962
foldlAll f z Nil = z
6063
foldlAll f z (Flip g :> gs) = \x -> foldlAll f (f z (g x)) gs
6164

6265
zipWithAll :: (forall a. f a -> g a -> h a) -> All f ts -> All g ts -> All h ts
6366
zipWithAll f Nil Nil = Nil
6467
zipWithAll f (x :> xs) (y :> ys) = f x y :> zipWithAll f xs ys
6568

66-
-- data Partial g b ts a = Partial { build :: g a, break :: ts @-> }
67-
-- incremental All? When building, we know the argument and can compute the rest, when reading, we know the value and can compute the rest
68-
69-
data Case f a ts = Case { cons :: ts @-> a, shape :: All f ts }
70-
data Data f g a = forall ts. Data { elim :: forall r. a -> EliminatorWrapper ts r, sum :: All (g (Case f a)) ts}
71-
72-
newtype EliminatorWrapper ts r = EliminatorWrapper { getEliminator :: Eliminator ts r }
73-
74-
7569
-- All glory to glguy
7670
apN :: Applicative f => f (ts @-> r) -> All f ts -> f r
7771
apN f Nil = f
@@ -80,14 +74,24 @@ apN f (x :> xs) = apN (f <*> x) xs
8074
liftAn :: Applicative f => (ts @-> r) -> All f ts -> f r
8175
liftAn = apN . pure
8276

83-
84-
merge :: All (NFlip r) ts -> Eliminator ts r -> r
77+
merge :: All ((:<-@) r) ts -> Eliminator ts r -> r
8578
merge Nil acc = acc
8679
merge (NFlip x :> xs) acc = merge xs (acc x)
8780

8881

89-
eliminate :: Monoid m => All (K m :*: All (Flip m)) ts -> EliminatorWrapper ts m -> m
90-
eliminate xs = merge (mapAll (\(K i :*: shape) -> NFlip (foldlAll (<>) i shape)) xs) . getEliminator
82+
-- incremental All? When building, we know the argument and can compute the rest, when reading, we know the value and can compute the rest
83+
84+
data Partial p g a ts = Partial { build :: !(g a), break :: !(ts @-> p), make :: !(ts @-> a) } -- forall xs. uncurryN make xs == runGet build . toLazyByteString $ uncurryN break xs
85+
86+
newtype EliminatorWrapper ts r = EliminatorWrapper { getEliminator :: Eliminator ts r }
87+
88+
alt :: (ts @-> a) -> All Prickler ts -> Partial Put Get a ts
89+
alt cons shape = Partial builder breaker cons
90+
where
91+
builder = liftAn cons (mapAll get shape)
92+
breaker = foldlAll (<>) mempty (mapAll (Flip . put) shape)
93+
94+
9195

9296

9397

@@ -98,14 +102,31 @@ eliminate xs = merge (mapAll (\(K i :*: shape) -> NFlip (foldlAll (<>) i shape))
98102

99103

100104

105+
data State a = State { written :: {-# UNPACK #-} !Int64, builder :: !Builder, contents :: a }
101106

107+
instance Functor State where
108+
fmap f (State w b v) = State w b (f v)
102109

110+
newtype PutM a = PutM { runPut :: Int64 -> State a }
103111

112+
instance Functor PutM where
113+
fmap f (PutM g) = PutM (fmap f . g)
104114

115+
instance Applicative PutM where
116+
pure x = PutM (\w -> State w mempty x)
117+
PutM f <*> PutM x = PutM $ \w -> case f w of State w1 b1 f' -> case x w1 of State w2 b2 x' -> State w2 (b1 <> b2) (f' x')
105118

119+
instance Monad PutM where
120+
return = pure
121+
PutM x >>= f = PutM (\w -> case x w of State w1 b1 x' -> case f x' of PutM f' -> case f' w1 of State w2 b2 x'' -> State w2 (b1 <> b2) x'')
106122

123+
type Put = PutM ()
107124

108-
data Prickler a = Prickler { get :: Get a, put :: a -> Builder } -- laws: get . put . get == get, put . get . put == put
125+
instance Monoid Put where
126+
mempty = pure ()
127+
mappend = (>>)
128+
129+
data Prickler a = Prickler { get :: Get a, put :: a -> Put } -- laws: get . put . get == get, put . get . put == put
109130

110131
expect :: Eq a => a -> Prickler a -> Prickler ()
111132
expect x (Prickler ga pa) = Prickler (do y <- ga; if x == y then return () else fail "Expectation failed") (const (pa x))
@@ -125,23 +146,121 @@ pair (Prickler ga pa) (Prickler gb pb) = Prickler (liftA2 (,) ga gb) (\(x, y) ->
125146
type Contiguous = (:$:)
126147
type Indexed i = (:*:) (K i)
127148

128-
contiguousData :: Integral i => Prickler i -> Data Prickler Contiguous a -> Prickler a
129-
contiguousData = undefined
130149

131-
taggedData :: Integral i => Prickler i -> Data Prickler (Indexed i) a -> Prickler a
132-
taggedData (Prickler gi pi) (Data elim sum) = Prickler getter (eliminate (mapAll (adjust pi) sum) . elim)
150+
untagged :: (forall r. a -> (ts @-> r) -> r) -> Partial Put Get a ts -> Prickler a
151+
untagged elim (Partial build break _) = Prickler build (flip elim break)
152+
153+
154+
tagged :: Ord i => Prickler i -> (forall r. a -> EliminatorWrapper ts r) -> All (Indexed i (Partial Put Get a)) ts -> Prickler a
155+
tagged (Prickler gi pi) elim sum = Prickler getter (merged (mapAll (adjust pi) sum) . elim)
133156
where
134-
adjust :: (i -> Builder) -> (K i :*: Case Prickler a) ts -> (K Builder :*: All (Flip Builder)) ts
135-
adjust pi (K i :*: Case _ shape) = K (pi i) :*: mapAll (Flip . put) shape
157+
merged :: All ((:<-@) r) ts -> EliminatorWrapper ts r -> r
158+
merged rs (EliminatorWrapper elim) = merge rs elim
159+
160+
adjust :: (i -> Put) -> (K i :*: Partial Put Get a) ts -> (Put :<-@ ts)
161+
adjust pi (K i :*: Partial _ breaker _) = NFlip breaker
162+
136163

137-
ps = IM.fromList (mapAllF (\(K x :*: y) -> (fromIntegral x, Exists y)) sum)
164+
ps = M.fromList (mapAllF (\(K x :*: y) -> (x, Exists y)) sum)
138165

139166
getter = do
140167
tag <- gi
141-
case IM.lookup (fromIntegral tag) ps of
142-
Nothing -> fail $ "Invalid tag: " ++ show (fromIntegral tag :: Integer)
143-
Just (Exists (Case cons shape)) -> liftAn cons (mapAll get shape)
168+
case M.lookup tag ps of
169+
Nothing -> fail $ "Invalid tag!"
170+
Just (Exists (Partial maker _ _)) -> maker
144171

145172

173+
taggedSized :: (Show i, Ord i, Integral s) => Prickler i -> Prickler s -> (forall r. a -> EliminatorWrapper ts r) -> All (Indexed i (Partial Put Get a)) ts -> Prickler a
174+
taggedSized (Prickler gi pi) (Prickler gs ps) elim sum = Prickler getter (merged (mapAll (adjust pi) sum) . elim)
175+
where
176+
merged :: All ((:<-@) r) ts -> EliminatorWrapper ts r -> r
177+
merged rs (EliminatorWrapper elim) = merge rs elim
178+
179+
adjust :: (i -> Put) -> (K i :*: Partial Put Get a) ts -> (Put :<-@ ts)
180+
adjust pi (K i :*: Partial _ breaker _) = NFlip breaker
181+
182+
183+
ps = M.fromList (mapAllF (\(K x :*: y) -> (x, Exists y)) sum)
184+
185+
getter = do
186+
tag <- gi
187+
size <- gs
188+
case M.lookup tag ps of
189+
Nothing -> fail $ "Invalid tag! " ++ show tag
190+
Just (Exists (Partial maker _ _)) -> do
191+
bs <- getLazyByteString (fromIntegral size)
192+
return $ runGet maker bs
193+
194+
195+
196+
alignedGet :: Int -> Get a -> Get a
197+
alignedGet n g = do
198+
br <- fromIntegral <$> bytesRead
199+
Get.skip $ n - br `rem` n
200+
g
201+
202+
203+
bytesWritten :: PutM Int64
204+
bytesWritten = PutM (\w -> State w mempty w)
205+
206+
singletonPut :: Word8 -> Put
207+
singletonPut x = PutM (\w -> State (w + 1) (singleton x) ())
208+
209+
alignedPut :: Int -> PutM a -> PutM a
210+
alignedPut n p = do
211+
bw <- fromIntegral <$> bytesWritten
212+
replicateM_ (n - (bw `rem` n)) (singletonPut 0)
213+
p
214+
146215
(#) :: a -> g x -> (K a :*: g) x
147216
i # x = K i :*: x
217+
218+
219+
word8 = Prickler getWord8 singletonPut
220+
221+
word16be = Prickler getWord16be (\x -> PutM (\w -> State (w + 2) (putWord16be x) ()))
222+
word16le = Prickler getWord16le (\x -> PutM (\w -> State (w + 2) (putWord16le x) ()))
223+
224+
word32be = Prickler getWord32be (\x -> PutM (\w -> State (w + 4) (putWord32be x) ()))
225+
word32le = Prickler getWord32le (\x -> PutM (\w -> State (w + 4) (putWord32le x) ()))
226+
227+
word64be = Prickler getWord64be (\x -> PutM (\w -> State (w + 8) (putWord64be x) ()))
228+
word64le = Prickler getWord64le (\x -> PutM (\w -> State (w + 8) (putWord64le x) ()))
229+
230+
int8 :: Prickler Int8
231+
int8 = wrap fromIntegral fromIntegral word8
232+
233+
int16be, int16le :: Prickler Int16
234+
int16be = wrap fromIntegral fromIntegral word16be
235+
int16le = wrap fromIntegral fromIntegral word16le
236+
237+
int32be, int32le :: Prickler Int32
238+
int32be = wrap fromIntegral fromIntegral word32be
239+
int32le = wrap fromIntegral fromIntegral word32le
240+
241+
int64be, int64le :: Prickler Int64
242+
int64be = wrap fromIntegral fromIntegral word64be
243+
int64le = wrap fromIntegral fromIntegral word64le
244+
245+
float :: Prickler Float
246+
float = error "foo"
247+
248+
double :: Prickler Double
249+
double = error "bar"
250+
251+
byteString :: Integral i => Prickler i -> Prickler BL.ByteString
252+
byteString (Prickler gi pi) = Prickler getter putter
253+
where
254+
getter = do len <- gi; getLazyByteString (fromIntegral len)
255+
putter xs = let len = BL.length xs in pi (fromIntegral len) <> PutM (\w -> State (w + fromIntegral len) (fromLazyByteString xs) ())
256+
257+
remainingByteString :: Prickler BL.ByteString
258+
remainingByteString = Prickler getRemainingLazyByteString putter
259+
where
260+
putter xs = undefined
261+
262+
gvector :: (Integral i, G.Vector v a) => Prickler i -> Prickler a -> Prickler (v a)
263+
gvector (Prickler gi pi) (Prickler ga pa) = Prickler getter putter
264+
where
265+
getter = do len <- gi; G.replicateM (fromIntegral len) ga
266+
putter xs = do pi (fromIntegral $ G.length xs); G.mapM_ pa xs

0 commit comments

Comments
 (0)