js/src/frontend/ParseNode.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef frontend_ParseNode_h
     8 #define frontend_ParseNode_h
    10 #include "mozilla/Attributes.h"
    12 #include "frontend/TokenStream.h"
    14 namespace js {
    15 namespace frontend {
    17 template <typename ParseHandler>
    18 struct ParseContext;
    20 class FullParseHandler;
    21 class FunctionBox;
    22 class ObjectBox;
    24 /*
    25  * Indicates a location in the stack that an upvar value can be retrieved from
    26  * as a two tuple of (level, slot).
    27  *
    28  * Some existing client code uses the level value as a delta, or level "skip"
    29  * quantity. We could probably document that through use of more types at some
    30  * point in the future.
    31  */
    32 class UpvarCookie
    33 {
    34     uint32_t level_ : SCOPECOORD_HOPS_BITS;
    35     uint32_t slot_ : SCOPECOORD_SLOT_BITS;
    37     void checkInvariants() {
    38         static_assert(sizeof(UpvarCookie) == sizeof(uint32_t),
    39                       "Not necessary for correctness, but good for ParseNode memory use");
    40     }
    42   public:
    43     // Steal one value to represent the sentinel value for UpvarCookie.
    44     static const uint32_t FREE_LEVEL = SCOPECOORD_HOPS_LIMIT - 1;
    45     bool isFree() const { return level_ == FREE_LEVEL; }
    47     uint32_t level() const { JS_ASSERT(!isFree()); return level_; }
    48     uint32_t slot()  const { JS_ASSERT(!isFree()); return slot_; }
    50     // This fails and issues an error message if newLevel or newSlot are too large.
    51     bool set(TokenStream &ts, unsigned newLevel, uint32_t newSlot) {
    52         if (newLevel >= FREE_LEVEL)
    53             return ts.reportError(JSMSG_TOO_DEEP, js_function_str);
    55         if (newSlot >= SCOPECOORD_SLOT_LIMIT)
    56             return ts.reportError(JSMSG_TOO_MANY_LOCALS);
    58         level_ = newLevel;
    59         slot_ = newSlot;
    60         return true;
    61     }
    63     void makeFree() {
    64         level_ = FREE_LEVEL;
    65         slot_ = 0;      // value doesn't matter, won't be used
    66         JS_ASSERT(isFree());
    67     }
    68 };
    70 #define FOR_EACH_PARSE_NODE_KIND(F) \
    71     F(NOP) \
    72     F(SEMI) \
    73     F(COMMA) \
    74     F(CONDITIONAL) \
    75     F(COLON) \
    76     F(POS) \
    77     F(NEG) \
    78     F(PREINCREMENT) \
    79     F(POSTINCREMENT) \
    80     F(PREDECREMENT) \
    81     F(POSTDECREMENT) \
    82     F(DOT) \
    83     F(ELEM) \
    84     F(ARRAY) \
    85     F(ELISION) \
    86     F(STATEMENTLIST) \
    87     F(LABEL) \
    88     F(OBJECT) \
    89     F(CALL) \
    90     F(NAME) \
    91     F(NUMBER) \
    92     F(STRING) \
    93     F(REGEXP) \
    94     F(TRUE) \
    95     F(FALSE) \
    96     F(NULL) \
    97     F(THIS) \
    98     F(FUNCTION) \
    99     F(IF) \
   100     F(ELSE) \
   101     F(SWITCH) \
   102     F(CASE) \
   103     F(DEFAULT) \
   104     F(WHILE) \
   105     F(DOWHILE) \
   106     F(FOR) \
   107     F(BREAK) \
   108     F(CONTINUE) \
   109     F(VAR) \
   110     F(CONST) \
   111     F(WITH) \
   112     F(RETURN) \
   113     F(NEW) \
   114     F(DELETE) \
   115     F(TRY) \
   116     F(CATCH) \
   117     F(CATCHLIST) \
   118     F(FINALLY) \
   119     F(THROW) \
   120     F(DEBUGGER) \
   121     F(YIELD) \
   122     F(YIELD_STAR) \
   123     F(GENEXP) \
   124     F(ARRAYCOMP) \
   125     F(ARRAYPUSH) \
   126     F(LEXICALSCOPE) \
   127     F(LET) \
   128     F(IMPORT) \
   129     F(IMPORT_SPEC_LIST) \
   130     F(IMPORT_SPEC) \
   131     F(EXPORT) \
   132     F(EXPORT_FROM) \
   133     F(EXPORT_SPEC_LIST) \
   134     F(EXPORT_SPEC) \
   135     F(EXPORT_BATCH_SPEC) \
   136     F(SEQ) \
   137     F(FORIN) \
   138     F(FOROF) \
   139     F(FORHEAD) \
   140     F(ARGSBODY) \
   141     F(SPREAD) \
   142     \
   143     /* Unary operators. */ \
   144     F(TYPEOF) \
   145     F(VOID) \
   146     F(NOT) \
   147     F(BITNOT) \
   148     \
   149     /* \
   150      * Binary operators. \
   151      * These must be in the same order as TOK_OR and friends in TokenStream.h. \
   152      */ \
   153     F(OR) \
   154     F(AND) \
   155     F(BITOR) \
   156     F(BITXOR) \
   157     F(BITAND) \
   158     F(STRICTEQ) \
   159     F(EQ) \
   160     F(STRICTNE) \
   161     F(NE) \
   162     F(LT) \
   163     F(LE) \
   164     F(GT) \
   165     F(GE) \
   166     F(INSTANCEOF) \
   167     F(IN) \
   168     F(LSH) \
   169     F(RSH) \
   170     F(URSH) \
   171     F(ADD) \
   172     F(SUB) \
   173     F(STAR) \
   174     F(DIV) \
   175     F(MOD) \
   176     \
   177     /* Assignment operators (= += -= etc.). */ \
   178     /* ParseNode::isAssignment assumes all these are consecutive. */ \
   179     F(ASSIGN) \
   180     F(ADDASSIGN) \
   181     F(SUBASSIGN) \
   182     F(BITORASSIGN) \
   183     F(BITXORASSIGN) \
   184     F(BITANDASSIGN) \
   185     F(LSHASSIGN) \
   186     F(RSHASSIGN) \
   187     F(URSHASSIGN) \
   188     F(MULASSIGN) \
   189     F(DIVASSIGN) \
   190     F(MODASSIGN)
   192 /*
   193  * Parsing builds a tree of nodes that directs code generation.  This tree is
   194  * not a concrete syntax tree in all respects (for example, || and && are left
   195  * associative, but (A && B && C) translates into the right-associated tree
   196  * <A && <B && C>> so that code generation can emit a left-associative branch
   197  * around <B && C> when A is false).  Nodes are labeled by kind, with a
   198  * secondary JSOp label when needed.
   199  *
   200  * The long comment after this enum block describes the kinds in detail.
   201  */
   202 enum ParseNodeKind
   203 {
   204 #define EMIT_ENUM(name) PNK_##name,
   205     FOR_EACH_PARSE_NODE_KIND(EMIT_ENUM)
   206 #undef EMIT_ENUM
   207     PNK_LIMIT, /* domain size */
   208     PNK_BINOP_FIRST = PNK_OR,
   209     PNK_BINOP_LAST = PNK_MOD,
   210     PNK_ASSIGNMENT_START = PNK_ASSIGN,
   211     PNK_ASSIGNMENT_LAST = PNK_MODASSIGN
   212 };
   214 /*
   215  * Label        Variant     Members
   216  * -----        -------     -------
   217  * <Definitions>
   218  * PNK_FUNCTION name        pn_funbox: ptr to js::FunctionBox holding function
   219  *                            object containing arg and var properties.  We
   220  *                            create the function object at parse (not emit)
   221  *                            time to specialize arg and var bytecodes early.
   222  *                          pn_body: PNK_ARGSBODY, ordinarily;
   223  *                            PNK_LEXICALSCOPE for implicit function in genexpr
   224  *                          pn_cookie: static level and var index for function
   225  *                          pn_dflags: PND_* definition/use flags (see below)
   226  *                          pn_blockid: block id number
   227  * PNK_ARGSBODY list        list of formal parameters followed by:
   228  *                              PNK_STATEMENTLIST node for function body
   229  *                                statements,
   230  *                              PNK_RETURN for expression closure, or
   231  *                              PNK_SEQ for expression closure with
   232  *                                destructured formal parameters
   233  *                          pn_count: 1 + number of formal parameters
   234  *                          pn_tree: PNK_ARGSBODY or PNK_STATEMENTLIST node
   235  * PNK_SPREAD   unary       pn_kid: expression being spread
   236  *
   237  * <Statements>
   238  * PNK_STATEMENTLIST list   pn_head: list of pn_count statements
   239  * PNK_IF       ternary     pn_kid1: cond, pn_kid2: then, pn_kid3: else or null.
   240  *                            In body of a comprehension or desugared generator
   241  *                            expression, pn_kid2 is PNK_YIELD, PNK_ARRAYPUSH,
   242  *                            or (if the push was optimized away) empty
   243  *                            PNK_STATEMENTLIST.
   244  * PNK_SWITCH   binary      pn_left: discriminant
   245  *                          pn_right: list of PNK_CASE nodes, with at most one
   246  *                            PNK_DEFAULT node, or if there are let bindings
   247  *                            in the top level of the switch body's cases, a
   248  *                            PNK_LEXICALSCOPE node that contains the list of
   249  *                            PNK_CASE nodes.
   250  * PNK_CASE,    binary      pn_left: case expr
   251  *                          pn_right: PNK_STATEMENTLIST node for this case's
   252  *                            statements
   253  * PNK_DEFAULT  binary      pn_left: null
   254  *                          pn_right: PNK_STATEMENTLIST node for this default's
   255  *                            statements
   256  *                          pn_val: constant value if lookup or table switch
   257  * PNK_WHILE    binary      pn_left: cond, pn_right: body
   258  * PNK_DOWHILE  binary      pn_left: body, pn_right: cond
   259  * PNK_FOR      binary      pn_left: either PNK_FORIN (for-in statement),
   260  *                            PNK_FOROF (for-of) or PNK_FORHEAD (for(;;))
   261  *                          pn_right: body
   262  * PNK_FORIN    ternary     pn_kid1:  PNK_VAR to left of 'in', or nullptr
   263  *                            its pn_xflags may have PNX_POPVAR
   264  *                            bit set
   265  *                          pn_kid2: PNK_NAME or destructuring expr
   266  *                            to left of 'in'; if pn_kid1, then this
   267  *                            is a clone of pn_kid1->pn_head
   268  *                          pn_kid3: object expr to right of 'in'
   269  * PNK_FOROF    ternary     pn_kid1:  PNK_VAR to left of 'of', or nullptr
   270  *                            its pn_xflags may have PNX_POPVAR
   271  *                            bit set
   272  *                          pn_kid2: PNK_NAME or destructuring expr
   273  *                            to left of 'of'; if pn_kid1, then this
   274  *                            is a clone of pn_kid1->pn_head
   275  *                          pn_kid3: expr to right of 'of'
   276  * PNK_FORHEAD  ternary     pn_kid1:  init expr before first ';' or nullptr
   277  *                          pn_kid2:  cond expr before second ';' or nullptr
   278  *                          pn_kid3:  update expr after second ';' or nullptr
   279  * PNK_THROW    unary       pn_op: JSOP_THROW, pn_kid: exception
   280  * PNK_TRY      ternary     pn_kid1: try block
   281  *                          pn_kid2: null or PNK_CATCHLIST list of
   282  *                          PNK_LEXICALSCOPE nodes, each with pn_expr pointing
   283  *                          to a PNK_CATCH node
   284  *                          pn_kid3: null or finally block
   285  * PNK_CATCH    ternary     pn_kid1: PNK_NAME, PNK_ARRAY, or PNK_OBJECT catch var node
   286  *                                   (PNK_ARRAY or PNK_OBJECT if destructuring)
   287  *                          pn_kid2: null or the catch guard expression
   288  *                          pn_kid3: catch block statements
   289  * PNK_BREAK    name        pn_atom: label or null
   290  * PNK_CONTINUE name        pn_atom: label or null
   291  * PNK_WITH     binary-obj  pn_left: head expr; pn_right: body; pn_binary_obj: StaticWithObject
   292  * PNK_VAR,     list        pn_head: list of PNK_NAME or PNK_ASSIGN nodes
   293  * PNK_CONST                         each name node has either
   294  *                                     pn_used: false
   295  *                                     pn_atom: variable name
   296  *                                     pn_expr: initializer or null
   297  *                                   or
   298  *                                     pn_used: true
   299  *                                     pn_atom: variable name
   300  *                                     pn_lexdef: def node
   301  *                                   each assignment node has
   302  *                                     pn_left: PNK_NAME with pn_used true and
   303  *                                              pn_lexdef (NOT pn_expr) set
   304  *                                     pn_right: initializer
   305  * PNK_RETURN   unary       pn_kid: return expr or null
   306  * PNK_SEMI     unary       pn_kid: expr or null statement
   307  *                          pn_prologue: true if Directive Prologue member
   308  *                              in original source, not introduced via
   309  *                              constant folding or other tree rewriting
   310  * PNK_LABEL    name        pn_atom: label, pn_expr: labeled statement
   311  *
   312  * <Expressions>
   313  * All left-associated binary trees of the same type are optimized into lists
   314  * to avoid recursion when processing expression chains.
   315  * PNK_COMMA    list        pn_head: list of pn_count comma-separated exprs
   316  * PNK_ASSIGN   binary      pn_left: lvalue, pn_right: rvalue
   317  * PNK_ADDASSIGN,   binary  pn_left: lvalue, pn_right: rvalue
   318  * PNK_SUBASSIGN,           pn_op: JSOP_ADD for +=, etc.
   319  * PNK_BITORASSIGN,
   320  * PNK_BITXORASSIGN,
   321  * PNK_BITANDASSIGN,
   322  * PNK_LSHASSIGN,
   323  * PNK_RSHASSIGN,
   324  * PNK_URSHASSIGN,
   325  * PNK_MULASSIGN,
   326  * PNK_DIVASSIGN,
   327  * PNK_MODASSIGN
   328  * PNK_CONDITIONAL ternary  (cond ? trueExpr : falseExpr)
   329  *                          pn_kid1: cond, pn_kid2: then, pn_kid3: else
   330  * PNK_OR       binary      pn_left: first in || chain, pn_right: rest of chain
   331  * PNK_AND      binary      pn_left: first in && chain, pn_right: rest of chain
   332  * PNK_BITOR    binary      pn_left: left-assoc | expr, pn_right: ^ expr
   333  * PNK_BITXOR   binary      pn_left: left-assoc ^ expr, pn_right: & expr
   334  * PNK_BITAND   binary      pn_left: left-assoc & expr, pn_right: EQ expr
   335  *
   336  * PNK_EQ,      binary      pn_left: left-assoc EQ expr, pn_right: REL expr
   337  * PNK_NE,
   338  * PNK_STRICTEQ,
   339  * PNK_STRICTNE
   340  * PNK_LT,      binary      pn_left: left-assoc REL expr, pn_right: SH expr
   341  * PNK_LE,
   342  * PNK_GT,
   343  * PNK_GE
   344  * PNK_LSH,     binary      pn_left: left-assoc SH expr, pn_right: ADD expr
   345  * PNK_RSH,
   346  * PNK_URSH
   347  * PNK_ADD      binary      pn_left: left-assoc ADD expr, pn_right: MUL expr
   348  *                          pn_xflags: if a left-associated binary PNK_ADD
   349  *                            tree has been flattened into a list (see above
   350  *                            under <Expressions>), pn_xflags will contain
   351  *                            PNX_STRCAT if at least one list element is a
   352  *                            string literal (PNK_STRING); if such a list has
   353  *                            any non-string, non-number term, pn_xflags will
   354  *                            contain PNX_CANTFOLD.
   355  * PNK_SUB      binary      pn_left: left-assoc SH expr, pn_right: ADD expr
   356  * PNK_STAR,    binary      pn_left: left-assoc MUL expr, pn_right: UNARY expr
   357  * PNK_DIV,                 pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD
   358  * PNK_MOD
   359  * PNK_POS,     unary       pn_kid: UNARY expr
   360  * PNK_NEG
   361  * PNK_TYPEOF,  unary       pn_kid: UNARY expr
   362  * PNK_VOID,
   363  * PNK_NOT,
   364  * PNK_BITNOT
   365  * PNK_PREINCREMENT, unary  pn_kid: MEMBER expr
   366  * PNK_POSTINCREMENT,
   367  * PNK_PREDECREMENT,
   368  * PNK_POSTDECREMENT
   369  * PNK_NEW      list        pn_head: list of ctor, arg1, arg2, ... argN
   370  *                          pn_count: 1 + N (where N is number of args)
   371  *                          ctor is a MEMBER expr
   372  * PNK_DELETE   unary       pn_kid: MEMBER expr
   373  * PNK_DOT      name        pn_expr: MEMBER expr to left of .
   374  *                          pn_atom: name to right of .
   375  * PNK_ELEM     binary      pn_left: MEMBER expr to left of [
   376  *                          pn_right: expr between [ and ]
   377  * PNK_CALL     list        pn_head: list of call, arg1, arg2, ... argN
   378  *                          pn_count: 1 + N (where N is number of args)
   379  *                          call is a MEMBER expr naming a callable object
   380  * PNK_GENEXP   list        Exactly like PNK_CALL, used for the implicit call
   381  *                          in the desugaring of a generator-expression.
   382  * PNK_ARRAY    list        pn_head: list of pn_count array element exprs
   383  *                          [,,] holes are represented by PNK_ELISION nodes
   384  *                          pn_xflags: PN_ENDCOMMA if extra comma at end
   385  * PNK_OBJECT   list        pn_head: list of pn_count binary PNK_COLON nodes
   386  * PNK_COLON    binary      key-value pair in object initializer or
   387  *                          destructuring lhs
   388  *                          pn_left: property id, pn_right: value
   389  *                          var {x} = object destructuring shorthand shares
   390  *                          PN_NAME node for x on left and right of PNK_COLON
   391  *                          node in PNK_OBJECT's list, has PNX_DESTRUCT flag
   392  * PNK_NAME,    name        pn_atom: name, string, or object atom
   393  * PNK_STRING               pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT
   394  *                          If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
   395  *                          with pn_cookie telling (staticLevel, slot) (see
   396  *                          jsscript.h's UPVAR macros) and pn_dflags telling
   397  *                          const-ness and static analysis results
   398  * PNK_REGEXP   nullary     pn_objbox: RegExp model object
   399  * PNK_NAME     name        If pn_used, PNK_NAME uses the lexdef member instead
   400  *                          of the expr member it overlays
   401  * PNK_NUMBER   dval        pn_dval: double value of numeric literal
   402  * PNK_TRUE,    nullary     pn_op: JSOp bytecode
   403  * PNK_FALSE,
   404  * PNK_NULL,
   405  * PNK_THIS
   406  *
   407  * PNK_LEXICALSCOPE name    pn_objbox: block object in ObjectBox holder
   408  *                          pn_expr: block body
   409  * PNK_ARRAYCOMP    list    pn_count: 1
   410  *                          pn_head: list of 1 element, which is block
   411  *                          enclosing for loop(s) and optionally
   412  *                          if-guarded PNK_ARRAYPUSH
   413  * PNK_ARRAYPUSH    unary   pn_op: JSOP_ARRAYCOMP
   414  *                          pn_kid: array comprehension expression
   415  * PNK_NOP          nullary
   416  */
   417 enum ParseNodeArity
   418 {
   419     PN_NULLARY,                         /* 0 kids, only pn_atom/pn_dval/etc. */
   420     PN_UNARY,                           /* one kid, plus a couple of scalars */
   421     PN_BINARY,                          /* two kids, plus a couple of scalars */
   422     PN_BINARY_OBJ,                      /* two kids, plus an objbox */
   423     PN_TERNARY,                         /* three kids */
   424     PN_CODE,                            /* module or function definition node */
   425     PN_LIST,                            /* generic singly linked list */
   426     PN_NAME                             /* name use or definition node */
   427 };
   429 struct Definition;
   431 class LabeledStatement;
   432 class LoopControlStatement;
   433 class BreakStatement;
   434 class ContinueStatement;
   435 class ConditionalExpression;
   436 class PropertyAccess;
   438 class ParseNode
   439 {
   440     uint32_t            pn_type   : 16, /* PNK_* type */
   441                         pn_op     : 8,  /* see JSOp enum and jsopcode.tbl */
   442                         pn_arity  : 5,  /* see ParseNodeArity enum */
   443                         pn_parens : 1,  /* this expr was enclosed in parens */
   444                         pn_used   : 1,  /* name node is on a use-chain */
   445                         pn_defn   : 1;  /* this node is a Definition */
   447     ParseNode(const ParseNode &other) MOZ_DELETE;
   448     void operator=(const ParseNode &other) MOZ_DELETE;
   450   public:
   451     ParseNode(ParseNodeKind kind, JSOp op, ParseNodeArity arity)
   452       : pn_type(kind), pn_op(op), pn_arity(arity), pn_parens(0), pn_used(0), pn_defn(0),
   453         pn_pos(0, 0), pn_offset(0), pn_next(nullptr), pn_link(nullptr)
   454     {
   455         JS_ASSERT(kind < PNK_LIMIT);
   456         memset(&pn_u, 0, sizeof pn_u);
   457     }
   459     ParseNode(ParseNodeKind kind, JSOp op, ParseNodeArity arity, const TokenPos &pos)
   460       : pn_type(kind), pn_op(op), pn_arity(arity), pn_parens(0), pn_used(0), pn_defn(0),
   461         pn_pos(pos), pn_offset(0), pn_next(nullptr), pn_link(nullptr)
   462     {
   463         JS_ASSERT(kind < PNK_LIMIT);
   464         memset(&pn_u, 0, sizeof pn_u);
   465     }
   467     JSOp getOp() const                     { return JSOp(pn_op); }
   468     void setOp(JSOp op)                    { pn_op = op; }
   469     bool isOp(JSOp op) const               { return getOp() == op; }
   471     ParseNodeKind getKind() const {
   472         JS_ASSERT(pn_type < PNK_LIMIT);
   473         return ParseNodeKind(pn_type);
   474     }
   475     void setKind(ParseNodeKind kind) {
   476         JS_ASSERT(kind < PNK_LIMIT);
   477         pn_type = kind;
   478     }
   479     bool isKind(ParseNodeKind kind) const  { return getKind() == kind; }
   481     ParseNodeArity getArity() const        { return ParseNodeArity(pn_arity); }
   482     bool isArity(ParseNodeArity a) const   { return getArity() == a; }
   483     void setArity(ParseNodeArity a)        { pn_arity = a; }
   485     bool isAssignment() const {
   486         ParseNodeKind kind = getKind();
   487         return PNK_ASSIGNMENT_START <= kind && kind <= PNK_ASSIGNMENT_LAST;
   488     }
   490     /* Boolean attributes. */
   491     bool isInParens() const                { return pn_parens; }
   492     void setInParens(bool enabled)         { pn_parens = enabled; }
   493     bool isUsed() const                    { return pn_used; }
   494     void setUsed(bool enabled)             { pn_used = enabled; }
   495     bool isDefn() const                    { return pn_defn; }
   496     void setDefn(bool enabled)             { pn_defn = enabled; }
   498     static const unsigned NumDefinitionFlagBits = 10;
   499     static const unsigned NumListFlagBits = 10;
   500     static const unsigned NumBlockIdBits = 22;
   501     static_assert(NumDefinitionFlagBits == NumListFlagBits,
   502                   "Assumed below to achieve consistent blockid offset");
   503     static_assert(NumDefinitionFlagBits + NumBlockIdBits <= 32,
   504                   "This is supposed to fit in a single uint32_t");
   506     TokenPos            pn_pos;         /* two 16-bit pairs here, for 64 bits */
   507     int32_t             pn_offset;      /* first generated bytecode offset */
   508     ParseNode           *pn_next;       /* intrinsic link in parent PN_LIST */
   509     ParseNode           *pn_link;       /* def/use link (alignment freebie) */
   511     union {
   512         struct {                        /* list of next-linked nodes */
   513             ParseNode   *head;          /* first node in list */
   514             ParseNode   **tail;         /* ptr to ptr to last node in list */
   515             uint32_t    count;          /* number of nodes in list */
   516             uint32_t    xflags:NumListFlagBits, /* see PNX_* below */
   517                         blockid:NumBlockIdBits; /* see name variant below */
   518         } list;
   519         struct {                        /* ternary: if, for(;;), ?: */
   520             ParseNode   *kid1;          /* condition, discriminant, etc. */
   521             ParseNode   *kid2;          /* then-part, case list, etc. */
   522             ParseNode   *kid3;          /* else-part, default case, etc. */
   523         } ternary;
   524         struct {                        /* two kids if binary */
   525             ParseNode   *left;
   526             ParseNode   *right;
   527             union {
   528                 unsigned iflags;        /* JSITER_* flags for PNK_FOR node */
   529                 ObjectBox *objbox;      /* Only for PN_BINARY_OBJ */
   530             };
   531         } binary;
   532         struct {                        /* one kid if unary */
   533             ParseNode   *kid;
   534             bool        prologue;       /* directive prologue member (as
   535                                            pn_prologue) */
   536         } unary;
   537         struct {                        /* name, labeled statement, etc. */
   538             union {
   539                 JSAtom      *atom;      /* lexical name or label atom */
   540                 ObjectBox   *objbox;    /* block or regexp object */
   541                 FunctionBox *funbox;    /* function object */
   542             };
   543             union {
   544                 ParseNode   *expr;      /* module or function body, var
   545                                            initializer, argument default, or
   546                                            base object of PNK_DOT */
   547                 Definition  *lexdef;    /* lexical definition for this use */
   548             };
   549             UpvarCookie cookie;         /* upvar cookie with absolute frame
   550                                            level (not relative skip), possibly
   551                                            in current frame */
   552             uint32_t    dflags:NumDefinitionFlagBits, /* see PND_* below */
   553                         blockid:NumBlockIdBits;  /* block number, for subset dominance
   554                                                     computation */
   555         } name;
   556         struct {
   557             double      value;          /* aligned numeric literal value */
   558             DecimalPoint decimalPoint;  /* Whether the number has a decimal point */
   559         } number;
   560         class {
   561             friend class LoopControlStatement;
   562             PropertyName     *label;    /* target of break/continue statement */
   563         } loopControl;
   564     } pn_u;
   566 #define pn_modulebox    pn_u.name.modulebox
   567 #define pn_funbox       pn_u.name.funbox
   568 #define pn_body         pn_u.name.expr
   569 #define pn_cookie       pn_u.name.cookie
   570 #define pn_dflags       pn_u.name.dflags
   571 #define pn_blockid      pn_u.name.blockid
   572 #define pn_index        pn_u.name.blockid /* reuse as object table index */
   573 #define pn_head         pn_u.list.head
   574 #define pn_tail         pn_u.list.tail
   575 #define pn_count        pn_u.list.count
   576 #define pn_xflags       pn_u.list.xflags
   577 #define pn_kid1         pn_u.ternary.kid1
   578 #define pn_kid2         pn_u.ternary.kid2
   579 #define pn_kid3         pn_u.ternary.kid3
   580 #define pn_left         pn_u.binary.left
   581 #define pn_right        pn_u.binary.right
   582 #define pn_pval         pn_u.binary.pval
   583 #define pn_iflags       pn_u.binary.iflags
   584 #define pn_binary_obj   pn_u.binary.objbox
   585 #define pn_kid          pn_u.unary.kid
   586 #define pn_prologue     pn_u.unary.prologue
   587 #define pn_atom         pn_u.name.atom
   588 #define pn_objbox       pn_u.name.objbox
   589 #define pn_expr         pn_u.name.expr
   590 #define pn_lexdef       pn_u.name.lexdef
   591 #define pn_dval         pn_u.number.value
   593   protected:
   594     void init(TokenKind type, JSOp op, ParseNodeArity arity) {
   595         pn_type = type;
   596         pn_op = op;
   597         pn_arity = arity;
   598         pn_parens = false;
   599         JS_ASSERT(!pn_used);
   600         JS_ASSERT(!pn_defn);
   601         pn_next = pn_link = nullptr;
   602     }
   604     static ParseNode *create(ParseNodeKind kind, ParseNodeArity arity, FullParseHandler *handler);
   606   public:
   607     /*
   608      * Append right to left, forming a list node.  |left| must have the given
   609      * kind and op, and op must be left-associative.
   610      */
   611     static ParseNode *
   612     append(ParseNodeKind tt, JSOp op, ParseNode *left, ParseNode *right, FullParseHandler *handler);
   614     /*
   615      * Either append right to left, if left meets the conditions necessary to
   616      * append (see append), or form a binary node whose children are right and
   617      * left.
   618      */
   619     static ParseNode *
   620     newBinaryOrAppend(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right,
   621                       FullParseHandler *handler, ParseContext<FullParseHandler> *pc,
   622                       bool foldConstants);
   624     inline PropertyName *name() const;
   625     inline JSAtom *atom() const;
   627     /*
   628      * The pn_expr and lexdef members are arms of an unsafe union. Unless you
   629      * know exactly what you're doing, use only the following methods to access
   630      * them. For less overhead and assertions for protection, use pn->expr()
   631      * and pn->lexdef(). Otherwise, use pn->maybeExpr() and pn->maybeLexDef().
   632      */
   633     ParseNode *expr() const {
   634         JS_ASSERT(!pn_used);
   635         JS_ASSERT(pn_arity == PN_NAME || pn_arity == PN_CODE);
   636         return pn_expr;
   637     }
   639     Definition *lexdef() const {
   640         JS_ASSERT(pn_used || isDeoptimized());
   641         JS_ASSERT(pn_arity == PN_NAME);
   642         return pn_lexdef;
   643     }
   645     ParseNode  *maybeExpr()   { return pn_used ? nullptr : expr(); }
   646     Definition *maybeLexDef() { return pn_used ? lexdef() : nullptr; }
   648     Definition *resolve();
   650 /* PN_CODE and PN_NAME pn_dflags bits. */
   651 #define PND_LET                 0x01    /* let (block-scoped) binding */
   652 #define PND_CONST               0x02    /* const binding (orthogonal to let) */
   653 #define PND_ASSIGNED            0x04    /* set if ever LHS of assignment */
   654 #define PND_PLACEHOLDER         0x08    /* placeholder definition for lexdep */
   655 #define PND_BOUND               0x10    /* bound to a stack or global slot */
   656 #define PND_DEOPTIMIZED         0x20    /* former pn_used name node, pn_lexdef
   657                                            still valid, but this use no longer
   658                                            optimizable via an upvar opcode */
   659 #define PND_CLOSED              0x40    /* variable is closed over */
   660 #define PND_DEFAULT             0x80    /* definition is an arg with a default */
   661 #define PND_IMPLICITARGUMENTS  0x100    /* the definition is a placeholder for
   662                                            'arguments' that has been converted
   663                                            into a definition after the function
   664                                            body has been parsed. */
   665 #define PND_EMITTEDFUNCTION    0x200    /* hoisted function that was emitted */
   667     static_assert(PND_EMITTEDFUNCTION < (1 << NumDefinitionFlagBits), "Not enough bits");
   669 /* Flags to propagate from uses to definition. */
   670 #define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_CLOSED)
   672 /* PN_LIST pn_xflags bits. */
   673 #define PNX_POPVAR      0x01            /* PNK_VAR or PNK_CONST last result
   674                                            needs popping */
   675 #define PNX_GROUPINIT   0x02            /* var [a, b] = [c, d]; unit list */
   676 #define PNX_FUNCDEFS    0x04            /* contains top-level function statements */
   677 #define PNX_SETCALL     0x08            /* call expression in lvalue context */
   678 #define PNX_DESTRUCT    0x10            /* destructuring special cases:
   679                                            1. shorthand syntax used, at present
   680                                               object destructuring ({x,y}) only;
   681                                            2. code evaluating destructuring
   682                                               arguments occurs before function
   683                                               body */
   684 #define PNX_SPECIALARRAYINIT 0x20       /* one or more of
   685                                            1. array initialiser has holes
   686                                            2. array initializer has spread node */
   687 #define PNX_NONCONST    0x40            /* initialiser has non-constants */
   689     static_assert(PNX_NONCONST < (1 << NumListFlagBits), "Not enough bits");
   691     unsigned frameLevel() const {
   692         JS_ASSERT(pn_arity == PN_CODE || pn_arity == PN_NAME);
   693         return pn_cookie.level();
   694     }
   696     uint32_t frameSlot() const {
   697         JS_ASSERT(pn_arity == PN_CODE || pn_arity == PN_NAME);
   698         return pn_cookie.slot();
   699     }
   701     bool functionIsHoisted() const {
   702         JS_ASSERT(pn_arity == PN_CODE && getKind() == PNK_FUNCTION);
   703         JS_ASSERT(isOp(JSOP_LAMBDA) ||        // lambda, genexpr
   704                   isOp(JSOP_LAMBDA_ARROW) ||  // arrow function
   705                   isOp(JSOP_DEFFUN) ||        // non-body-level function statement
   706                   isOp(JSOP_NOP) ||           // body-level function stmt in global code
   707                   isOp(JSOP_GETLOCAL) ||      // body-level function stmt in function code
   708                   isOp(JSOP_GETARG));         // body-level function redeclaring formal
   709         return !isOp(JSOP_LAMBDA) && !isOp(JSOP_LAMBDA_ARROW) && !isOp(JSOP_DEFFUN);
   710     }
   712     /*
   713      * True if this statement node could be a member of a Directive Prologue: an
   714      * expression statement consisting of a single string literal.
   715      *
   716      * This considers only the node and its children, not its context. After
   717      * parsing, check the node's pn_prologue flag to see if it is indeed part of
   718      * a directive prologue.
   719      *
   720      * Note that a Directive Prologue can contain statements that cannot
   721      * themselves be directives (string literals that include escape sequences
   722      * or escaped newlines, say). This member function returns true for such
   723      * nodes; we use it to determine the extent of the prologue.
   724      */
   725     JSAtom *isStringExprStatement() const {
   726         if (getKind() == PNK_SEMI) {
   727             JS_ASSERT(pn_arity == PN_UNARY);
   728             ParseNode *kid = pn_kid;
   729             if (kid && kid->getKind() == PNK_STRING && !kid->pn_parens)
   730                 return kid->pn_atom;
   731         }
   732         return nullptr;
   733     }
   735     inline bool test(unsigned flag) const;
   737     bool isLet() const          { return test(PND_LET); }
   738     bool isConst() const        { return test(PND_CONST); }
   739     bool isPlaceholder() const  { return test(PND_PLACEHOLDER); }
   740     bool isDeoptimized() const  { return test(PND_DEOPTIMIZED); }
   741     bool isAssigned() const     { return test(PND_ASSIGNED); }
   742     bool isClosed() const       { return test(PND_CLOSED); }
   743     bool isBound() const        { return test(PND_BOUND); }
   744     bool isImplicitArguments() const { return test(PND_IMPLICITARGUMENTS); }
   746     /* True if pn is a parsenode representing a literal constant. */
   747     bool isLiteral() const {
   748         return isKind(PNK_NUMBER) ||
   749                isKind(PNK_STRING) ||
   750                isKind(PNK_TRUE) ||
   751                isKind(PNK_FALSE) ||
   752                isKind(PNK_NULL);
   753     }
   755     /* Return true if this node appears in a Directive Prologue. */
   756     bool isDirectivePrologueMember() const { return pn_prologue; }
   758 #ifdef JS_HAS_GENERATOR_EXPRS
   759     ParseNode *generatorExpr() const {
   760         JS_ASSERT(isKind(PNK_GENEXP));
   761         ParseNode *callee = this->pn_head;
   762         ParseNode *body = callee->pn_body;
   763         JS_ASSERT(body->isKind(PNK_LEXICALSCOPE));
   764         return body->pn_expr;
   765     }
   766 #endif
   768     inline void markAsAssigned();
   770     /*
   771      * Compute a pointer to the last element in a singly-linked list. NB: list
   772      * must be non-empty for correct PN_LAST usage -- this is asserted!
   773      */
   774     ParseNode *last() const {
   775         JS_ASSERT(pn_arity == PN_LIST);
   776         JS_ASSERT(pn_count != 0);
   777         return (ParseNode *)(uintptr_t(pn_tail) - offsetof(ParseNode, pn_next));
   778     }
   780     void initNumber(double value, DecimalPoint decimalPoint) {
   781         JS_ASSERT(pn_arity == PN_NULLARY);
   782         JS_ASSERT(getKind() == PNK_NUMBER);
   783         pn_u.number.value = value;
   784         pn_u.number.decimalPoint = decimalPoint;
   785     }
   787     void makeEmpty() {
   788         JS_ASSERT(pn_arity == PN_LIST);
   789         pn_head = nullptr;
   790         pn_tail = &pn_head;
   791         pn_count = 0;
   792         pn_xflags = 0;
   793         pn_blockid = 0;
   794     }
   796     void initList(ParseNode *pn) {
   797         JS_ASSERT(pn_arity == PN_LIST);
   798         if (pn->pn_pos.begin < pn_pos.begin)
   799             pn_pos.begin = pn->pn_pos.begin;
   800         pn_pos.end = pn->pn_pos.end;
   801         pn_head = pn;
   802         pn_tail = &pn->pn_next;
   803         pn_count = 1;
   804         pn_xflags = 0;
   805         pn_blockid = 0;
   806     }
   808     void append(ParseNode *pn) {
   809         JS_ASSERT(pn_arity == PN_LIST);
   810         JS_ASSERT(pn->pn_pos.begin >= pn_pos.begin);
   811         pn_pos.end = pn->pn_pos.end;
   812         *pn_tail = pn;
   813         pn_tail = &pn->pn_next;
   814         pn_count++;
   815     }
   817     void checkListConsistency()
   818 #ifndef DEBUG
   819     {}
   820 #endif
   821     ;
   823     bool getConstantValue(ExclusiveContext *cx, bool strictChecks, MutableHandleValue vp);
   824     inline bool isConstant();
   826     template <class NodeType>
   827     inline bool is() const {
   828         return NodeType::test(*this);
   829     }
   831     /* Casting operations. */
   832     template <class NodeType>
   833     inline NodeType &as() {
   834         JS_ASSERT(NodeType::test(*this));
   835         return *static_cast<NodeType *>(this);
   836     }
   838     template <class NodeType>
   839     inline const NodeType &as() const {
   840         JS_ASSERT(NodeType::test(*this));
   841         return *static_cast<const NodeType *>(this);
   842     }
   844 #ifdef DEBUG
   845     void dump();
   846     void dump(int indent);
   847 #endif
   848 };
   850 struct NullaryNode : public ParseNode
   851 {
   852     NullaryNode(ParseNodeKind kind, const TokenPos &pos)
   853       : ParseNode(kind, JSOP_NOP, PN_NULLARY, pos) {}
   854     NullaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos)
   855       : ParseNode(kind, op, PN_NULLARY, pos) {}
   857     // This constructor is for a few mad uses in the emitter. It populates
   858     // the pn_atom field even though that field belongs to a branch in pn_u
   859     // that nullary nodes shouldn't use -- bogus.
   860     NullaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, JSAtom *atom)
   861       : ParseNode(kind, op, PN_NULLARY, pos)
   862     {
   863         pn_atom = atom;
   864     }
   866     static bool test(const ParseNode &node) {
   867         return node.isArity(PN_NULLARY);
   868     }
   870 #ifdef DEBUG
   871     void dump();
   872 #endif
   873 };
   875 struct UnaryNode : public ParseNode
   876 {
   877     UnaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *kid)
   878       : ParseNode(kind, op, PN_UNARY, pos)
   879     {
   880         pn_kid = kid;
   881     }
   883     static inline UnaryNode *create(ParseNodeKind kind, FullParseHandler *handler) {
   884         return (UnaryNode *) ParseNode::create(kind, PN_UNARY, handler);
   885     }
   887     static bool test(const ParseNode &node) {
   888         return node.isArity(PN_UNARY);
   889     }
   891 #ifdef DEBUG
   892     void dump(int indent);
   893 #endif
   894 };
   896 struct BinaryNode : public ParseNode
   897 {
   898     BinaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *left, ParseNode *right)
   899       : ParseNode(kind, op, PN_BINARY, pos)
   900     {
   901         pn_left = left;
   902         pn_right = right;
   903     }
   905     BinaryNode(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right)
   906       : ParseNode(kind, op, PN_BINARY, TokenPos::box(left->pn_pos, right->pn_pos))
   907     {
   908         pn_left = left;
   909         pn_right = right;
   910     }
   912     static inline BinaryNode *create(ParseNodeKind kind, FullParseHandler *handler) {
   913         return (BinaryNode *) ParseNode::create(kind, PN_BINARY, handler);
   914     }
   916     static bool test(const ParseNode &node) {
   917         return node.isArity(PN_BINARY);
   918     }
   920 #ifdef DEBUG
   921     void dump(int indent);
   922 #endif
   923 };
   925 struct BinaryObjNode : public ParseNode
   926 {
   927     BinaryObjNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *left, ParseNode *right,
   928                   ObjectBox *objbox)
   929       : ParseNode(kind, op, PN_BINARY_OBJ, pos)
   930     {
   931         pn_left = left;
   932         pn_right = right;
   933         pn_binary_obj = objbox;
   934     }
   936     static inline BinaryObjNode *create(ParseNodeKind kind, FullParseHandler *handler) {
   937         return (BinaryObjNode *) ParseNode::create(kind, PN_BINARY_OBJ, handler);
   938     }
   940     static bool test(const ParseNode &node) {
   941         return node.isArity(PN_BINARY_OBJ);
   942     }
   944 #ifdef DEBUG
   945     void dump(int indent);
   946 #endif
   947 };
   949 struct TernaryNode : public ParseNode
   950 {
   951     TernaryNode(ParseNodeKind kind, JSOp op, ParseNode *kid1, ParseNode *kid2, ParseNode *kid3)
   952       : ParseNode(kind, op, PN_TERNARY,
   953                   TokenPos((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin,
   954                            (kid3 ? kid3 : kid2 ? kid2 : kid1)->pn_pos.end))
   955     {
   956         pn_kid1 = kid1;
   957         pn_kid2 = kid2;
   958         pn_kid3 = kid3;
   959     }
   961     TernaryNode(ParseNodeKind kind, JSOp op, ParseNode *kid1, ParseNode *kid2, ParseNode *kid3,
   962                 const TokenPos &pos)
   963       : ParseNode(kind, op, PN_TERNARY, pos)
   964     {
   965         pn_kid1 = kid1;
   966         pn_kid2 = kid2;
   967         pn_kid3 = kid3;
   968     }
   970     static inline TernaryNode *create(ParseNodeKind kind, FullParseHandler *handler) {
   971         return (TernaryNode *) ParseNode::create(kind, PN_TERNARY, handler);
   972     }
   974     static bool test(const ParseNode &node) {
   975         return node.isArity(PN_TERNARY);
   976     }
   978 #ifdef DEBUG
   979     void dump(int indent);
   980 #endif
   981 };
   983 struct ListNode : public ParseNode
   984 {
   985     ListNode(ParseNodeKind kind, const TokenPos &pos)
   986       : ParseNode(kind, JSOP_NOP, PN_LIST, pos)
   987     {
   988         makeEmpty();
   989     }
   991     ListNode(ParseNodeKind kind, JSOp op, ParseNode *kid)
   992       : ParseNode(kind, op, PN_LIST, kid->pn_pos)
   993     {
   994         initList(kid);
   995     }
   997     static inline ListNode *create(ParseNodeKind kind, FullParseHandler *handler) {
   998         return (ListNode *) ParseNode::create(kind, PN_LIST, handler);
   999     }
  1001     static bool test(const ParseNode &node) {
  1002         return node.isArity(PN_LIST);
  1005 #ifdef DEBUG
  1006     void dump(int indent);
  1007 #endif
  1008 };
  1010 struct CodeNode : public ParseNode
  1012     static inline CodeNode *create(ParseNodeKind kind, FullParseHandler *handler) {
  1013         return (CodeNode *) ParseNode::create(kind, PN_CODE, handler);
  1016     static bool test(const ParseNode &node) {
  1017         return node.isArity(PN_CODE);
  1020 #ifdef DEBUG
  1021     void dump(int indent);
  1022 #endif
  1023 };
  1025 struct NameNode : public ParseNode
  1027     NameNode(ParseNodeKind kind, JSOp op, JSAtom *atom, uint32_t blockid,
  1028              const TokenPos &pos)
  1029       : ParseNode(kind, op, PN_NAME, pos)
  1031         pn_atom = atom;
  1032         pn_expr = nullptr;
  1033         pn_cookie.makeFree();
  1034         pn_dflags = 0;
  1035         pn_blockid = blockid;
  1036         JS_ASSERT(pn_blockid == blockid);  // check for bitfield overflow
  1039     static bool test(const ParseNode &node) {
  1040         return node.isArity(PN_NAME);
  1043 #ifdef DEBUG
  1044     void dump(int indent);
  1045 #endif
  1046 };
  1048 struct LexicalScopeNode : public ParseNode
  1050     static inline LexicalScopeNode *create(ParseNodeKind kind, FullParseHandler *handler) {
  1051         return (LexicalScopeNode *) ParseNode::create(kind, PN_NAME, handler);
  1053 };
  1055 class LabeledStatement : public ParseNode
  1057   public:
  1058     LabeledStatement(PropertyName *label, ParseNode *stmt, uint32_t begin)
  1059       : ParseNode(PNK_LABEL, JSOP_NOP, PN_NAME, TokenPos(begin, stmt->pn_pos.end))
  1061         pn_atom = label;
  1062         pn_expr = stmt;
  1065     PropertyName *label() const {
  1066         return pn_atom->asPropertyName();
  1069     ParseNode *statement() const {
  1070         return pn_expr;
  1073     static bool test(const ParseNode &node) {
  1074         bool match = node.isKind(PNK_LABEL);
  1075         JS_ASSERT_IF(match, node.isArity(PN_NAME));
  1076         JS_ASSERT_IF(match, node.isOp(JSOP_NOP));
  1077         return match;
  1079 };
  1081 class LoopControlStatement : public ParseNode
  1083   protected:
  1084     LoopControlStatement(ParseNodeKind kind, PropertyName *label, const TokenPos &pos)
  1085       : ParseNode(kind, JSOP_NOP, PN_NULLARY, pos)
  1087         JS_ASSERT(kind == PNK_BREAK || kind == PNK_CONTINUE);
  1088         pn_u.loopControl.label = label;
  1091   public:
  1092     /* Label associated with this break/continue statement, if any. */
  1093     PropertyName *label() const {
  1094         return pn_u.loopControl.label;
  1097     static bool test(const ParseNode &node) {
  1098         bool match = node.isKind(PNK_BREAK) || node.isKind(PNK_CONTINUE);
  1099         JS_ASSERT_IF(match, node.isArity(PN_NULLARY));
  1100         JS_ASSERT_IF(match, node.isOp(JSOP_NOP));
  1101         return match;
  1103 };
  1105 class BreakStatement : public LoopControlStatement
  1107   public:
  1108     BreakStatement(PropertyName *label, const TokenPos &pos)
  1109       : LoopControlStatement(PNK_BREAK, label, pos)
  1110     { }
  1112     static bool test(const ParseNode &node) {
  1113         bool match = node.isKind(PNK_BREAK);
  1114         JS_ASSERT_IF(match, node.isArity(PN_NULLARY));
  1115         JS_ASSERT_IF(match, node.isOp(JSOP_NOP));
  1116         return match;
  1118 };
  1120 class ContinueStatement : public LoopControlStatement
  1122   public:
  1123     ContinueStatement(PropertyName *label, const TokenPos &pos)
  1124       : LoopControlStatement(PNK_CONTINUE, label, pos)
  1125     { }
  1127     static bool test(const ParseNode &node) {
  1128         bool match = node.isKind(PNK_CONTINUE);
  1129         JS_ASSERT_IF(match, node.isArity(PN_NULLARY));
  1130         JS_ASSERT_IF(match, node.isOp(JSOP_NOP));
  1131         return match;
  1133 };
  1135 class DebuggerStatement : public ParseNode
  1137   public:
  1138     DebuggerStatement(const TokenPos &pos)
  1139       : ParseNode(PNK_DEBUGGER, JSOP_NOP, PN_NULLARY, pos)
  1140     { }
  1141 };
  1143 class ConditionalExpression : public ParseNode
  1145   public:
  1146     ConditionalExpression(ParseNode *condition, ParseNode *thenExpr, ParseNode *elseExpr)
  1147       : ParseNode(PNK_CONDITIONAL, JSOP_NOP, PN_TERNARY,
  1148                   TokenPos(condition->pn_pos.begin, elseExpr->pn_pos.end))
  1150         JS_ASSERT(condition);
  1151         JS_ASSERT(thenExpr);
  1152         JS_ASSERT(elseExpr);
  1153         pn_u.ternary.kid1 = condition;
  1154         pn_u.ternary.kid2 = thenExpr;
  1155         pn_u.ternary.kid3 = elseExpr;
  1158     ParseNode &condition() const {
  1159         return *pn_u.ternary.kid1;
  1162     ParseNode &thenExpression() const {
  1163         return *pn_u.ternary.kid2;
  1166     ParseNode &elseExpression() const {
  1167         return *pn_u.ternary.kid3;
  1170     static bool test(const ParseNode &node) {
  1171         bool match = node.isKind(PNK_CONDITIONAL);
  1172         JS_ASSERT_IF(match, node.isArity(PN_TERNARY));
  1173         JS_ASSERT_IF(match, node.isOp(JSOP_NOP));
  1174         return match;
  1176 };
  1178 class ThisLiteral : public ParseNode
  1180   public:
  1181     ThisLiteral(const TokenPos &pos) : ParseNode(PNK_THIS, JSOP_THIS, PN_NULLARY, pos) { }
  1182 };
  1184 class NullLiteral : public ParseNode
  1186   public:
  1187     NullLiteral(const TokenPos &pos) : ParseNode(PNK_NULL, JSOP_NULL, PN_NULLARY, pos) { }
  1188 };
  1190 class BooleanLiteral : public ParseNode
  1192   public:
  1193     BooleanLiteral(bool b, const TokenPos &pos)
  1194       : ParseNode(b ? PNK_TRUE : PNK_FALSE, b ? JSOP_TRUE : JSOP_FALSE, PN_NULLARY, pos)
  1195     { }
  1196 };
  1198 class RegExpLiteral : public NullaryNode
  1200   public:
  1201     RegExpLiteral(ObjectBox *reobj, const TokenPos &pos)
  1202       : NullaryNode(PNK_REGEXP, JSOP_REGEXP, pos)
  1204         pn_objbox = reobj;
  1207     ObjectBox *objbox() const { return pn_objbox; }
  1209     static bool test(const ParseNode &node) {
  1210         bool match = node.isKind(PNK_REGEXP);
  1211         JS_ASSERT_IF(match, node.isArity(PN_NULLARY));
  1212         JS_ASSERT_IF(match, node.isOp(JSOP_REGEXP));
  1213         return match;
  1215 };
  1217 class PropertyAccess : public ParseNode
  1219   public:
  1220     PropertyAccess(ParseNode *lhs, PropertyName *name, uint32_t begin, uint32_t end)
  1221       : ParseNode(PNK_DOT, JSOP_NOP, PN_NAME, TokenPos(begin, end))
  1223         JS_ASSERT(lhs != nullptr);
  1224         JS_ASSERT(name != nullptr);
  1225         pn_u.name.expr = lhs;
  1226         pn_u.name.atom = name;
  1229     static bool test(const ParseNode &node) {
  1230         bool match = node.isKind(PNK_DOT);
  1231         JS_ASSERT_IF(match, node.isArity(PN_NAME));
  1232         return match;
  1235     ParseNode &expression() const {
  1236         return *pn_u.name.expr;
  1239     PropertyName &name() const {
  1240         return *pn_u.name.atom->asPropertyName();
  1242 };
  1244 class PropertyByValue : public ParseNode
  1246   public:
  1247     PropertyByValue(ParseNode *lhs, ParseNode *propExpr, uint32_t begin, uint32_t end)
  1248       : ParseNode(PNK_ELEM, JSOP_NOP, PN_BINARY, TokenPos(begin, end))
  1250         pn_u.binary.left = lhs;
  1251         pn_u.binary.right = propExpr;
  1253 };
  1255 #ifdef DEBUG
  1256 void DumpParseTree(ParseNode *pn, int indent = 0);
  1257 #endif
  1259 /*
  1260  * js::Definition is a degenerate subtype of the PN_FUNC and PN_NAME variants
  1261  * of js::ParseNode, allocated only for function, var, const, and let
  1262  * declarations that define truly lexical bindings. This means that a child of
  1263  * a PNK_VAR list may be a Definition as well as a ParseNode. The pn_defn bit
  1264  * is set for all Definitions, clear otherwise.
  1266  * In an upvars list, defn->resolve() is the outermost definition the
  1267  * name may reference. If a with block or a function that calls eval encloses
  1268  * the use, the name may end up referring to something else at runtime.
  1270  * Note that not all var declarations are definitions: JS allows multiple var
  1271  * declarations in a function or script, but only the first creates the hoisted
  1272  * binding. JS programmers do redeclare variables for good refactoring reasons,
  1273  * for example:
  1275  *   function foo() {
  1276  *       ...
  1277  *       for (var i ...) ...;
  1278  *       ...
  1279  *       for (var i ...) ...;
  1280  *       ...
  1281  *   }
  1283  * Not all definitions bind lexical variables, alas. In global and eval code
  1284  * var may re-declare a pre-existing property having any attributes, with or
  1285  * without JSPROP_PERMANENT. In eval code, indeed, ECMA-262 Editions 1 through
  1286  * 3 require function and var to bind deletable bindings. Global vars thus are
  1287  * properties of the global object, so they can be aliased even if they can't
  1288  * be deleted.
  1290  * Only bindings within function code may be treated as lexical, of course with
  1291  * the caveat that hoisting means use before initialization is allowed. We deal
  1292  * with use before declaration in one pass as follows (error checking elided):
  1294  *   for (each use of unqualified name x in parse order) {
  1295  *       if (this use of x is a declaration) {
  1296  *           if (x in pc->decls) {                          // redeclaring
  1297  *               pn = allocate a PN_NAME ParseNode;
  1298  *           } else {                                       // defining
  1299  *               dn = lookup x in pc->lexdeps;
  1300  *               if (dn)                                    // use before def
  1301  *                   remove x from pc->lexdeps;
  1302  *               else                                       // def before use
  1303  *                   dn = allocate a PN_NAME Definition;
  1304  *               map x to dn via pc->decls;
  1305  *               pn = dn;
  1306  *           }
  1307  *           insert pn into its parent PNK_VAR/PNK_CONST list;
  1308  *       } else {
  1309  *           pn = allocate a ParseNode for this reference to x;
  1310  *           dn = lookup x in pc's lexical scope chain;
  1311  *           if (!dn) {
  1312  *               dn = lookup x in pc->lexdeps;
  1313  *               if (!dn) {
  1314  *                   dn = pre-allocate a Definition for x;
  1315  *                   map x to dn in pc->lexdeps;
  1316  *               }
  1317  *           }
  1318  *           append pn to dn's use chain;
  1319  *       }
  1320  *   }
  1322  * See frontend/BytecodeEmitter.h for js::ParseContext and its top*Stmt,
  1323  * decls, and lexdeps members.
  1325  * Notes:
  1327  *  0. To avoid bloating ParseNode, we steal a bit from pn_arity for pn_defn
  1328  *     and set it on a ParseNode instead of allocating a Definition.
  1330  *  1. Due to hoisting, a definition cannot be eliminated even if its "Variable
  1331  *     statement" (ECMA-262 12.2) can be proven to be dead code. RecycleTree in
  1332  *     ParseNode.cpp will not recycle a node whose pn_defn bit is set.
  1334  *  2. "lookup x in pc's lexical scope chain" gives up on def/use chaining if a
  1335  *     with statement is found along the the scope chain, which includes pc,
  1336  *     pc->parent, etc. Thus we eagerly connect an inner function's use of an
  1337  *     outer's var x if the var x was parsed before the inner function.
  1339  *  3. A use may be eliminated as dead by the constant folder, which therefore
  1340  *     must remove the dead name node from its singly-linked use chain, which
  1341  *     would mean hashing to find the definition node and searching to update
  1342  *     the pn_link pointing at the use to be removed. This is costly, so as for
  1343  *     dead definitions, we do not recycle dead pn_used nodes.
  1345  * At the end of parsing a function body or global or eval program, pc->lexdeps
  1346  * holds the lexical dependencies of the parsed unit. The name to def/use chain
  1347  * mappings are then merged into the parent pc->lexdeps.
  1349  * Thus if a later var x is parsed in the outer function satisfying an earlier
  1350  * inner function's use of x, we will remove dn from pc->lexdeps and re-use it
  1351  * as the new definition node in the outer function's parse tree.
  1353  * When the compiler unwinds from the outermost pc, pc->lexdeps contains the
  1354  * definition nodes with use chains for all free variables. These are either
  1355  * global variables or reference errors.
  1356  */
  1357 #define dn_uses         pn_link
  1359 struct Definition : public ParseNode
  1361     bool isFreeVar() const {
  1362         JS_ASSERT(isDefn());
  1363         return pn_cookie.isFree();
  1366     enum Kind { MISSING = 0, VAR, CONST, LET, ARG, NAMED_LAMBDA, PLACEHOLDER };
  1368     bool canHaveInitializer() { return int(kind()) <= int(ARG); }
  1370     static const char *kindString(Kind kind);
  1372     Kind kind() {
  1373         if (getKind() == PNK_FUNCTION) {
  1374             if (isOp(JSOP_GETARG))
  1375                 return ARG;
  1376             return VAR;
  1378         JS_ASSERT(getKind() == PNK_NAME);
  1379         if (isOp(JSOP_CALLEE))
  1380             return NAMED_LAMBDA;
  1381         if (isPlaceholder())
  1382             return PLACEHOLDER;
  1383         if (isOp(JSOP_GETARG))
  1384             return ARG;
  1385         if (isConst())
  1386             return CONST;
  1387         if (isLet())
  1388             return LET;
  1389         return VAR;
  1391 };
  1393 class ParseNodeAllocator
  1395   public:
  1396     explicit ParseNodeAllocator(ExclusiveContext *cx, LifoAlloc &alloc)
  1397       : cx(cx), alloc(alloc), freelist(nullptr)
  1398     {}
  1400     void *allocNode();
  1401     void freeNode(ParseNode *pn);
  1402     ParseNode *freeTree(ParseNode *pn);
  1403     void prepareNodeForMutation(ParseNode *pn);
  1405   private:
  1406     ExclusiveContext *cx;
  1407     LifoAlloc &alloc;
  1408     ParseNode *freelist;
  1409 };
  1411 inline bool
  1412 ParseNode::test(unsigned flag) const
  1414     JS_ASSERT(pn_defn || pn_arity == PN_CODE || pn_arity == PN_NAME);
  1415 #ifdef DEBUG
  1416     if ((flag & PND_ASSIGNED) && pn_defn && !(pn_dflags & flag)) {
  1417         for (ParseNode *pn = ((Definition *) this)->dn_uses; pn; pn = pn->pn_link) {
  1418             JS_ASSERT(!pn->pn_defn);
  1419             JS_ASSERT(!(pn->pn_dflags & flag));
  1422 #endif
  1423     return !!(pn_dflags & flag);
  1426 inline void
  1427 ParseNode::markAsAssigned()
  1429     JS_ASSERT(js_CodeSpec[pn_op].format & JOF_NAME);
  1430     if (isUsed())
  1431         pn_lexdef->pn_dflags |= PND_ASSIGNED;
  1432     pn_dflags |= PND_ASSIGNED;
  1435 inline Definition *
  1436 ParseNode::resolve()
  1438     if (isDefn())
  1439         return (Definition *)this;
  1440     JS_ASSERT(lexdef()->isDefn());
  1441     return (Definition *)lexdef();
  1444 inline bool
  1445 ParseNode::isConstant()
  1447     switch (pn_type) {
  1448       case PNK_NUMBER:
  1449       case PNK_STRING:
  1450       case PNK_NULL:
  1451       case PNK_FALSE:
  1452       case PNK_TRUE:
  1453         return true;
  1454       case PNK_ARRAY:
  1455       case PNK_OBJECT:
  1456         JS_ASSERT(isOp(JSOP_NEWINIT));
  1457         return !(pn_xflags & PNX_NONCONST);
  1458       default:
  1459         return false;
  1463 class ObjectBox
  1465   public:
  1466     JSObject *object;
  1468     ObjectBox(JSObject *object, ObjectBox *traceLink);
  1469     bool isFunctionBox() { return object->is<JSFunction>(); }
  1470     FunctionBox *asFunctionBox();
  1471     void trace(JSTracer *trc);
  1473   protected:
  1474     friend struct CGObjectList;
  1476     ObjectBox *traceLink;
  1477     ObjectBox *emitLink;
  1479     ObjectBox(JSFunction *function, ObjectBox *traceLink);
  1480 };
  1482 enum ParseReportKind
  1484     ParseError,
  1485     ParseWarning,
  1486     ParseExtraWarning,
  1487     ParseStrictError
  1488 };
  1490 enum FunctionSyntaxKind { Expression, Statement, Arrow };
  1492 static inline ParseNode *
  1493 FunctionArgsList(ParseNode *fn, unsigned *numFormals)
  1495     JS_ASSERT(fn->isKind(PNK_FUNCTION));
  1496     ParseNode *argsBody = fn->pn_body;
  1497     JS_ASSERT(argsBody->isKind(PNK_ARGSBODY));
  1498     *numFormals = argsBody->pn_count;
  1499     if (*numFormals > 0 && argsBody->last()->isKind(PNK_STATEMENTLIST))
  1500         (*numFormals)--;
  1501     JS_ASSERT(argsBody->isArity(PN_LIST));
  1502     return argsBody->pn_head;
  1505 } /* namespace frontend */
  1506 } /* namespace js */
  1508 #endif /* frontend_ParseNode_h */

mercurial