1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
{-
Kaya - My favourite toy language.
Copyright (C) 2004, 2005 Edwin Brady
This file is distributed under the terms of the GNU General
Public Licence. See COPYING for licence.
-}
module PureFun where
-- Detects pure functions (i.e., those with no side effects)
import Language
-- Update a program with purity information
findPure :: Program -> Program
findPure xs = fp [] xs
where fp acc [] = acc
fp acc ((FunBind (f,l,n,ty,opt,Defined exp) doc ority):xs)
| not (elem Pure opt) && (isPure exp n (numargs ty) acc) =
fp (acc++[FunBind (f,l,n,ty,Pure:opt,Defined exp) doc ority]) xs
fp acc (x:xs) = fp (acc++[x]) xs
-- Checks if the given expression, with number of arguments <args>
-- is pure, in the context <ctx>
isPure :: Expr Name -> Name -> Int -> Program -> Bool
isPure def fn args ctx = foldsubexpr pfn (&&) True def
where pfn (GVar _) = False
pfn (Foreign _ _ _) = False
pfn (Global n _ _) | n/=fn = lookupPure n ctx
pfn (Assign a e) = (assignPure a) && (pfn e)
pfn x = isPure x fn args ctx
lookupPure n [] = False
lookupPure n ((FunBind (_,_,fn,_,fopts,_) _ _):xs)
| n == fn = elem Pure fopts
lookupPure n (_:xs) = lookupPure n xs
assignPure (AIndex a e) = assignPure a && (pfn e)
assignPure (AField a n i j) = assignPure a
assignPure (AName x) = x>=args -- assigning to an argument is impire
assignPure (AGlob x) = False
|