| 1 | {-# OPTIONS_GHC -fglasgow-exts -cpp #-} |
|---|
| 2 | |
|---|
| 3 | -- -fth -cpp -package plugins #-} |
|---|
| 4 | |
|---|
| 5 | module Pugs.External.Haskell where |
|---|
| 6 | import Pugs.AST |
|---|
| 7 | |
|---|
| 8 | #undef PUGS_HAVE_TH |
|---|
| 9 | -- #include "../pugs_config.h" |
|---|
| 10 | #if !defined(PUGS_HAVE_TH) || !defined(PUGS_HAVE_HSPLUGINS) |
|---|
| 11 | externalizeHaskell :: String -> String -> IO String |
|---|
| 12 | externalizeHaskell = error "Template Haskell support not compiled in" |
|---|
| 13 | loadHaskell :: FilePath -> IO [(String, [Val] -> Eval Val)] |
|---|
| 14 | loadHaskell = error "Template Haskell support not compiled in" |
|---|
| 15 | #else |
|---|
| 16 | |
|---|
| 17 | import Language.Haskell.TH as TH |
|---|
| 18 | import Language.Haskell.Parser |
|---|
| 19 | import Language.Haskell.Syntax |
|---|
| 20 | import System.Plugins |
|---|
| 21 | import Pugs.Config |
|---|
| 22 | import Pugs.Internals |
|---|
| 23 | |
|---|
| 24 | {- ourPackageConfigs :: [PackageConfig] |
|---|
| 25 | ourPackageConfigs = [ |
|---|
| 26 | PackageConfig { |
|---|
| 27 | hs_libraries = ["Unicode.o"] |
|---|
| 28 | extra_libraries = ["UnicodeC.o"] |
|---|
| 29 | } |
|---|
| 30 | ] -} |
|---|
| 31 | ourPackageConfigs :: [a] |
|---|
| 32 | ourPackageConfigs = [] |
|---|
| 33 | |
|---|
| 34 | loadOrDie |
|---|
| 35 | :: FilePath -- ^ object file |
|---|
| 36 | -> [FilePath] -- ^ any include paths |
|---|
| 37 | -> [FilePath] -- ^ list of package.conf paths |
|---|
| 38 | -> String -- ^ symbol to find |
|---|
| 39 | -> IO (a) |
|---|
| 40 | loadOrDie obj includes configs symbol = do |
|---|
| 41 | stat <- load obj includes configs symbol |
|---|
| 42 | case stat of |
|---|
| 43 | LoadFailure errs -> error $ unlines $ ["Error loading "++symbol++" from "++obj] ++ errs |
|---|
| 44 | LoadSuccess _ a -> return a |
|---|
| 45 | |
|---|
| 46 | loadHaskell :: FilePath -> IO [(String, [Val] -> Eval Val)] |
|---|
| 47 | loadHaskell file = do |
|---|
| 48 | let coredir = getConfig "installarchlib" ++ "/CORE/pugs/" |
|---|
| 49 | objDir = getConfig "installsitearch" |
|---|
| 50 | objFile = (objDir ++ "/" ++ file) |
|---|
| 51 | loadpaths = [coredir, objDir] |
|---|
| 52 | -- For Unicode |
|---|
| 53 | loadRawObject $ coredir++"UnicodeC.o" |
|---|
| 54 | -- For RRegex |
|---|
| 55 | loadRawObject $ coredir++"pcre/pcre.o" |
|---|
| 56 | |
|---|
| 57 | -- AST has early requirements and late requirements, because of recrusivity. |
|---|
| 58 | -- The logic for this should probably be moved to hs-plugins, but do it here |
|---|
| 59 | -- for now. |
|---|
| 60 | {- |
|---|
| 61 | mapM |
|---|
| 62 | (\n -> load (coredir++n++".o") loadpaths ourPackageConfigs "") |
|---|
| 63 | ["Compat", "Cont", "Embed", "Embed/Perl5", "Internals", "RRegex", "RRegex/PCRE", "RRegex/Syntax", "Rule/Pos", "UTF8", "Unicode", "AST"] |
|---|
| 64 | -} |
|---|
| 65 | |
|---|
| 66 | (extern :: [String]) <- loadOrDie objFile loadpaths ourPackageConfigs "extern__" |
|---|
| 67 | -- print (">"++(show extern)++"<") |
|---|
| 68 | (`mapM` extern) $ \name -> do |
|---|
| 69 | func <- loadOrDie objFile loadpaths ourPackageConfigs ("extern__" ++ name) |
|---|
| 70 | return (name, func) |
|---|
| 71 | |
|---|
| 72 | externalizeHaskell :: String -> String -> IO String |
|---|
| 73 | #ifndef HADDOCK |
|---|
| 74 | externalizeHaskell mod code = do |
|---|
| 75 | let names = map snd exports |
|---|
| 76 | symTable <- runQ [d| |
|---|
| 77 | extern__ :: [String] |
|---|
| 78 | extern__ = names |
|---|
| 79 | |] |
|---|
| 80 | symDecls <- mapM wrap names |
|---|
| 81 | return $ unlines $ |
|---|
| 82 | [ "module " ++ mod ++ " where" |
|---|
| 83 | , "import Internals" |
|---|
| 84 | , "import GHC.Base" |
|---|
| 85 | , "import AST" |
|---|
| 86 | , "" |
|---|
| 87 | , code |
|---|
| 88 | , "" |
|---|
| 89 | , "-- below are automatically generated by Pugs --" |
|---|
| 90 | , TH.pprint symTable |
|---|
| 91 | , TH.pprint symDecls |
|---|
| 92 | ] |
|---|
| 93 | where |
|---|
| 94 | exports :: [(HsQualType, String)] |
|---|
| 95 | exports = concat [ [ (typ, name) | HsIdent name <- names ] |
|---|
| 96 | | HsTypeSig _ names typ <- parsed |
|---|
| 97 | ] |
|---|
| 98 | parsed = case parseModule code of |
|---|
| 99 | ParseOk (HsModule _ _ _ _ decls) -> decls |
|---|
| 100 | ParseFailed _ err -> error err |
|---|
| 101 | #endif |
|---|
| 102 | |
|---|
| 103 | wrap :: String -> IO Dec |
|---|
| 104 | #ifndef HADDOCK |
|---|
| 105 | wrap fun = do |
|---|
| 106 | [quoted] <- runQ [d| |
|---|
| 107 | name :: [Val] -> Eval Val |
|---|
| 108 | name = \[v] -> do |
|---|
| 109 | s <- fromVal v |
|---|
| 110 | return (castV ($(dyn fun) s)) |
|---|
| 111 | |] |
|---|
| 112 | return $ munge quoted ("extern__" ++ fun) |
|---|
| 113 | #endif |
|---|
| 114 | |
|---|
| 115 | munge :: Dec -> String -> Dec |
|---|
| 116 | munge (ValD _ x y) name = ValD (VarP (mkName name)) x y |
|---|
| 117 | munge _ _ = error "impossible" |
|---|
| 118 | |
|---|
| 119 | |
|---|
| 120 | |
|---|
| 121 | #endif |
|---|