packages feed

cnc-spec-compiler-0.2.0.0: Intel/Cnc/Spec/TagFun.hs

{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables  #-}
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}

-- This file should contain everything having to do with the structure
-- and analysis of tag functions.

----------------------------------------------------------------------------------------------------
module Intel.Cnc.Spec.TagFun where 

import StringTable.Atom
import Data.Data
import Data.Char
import Text.PrettyPrint.HughesPJClass
import Intel.Cnc.Spec.Util
import Intel.Cnc.Spec.SrcLoc
import Intel.Cnc.Spec.AST

------------------------------------------------------------
-- Type definition.
------------------------------------------------------------
-- Tag expressions are distinct from Exp (in AST.hs) and much more
-- restrictive.  (For example, conditionals are not allowed.)

-- Tag expressions are parameterized by the type of variable references.
data TagExp var = 
   TEVar var
 | TEInt Int -- Is there any conceivable need for arbitrary precision here?
 | TEApp Atom [TagExp var]

-- TODO: Add optionality (maybe) to tag functions.
-- TODO: Possible adapt tag functions to return sets of tags.
 deriving (Eq,Ord,Show,Data,Typeable)

------------------------------------------------------------
-- Instances.
------------------------------------------------------------

instance Pretty var => Pretty (TagExp var) where 
  pPrint te =  case te of
    TEVar v  -> pPrint v
    TEInt n  -> text (show n)
    TEApp rat rands -> 
     case rands of 
       [left,right] | not $ isAlpha (head (fromAtom rat)) -> 
     	     parens (pp left <+> text (fromAtom rat) <+> pp right)
       _ ->  text (fromAtom rat) <> (parens $ commasep rands)

-- A tag function of dimension N has N formal parameters and N "bodies".
data TagFun = TF [Atom] [TagExp Atom]
  deriving (Eq, Ord)

instance Pretty TagFun where 
  pPrint (TF formals bods) =
    text "\\" <> hsep (map (text . fromAtom) formals) <+> text "->" <+> 
    commacat bods

-- Again, might as well use the pretty version
instance Show TagFun where 
  show = show . pp

instance Functor TagExp where
  fmap f (TEVar v) = TEVar (f v)
  fmap _ (TEInt i) = TEInt i 
  fmap f (TEApp op ls) = TEApp op $ map (fmap f) ls


------------------------------------------------------------
-- API for tag functions.
------------------------------------------------------------

-- The left argument is the "formal parameter" and the right argument the "body".
-- But really it's just an equality.
-- Note, the reason these are Exp LISTS is because these are implicitly tuples.
-- The tag functions are multi-dimensional.
--
-- TODO: This function could solve simple equations to get the formal
-- parameters all to one side of the equation, allowing things like (2*i -> 3*i).

--mkTagFun :: (CncGraphNode, [Exp SrcSpan]) -> 
--	    (CncGraphNode, [Exp SrcSpan]) -> Maybe TagFun
--mkTagFun (node1,exps1) (node2,exps2) = 
mkTagFun :: String -> [Exp SrcSpan] -> [Exp SrcSpan] -> Maybe TagFun
mkTagFun ctxtmsg exps1 exps2 = 
 let e1s = Prelude.map checkConvertTF exps1
     e2s = Prelude.map checkConvertTF exps2
 in if all isTEVar e1s
    then
         if not (Prelude.null exps1) && not (Prelude.null exps2)
	     -- length exps1 == length exps2 
         then Just (TF (Prelude.map unTEVar e1s) e2s)
	 -- Otherwise there is a mismatch in the number of tag components:
	 else if Prelude.null exps2 
	      then Nothing -- It's ok to simply leave off a tag function (but to have some var names on the step).
	      else error$ "ERROR:\n   It is not acceptable to use the following tag components without\n"++
		          "   tag components indexing the step: "
--		          "   the same number of corresponding tag components indexing the step: "
		          ++ (show$ pp exps2) ++ 
			  showSpanDetailed (foldl1 combineSrcSpans $ Prelude.map getDecor exps2)

    else error$ ctxtmsg ++ ": mkTagFun of  "++ (show$ pp exps1) ++ " and "++ show (pp exps2)++ 
		" - Presently the tag expressions indexing step collections must be simple variables." 


-- Substititution on tag expression's variables.
substTagExp :: Eq a => a -> a -> TagExp a -> TagExp a
substTagExp old new exp = 
  case exp of 
   TEVar v | v == old  -> TEVar new
	   | otherwise -> TEVar v
   TEInt i -> TEInt i
   TEApp op ls -> TEApp op $ map (substTagExp old new) ls


-- Create a C++ expression that represents the application of the tag function.
-- TODO: Generalize this.
applyTagFun :: TagFun -> Doc -> [Doc]
applyTagFun (TF [formal] [body]) arg =
  [pPrint$ substTagExp formal (toAtom$ render arg) body]

applyTagFun _ _ = error "TODO: applyTagFun implement multidimensional"

isTEVar (TEVar _) = True
isTEVar _ = False

-- Avoid exhaustiveness warnings here:
unTEVar (TEVar name) = name
unTEVar _ = error "unTEVar: not TEVar"

-- This is where we convert arbitrary Exps into more restricted tag expressions that
-- support symbolic manipulation.
checkConvertTF e = 
  case e of 
    Lit s l -> case l of 
	         LitInt i -> TEInt i; 
		 _ -> locErr s "Only integer literals supported in tag functions presently."
    Var s name -> TEVar name 
    App _ (Var _ name) rands -> TEApp name (Prelude.map checkConvertTF rands)
    App s _ _  -> locErr s "Only very simple function applications allowed in tag functions presently."
    If s _ _ _ -> locErr s "Conditionals disallowed in tag functions."

-- | Compute the getcount contribution of a single tag function.
getCountTF :: TagFun -> Maybe Int
getCountTF (TF formals body) = 
  case body of
   -- UNFINISHED
    _ -> Nothing
 where