1
1
{-# LANGUAGE DoRec #-}
2
- module Language.Java.ClassFile (getClass , nameConstructor ) where
2
+ module Language.Java.ClassFile (
3
+ ImportedDecl (.. ),
4
+ -- * Classfile parsing
5
+ getClass ,
6
+ -- * Magic identifiers
7
+ nameConstructor
8
+ ) where
3
9
4
10
import Language.Java.Syntax
5
11
import Data.Binary.Get
@@ -15,6 +21,8 @@ import Control.Monad.Reader
15
21
import Text.ParserCombinators.Parsec
16
22
import Data.List
17
23
24
+ import Debug.Trace
25
+
18
26
parseFull :: Parser a -> Parser a
19
27
-- language-java depends on Parsec 2, which is not Applicative...
20
28
-- parseFull p = p <* eof
@@ -48,7 +56,7 @@ readType s = case parse (parseFull parseType) "" s of
48
56
49
57
parseClassType :: Parser ClassType
50
58
parseClassType =
51
- do parts <- (many1 alphaNum) `sepBy` (char ' /' )
59
+ do parts <- (many1 alphaNum) `sepBy` (char ' /' <|> char ' $ ' )
52
60
let ids = map (\ part -> (Ident part, [] )) parts
53
61
return $ ClassType ids
54
62
@@ -132,32 +140,15 @@ getConstants = do
132
140
classObject :: ClassType
133
141
classObject = ClassType [(Ident " java" , [] ), (Ident " lang" , [] ), (Ident " Object" , [] )]
134
142
143
+ -- | Constructors are encoded in .class files as member functions of the name \"@\<init>@\".
135
144
nameConstructor :: String
136
145
nameConstructor = " <init>"
137
146
138
147
getClassType :: ClassImporter ClassType
139
148
getClassType = constClass <$> getConstantRef
140
149
141
- getClass :: Get TypeDecl
142
- getClass =
143
- do (_major, _minor) <- getHeader
144
- constTable <- getConstants
145
- flip runReaderT constTable $
146
- do (isInterface, modifiers) <- getToplevel
147
-
148
- ClassType [(this, _)] <- getClassType
149
- superClass <- getClassType
150
- let super = if superClass == classObject then Nothing else Just (ClassRefType superClass)
151
-
152
- ifaces <- getMany (ClassRefType <$> getClassType)
153
- fields <- getMany getField
154
- methods <- catMaybes <$> getMany (getMethod this)
155
-
156
- _attributes <- getAttributes
157
-
158
- return $ if isInterface
159
- then InterfaceTypeDecl $ InterfaceDecl modifiers this [] ifaces (InterfaceBody [] )
160
- else ClassTypeDecl $ ClassDecl modifiers this [] super ifaces (ClassBody $ map MemberDecl $ fields ++ methods)
150
+ -- getClassTypeMaybe :: ClassImporter (Maybe ClassType)
151
+ -- getClassTypeMaybe = constClassMaybe <$>
161
152
162
153
getHeader =
163
154
do signature <- replicateM 4 getWord8
@@ -167,20 +158,34 @@ getHeader =
167
158
major <- getWord16be
168
159
return (major, minor)
169
160
170
- getConstantRef :: ClassImporter Constant
171
- getConstantRef =
161
+ getConstantRefMaybe :: ClassImporter ( Maybe Constant )
162
+ getConstantRefMaybe =
172
163
do idx <- lift getConstIdx
173
- asks (! idx)
164
+ if idx == 0 then return Nothing else Just <$> asks (! idx)
165
+
166
+ getConstantRef :: ClassImporter Constant
167
+ getConstantRef = fromJust <$> getConstantRefMaybe
174
168
175
- getStringRef :: ClassImporter String
176
- getStringRef =
177
- do const <- getConstantRef
178
- case const of
179
- ConstantString s -> return s
169
+ getStringRefMaybe :: ClassImporter (Maybe String )
170
+ getStringRefMaybe =
171
+ do const <- getConstantRefMaybe
172
+ return $ case const of
173
+ Just (ConstantString s) -> Just s
174
+ _ -> Nothing
175
+
176
+ getStringRef :: ClassImporter String
177
+ getStringRef = fromJust <$> getStringRefMaybe
178
+
179
+ data InnerClass = InnerClass { innerInner :: ClassType ,
180
+ innerOuter :: Maybe ClassType ,
181
+ innerName :: Maybe String ,
182
+ innerFlags :: Word16 }
183
+ deriving Show
180
184
181
185
data Attribute = AttrConstantValue ConstantValue
182
186
| AttrExceptions [ClassType ]
183
187
| AttrSynthetic
188
+ | AttrInnerClasses [InnerClass ]
184
189
deriving Show
185
190
186
191
isAttrSynthetic AttrSynthetic = True
@@ -190,8 +195,19 @@ isAttrConstantValue (AttrConstantValue _) = True
190
195
isAttrConstantValue _ = False
191
196
192
197
isAttrExceptions (AttrExceptions _) = True
193
- isAttrExceptions _ = False
194
-
198
+ isAttrExceptions _ = False
199
+
200
+ isAttrInnerClasses (AttrInnerClasses _) = True
201
+ isAttrInnerClasses _ = False
202
+
203
+ getInnerClass :: ClassImporter InnerClass
204
+ getInnerClass =
205
+ do inner <- getClassType
206
+ outer <- fmap constClass <$> getConstantRefMaybe
207
+ name <- getStringRefMaybe
208
+ flags <- lift getWord16be
209
+ return $ InnerClass inner outer name flags
210
+
195
211
getAttribute :: ClassImporter (Maybe Attribute )
196
212
getAttribute =
197
213
do name <- getStringRef
@@ -206,13 +222,15 @@ getAttribute =
206
222
ConstantValue val -> val
207
223
" Exceptions" ->
208
224
Just <$> AttrExceptions <$> getMany getClassType
225
+ " InnerClasses" ->
226
+ do Just <$> AttrInnerClasses <$> getMany getInnerClass
209
227
_ ->
210
228
do lift $ skip (fromIntegral len)
211
229
return Nothing
212
230
213
231
getAttributes = catMaybes <$> getMany getAttribute
214
232
215
- getField :: ClassImporter MemberDecl
233
+ getField :: ClassImporter ( Maybe MemberDecl )
216
234
getField =
217
235
do modifiers <- getModifiers
218
236
name <- getStringRef
@@ -227,7 +245,8 @@ getField =
227
245
ValueString s -> String s
228
246
ValueFloat x -> Float $ realToFrac x
229
247
ValueDouble x -> Double x
230
- return $ FieldDecl modifiers ty [VarDecl (VarId $ Ident name) init ]
248
+ return $ unlessSynthetic attributes $
249
+ FieldDecl modifiers ty [VarDecl (VarId $ Ident name) init ]
231
250
232
251
getMethod :: Ident -> ClassImporter (Maybe MemberDecl )
233
252
getMethod cls =
@@ -240,12 +259,13 @@ getMethod cls =
240
259
let exceptions = case find (isAttrExceptions) attributes of
241
260
Nothing -> []
242
261
Just (AttrExceptions tys) -> map ClassRefType tys
243
- return $
244
- if any isAttrSynthetic attributes then Nothing
245
- else Just $
246
- if isConstructor
247
- then ConstructorDecl modifiers [] cls formals exceptions (ConstructorBody Nothing [] )
248
- else MethodDecl modifiers [] ret (Ident name) formals exceptions (MethodBody Nothing )
262
+ return $ unlessSynthetic attributes $
263
+ if isConstructor
264
+ then ConstructorDecl modifiers [] cls formals exceptions (ConstructorBody Nothing [] )
265
+ else MethodDecl modifiers [] ret (Ident name) formals exceptions (MethodBody Nothing )
266
+
267
+ unlessSynthetic :: [Attribute ] -> a -> Maybe a
268
+ unlessSynthetic attributes x = if any isAttrSynthetic attributes then Nothing else Just x
249
269
250
270
parseModifiers :: Word16 -> [Modifier ]
251
271
parseModifiers flags =
@@ -272,3 +292,52 @@ getToplevel =
272
292
let iface = 0x0200 .~. flags
273
293
modifiers = parseModifiers flags
274
294
return (iface, modifiers)
295
+
296
+ data ImportedDecl = ImportedTopLevel TypeDecl
297
+ | ImportedInner TypeDecl
298
+
299
+ type DeclMap = [(ClassType , ImportedDecl )]
300
+
301
+ -- | Parse a binary .class file into a 'TypeDecl'
302
+ getClass :: Maybe DeclMap -> Get (ClassType , ImportedDecl )
303
+ getClass declMap =
304
+ do (_major, _minor) <- getHeader
305
+ constTable <- getConstants
306
+ flip runReaderT constTable $
307
+ do (isInterface, modifiers) <- getToplevel
308
+
309
+ classType@ (ClassType parts) <- getClassType
310
+ let (this, _) = last parts
311
+ superClass <- getClassType
312
+ let super = if superClass == classObject then Nothing else Just (ClassRefType superClass)
313
+
314
+ ifaces <- getMany (ClassRefType <$> getClassType)
315
+ fields <- catMaybes <$> getMany getField
316
+ methods <- catMaybes <$> getMany (getMethod this)
317
+
318
+ attributes <- getAttributes
319
+ let innerClasses =
320
+ case find isAttrInnerClasses attributes of
321
+ Nothing -> []
322
+ Just (AttrInnerClasses ics) -> ics
323
+ innerDecls = mapMaybe (toInnerDecl classType) innerClasses
324
+ isInner = any (\ ic -> innerInner ic == classType) innerClasses
325
+
326
+ let members = fields ++ methods ++ innerDecls
327
+ decl = if isInterface
328
+ then InterfaceTypeDecl $ InterfaceDecl modifiers this [] ifaces (InterfaceBody members)
329
+ else ClassTypeDecl $ ClassDecl modifiers this [] super ifaces (ClassBody $ map MemberDecl members)
330
+
331
+ return (classType, (if isInner then ImportedInner else ImportedTopLevel ) decl)
332
+
333
+ where toInnerDecl classType ic =
334
+ do outer <- innerOuter ic
335
+ guard $ outer == classType
336
+ ImportedInner inner <- lookup (innerInner ic) =<< declMap
337
+ let modifiers = parseModifiers $ innerFlags ic
338
+ return $ case inner of
339
+ ClassTypeDecl classDecl -> MemberClassDecl $ classDecl `withClassModifiers` modifiers
340
+ InterfaceTypeDecl ifaceDecl -> MemberInterfaceDecl $ ifaceDecl `withInterfaceModifiers` modifiers
341
+
342
+ (ClassDecl _ id tys super ifaces body) `withClassModifiers` ms = ClassDecl ms id tys super ifaces body
343
+ (InterfaceDecl _ id tys ifaces body) `withInterfaceModifiers` ms = InterfaceDecl ms id tys ifaces body
0 commit comments