-- | Conversion of Flow to Tetra -- module DDC.Core.Flow.Convert ( tetraOfFlowModule ) where import DDC.Core.Flow.Convert.Base import DDC.Core.Flow.Convert.Type import DDC.Core.Flow.Convert.Exp import DDC.Core.Exp.Annot import DDC.Core.Module import DDC.Control.Monad.Check import qualified DDC.Core.Flow.Prim as F import qualified DDC.Core.Salt.Name as T import qualified DDC.Core.Salt.Compounds as T import DDC.Core.Salt.Convert (initRuntime) import DDC.Core.Salt.Runtime (Config(..)) import qualified Data.Set as S tetraOfFlowModule :: Module a F.Name -> Either Error (Module a T.Name) tetraOfFlowModule mm = evalCheck (S.empty, S.empty) $ convertM mm convertM :: Module a F.Name -> ConvertM (Module a T.Name) convertM mm = do -- Convert signatures of imported functions. tsImportT' <- mapM convertImportNameTypeM $ moduleImportTypes mm tsImportV' <- mapM convertImportNameValueM $ moduleImportValues mm let tsImportV'rest = [ ( T.NameVar "getFieldOfBoxed" , ImportValueSea "getFieldOfBoxed" $ tForalls [kRegion, kData] $ \[r,d] -> T.tPtr r T.tObj `tFun` T.tNat `tFun` d) , ( T.NameVar "setFieldOfBoxed" , ImportValueSea "setFieldOfBoxed" $ tForalls [kRegion, kData] $ \[r,d] -> T.tPtr r T.tObj `tFun` T.tNat `tFun` d `tFun` T.tVoid) , ( T.NameVar "allocBoxed" , ImportValueSea "allocBoxed" $ tForalls [kRegion ] $ \[r ] -> T.tTag `tFun` T.tNat `tFun` T.tPtr r T.tObj) ] -- Convert signatures of exported functions. tsExportT' <- mapM convertExportM $ moduleExportTypes mm tsExportV' <- mapM convertExportM $ moduleExportValues mm -- Convert the body of the module body' <- convertX $ moduleBody mm -- Build the output module. let mm_tetra = ModuleCore { moduleName = moduleName mm , moduleIsHeader = moduleIsHeader mm , moduleExportTypes = tsExportT' , moduleExportValues = tsExportV' , moduleImportTypes = tsImportT' , moduleImportCaps = [] , moduleImportValues = tsImportV' ++ tsImportV'rest -- We're only using whole module compilation for -- flow programs, so there aren't any imports. , moduleImportDataDefs = [] , moduleDataDefsLocal = [] , moduleBody = body' } -- Initialise the salt heap. -- Hardcode this for now, because eventually this will target tetra. mm_init <- case initRuntime (Config 10000) mm_tetra of Nothing -> return mm_tetra Just mm' -> return mm' return $ mm_init --------------------------------------------------------------------------------------------------- -- | Convert an export spec. convertExportM :: (F.Name, ExportSource F.Name) -> ConvertM (T.Name, ExportSource T.Name) convertExportM (n, esrc) = do n' <- convertName n esrc' <- convertExportSourceM esrc return (n', esrc') -- Convert an export source. convertExportSourceM :: ExportSource F.Name -> ConvertM (ExportSource T.Name) convertExportSourceM esrc = case esrc of ExportSourceLocal n t -> do n' <- convertName n t' <- convertType t return $ ExportSourceLocal n' t' ExportSourceLocalNoType n -> do n' <- convertName n return $ ExportSourceLocalNoType n' --------------------------------------------------------------------------------------------------- -- | Convert an import spec. convertImportNameTypeM :: (F.Name, ImportType F.Name) -> ConvertM (T.Name, ImportType T.Name) convertImportNameTypeM (n, isrc) = do n' <- convertImportNameM n isrc' <- convertImportTypeM isrc return (n', isrc') -- | Convert an import spec. convertImportNameValueM :: (F.Name, ImportValue F.Name) -> ConvertM (T.Name, ImportValue T.Name) convertImportNameValueM (n, isrc) = do n' <- convertImportNameM n isrc' <- convertImportValueM isrc return (n', isrc') -- | Convert an imported name. -- These can be variable names for values, -- or variable or constructor names for type imports. convertImportNameM :: F.Name -> ConvertM T.Name convertImportNameM n = case n of F.NameVar str -> return $ T.NameVar str F.NameCon str -> return $ T.NameCon str _ -> throw $ ErrorInvalidBinder n -- | Convert an import source. convertImportTypeM :: ImportType F.Name -> ConvertM (ImportType T.Name) convertImportTypeM isrc = case isrc of ImportTypeAbstract t -> do t' <- convertType t return $ ImportTypeAbstract t' ImportTypeBoxed t -> do t' <- convertType t return $ ImportTypeBoxed t' -- | Convert an import value spec. convertImportValueM :: ImportValue F.Name -> ConvertM (ImportValue T.Name) convertImportValueM isrc = case isrc of ImportValueModule mn n t _ -> do n' <- convertName n t' <- convertType t return $ ImportValueModule mn n' t' Nothing ImportValueSea str t -> do t' <- convertType t return $ ImportValueSea str t'