Skip to content
This repository
tree: 61a1b8b071
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 197 lines (167 sloc) 6.678 kb
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TemplateHaskell #-}
module Lang.Php.Ast.ExprTypes where

import Text.PrettyPrint.GenericPretty

import Lang.Php.Ast.Common
import Lang.Php.Ast.Lex
import qualified Data.Intercal as IC

-- Val's are defined to only contain: "$", identifiers, "[Expr]", "[]",
-- "(Exprs)", "${Expr}", "::", "->". The most important consideration is which
-- ones can be assigned to (LVal's) and which ones can be assigned from
-- (RVal's). In PHP, most but not all LVal's are also RVal's.

-- Note that this grammar allows "$$a[]->a = 5;" but Zend does not. However,
-- Zend allows "${$a}[]->a = 5;", and it's not clear what is gained by treating
-- $a and ${..} asymmetrically here. PHP also allows "${$a}[0]->a = 5" and
-- "$$a[0]->a = 5;". So we're regarding this as a by-product of the Zend
-- implementation. In particular, we think they simplify their job by slurping
-- all [Expr?]'s onto Var's and only later analyze things with regard to LVal
-- considerations, simply fataling if something is then awry.
--
-- Modeling that nuance is impractical under the clear division of
-- Var's, LVal's, and RVal's that we desire to make the AST nice for
-- refactoring.

data Val = ValLOnlyVal LOnlyVal | ValROnlyVal ROnlyVal | ValLRVal LRVal
  deriving (Data, Eq, Generic, Show, Typeable)

data LVal = LValLOnlyVal LOnlyVal | LValLRVal LRVal
  deriving (Data, Eq, Generic, Show, Typeable)

data RVal = RValROnlyVal ROnlyVal | RValLRVal LRVal
  deriving (Data, Eq, Generic, Show, Typeable)

data Var =
  -- In php, indexing is oddly coupled very tightly with being a non-dyn var.
  Var String [((WS, (Bool, WSCap Expr)))] | -- "$a", "$a[0]", "$a[0][0]"
  VarDyn WS Var | -- "$$a"
                               -- note: "$$a[0]()->a" == "${$a[0]}()->a"
  VarDynExpr WS (WSCap Expr) -- "${$a . '_'}"
  deriving (Data, Eq, Generic, Show, Typeable)

data DynConst = DynConst [(String, WS2)] Var -- "a::$a"
  deriving (Data, Eq, Generic, Show, Typeable)

data LRVal =
  LRValVar DynConst |
  LRValInd RVal WS (WSCap Expr) | -- "$a->a[0]"
  LRValMemb RVal WS2 Memb | -- $a->a
  LRValStaMemb RVal WS2 Memb -- $a::a
  deriving (Data, Eq, Generic, Show, Typeable)

data LOnlyVal =
  LOnlyValList WS (Either WS [Either WS (WSCap LVal)]) |
  LOnlyValAppend LVal WS2 | -- "$a[]"
  LOnlyValInd LOnlyVal WS (WSCap Expr) | -- "$a[][0]"
  LOnlyValMemb LOnlyVal WS2 Memb -- "$a[]->a"
  deriving (Data, Eq, Generic, Show, Typeable)

data Const = Const [(String, WS2)] String -- "a::a"
  deriving (Data, Eq, Generic, Show, Typeable)

data ROnlyVal =
  ROnlyValConst Const |
  -- "a()", "$a()"
  ROnlyValFunc (Either LRVal Const) WS (Either WS [WSCap (Either Expr LVal)])
  deriving (Data, Eq, Generic, Show, Typeable)

data Memb =
  MembStr String |
  MembVar Var |
  MembExpr (WSCap Expr)
  deriving (Data, Eq, Generic, Show, Typeable)

-- Expr's

data Expr =
  ExprArray WS (Either WS ([WSCap DubArrowMb], Maybe WS)) |
  ExprAssign (Maybe BinOpBy) LVal WS2 Expr |
  ExprBackticks String |
  ExprBinOp BinOp Expr WS2 Expr |
  -- we're lazy so just String here instead of like PhpType
  ExprCast (WSCap String) WS Expr |
  ExprEmpty WS (WSCap LRVal) |
  ExprEval WS (WSCap Expr) |
  ExprExit Bool (Maybe (WS, Either WS (WSCap Expr))) |
  ExprHereDoc HereDoc |
  -- FIXME: this fb extension should be separated to a superclass-like Lang?
  ExprIndex Expr WS (WSCap Expr) |
  ExprInclude IncOrReq OnceOrNot WS Expr |
  -- true story: "instanceof" takes LRVal's but not non-Const ROnlyVal's..
  ExprInstOf Expr WS2 (Either LRVal Const) |
  ExprIsset WS [WSCap LRVal] |
  ExprNew WS RVal (Maybe (WS, Either WS [WSCap Expr])) |
  ExprNumLit NumLit |
  ExprParen (WSCap Expr) |
  ExprPostOp PostOp Expr WS |
  ExprPreOp PreOp WS Expr |
  -- note: "list"/"&" is actually more limited
  -- ("list() = &$a;" is nonsyntactic)
  ExprRef WS (Either Expr Val) |
  ExprRVal RVal |
  ExprStrLit StrLit |
  ExprTernaryIf TernaryIf |
  -- FIXME: this fb extension should be separated to a superclass-like Lang?
  ExprXml Xml
  deriving (Data, Eq, Generic, Show, Typeable)

data Xml = Xml String
  (IC.Intercal WS (String, Maybe (WS2, Either StrLit (WSCap Expr))))
  (Maybe ([Either XmlLitOrExpr Xml], Bool))
  deriving (Data, Eq, Generic, Show, Typeable)

data XmlLitOrExpr = XmlLit String | XmlExpr (WSCap Expr)
  deriving (Data, Eq, Generic, Show, Typeable)

data BinOp = BAnd | BAndWd | BEQ | BGE | BGT | BID | BLE | BLT | BNE |
  -- <> has different precedence than !=
  BNEOld | BNI | BOr | BOrWd | BXorWd | BByable BinOpBy
  deriving (Data, Eq, Generic, Show, Typeable)

data BinOpBy = BBitAnd | BBitOr | BConcat | BDiv | BMinus | BMod | BMul |
  BPlus | BShiftL | BShiftR | BXor
  deriving (Data, Eq, Generic, Show, Typeable)

data PreOp = PrPrint | PrAt | PrBitNot | PrClone | PrNegate | PrNot | PrPos |
  PrSuppress | PrIncr | PrDecr
  deriving (Data, Eq, Generic, Show, Typeable)

data PostOp = PoIncr | PoDecr
  deriving (Data, Eq, Generic, Show, Typeable)

data IncOrReq = Inc | Req
  deriving (Data, Eq, Generic, Show, Typeable)

data OnceOrNot = Once | NotOnce
  deriving (Data, Eq, Generic, Show, Typeable)

data TernaryIf = TernaryIf {
  ternaryIfCond :: Expr,
  ternaryIfWS1 :: WS2,
  ternaryIfThen :: Maybe Expr,
  ternaryIfWS2 :: WS2,
  ternaryIfElse :: Expr}
  deriving (Data, Eq, Generic, Show, Typeable)

data DubArrowMb = DubArrowMb (Maybe (Expr, WS2)) Expr
  deriving (Data, Eq, Generic, Show, Typeable)

instance Out BinOp
instance Out BinOpBy
instance Out Const
instance Out DubArrowMb
instance Out DynConst
instance Out Expr
instance Out IncOrReq
instance Out LOnlyVal
instance Out LRVal
instance Out LVal
instance Out Memb
instance Out OnceOrNot
instance Out PostOp
instance Out PreOp
instance Out ROnlyVal
instance Out RVal
instance Out TernaryIf
instance Out Val
instance Out Var
instance Out Xml
instance Out XmlLitOrExpr

$(derive makeBinary ''BinOp)
$(derive makeBinary ''BinOpBy)
$(derive makeBinary ''Const)
$(derive makeBinary ''DubArrowMb)
$(derive makeBinary ''DynConst)
$(derive makeBinary ''Expr)
$(derive makeBinary ''IncOrReq)
$(derive makeBinary ''LOnlyVal)
$(derive makeBinary ''LRVal)
$(derive makeBinary ''LVal)
$(derive makeBinary ''Memb)
$(derive makeBinary ''OnceOrNot)
$(derive makeBinary ''PostOp)
$(derive makeBinary ''PreOp)
$(derive makeBinary ''ROnlyVal)
$(derive makeBinary ''RVal)
$(derive makeBinary ''TernaryIf)
$(derive makeBinary ''Val)
$(derive makeBinary ''Var)
$(derive makeBinary ''Xml)
$(derive makeBinary ''XmlLitOrExpr)

Something went wrong with that request. Please try again.