Embedding.hs (2627B)
1 {-# LANGUAGE ForeignFunctionInterface #-} 2 {-# LANGUAGE OverloadedStrings #-} 3 -- Bundle loading and IO extend the internal reducer and value boundary. 4 module Embedding (module Embedding, module EmbeddingCore) where 5 6 import EmbeddingCore 7 import Control.Monad.State.Strict 8 import qualified Data.Map.Lazy as L 9 import qualified Data.Vector as V 10 import Data.Word 11 import Foreign 12 import Foreign.C.Types 13 import Runtime.Value (ofList) 14 import qualified Wire 15 import qualified IODriver 16 import qualified IO.Driver as IO 17 import qualified IO.Protocol as Protocol 18 19 loadBundle :: Word64 -> Ptr Word8 -> CSize -> Ptr Word8 -> CSize -> Ptr Word64 -> IO Word32 20 loadBundle ctx ptr len namePtr nameLen out = withContext ctx $ do 21 bytes <- liftIO (readBytes ptr len) 22 name <- liftIO (readText namePtr nameLen) 23 bundle <- liftIO (checked 3 (Wire.decodeBundle bytes)) 24 liftIO (checked 3 (Wire.verifyBundle bundle)) 25 exported <- case filter ((== name) . Wire.exportName) (Wire.manifestExports (Wire.bundleManifest bundle)) of 26 [value] -> pure value 27 _ -> liftIO (fault 3 "bundle export not found") 28 liftIO (require (Wire.exportKind exported == "term" && Wire.exportAbi exported == "arboricx.abi.tree.v1") "unsupported export ABI") 29 let terms = Wire.reconstructBundleTerms (Wire.bundleNodes bundle) 30 publish out (terms V.! fromIntegral (Wire.exportRoot exported)) 31 runIO :: Word64 -> Word64 -> Ptr Word32 -> Ptr Word64 -> Ptr Word64 -> IO Word32 32 runIO ctx program outcome out cleanup = withContext ctx $ do 33 liftIO (require (outcome /= nullPtr && out /= nullPtr && cleanup /= nullPtr && 34 castPtr outcome /= out && castPtr outcome /= cleanup && out /= cleanup) "invalid IO outputs") 35 tree <- lookupRoot program 36 (version,action) <- liftIO (checked 3 (IODriver.checkIOSentinel tree)) 37 liftIO (require (version == 2) "unsupported IO version") 38 result <- liftIO (IO.runDetailed action) 39 let (tag,value,problems) = case result of 40 IO.Completed v -> (0,v,[]) 41 IO.Failed v ps -> (1,v,ps) 42 IO.Cancelled v ps -> (2,v,ps) 43 -- Reserve both IDs before publishing any output. Neither payload is forced. 44 valueId <- liftIO newIdentity 45 cleanupId <- liftIO newIdentity 46 modify' (\c -> c {roots = L.insert valueId value $ 47 L.insert cleanupId (ofList (map Protocol.problemTree problems)) (roots c)}) 48 pure (poke outcome tag >> poke out valueId >> poke cleanup cleanupId) 49 foreign export ccall "tricu_load_bundle" loadBundle :: Word64 -> Ptr Word8 -> CSize -> Ptr Word8 -> CSize -> Ptr Word64 -> IO Word32 50 foreign export ccall "tricu_run_io" runIO :: Word64 -> Word64 -> Ptr Word32 -> Ptr Word64 -> Ptr Word64 -> IO Word32