{-# LANGUAGE DeriveDataTypeable #-} module Agda.Compiler.JS.Syntax where import Data.Map ( Map ) import qualified Data.Map as Map import Data.Set ( Set, empty, singleton, union ) import Agda.Syntax.Common ( Nat ) -- An untyped lambda calculus with records, -- and a special self-binder for recursive declarations data Exp = Self | Local LocalId | Global GlobalId | Undefined | String String | Char Char | Integer Integer | Double Double | Lambda Nat Exp | Object (Map MemberId Exp) | Apply Exp [Exp] | Lookup Exp MemberId | If Exp Exp Exp | BinOp Exp String Exp | PreOp String Exp | Const String | PlainJS String -- ^ Arbitrary JS code. deriving Show -- Local identifiers are named by De Bruijn indices. -- Global identifiers are named by string lists. -- Object members are named by strings. newtype LocalId = LocalId Nat deriving (Eq, Ord, Show) newtype GlobalId = GlobalId [String] deriving (Eq, Ord, Show) newtype MemberId = MemberId String deriving (Eq, Ord, Show) -- The top-level compilation unit is a module, which names -- the GId of its exports, and a list of definitions data Export = Export { expName :: [MemberId], defn :: Exp } deriving Show data Module = Module { modName :: GlobalId, exports :: [Export], postscript :: Maybe Exp } deriving Show -- Note that modules are allowed to be recursive, via the Self expression, -- which is bound to the exported module. -- Top-level uses of the form exports.l1....lN. class Uses a where uses :: a -> Set [MemberId] instance Uses a => Uses [a] where uses = foldr (union . uses) empty instance Uses a => Uses (Map k a) where uses = Map.foldr (union . uses) empty instance Uses Exp where uses (Object o) = Map.foldr (union . uses) empty o uses (Apply e es) = foldr (union . uses) (uses e) es uses (Lookup e l) = uses' e [l] where uses' Self ls = singleton ls uses' (Lookup e l) ls = uses' e (l : ls) uses' e ls = uses e uses (If e f g) = uses e `union` uses f `union` uses g uses (BinOp e op f) = uses e `union` uses f uses (PreOp op e) = uses e uses e = empty instance Uses Export where uses (Export _ e) = uses e -- All global ids class Globals a where globals :: a -> Set GlobalId instance Globals a => Globals [a] where globals = foldr (union . globals) empty instance Globals a => Globals (Map k a) where globals = Map.foldr (union . globals) empty instance Globals Exp where globals (Global i) = singleton i globals (Lambda n e) = globals e globals (Object o) = globals o globals (Apply e es) = globals e `union` globals es globals (Lookup e l) = globals e globals (If e f g) = globals e `union` globals f `union` globals g globals (BinOp e op f) = globals e `union` globals f globals (PreOp op e) = globals e globals _ = empty instance Globals Export where globals (Export _ e) = globals e instance Globals Module where globals (Module m es _) = globals es