module Language.ECMAScript3.Analysis.LabelSets
(annotateLabelSets
,Label(..)) where
import Language.ECMAScript3.Syntax
import Language.ECMAScript3.Syntax.Annotations
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Generics.Uniplate.Data
import Data.Data (Data)
import Control.Applicative
import Data.Typeable (Typeable)
data Label = Label String
| EmptyLabel
deriving (Ord, Eq, Show, Data, Typeable)
annotateLabelSets :: Data a =>
(a -> Set Label)
-> (Set Label -> a -> a)
-> JavaScript a
-> JavaScript a
annotateLabelSets r w = transformBi (annotateFuncStmtBodies r w)
. transformBi (annotateFuncExprBodies r w)
. descendBi (annotateStatement r w)
annotateFuncStmtBodies :: Data a =>
(a -> Set Label)
-> (Set Label -> a -> a)
-> Statement a
-> Statement a
annotateFuncStmtBodies r w s = case s of
FunctionStmt a name params body ->
let newbody = map (descend (annotateStatement r w)) body
in FunctionStmt a name params newbody
_ -> s
annotateFuncExprBodies :: Data a =>
(a -> Set Label)
-> (Set Label -> a -> a)
-> Expression a
-> Expression a
annotateFuncExprBodies r w e = case e of
FuncExpr a mname params body ->
let newbody = map (descend (annotateStatement r w)) body
in FuncExpr a mname params newbody
_ -> e
annotateStatement :: Data a =>
(a -> Set Label)
-> (Set Label -> a -> a)
-> Statement a
-> Statement a
annotateStatement r w s = case s of
LabelledStmt ann lab stmt ->
let labelset = Set.insert (id2Label lab) (r ann)
newstmt = annotateStatement r w $ w labelset <$> stmt
in LabelledStmt ann lab newstmt
SwitchStmt {} ->
let labelset = Set.insert EmptyLabel (r $ getAnnotation s)
in descend (annotateStatement r w) (w labelset <$> s)
_ | isIterationStmt s ->
let labelset = Set.insert EmptyLabel (r $ getAnnotation s)
in descend (annotateStatement r w) (w labelset <$> s)
_ -> descend (annotateStatement r w) s
id2Label :: Id a -> Label
id2Label = Label . unId