//------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once struct Ident; typedef Ident *IdentPtr; class Scope; /*************************************************************************** Flags for classifying node operators. ***************************************************************************/ const uint fnopNone = 0x0000; const uint fnopConst = 0x0001; // constant const uint fnopLeaf = 0x0002; // leaf const uint fnopUni = 0x0004; // unary const uint fnopBin = 0x0008; // binary const uint fnopRel = 0x0010; // relational const uint fnopAsg = 0x0020; // assignment const uint fnopBreak = 0x0040; // break can be used within this statement const uint fnopContinue = 0x0080; // continue can be used within this statement const uint fnopCleanup = 0x0100; // requires cleanup (eg, with or for-in). const uint fnopJump = 0x0200; const uint fnopNotExprStmt = 0x0400; const uint fnopBinList = 0x0800; const uint fnopExprMask = (fnopLeaf|fnopUni|fnopBin); /*************************************************************************** Flags for classifying parse nodes. ***************************************************************************/ enum PNodeFlags : ushort { fpnNone = 0x0000, // knopFncDecl nodes. fpnArguments_overriddenByDecl = 0x0001, // function has a let/const decl, class or nested function named 'arguments', which overrides the built-in arguments object in the body fpnArguments_overriddenInParam = 0x0002, // function has a parameter named arguments fpnArguments_varDeclaration = 0x0004, // function has a var declaration named 'arguments', which may change the way an 'arguments' identifier is resolved // knopVarDecl nodes. fpnArguments = 0x0008, fpnHidden = 0x0010, // Statement nodes. fpnExplicitSemicolon = 0x0020, // statement terminated by an explicit semicolon fpnAutomaticSemicolon = 0x0040, // statement terminated by an automatic semicolon fpnMissingSemicolon = 0x0080, // statement missing terminating semicolon, and is not applicable for automatic semicolon insertion fpnDclList = 0x0100, // statement is a declaration list fpnSyntheticNode = 0x0200, // node is added by the parser or does it represent user code fpnIndexOperator = 0x0400, // dot operator is an optimization of an index operator fpnJumbStatement = 0x0800, // break or continue that was removed by error recovery // Unary/Binary nodes fpnCanFlattenConcatExpr = 0x1000, // the result of the binary operation can participate in concat N // Potentially overlapping traversal flags // These flags are set and cleared during a single node traversal and their values can be used in other node traversals. fpnMemberReference = 0x2000, // The node is a member reference symbol fpnCapturesSyms = 0x4000, // The node is a statement (or contains a sub-statement) // that captures symbols. }; /*************************************************************************** Data structs for ParseNodes. ParseNode includes a union of these. ***************************************************************************/ struct PnUni { ParseNodePtr pnode1; }; struct PnBin { ParseNodePtr pnodeNext; ParseNodePtr pnode1; ParseNodePtr pnode2; }; struct PnTri { ParseNodePtr pnodeNext; ParseNodePtr pnode1; ParseNodePtr pnode2; ParseNodePtr pnode3; }; struct PnSlot { uint slotIndex; }; struct PnUniSlot : PnUni { uint slotIndex; uint staticFuncId; }; struct PnInt { int32 lw; }; struct PnFlt { double dbl; bool maybeInt : 1; }; class Symbol; struct PidRefStack; struct PnPid { IdentPtr pid; Symbol **symRef; Symbol *sym; UnifiedRegex::RegexPattern* regexPattern; uint regexPatternIndex; void SetSymRef(PidRefStack *ref); Symbol **GetSymRef() const { return symRef; } Js::PropertyId PropertyIdFromNameNode() const; }; struct PnVar { ParseNodePtr pnodeNext; IdentPtr pid; Symbol *sym; Symbol **symRef; ParseNodePtr pnodeInit; BOOLEAN isSwitchStmtDecl; BOOLEAN isBlockScopeFncDeclVar; void InitDeclNode(IdentPtr name, ParseNodePtr initExpr) { this->pid = name; this->pnodeInit = initExpr; this->pnodeNext = nullptr; this->sym = nullptr; this->symRef = nullptr; this->isSwitchStmtDecl = false; this->isBlockScopeFncDeclVar = false; } }; struct PnLabel { IdentPtr pid; ParseNodePtr pnodeNext; }; struct PnArrLit : PnUni { uint count; uint spreadCount; BYTE arrayOfTaggedInts:1; // indicates that array initializer nodes are all tagged ints BYTE arrayOfInts:1; // indicates that array initializer nodes are all ints BYTE arrayOfNumbers:1; // indicates that array initializer nodes are all numbers BYTE hasMissingValues:1; }; class FuncInfo; enum PnodeBlockType : unsigned { Global, Function, Regular, Parameter }; enum FncFlags { kFunctionNone = 0, kFunctionNested = 1 << 0, // True if function is nested in another. kFunctionDeclaration = 1 << 1, // is this a declaration or an expression? kFunctionCallsEval = 1 << 2, // function uses eval kFunctionUsesArguments = 1 << 3, // function uses arguments kFunctionHasHeapArguments = 1 << 4, // function's "arguments" escape the scope kFunctionHasReferenceableBuiltInArguments = 1 << 5, // the built-in 'arguments' object is referenceable in the function kFunctionIsAccessor = 1 << 6, // function is a property getter or setter kFunctionHasNonThisStmt = 1 << 7, kFunctionStrictMode = 1 << 8, kFunctionDoesNotEscape = 1 << 9, // function is known not to escape its declaring scope kFunctionIsModule = 1 << 10, // function is a module body kFunctionHasThisStmt = 1 << 11, // function has at least one this.assignment and might be a constructor kFunctionHasWithStmt = 1 << 12, // function (or child) uses with kFunctionIsLambda = 1 << 13, kFunctionChildCallsEval = 1 << 14, kFunctionHasNonSimpleParameterList = 1 << 15, kFunctionHasSuperReference = 1 << 16, kFunctionIsMethod = 1 << 17, kFunctionIsClassConstructor = 1 << 18, // function is a class constructor kFunctionIsBaseClassConstructor = 1 << 19, // function is a base class constructor kFunctionIsClassMember = 1 << 20, // function is a class member kFunctionNameIsHidden = 1 << 21, // True if a named function expression has its name hidden from nested functions kFunctionIsGeneratedDefault = 1 << 22, // Is the function generated by us as a default (e.g. default class constructor) kFunctionHasDefaultArguments = 1 << 23, // Function has one or more ES6 default arguments kFunctionIsStaticMember = 1 << 24, kFunctionIsGenerator = 1 << 25, // Function is an ES6 generator function kFunctionAsmjsMode = 1 << 26, kFunctionHasNewTargetReference = 1 << 27, // function has a reference to new.target kFunctionIsAsync = 1 << 28, // function is async kFunctionHasDirectSuper = 1 << 29, // super() kFunctionIsDefaultModuleExport = 1 << 30, // function is the default export of a module kFunctionHasAnyWriteToFormals = 1 << 31 // To Track if there are any writes to formals. }; struct RestorePoint; struct DeferredFunctionStub; struct PnFnc { ParseNodePtr pnodeNext; ParseNodePtr pnodeName; IdentPtr pid; LPCOLESTR hint; uint32 hintLength; uint32 hintOffset; bool isNameIdentifierRef; bool nestedFuncEscapes; ParseNodePtr pnodeScopes; ParseNodePtr pnodeBodyScope; ParseNodePtr pnodeParams; ParseNodePtr pnodeVars; ParseNodePtr pnodeBody; ParseNodePtr pnodeRest; FuncInfo *funcInfo; // function information gathered during byte code generation Scope *scope; uint nestedCount; // Nested function count (valid until children have been processed) uint nestedIndex; // Index within the parent function uint16 firstDefaultArg; // Position of the first default argument, if any unsigned int fncFlags; int32 astSize; size_t cbMin; // Min an Lim UTF8 offsets. size_t cbLim; ULONG lineNumber; // Line number relative to the current source buffer of the function declaration. ULONG columnNumber; // Column number of the declaration. Js::LocalFunctionId functionId; #if DBG Js::LocalFunctionId deferredParseNextFunctionId; #endif RestorePoint *pRestorePoint; DeferredFunctionStub *deferredStub; bool canBeDeferred; bool isBodyAndParamScopeMerged; // Indicates whether the param scope and the body scope of the function can be merged together or not. // We cannot merge both scopes together if there is any closure capture or eval is present in the param scope. bool fibPreventsDeferral; static const int32 MaxStackClosureAST = 800000; static bool CanBeRedeferred(unsigned int flags) { return !(flags & (kFunctionIsGenerator | kFunctionIsAsync)); } private: void SetFlags(uint flags, bool set) { if (set) { fncFlags |= flags; } else { fncFlags &= ~flags; } } bool HasFlags(uint flags) const { return (fncFlags & flags) == flags; } bool HasAnyFlags(uint flags) const { return (fncFlags & flags) != 0; } bool HasNoFlags(uint flags) const { return (fncFlags & flags) == 0; } public: void ClearFlags() { fncFlags = kFunctionNone; canBeDeferred = false; isBodyAndParamScopeMerged = true; } void SetAsmjsMode(bool set = true) { SetFlags(kFunctionAsmjsMode, set); } void SetCallsEval(bool set = true) { SetFlags(kFunctionCallsEval, set); } void SetChildCallsEval(bool set = true) { SetFlags(kFunctionChildCallsEval, set); } void SetDeclaration(bool set = true) { SetFlags(kFunctionDeclaration, set); } void SetDoesNotEscape(bool set = true) { SetFlags(kFunctionDoesNotEscape, set); } void SetHasDefaultArguments(bool set = true) { SetFlags(kFunctionHasDefaultArguments, set); } void SetHasHeapArguments(bool set = true) { SetFlags(kFunctionHasHeapArguments, set); } void SetHasAnyWriteToFormals(bool set = true) { SetFlags((uint)kFunctionHasAnyWriteToFormals, set); } void SetHasNonSimpleParameterList(bool set = true) { SetFlags(kFunctionHasNonSimpleParameterList, set); } void SetHasNonThisStmt(bool set = true) { SetFlags(kFunctionHasNonThisStmt, set); } void SetHasReferenceableBuiltInArguments(bool set = true) { SetFlags(kFunctionHasReferenceableBuiltInArguments, set); } void SetHasSuperReference(bool set = true) { SetFlags(kFunctionHasSuperReference, set); } void SetHasDirectSuper(bool set = true) { SetFlags(kFunctionHasDirectSuper, set); } void SetHasNewTargetReference(bool set = true) { SetFlags(kFunctionHasNewTargetReference, set); } void SetHasThisStmt(bool set = true) { SetFlags(kFunctionHasThisStmt, set); } void SetHasWithStmt(bool set = true) { SetFlags(kFunctionHasWithStmt, set); } void SetIsAccessor(bool set = true) { SetFlags(kFunctionIsAccessor, set); } void SetIsAsync(bool set = true) { SetFlags(kFunctionIsAsync, set); } void SetIsClassConstructor(bool set = true) { SetFlags(kFunctionIsClassConstructor, set); } void SetIsBaseClassConstructor(bool set = true) { SetFlags(kFunctionIsBaseClassConstructor, set); } void SetIsClassMember(bool set = true) { SetFlags(kFunctionIsClassMember, set); } void SetIsGeneratedDefault(bool set = true) { SetFlags(kFunctionIsGeneratedDefault, set); } void SetIsGenerator(bool set = true) { SetFlags(kFunctionIsGenerator, set); } void SetIsLambda(bool set = true) { SetFlags(kFunctionIsLambda, set); } void SetIsMethod(bool set = true) { SetFlags(kFunctionIsMethod, set); } void SetIsStaticMember(bool set = true) { SetFlags(kFunctionIsStaticMember, set); } void SetNameIsHidden(bool set = true) { SetFlags(kFunctionNameIsHidden, set); } void SetNested(bool set = true) { SetFlags(kFunctionNested, set); } void SetStrictMode(bool set = true) { SetFlags(kFunctionStrictMode, set); } void SetIsModule(bool set = true) { SetFlags(kFunctionIsModule, set); } void SetUsesArguments(bool set = true) { SetFlags(kFunctionUsesArguments, set); } void SetIsDefaultModuleExport(bool set = true) { SetFlags(kFunctionIsDefaultModuleExport, set); } void SetNestedFuncEscapes(bool set = true) { nestedFuncEscapes = set; } void SetCanBeDeferred(bool set = true) { canBeDeferred = set; } void ResetBodyAndParamScopeMerged() { isBodyAndParamScopeMerged = false; } void SetFIBPreventsDeferral(bool set = true) { fibPreventsDeferral = set; } bool CallsEval() const { return HasFlags(kFunctionCallsEval); } bool ChildCallsEval() const { return HasFlags(kFunctionChildCallsEval); } bool DoesNotEscape() const { return HasFlags(kFunctionDoesNotEscape); } bool GetArgumentsObjectEscapes() const { return HasFlags(kFunctionHasHeapArguments); } bool GetAsmjsMode() const { return HasFlags(kFunctionAsmjsMode); } bool GetStrictMode() const { return HasFlags(kFunctionStrictMode); } bool HasDefaultArguments() const { return HasFlags(kFunctionHasDefaultArguments); } bool HasHeapArguments() const { return true; /* HasFlags(kFunctionHasHeapArguments); Disabling stack arguments. Always return HeapArguments as True */ } bool HasAnyWriteToFormals() const { return HasFlags((uint)kFunctionHasAnyWriteToFormals); } bool HasOnlyThisStmts() const { return !HasFlags(kFunctionHasNonThisStmt); } bool HasReferenceableBuiltInArguments() const { return HasFlags(kFunctionHasReferenceableBuiltInArguments); } bool HasSuperReference() const { return HasFlags(kFunctionHasSuperReference); } bool HasDirectSuper() const { return HasFlags(kFunctionHasDirectSuper); } bool HasNewTargetReference() const { return HasFlags(kFunctionHasNewTargetReference); } bool HasNonSimpleParameterList() { return HasFlags(kFunctionHasNonSimpleParameterList); } bool HasThisStmt() const { return HasFlags(kFunctionHasThisStmt); } bool HasWithStmt() const { return HasFlags(kFunctionHasWithStmt); } bool IsAccessor() const { return HasFlags(kFunctionIsAccessor); } bool IsAsync() const { return HasFlags(kFunctionIsAsync); } bool IsConstructor() const { return HasNoFlags(kFunctionIsAsync|kFunctionIsLambda|kFunctionIsAccessor); } bool IsClassConstructor() const { return HasFlags(kFunctionIsClassConstructor); } bool IsBaseClassConstructor() const { return HasFlags(kFunctionIsBaseClassConstructor); } bool IsClassMember() const { return HasFlags(kFunctionIsClassMember); } bool IsDeclaration() const { return HasFlags(kFunctionDeclaration); } bool IsGeneratedDefault() const { return HasFlags(kFunctionIsGeneratedDefault); } bool IsGenerator() const { return HasFlags(kFunctionIsGenerator); } bool IsCoroutine() const { return HasAnyFlags(kFunctionIsGenerator | kFunctionIsAsync); } bool IsLambda() const { return HasFlags(kFunctionIsLambda); } bool IsMethod() const { return HasFlags(kFunctionIsMethod); } bool IsNested() const { return HasFlags(kFunctionNested); } bool IsStaticMember() const { return HasFlags(kFunctionIsStaticMember); } bool IsModule() const { return HasFlags(kFunctionIsModule); } bool NameIsHidden() const { return HasFlags(kFunctionNameIsHidden); } bool UsesArguments() const { return HasFlags(kFunctionUsesArguments); } bool IsDefaultModuleExport() const { return HasFlags(kFunctionIsDefaultModuleExport); } bool NestedFuncEscapes() const { return nestedFuncEscapes; } bool CanBeDeferred() const { return canBeDeferred; } bool IsBodyAndParamScopeMerged() { return isBodyAndParamScopeMerged; } bool FIBPreventsDeferral() const { return fibPreventsDeferral; } // Only allow the normal functions to be asm.js bool IsAsmJsAllowed() const { return (fncFlags & ~( kFunctionAsmjsMode | kFunctionNested | kFunctionDeclaration | kFunctionStrictMode | kFunctionNameIsHidden | kFunctionHasReferenceableBuiltInArguments | kFunctionHasNonThisStmt | // todo:: we shouldn't accept kFunctionHasAnyWriteToFormals on the asm module, but it looks like a bug is setting that flag incorrectly kFunctionHasAnyWriteToFormals )) == 0; } size_t LengthInBytes() { return cbLim - cbMin; } Symbol *GetFuncSymbol(); void SetFuncSymbol(Symbol *sym); ParseNodePtr GetParamScope() const; ParseNodePtr GetBodyScope() const; ParseNodePtr GetTopLevelScope() const { // Top level scope will be the same for knopProg and knopFncDecl. return GetParamScope(); } template void MapContainerScopes(Fn fn) { fn(this->pnodeScopes->sxBlock.pnodeScopes); if (this->pnodeBodyScope != nullptr) { fn(this->pnodeBodyScope->sxBlock.pnodeScopes); } } }; struct PnClass { ParseNodePtr pnodeName; ParseNodePtr pnodeDeclName; ParseNodePtr pnodeBlock; ParseNodePtr pnodeConstructor; ParseNodePtr pnodeMembers; ParseNodePtr pnodeStaticMembers; ParseNodePtr pnodeExtends; bool isDefaultModuleExport; void SetIsDefaultModuleExport(bool set) { isDefaultModuleExport = set; } bool IsDefaultModuleExport() const { return isDefaultModuleExport; } }; struct PnExportDefault { ParseNodePtr pnodeExpr; }; struct PnStrTemplate { ParseNodePtr pnodeStringLiterals; ParseNodePtr pnodeStringRawLiterals; ParseNodePtr pnodeSubstitutionExpressions; uint16 countStringLiterals; BYTE isTaggedTemplate:1; }; struct PnProg : PnFnc { ParseNodePtr pnodeLastValStmt; bool m_UsesArgumentsAtGlobal; }; struct PnModule : PnProg { ModuleImportOrExportEntryList* localExportEntries; ModuleImportOrExportEntryList* indirectExportEntries; ModuleImportOrExportEntryList* starExportEntries; ModuleImportOrExportEntryList* importEntries; IdentPtrList* requestedModules; }; struct PnCall { ParseNodePtr pnodeNext; ParseNodePtr pnodeTarget; ParseNodePtr pnodeArgs; uint16 argCount; uint16 spreadArgCount; BYTE callOfConstants : 1; BYTE isApplyCall : 1; BYTE isEvalCall : 1; BYTE hasDestructuring : 1; }; struct PnStmt { ParseNodePtr pnodeOuter; // Set by parsing code, used by code gen. uint grfnop; // Needed for byte code gen. Js::ByteCodeLabel breakLabel; Js::ByteCodeLabel continueLabel; }; struct PnBlock : PnStmt { ParseNodePtr pnodeStmt; ParseNodePtr pnodeLastValStmt; ParseNodePtr pnodeLexVars; ParseNodePtr pnodeScopes; ParseNodePtr pnodeNext; Scope *scope; ParseNodePtr enclosingBlock; int blockId; PnodeBlockType blockType:2; BYTE callsEval:1; BYTE childCallsEval:1; void SetCallsEval(bool does) { callsEval = does; } bool GetCallsEval() const { return callsEval; } void SetChildCallsEval(bool does) { childCallsEval = does; } bool GetChildCallsEval() const { return childCallsEval; } void SetEnclosingBlock(ParseNodePtr pnode) { enclosingBlock = pnode; } ParseNodePtr GetEnclosingBlock() const { return enclosingBlock; } bool HasBlockScopedContent() const; }; struct PnJump : PnStmt { ParseNodePtr pnodeTarget; bool hasExplicitTarget; }; struct PnLoop : PnStmt { // Needed for byte code gen uint loopId; }; struct PnWhile : PnLoop { ParseNodePtr pnodeCond; ParseNodePtr pnodeBody; }; struct PnWith : PnStmt { ParseNodePtr pnodeObj; ParseNodePtr pnodeBody; ParseNodePtr pnodeScopes; ParseNodePtr pnodeNext; Scope *scope; }; struct PnParamPattern { ParseNodePtr pnodeNext; Js::RegSlot location; ParseNodePtr pnode1; }; struct PnIf : PnStmt { ParseNodePtr pnodeCond; ParseNodePtr pnodeTrue; ParseNodePtr pnodeFalse; }; struct PnHelperCall2 { ParseNodePtr pnodeArg1; ParseNodePtr pnodeArg2; int helperId; }; struct PnForInOrForOf : PnLoop { ParseNodePtr pnodeObj; ParseNodePtr pnodeBody; ParseNodePtr pnodeLval; ParseNodePtr pnodeBlock; Js::RegSlot itemLocation; }; struct PnFor : PnLoop { ParseNodePtr pnodeCond; ParseNodePtr pnodeBody; ParseNodePtr pnodeInit; ParseNodePtr pnodeIncr; ParseNodePtr pnodeBlock; ParseNodePtr pnodeInverted; }; struct PnSwitch : PnStmt { ParseNodePtr pnodeVal; ParseNodePtr pnodeCases; ParseNodePtr pnodeDefault; ParseNodePtr pnodeBlock; }; struct PnCase : PnStmt { ParseNodePtr pnodeNext; ParseNodePtr pnodeExpr; // nullptr for default ParseNodePtr pnodeBody; Js::ByteCodeLabel labelCase; }; struct PnReturn : PnStmt { ParseNodePtr pnodeExpr; }; struct PnTryFinally : PnStmt { ParseNodePtr pnodeTry; ParseNodePtr pnodeFinally; }; struct PnTryCatch : PnStmt { ParseNodePtr pnodeTry; ParseNodePtr pnodeCatch; }; struct PnTry : PnStmt { ParseNodePtr pnodeBody; }; struct PnCatch : PnStmt { ParseNodePtr pnodeNext; ParseNodePtr pnodeParam; ParseNodePtr pnodeBody; ParseNodePtr pnodeScopes; Scope *scope; }; struct PnFinally : PnStmt { ParseNodePtr pnodeBody; }; struct ParseNode { OpCode nop; ushort grfpn; charcount_t ichMin; // start offset into the original source buffer charcount_t ichLim; // end offset into the original source buffer Js::RegSlot location; bool isUsed; // indicates whether an expression such as x++ is used bool emitLabels; bool notEscapedUse; // Use by byte code generator. Currently, only used by child of knopComma bool isInList; bool isCallApplyTargetLoad; #ifdef EDIT_AND_CONTINUE ParseNodePtr parent; #endif union { PnArrLit sxArrLit; // Array literal PnBin sxBin; // binary operators PnBlock sxBlock; // block { } PnCall sxCall; // function call PnCase sxCase; // switch case PnCatch sxCatch; // { catch(e : expr) {body} } PnClass sxClass; // class declaration PnFinally sxFinally; // finally PnExportDefault sxExportDefault;// export default expr; PnFlt sxFlt; // double constant PnFnc sxFnc; // function declaration PnFor sxFor; // for loop PnForInOrForOf sxForInOrForOf; // for-in loop PnHelperCall2 sxHelperCall2; // call to helper PnIf sxIf; // if PnInt sxInt; // integer constant PnJump sxJump; // break and continue PnLabel sxLabel; // label nodes PnLoop sxLoop; // base for loop nodes PnModule sxModule; // global module PnPid sxPid; // identifier or string PnProg sxProg; // global program PnReturn sxReturn; // return [expr] PnStmt sxStmt; // base for statement nodes PnStrTemplate sxStrTemplate; // string template declaration PnSwitch sxSwitch; // switch PnTri sxTri; // ternary operator PnTry sxTry; // try-catch PnTryCatch sxTryCatch; // try-catch PnTryFinally sxTryFinally; // try-catch-finally PnUni sxUni; // unary operators PnVar sxVar; // variable declaration PnWhile sxWhile; // while and do-while loops PnWith sxWith; // with PnParamPattern sxParamPattern; // Destructure pattern for function/catch parameter }; IdentPtr name() { if (this->nop == knopName || this->nop == knopStr) { return this->sxPid.pid; } else if (this->nop == knopVarDecl) { return this->sxVar.pid; } else if (this->nop == knopConstDecl) { return this->sxVar.pid; } return nullptr; } static const uint mpnopgrfnop[knopLim]; static uint Grfnop(int nop) { Assert(nop < knopLim); return nop < knopLim ? mpnopgrfnop[nop] : fnopNone; } BOOL IsStatement() { return (nop >= knopList && nop != knopLabel) || ((Grfnop(nop) & fnopAsg) != 0); } uint Grfnop(void) { Assert(nop < knopLim); return nop < knopLim ? mpnopgrfnop[nop] : fnopNone; } charcount_t LengthInCodepoints() const { return (this->ichLim - this->ichMin); } // This node is a function decl node and function has a var declaration named 'arguments', bool HasVarArguments() const { return ((nop == knopFncDecl) && (grfpn & PNodeFlags::fpnArguments_varDeclaration)); } bool CapturesSyms() const { return (grfpn & PNodeFlags::fpnCapturesSyms) != 0; } void SetCapturesSyms() { grfpn |= PNodeFlags::fpnCapturesSyms; } bool IsInList() const { return this->isInList; } void SetIsInList() { this->isInList = true; } bool IsNotEscapedUse() const { return this->notEscapedUse; } void SetNotEscapedUse() { this->notEscapedUse = true; } bool CanFlattenConcatExpr() const { return !!(this->grfpn & PNodeFlags::fpnCanFlattenConcatExpr); } bool IsCallApplyTargetLoad() { return isCallApplyTargetLoad; } void SetIsCallApplyTargetLoad() { isCallApplyTargetLoad = true; } bool IsVarLetOrConst() const { return this->nop == knopVarDecl || this->nop == knopLetDecl || this->nop == knopConstDecl; } ParseNodePtr GetFormalNext() { ParseNodePtr pnodeNext = nullptr; if (nop == knopParamPattern) { pnodeNext = this->sxParamPattern.pnodeNext; } else { Assert(IsVarLetOrConst()); pnodeNext = this->sxVar.pnodeNext; } return pnodeNext; } bool IsPattern() const { return nop == knopObjectPattern || nop == knopArrayPattern; } #if DBG_DUMP void Dump(); #endif }; const int kcbPnNone = offsetof(ParseNode, sxUni); const int kcbPnArrLit = kcbPnNone + sizeof(PnArrLit); const int kcbPnBin = kcbPnNone + sizeof(PnBin); const int kcbPnBlock = kcbPnNone + sizeof(PnBlock); const int kcbPnCall = kcbPnNone + sizeof(PnCall); const int kcbPnCase = kcbPnNone + sizeof(PnCase); const int kcbPnCatch = kcbPnNone + sizeof(PnCatch); const int kcbPnClass = kcbPnNone + sizeof(PnClass); const int kcbPnExportDefault= kcbPnNone + sizeof(PnExportDefault); const int kcbPnFinally = kcbPnNone + sizeof(PnFinally); const int kcbPnFlt = kcbPnNone + sizeof(PnFlt); const int kcbPnFnc = kcbPnNone + sizeof(PnFnc); const int kcbPnFor = kcbPnNone + sizeof(PnFor); const int kcbPnForIn = kcbPnNone + sizeof(PnForInOrForOf); const int kcbPnForOf = kcbPnNone + sizeof(PnForInOrForOf); const int kcbPnHelperCall3 = kcbPnNone + sizeof(PnHelperCall2); const int kcbPnIf = kcbPnNone + sizeof(PnIf); const int kcbPnInt = kcbPnNone + sizeof(PnInt); const int kcbPnJump = kcbPnNone + sizeof(PnJump); const int kcbPnLabel = kcbPnNone + sizeof(PnLabel); const int kcbPnModule = kcbPnNone + sizeof(PnModule); const int kcbPnPid = kcbPnNone + sizeof(PnPid); const int kcbPnProg = kcbPnNone + sizeof(PnProg); const int kcbPnReturn = kcbPnNone + sizeof(PnReturn); const int kcbPnSlot = kcbPnNone + sizeof(PnSlot); const int kcbPnStrTemplate = kcbPnNone + sizeof(PnStrTemplate); const int kcbPnSwitch = kcbPnNone + sizeof(PnSwitch); const int kcbPnTri = kcbPnNone + sizeof(PnTri); const int kcbPnTry = kcbPnNone + sizeof(PnTry); const int kcbPnTryCatch = kcbPnNone + sizeof(PnTryCatch); const int kcbPnTryFinally = kcbPnNone + sizeof(PnTryFinally); const int kcbPnUni = kcbPnNone + sizeof(PnUni); const int kcbPnUniSlot = kcbPnNone + sizeof(PnUniSlot); const int kcbPnVar = kcbPnNone + sizeof(PnVar); const int kcbPnWhile = kcbPnNone + sizeof(PnWhile); const int kcbPnWith = kcbPnNone + sizeof(PnWith); const int kcbPnParamPattern = kcbPnNone + sizeof(PnParamPattern); #define AssertNodeMem(pnode) AssertPvCb(pnode, kcbPnNone) #define AssertNodeMemN(pnode) AssertPvCbN(pnode, kcbPnNone)