summaryrefslogtreecommitdiff
path: root/compiler/GHC/JS/Syntax.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/JS/Syntax.hs')
-rw-r--r--compiler/GHC/JS/Syntax.hs275
1 files changed, 119 insertions, 156 deletions
diff --git a/compiler/GHC/JS/Syntax.hs b/compiler/GHC/JS/Syntax.hs
index 66067ced9e..0b8a6c05b2 100644
--- a/compiler/GHC/JS/Syntax.hs
+++ b/compiler/GHC/JS/Syntax.hs
@@ -48,92 +48,60 @@
-- GHC.StgToJS.\*. Please see 'GHC.JS.Make' for a module which provides
-- helper functions that use the deeply embedded DSL defined in this module
-- to provide some of the benefits of a shallow embedding.
+--
-----------------------------------------------------------------------------
+
module GHC.JS.Syntax
( -- * Deeply embedded JS datatypes
JStat(..)
, JExpr(..)
, JVal(..)
- , JOp(..)
- , JUOp(..)
+ , Op(..)
+ , UOp(..)
, Ident(..)
- , identFS
- , JsLabel
+ , JLabel
-- * pattern synonyms over JS operators
- , pattern New
- , pattern Not
- , pattern Negate
- , pattern Add
- , pattern Sub
- , pattern Mul
- , pattern Div
- , pattern Mod
- , pattern BOr
- , pattern BAnd
- , pattern BXor
- , pattern BNot
- , pattern LOr
- , pattern LAnd
- , pattern Int
- , pattern String
- , pattern PreInc
- , pattern PostInc
- , pattern PreDec
- , pattern PostDec
- -- * Ident supply
- , IdentSupply(..)
- , newIdentSupply
- , pseudoSaturate
+ , pattern JNew
+ , pattern JNot
+ , pattern JNegate
+ , pattern JAdd
+ , pattern JSub
+ , pattern JMul
+ , pattern JDiv
+ , pattern JMod
+ , pattern JBOr
+ , pattern JBAnd
+ , pattern JBXor
+ , pattern JBNot
+ , pattern JLOr
+ , pattern JLAnd
+ , pattern SatInt
+ , pattern JString
+ , pattern JPreInc
+ , pattern JPostInc
+ , pattern JPreDec
+ , pattern JPostDec
-- * Utility
, SaneDouble(..)
+ , jassignAll
+ , jassignAllEqual
+ , jvar
) where
import GHC.Prelude
+import GHC.JS.Unsat.Syntax (Ident(..))
+import GHC.Data.FastString
+import GHC.Types.Unique.Map
+import GHC.Utils.Misc
+
import Control.DeepSeq
-import Data.Function
import Data.Data
-import Data.Word
import qualified Data.Semigroup as Semigroup
import GHC.Generics
-import GHC.Data.FastString
-import GHC.Utils.Monad.State.Strict
-import GHC.Types.Unique
-import GHC.Types.Unique.Map
-
--- | A supply of identifiers, possibly empty
-newtype IdentSupply a
- = IS {runIdentSupply :: State [Ident] a}
- deriving Typeable
-
-instance NFData (IdentSupply a) where rnf IS{} = ()
-
-inIdentSupply :: (State [Ident] a -> State [Ident] b) -> IdentSupply a -> IdentSupply b
-inIdentSupply f x = IS $ f (runIdentSupply x)
-
-instance Functor IdentSupply where
- fmap f x = inIdentSupply (fmap f) x
-
-newIdentSupply :: Maybe FastString -> [Ident]
-newIdentSupply Nothing = newIdentSupply (Just "jmId")
-newIdentSupply (Just pfx) = [ TxtI (mconcat [pfx,"_",mkFastString (show x)])
- | x <- [(0::Word64)..]
- ]
-
--- | Given a Pseudo-saturate a value with garbage @<<unsatId>>@ identifiers.
-pseudoSaturate :: IdentSupply a -> a
-pseudoSaturate x = evalState (runIdentSupply x) $ newIdentSupply (Just "<<unsatId>>")
-
-instance Eq a => Eq (IdentSupply a) where
- (==) = (==) `on` pseudoSaturate
-instance Ord a => Ord (IdentSupply a) where
- compare = compare `on` pseudoSaturate
-instance Show a => Show (IdentSupply a) where
- show x = "(" ++ show (pseudoSaturate x) ++ ")"
-
--------------------------------------------------------------------------------
-- Statements
@@ -142,26 +110,25 @@ instance Show a => Show (IdentSupply a) where
-- Reference](https://tc39.es/ecma262/#sec-ecmascript-language-statements-and-declarations)
-- for details
data JStat
- = DeclStat !Ident !(Maybe JExpr) -- ^ Variable declarations: var foo [= e]
- | ReturnStat JExpr -- ^ Return
- | IfStat JExpr JStat JStat -- ^ If
- | WhileStat Bool JExpr JStat -- ^ While, bool is "do" when True
- | ForInStat Bool Ident JExpr JStat -- ^ For-in, bool is "each' when True
+ = DeclStat !Ident !(Maybe JExpr) -- ^ Variable declarations: var foo [= e]
+ | ReturnStat JExpr -- ^ Return
+ | IfStat JExpr JStat JStat -- ^ If
+ | WhileStat Bool JExpr JStat -- ^ While, bool is "do" when True
+ | ForInStat Bool Ident JExpr JStat -- ^ For-in, bool is "each' when True
| SwitchStat JExpr [(JExpr, JStat)] JStat -- ^ Switch
- | TryStat JStat Ident JStat JStat -- ^ Try
- | BlockStat [JStat] -- ^ Blocks
- | ApplStat JExpr [JExpr] -- ^ Application
- | UOpStat JUOp JExpr -- ^ Unary operators
- | AssignStat JExpr JExpr -- ^ Binding form: @foo = bar@
- | UnsatBlock (IdentSupply JStat) -- ^ /Unsaturated/ blocks see 'pseudoSaturate'
- | LabelStat JsLabel JStat -- ^ Statement Labels, makes me nostalgic for qbasic
- | BreakStat (Maybe JsLabel) -- ^ Break
- | ContinueStat (Maybe JsLabel) -- ^ Continue
+ | TryStat JStat Ident JStat JStat -- ^ Try
+ | BlockStat [JStat] -- ^ Blocks
+ | ApplStat JExpr [JExpr] -- ^ Application
+ | UOpStat UOp JExpr -- ^ Unary operators
+ | AssignStat JExpr JExpr -- ^ Binding form: @foo = bar@
+ | LabelStat JLabel JStat -- ^ Statement Labels, makes me nostalgic for qbasic
+ | BreakStat (Maybe JLabel) -- ^ Break
+ | ContinueStat (Maybe JLabel) -- ^ Continue
deriving (Eq, Typeable, Generic)
-- | A Label used for 'JStat', specifically 'BreakStat', 'ContinueStat' and of
-- course 'LabelStat'
-type JsLabel = LexicalFastString
+type JLabel = LexicalFastString
instance Semigroup JStat where
(<>) = appendJStat
@@ -178,10 +145,10 @@ appendJStat :: JStat -> JStat -> JStat
appendJStat mx my = case (mx,my) of
(BlockStat [] , y ) -> y
(x , BlockStat []) -> x
- (BlockStat xs , BlockStat ys) -> BlockStat $ xs ++ ys
- (BlockStat xs , ys ) -> BlockStat $ xs ++ [ys]
- (xs , BlockStat ys) -> BlockStat $ xs : ys
- (xs , ys ) -> BlockStat [xs,ys]
+ (BlockStat xs , BlockStat ys) -> BlockStat $! xs ++ ys
+ (BlockStat xs , ys ) -> BlockStat $! xs ++ [ys]
+ (xs , BlockStat ys) -> BlockStat $! xs : ys
+ (xs , ys ) -> BlockStat [xs,ys]
--------------------------------------------------------------------------------
@@ -189,16 +156,13 @@ appendJStat mx my = case (mx,my) of
--------------------------------------------------------------------------------
-- | JavaScript Expressions
data JExpr
- = ValExpr JVal -- ^ All values are trivially expressions
- | SelExpr JExpr Ident -- ^ Selection: Obj.foo, see 'GHC.JS.Make..^'
+ = ValExpr JVal -- ^ All values are trivially expressions
+ | SelExpr JExpr Ident -- ^ Selection: Obj.foo, see 'GHC.JS.Make..^'
| IdxExpr JExpr JExpr -- ^ Indexing: Obj[foo], see 'GHC.JS.Make..!'
- | InfixExpr JOp JExpr JExpr -- ^ Infix Expressions, see 'JExpr'
- -- pattern synonyms
- | UOpExpr JUOp JExpr -- ^ Unary Expressions
- | IfExpr JExpr JExpr JExpr -- ^ If-expression
+ | InfixExpr Op JExpr JExpr -- ^ Infix Expressions, see 'JExpr' pattern synonyms
+ | UOpExpr UOp JExpr -- ^ Unary Expressions
+ | IfExpr JExpr JExpr JExpr -- ^ If-expression
| ApplExpr JExpr [JExpr] -- ^ Application
- | UnsatExpr (IdentSupply JExpr) -- ^ An /Unsaturated/ expression.
- -- See 'pseudoSaturate'
deriving (Eq, Typeable, Generic)
-- * Useful pattern synonyms to ease programming with the deeply embedded JS
@@ -207,110 +171,110 @@ data JExpr
-- and Integer literals.
-- | pattern synonym for a unary operator new
-pattern New :: JExpr -> JExpr
-pattern New x = UOpExpr NewOp x
+pattern JNew :: JExpr -> JExpr
+pattern JNew x = UOpExpr NewOp x
-- | pattern synonym for prefix increment @++x@
-pattern PreInc :: JExpr -> JExpr
-pattern PreInc x = UOpExpr PreIncOp x
+pattern JPreInc :: JExpr -> JExpr
+pattern JPreInc x = UOpExpr PreIncOp x
-- | pattern synonym for postfix increment @x++@
-pattern PostInc :: JExpr -> JExpr
-pattern PostInc x = UOpExpr PostIncOp x
+pattern JPostInc :: JExpr -> JExpr
+pattern JPostInc x = UOpExpr PostIncOp x
-- | pattern synonym for prefix decrement @--x@
-pattern PreDec :: JExpr -> JExpr
-pattern PreDec x = UOpExpr PreDecOp x
+pattern JPreDec :: JExpr -> JExpr
+pattern JPreDec x = UOpExpr PreDecOp x
-- | pattern synonym for postfix decrement @--x@
-pattern PostDec :: JExpr -> JExpr
-pattern PostDec x = UOpExpr PostDecOp x
+pattern JPostDec :: JExpr -> JExpr
+pattern JPostDec x = UOpExpr PostDecOp x
-- | pattern synonym for logical not @!@
-pattern Not :: JExpr -> JExpr
-pattern Not x = UOpExpr NotOp x
+pattern JNot :: JExpr -> JExpr
+pattern JNot x = UOpExpr NotOp x
-- | pattern synonym for unary negation @-@
-pattern Negate :: JExpr -> JExpr
-pattern Negate x = UOpExpr NegOp x
+pattern JNegate :: JExpr -> JExpr
+pattern JNegate x = UOpExpr NegOp x
-- | pattern synonym for addition @+@
-pattern Add :: JExpr -> JExpr -> JExpr
-pattern Add x y = InfixExpr AddOp x y
+pattern JAdd :: JExpr -> JExpr -> JExpr
+pattern JAdd x y = InfixExpr AddOp x y
-- | pattern synonym for subtraction @-@
-pattern Sub :: JExpr -> JExpr -> JExpr
-pattern Sub x y = InfixExpr SubOp x y
+pattern JSub :: JExpr -> JExpr -> JExpr
+pattern JSub x y = InfixExpr SubOp x y
-- | pattern synonym for multiplication @*@
-pattern Mul :: JExpr -> JExpr -> JExpr
-pattern Mul x y = InfixExpr MulOp x y
+pattern JMul :: JExpr -> JExpr -> JExpr
+pattern JMul x y = InfixExpr MulOp x y
-- | pattern synonym for division @*@
-pattern Div :: JExpr -> JExpr -> JExpr
-pattern Div x y = InfixExpr DivOp x y
+pattern JDiv :: JExpr -> JExpr -> JExpr
+pattern JDiv x y = InfixExpr DivOp x y
-- | pattern synonym for remainder @%@
-pattern Mod :: JExpr -> JExpr -> JExpr
-pattern Mod x y = InfixExpr ModOp x y
+pattern JMod :: JExpr -> JExpr -> JExpr
+pattern JMod x y = InfixExpr ModOp x y
-- | pattern synonym for Bitwise Or @|@
-pattern BOr :: JExpr -> JExpr -> JExpr
-pattern BOr x y = InfixExpr BOrOp x y
+pattern JBOr :: JExpr -> JExpr -> JExpr
+pattern JBOr x y = InfixExpr BOrOp x y
-- | pattern synonym for Bitwise And @&@
-pattern BAnd :: JExpr -> JExpr -> JExpr
-pattern BAnd x y = InfixExpr BAndOp x y
+pattern JBAnd :: JExpr -> JExpr -> JExpr
+pattern JBAnd x y = InfixExpr BAndOp x y
-- | pattern synonym for Bitwise XOr @^@
-pattern BXor :: JExpr -> JExpr -> JExpr
-pattern BXor x y = InfixExpr BXorOp x y
+pattern JBXor :: JExpr -> JExpr -> JExpr
+pattern JBXor x y = InfixExpr BXorOp x y
-- | pattern synonym for Bitwise Not @~@
-pattern BNot :: JExpr -> JExpr
-pattern BNot x = UOpExpr BNotOp x
+pattern JBNot :: JExpr -> JExpr
+pattern JBNot x = UOpExpr BNotOp x
-- | pattern synonym for logical Or @||@
-pattern LOr :: JExpr -> JExpr -> JExpr
-pattern LOr x y = InfixExpr LOrOp x y
+pattern JLOr :: JExpr -> JExpr -> JExpr
+pattern JLOr x y = InfixExpr LOrOp x y
-- | pattern synonym for logical And @&&@
-pattern LAnd :: JExpr -> JExpr -> JExpr
-pattern LAnd x y = InfixExpr LAndOp x y
-
+pattern JLAnd :: JExpr -> JExpr -> JExpr
+pattern JLAnd x y = InfixExpr LAndOp x y
-- | pattern synonym to create integer values
-pattern Int :: Integer -> JExpr
-pattern Int x = ValExpr (JInt x)
+pattern SatInt :: Integer -> JExpr
+pattern SatInt x = ValExpr (JInt x)
-- | pattern synonym to create string values
-pattern String :: FastString -> JExpr
-pattern String x = ValExpr (JStr x)
+pattern JString :: FastString -> JExpr
+pattern JString x = ValExpr (JStr x)
--------------------------------------------------------------------------------
-- Values
--------------------------------------------------------------------------------
+
-- | JavaScript values
data JVal
- = JVar Ident -- ^ A variable reference
- | JList [JExpr] -- ^ A JavaScript list, or what JS
- -- calls an Array
- | JDouble SaneDouble -- ^ A Double
- | JInt Integer -- ^ A BigInt
- | JStr FastString -- ^ A String
- | JRegEx FastString -- ^ A Regex
+ = JVar Ident -- ^ A variable reference
+ | JList [JExpr] -- ^ A JavaScript list, or what JS calls an Array
+ | JDouble SaneDouble -- ^ A Double
+ | JInt Integer -- ^ A BigInt
+ | JStr FastString -- ^ A String
+ | JRegEx FastString -- ^ A Regex
| JHash (UniqMap FastString JExpr) -- ^ A JS HashMap: @{"foo": 0}@
- | JFunc [Ident] JStat -- ^ A function
- | UnsatVal (IdentSupply JVal) -- ^ An /Unsaturated/ value, see 'pseudoSaturate'
+ | JFunc [Ident] JStat -- ^ A function
deriving (Eq, Typeable, Generic)
+
--------------------------------------------------------------------------------
-- Operators
--------------------------------------------------------------------------------
+
-- | JS Binary Operators. We do not deeply embed the comma operator and the
-- assignment operators
-data JOp
+data Op
= EqOp -- ^ Equality: `==`
| StrictEqOp -- ^ Strict Equality: `===`
| NeqOp -- ^ InEquality: `!=`
@@ -336,10 +300,10 @@ data JOp
| InOp -- ^ @in@
deriving (Show, Eq, Ord, Enum, Data, Typeable, Generic)
-instance NFData JOp
+instance NFData Op
-- | JS Unary Operators
-data JUOp
+data UOp
= NotOp -- ^ Logical Not: @!@
| BNotOp -- ^ Bitwise Not: @~@
| NegOp -- ^ Negation: @-@
@@ -355,7 +319,7 @@ data JUOp
| PostDecOp -- ^ Postfix Decrement: @x--@
deriving (Show, Eq, Ord, Enum, Data, Typeable, Generic)
-instance NFData JUOp
+instance NFData UOp
-- | A newtype wrapper around 'Double' to ensure we never generate a 'Double'
-- that becomes a 'NaN', see 'Eq SaneDouble', 'Ord SaneDouble' for details on
@@ -376,17 +340,16 @@ instance Ord SaneDouble where
instance Show SaneDouble where
show (SaneDouble x) = show x
-
--------------------------------------------------------------------------------
--- Identifiers
+-- Helper Functions
--------------------------------------------------------------------------------
--- We use FastString for identifiers in JS backend
--- | A newtype wrapper around 'FastString' for JS identifiers.
-newtype Ident = TxtI { itxt :: FastString }
- deriving stock (Show, Eq)
- deriving newtype (Uniquable)
+jassignAllEqual :: [JExpr] -> [JExpr] -> JStat
+jassignAllEqual xs ys = mconcat (zipWithEqual "assignAllEqual" AssignStat xs ys)
+
+jassignAll :: [JExpr] -> [JExpr] -> JStat
+jassignAll xs ys = mconcat (zipWith AssignStat xs ys)
+
+jvar :: FastString -> JExpr
+jvar = ValExpr . JVar . TxtI
-identFS :: Ident -> FastString
-identFS = \case
- TxtI fs -> fs