refactor: store amount of arguments of a method in RawMethod
[mate.git] / Mate / ClassPool.hs
index 8d88ad325e31f02e5835aa6923d91888f9b71b23..ad290542d7167c57b8a4a9b29efbd149d71d212b 100644 (file)
@@ -19,6 +19,7 @@ import Data.Word
 import Data.Binary
 import qualified Data.Map as M
 import qualified Data.Set as S
+import Data.List
 import qualified Data.ByteString.Lazy as B
 import Data.String.Utils
 import Control.Monad
@@ -188,41 +189,34 @@ loadInterface path = do
       setInterfaceMethodMap $ M.fromList sm `M.union` M.fromList mm `M.union` immap
       setInterfaceMap $ M.insert path cfile imap'
   where
-  zipbase base = zipWith (\x y -> (entry y, x + base)) [0,4..]
-  entry = getname path
-  getname p y = p `B.append` methodName y `B.append` encode (methodSignature y)
+    zipbase base = zipWith (\x y -> (entry y, x + base)) [0,4..]
+    entry = getname path
+    getname p y = p `B.append` methodName y `B.append` encode (methodSignature y)
 
 
 calculateFields :: Class Direct -> Maybe ClassInfo -> IO (FieldMap, FieldMap)
 calculateFields cf superclass = do
     -- TODO(bernhard): correct sizes. int only atm
 
-    -- TODO(bernhard): nicer replacement for `myspan'
-    let (sfields, ifields) = myspan (S.member ACC_STATIC . fieldAccessFlags) (classFields cf)
-        myspan :: (a -> Bool) -> [a] -> ([a], [a])
-        myspan _ [] = ([],[])
-        myspan p (x:xs)
-          | p x = (x:ns, ni)
-          | otherwise = (ns, x:ni)
-          where (ns,ni) = myspan p xs
+    let (sfields, ifields) = partition (S.member ACC_STATIC . fieldAccessFlags) (classFields cf)
 
-    staticbase <- mallocClassData $ fromIntegral (length sfields) * 4
-    let i_sb = fromIntegral $ ptrToIntPtr staticbase
-    let sm = zipbase i_sb sfields
     let sc_sm = getsupermap superclass ciStaticMap
+    staticbase <- mallocClassData $ fromIntegral (length sfields) * 4
+    let sm = zipbase (fromIntegral $ ptrToIntPtr staticbase) sfields
     -- new fields "overwrite" old ones, if they have the same name
-    let staticmap = M.fromList sm `M.union` sc_sm
+    let staticmap = sm `M.union` sc_sm
 
     let sc_im = getsupermap superclass ciFieldMap
     -- "+ 4" for the method table pointer
     let max_off = (4+) $ fromIntegral $ M.size sc_im * 4
     let im = zipbase max_off ifields
     -- new fields "overwrite" old ones, if they have the same name
-    let fieldmap = M.fromList im `M.union` sc_im
+    let fieldmap = im `M.union` sc_im
 
     return (staticmap, fieldmap)
   where
-  zipbase base = zipWith (\x y -> (fieldName y, x + base)) [0,4..]
+    zipbase :: Int32 -> [Field Direct] -> FieldMap
+    zipbase base = foldr (\(x,y) -> M.insert (fieldName y) (x + base)) M.empty . zip [0,4..]
 
 -- helper
 getsupermap :: Maybe ClassInfo -> (ClassInfo -> FieldMap) -> FieldMap
@@ -260,16 +254,13 @@ loadAndInitClass path = do
   -- execute class initializer
   case lookupMethod "<clinit>" (ciFile ci) of
     Just m -> do
-      hmap <- parseMethod (ciFile ci) "<clinit>" $ MethodSignature [] ReturnsVoid
-      case hmap of
-        Just hmap' -> do
-          let mi = MethodInfo "<clinit>" path (methodSignature m)
-          entry <- compileBB hmap' mi
-          addMethodRef entry mi [path]
-          printfCp "executing static initializer from %s now\n" (toString path)
-          executeFuncPtr entry
-          printfCp "static initializer from %s done\n" (toString path)
-        Nothing -> error "readClass: static initializer not found (WTF?). abort"
+      rawmethod <- parseMethod (ciFile ci) "<clinit>" $ MethodSignature [] ReturnsVoid
+      let mi = MethodInfo "<clinit>" path (methodSignature m)
+      entry <- compileBB rawmethod mi
+      addMethodRef entry mi [path]
+      printfCp "executing static initializer from %s now\n" (toString path)
+      executeFuncPtr entry
+      printfCp "static initializer from %s done\n" (toString path)
     Nothing -> return ()
 
   class_map' <- getClassMap
@@ -281,23 +272,23 @@ loadAndInitClass path = do
 readClassFile :: String -> IO (Class Direct)
 readClassFile path' = readIORef classPaths >>= rcf
   where
-  path = replace "." "/" path'
-  rcf :: [MClassPath] -> IO (Class Direct)
-  rcf [] = error $ "readClassFile: Class \"" ++ show path ++ "\" not found."
-  rcf (Directory pre:xs) = do
-    let cf = pre ++ path ++ ".class"
-    printfCp "rcf: searching @ %s for %s\n" (show pre) (show path)
-    b <- doesFileExist cf
-    if b
-      then parseClassFile cf
-      else rcf xs
-  rcf (JAR p:xs) = do
-    printfCp "rcf: searching %s in JAR\n" (show path)
-    entry <- getEntry p path
-    case entry of
-      Just (LoadedJAR _ cls) -> return cls
-      Nothing -> rcf xs
-      _ -> error $ "readClassFile: Class \"" ++ show path ++ "\" in JAR not found. #1"
+    path = replace "." "/" path'
+    rcf :: [MClassPath] -> IO (Class Direct)
+    rcf [] = error $ "readClassFile: Class \"" ++ show path ++ "\" not found."
+    rcf (Directory pre:xs) = do
+      let cf = pre ++ path ++ ".class"
+      printfCp "rcf: searching @ %s for %s\n" (show pre) (show path)
+      b <- doesFileExist cf
+      if b
+        then parseClassFile cf
+        else rcf xs
+    rcf (JAR p:xs) = do
+      printfCp "rcf: searching %s in JAR\n" (show path)
+      entry <- getEntry p path
+      case entry of
+        Just (LoadedJAR _ cls) -> return cls
+        Nothing -> rcf xs
+        _ -> error $ "readClassFile: Class \"" ++ show path ++ "\" in JAR not found. #1"
 
 data MClassPath =
   Directory String |