2013-01-22 46 views
7

क्या यह संभव है पैदा करते हैं और चलाने TemplateHaskell कार्यावधि में कोड उत्पन्न करने के लिए?रनटाइम पर टेम्पलेटहस्केल जेनरेट कोड उत्पन्न करना और चलाने के लिए संभव है?

, सी का उपयोग क्रम में, मैं कर सकते हैं:

  • एक समारोह के स्रोत कोड बनाने के लिए, एक .so (लिनक्स) (या उपयोग LLVM, आदि के लिए यह संकलन करने
  • जीसीसी के लिए कॉल बाहर ।),
  • लोड .so और
  • कॉल समारोह।

एक ऐसी ही बात खाका हास्केल के साथ संभव है?

+0

खाका Haskell उत्पन्न कोड रनटाइम पर चलाया जाता है: पी – Satvik

+0

@Satvik - उत्पन्न कोड के क्रम में स्पष्ट रूप से, लेकिन मैं * जनरेटर के * रन टाइम पर तैयार किए गए कोड को चलाने में विशेष रूप से interesed हूँ – fadedbee

उत्तर

11

हाँ, यह संभव है। जीएचसी एपीआई टेम्पलेट हास्केल संकलित करेगा। एक सबूत-ऑफ-अवधारणा https://github.com/JohnLato/meta-th पर उपलब्ध है, हालांकि, हालांकि बहुत परिष्कृत नहीं है, एक सामान्य तकनीक दिखाती है जो कि प्रकार की सुरक्षा का एक मामला भी प्रदान करती है। टेम्पलेट हास्केल एक्सप्रेशन Meta प्रकार का उपयोग कर निर्माण कर रहे हैं, जिसे तब संकलित और उपयोग करने योग्य फ़ंक्शन में लोड किया जा सकता है।

{-# LANGUAGE ScopedTypeVariables #-} 
{-# LANGUAGE TemplateHaskell #-} 

{-# OPTIONS_GHC -Wall #-} 
module Data.Meta.Meta (
-- * Meta type 
    Meta (..) 

-- * Functions 
, metaCompile 
) where 

import Language.Haskell.TH 

import Data.Typeable as Typ 
import Control.Exception (bracket) 

import System.Plugins -- from plugins 
import System.IO 
import System.Directory 

newtype Meta a = Meta { unMeta :: ExpQ } 

-- | Super-dodgy for the moment, the Meta type should register the 
-- imports it needs. 
metaCompile :: forall a. Typeable a => Meta a -> IO (Either String a) 
metaCompile (Meta expr) = do 
    expr' <- runQ expr 

    -- pretty-print the TH expression as source code to be compiled at 
    -- run-time 
    let interpStr = pprint expr' 
     typeTypeRep = Typ.typeOf (undefined :: a) 

    let opener = do 
     (tfile, h) <- openTempFile "." "fooTmpFile.hs" 
     hPutStr h (unlines 
       [ "module TempMod where" 
       , "import Prelude" 
       , "import Language.Haskell.TH" 
       , "import GHC.Num" 
       , "import GHC.Base" 
       , "" 
       , "myFunc :: " ++ show typeTypeRep 
       , "myFunc = " ++ interpStr]) 
     hFlush h 
     hClose h 
     return tfile 
    bracket opener removeFile $ \tfile -> do 

     res <- make tfile ["-O2", "-ddump-simpl"] 
     let ofile = case res of 
        MakeSuccess _ fp -> fp 
        MakeFailure errs -> error $ show errs 
     print $ "loading from: " ++ show ofile 
     r2 <- load (ofile) [] [] "myFunc" 
     print "loaded" 

     case r2 of 
     LoadFailure er -> return (Left (show er)) 
     LoadSuccess _ (fn :: a) -> return $ Right fn 

यह समारोह एक ExpQ एक सादे Exp बनाने के लिए आईओ में इसे चलाता लेता है, और पहले। Exp तब सोर्स कोड में सुंदर-मुद्रित होता है, जिसे संकलित और रन-टाइम पर लोड किया जाता है। प्रैक्टिस में, मैंने पाया है कि अधिक कठिन बाधाओं में से एक उत्पन्न जेड कोड में सही आयात निर्दिष्ट कर रहा है।

+3

यह थोड़ा डरावना है। –

4

जो मैं समझता हूं कि आप रनटाइम पर एक कोड बनाना और चलाने के लिए चाहते हैं, जो मुझे लगता है कि आप GHC API का उपयोग करके कर सकते हैं लेकिन मुझे यह सुनिश्चित नहीं है कि आप क्या हासिल कर सकते हैं। यदि आप हॉट कोड स्वैपिंग की तरह कुछ चाहते हैं तो आप पैकेज hotswap पर देख सकते हैं।

+0

हाँ, यह GHC एपीआई + तरह लग रहा है होट्सएप ऐसा कर सकता है जो मैं ढूंढ रहा हूं। – fadedbee