public
Description: An Actionscript 3 to haXe source converter written in Haskell
Homepage: http://geekrelief.wordpress.com
Clone URL: git://github.com/geekrelief/as3tohaxe.git
Click here to lend your support to: as3tohaxe and make a donation at www.pledgie.com !
as3tohaxe / as3tohaxe.hs
100644 107 lines (94 sloc) 5.203 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{-
as3tohaxe - An Actionscript 3 to haXe source file translator
Copyright (C) 2008 Don-Duong Quach
 
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-}
-- Translate a file
 
import ActionhaXe.Lexer
import ActionhaXe.Data
import ActionhaXe.Prim
import ActionhaXe.Parser
import ActionhaXe.Translator
import ActionhaXe.CLArgs
 
import System.Directory
import System.Environment (getArgs)
import Control.Monad.State
import System.Exit
import Data.Char (toUpper, toLower)
import Data.List (isSuffixOf, intercalate)
import System.Console.ParseArgs
import Data.Maybe (fromJust, fromMaybe)
import System.FilePath.Posix (takeDirectory, takeBaseName, splitDirectories)
import qualified Data.Map as Map
 
translateFile :: String -> StateT Conf IO ()
translateFile filename = do
    conf <- get
    let outdir = confOutput conf
    let dir = takeDirectory filename
    dirExists <- liftIO $ doesDirectoryExist (outdir ++ dir) -- check if dir exists
    -- create dir
    liftIO $ unless dirExists (createDirectoryIfMissing True (outdir++dir) >> putStrLn ("Created " ++ outdir++dir))
    -- add path to imports
    unless dirExists (put conf{ imports = (Map.insert dir [] $ imports conf) })
    -- add class to imports
    put conf{imports = (Map.insertWith (\x y -> x ++ y) dir [takeBaseName $ (toUpper $ head filename):(tail filename)] $ imports conf) }
    liftIO $ putStrLn $ "Translating " ++ filename
    contents <- liftIO $ readFile filename
    let updated_contents = if gotArg (confArgs conf) NoCarriage
                               then filter ( /= '\r' ) contents -- remove carriage
                               else contents
    let tokens = runLexer "" updated_contents
    let outfilename = outdir ++ (reverse $ "xh" ++ ( drop 2 $ reverse filename))
    program <- case parseTokens filename tokens of
        Right p@(AS3Program x st) -> return (p, st{outfile = outfilename, conf=conf })
        Right p@(AS3Directives x st) -> return (p, st{outfile = outfilename, conf=conf })
        Left err -> fail $ show err
    trans <- liftIO $ runStateT (translateAs3Ast (fst program)) (snd program)
    liftIO $ writeFile outfilename $ fst trans
 
isFile :: String -> StateT Conf IO Bool
isFile f = do conf <- get
              let outdir = confOutput conf
              t <- liftIO $ doesFileExist f
              let outfilename = outdir ++ (reverse $ "xh" ++ ( drop 2 $ reverse f))
              o <- liftIO $ doesFileExist (outfilename)
              when o $ liftIO $ putStrLn $ "Skipping " ++ f
              return $ not o && t && ("as" == (map toLower $ reverse $ take 2 $ reverse f))
 
isDir :: String -> StateT Conf IO Bool
isDir d = do t <- liftIO $ doesDirectoryExist d
             return $ t
 
translateDir :: String -> StateT Conf IO ()
translateDir dir = do
    conf <- get
    let outdir = confOutput conf
    contents <- liftIO $ getDirectoryContents dir
    let c = map (\e -> dir++"/"++e) (filter (\d-> d /= "." && d /=".." && d /= ".svn") contents)
    asfiles <- filterM isFile c
    asdirs <- filterM isDir c
    mapM_ translateFile asfiles
    mapM_ translateDir asdirs
 
main = do args <- parseArgsIO ArgsTrailing clargs
          let input = fromJust $ getArgString args Input
          let outdir = fromMaybe "hx_output/" $ getArgString args OutputDir
          let conf = Conf{ confArgs = args , confInput = input, confOutput = outdir, imports = Map.empty}
          (_, updated_conf) <- if isSuffixOf ".as" input
                              then do dirExists <- doesDirectoryExist outdir
                                      unless dirExists ((createDirectoryIfMissing True outdir) >> putStrLn ("Created " ++ outdir))
                                      runStateT (translateFile input) conf
                              else runStateT (translateDir input) conf
          if gotArg (confArgs updated_conf) CreateImports
              then do putStrLn $ "Creating import files in "++outdir
                      mapM_ (\(k, v)-> createImport outdir k $ reverse v) $ Map.toList $ imports updated_conf
              else return ()
 
createImport outdir packagePath packageList = do let importFileName = intercalate "_" ("Import":(splitDirectories packagePath))
                                                 writeFile (outdir ++ importFileName++".hx") $ packageContent packagePath packageList
    where packageContent path list = foldl (\content klass -> content++ "typedef "++klass++" = "++ppath++klass++"\n") "" list
                                         where ppath = (intercalate "." $ splitDirectories path)++"."