packages feed

hugs2yc-0.1: Yhc/Core/FrontEnd/Hugs/LinkUtil.hs

-- Linker utility functions for Hugs Core

module Yhc.Core.FrontEnd.Hugs.LinkUtil where

import Control.Monad
import Data.Maybe
import Yhc.Core.Extra
import qualified Data.Set as S
import qualified Data.Map as M
import qualified Data.List as L
import Yhc.Core.FrontEnd.Hugs.ParseUtil (nameGen)
import Yhc.Core.FrontEnd.Hugs.PrimTable (hugsPrimTable)

import Debug.Trace

-- Taken from Yhc Linker

mergeCores :: String -> [Core] -> Core
mergeCores modname cores = Core modname [] (concat datas) (concat funcs)
    where (datas,funcs) = unzip $ map (\x -> (coreDatas x, coreFuncs x)) cores

-- Fix core by deriving some missing objects such as tuple constructors,
-- or some other known constructors and functions.

fixCore :: Core -> Core

fixCore c = 
  let urd = coreUnreachableDatas c 
      c' = fixDatas urd c
      urf = coreUnreachableFuncs c'
  in  fixFuncs urf c' where
  fixFuncs _ c = c
  fixDatas mcs c = foldl fixOneData c mcs where
    isTuple ('H':'u':'g':'s':'.':'P':'r':'e':'l':'u':'d':'e':';':'(' : rtpl)
      | all (== ',') ((reverse . tail . reverse) rtpl) = length rtpl
    isTuple _ = 0
    fixOneData c tpl | isTuple tpl > 0 =
      let ntpl = isTuple tpl
          cargs = take ntpl nameGen
          tpldata = CoreData {
            coreDataName = tpl,
            coreDataTypes = [],
            coreDataCtors = [CoreCtor {
              coreCtorName = tpl,
              coreCtorFields = zip cargs (repeat Nothing)}]}
      in c {coreDatas = tpldata : coreDatas c,
            coreFuncs = coreFuncs c}
    fixOneData c _ = c

-- Convert cases with calls to PrimPmXXX to case with constant patterns.
-- Hugs generates:
-- case (Prelude;primPmInt Prelude;v30 0 _1) of
--   Prelude;True -> Prelude;v1489 0
--   _ -> foo
--
-- This has to be transformed to:
-- case _1 of
--   0 -> Prelude;v1489 0
--   _ -> foo
-- In this case, the first argument of primPmInt is a dictionary 
-- that would not be used under the new scheme. The second is
-- a constant to match, and the third is a variable to become
-- the case scrutinee variable under the new scheme.

pmfuns = map ("Prelude;primPm" ++) ["Int", "Integer", "Flt"]

fixCasePats :: Core -> Core

fixCasePats core = transformExpr (f core) core where
  f core (CoreCase (CoreApp (CoreFun pmfun) [_, CoreLit clit, cvar]) 
            [(PatCon "Prelude;True" [], exmat), d@(PatDefault, exdfl)]) 
              | pmfun `elem` pmfuns =
    CoreCase cvar [(PatLit clit, exmat), d]
  f _ x = x

-- Remap function names in the case Hugs defines them in an undesired way.
-- Basically, everything defined in Hugs.Prelude goes to Prelude.

mapFuns :: Core -> Core

mapFuns core = mapFunNames funmap core where
  funmap = M.fromList $ zip hpfuns pfuns
  hpfuns = filter toRemap allfuns
  allfuns = map coreFuncName $ coreFuncs core
  pfuns = map (("Prelude;" ++ ) . dropModule) hpfuns


-- Remap constructor names in the case Hugs defines them in an undesired way.
-- Basically, everything defined in Hugs.Prelude goes to Prelude.

mapCons :: Core -> Core

mapCons core = mapConNames ctormap core where
  ctormap = M.fromList $ zip hpctors pctors
  hpctors = filter toRemap allctors
  allctors = map coreCtorName $ concat $ map coreDataCtors $ coreDatas core
  pctors = map (("Prelude;" ++ ) . dropModule) hpctors

-- Remap data objects (LHS of data XXX) in the case Hugs defines them in an undesired way.
-- Basically, everything defined in Hugs.Prelude goes to Prelude.

mapDatas :: Core -> Core

mapDatas core = mapDataNames dtmap core where
  dtmap = M.fromList $ zip hpdatas pdatas
  hpdatas = filter toRemap alldatas
  alldatas = map coreDataName $ coreDatas core
  pdatas = map (("Prelude;" ++ ) . dropModule) hpdatas

-- Remap Hugs primitives into Yhc Core normal primitives.
-- The mapping table is in the Yhc.Core.FrontEnd.Hugs.PrimTable module.

mapPrims :: Core -> Core

mapPrims = mapFunNames (M.fromList hugsPrimTable)

-- Filter for function names to remap by mapFuns.

toRemap ('H':'u':'g':'s':'.':'P':'r':'e':'l':'u':'d':'e':';': _) = True
toRemap _ = False

-- Transform all calls to constructor lifting functions into
-- calls to conctructors themselves provided that call to the lifting
-- function was saturated.

unLiftCtors :: Core -> Core
unLiftCtors core = transformExpr (fx core) core where
  fx core ap@(CoreApp (CoreFun f) args) | coreSaturated core ap =
    fromMaybe ap $ do
      fdef <- coreFuncMaybe core f
      when (isCorePrim fdef) $ fail $ "unLiftCtors: primitive " ++ f
      let fbdy = coreFuncBody fdef
          fargs = coreFuncArgs fdef
      case fbdy of
        CoreApp cc@(CoreCon c) cargs
          | length fargs == length cargs &&
            all isCoreVar cargs &&
            all id (zipWith (==) (map CoreVar fargs) cargs) -> return $ CoreApp cc args
        _ -> return ap
  fx _ x = x