packages feed

INblobs-0.1.1: src/Functional/Language.hs

{-|
    Module      :  Functional.Language
    Copyright   :  (c) Miguel Vilaça 2007

    Maintainer  :  jmvilaca@di.uminho.pt
    Stability   :  experimental
    Portability :  portable


    Small Functional Language

-}
module Functional.Language where

import Data.List

import Common


type Variable = String

data CallBy = Value | Name | Need deriving (Eq, Show)

data FuncLang = Var Variable  -- 1 (precedences)
	      | Abst Variable FuncLang -- 7
	      | Appl FuncLang FuncLang -- 10
	      | TT -- 1
	      | FF -- 1
	      | IterBool FuncLang FuncLang FuncLang -- 5
	      | Zero -- 1
	      | Succ FuncLang -- 3
	      | IterNat Variable FuncLang FuncLang FuncLang -- 5
	      | Nil -- 1
	      | Cons FuncLang FuncLang -- 3
	      | IterList Variable Variable FuncLang FuncLang FuncLang -- 5
	      deriving (Eq)

-- | Default names and expressions for 'FuncLang' terms.
listLangConstructors :: [(String, FuncLang)]
listLangConstructors =
	[ ("Abstraction"  , Abst "x" (Var "t"))
	, ("Application"  , Appl (Var "t") (Var "u"))
	, ("True"	  , TT)
	, ("False"	  , FF)
	, ("If then else" , IterBool (Var "V") (Var "F") (Var "b"))
	, ("0"		  , Zero)
	, ("successor"	  , Succ (Var "t"))
	, ("Nat iterator" , IterNat "x" (Var "S") (Var "Z") (Var "t"))
	, ("[]"		  , Nil)
	, (":"		  , Cons (Var "H") (Var "T"))
	, ("List iterator", IterList "x" "y" (Var "C") (Var "N") (Var "t"))
	]

instance Show FuncLang where
 -- precedence 9 is a special one; means that it is inside an abstraction
 showsPrec 9 (Abst v t) =
		showChar ','
		. showString v
		. showsPrec 9 t
 showsPrec 9 x = showChar ']' . showsPrec 0 x
 showsPrec d (Abst v t) =
		showParen (d > 7) $
		showChar '['
		. showString v
		. showsPrec 9 t
 -- elements of precedence 1; those never surrounded by parenthesis
 showsPrec _ (Var x) = showString x
 showsPrec _ TT      = showString "tt"
 showsPrec _ FF      = showString "ff"
 showsPrec _ Zero    = showString "0"
 showsPrec _ Nil     = showString "nil"
 -- elements of precedence 3
 showsPrec _ (Succ n) =
		showString "suc("
		. showsPrec 0 n
		. showChar ')'
 showsPrec _ (Cons h t) =
		showString "cons("
		. showsPrec 0 h
		. showChar ','
		. showsPrec 0 t
		. showChar ')'
 -- elements of precedence 5
 showsPrec _ (IterBool v f b) =
		showString "iterbool("
		. showsPrec 0 v
		. showChar ','
		. showsPrec 0 f
		. showChar ','
		. showsPrec 0 b
		. showChar ')'
 showsPrec _ (IterNat x s z n) =
		showString "iternat("
		. showsPrec 0 (Abst x s)
		. showChar ','
		. showsPrec 0 z
		. showChar ','
		. showsPrec 0 n
		. showChar ')'
 showsPrec _ (IterList h t c n l) =
		showString "iterlist("
		. showsPrec 0 (Abst h $ Abst t c)
		. showChar ','
		. showsPrec 0 n
		. showChar ','
		. showsPrec 0 l
		. showChar ')'
 -- elements of precedence 10
 showsPrec d (Appl u v) =
		showParen (d > 10) $
		showsPrec 11 u
		. showChar ' '
		. showsPrec 11 v

-- | Show iter_TYPE symbols.
showAgent :: FuncLang -> String
showAgent t@(IterBool v f (Var ""))     = show t
showAgent t@(IterNat x s z (Var ""))    = show t
showAgent t@(IterList h r c n (Var "")) = show t
showAgent _ = error "unexpected functional term here"

cata :: (Variable -> r) -- ^ Var
     -> (Variable -> r -> r) -- ^ Abstraction
     -> (r -> r -> r) -- ^ Application
     -> r -- ^ True
     -> r -- ^ False
     -> (r -> r -> r -> r) -- ^ IterBool
     -> r -- ^ Zero
     -> (r -> r) -- ^ Succ
     -> (Variable -> r -> r -> r -> r) -- ^ IterNat
     -> r -- ^ Nil
     -> (r -> r -> r) -- ^ Cons
     -> (Variable -> Variable -> r -> r -> r -> r) -- ^ IterList
     -> FuncLang -- ^ term
     -> r -- ^ result
cata fVar fAbst fAppl fTT fFF fIB fZ fS fIN fN fC fIL = cata'
 where cata' term =
	    case term of
	Var var 		    -> fVar var
	Abst var t 		    -> fAbst var (cata' t)
	Appl t1 t2 		    -> fAppl (cata' t1) (cata' t2)
	TT 			    -> fTT
	FF 			    -> fFF
	IterBool t1 t2 t3 	    -> fIB (cata' t1) (cata' t2) (cata' t3)
	Zero 			    -> fZ
	Succ t 			    -> fS (cata' t)
	IterNat var t1 t2 t3 	    -> fIN var (cata' t1) (cata' t2) (cata' t3)
	Nil 			    -> fN
	Cons t1 t2 		    -> fC (cata' t1) (cata' t2)
	IterList var1 var2 t1 t2 t3 -> fIL var1 var2 (cata' t1) (cata' t2) (cata' t3)

-- | Dummy variable
eVar = Var ""

-- | Collect all the symbols in a term.
-- The possible symbols are:
--   *  @ IterBool t1 t2 (Var \"\") @
--   *  @ IterNat v t1 t2 (Var \"\") @
--   *  @ IterList v1 v2 t1 t2 (Var \"\") @
listIteratorSymbols,listSymbs :: FuncLang -> [FuncLang]
listIteratorSymbols = listSymbs

listSymbs term =
    case term of
	Var _var 		    -> []
	Abst _var t 		    -> listSymbs t
	Appl t1 t2 		    -> (listSymbs t1) `join` (listSymbs t2)
	TT 			    -> []
	FF 			    -> []
	IterBool t1 t2 t3 	    -> [IterBool t1 t2 eVar] `join` (listSymbs t1) `join` (listSymbs t2) `join` (listSymbs t3)
	Zero 			    -> []
	Succ t 			    -> listSymbs t
	IterNat var t1 t2 t3 	    -> [IterNat var t1 t2 eVar] `join` (listSymbs t1) `join` (listSymbs t2) `join` (listSymbs t3)
	Nil 			    -> []
	Cons t1 t2 		    -> (listSymbs t1) `join` (listSymbs t2)
	IterList var1 var2 t1 t2 t3 -> [IterList var1 var2 t1 t2 eVar] `join` (listSymbs t1) `join` (listSymbs t2) `join` (listSymbs t3)
  where join = union

-- | Give some sequential names to symbols.
giveNames :: [FuncLang] -> [(FuncLang, String)]
giveNames = snd . mapAccumL f 1
  where f acc x = (acc+1,(x,"Iter_" ++ show acc))


-- | List the free variables of a term; the result is a set.
freeVars :: FuncLang -> [String]
freeVars = cata singleton delete union [] [] fIB [] id fIN [] union fIL
  where
	fIB r1 r2 r3 = r1 `union` r2 `union` r3
	fIN v r1 r2 r3 = (delete v r1) `union` r2 `union` r3
	fIL x y r1 r2 r3 = ( r1\\[x,y] ) `union` r2 `union` r3

-- | Special lookup function for iterators with an equality.
lookupIterName :: FuncLang -> [(FuncLang, String)] -> Maybe String
lookupIterName term [] = Nothing
lookupIterName term ((term2,str):xs) | term `equal` term2 = Just str
				     | otherwise = lookupIterName term xs
  where
	equal :: FuncLang -> FuncLang -> Bool
	equal (IterBool v1 f1 _) (IterBool v2 f2 _) = v1==v2 && f1==f2
	equal (IterNat x1 s1 z1 _) (IterNat x2 s2 z2 _) = x1==x2 && s1==s2 && z1==z2
	equal (IterList x1 y1 c1 n1 _) (IterList x2 y2 c2 n2 _) = x1==x2 && y1==y2 && c1==c2 && n1==n2
	equal _ _ = False