packages feed

alpha-1.0.11: src/Context/Language.hs

{-# LANGUAGE NoMonomorphismRestriction, FlexibleContexts #-}

module Context.Language where

import Context.Types as C
import Control.Monad.Trans
import Data.Maybe
import Data.Monoid
import ID
import My.Control.Monad
import My.Control.Monad.State
import My.Data.List
import My.Prelude
import PCode
import Translate
import qualified Data.Bimap as BM
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.Traversable as T

showTable name showLine contents = (name++":"):map ("  "++) (concatMap showLine contents)
instance Show Language where
  show e = intercalate "\n" $ showTable "Context" id [
    ["Max ID: "++show (maxIDL e)],
    showTable "Symbols" (\(s,i) -> [s++" -> "++show i]) $ BM.toList (symbolsL e),
    showTable "Aliases" (\(i,i') -> [show i++" -> "++show i']) $ M.toList (aliasesL e),
    showTable "Equivs" (\(i,i') -> [show i++" -> "++show i']) $ M.toList (equivsL e),
    showTable "Modules" (\(s,Range r) -> [s++" -> "++show r]) $ BM.toList (languagesL e),
    showTable "Values" (\(i,v) -> [show i++" -> "++show v]) $ M.toList (valuesL e),
    ["Exports: "++show (exportsL e)]]

translateInit init l' l = translate (translateFromSub l' l) init
translateFromSub l' l = \s' -> fromMaybe (tr s') $ M.lookup (tr s') (aliasesL l)
  where tr s' = fromMaybe (s' + mi) $ do
          m <- lookupSymMod s' l'
          Range (r,_) <- BM.lookup m (languagesL l)
          Range (r',_) <- BM.lookup m (languagesL l')
          return $ s'-r'+r
        Range (mi,_) = languagesL l BM.! nameL l'
instance Monoid Language where
  mempty = Language undefined (toEnum 0) BM.empty M.empty M.empty BM.empty M.empty S.empty
  mappend l l' = flip execState l $ do
    mapM_ (state . internSym) $ BM.keys (symbolsL l')
    modify $ \l ->
      let aliases = [(i'+mi,symbolsL l BM.! s') 
                    | (s',i') <- BM.toList (symbolsL l')]
          mi = maxIDL l ; nmi = mi + maxIDL l'
      in l { maxIDL = nmi,
             aliasesL = aliasesL l `M.union` M.fromList aliases,
             equivsL = equivsL l `M.union` M.fromList (map swap aliases),
             languagesL = BM.insert (nameL l') (Range (mi,nmi)) (languagesL l) }
    modify $ \l ->
      let newVals = M.mapKeys tr $ M.map (translate tr) $ valuesL l'
          tr = translateFromSub l' l
      in l { valuesL    = M.unionWith (\_ a -> a) (valuesL l) newVals,
             exportsL   = exportsL l S.\\ M.keysSet newVals }

createSym l@(Language { maxIDL = m }) = (m,l { maxIDL = succ m })

lookupSymName sym l = BM.lookupR sym (symbolsL l)
lookupSymVal sym l  = fromMaybe NoValue $ M.lookup sym (valuesL l) 
lookupSymMod sym l  = BM.lookupR (singleRange sym) (languagesL l) 

addExport sym l = l { exportsL = S.insert sym (exportsL l) }

getImports l  = map fst $ BM.toList $ languagesL l
isImport im l = BM.member im (languagesL l)

setSymVal sym v l  = l { valuesL = M.insert sym v (valuesL l) }
exportSymVal sym v = setSymVal sym v . addExport sym

internSym s l = runState (st $ BM.lookup s (symbolsL l)) l 
  where st (Just id) = return id
        st _ = do
          i <- state createSym 
          modifying syms_ (BM.insert s i)  
          return i

envCast t = T.mapM (state . intern) t
  where intern "?" = createSym
        intern str = internSym str

set2Map s = M.fromAscList (zip (S.toAscList s) (repeat undefined))
purgeLanguage l = mempty {
  maxIDL     = maxIDL l,
  symbolsL   = BM.filter exportNameP (symbolsL l),
  languagesL = languagesL l,
  valuesL    = vals'
  }
  where Language { exportsL = ex, equivsL = eqs } = l
        vals' = M.map (translate $ mapTranslate eqs) $ M.intersection (valuesL l) (set2Map ex)
        refs = S.fromList $ concatMap references (M.elems vals')
        exportNameP _ s = (S.member s ex || S.member s refs) && not (M.member s eqs)