[
  {
    "path": ".gitignore",
    "content": ".DS_Store\nwww.pid\n.commit-template\n*.php.diff\n*.php.out\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code of Conduct\nFacebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.fb.com/codeofconduct) so that you can understand what actions will and will not be tolerated."
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "## Contributing to the Specification for Hack\n\nWe'd love your help in improving, correcting, adding to the specification.\nPlease [file an issue](https://github.com/hhvm/hack-langspec/issues/) or submit a \npull request at the [spec git repo](https://github.com/hhvm/hack-langspec).\n\n## License for your Contributions\n\nAny contribution you provide to the Specification for Hack must adhere to the\nsame license as stated in the [LICENSE](LICENSE).\n"
  },
  {
    "path": "FORMATTING.md",
    "content": "# Formatting rules\n\n1. The format of the Hack Language Specification is\n   [Markdown](http://daringfireball.net/projects/markdown/).\n2. Everything in the actual specification document must be ASCII only.\n3. The only allowed extensions to original Markdown are tables and code blocks\n   (indicated by three backticks).\n4. Style\n  * Use spaces to indent, not tabs.\n  * For headings, use prefixed hash symbols `# Example`, not underlining it\n    with `===`.\n  * Use of *inline* links `[example](http://example.org)` is preferred over\n    *reference* links `[example][xmpl]` unless used multiple times in a\n    paragraph or section. This is to allow for easier splitting and\n    reorganization of the document.\n  * Try to stick to 80 chars wide, if possible. This is not as strict as\n    in coding standard rules, but still easier to read most of the times.\n    This does only apply to text, not to code examples or tables.\n"
  },
  {
    "path": "LICENSE",
    "content": "Facebook has dedicated all copyright to this specification to the public \ndomain worldwide under the CC0 Public Domain Dedication located at \n<http://creativecommons.org/publicdomain/zero/1.0/>. \n\nThe first draft of this specification was initially written in 2015 by\nFacebook, Inc.\n\nThis specification is distributed without any warranty.\n\n"
  },
  {
    "path": "README.md",
    "content": "## Deprecated, Unmaintained\n\nThis repo contains the Hack Language Specification, a modified version\nof the PHP specification. It is no longer maintained and does not\nreflect the current version of Hack.\n\n# Hack Language Specification\n\nThe easiest way to navigate the specification is\nvia the [table of contents](https://github.com/hhvm/hack-langspec/blob/master/spec/00-specification-for-hack.md).\n\nThe latest official release of the specification is [1.1](https://github.com/hhvm/hack-langspec/releases/tag/v1.1).\n\nYou can run the specification tests with [HHVM](https://docs.hhvm.com/hhvm/) via its\n[test runner](https://github.com/facebook/hhvm/blob/master/hphp/test/README.md) and the\n[Hack typechecker](https://docs.hhvm.com/hack/typechecker/introduction) via `hh_client`.\n\nPull requests, issue filings and comments are extremely welcome.\n\nMake sure you understand the [*contribution process*](CONTRIBUTING.md).\n"
  },
  {
    "path": "spec/00-specification-for-hack.md",
    "content": "<!-- This file is autogenerated, do not edit it manually -->\n<!-- Run tools/toc.php instead -->\n\n# Specification for Hack\nFacebook has dedicated all copyright to this specification to the public\ndomain worldwide under the CC0 Public Domain Dedication located at\n<http://creativecommons.org/publicdomain/zero/1.0/>. This specification\nis distributed without any warranty.\n\n(Initially written by Facebook, Inc., February 2015)\n\n**Table of Contents**\n- [Introduction](01-introduction.md#introduction)\n- [Conformance](02-conformance.md#conformance)\n- [Terms and Definitions](03-terms-and-definitions.md#terms-and-definitions)\n- [Basic Concepts](04-basic-concepts.md#basic-concepts)\n  - [Program Structure](04-basic-concepts.md#program-structure)\n  - [Program Start-Up](04-basic-concepts.md#program-start-up)\n  - [Program Termination](04-basic-concepts.md#program-termination)\n  - [The Memory Model](04-basic-concepts.md#the-memory-model)\n    - [General](04-basic-concepts.md#general)\n    - [Reclamation and Automatic Memory Management](04-basic-concepts.md#reclamation-and-automatic-memory-management)\n    - [Assignment](04-basic-concepts.md#assignment)\n      - [General](04-basic-concepts.md#general-1)\n      - [Value Assignment of Scalar Types to a Local Variable](04-basic-concepts.md#value-assignment-of-scalar-types-to-a-local-variable)\n      - [Value Assignment of Object and Resource Types to a Local Variable](04-basic-concepts.md#value-assignment-of-object-and-resource-types-to-a-local-variable)\n      - [ByRef Assignment for Scalar Types with Local Variables](04-basic-concepts.md#byref-assignment-for-scalar-types-with-local-variables)\n      - [Byref Assignment of Non-Scalar Types with Local Variables](04-basic-concepts.md#byref-assignment-of-non-scalar-types-with-local-variables)\n      - [Value Assignment of Array Types to Local Variables](04-basic-concepts.md#value-assignment-of-array-types-to-local-variables)\n      - [Deferred Array Copying](04-basic-concepts.md#deferred-array-copying)\n      - [General Value Assignment](04-basic-concepts.md#general-value-assignment)\n      - [General ByRef Assignment](04-basic-concepts.md#general-byref-assignment)\n    - [Argument Passing](04-basic-concepts.md#argument-passing)\n    - [Value Returning](04-basic-concepts.md#value-returning)\n    - [Cloning objects](04-basic-concepts.md#cloning-objects)\n  - [Scope](04-basic-concepts.md#scope)\n  - [Storage Duration](04-basic-concepts.md#storage-duration)\n- [Types](05-types.md#types)\n  - [General](05-types.md#general)\n  - [The Boolean Type](05-types.md#the-boolean-type)\n  - [The Integer Type](05-types.md#the-integer-type)\n  - [The Floating-Point Type](05-types.md#the-floating-point-type)\n  - [The Numeric Type](05-types.md#the-numeric-type)\n  - [The String Type](05-types.md#the-string-type)\n  - [The Array Key Type](05-types.md#the-array-key-type)\n  - [The Null Type](05-types.md#the-null-type)\n  - [Enumerated Types](05-types.md#enumerated-types)\n  - [The Void Type](05-types.md#the-void-type)\n  - [Array Types](05-types.md#array-types)\n  - [Class Types](05-types.md#class-types)\n  - [Interface Types](05-types.md#interface-types)\n  - [Trait Types](05-types.md#trait-types)\n  - [The `this` Type](05-types.md#the-this-type)\n  - [Tuple Types](05-types.md#tuple-types)\n  - [Shape Types](05-types.md#shape-types)\n  - [Closure Types](05-types.md#closure-types)\n  - [Resource Types](05-types.md#resource-types)\n  - [Nullable Types](05-types.md#nullable-types)\n  - [Generic Types](05-types.md#generic-types)\n  - [The Classname Type](05-types.md#the-classname-type)\n  - [Type Aliases](05-types.md#type-aliases)\n  - [Supertypes and Subtypes](05-types.md#supertypes-and-subtypes)\n  - [Type Side Effects](05-types.md#type-side-effects)\n  - [Type Inferencing](05-types.md#type-inferencing)\n- [Constants](06-constants.md#constants)\n  - [General](06-constants.md#general)\n  - [Context-Dependent Constants](06-constants.md#context-dependent-constants)\n  - [Core Predefined Constants](06-constants.md#core-predefined-constants)\n  - [User-Defined Constants](06-constants.md#user-defined-constants)\n- [Variables](07-variables.md#variables)\n  - [General](07-variables.md#general)\n  - [Kinds of Variables](07-variables.md#kinds-of-variables)\n    - [Local Variables](07-variables.md#local-variables)\n    - [Array Elements](07-variables.md#array-elements)\n    - [Function Statics](07-variables.md#function-statics)\n    - [Instance Properties](07-variables.md#instance-properties)\n    - [Static Properties](07-variables.md#static-properties)\n    - [Class and Interface Constants](07-variables.md#class-and-interface-constants)\n- [Conversions](08-conversions.md#conversions)\n  - [General](08-conversions.md#general)\n  - [Converting to Boolean Type](08-conversions.md#converting-to-boolean-type)\n  - [Converting to Integer Type](08-conversions.md#converting-to-integer-type)\n  - [Converting to Floating-Point Type](08-conversions.md#converting-to-floating-point-type)\n  - [Converting to Number Type](08-conversions.md#converting-to-number-type)\n  - [Converting to String Type](08-conversions.md#converting-to-string-type)\n  - [Converting to Array Key Type](08-conversions.md#converting-to-array-key-type)\n  - [Converting to Array Type](08-conversions.md#converting-to-array-type)\n  - [Converting to Object Type](08-conversions.md#converting-to-object-type)\n  - [Converting to Interface Type](08-conversions.md#converting-to-interface-type)\n  - [Converting to Resource Type](08-conversions.md#converting-to-resource-type)\n  - [Converting to Mixed Type](08-conversions.md#converting-to-mixed-type)\n- [Lexical Structure](09-lexical-structure.md#lexical-structure)\n  - [Scripts](09-lexical-structure.md#scripts)\n  - [Grammars](09-lexical-structure.md#grammars)\n  - [Grammar ambiguities](09-lexical-structure.md#grammar-ambiguities)\n  - [Lexical Analysis](09-lexical-structure.md#lexical-analysis)\n    - [General](09-lexical-structure.md#general)\n    - [Comments](09-lexical-structure.md#comments)\n    - [White Space](09-lexical-structure.md#white-space)\n    - [Tokens](09-lexical-structure.md#tokens)\n      - [General](09-lexical-structure.md#general-1)\n      - [Names](09-lexical-structure.md#names)\n      - [Keywords](09-lexical-structure.md#keywords)\n      - [Literals](09-lexical-structure.md#literals)\n        - [General](09-lexical-structure.md#general-2)\n        - [Boolean Literals](09-lexical-structure.md#boolean-literals)\n        - [Integer Literals](09-lexical-structure.md#integer-literals)\n        - [Floating-Point Literals](09-lexical-structure.md#floating-point-literals)\n        - [String Literals](09-lexical-structure.md#string-literals)\n          - [Single-Quoted String Literals](09-lexical-structure.md#single-quoted-string-literals)\n          - [Double-Quoted String Literals](09-lexical-structure.md#double-quoted-string-literals)\n          - [Heredoc String Literals](09-lexical-structure.md#heredoc-string-literals)\n          - [Nowdoc String Literals](09-lexical-structure.md#nowdoc-string-literals)\n        - [The Null Literal](09-lexical-structure.md#the-null-literal)\n      - [Operators and Punctuators](09-lexical-structure.md#operators-and-punctuators)\n- [Expressions](10-expressions.md#expressions)\n  - [General](10-expressions.md#general)\n  - [Restrictions on Arithmetic Operations](10-expressions.md#restrictions-on-arithmetic-operations)\n  - [Operations on Operands Having One or More Subtypes](10-expressions.md#operations-on-operands-having-one-or-more-subtypes)\n  - [Primary Expressions](10-expressions.md#primary-expressions)\n    - [General](10-expressions.md#general-1)\n    - [Intrinsics](10-expressions.md#intrinsics)\n      - [General](10-expressions.md#general-2)\n      - [array](10-expressions.md#array)\n      - [echo](10-expressions.md#echo)\n      - [exit](10-expressions.md#exit)\n      - [invariant](10-expressions.md#invariant)\n      - [list](10-expressions.md#list)\n    - [Collection Literals](10-expressions.md#collection-literals)\n    - [Tuple Literals](10-expressions.md#tuple-literals)\n    - [Shape Literals](10-expressions.md#shape-literals)\n    - [Anonymous Function-Creation](10-expressions.md#anonymous-function-creation)\n    - [Async Blocks](10-expressions.md#async-blocks)\n  - [Postfix Operators](10-expressions.md#postfix-operators)\n    - [General](10-expressions.md#general-3)\n    - [The `clone` Operator](10-expressions.md#the-clone-operator)\n    - [The `new` Operator](10-expressions.md#the-new-operator)\n    - [Array Creation Operator](10-expressions.md#array-creation-operator)\n    - [Subscript Operator](10-expressions.md#subscript-operator)\n    - [Function Call Operator](10-expressions.md#function-call-operator)\n    - [Member-Selection Operator](10-expressions.md#member-selection-operator)\n    - [Null-Safe Member-Selection Operator](10-expressions.md#null-safe-member-selection-operator)\n    - [Postfix Increment and Decrement Operators](10-expressions.md#postfix-increment-and-decrement-operators)\n    - [Scope-Resolution Operator](10-expressions.md#scope-resolution-operator)\n    - [Exponentiation Operator](10-expressions.md#exponentiation-operator)\n  - [Unary Operators](10-expressions.md#unary-operators)\n    - [General](10-expressions.md#general-4)\n    - [Prefix Increment and Decrement Operators](10-expressions.md#prefix-increment-and-decrement-operators)\n    - [Unary Arithmetic Operators](10-expressions.md#unary-arithmetic-operators)\n    - [Error Control Operator](10-expressions.md#error-control-operator)\n    - [Cast Operator](10-expressions.md#cast-operator)\n    - [Await Operator](10-expressions.md#await-operator)\n  - [`instanceof` Operator](10-expressions.md#instanceof-operator)\n  - [Multiplicative Operators](10-expressions.md#multiplicative-operators)\n  - [Additive Operators](10-expressions.md#additive-operators)\n  - [Bitwise Shift Operators](10-expressions.md#bitwise-shift-operators)\n  - [Relational Operators](10-expressions.md#relational-operators)\n  - [Equality Operators](10-expressions.md#equality-operators)\n  - [Bitwise AND Operator](10-expressions.md#bitwise-and-operator)\n  - [Bitwise Exclusive OR Operator](10-expressions.md#bitwise-exclusive-or-operator)\n  - [Bitwise Inclusive OR Operator](10-expressions.md#bitwise-inclusive-or-operator)\n  - [Logical AND Operator](10-expressions.md#logical-and-operator)\n  - [Logical Inclusive OR Operator](10-expressions.md#logical-inclusive-or-operator)\n  - [Conditional Operator](10-expressions.md#conditional-operator)\n  - [Coalesce Operator](10-expressions.md#coalesce-operator)\n  - [Pipe Operator](10-expressions.md#pipe-operator)\n  - [Lambda Expressions](10-expressions.md#lambda-expressions)\n  - [Assignment Operators](10-expressions.md#assignment-operators)\n    - [General](10-expressions.md#general-5)\n    - [Simple Assignment](10-expressions.md#simple-assignment)\n    - [Compound Assignment](10-expressions.md#compound-assignment)\n  - [`yield` Operator](10-expressions.md#yield-operator)\n  - [Constant Expressions](10-expressions.md#constant-expressions)\n- [Statements](11-statements.md#statements)\n  - [General](11-statements.md#general)\n  - [Compound Statements](11-statements.md#compound-statements)\n  - [Labeled Statements](11-statements.md#labeled-statements)\n  - [Expression Statements](11-statements.md#expression-statements)\n  - [Selection Statements](11-statements.md#selection-statements)\n    - [General](11-statements.md#general-1)\n    - [The `if` Statement](11-statements.md#the-if-statement)\n    - [The `switch` Statement](11-statements.md#the-switch-statement)\n  - [Iteration Statements](11-statements.md#iteration-statements)\n    - [General](11-statements.md#general-2)\n    - [The `while` Statement](11-statements.md#the-while-statement)\n    - [The `do` Statement](11-statements.md#the-do-statement)\n    - [The `for` Statement](11-statements.md#the-for-statement)\n    - [The `foreach` Statement](11-statements.md#the-foreach-statement)\n  - [Jump Statements](11-statements.md#jump-statements)\n    - [General](11-statements.md#general-3)\n    - [The `continue` Statement](11-statements.md#the-continue-statement)\n    - [The `break` Statement](11-statements.md#the-break-statement)\n    - [The `return` Statement](11-statements.md#the-return-statement)\n    - [The `throw` Statement](11-statements.md#the-throw-statement)\n  - [The `try` Statement](11-statements.md#the-try-statement)\n- [Script Inclusion Operators](12-script-inclusion.md#script-inclusion-operators)\n  - [General](12-script-inclusion.md#general)\n  - [The `require` Directive](12-script-inclusion.md#the-require-directive)\n  - [The `require_once` Directive](12-script-inclusion.md#the-require_once-directive)\n- [Enums](13-enums.md#enums)\n  - [General](13-enums.md#general)\n  - [Enum Declarations](13-enums.md#enum-declarations)\n  - [The Predefined Enumerated Type Methods](13-enums.md#the-predefined-enumerated-type-methods)\n- [Generic Types, Methods, and Functions](14-generic-types-methods-and-functions.md#generic-types-methods-and-functions)\n  - [General](14-generic-types-methods-and-functions.md#general)\n  - [Type Parameters](14-generic-types-methods-and-functions.md#type-parameters)\n  - [Type Constraints](14-generic-types-methods-and-functions.md#type-constraints)\n  - [Type Arguments](14-generic-types-methods-and-functions.md#type-arguments)\n  - [Open and Closed Generic Types](14-generic-types-methods-and-functions.md#open-and-closed-generic-types)\n  - [Type Inferencing Revisited](14-generic-types-methods-and-functions.md#type-inferencing-revisited)\n- [Functions](15-functions.md#functions)\n  - [General](15-functions.md#general)\n  - [Function Calls](15-functions.md#function-calls)\n  - [Function Definitions](15-functions.md#function-definitions)\n  - [Anonymous Functions](15-functions.md#anonymous-functions)\n  - [Asynchronous Functions](15-functions.md#asynchronous-functions)\n- [Classes](16-classes.md#classes)\n  - [General](16-classes.md#general)\n  - [Class Declarations](16-classes.md#class-declarations)\n  - [Class Members](16-classes.md#class-members)\n  - [Dynamic Methods](16-classes.md#dynamic-methods)\n  - [Constants](16-classes.md#constants)\n  - [Properties](16-classes.md#properties)\n  - [Methods](16-classes.md#methods)\n  - [Constructors](16-classes.md#constructors)\n  - [Destructors](16-classes.md#destructors)\n  - [Type Constants](16-classes.md#type-constants)\n  - [Methods with Special Semantics](16-classes.md#methods-with-special-semantics)\n    - [General](16-classes.md#general-1)\n    - [Method `__call`](16-classes.md#method-__call)\n    - [Method `__callStatic`](16-classes.md#method-__callstatic)\n    - [Method `__clone`](16-classes.md#method-__clone)\n    - [Method `__sleep`](16-classes.md#method-__sleep)\n    - [Method `__toString`](16-classes.md#method-__tostring)\n    - [Method `__wakeup`](16-classes.md#method-__wakeup)\n  - [Serialization](16-classes.md#serialization)\n  - [Predefined Classes](16-classes.md#predefined-classes)\n    - [Class `AsyncGenerator`](16-classes.md#class-asyncgenerator)\n    - [Class `Generator`](16-classes.md#class-generator)\n    - [Class `__PHP_Incomplete_Class`](16-classes.md#class-__php_incomplete_class)\n    - [Class `Shapes`](16-classes.md#class-shapes)\n    - [Class `stdClass`](16-classes.md#class-stdclass)\n- [Interfaces](17-interfaces.md#interfaces)\n  - [General](17-interfaces.md#general)\n  - [Interface Declarations](17-interfaces.md#interface-declarations)\n  - [Interface Members](17-interfaces.md#interface-members)\n  - [Constants](17-interfaces.md#constants)\n  - [Methods](17-interfaces.md#methods)\n  - [Predefined Interfaces](17-interfaces.md#predefined-interfaces)\n    - [Interface `ArrayAccess`](17-interfaces.md#interface-arrayaccess)\n    - [Interface `AsyncIterator`](17-interfaces.md#interface-asynciterator)\n    - [Interface `AsyncKeyedIterator`](17-interfaces.md#interface-asynckeyediterator)\n    - [Interface `Awaitable`](17-interfaces.md#interface-awaitable)\n    - [Interface `Container`](17-interfaces.md#interface-container)\n    - [Interface `IMemoizeParam`](17-interfaces.md#interface-imemoizeparam)\n    - [Interface `Iterator`](17-interfaces.md#interface-iterator)\n    - [Interface `IteratorAggregate`](17-interfaces.md#interface-iteratoraggregate)\n    - [Interface `KeyedContainer`](17-interfaces.md#interface-keyedcontainer)\n    - [Interface `KeyedTraversable`](17-interfaces.md#interface-keyedtraversable)\n    - [Interface  `Serializable`](17-interfaces.md#interface--serializable)\n    - [Interface `Stringish`](17-interfaces.md#interface-stringish)\n    - [Interface `Traversable`](17-interfaces.md#interface-traversable)\n- [Traits](18-traits.md#traits)\n  - [General](18-traits.md#general)\n  - [Trait Declarations](18-traits.md#trait-declarations)\n  - [Trait Members](18-traits.md#trait-members)\n- [Exception Handling](19-exception-handling.md#exception-handling)\n  - [General](19-exception-handling.md#general)\n  - [Class `Exception`](19-exception-handling.md#class-exception)\n  - [Tracing Exceptions](19-exception-handling.md#tracing-exceptions)\n  - [User-Defined Exception Classes](19-exception-handling.md#user-defined-exception-classes)\n- [Namespaces](20-namespaces.md#namespaces)\n  - [General](20-namespaces.md#general)\n  - [Name Lookup](20-namespaces.md#name-lookup)\n  - [Defining Namespaces](20-namespaces.md#defining-namespaces)\n  - [Namespace Use Declarations**](20-namespaces.md#namespace-use-declarations)\n- [Attributes](21-attributes.md#attributes)\n  - [General](21-attributes.md#general)\n  - [Attribute Specification](21-attributes.md#attribute-specification)\n  - [Predefined Attributes](21-attributes.md#predefined-attributes)\n    - [General](21-attributes.md#general-1)\n    - [Attribute `__ConsistentConstruct`](21-attributes.md#attribute-__consistentconstruct)\n    - [Attribute `__Memoize`](21-attributes.md#attribute-__memoize)\n    - [Attribute `__Override`](21-attributes.md#attribute-__override)\n- [Grammar](22-grammar.md#grammar)\n  - [General](22-grammar.md#general)\n  - [Lexical Grammar](22-grammar.md#lexical-grammar)\n    - [General](22-grammar.md#general-1)\n    - [Comments](22-grammar.md#comments)\n    - [White Space](22-grammar.md#white-space)\n    - [Tokens](22-grammar.md#tokens)\n      - [General](22-grammar.md#general-2)\n      - [Names](22-grammar.md#names)\n    - [Keywords](22-grammar.md#keywords)\n    - [Literals](22-grammar.md#literals)\n      - [General](22-grammar.md#general-3)\n      - [Boolean Literals](22-grammar.md#boolean-literals)\n      - [Integer Literals](22-grammar.md#integer-literals)\n      - [Floating-Point Literals](22-grammar.md#floating-point-literals)\n      - [String Literals](22-grammar.md#string-literals)\n      - [The Null Literal](22-grammar.md#the-null-literal)\n    - [Operators and Punctuators](22-grammar.md#operators-and-punctuators)\n  - [Syntactic Grammar](22-grammar.md#syntactic-grammar)\n    - [Program Structure](22-grammar.md#program-structure)\n    - [Types](22-grammar.md#types)\n      - [General](22-grammar.md#general-4)\n      - [Array Types](22-grammar.md#array-types)\n      - [Tuple Types](22-grammar.md#tuple-types)\n      - [Shape Types](22-grammar.md#shape-types)\n      - [Closure Types](22-grammar.md#closure-types)\n      - [Nullable Types](22-grammar.md#nullable-types)\n      - [The Classname Type](22-grammar.md#the-classname-type)\n      - [Type Aliases](22-grammar.md#type-aliases)\n    - [Variables](22-grammar.md#variables)\n    - [Expressions](22-grammar.md#expressions)\n      - [Primary Expressions](22-grammar.md#primary-expressions)\n      - [Postfix Operators](22-grammar.md#postfix-operators)\n      - [Unary Operators](22-grammar.md#unary-operators)\n      - [instanceof Operator](22-grammar.md#instanceof-operator)\n      - [Multiplicative Operators](22-grammar.md#multiplicative-operators)\n      - [Additive Operators](22-grammar.md#additive-operators)\n      - [Bitwise Shift Operators](22-grammar.md#bitwise-shift-operators)\n      - [Relational Operators](22-grammar.md#relational-operators)\n      - [Equality Operators](22-grammar.md#equality-operators)\n      - [Bitwise Logical Operators](22-grammar.md#bitwise-logical-operators)\n      - [Logical Operators](22-grammar.md#logical-operators)\n      - [Conditional Operator](22-grammar.md#conditional-operator)\n      - [Pipe Operator](22-grammar.md#pipe-operator)\n      - [Lambda Expressions](22-grammar.md#lambda-expressions)\n      - [Assignment Operators](22-grammar.md#assignment-operators)\n      - [yield Operator](22-grammar.md#yield-operator)\n      - [Constant Expressions](22-grammar.md#constant-expressions)\n    - [Statements](22-grammar.md#statements)\n      - [General](22-grammar.md#general-5)\n      - [Compound Statements](22-grammar.md#compound-statements)\n      - [Labeled Statements](22-grammar.md#labeled-statements)\n      - [Expression Statements](22-grammar.md#expression-statements)\n      - [Iteration Statements](22-grammar.md#iteration-statements)\n      - [Jump Statements](22-grammar.md#jump-statements)\n      - [The try Statement](22-grammar.md#the-try-statement)\n    - [Script Inclusion](22-grammar.md#script-inclusion)\n    - [Enums](22-grammar.md#enums)\n    - [Generic Types, Methods and Functions](22-grammar.md#generic-types-methods-and-functions)\n    - [Functions](22-grammar.md#functions)\n    - [Classes](22-grammar.md#classes)\n    - [Interfaces](22-grammar.md#interfaces)\n    - [Traits](22-grammar.md#traits)\n    - [Namespaces](22-grammar.md#namespaces)\n    - [Attributes](22-grammar.md#attributes)\n- [Differences from PHP](23-differences-from-php.md#differences-from-php)\n  - [General](23-differences-from-php.md#general)\n  - [Program Start-Up](23-differences-from-php.md#program-start-up)\n  - [Constants](23-differences-from-php.md#constants)\n  - [Variables](23-differences-from-php.md#variables)\n  - [Conversions](23-differences-from-php.md#conversions)\n  - [Lexical Structure](23-differences-from-php.md#lexical-structure)\n    - [Comments](23-differences-from-php.md#comments)\n    - [Names](23-differences-from-php.md#names)\n    - [Keywords](23-differences-from-php.md#keywords)\n  - [Expressions](23-differences-from-php.md#expressions)\n    - [Primary Expressions](23-differences-from-php.md#primary-expressions)\n      - [General](23-differences-from-php.md#general-1)\n      - [Intrinsics](23-differences-from-php.md#intrinsics)\n      - [Anonymous Function-Creation](23-differences-from-php.md#anonymous-function-creation)\n    - [Postfix Operators](23-differences-from-php.md#postfix-operators)\n      - [The `new` Operator](23-differences-from-php.md#the-new-operator)\n      - [Array Creation Operator](23-differences-from-php.md#array-creation-operator)\n      - [Function call operator](23-differences-from-php.md#function-call-operator)\n      - [Member-Selection Operator](23-differences-from-php.md#member-selection-operator)\n      - [Postfix Increment and Decrement Operators](23-differences-from-php.md#postfix-increment-and-decrement-operators)\n      - [Exponentiation Operator](23-differences-from-php.md#exponentiation-operator)\n    - [Unary Operators](23-differences-from-php.md#unary-operators)\n      - [Prefix Increment and Decrement Operators](23-differences-from-php.md#prefix-increment-and-decrement-operators)\n      - [Unary Arithmetic Operators](23-differences-from-php.md#unary-arithmetic-operators)\n      - [Shell Command Operator](23-differences-from-php.md#shell-command-operator)\n      - [Cast Operator](23-differences-from-php.md#cast-operator)\n      - [Variable-Name Creation Operator](23-differences-from-php.md#variable-name-creation-operator)\n    - [`instanceof` Operator](23-differences-from-php.md#instanceof-operator)\n    - [Multiplicative Operators](23-differences-from-php.md#multiplicative-operators)\n    - [Bitwise Shift Operators](23-differences-from-php.md#bitwise-shift-operators)\n    - [Bitwise `AND` Operator](23-differences-from-php.md#bitwise-and-operator)\n    - [Bitwise Exclusive `OR` Operator](23-differences-from-php.md#bitwise-exclusive-or-operator)\n    - [Bitwise Inclusive `OR` Operator](23-differences-from-php.md#bitwise-inclusive-or-operator)\n    - [Assignment Operators](23-differences-from-php.md#assignment-operators)\n      - [byRef Assignment](23-differences-from-php.md#byref-assignment)\n    - [Logical `AND`, `OR`, `XOR` Operators (Alternate Forms)](23-differences-from-php.md#logical-and-or-xor-operators-alternate-forms)\n    - [String Literals](23-differences-from-php.md#string-literals)\n  - [Statements](23-differences-from-php.md#statements)\n    - [General](23-differences-from-php.md#general-2)\n    - [Labeled Statements](23-differences-from-php.md#labeled-statements)\n    - [The `if` Statement](23-differences-from-php.md#the-if-statement)\n    - [The `switch` Statement](23-differences-from-php.md#the-switch-statement)\n    - [The `while` Statement](23-differences-from-php.md#the-while-statement)\n    - [The `for` Statement](23-differences-from-php.md#the-for-statement)\n    - [The `foreach` Statement](23-differences-from-php.md#the-foreach-statement)\n    - [The `goto` Statement](23-differences-from-php.md#the-goto-statement)\n    - [The `continue` Statement](23-differences-from-php.md#the-continue-statement)\n    - [The `break` Statement](23-differences-from-php.md#the-break-statement)\n    - [The `return` Statement](23-differences-from-php.md#the-return-statement)\n    - [The declare Statement](23-differences-from-php.md#the-declare-statement)\n  - [Script Inclusion](23-differences-from-php.md#script-inclusion)\n  - [Functions](23-differences-from-php.md#functions)\n  - [Classes](23-differences-from-php.md#classes)\n    - [Class Members](23-differences-from-php.md#class-members)\n    - [Dynamic Members](23-differences-from-php.md#dynamic-members)\n    - [Properties](23-differences-from-php.md#properties)\n    - [Methods](23-differences-from-php.md#methods)\n    - [Constructors](23-differences-from-php.md#constructors)\n    - [Methods with Special Semantics](23-differences-from-php.md#methods-with-special-semantics)\n      - [General](23-differences-from-php.md#general-3)\n      - [Method `__call`](23-differences-from-php.md#method-__call)\n      - [Method `__get`](23-differences-from-php.md#method-__get)\n      - [Method `__invoke`](23-differences-from-php.md#method-__invoke)\n      - [Method __isset](23-differences-from-php.md#method-__isset)\n      - [Method __set](23-differences-from-php.md#method-__set)\n      - [Method __set_state](23-differences-from-php.md#method-__set_state)\n      - [Method __unset](23-differences-from-php.md#method-__unset)\n    - [Predefined Classes](23-differences-from-php.md#predefined-classes)\n      - [Class Closure](23-differences-from-php.md#class-closure)\n  - [Interfaces](23-differences-from-php.md#interfaces)\n    - [Interface Members](23-differences-from-php.md#interface-members)\n    - [Methods](23-differences-from-php.md#methods-1)\n    - [Predefined Interfaces](23-differences-from-php.md#predefined-interfaces)\n  - [Traits](23-differences-from-php.md#traits)\n    - [Trait Declarations](23-differences-from-php.md#trait-declarations)\n  - [Namespaces](23-differences-from-php.md#namespaces)\n    - [Namespace Use Declarations](23-differences-from-php.md#namespace-use-declarations)\n- [Bibliography](24-bibliography.md#bibliography)\n"
  },
  {
    "path": "spec/01-introduction.md",
    "content": "# Introduction\nThis specification is intended to provide a complete and concise\ndefinition of the syntax and semantics of the Hack language, suitable for\nuse by the following:\n\n-   Developers of a Hack implementation\n-   Implementers of a test suite for the Hack language\n-   Programmers writing Hack code\n\nFor now, the runtime library has been excluded, as that is documented at [www.php.net](http://www.php.net) and [docs.hhvm.com](http://docs.hhvm.com). As such, all forward references to library facilities have placeholders of the form (§xx).\n"
  },
  {
    "path": "spec/02-conformance.md",
    "content": "# Conformance\nIn this specification, \"must\" is to be interpreted as a requirement on\nan implementation or on a program; conversely, \"must not\" is to be\ninterpreted as a prohibition.\n\nIf a \"must\" or \"must not\" requirement that appears outside of a\nconstraint is violated, the behavior is undefined. Undefined behavior is\notherwise indicated in this specification by the words \"undefined\nbehavior\" or by the omission of any explicit definition of behavior.\nThere is no difference in emphasis among these three; they all describe\n\"behavior that is undefined\".\n\nThe word \"may\" indicates \"permission\", and is never used to mean\n\"might\".\n\nA *strictly conforming program* must use only those features of the\nlanguage described in this specification. In particular, it must not\nproduce output dependent on any unspecified, undefined, or\nimplementation-defined behavior.\n\nA *conforming implementation* must accept any strictly conforming\nprogram. A conforming implementation may have extensions, provided they\ndo not alter the behavior of any strictly conforming program.\n\nA *conforming program* is one that is acceptable to a conforming\nimplementation.\n\nA conforming implementation must be accompanied by a document that\ndefines all implementation-defined characteristics and all extensions.\n\nSome Syntax sections are followed by a Constraints section, which\nfurther restricts the grammar. After issuing a diagnostic for a\nconstraint violation, a conforming implementation may continue program\nexecution. In some cases, such continuation behavior is documented.\nMaking such things constraint violations simply forces the issuance of a\ndiagnostic; it does not require that program execution terminate.\n\nThis specification contains explanatory material—called *informative* or\n*non-normative* text—that, strictly speaking, is not necessary in a\nformal language specification. Examples are provided to illustrate\npossible forms of the constructions described. References are used to\nrefer to related clauses. Notes and Implementer Notes are provided to\ngive advice or guidance to implementers or programmers. Informative\nannexes provide additional information and summarize the information\ncontained in this specification. All text not marked as informative is\n*normative*.\n\nCertain features are marked as *deprecated*. While these are normative\nfor the current edition of this specification, they are not guaranteed\nto exist in future revisions. Usually, they are old approaches that have\nbeen superseded by new ones, and use of the old approach is discouraged.\n(Examples of this include the use of braces ({ }) for subscripting.)\n\n"
  },
  {
    "path": "spec/03-terms-and-definitions.md",
    "content": "# Terms and Definitions\nFor the purposes of this document, the following terms and definitions\napply:\n\n<pre>\n\n  <b>argument:</b>\n    a value passed to a function, that is intended to map to a\n    corresponding parameter.\n      \n  <b>behavior:</b>\n    external appearance or action.\n\n  <b>behavior, implementation-defined:</b>\n    behavior specific to an implementation, where that implementation\n    must document that behavior.\n\n  <b>behavior, undefined:</b>\n    behavior which is not guaranteed to\n    produce any specific result. Usually follows an erroneous program\n    construct or data.\n\n  <b>behavior, unspecified:</b>\n    behavior for which this specification provides no requirements.\n\n  <b>case-preserved:</b>\n    a construct which is case-insensitive upon declaration, but\n    case-sensitive upon subsequent usage.\n\n  <b>constraint:</b>\n    restriction, either syntactic or semantic, on how language elements\n    can be used.\n\n  <b>error, fatal:</b>\n    a translation or runtime condition from which the translator or\n    engine cannot recover.\n\n  <b>error, fatal, catchable:</b>\n    a fatal error that can be caught by a user-defined handler.\n\n  <b>error, non-fatal:</b>\n    an error that is not fatal.\n\n  <b>lvalue:</b>\n    an expression that designates a memory location having a type.\n\n  <b>lvalue, modifiable:</b>\n    an lvalue whose value can be changed.\n\n  <b>lvalue, non-modifiable:</b>\n    an lvalue whose value cannot be changed.\n\n  <b>parameter:</b>\n    a variable declared in the parameter list of a function that is\n    intended to map to a corresponding argument in a call to that\n    function.\n\n  <b>Hack Run-Time Engine:</b>\n    the machinery that executes a Hack program. Referred to as *the\n    Engine* throughout this specification.\n\n  <b>value:</b>\n    precise meaning of the contents of a memory location when\n    interpreted as having a specific type.\n</pre>\n\nOther terms are defined throughout this specification, as needed, with\nthe first usage being typeset *like this*.\n"
  },
  {
    "path": "spec/04-basic-concepts.md",
    "content": "# Basic Concepts\n## Program Structure\nA Hack *program* consists of one or more source files, known formally as\n*scripts*.\n\n<pre>\n<i>script:\n  </i>&lt;?hh // strict\n  <i>declaration-list<sub>opt</sub></i>\n\n<i>declaration-list:</i>\n  <i>declaration</i>\n  <i>declaration-list</i> <i>declaration</i>\n\n<i>declaration:</i>\n  <i>inclusion-directive</i>\n  <i>enum-declaration</i>\n  <i>function-definition</i>\n  <i>class-declaration</i>\n  <i>interface-declaration</i>\n  <i>trait-declaration</i>\n  <i>namespace-definition</i>\n  <i>namespace-use-declaration</i>\n  <i>alias-declaration</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*alias-declaration*](05-types.md#type-aliases)\n* [*class-declaration*](16-classes.md#class-declarations)\n* [*enum-declaration*](13-enums.md#enum-declarations)\n* [*function-definition*](15-functions.md#function-definitions)\n* [*inclusion-directive*](12-script-inclusion.md#general)\n* [*interface-declaration*](17-interfaces.md#interface-declarations)\n* [*namespace-definition*](20-namespaces.md#defining-namespaces)\n* [*namespace-use-declaration*](20-namespaces.md#namespace-use-declarations)\n* [*trait-declaration*](18-traits.md#trait-declarations)\n\nA Hack script can be processed in any one of a number of *modes*, of which\n`strict` is one. This mode is specified in a [*special single-line-comment*](09-lexical-structure.md#comments), on the first source line, as shown. This comment may be separated\nfrom the preceding &lt;?hh by an arbitrary amount of [horizontal white space](09-lexical-structure.md#white-space), which must not include any [*delimited-comments*](09-lexical-structure.md#comments). This\nspecification is written from the perspective of strict mode only. A\nconforming implementation may provide modes other than `strict`, but they are\noutside the scope of this specification.\n\nA script can import another script via [script inclusion](12-script-inclusion.md#script-inclusion-operators).\n\nThe top level of a script is simply referred to as the *top level*.\n\n## Program Start-Up\nOnce the start-up function begins execution, it is implementation-defined as\nto whether it has access to things like command-line arguments and environment\nvariables. [PHP's global variables `$argc` and `$argv` are not available in\n`strict` mode.]\n\n## Program Termination\nA program may terminate normally in the following ways:\n\n-   A [`return` statement](11-statements.md#the-return-statement) in the start-up function is executed.\n-   The intrinsic [`exit`](10-expressions.md#exit) is called explicitly.\n\nThe behavior of the first case is equivalent to corresponding calls\nto `exit`.\n\nA program may terminate abnormally under various circumstances, such as\nthe detection of an uncaught exception, or the lack of memory or other\ncritical resource. If execution reaches the end of the start-up script\nvia a fatal error, or via an uncaught exception and there is no uncaught\nexception handler registered by `set_exception_handler`, that is\nequivalent to `exit(255)`. If execution reaches the end of the start-up\nscript via an uncaught exception and an uncaught exception handler was\nregistered by `set_exception_handler`, that is equivalent to exit(0). It\nis unspecified whether [object destructors](16-classes.md#destructors) are run. In all other cases,\nthe behavior is unspecified.\n\n## The Memory Model\n### General\nThis section and those immediately following it describe the abstract\nmemory model used by Hack for storing variables. A conforming\nimplementation may use whatever approach is desired as long as from any\ntestable viewpoint it appears to behave as if it follows this abstract\nmodel. The abstract model makes no explicit or implied restrictions or\nclaims about performance, memory consumption, and machine resource\nusage.\n\nThe abstract model presented here defines three kinds of abstract memory\nlocations:\n\n-   A *value storage location* (VStore) is used to represent a program\n    value, and is created by the Engine as needed. A VStore can contain\n    a scalar value such as an integer or a Boolean, or it can contain a\n    handle pointing to an HStore (see below).\n-   A *variable slot* (VSlot) is used to represent a variable named by\n    the programmer in the source code, such as a local variable, an\n    array element, an instance property of an object, or a static\n    property of a class. A VSlot comes into being based on explicit\n    usage of a variable in the source code. A VSlot contains a pointer\n    to a VStore.\n-   A *heap storage location* (HStore) is used to represent the contents\n    of any non-scalar value, and is created by the Engine as needed.\n\nEach existing variable has its own VSlot, which at any time contains a\npointer to a VStore. A VSlot cannot contain a null pointer. A VSlot can\nbe changed to point to different VStores over time. Multiple VSlots may\nsimultaneously point to the same VStore. When a new VSlot is created, a\nnew VStore is also created and the VSlot is initially set to point to\nthe new VStore.\n\nA VStore can be changed to contain different scalar values and handles\nover time. Multiple VStores may simultaneously contain handles that\npoint to the same HStore. When a VStore is created it initially contains\nthe scalar value `null` unless specified otherwise. In addition to\ncontaining a value, VStores also carry a *type tag* that indicates the [type](05-types.md#types) of the VStore’s value. A VStore’s type tag can be changed over\ntime. At any given time a VStore’s type tag may be one of the following:\n`Null`, `Bool`, `Int`, `Float`, `Str`, `Arr`, `Arr-D` (see [§§](#deferred-array-copying)), `Obj`, or `Res`.\n\nAn HStore represents the contents of a non-scalar value, and it may\ncontain zero or more VSlots. At run time, the Engine may add new VSlots\nand it may remove and destroy existing VSlots as needed to support\nadding/removing array elements (for arrays) and to support\nadding/removing instance properties (for objects). HStores that\nrepresent the contents of arrays and objects have some unspecified way\nto identify and retrieve a contained VSlot using a dictionary scheme\n(such as having values with integer keys or case-sensitive string keys).\nWhether an HStore is a fixed-size during its whole lifetime or whether\nit can change size, is unspecified. Whether it allocates auxiliary\nchunks of memory or not, is unspecified. Whether it organizes it's\ncontained VSlots in a linked list or some other manner is unspecified.\n\nAn HStore’s VSlots (i.e., the VSlots contained within the HStore) point\nto VStores, and each VStore contains a scalar value or a handle to an\nHStore, and so on through arbitrary levels, allowing arbitrarily complex\ndata structures to be represented. For example, a singly linked list\nmight consist of a variable called `$root`, which is represented by a\nVSlot pointing to a VStore containing a handle to the first node. Each\nnode is represented by an HStore that contains the data for that node in\none or more VSlots, as well as a VSlot pointing to VStore containing a\nhandle to the next node. Similarly, a binary tree might consist of a\nvariable called `$root`, which is represented by a VSlot pointing to a\nVStore containing a handle to the root node. Each node is represented by\nan HStore that contains the data for that node in one or more VSlots, as\nwell as a pair of VSlots pointing to VStores containing the handles to\nthe left and right branch nodes. The leaves of the tree would be VStores\nor HStores, as needed.\n\nVSlots cannot contain pointers to VSlots or handles to HStores. VStores\ncannot contain pointers to VSlots or VStores. HStores cannot directly\ncontain any pointers or handles to any abstract memory location; HStores\ncan only directly contain VSlots.\n\nHere is an example demonstrating one possible arrangement of VSlots,\nVStores, and HStores:\n\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                                        |            |\n                                                        V            V\n                                                [VStore Int 1]  [VStore Int 3]\n</pre>\n\nIn this picture the VSlot in the upper left corner represents the\nvariable `$a`, and it points to a VStore that represents `$a`’s current\nvalue. This VStore contains a handle to an HStore which represents the\ncontents of an object of type Point with two instance properties `$x`\nand `$y`. This HStore contains two VSlots representing instance\nproperties `$x` and `$y`, and each of these VSlots points to a distinct\nVStore which contains an integer value. \n\n***Implementation Notes*** A concrete implementation of Hack may be mapped roughly\nonto the abstract memory model as follows: `zval pointer => VSlot, zval\n=> VStore, HashTable => HStore`, and\n`zend_object/zend_object_handlers => HStore`. Note, however, that the\nabstract memory model is not intended to exactly match any specific\nimplementation’s model, and for generality and simplicity there may be some\nsuperficial differences between the described model and an implementation's model.\n\nFor most operations, the mapping between VSlots and VStores remains the\nsame. Only the following program constructs can change a VSlot to point\nto different VStore: the use of `&` in a [`foreach` statement](11-statements.md#the-foreach-statement).\n\n### Reclamation and Automatic Memory Management\nThe Engine is required to manage the lifetimes of VStores and HStores\nusing some form of automatic memory management.\n\nWhen dealing with VStores and HStores, the Engine is required to implement\nsome form of automatic memory management. When a VStore or HStore\nis created, memory is allocated for it, and for an HStore that represents\nan [object](05-types.md#class-types), its [constructor](16-classes.md#constructors) is invoked.\n\nLater, if a VStore or HStore becomes unreachable through any existing\nvariable, they become eligible for reclamation to release the memory\nthey occupy. The engine may reclaim a VStore or HStore at any time\nbetween when it becomes eligible for reclamation and when the script\nexits. Before reclaiming an HStore that represents an [object](05-types.md#class-types),\nthe Engine will invoke the object’s [destructor](16-classes.md#destructors) if one is defined.\n\nThe Engine must reclaim each VSlot when the [storage duration](#storage-duration) of its\ncorresponding variable ends, when the variable is explicitly unset by the\nprogrammer, or when the script exits, whichever comes first. In the case where\na VSlot is contained within an HStore (i.e. an array element or an object\ninstance property), the engine must immediate reclaim the VSlot when it is\nexplicitly unset by the programmer, when the containing HStore is reclaimed,\nor when the script exits, whichever comes first.\n\nThe precise form of automatic memory management used by the Engine is\nunspecified, which means that the time and order of the reclamation of\nVStores and HStores is unspecified.\n\nA VStore’s refcount is defined as the number of unreclaimed VSlots that point\nto the VStore. Because the precise form of automatic memory management is not\nspecified, a VStore’s refcount at a given time may differ between\nconforming implementations due to VSlots, VStores, and HStores being\nreclaimed at different times. Despite the use of the term refcount,\nconforming implementations are not required to use a reference\ncounting-based implementation for automatic memory management.\n\n### Assignment\n#### General\nThis section and those immediately following it describe the abstract\nmodel’s implementation of *value assignment* and *byRef assignment*.\nValue assignment of non-array types to local variables is described\nfirst, followed by byRef assignment with local variables, followed by\nvalue assignment of array types to local variables, and ending with\nvalue assignment with complex left-hand side expressions, and byRef\nassignment with complex expressions on the left- or right-hand side.\n\nValue assignment and byRef assignment are core to HHVM, the Engine which\nsupports the  PHP and Hack languages. Many other operations in the PHP and\nHack specification are described in terms of value assignment. On the other\nhand, byRef assignment is used only by PHP, not by Hack. However, a discussion\nof such assignment has been retained here for historical reference.\n\n#### Value Assignment of Scalar Types to a Local Variable\nValue assignment is the primary means by which the programmer can create\nlocal variables. If a local variable appears on the left-hand side of\nvalue assignment does not exist, the engine will bring a new local\nvariable into existence and create a VSlot and initial VStore for\nstoring the local variable’s value.\n\nConsider the following example of [value assignment](10-expressions.md#simple-assignment) of scalar\nvalues to local variables:\n\n```Hack\n$a = 123;\n\n$b = false;\n```\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n\n[VSlot $b *]-->[VStore Bool false]\n</pre>\n\nVariable `$a` comes into existence and is represented by a newly created\nVSlot pointing to a newly created VStore. Then the integer value 123 is\nwritten to the VStore. Next, `$b` comes into existence represented by a\nVSlot and corresponding VStore, and the Boolean value false is written\nto the VStore.\n\nNext consider the value assignment `$b = $a`:\n\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n\n[VSlot $b *]-->[VStore Int 123 (Bool false was overwritten)]\n</pre>\n\nThe integer value 123 is read from `$a`’s VStore and is written into\n`$b`’s VStore, overwriting its previous contents. As we can see, the two\nvariables are completely self-contained; each has its own VStore\ncontaining a separate copy of the integer value 123. Value assignment\nreads the contents of one VStore and overwrites the contents of the\nother VStore, but the relationship of VSlots to VStores remains\nunchanged. Changing the value of `$b` has no effect on `$a`, and vice\nversa.\n\nUsing literals or arbitrarily complex expressions on the right hand side\nof value assignment value works the same as it does for variables,\nexcept that the literals or expressions don’t have their own VSlots or\nVStores. The scalar value or handle produced by the literal or\nexpression is written into the VStore of the left hand side, overwriting\nits previous contents.\n\n***Implementation Notes*** For simplicity, the abstract model’s\ndefinition of value assignment never changes the mapping from VSlots to\nVStores. This aspect of the abstract model is superficially different\nfrom the php.net implementation’s model, which in some cases will set\ntwo variable slots to point to the same zval when performing value\nassignment. Despite this superficial difference, php.net’s\nimplementation produces the same observable behavior as the abstract\nmodel presented here.\n\nTo illustrate the semantics of value assignment further, consider `++$b`:\n\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n\n[VSlot $b *]-->[VStore Int 124 (123 was overwritten)]\n</pre>\n\nNow consider `$a = 99`:\n\n<pre>\n[VSlot $a *]-->[VStore Int 99 (123 was overwritten)]\n\n[VSlot $b *]-->[VStore Int 124]\n</pre>\n\nIn both of these examples, one variable’s value is changed without\naffecting the other variable’s value. While the above examples only\ndemonstrate value assignment for integer and Boolean values, the same\nmechanics apply for all scalar types.\n\nNote that strings are also considered scalar values for the purposes of\nthe abstract memory model. Unlike non-scalar types which are represented\nusing a VStore pointing to an HStore containing the non-scalar value’s\ncontents, the abstract model assumes that a string’s entire contents\n(i.e., the string’s characters and its length) can be stored in a VStore\nand that value assignment for a string eagerly copies a string’s entire\ncontents to the VStore being written to. Consider the following example:\n\n```Hack\n$a = 'gg';\n\n$b = $a;\n```\n\n<pre>\n[VSlot $a *]-->[VStore Str 'gg']\n\n[VSlot $b *]-->[VStore Str 'gg']\n</pre>\n\n`$a`’s string value and `$b`’s string values are distinct from each other,\nand mutating `$a`’s string will not affect `$b`. Consider `++$b`, for\nexample:\n\n<pre>\n[VSlot $a *]-->[VStore Str 'gg']\n\n[VSlot $b *]-->[VStore Str 'gh']\n</pre>\n\n***Implementation Notes*** For simplicity, the abstract model represents\na string as a scalar value that can be entirely contained within VStore.\nThis aspect of the abstract model is superficially different from the\nphp.net implementation’s model, where a zval points to a separate buffer\nin memory containing a string’s characters and in the common case\nmultiple slots point to the same zval that holds the string. Despite\nthis superficial difference, php.net’s implementation produces the same\nobservable behavior (excluding performance and resource consumption) as\nthe abstract model presented here.\n\nBecause a string’s content can be arbitrarily large, copying a string’s\nentire contents for value assignment can be expensive. In practice an\napplication written in Hack may rely on value assignment of strings being\nrelatively inexpensive (in order to deliver acceptable performance), and\nas such it is common for an implementation to use a deferred copy\nmechanism to reduce the cost of value assignment for strings. Deferred\ncopy mechanisms work by not copying a string during value assignment and\ninstead allowing multiple variables to share the string’s contents\nindefinitely until a mutating operation (such as the increment operator)\nis about to be executed on the string, at which time some or all of the\nstring’s contents are copied. A conforming implementation may choose to\ndefer copying a string’s contents for value assignment so long as it has\nno observable effect on behavior from any testable viewpoint (excluding\nperformance and resource consumption).\n\n#### Value Assignment of Object and Resource Types to a Local Variable\n\nTo demonstrate value assignment of objects to local variables, consider\nthe case in which we have a Point class that supports a two-dimensional\nCartesian system. An instance of Point contains two instance properties,\n`$x` and `$y`, that store the x- and y-coordinates, respectively. A\n[constructor call](14-classes.md#constructors) of the form `Point(x, y)` used with [operator `new`](10-expressions.md#the-new-operator)\ncreates a new point at the given location, and a method call\nof the form `move(newX, newY)` moves a `Point` to the new location.\n\nWith the `Point` class, let us consider the value assignment `$a = new\nPoint(1, 3)`:\n\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                                        |            |\n                                                        V            V\n                                                 [VStore Int 1]  [VStore Int 3]\n</pre>\n\nVariable `$a` is given its own VSlot, which points to a VStore that\ncontains a handle pointing to an HStore allocated by [`new`](10-expressions.md#the-new-operator) and\nthat is initialized by `Point`'s constructor.\n\nNow consider the value assignment `$b = $a`:\n\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                  ^                     |            |\n                                  |                     V            V\n[VSlot $b *]-->[VStore Obj *]-----+             [VStore Int 1] [VStore Int 3]\n</pre>\n\n`$b`‘s VStore contains a handle that points to the same object as does\n`$a`‘s VStore’s handle. Note that the Point object itself was not copied,\nand note that `$a`’s and `$b`’s VSlots point to distinct VStores.\n\nLet's modify the value of the Point whose handle is stored in `$b` using\n`$b->move(4, 6)`:\n\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                  ^                     |            |\n                                  |                     V            V\n[VSlot $b *]-->[VStore Obj *]-----+         [VStore Int 4] [VStore Int 6]\n                                       (1 was overwritten) (3 was overwritten)\n</pre>\n\nAs we can see, changing `$b`'s Point changes `$a`'s as well.\n\nNow, let's make `$a` point to a different object using `$a = new Point(2,\n1)`:\n\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                                        |            |\n[VSlot $b *]-->[VStore Obj *]-----+                     V            V\n                                  |             [VStore Int 2] [VStore Int 1]\n                                  V\n                                [HStore Point [VSlot $x *] [VSlot $y *]]\n                                                        |            |\n                                                        V            V\n                                                [VStore Int 4] [VStore Int 6]\n</pre>\n\nBefore `$a` can take on the handle of the new `Point`, its handle to the\nold `Point` must be removed, which leaves the handles of `$a` and `$b`\npointing to different Points.\n\nWe can remove all these handles using `$a = null` and `$b = null`:\n<pre>\n[VSlot $a *]-->[VStore Null]    [HStore Point [VSlot $x *] [VSlot $y *] (dead)]\n                                                        |            |\n[VSlot $b *]-->[VStore Null]    [VStore Int 2 (dead)]&lt;--+            V\n                                                          [VStore Int 1 (dead)]\n                                                          \n                                [HStore Point [VSlot $x *] [VSlot $y *] (dead)]\n                                                        |            |\n                                [VStore Int 4 (dead)]&lt;--+            V\n                                                        [VStore Int 6 (dead)]\n</pre>\n\nBy assigning null to `$a`, we remove the only handle to `Point(2,1)`, which\nallows that object's [destructor](14-classes.md#destructors) to run. A similar thing happens\nwith `$b`, as it too is the only handle to its Point.\n\nAlthough the examples above only show with only two instance properties,\nthe same mechanics apply for value assignment of all object types, even\nthough they can have an arbitrarily large number of instance properties\nof arbitrary type. Likewise, the same mechanics apply to value\nassignment of all resource types.\n\n#### ByRef Assignment for Scalar Types with Local Variables\nLet's begin with the same [value assignment](10-expressions.md#simple-assignment) as in the previous\nsection, `$a = 123` and `$b = false`:\n\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n\n[VSlot $b *]-->[VStore Bool false]\n</pre>\n\nNow consider the [byRef assignment](10-expressions.md#byref-assignment) `$b =& $a`, which has byRef\nsemantics:\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n                 ^\n                 |\n[VSlot $b *]-----+     [VStore Bool false (dead)]\n</pre>\n\nIn this example, byRef assignment changes `$b`’s VSlot point to the same\nVStore that `$a`’s VSlot points to. The old VStore that `$b`’s VSlot used\nto point to is now unreachable. As stated in [§§](#general), it is not possible for a VSlot to point to another VSlot, so `$b`‘s VSlot cannot point to `$a`‘s VSlot. When multiple variables’ VSlots point to the same VStore,\nthe variables are said to be *aliases* of each other or they are said to\nhave an *alias relationship*. In the example above, after the byRef\nassignment executes the variables `$a` and `$b` will be aliases of each\nother.\n\nNow, let's observe what happens when we change the value of `$b` using\n`++$b`:\n<pre>\n[VSlot $a *]-->[VStore Int 124 (123 was overwritten)]\n                 ^\n                 |\n[VSlot $b *]-----+\n</pre>\n\n`$b`‘s value, which is stored in the VStore that `$b`’s VSlot points, is\nchanged to 124. And as that VStore is also aliased by `$a`’s VSlot, the\nvalue of `$a` is also 124. Indeed, any variable’s VSlot that is aliased\nto that VStore will have the value 124.\n\nNow consider the value assignment `$a = 99`:\n<pre>\n[VSlot $a *]-->[VStore Int 99 (124 was overwritten)]\n                 ^\n                 |\n[VSlot $b *]-----+\n</pre>\n\nThe alias relationship between `$a` and `$b` can be broken explicitly by\nusing `unset` on variable `$a` or variable `$b`. For example, consider\n`unset($a)`:\n<pre>\n[VSlot $a (dead)]      [VStore Int 99]\n                         ^\n                         |\n[VSlot $b *]-------------+\n</pre>\n\nUnsetting `$a` causes variable `$a` to be destroyed and its corresponding\nalias to the VStore to be removed, leaving `$b`’s VSlot as the only\npointer remaining to the VStore.\n\nOther operations can also break an alias relationship between two or\nmore variables. For example, `$a = 123` and `$b =& $a`, and `$c = 'hi'`:\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n                 ^\n                 |\n[VSlot $b *]-----+\n\n[VSlot $c *]-->[VStore Str 'hi']\n</pre>\n\nAfter the byRef assignment, `$a` and `$b` now have an alias relationship.\nNext, let's observe what happens for `$b =& $c`:\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n\n[VSlot $b *]-----+\n                 |\n                 V\n[VSlot $c *]-->[VStore Str 'hi']\n</pre>\n\nAs we can see, the byRef assignment above breaks the alias relationship\nbetween `$a` and `$b`, and now `$b` and `$c` are aliases of each other. When\nbyRef assignment changes a VSlot to point to a different VStore, it\nbreaks any existing alias relationship the left hand side variable had\nbefore the assignment operation.\n\nIt is also possible to use byRef assignment to make three or more VSlots\npoint to the same VStore. Consider the following example:\n\n```Hack\n$b =& $a;\n$c =& $b;\n$a = 123;\n```\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n                 ^   ^\n                 |   |\n[VSlot $b *]-----+   |\n                     |\n[VSlot $c *]---------+\n</pre>\n\nLike value assignment, byRef assignment provides a means for the\nprogrammer to created variables. If the local variables that appear on\nthe left- or right-hand side of byRef assignment do not exist, the\nengine will bring new local variables into existence and create a VSlot\nand initial VStore for storing the local variable’s value.\n\nNote that literals, constants, and other expressions that don’t\ndesignate a modifiable lvalue cannot be used on the left- or right-hand\nside of byRef assignment.\n\n#### Byref Assignment of Non-Scalar Types with Local Variables\nbyRef assignment of non-scalar types works using the same mechanism as\nbyRef assignment for scalar types. Nevertheless, it is worthwhile to\ndescribe a few examples to clarify the semantics of byRef assignment.\nRecall the example from [§§](#value-assignment-of-object-and-resource-types-to-a-local-variable)) using the `Point` class:\n\n`$a = new Point(1, 3);`\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                                        |            |\n                                                        V            V\n                                               [VStore Int 1]  [VStore Int 3]\n</pre>\n\nNow consider the [byRef assignment](10-expressions.md#byref-assignment) `$b =& $a`, which has byRef\nsemantics:\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *][VSlot $y *]]\n                 ^                                      |           |\n                 |                                      V           V\n[VSlot $b *]-----+                               [VStore Int 1] [VStore Int 3]\n</pre>\n`$a` and `$b` now aliases of each other. Note that byRef assignment\nproduces a different result than `$b = $a` where `$a` and `$b` would point\nto distinct VStores pointing to the same HStore.\n\nLet's modify the value of the `Point` aliased by `$a` using `$a->move(4,\n6)`:\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] VSlot $y *]]\n                 ^                                      |           |\n                 |                                      V           V\n[VSlot $b *]-----+                           [VStore Int 4] [VStore Int 6]\n                                        (1 was overwritten) (3 was overwritten)\n</pre>\n\nNow, let's change `$a` itself using the value assignment `$a = new\nPoint(2, 1)`:\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *][VSlot $y *]]\n                 ^                                      |           |\n                 |                                      V           V\n[VSlot $b *]-----+                             [VStore Int 2] [VStore Int 1]\n\n                               [HStore Point [VSlot $x *]   [VSlot $y *] (dead)]\n                                                       |              |\n                                                       V              V\n                                     [VStore Int 4 (dead)] [VStore Int 6 (dead)]\n</pre>\n\nAs we can see, `$b` continues to have an alias relationship with `$a`.\nHere's what's involved in that assignment: `$a` and `$b`'s VStore’s handle\npointing to `Point(4,6)` is removed, `Point(2,1)` is created, and `$a` and\n`$b`’s VStore is overwritten to contain a handle pointing to that new\n`Point`. As there are now no VStores pointing to `Point(4,6)`, its\n[destructor](14-classes.md#destructors) can run.\n\nWe can remove these aliases using `unset($a, $b)`:\n<pre>\n[VSlot $a (dead)]       [HStore Point [VSlot $x *] [VSlot $y *] (dead)]\n                                                |            |\n                                                V            V\n[VSlot $b (dead)]             [VStore Int 2 (dead)]  [VStore Int 1 (dead)]\n</pre>\n\nOnce all the aliases to the VStores are gone, the VStores can be\ndestroyed, in which case, there are no more pointers to the HStore, and\nits [destructor](16-classes.md#destructors) can be run.\n\n#### Value Assignment of Array Types to Local Variables\nThe semantics of value assignment of array types is different from value\nassignment of other types. Recall the `Point` class from the examples in [§§](#value-assignment-of-object-and-resource-types-to-a-local-variable), and consider the following [value assignments](10-expressions.md#simple-assignment) and their abstract implementation:\n\n`$a = array(10, 'B' => new Point(1, 3));`\n<pre>\n[VSlot $a *]-->[VStore Arr *]-->[HStore Array [VSlot 0 *] [VSlot 'B' *]]\n                                                       |             |\n                                                       V             V\n                                             [VStore Int 10]   [VStore Obj *]\n                                                                           |\n                                [HStore Point [VSlot $x *] [VSlot $y *]]&lt;--+\n                                                        |            |\n                                                        V            V\n                                            [VStore Int 1]  [VStore Int 3]\n</pre>\n\nIn the example above, `$a`‘s VStore is initialized to contain a handle to\nan HStore for an array containing two elements, where one element is an\ninteger and the other is a handle to an HStore for an object.\n\nNow consider the following value assignment `$b = $a`. A conforming\nimplementation must implement value assignment of arrays in one of the\nfollowing ways: (1) eager copying, where the implementation makes a copy\nof `$a`’s array during value assignment and changes `$b`’s VSlot to point\nto the copy; or (2) deferred copying, where the implementation uses a\ndeferred copy mechanism that meets certain requirements. This section\ndescribes eager copying, and the section that immediately follows ([§§](#deferred-array-copying))\ndescribes deferred copying.\n\nTo describe the semantics of eager copying, let’s begin by considering\nthe value assignment `$b = $a`:\n<pre>\n[VSlot $a *]-->[VStore Arr *]-->[HStore Array [VSlot 0 *] [VSlot 'B' *]]\n                                                       |             |\n[VSlot $b *]-->[VStore Arr *]                          V             V\n                           |                    [VStore Int 10]  [VStore Obj *]\n                           V                                                 |\n[HStore Array [VSlot 0 *] [VSlot 'B' *]]                                     |\n                       |             |                                       |\n             +---------+   +---------+                                       |\n             V             V                                                 |\n[VStore Int 10] [VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]&lt;---+\n                                                         |            |\n                                                         V            V\n                                                 [VStore Int 1]  [VStore Int 3]\n</pre>\n\nThe value assignment `$b = $a` made a copy of `$a`’s array. Note how\n`$b`’s VSlot points to a different VStore than `$a`’s VSlot, and `$b`’s\nVStore points to a different HStore than `$b`’s VStore. Each source array\nelement is copied using *member-copy assignment* `=*`, which is defined\nas follows:\n\n```Hack\n   $destination =* $source\n```\n-   If `$source`’s VStore has a refcount equal to 1, the Engine copies the\n    array element using  value assignment (`destination = $source`).\n-   If `$source`’s VStore has a refcount that is greater than 1, the Engine\n    uses an implementation-defined algorithm to decide whether to copy the element\n    using value assignment (`$destination = $source`) or byRef\n    assignment (`$destination =& $source`).\n\nNote the member-copy assignment `=*` is **not** an operator or language\nconstruct in the Hack language, but instead it is used internally to\ndescribe behavior for the engine for array copying and other operations\n\nFor the particular example above, member-copy assignment exhibits the\nsame semantics as value assignment for all conforming implementations\nbecause all of the array elements’ VStores have a refcount equal to 1.\nThe first element VSlots in `$a`’s array and `$b`’s array point\nto distinct VStores, each of which contain a distinct copy of the\ninteger value 10. The second element VSlots in `$a`’s array and `$b`’s\narray point to distinct VStores, each of which contain a handle to the\nsame object HStore.\n\nLet’s consider another example:\n```Hack\n$x = 123;\n$a = array(array(&$x, 'hi'));\n$b = $a;\n```\n\nEager copying can produce two possible outcomes depending on the\nimplementation. Here is the first possible outcome:\n<pre>\n[VSlot $a *]---->[VStore Arr *]---->[HStore Array [VSlot 0 *]]\n                                                           |\n[VSlot $x *]-------------------------+   [VStore Arr *]&lt;---+\n                                     |               |\n[VSlot $b *]-->[VStore Arr *]        |               V\n                           |         |  [HStore Array [VSlot 0 *][VSlot 1 *]]\n                           V         |                          |          |\n         [HStore Array [VSlot 0 *]]  |                          V          |\n                                |    +---------------->[VStore Int 123]    |\n                                V                          ^               V\n                     [VStore Arr *]                        |   [VStore Str 'hi']\n                                 |          +--------------+\n                                 V          |\n                     [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                                                        |\n                                                        V\n                                                     [VStore Str 'hi']\n</pre>\n\nHere is the second possible outcome:\n<pre>\n[VSlot $a *]---->[VStore Arr *]---->[HStore Array [VSlot 0 *]]\n                                                           |\n[VSlot $x *]-------------------------+  [VStore Arr *]&lt;----+\n                                     |               |\n[VSlot $b *]-->[VStore Arr *]        |               V\n                           |         |  [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                           V         |                         |           |\n         [HStore Array [VSlot 0 *]]  |                         V           |\n                                |    +---------------->[VStore Int 123]    |\n                                V                                          V\n                     [VStore Arr *]                            [VStore Str 'hi']\n                                 |\n                                 V\n                    [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                                           |           |\n                                           V           V \n                                  [VStore Int 123]  [VStore Str 'hi']\n</pre>\n\nIn both possible outcomes, value assignment with eager copying makes a\ncopy of `$a`’s array, copying the array’s single element using\nmember-copy assignment (which in this case will exhibit the same\nsemantics of value assignment for all implementations), which in turn\nmakes a copy of the inner array inside `$a`’s array, copying the inner\narray’s elements using member-copy assignment. The inner array’s first\nelement VSlot points to a VStore that has a refcount that is greater than 1,\nso an implementation-defined algorithm is used to decide whether to use value\nassignment or byRef assignment. The first possible outcome shown above\ndemonstrates what happens if the implementation chooses to do byRef\nassignment, and the second possible outcome shown above demonstrates\nwhat happens if the implementation chooses to do value assignment. The\ninner array’s second element VSlot points to a VStore that has a refcount\nequal to 1, so value assignment is used to copy the inner array’s second\nelement for all conforming implementations that use eager copying.\n\nAlthough the examples in this section only use arrays with one\nelement or two elements, the model works equally well for all\narrays even though they can have an arbitrarily large number\nof elements. As to how an HStore accommodates all of them, is\nunspecified and unimportant to the abstract model.\n\n#### Deferred Array Copying\nAs mentioned in the previous section ([§§](#value-assignment-of-array-types-to-local-variables)), an implementation may\nchoose to use a deferred copy mechanism instead of eagerly making a copy\nfor value assignment of arrays. An implementation may use any deferred\ncopy mechanism desired so long as it conforms to the abstract model’s\ndescription of deferred array copy mechanisms presented in this\nsection.\n\nBecause an array’s contents can be arbitrarily large, eagerly copying an\narray’s entire contents for value assignment can be expensive. In\npractice an application written in Hack may rely on value assignment of\narrays being relatively inexpensive for the common case (in order to deliver\nacceptable performance), and as such it is common for an implementation\nto use a deferred array copy mechanism in order to reduce the cost of\nvalue assignment for arrays.\n\nUnlike conforming deferred string copy mechanisms discussed in [§§](#value-assignment-of-scalar-types-to-a-local-variable)\nthat must produce the same observable behavior as eager string copying,\ndeferred array copy mechanisms are allowed in some cases to exhibit\nobservably different behavior than eager array copying. Thus, for\ncompleteness this section describes how deferred array copies can be\nmodeled in the abstract memory model and how conforming deferred array\ncopy mechanisms must behave.\n\nConforming deferred array copy mechanisms work by not making an array\ncopy during value assignment, by allowing the destination VStore to\nshare an array HStore with the source VStore, and by making a copy of\nthe array HStore at a later time if or when it is necessary. The\nabstract model represents a deferred array copy relationship by marking\nthe destination VStore with a special “Arr-D” type tag and by sharing\nthe same array HStore between the source and destination VStores. Note\nthat the source VStore’s type tag remains unchanged. For the purposes of\nthis abstract model, the “Arr-D” type tag is considered identical to the\n“Arr” type in all respects except when specified otherwise.\n\nTo illustrate this, let’s see how the previous example would be\nrepresented under the abstract model assuming the implementation defers\nthe copying the array:\n\n```Hack\n$x = 123;\n$a = array(array(&$x, ‘hi’));\n$b = $a;\n```\n<pre>\n[VSlot $a *]--->[VStore Arr *]--->[HStore Array [VSlot 0 *]]\n                                    ^                    |\n                                    |   [VStore Arr *]&lt;--+\n[VSlot $b *]--->[VStore Arr-D *]----+               |\n                                                    V\n                                        [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                                                               |           |\n                                                               V           |\n[VSlot $x *]------------------------------------------>[VStore Int 123]    |\n                                                                           V\n                                                               [VStore Str 'hi']\n</pre>\n\nAs we can see, both `$a`’s VStore (the source VStore) and `$b`’s VStore\n(the destination VStore) point to the same array HStore. Note the\nasymmetric nature of how deferred array copies are represented in the\nabstract model. In the above example the source VStore’s type tag\nremains unchanged after value assignment, whereas the destination\nVStore’s type tag was changed to “Arr-D”.\n\nWhen the engine is about to perform an array-mutating operation on a\nVStore tagged “Arr” that participates in a deferred array copy\nrelationship or on a VStore tagged “Arr-D”, the engine must first take\ncertain actions that involve making a copy of the array (described in\nthe next paragraph) before performing the array-mutating operation. An\narray-mutating operation is any operation can add or remove array\nelements, overwrite existing array elements, change the state of the\narray’s internal cursor, or cause the refcount of one or more of the\narray’s element VStores or subelement VStores to increase from 1 to\na value greater than 1. This requirement to take certain actions before\nperforming an array-mutation operation on a VStore participating in a\ndeferred array copy relationship is commonly referred to as the\ncopy-on-write requirement.\n\nWhen an array-mutating operation is about to be performed on a given\nVStore X with an “Arr” type tag that participates in a deferred array\ncopy relationship, the engine must find all of the VStores tagged\n“Arr-D” that point to the same array HStore that VStore X points to,\nmake a copy of the array (using member-copy assignment to copy the\narray’s elements as described in [§§](#value-assignment-of-array-types-to-local-variables)), and update all of these\nVStores tagged “Arr-D” to point to the newly created copy (note that\nVStore X remains unchanged). When an array-mutation operation is about\nto be performed on a given VStore X with an “Arr-D” type tag, the engine\nmust make a copy of the array (as described in [§§](#value-assignment-of-array-types-to-local-variables)), update VStore\nX to point to the newly created copy, and change VStore X’s type tag to\n“Arr”. These specific actions that the engine must perform on VStore at\ncertain times to satisfy the copy-on-write requirement are collectively\nreferred to as “array-separation” or “array-separating the VStore”. An\narray-mutation operation is said to “trigger” an array-separation.\n\nNote that for any VStore with an “Arr” type tag that participates in a\ndeferred array copy relationship, or for any VStore with an “Arr-D” type\ntag, a conforming implementation may choose to array-separate the VStore\nat any time for any reason as long as the copy-on-write requirement is\nupheld.\n\nContinuing with the previous example, consider the array-mutating\noperation `$b[1]++`. Depending on the implementation, this can produce\none of three possible outcomes. Here is the one of the possible\noutcomes:\n<pre>\n[VSlot $a *]---->[VStore Arr *]---->[HStore Array [VSlot 0 *]]\n                                                           |\n[VSlot $b *]-->[VStore Arr *]            [VStore Arr *]&lt;---+\n                             |                       |\n      +----------------------+              +--------+\n      V                                     V\n  [HStore Array [VSlot 0 *] [VSlot 1 *]]  [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                         |           |       ^                  |          |\n                         |           V       |                  V          |\n                         |   [VStore Int 1]  |            [VStore Int 123] |\n                         V                   |             ^               V\n                       [VStore Arr-D *]-----+              |   [VStore Str 'hi']\n                                                           |\n [VSlot $x *]----------------------------------------------+\n</pre>\n\nAs we can see in the outcome shown above, `$b`’s VStore was\narray-separated and now `$a`’s VStore and `$b`’s VStore point to distinct\narray HStores. Performing array-separation on `$b`’s VStore was necessary\nto satisfy the copy-on-write requirement. `$a`’s array remains unchanged\nand that `$x` and `$a[0][0]` still have an alias relationship with each\nother. For this particular example, conforming implementations are\nrequired to preserve `$a`’s array’s contents and to preserve the alias\nrelationship between `$x` and `$a[0][0]`. Finally, note that `$a[0]` and\n`$b[0]` have a deferred copy relationship with each other in the outcome\nshown above. For this particular example, a conforming implementation is\nnot required to array-separate `$b[0]`’s VStore, and the outcome shown\nabove demonstrates what happens when `$b[0]`’s VStore is not\narray-separated. However, an implementation can choose to array-separate\n`$b[0]`’s VStore at any time if desired. The other two possible outcomes\nshown below demonstrate what can possibly happen if the implementation\nchoose to array-separate `$b[0]`’s VStore as well. Here is the second\npossible outcome:\n<pre>\n[VSlot $a *]---->[VStore Arr *]---->[HStore Array [VSlot 0 *]]\n                                                           |\n[VSlot $b *]-->[VStore Arr *]            [VStore Arr *]&lt;---+\n                          |                          |\n                          V                          V\n  [HStore Array [VSlot 0 *] [VSlot 1 *]]  [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                         |           |                           |           |\n       +-----------------+           V                           |           |\n       |                     [VStore Int 1]                  +---+           |\n       V                                                     |               V\n  [VStore Arr-D *]-->[HStore Array [VSlot 0 *] [VSlot 1 *]] | [VStore Str 'hi']\n                                            |           |   |\n                                    +-------+           |   |\n                                    |                   V   |\n                                    |    [VStore Str ‘hi’]  |\n                                    V                       |\n [VSlot $x *]--------------------->[VStore Int 123]&lt;--------+\n</pre>\n\nHere is the third possible outcome:\n<pre>\n[VSlot $a *]---->[VStore Arr *-]---->[HStore Array [VSlot 0 *]]\n                                                            |\n[VSlot $b *]-->[VStore Arr *]             [VStore Arr *]&lt;---+\n                            |                          |\n                            V                          V\n [HStore Array [VSlot 0 *] [VSlot 1 *]]  [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                         |           |                           |           |\n       +-----------------+           V                           |           |\n       |                     [VStore Int 1]                  +---+           |\n       V                                                     |               V\n   [VStore Arr-D *]-->[HStore Array [VSlot 0 *] [VSlot 1 *]] | [VStore Str 'hi']\n                                             |           |   |\n                     [VStore Int 123]&lt;-------+           |   |\n                                                         V   |\n                                          [VStore Str 'hi']  |\n                                                             |\n [VSlot $x *]--------------------->[VStore Int 123]&lt;--------+\n</pre>\n\nThe second and third possible outcomes show what can possibly happen if\nthe implementation chooses to array-separate `$b[0]`’s VStore. In the\nsecond outcome, `$b[0][0]` has an alias relationship with `$x` and\n`$a[0][0]`. In the third outcome, `$b[0][0]` does not have an alias\nrelationship, though `$x` and `$a[0][0]` still have an alias relationship\nwith each other. The differences between the second and third outcome\nare reflect that different possibilities when the engine uses\nmember-copy assignment to copy `$a[0]`’s arrays’s elements into `$b[0]`’s\narray.\n\nFinally, let’s briefly consider one more example:\n```Hack\n$x = 0;\n$a = array(&$x);\n$b = $a;\n$x = 2;\nunset($x);\n$b[1]++;\n$b[0]++;\necho $a[0], ' ', $b[0];\n```\n\nFor the example above, a conforming implementation could output “2 1”,\n“2 3”, or “3 3” depending on how it implements value assignment for\narrays.\n\nFor portability, it is generally recommended that programs written in\nHack should avoid performing value assignment with a right-hand side that\nis an array with one or more elements or sub-elements that have an alias\nrelationship.\n\n***Implementation Notes*** For generality and for simplicity, the\nabstract model represents deferred array copy mechanisms in a manner\nthat is more open-ended and superficially different than the php.net\nimplementation’s model, which uses a symmetric deferred copy mechanism\nwhere a single zval contains the sole pointer to a given Hashtable and\ndeferred array copies are represented as multiple slots pointing to the\nsame single zval that holds the array. Despite this superficial\ndifference, php.net’s implementation produces behavior that is\ncompatible with the abstract model’s definition of deferred array copy\nmechanisms.\n\n#### General Value Assignment\nThe sections above thus far have described the mechanics of value assignment\nto a local variable. This section describes how value assignment works\nwhen general modifiable lvalue expressions are used on the left hand side.\n\nFor example, assuming `Point` definition as in previous sections and further\nassuming all instance properties are public, this code:\n\n```Hack\n$a = new Point(1, 3);\n$b = 123;\n$a->x = $b;\n```\n\nwill result in:\n<pre>\n[VSlot $a *]-->[VStore object *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                                           |            |\n                                                           V            V\n                                                  [VStore int 123] [VStore int 3]\n[VSlot $b *]-->[VStore int 123]\n</pre>\n\nIf needed, new VSlots are created as part of the containing VStore, for example:\n\n```Hack\n$a = new Point(1, 3);\n$b = 123;\n$a->z = $b;\n```\n\nwill result in:\n<pre>\n[VSlot $a *]-->[VStore object *]-->[HStore Point [VSlot $x *] [VSlot $y *] [VSlot $z *]]\n                                                           |            |            |\n                                                           V            V            V\n                                                  [VStore int 1] [VStore int 3] [VStore int 123]\n[VSlot $b *]-->[VStore int 123]\n</pre>\n\nThe same holds for array elements:\n```Hack\n$a = array('hello', 'world');\n$b = 'hack';\n$a[1] = $b;\n$a[2] = 'World!';\n```\n\nwill result in:\n<pre>\n[VSlot $a *]-->[VStore array *]-->[HStore Array [VSlot 0 *]  [VSlot 1 *]  [VSlot 2 *]]\n                                                         |            |            |\n                                                         V            V            V\n                                    [VStore string 'hello'] [VStore string 'hack'] [VStore string 'World!']\n[VSlot $b *]-->[VStore string 'hack']\n</pre>\n\nwhere the third VSlot with index 2 was created by the assignment.\n\nNote that any array element and instance property, including a designation of non-existing ones,\nis considered a modifiable lvalue, and the VSlot will be created by the engine and added\nto the appropriate HStore automatically. Static class properties are considered modifiable lvalues too,\nthough new ones would not be created automatically.\n\n#### General ByRef Assignment\nThe sections above thus far have described the mechanics of byref assignment\nwith local variables. This section describes how byref assignment works when\ngeneral modifiable lvalue expressions are used on the left hand side and/or\nthe right hand side.\n\nFor example:\n\n```Hack\n$a = new Point(1, 3);\n$b = 123;\n$a->z =& $b;\n```\n\nwill result in:\n<pre>\n[VSlot $a *]-->[VStore object *]-->[HStore Point [VSlot $x *] [VSlot $y *] [VSlot $z *]]\n                                                           |            |            |\n                                                           V            V            |\n                                                  [VStore int 1] [VStore int 3]      |\n[VSlot $b *]---------------->[VStore int 123]&lt;---------------------------------------+\n</pre>\n\n### Argument Passing\nArgument passing is defined in terms of simple assignment[§§](#value-assignment-of-scalar-types-to-a-local-variable), [§§](#value-assignment-of-object-and-resource-types-to-a-local-variable), [§§](#value-assignment-of-array-types-to-local-variables), and [§§](10-expressions.md#simple-assignment)). \nThat is, passing an argument to a function having a corresponding\nparameter is like assigning that argument to that parameter.\n\n### Value Returning\nReturning a value from a function is defined in terms of simple\nassignment ([§§](#value-assignment-of-scalar-types-to-a-local-variable), [§§](#value-assignment-of-object-and-resource-types-to-a-local-variable), [§§](#value-assignment-of-array-types-to-local-variables), and [§§](10-expressions.md#simple-assignment)).  That is, returning a value from a function to its\ncaller is like assigning that value to the user of the caller's return\nvalue.\n\n\n### Cloning objects\nWhen an instance is allocated, [operator `new`](10-expressions.md#the-new-operator) returns a handle\nthat points to that object. (As described in [§§](#value-assignment-of-object-and-resource-types-to-a-local-variable)), value assignment of a handle to an object does not copy the object HStore itself. Instead, it creates a copy of the handle. How then to make a copy of the object itself? Our only access to it is\nvia the handle. The Hack language allows us to do this via [operator `clone`](10-expressions.md#the-clone-operator).\n\nTo demonstrate how the `clone` operator works, consider the case in which\nan instance of class `Widget` contains two instance properties: `$p1` has\nthe integer value 10, and `$p2` is a handle to an array of elements of\nsome type(s) or to an instance of some other type.\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Widget [VSlot $p1 *][VSlot $p2 *]]\n                                                          |          |\n                                                          V          V\n                                               [VStore Int 10] [VStore Obj *]\n                                                                         |\n                                                                         V\n                                                                 [HStore ...]\n</pre>\n\nLet us consider the result of `$b = clone $a`:\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Widget [VSlot $p1 *][VSlot $p2 *]]\n                                                          |            |\n[VSlot $b *]-->[VStore Obj *]                             V            V\n                             |                  [VStore Int 10] [VStore Obj *]\n     +-----------------------+                                              |\n     V                                                                      V\n   [HStore Widget [VSlot $p1 *] [VSlot $p2 *]]              +--->[HStore ...]\n                             |             |                |\n                             V             V                |\n                 [VStore Int 10] [VStore Obj *]-------------+\n</pre>\n\nThe clone operator will create another object HStore of the same class\nas the original, copy `$a`’s object’s instance properties using\nmember-copy [assignment `=*`](#value-assignment-of-array-types-to-local-variables). For the example shown above, the\nhandle to the newly created HStore stored into `$b` using value\nassignment. Note that the clone operator will not recursively clone\nobjects held in `$a`’s instance properties; hence the object copying\nperformed by the clone operator is often referred to as a *shallow\ncopy*. If a *deep copy* of an object is desired, the programmer must\nachieve this manually by using the method [`__clone`](16-classes.md#method-__clone) or by\nother means.\n\n## Scope\n\nThe same name can designate different things at different places in a\nprogram. For each different thing that a name designates, that name is\nvisible only within a part of the program called that name's *scope*.\nThe following distinct scopes exist:\n\n-   Script, which means from the point of declaration/first\n    initialization through to the end of that script, including any\n    [included scripts](12-script-inclusion.md#script-inclusion-operators).\n-   Function, which means from the point of declaration/first\n    initialization through to the end of that [function](15-functions.md#function-definitions).\n-   Class, which means the body of that class and any classes derived\n    from it ([§§](16-classes.md#class-declarations)).\n-   Interface, which means the body of that interface, any interfaces\n    derived from it, and any classes that implement it ([§§](17-interfaces.md#interface-declarations)).\n-   Namespace, which means from the point of declaration/first\n    initialization through to the end of that [namespace](20-namespaces.md#general).\n\nA variable declared or first initialized inside a function has function scope.\n\nEach function has its own function scope. An [anonymous function](15-functions.md#anonymous-functions)\nhas its own scope separate from that of any function inside which that\nanonymous function is defined.\n\nThe scope of a parameter is the body of the function in which the\nparameter is declared. For the purposes of scope, a [catch-block](11-statements.md#the-try-statement)\nis treated like a function body, in which case, the *variable-name* in\n*parameter-declaration-list* is treated like a parameter.\n\nThe scope of a class member `m` ([§§](16-classes.md#class-members)) declared in, or inherited by, a\nclass type `C` is the body of `C`.\n\nThe scope of an interface member `m` ([§§](17-interfaces.md#interface-members)) declared in, or inherited by,\nan interface type `I` is the body of `I`.\n\nWhen a [trait](18-traits.md#general) is used by a class or an interface, the [trait's\nmembers](16-classes.md#class-members) take on the scope of a member of that class or\ninterface.\n\n## Storage Duration\n\nThe lifetime of a variable is the time during program execution that\nstorage for that variable is guaranteed to exist. This lifetime is\nreferred to as the variable's *storage duration*, of which there are\nthree kinds: automatic, static, and allocated.\n\nA variable having *automatic storage duration* comes into being and is\ninitialized at its declaration or on its first use, if it has no\ndeclaration. Its lifetime is delimited by an enclosing [scope](#scope). The\nautomatic variable's lifetime ends at the end of that scope. Automatic\nvariables lend themselves to being stored on a stack where they can help\nsupport argument passing and recursion. [Local variables](07-variables.md#local-variables), which\ninclude [function parameters](15-functions.md#function-definitions), have automatic storage duration.\n\nA variable having *static storage duration* comes into being and is\ninitialized before its first use, and lives until program shutdown. The\nfollowing kinds of variables have static storage duration: [function statics](07-variables.md#function-statics), [static properties](07-variables.md#static-properties), and [class and interface constants](07-variables.md#class-and-interface-constants).\n\nA variable having *allocated storage duration* comes into being based on\nprogram logic by use of the [`new` operator](10-expressions.md#the-new-operator). Ordinarily, once\nsuch storage is no longer needed, it is reclaimed automatically by the\nEngine via its garbage-collection process and the use of\n[destructors](16-classes.md#destructors). The following kinds of variables have allocated\nstorage duration: [array elements](07-variables.md#array-elements) and [instance properties](07-variables.md#instance-properties).\n\nThe following example demonstrates the three storage durations:\n\n```Hack\nclass Point { ... }\n\nfunction doit($p1) {\n  $av2 = ...;           // auto variable $av2 created and initialized\n  static $sv2 = ...;    // static variable $sv2 created and initialized\n  if ($p1) {\n    $av3 = ...;         // auto variable $av3 created and initialized\n    static $sv3 = ...;  // static variable $sv3 created and initialized\n    ...\n  }\n  global $av1;\n  $av1 = new Point(2, 3);   // Point(0,1) is eligible for destruction\n  ...\n}                       // $av2 and $av3 are eligible for destruction\n\nfunction main($p1): void {\n  $av1 = new Point();   // auto variable $av1 created and initialized\n  static $sv1 = ...;    // static variable $sv1 created and initialized\n  doit(true);\n}\n\n// At end of script, $sv1, $sv2, and $sv3 are eligible for destruction\n```\n\nThe comments indicate the beginning and end of lifetimes for each\nvariable.\n\nIf function `doit` is called multiple times, each time it is called, its\nautomatic variables are created and initialized, whereas its static\nvariables retain their values from previous calls.\n\nConsider the following recursive function: \n\n```Hack\nfunction factorial(int $i): int {\n  if ($i > 1) return $i * factorial($i - 1);\n  else if ($i == 1) return $i;\n  else return 0;\n}\n```\n\nWhen `factorial` is first called, the local variable parameter `$i` is\ncreated and initialized with the value of the argument in the call.\nThen, if this function calls itself, the same process is repeated each\ncall. Specifically, each time `factorial` calls itself, a new local\nvariable parameter `$i` is created and initialized with the value of the\nargument in the call.\n\nThe lifetime of any [VStore](#general) or [HStore](#general) can be extended by\nthe Engine as long as needed. Conceptually, the lifetime of a VStore ends\nwhen it is no longer pointed to by any [VSlots](#general). Conceptually, the\nlifetime of an HStore ends when no VStores have a handle to it.\n"
  },
  {
    "path": "spec/05-types.md",
    "content": "# Types\n\n## General\n\nThe meaning of a value is decided by its *type*. Hack's types are\ncategorized as *scalar types* and *composite types*. The scalar types\nare [Boolean](#the-boolean-type), [integer](#the-integer-type), [floating-point](#the-floating-point-type), [numeric](05-types.md#the-numeric-type), [string](#the-string-type), [array key](05-types.md#the-array-key-type), [null](#the-null-type), and\n[enumerated](05-types.md#enumerated-types). The non-scalar types are [array](05-types.md#array-types), [class](05-types.md#class-types), [interface](05-types.md#interface-types), [tuple](05-types.md#tuple-types), [shape](05-types.md#shape-types), [closure](05-types.md#closure-types), [resource](05-types.md#resource-types), and [nullable](05-types.md#nullable-types). The [void type](05-types.md#the-void-type) is neither scalar nor\nnon-scalar.\n\nThe integer, floating-point, and numeric types are known collectively as\narithmetic types. (Note carefully, that the library function [is_numeric](http://www.php.net/is_numeric) indicates if a given value is an int, a float, or a [numeric string](05-types.md#the-string-type).)\n\nThe scalar types are *value types*. That is, a variable of scalar type\nbehaves as though it contains its own value. On the\nother hand, the non-scalar types are *handles*. A variable of\nnon-scalar type contains information—in a *handle*—that leads to the\nvalue. The differences between value types and handles become apparent\nwhen it comes to understanding the semantics of assignment, and passing\narguments to, and returning values from, functions ([§§](04-basic-concepts.md#the-memory-model)). That said,\narray types really are a hybrid; on the one hand, an array may contain\nan arbitrary number of elements separate from the array variable itself,\nyet on the other hand, certain array operations do have value semantics.\n\n**Note**: One could differentiate value types and handles in the same way that pass-by-value and pass-by-reference types are distinguished.\n\nVariables are not declared to have a particular type. Instead, a\nvariable's type is decided at runtime by the context in which it is\nused.\n\nA *type constraint* indicates a requirement that a type must fulfill in order to be accepted in a given context. Type constraints are used in [type aliasing](05-types.md#type-aliases), [enum declarations](13-enums.md#enum-declarations), [type parameters](14-generic-types-methods-and-functions.md#type-parameters), and [type constants](16-classes.md#type-constants).\n\nThe library function [`is_scalar`](http://www.php.net/is_scalar) indicates if a given value has a scalar\ntype. However, that function does not consider `null` to be scalar. To test\nfor `null`, use [`is_null`](http://www.php.net/is_null). Useful library functions for interrogating and using type information include [`gettype`](http://www.php.net/gettype), [`is_type`](http://www.php.net/is_type), [`settype`](http://www.php.net/settype), and [`var_dump`](http://www.php.net/var_dump).\n\n**Syntax**\n<pre>\n<i>type-specifier:</i>\n  arraykey\n  bool\n  float\n  int\n  num\n  resource\n  string\n  this\n  void\n  <i>alias-type-specifier</i>\n  <i>class-interface-trait-specifier</i>\n  <i>classname-type-specifier</i>\n  <i>closure-type-specifier</i>\n  <i>enum-specifier</i>\n  <i>generic-type-parameter-name</i>\n  <i>map-like-array-type-specifier</i>\n  <i>nullable-type-specifier</i>\n  <i>shape-specifier</i>\n  <i>tuple-type-specifier</i>\n  <i>type-constant-type-name</i>\n  <i>vector-like-array-type-specifier</i>\n\n<i>alias-type-specifier:</i>\n  <i>qualified-name</i>\n\n<i>enum-specifier:</i>\n  <i>qualified-name</i>\n\n<i>class-interface-trait-specifier:</i>\n  <i>qualified-name generic-type-argument-list<sub>opt</sub></i>\n\n<i>type-specifier-list:</i>\n  <i>type-specifiers</i>  ,<sub>opt</sub>\n\n<i>type-specifiers</i>\n  <i>type-specifier</i>\n  <i>type-specifiers</i> , <i>type-specifier</i>\n\n<i>type-constraint:</i>\n  as  <i>type-specifier</i>\n\n<i>type-constant-type-name:</i>\n  <i>name</i>  ::  <i>name</i>\n  self  ::  <i>name</i>\n  this  ::  <i>name</i>\n  <i>type-constant-type-name</i>  ::  <i>name</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*classname-type-specifier*](05-types.md#the-classname-type)\n* [*closure-type-specifier*](05-types.md#closure-types)\n* [*generic-type-argument-list*](14-generic-types-methods-and-functions.md#type-arguments)\n* [*generic-type-parameter-name*](14-generic-types-methods-and-functions.md#type-parameters)\n* [*map-like-array-type-specifier*](05-types.md#array-types)\n* [*name*](09-lexical-structure.md#names)\n* [*nullable-type-specifier*](05-types.md#nullable-types)\n* [*qualified-name*](20-namespaces.md#defining-namespaces)\n* [*shape-type-specifier*](05-types.md#shape-types)\n* [*tuple-type-specifier*](05-types.md#tuple-types)\n* [*vector-like-array-type-specifier*](05-types.md#array-types)\n\n**Constraints**\n\nThe *qualified-name* in *alias-type-specifier* must qualify the *name* of a\ntype alias declared in an [*alias-declaration*](05-types.md#type-aliases).\n\nThe *qualified-name* in *enum-specifier* must qualify the *name* of an enumerated type declared in an [*enum-declaration*](13-enums.md#enum-declarations).\n\nThe *qualified-name* in *class-interface-trait-specifier* must qualify the\n*name* of a class type declared in a [*class-declaration*](16-classes.md#class-declarations), of an\ninterface type declared in an [*interface-declaration*](17-interfaces.md#interface-declarations), or of a trait\ntype declared in a [*trait-declaration*](18-traits.md#trait-declarations).\n\nThe *name* of a trait type declared in a *trait-declaration* can only be used\nas a type-specifier in the context of a [*trait-use-clauses*](18-traits.md#trait-declarations).\n\nFor *name* `::` *name*, the left-hand *name* must be the name of a class or interface that directly or indirectly has a [type-constant member](16-classes.md#type-constants) whose name is the right-hand *name*.\n\nFor `self` `::` *name*, *name* must be the name of a type-constant member in the current class (including any implemented interfaces).\n\nFor `this` `::` *name*, *name* must be the name of a type-constant member in the current class/interface hierarchy.\n\nA *type-constant-type-name* beginning with `self` or `this` must be used in the context of a class or interface to which `self` or `this`, respectively, can apply.\n\n**Semantics**\n\nA *type-constant-type-name* specifies a type, as follows:\n\n*\tFor *name* `::` *name*, the type is that designated by the type-constant having the right-hand *name*, in the class or interface having the left-hand *name*.\n*\tFor `self` `::` *name*, used within a class, the type is that designated by the type-constant named *name*, in the enclosing class, ignoring any overrides.\n*\tFor `this` `::` *name*, used within a class, the type is that designated by the type-constant named *name*, in the enclosing class’s hierarchy resolved in a late-bound context. For a non-static member, this designates the class of the `$this` object; for a static member, this designates the current class. `this` is recommended when accessing abstract type constant names.\n*\tIn cases of *type-constant-type-name* having the form `x::y::z`, the type is resolved left-to-right.\n\nA given type constant can be referenced via multiple names; for example:\n\n```Hack\ninterface I {\n  const type T = int;\n}\n\nclass C1 implements I {}\nclass C2 extends C1 {}\n```\n\nHere, `I::T`, `C1::T`, and `C2::T`, all refer to the same type constant.\n\nConsider the following:\n\n```Hack\ninterface I {\n  const type this = int;    // this is a name, NOT a keyword\n}\n\nclass C {\n  const type self = I;      // self is a name, NOT a keyword\n}\n\nfunction test10(C::self::this $x): void {}\n```\n\nFor some examples, see [§§](16-classes.md#type-constants).\n\n## The Boolean Type\n\nThe Boolean type is `bool`. This\ntype is capable of storing two distinct values, which correspond to the\nBoolean values `true` and `false`, respectively. The representation of\nthis type and its values is unspecified.\n\nThe library function [`is_bool`](http://www.php.net/is_bool) indicates if a given value has type\n`bool`.\n\n## The Integer Type\n\nThere is one integer type, `int`.\nThis type is binary, signed, and uses twos-complement representation for\nnegative values. The range of values that can be stored is\nimplementation-defined; however, the range [-9223372036854775808, 9223372036854775807],\nmust be supported.\n\nCertain operations on integer values produce a mathematical result that\ncannot be represented as an integer. Examples include the following:\n\n-   Incrementing the largest value or decrementing the smallest value\n-   Applying the unary minus to the smallest value\n-   Multiplying, adding, or subtracting two values\n\nIn such cases, the resulting type and value is implementation-defined,\nbut must be one of the following:\n\n-   The result type is int and the value reflects wrap-around (for\n    example adding 1 to the largest value results in the smallest value)\n-   The computation is done as though the type had some unspecified,\n    arithmetic-like object type with the result being mathematically\n    correct\n\nThe constants [`PHP_INT_SIZE`, `PHP_INT_MIN` and `PHP_INT_MAX`](06-constants.md#core-predefined-constants) define certain\ncharacteristics about type `int`.\n\nThe library function [`is_int`](http://www.php.net/is_int) indicates if a given value has type\nint.\n\n## The Floating-Point Type\n\nThere is one floating-point type, `float`. The `float` type must support at least the range and\nprecision of IEEE 754 64-bit double-precision representation.\n\nThe library function [`is_float`](http://www.php.net/is_float) indicates if a given value has type\n`float`. The library function [`is_finite`](http://www.php.net/is_finite) indicates if a given\nfloating-point value is finite. The library function [`is_infinite`](http://www.php.net/is_infinite)\nindicates if a given floating-point value is infinite. The library\nfunction [`is_nan`](http://www.php.net/is_nan) indicates if a given floating-point value is a\n`NaN`.\n\n## The Numeric Type\n\nThe type `num` can represent any integer or floating-point value.\n\nSee the discussion of [type side effects](05-types.md#type-side-effects).\n\n## The String Type\n\nThere is one string type, `string`.\n\nA string is a set of contiguous bytes that represents a sequence of zero\nor more characters.\n\nConceptually, a string can be considered as an [array](05-types.md#array-types) of\nbytes—the *elements*—whose keys are the `int` values starting at zero. The\ntype of each element is `string`. However, a string is *not* considered a\ncollection, so it cannot be iterated over.\n\nA string whose length is zero is an *empty string*.\n\nAs to how the bytes in a string translate into characters is\nunspecified.\n\nAlthough a user of a string might choose to ascribe special semantics to\nbytes having the value `U+0000`, from Hack's perspective, such *null bytes*\nare simply just bytes! Hack does not assume strings contain any specific\ndata or assign special values to any bytes or sequences. However, many\nlibrary functions assume the strings they receive as arguments are UTF-8\nencoded, often without explicitly mentioning that fact.\n\nA *numeric string* is a string whose content exactly matches the pattern\ndefined by the *str-numeric* production below. A *leading-numeric string* is a string whose initial characters follow\nthe requirements of a numeric string, and whose trailing characters are\nnon-numeric. A *non-numeric string* is a string that is not a numeric\nstring.\n\n<pre>\n  <i>str-numeric::</i>\n    <i>str-whitespace<sub>opt</sub>   sign<sub>opt</sub>   str-number</i>\n\n  <i>str-whitespace::</i>\n    <i>str-whitespace<sub>opt</sub>   str-whitespace-char</i>\n\n  <i>str-whitespace-char::</i>\n    <i>new-line</i>\n    Space character (U+0020)\n    Horizontal-tab character (U+0009)\n    Vertical-tab character (U+000B)\n    Form-feed character (U+000C)\n\n  <i>str-number::</i>\n    <i>digit-sequence</i>\n    <i>floating-literal</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*digit-sequence*](09-lexical-structure.md#floating-point-literals)\n* [*floating-literal*](09-lexical-structure.md#floating-point-literals)\n* [*new-line*](09-lexical-structure.md#comments)\n* [*sign*](09-lexical-structure.md#floating-point-literals)\n\nNote that *digit-sequence* is interpreted as having base-10 (so `\"0377\"` is treated as 377 decimal with a redundant\nleading zero, rather than as octal 377).\n\nOnly one mutation operation may be performed on a string, offset\nassignment, which involves the [simple assignment operator `=`](10-expressions.md#simple-assignment).\n\nThe library function [`is_string`](http://www.php.net/is_string) indicates if a given value has\ntype `string`.\n\n## The Array Key Type\nThe type `arraykey` can represent any integer or string value.\n\nSee the discussion of [type side effects](05-types.md#type-side-effects).\n\n## The Null Type\n\nThe null type has only one possible value, [`null`](06-constants.md#core-predefined-constants). The representation\nof this type and its value is unspecified.\n\nThe library function [`is_null`](http://www.php.net/is_null) indicates if a given value is `null`.\n\n## Enumerated Types\n\nEnumerated types are described in [§§](13-enums.md#enums).\n\n## The Void Type\n\nThe type `void` indicates the absence of a value. Its primary use is as the\nreturn type of a function.\n\n## Array Types\n\n**Syntax**\n<pre>\n<i>vector-like-array-type-specifier:</i>\n  array &lt; <i>array-value-type-specifier</i> &gt;\n\n<i>map-like-array-type-specifier:</i>\n  array &lt; <i>array-value-type-specifier</i> , <i>array-value-type-specifier</i> &gt;\n\n<i>array-value-type-specifier:</i>\n  <i>type-specifier</i>\n\n<i>array-key-type-specifier:</i>\n  <i>type-specifier</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*type-specifier*](05-types.md#general).\n\n**Constraints**\n\nThis is not currently a syntax constraint, but ... Although\n*array-key-type-specifier* can really be any type,\nbehind the scenes, the key is actually represented as an `int` or `string`,\nso (possibly surprising, or at least, unexpected) conversions occur when other\nkey types are specified. Similarly, *array-value-type-specifier* can really be\nany type. Programmers are\nstrongly advised to avoid using key types other than `int` or `string`.\n\n**Semantics**\n\nAn *array* is a data structure that contains a collection of zero or more elements each of which is accessed through a corresponding key. As the number\nof elements in an array can change at runtime, the *type-specifier* for an\narray does not include an element count.\n\nFor a *vector-like-array-type-specifier*, the array has an implicit key type\nof `int`, and an explicit value type as indicated by\n*array-value-type-specifier*.\n\nFor a *map-like-array-type-specifier*, the array has an explicit key type as\nindicated by *array-key-type-specifier*, and an explicit value type as\nindicated by *array-value-type-specifier*.\n\nEach element in an array must have a type that is the exact type indicated by\n*array-value-type-specifier*, or a [subtype](05-types.md#supertypes-and-subtypes) of that type. For example,\nan array of `num` can contain a mixture of `int` elements and `float` elements.\n\nAn array element can have any type (which allows for arrays of arrays).\n\nAn array is represented as an ordered map in which each entry is a key/value\npair that represents an element. Duplicate keys are not permitted. The order\nof the elements in the map is the order in which the elements were inserted\ninto the array. An element is said to *exist* once it has been inserted into\nthe array with a corresponding key. An array is *extended* by initializing a\npreviously non-existent element using a new key. Elements cannot be removed\nfrom an array.\n\nThe [`foreach` statement](11-statements.md#the-foreach-statement) can be used to iterate over the collection\nof elements in an array, in the order in which the elements were inserted.\nThis statement provides a way to access the key and value for each element.\n\nEach array has its own current element pointer that designates the current\narray element. When an array is created, the current element is the first\nelement inserted into the array.\n\n[Note: Arrays in Hack are quite different to arrays in numerous mainstream\nlanguages. Specifically, in Hack, array elements need not have the same type,\nthe subscript index need not be an integer (so there is no concept of a base\nindex of zero or 1), and there is no concept of consecutive elements occupying\nphysically adjacent memory locations.]\n\nAn array is created and initialized by one of two equivalent ways: via the [array-creation operator `[]`](10-expressions.md#array-creation-operator) or the intrinsic [`array`](10-expressions.md#array).\n\nThe value (and possibly the type) of an existing element is obtained or\nchanged, and new elements are inserted, using the [subscript operator `[]`](10-expressions.md#subscript-operator).\n\nThe library function [`is_array`](http://www.php.net/is_array) indicates if a given value is an array.\nNumerous other library functions are available to create and/or manipulate\narrays.\n\n**Examples**\n```Hack\nprivate array<string> $colorsVect;\nprivate array<int, string> $colorsMap;\nprivate array<num> $measurements = array(10, 25.55);\nprivate array<int, mixed> $items = array(true, 123, ‘red’, null);\nprivate array<array<int>> $valueSets = array(array(10,20,30,40), array(1,2));\nfunction f(array<?Button> $buttons): void { … }\nfunction getProcesses(): array<?(function (string): int)> { … }\n```\n\n## Class Types\n\nClass types are described in [§§](16-classes.md#classes).\n\nSee the discussion of [type side effects](05-types.md#type-side-effects).\n\nThe library function [`is_object`] (http://www.php.net/is_object) indicates if a given value is an\ninstance of any class, and the library function\n[`get_class`](http://docs.hhvm.com/manual/en/function.get-class.php)\n(§xx) indicates the name of an object's class. See also the [`instanceof`\noperator](10-expressions.md#instanceof-operator).\n\n## Interface Types\n\nInterface types are described in [§§](17-interfaces.md#interfaces).\n\nSee the discussion of [type side effects](05-types.md#type-side-effects).\n\n## Trait Types\n\nTrait types are described in [§§](18-traits.md#traits).\n\nAlthough traits are used to declare class and interface types, a trait type\ncannot be used in the usual context of a type name (see [Constraints](05-types.md#general).\nThat said, for the purposes of [subtyping](05-types.md#supertypes-and-subtypes), traits are considered types.\n\n## The `this` Type\n\nThe type name `this` refers to “the current class type at run time”. As such, it can only be used from within a class, an interface, or a trait. (`this` should not be confused with [`$this`](10-expressions.md#primary-expressions), which refers to “the current instance”, whose type is `this`.)\n\n## Tuple Types\n\n**Syntax**\n<pre>\n<i>tuple-type-specifier:</i>\n  ( <i>type-specifier</i>  ,  <i>type-specifier-list</i>  )\n</pre>\n\n**Defined elsewhere**\n\n* [*type-specifier*](05-types.md#general)\n* [*type-specifier-list*](05-types.md#general)\n\n**Semantics**\n\nA *tuple* is a sequence of one or more elements the number of which is fixed\nat the time of tuple creation. After a tuple has been created, no elements can\nbe added or removed, and the type of an existing element cannot be changed.\nHowever, the value of any existing element can be changed. Each element can\nhave any type, and each unique, lexically ordered combination of element types\ndesignates a distinct tuple type.\n\nA tuple can be indexed with the [subscript operator](10-expressions.md#subscript-operator). The index of the\nfirst element is zero, with subsequent elements having index values one more\nthan their predecessor. Specifically, for a tuple having n elements, their\nindices are 0–*n*-1.\n\nNote: Although a tuple of only one element can be created using a [tuple\nliteral](10-expressions.md#tuple-literals), a *tuple-type-specifier* must contain at least two elements.\nWhile this disallows a function to take an argument or to return a value of\ntype (*T*), for example, one could simply declare that function to take or\nreturn a value of type *T* directly instead.\n\n**Examples**\n\n```Hack\nfunction f1((int, string) $p): void { … }\n// -----------------------------------------\nfunction f2(): (bool, array<int>, float) {\n  return tuple(true, array(99, 88, 77), 10.5);\n}\n// -----------------------------------------\nprivate ?(int, (string, float)) $prop = null;\n```\n\n## Shape Types\n\n**Syntax**\n<pre>\n<i>shape-specifier:</i>\n  shape ( <i>field-specifier-list<sub>opt</sub></i> )\n\n<i>field-specifier-list:</i>\n  <i>field-specifier</i>\n  <i>field-specifier-list</i>  ,  <i>field-specifier</i>\n\n<i>field-specifier:</i>\n  <i>single-quoted-string-literal</i>  =>  <i>type-specifier</i>\n  <i>qualified-name</i>  =>  <i>type-specifier</i>\n  <i>scope-resolution-expression</i>  =>  <i>type-specifier</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*qualified-name*](20-namespaces.md#defining-namespaces)\n* [*scope-resolution-expression*](10-expressions.md#scope-resolution-operator)\n* [*single-quoted-string-literal*](09-lexical-structure.md#single-quoted-string-literals)\n* [*type-specifier*](05-types.md#general)\n\n**Constraints**\nThe *qualified-name* or *scope-resolution-expression* must designate \na [class constant](16-classes.md#constants) of type `int` or `string`.\n\nEach string in the set of strings designated by all the\n*single-quoted-string-literals*, *qualified-names* and\n*scope-resolution-expressions* in a\n*field-specifier-list* must have a distinct value.\n\nEach integer in the set of all the *qualified-names* and \n*scope-resolution-expressions* \nin a *field-specifier-list* must have a distinct value.\n\nThe *field-specifiers* in a *field-specifier-list* must all have the\n*single-quoted-string-literal* form, or all\nhave the *qualified-name* or *scope-resolution-expression* form; \nthe forms must not be mixed.\n\n**Semantics**\n\nA *shape* consists of a group of zero or more data *fields* taken together as\na whole. [It takes on the role of what C and C# call a struct.] Such a\nconstruct is sometimes referred to as a \"lightweight class\".\n\nA *shape-specifier* defines a shape type as having an unordered set of fields\neach of which has a name (indicated by *single-quoted-string-literal*, \n*qualified-name* or *scope-resolution-operator*) and a type (indicated by\n*type-specifier*). A field in a shape is accessed using its name as the key in\na [*subscript-expression*](10-expressions.md#subscript-operator) that operates on a shape of the\ncorresponding shape type.\n\nA field that has a [nullable type](05-types.md#nullable-types) need not be mentioned in any initializer of, or assignment to, a variable of that type; however, until its value is set explicitly, that field does not actually exist in the shape. Consider the following:\n\n```Hack\nfunction f3(shape('a' => int, 'n' => ?string) $p): void {\n  echo \"\\$p['a']: \" . $p['a'] . \"\\n\";\n  echo \"\\$p['n']: \" . $p['n'] . \"\\n\";  // only permitted if n exists\n}\n```\n\nGiven the call `f3(shape('a' => 10, 'n' => null))`, field `n` has its value set explicitly, and `f3` works fine. However, given the call `f3(shape('a' => 10))`, field `n` does not have its value set explicitly, in which case, attempting to access that field using `$p['n']` results in an “undefined index” error at runtime. To be certain such accesses succeed, first call [`Shapes::keyExists`](16-classes.md#class-shapes).\n\nConsider a shape type *S2* whose field set is a superset of that in shape type *S1*. As such, *S2* is a subtype of *S1*. (See the banking example below.) However, when an *S2* is used as an *S1*, only the *S1* fields in that *S2* are accessible.\n\n**Examples**\n\n```Hack\nshape('x' => int, 'y' => int)\nshape('real' => float, 'imag' => float)\nshape('id' => string, 'url' => string, 'count' => int)\nshape('name' => string, 'address' => shape('street' => string, 'city' => string, 'state' => string, 'postcode' => int));\ntype APoint<T> = shape('x' => T, 'y' => T);\n// -----------------------------------------\nenum Bank: int {\n  INVALID = 0;\n  DEPOSIT = 1;\n  WITHDRAWAL = 2;\n  TRANSFER = 3;\n}\n\ntype Transaction = shape('trtype' => Bank);\ntype Deposit = shape('trtype' => Bank, 'toaccnum' => int, 'amount' => float);\ntype Withdrawal = shape('trtype' => Bank, 'fromaccnum' => int, 'amount' => float);\ntype Transfer = shape('trtype' => Bank, 'fromaccnum' => int, 'toaccnum' => int, 'amount' => float);\n\nfunction main(): void {\n  processTransaction(shape('trtype' => Bank::DEPOSIT, 'toaccnum' => 23456, 'amount' => 100.00));\n  processTransaction(shape('trtype' => Bank::WITHDRAWAL, 'fromaccnum' => 3157, 'amount' => 100.00));\n  processTransaction(shape('trtype' => Bank::TRANSFER, 'fromaccnum' => 23456, 'toaccnum' => 3157, 'amount' => 100.00));\n}\n\nfunction processTransaction(Transaction $t): void {\n  $ary = Shapes::toArray($t);\n  switch ($t['trtype']) {\n  case Bank::TRANSFER:\n    echo \"Transfer: \" . ((string)$ary['amount'])\n      . \" from Account \" . ((string)$ary['fromaccnum'])\n      . \" to Account \" . ((string)$ary['toaccnum']) . \"\\n\";\n    break;\n\n  case Bank::DEPOSIT:\n    …\n  }\n}\n```\n\nNote carefully, that inside function `processTransaction`, even though the transaction passed in might have been a `Deposit`, a `Withdrawal`, or a `Transfer`, it always appears as a `Transaction`, so the only field you can access in `$t` is `trtype`. However, using `Shapes::toArray`, we can convert the `Transaction` to an array, and then get read-access to the field values we know that array must contain by indexing it using the field names, as shown.\n\n## Closure Types\n\n**Syntax**\n<pre>\n<i>closure-type-specifier:</i>\n( function ( <i>type-specifier-list<sub>opt</sub></i> ) : <i>type-specifier</i> )\n</pre>\n\n**Defined elsewhere**\n\n* [*type-specifier*](05-types.md#general)\n* [*type-specifier-list*](05-types.md#general)\n\n**Semantics**\n\nA *closure* is an object that encapsulates a function with a given argument\nlist and return type. The function can then be called through that object by\nusing the [function-call operator](10-expressions.md#function-call-operator).\n\nNote: The library functions [`class_meth`](http://www.php.net/class_meth), [`fun1](http://www.php.net/fun), [`inst_meth`](http://www.php.net/inst_meth), and [`meth_caller`](http://www.php.net/meth_caller) allow a string constant containing the name of\na function to be turned into a closure.\n\n**Examples**\n\n```Hack\nprivate (function (): void) $prop;\npublic function setProcess1((function (int): (int, int)) $val): void { … }\npublic function getProcess2(): (function (): ?array<int>) { … }\n// -----------------------------------------\nfunction doit(int $iValue, (function (int): int) $process): int {\n  return $process($iValue);\n}\n$result = doit(5, function (int $p) { return $p * 2; });    // doubles 5\n$result = doit(5, function (int $p) { return $p * $p; });   // squares 5\n```\n\n## Resource Types\n\nA [*resource*](http://docs.hhvm.com/manual/en/language.types.resource.php)\nis a descriptor to some sort of external entity. (Examples include\nfiles, databases, and sockets.)\n\nA resource is an abstract entity whose representation is unspecified.\nResources are only created or consumed by the implementation; they are\nnever created or consumed by Hack code.\n\nEach distinct resource has a unique ID of some unspecified form.\n\nWhen scripts execute in a mode having a command-line interface, the\nfollowing predefined resource-like constants that correspond to file streams\nare automatically opened at program start-up:\n\n-   STDIN, which maps to standard input (php://stdin)\n-   STDOUT, which maps to standard output (php://stdout)\n-   STDERR, which maps to standard error (php://stderr)\n\nThese constants have some unspecified type, which behaves like a subtype of\ntype `resource`.\n\nThe library function [`is_resource`](http://www.php.net/is_resource) indicates if a given value is a\nresource, and the library function\n[`get_resource_type`](http://docs.hhvm.com/manual/en/function.get-resource-type.php)\n(§xx) indicates the type of a resource.\n\n## Nullable Types\n\n**Syntax**\n<pre>\n  <i>nullable-type-specifier:</i>\n  ? <i>type-specifier</i>\n  mixed\n</pre>\n\n**Defined elsewhere**\n\n* [*type-specifier*](05-types.md#general)\n\n**Constraints**\n\n*type-specifier* must not be `void` or `mixed`.\n\n**Semantics**\nExcept for the type `mixed`, a *nullable* type can represent all of the values\nof its underlying type, plus an additional value, `null`. In such cases, a\nnullable type is written *?T*, where *T* is the underlying type. For example, a\nvariable of type `?bool` can contain the values `true`, `false`, or `null`.\n\nA variable of type `mixed` can represent the values of any other type, including any nullable type, which makes mixed a nullable type. (As such,\nthere is no type `?mixed`.)\n\nSee the discussion of [type side effects](05-types.md#type-side-effects).\n\n**Examples**\n```Hack\nprivate ?bool $pr_nbool;\nprivate mixed $pr_mixed;\nprivate array<?int> $a_nint = array(3, null);   // array of nullable int\nprivate ?Button $pr_nButton;                    // nullable class\nprivate ?MyCollection $pr_nMyCollection;        // nullable interface\nprivate ?(int, ?string, ?(bool, int)) $pr;      // nullable tuple whose\n    // second element has type \"nullable string\", and whose third element\n    // has type \"nullable tuple of bool and int\"\n```\n\n## Generic Types\nHack contains a mechanism to define generic (that is, type-less) classes,\ninterfaces, and traits, and to create type-specific instances of them via\nparameters. See [§§](14-generic-types-methods-and-functions.md#generic-types-methods-and-functions).\n\n## The Classname Type\n\n**Syntax**\n<pre>\n<i>classname-type-specifier:</i>\n  classname  <  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>  >\n</pre>\n\n**Defined elsewhere**\n\n* [*qualified-name*](20-namespaces.md#defining-namespaces)\n\n**Constraints**\n\n*qualified-name* must be the name of a class or interface type.\n\n**Semantics**\n\nThis type gets around some limitations Hack has that its ancestor, PHP, does not. Specifically, the use of type-name strings as operands to [`new`](10-expressions.md#the-new-operator), [`instanceof`](10-expressions.md#instanceof-operator), and [`::`](10-expressions.md#scope-resolution-operator), is prohibited in Hack. However, equivalent functionality is possible via an instance of this type (which can only be created via `::`).\n\nThe value of an expression of the classname type can be converted implicitly or explicitly to type [`string`](08-conversions.md#converting-to-string-type). The classname type is not assignment-compatible with any other type.\n\nThe representation of a value having the classname type is unspecified.\n\n**Examples**\n\n```Hack\nnamespace NS_cn;\nclass C1 { … }\nclass C2 {\n  public static classname<\\NS_cn\\C1> $p1 = \\NS_cn\\C1::class;\n  public static function f(?classname<C1> $p) : classname<C1> { … }\n  public static array<classname<C1>> $p2 = array(C1::class);\n}\n```\n\n## Type Aliases\n\n**Syntax**\n<pre>\n<i>alias-declaration:</i>\n  <i>attribute-specification<sub>opt</sub>  type  <i>name</i>  <i>generic-type-parameter-list</i><sub>opt</sub>  =  <i>type-specifier</i>  ;\n  <i>attribute-specification<sub>opt</sub>  newtype  <i>name</i>  <i>generic-type-parameter-list</i><sub>opt</sub>  <i>type-constraint<sub>opt</sub></i>  =  <i>type-specifier</i>  ;\n</pre>\n\n**Defined elsewhere**\n\n* [*attribute-specification*](21-attributes.md#attribute-specification)\n* [*generic-type-parameter-list*](14-generic-types-methods-and-functions.md#type-parameters)\n* [*name*](09-lexical-structure.md#names)\n* [*type-constraint*](05-types.md#general)\n* [*type-specifier*](05-types.md#general)\n\n**Constraints**\n\nThe *type-specifier* in the optional *type-constraint* must be a subtype \nof the *type-specifier* to the right of the equals.\n\n**Semantics**\n\nAn *alias-declaration* creates an alias *name* for the specified type.\nOnce such a type alias has been defined, that alias can\nbe used in any context in which a *type-specifier* is permitted.\n\nAny given type can have multiple aliases, and a type alias can itself have\naliases.\n\nAn alias created using `type` is a *transparent type alias*. For a given type,\nthat type and all transparent aliases to that type are all the same type, and\ncan be freely interchanged. There are no restrictions on where a transparent\ntype alias can be defined or which source code can access its underlying\nimplementation.\n\nAn alias created using `newtype` is an *opaque type alias*. In the absence of\na *type-constraint*, each opaque alias type is distinct from its\nunderlying type and from any other types aliasing it or its underlying type. \nOnly source code in the file that contains the definition of the opaque type \nalias is allowed access to the underlying implementation. As such, opaque type \naliasing is an abstraction mechanism. Consider the following file, which \ncontains an opaque alias definition:\n\n```Hack\nnewtype Point = (int, int);\n\nfunction create_point(int $x, int $y): Point {\n  return tuple($x, $y);\n}\n\nfunction distance(Point $p1, Point $p2): float {\n  $dx = $p1[0] - $p2[0];\n  $dy = $p1[1] - $p2[1];\n  return sqrt($dx*$dx + $dy*$dy);\n}\n```\n\nBeing in the same file as the alias definition, the functions `create_point`\nand distance have direct access to the integer fields in any `Point`'s tuple.\nHowever, any file that includes this file does not.\n\nSimilarly, if a file defines the following alias:\n\n`newtype Widget = int;`\n\nany file that includes this file has no knowledge that a `Widget` is really an\ninteger, so that the including file cannot perform any integer-like operations\non a `Widget`.\n\nThe presence of a *type-constraint* allows an opaque type alias to be treated\nas if it had the type specified by *type-specifier* in *type-constraint*, which removes some\nof the alias' opaqueness. Note: Although the presence of a constraint allows\nthe alias type to be converted implicitly to that constraint type, there is no\nconversion in the opposite direction.\n\n**Examples**\n\n```Hack\ntype Counter = int;\nnewtype NameList = array<string>;\n// -----------------------------------------\nclass Fullname {\n  private string $firstName = '';\n  private string $lastName = '';\n}\ntype Name = Fullname;\nclass C1 {\n  private ?Name $pr = null;\n  public static function fa(Name $p1, array<Name> $p2): void {}\n}\n// -----------------------------------------\ntype Complex = shape('real' => float, 'imag' => float);\ntype PropList = (int, string, int);\nnewtype Matrix<T> = Vector<Vector<T>>;\ntype Serialized<T> = string;    // T is not used\n```\n\n## Supertypes and Subtypes\n\nThe set of built-in and user-defined types in Hack can be represented as a\ndirected graph in which each vertex designates a distinct type. Each directed\nedge connects one vertex with another, with the starting vertex of an edge\nbeing a *supertype* of the *subtype* designated by the ending vertex of that edge.\n\nA supertype can have one or more subtypes, and a subtype can have one or more\nsupertypes. A supertype can be a subtype of some other supertype, and a\nsubtype can be a supertype of some other subtype. If T1 is a supertype of T2,\nand T2 is, in turn, a supertype of T3, then T1 is a supertype of T3, and T3 is\na subtype of T1.\n\nThe relationship between a supertype and any of its subtypes involves the\nnotion of substitutability. Specifically, if T2 is a subtype of T1, program\nelements designed to operate on T1 can also operate on T2.\n\nFor types in Hack, the following rules apply:\n\n1.  The source vertex of the graph is the type `mixed`; as such, every type is a subtype of that type.\n2.  Any type is a subtype of itself.\n3.  `int` and `float` are subtypes of `num`.\n4.  `int` and `string` are subtypes of `arraykey`.\n5.  For each type T, T is a subtype of the nullable type ?T.\n6.  For each type T, the null type is a subtype of all nullable types ?T.\n7.  string is a subtype of `Stringish`.\n8.  The predefined types `Vector`, `ImmVector`, `Map`, `ImmMap`, `Set`, `ImmSet`, and `Pair` and all array types are subtypes of `Container`, `KeyedTraversable`, and `Traversable`.\n9.  The predefined types `Vector`, `ImmVector`, `Map`, `ImmMap`, and `Pair` and all array types are subtypes of `KeyedContainer`.\n10. If A is an alias for a type T created using type, then A is a subtype of T, and T is a subtype of A.\n11. If A is an alias for a type T created using `newtype`, inside the file containing the `newtype` definition, A is a subtype of T, and T is a subtype of A. Outside that file, A and T have no relationship, except that given `newtype` A as C = T, outside the file with the `newtype` definition, A is a subtype of C.\n12. Any class, interface, or trait having a public instance method `__toString` taking no arguments and returning string, is a subtype of `Stringish`.\n13. A class type is a subtype of all its direct and indirect base-class types, including those resulting from [*require-extends-clauses*](17-interfaces.md#interface-members).\n14. A class type is a subtype of all the interfaces it and its direct and indirect base-class types implement, including those resulting from [*require-implements-clauses*](18-traits.md#trait-members).\n15. An interface type is a subtype of all its direct and indirect base interfaces.\n16. A shape type *S2* whose field set is a superset of that in shape type *S1*, is a subtype of *S1*.\n17. Although this specification doesn’t treat the *return-type* [`noreturn`](15-functions.md#function-definitions) as a type, per se, `noreturn` is regarded as a subtype of all other types, and a supertype of none.\n\n## Type Side Effects\n\nAs stated in [§§](05-types.md#supertypes-and-subtypes), a supertype has one or more subtypes, and while any\noperation permitted on a value of some supertype is also permitted on a value\nof any of its subtypes, the reverse is not true. For example, the type `num`\nis a supertype of `int` and `float`, and while addition and subtraction are\nwell defined for all three types, bit shifting requires integer operands. As\nsuch, a `num` cannot be bit-shifted directly. (Similar situations occur with\n`arraykey` and its subtypes `int` and `string`, with nullable types and their subtypes, and with `mixed` and its subtypes.)\n\nCertain program elements are capable of changing the type of an expression\nusing what is called a *type side effect* (which is not to be confused with a\n[*value side effect*](10-expressions.md#general).\n\nConsider the following function:\n\n```Hack\nfunction F_n_int(?int $p1): void {\n  $x = $p1 % 3;         // rejected; % not defined for ?int\n  if (is_int($p1)) {    // type side effect occurs; $p1 has type int\n    $x = $p1 % 3;       // accepted; % defined for int\n  }\n```\n\nOn entry, `$p1` contains `null` or some `int`. However, the type of the\nexpression `$p1` is not known to be `int`, so it is not safe to allow the `%`\noperator to be applied. When the library function `is_int` is applied to `$p1`\n, a type side effect occurs in which the type of the expression `$p1` is changed to `int` **for the true path of the `if` statement only**. As such,\nthe `%` operator can be applied. However, once execution flows out of the `if`\nstatement, the type of the expression `$p1` is `?int`.\n\nConsider the following code:\n\n```Hack\n  if (is_null($p1)) {   // type side effect occurs; $p1 has type null\n    $x = $p1 % 3;         // rejected; % not defined for null\n  } else {              // type side effect occurs; $p1 has type int\n    $x = $p1 % 3;         // accepted; % defined for int\n  }\n```\n\nThe first assignment is rejected, not because we don’t know `$p1`'s type, but\nbecause we know its type is not `int`. See how an opposite type side effect\noccurs with the `else`.\n\nSimilarly, we can write the following:\n\n```Hack\n  if (!is_null($p1)) {// type side effect occurs; $p1 has type int\n    $x = $p1 % 3;   // accepted; % defined for int\n  }\n\n  if ($p1 !== null) {   // type side effect occurs; $p1 has type int\n    $x = $p1 % 3;   // accepted; % defined for int\n  }\n}\n```\n\nConsider the following example that contains non-trivial selection criteria:\n\n```Hack\nfunction F_n_num(?num $p1): void {\n  if (is_int($p1) || is_float($p1)) {\n    $x = $p1**2;    // rejected\n  }\n  …\n}\n```\n\nAn implementation is **not** required to produce the correct type side effect when\nusing multiple criteria directly.\n\nThe following example shows type side effects in the context of a nullable\nclass type that involves inheritance:\n\n```Hack\nfunction F_Button(Button $p1): void {}\nfunction F_CustomButton(CustomButton $p1): void {}\nfunction F_n_class_hier(?Button $p1): void {\n  if (!is_null($p1)) {      // type side effect occurs; $p1 has type Button\n    F_Button($p1);          // call permitted; argument has type Button\n    F_CustomButton($p1);    // call rejected; not necessarily a CustomButton\n    if ($p1 instanceof CustomButton) {  // type side effect occurs\n      F_CustomButton($p1);  // call permitted; argument has type CustomButton\n    }\n  }\n}\n```\n\nThe following constructs involve type side effects:\n\n* When used as the controlling expression in an `if`, `while`, or `for`statement, the operators [`==`, `!=`, `===`, and `!==`](10-expressions.md#equality-operators) when used with one operand of `null`, [`instanceof`](10-expressions.md#instanceof-operator), and [simple assignment `=`](10-expressions.md#simple-assignment). [Note that if `$x` is an expression of some nullable type, the logical test `if ($x)` is equivalent to `if ($x !== null)`.]\n* The operators `&&`, `||`, and `?:`.\n* The intrinsic [`invariant`](10-expressions.md#invariant).\n* The library functions `is_array`, `is_bool`, `is_float`, `is_int`, `is_null`, `is_resource`, and `is_string`.\n\nThus far, all the examples use the value of an expression that designates a\nparameter (which is a local variable). Consider the following case, which\ninvolves a property instead:\n\n```Hack\nclass C {\n  private ?int $p1 = 8;     // holds an int, but type is ?int\n  public function m(): void {\n    if (is_int($this->p1)) {    // type side effect occurs; $this->p1 is int\n      $x = $this->p1 << 2;      // allowed; type is int\n      $this->n();           // could involve a type side effect on $p1\n      $x = $this->p1 << 2;      // disallowed; might no longer be int\n    }\n  }\n  public function n(): void { … }\n}\n```\n\nInside the true path of the `if` statement, even though we know that\n`$this->p1` is an `int` to begin with, once any method in this class is\ncalled, the implementation must assume that method could have caused a type side\neffect on anything currently in scope. As a result, the second attempt to left\nshift is rejected.\n\n## Type Inferencing\n\nWhile certain kinds of variables must have their type declared explicitly, others can have their type inferred by having the implementation perform static analysis of the context in which those variables are used. Specifically,\n* Types **must be declared** for [properties](16-classes.md#properties) and for the parameters and the return type of a [named  function](15-functions.md#function-definitions).\n* Types **must be inferred** for [local variables](07-variables.md#local-variables), which includes [function statics](07-variables.md#function-statics) and parameters.\n* Types **can be declared or inferred** for [constants](16-classes.md#constants) and for the parameters and return type of an [unnamed function](15-functions.md#anonymous-functions).\n\nThe process of type inferencing does not cross function boundaries.\n\nHere's an example involving a local variable:\n\n```Hack\nfunction f(): void {\n  $v = 'acb';       // $v has type string\n  …\n  $v = true;        // $v has type bool\n  …\n  $v = array('red' => 10; 'green' => 15); // $v has type map-like array of int\n  …\n  $v = new C();     // $v has type C\n}\n```\n\nFor each assignment, the type of `$v` is inferred from the type of the\nexpression on the right-hand side, as shown in the comments. The type of\nfunction statics is inferred in the same manner, as are function parameters.\n\nFor example:\n\n```Hack\nfunction g(int $p1 = -1): void\n{\n  // on entry to the function, $p1 has the declared type int\n  …\n  $p1 = 23.56;      // $p1 has type float\n  …\n}\n```\n\nAs a parameter, `$p1` is required to have a declared type, in this case,\n`int`. However, when used as an expression, `$p1`'s type can change, as shown.\n\nIn the case of a class constant, if the type is omitted, it is inferred from\nthe initializer:\n\n```Hack\nclass C {\n  const C1 = 10;            // type int inferred from initializer\n  const string C2 = \"red\";  // type string declared\n}\n```\n\nLet's consider types in anonymous functions:\n\n```Hack\n$doubler = (function ($p) { return $p * 2; });\n$doubler(3);\n$doubler(4.2);\n```\n\nThe type of the parameter `$p` and the function's return type have been\nomitted. These types are inferred each time the anonymous function is called\nthrough the variable `$doubler`. When `3` is passed, as that has type `int`,\nthat is inferred as the type of `$p`. The literal `2` also has type `int`, so\nthe type of the value returned is the type of `$p * 2`, which is `int`, and\nthat becomes the function's return type. When `4.2` is passed, as that has\ntype `float`, that is inferred as the type of `$p`. The literal `2` has type\n`int`, so the type of the value returned is the type of `$p * 2`, which is\n`float`, and that becomes the function's return type.\n\nConsider the following, subtly different, version (note the literal 2.0\ninstead of 2):\n\n`$doubler = (function ($p) { return $p * 2.0; });`\n\nWhether an `int` or `float` value is passed, it matters not, as when either is multiplied by a `float`, the result is `float`, so that becomes the function's return type.\n\nWe can add partial explicit type information; the following all result in the same behavior:\n\n```Hack\n$doubler = (function (int $p) { return $p * 2; });\n$doubler = (function ($p = 0) { return $p * 2; });\n$doubler = (function ($p): int { return $p * 2; });\n```\n\nIn the first case, as `$p` has the declared type `int`, and `int * int` gives\n`int`, the return type is inferred as `int`. In the second case, as the\ndefault value `0` has type `int`, `$p` is inferred to also have that type, and\n`int * int` gives `int`, so the return type is inferred as `int`. In the third\ncase, as the return type is declared as `int`, and `$p * 2` must have that\ntype, the type of `$p` is inferred as `int`, so that must also be the type of\nthe parameter.\n\nWhile all three of these cases allow a call such as `$doubler(3)`, none of\nthem allows a call such as `$doubler(4.2)`. So, the fact that type information\ncan be provided explicitly in these cases doesn’t mean it's necessarily a good idea to do so.\n\nOther considerations apply to type inferencing in the context of [generic types](14-generic-types-methods-and-functions.md#type-inferencing-revisited).\n"
  },
  {
    "path": "spec/06-constants.md",
    "content": "# Constants\n\n## General\n\nA *constant* is a [named](09-lexical-structure.md#names) value. Once defined, the value\nof the constant can not be changed.\n\nA constant can be defined in one of two ways: as a *c-constant* using a [*const-declaration*](16-classes.md#constants) or via a [string literal](09-lexical-structure.md#string-literals), or as a *d-constant* by calling the library function [`define`](http://www.php.net/define). However, the two approaches differ slightly. Specifically:\n\n-   The name of a c-constant must comply with the lexical grammar for a\n    name while that for a d-constant can contain any source character.\n-   The name of a c-constant is case-insensitive while that for a\n    d-constant can be case-sensitive or case-insensitive based on the\n    value of the third argument passed to `define`.\n-   If `define` is able to define the given name, it returns `true`;\n    otherwise, it returns `false`.\n\nThe library function [`defined`](http://www.php.net/defined) reports if a given name (specified as a string) is defined as a constant. The library function [`constant`](http://www.php.net/constant) returns the value of a given constant whose name is specified as a string.\n\n**Examples**\n\n```Hack\nclass C {\n  const float MAX_HEIGHT = 10.5;            // define two (case-insensitive) c-constants\n  const float UPPER_LIMIT = MAX_HEIGHT;\n}\ndefine('COEFFICIENT_1', 2.345, true); // define a case-insensitive d-constant\ndefine('FAILURE', true, false);       // define a case-sensitive d-constant\n```\n\n## Context-Dependent Constants\n\nThe following constants—sometimes referred to as *magic constants*—are\nautomatically available to all scripts; their values are not fixed:\n\n Constant Name                    | Description                     \n -----------------                | ---------                            \n `__CLASS__`                        | `string`; The name of the current class. From within a trait method, the name of the class in which that trait is used. If the current namespace is other than the default, the namespace name and \"\\\\\" are prepended, in that order. If used outside all classes, the value is the empty string. \n`__DIR__`                            | `string`; The directory name of the script. A directory separator is only appended for the root directory.\n`__FILE__`                           | `string`; The full name of the script.\n`__FUNCTION__`                       | `string`; Inside a function, the name of the current function exactly as it was declared, with the following prepended: If a named namespace exists, that namespace name followed by \"\\\". If used outside all functions, the result is the empty string. For a method, no parent-class prefix is present. (See `__METHOD__` and [anonymous functions](15-functions.md#anonymous-functions).)\n`__LINE__`                           | `int`; the number of the current source line\n`__METHOD__`                         | `string`; Inside a method, the name of the current method exactly as it was declared, with the following prepended, in order: If a named namespace exists, that namespace name followed by \"\\\"; the parent class name or trait name followed by `::`. If used outside all methods, the result is the same as for `__FUNCTION__`.\n`__NAMESPACE__`                      | `string`; The name of the current namespace exactly as it was declared. For the default namespace, the result is the empty string.\n`__TRAIT__`                          | `string`; The name of the current trait. From within a trait method, the name of the current trait. If used outside all traits, the result is the empty string.\n\nConstant names beginning with __ are reserved for future use by the Engine.\n\n## Core Predefined Constants\n\nThe following constants are automatically available to all scripts:\n\nConstant Name | Description\n-------------   | -----------  \n`E_ALL` | `int`; All errors and warnings, as supported.\n`E_COMPILE_ERROR` | `int`; Fatal compile-time errors. This is like an `E_ERROR`, except that `E_COMPILE_ERROR` is generated by the scripting engine.\n`E_COMPILE_WARNING` | `int`; Compile-time warnings (non-fatal errors). This is like an `E_WARNING`, except that `E_COMPILE_WARNING` is generated by the scripting engine.\n`E_CORE_ERROR` | `int`; Fatal errors that occur during Hack's initial start-up. This is like an `E_ERROR`, except that `E_CORE_ERROR` is generated by the core of Hack.\n`E_CORE_WARNING` | `int`; Warnings (non-fatal errors) that occur during Hack's initial start-up. This is like an `E_WARNING`, except that `E_CORE_WARNING` is generated by the core of Hack.\n`E_DEPRECATED` | `int`; Deprecation notices. Enable this to receive warnings about code that will not work in future versions.\n`E_ERROR` | `int`; Fatal run-time errors. These indicate errors that cannot be recovered from, such as a memory allocation problem. Execution of the script is halted.\n`E_NOTICE` | `int`; Run-time notices. Indicate that the script encountered something that could indicate an error, but could also happen in the normal course of running a script.\n`E_PARSE` | `int`; Compile-time parse errors.\n`E_RECOVERABLE_ERROR` | `int`; Catchable fatal error. It indicates that a probably dangerous error occurred, but did not leave the Engine in an unstable state. If the error is not caught by a user defined handler (see the library function [`set_error_handler`](http://www.php.net/set_error_handler)), the application aborts as it was an `E_ERROR`.\n`E_STRICT` | `int`; Have Hack suggest changes to the source code to ensure the best interoperability.\n`E_USER_DEPRECATED` | `int`; User-generated error message. This is like an `E_DEPRECATED`, except that `E_USER_DEPRECATED` is generated in Hack code by using the library function [`trigger_error`](http://www.php.net/trigger_error).\n`E_USER_ERROR` | `int`; User-generated error message. This is like an `E_ERROR`, except that `E_USER_ERROR` is generated in Hack code by using the library function [`trigger_error`](http://www.php.net/trigger_error).\n`E_USER_NOTICE` | `int`; User-generated warning message. This is like an `E_NOTICE`, except that `E_USER_NOTICE` is generated in Hack code by using the library function [`trigger_error`](http://www.php.net/trigger_error).\n`E_USER_WARNING` | `int`; User-generated warning message. This is like an `E_WARNING`, except that  `E_USER_WARNING` is generated in Hack code by using the library function [`trigger_error`](http://www.php.net/trigger_error).\n`E_WARNING` | `int`; Run-time warnings (non-fatal errors). Execution of the script is not halted.\n`E_USER_DEPRECATED` | `int`; User-generated warning message. This is like an `E_DEPRECATED`, except that  `E_USER_DEPRECATED` is generated in Hack code by using the library function [`trigger_error`](http://www.php.net/trigger_error).\n`INF` | `float`; Infinity\n`M_E` | `float`; e\n`M_PI` | `float`; Pi\n`NAN` | `float`; Not-a-Number\n`PHP_EOL` | `string`; the end-of-line terminator for this platform.\n`PHP_INT_MAX` | `int`; the maximum representable value for an integer.\n`PHP_INT_MIN` | `int`; the minimum representable value for an integer. \n`PHP_INT_SIZE` | `int`; the number of bytes used to represent an integer.\n\nThe members of the `E_*` family have values that are powers of 2, so\nthey can be combined meaningfully using bitwise operators.\n\n## User-Defined Constants\n\nA constant may be defined inside a [class](16-classes.md#constants) or inside an [interface](17-interfaces.md#constants).\n\n\n\n"
  },
  {
    "path": "spec/07-variables.md",
    "content": "# Variables\n\n## General\n\nA *variable* is a named area of data storage that has a type and a\nvalue. A variable is represented by a \n[VSlot](04-basic-concepts.md#general). A variable is created by [assigning a value to it](10-expressions.md#simple-assignment). A variable that somehow becomes defined, but is not initialized starts out with the value `null`.\n\nVariables have [names](09-lexical-structure.md#names). Distinct variables may have\nthe same name provided they are in different [scopes](04-basic-concepts.md#scope).\n\nA [constant](06-constants.md#general) is a variable that, once initialized, its value cannot\nbe changed. \n\nBased on the context in which it is declared, a variable has a \n[scope](04-basic-concepts.md#scope) and a [storage duration](04-basic-concepts.md#storage-duration).\n\nThe following kinds of variable may exist in a script:\n\n-   [Local variable](07-variables.md#local-variables)\n-   [Array element](07-variables.md#array-elements)\n-   [Function static](07-variables.md#function-statics)\n-   [Instance property](07-variables.md#instance-properties)\n-   [Static property](07-variables.md#static-properties)\n-   [Class and interface constant](07-variables.md#class-and-interface-constants)\n\n## Kinds of Variables\n\n### Local Variables\n\n**Syntax**\n\nSee Semantics below.\n\n**Semantics**\n\nExcept for a [function parameter](15-functions.md#general), a local variable is never defined explicitly; instead, it is created when it is first assigned a value. A local variable can be assigned to as a parameter in the parameter list of a [function definition](15-functions.md#function-definitions) or inside any [compound statement](11-statements.md#compound-statements). It has [function scope](04-basic-concepts.md#scope) and [automatic storage duration](04-basic-concepts.md#storage-duration). A local variable is a modifiable lvalue.\n\n**Examples**\n\n```Hack\nfunction doit(bool $p1): void {  // assigned the value true when called\n  $count = 10;\n    ...\n  if ($p1)\n  {\n    $message = \"Can't open master file.\";\n    ...\n  }\n  ...\n}\ndoit(true);\n// -----------------------------------------\nfunction f(): void\n{\n  $lv = 1;\n  echo \"\\$lv = $lv\\n\";\n  ++$lv;\n}\nfor ($i = 1; $i <= 3; ++$i)\n  f();\n```\n\nUnlike the [function static equivalent](07-variables.md#function-statics), function `f` outputs\n\"`$lv = 1`\" each time.\n\nSee the [recursive function example](04-basic-concepts.md#storage-duration).\n\n### Array Elements\n\n**Syntax**\n\n[Arrays](05-types.md#array-types) are created via the [array-creation operator](10-expressions.md#array-creation-operator) or\nthe intrinsic [`array`](10-expressions.md#array). At the same time, one or more elements\nmay be created for that array. New elements are inserted into an\nexisting array via the [simple-assignment operator](10-expressions.md#simple-assignment) in\nconjunction with the [subscript operator `[]`](10-expressions.md#subscript-operator).\n\n**Semantics**\n\nThe [scope](04-basic-concepts.md#scope) of an array element is the same as the scope of that\narray's name. An array element has [allocated storage duration](04-basic-concepts.md#storage-duration).\n\n**Examples**\n\n```Hack\n$colors = [\"red\", \"white\", \"blue\"]; // create array with 3 elements\n$colors[] = \"green\";                // insert a new element\n```\n\n### Function Statics\n\n**Syntax:**\n\n<pre>\n  <i>function-static-declaration:</i>\n    static <i>static-declarator-list</i>  ;\n  <i>static-declarator-list:</i>\n    <i>static-declarator</i>  \n    <i>static-declarator-list</i>  ,  <i>static-declarator</i> \n  <i>static-declarator:</i> \n    <i>variable-name</i>  <i>function-static-initializer<sub>opt</sub></i>\n  <i>function-static-initializer:</i>\n    = <i>const-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*variable-name*](09-lexical-structure.md#names)\n* [*constant-expression*](10-expressions.md#constant-expressions)\n\n**Semantics**\n\nA function static may be defined inside any [compound statement](11-statements.md#compound-statements).\nIt is a modifiable lvalue.\n\nA function static has [function scope](04-basic-concepts.md#scope) and \n[static storage duration](04-basic-concepts.md#storage-duration).\n\nThe value of a function static is retained across calls to its parent\nfunction. Each time the function containing a function static\ndeclaration is called, that execution is dealing with an [alias](04-basic-concepts.md#general)\nto that static variable. The next time that function\nis called, a new alias is created.\n\n**Examples**\n\n```Hack\nfunction f(): void {\n  static $fs = 1;\n  echo \"\\$fs = $fs\\n\";\n  ++$fs;\n}\nfor ($i = 1; $i <= 3; ++$i)\n  f();\n```\n\nUnlike the [local variable equivalent](07-variables.md#local-variables), function `f` outputs \"`$fs\n= 1`\", \"`$fs = 2`\", and \"`$fs = 3`\", as `$fs` retains its value across\ncalls.\n\n### Instance Properties\n\nThese are described in [class instance properties section](16-classes.md#properties). They have [class scope](04-basic-concepts.md#scope) and [allocated storage duration](04-basic-concepts.md#storage-duration).\n\n### Static Properties\n\nThese are described in [class static properties section](16-classes.md#properties). They have [class scope](04-basic-concepts.md#scope) and [static storage duration](04-basic-concepts.md#storage-duration).\n\n### Class and Interface Constants\n\nThese are described in [class constants section](16-classes.md#constants) and [interface constants section](17-interfaces.md#constants). They have [class or interface scope](04-basic-concepts.md#scope) and [static storage duration](04-basic-concepts.md#storage-duration).\n"
  },
  {
    "path": "spec/08-conversions.md",
    "content": "# Conversions\n\n## General\n\nSome operators implicitly convert automatically the values of operands\nfrom one type to another. Explicit conversion is performed using the\n[cast operator](10-expressions.md#cast-operator).\n\nIf an expression is converted to its own type, the type and value of the\nresult are the same as the type and value of the expression.\n\nWhen an expression of type `num` is converted, if that expression is currently \nan `int`, then `int` conversion rules apply; otherwise, `float` conversion rules apply.\n\nWhen an expression of type `arraykey` is converted, if that expression is \ncurrently an `int`, then `int` conversion rules apply; otherwise, `string` \nconversion rules apply.\n\n## Converting to Boolean Type\n\nNo non-`bool` type can be converted implicitly to `bool`. All other conversions \nmust be explicit.\n\nThe [result type](http://docs.hhvm.com/manual/en/language.types.boolean.php#language.types.boolean.casting) is `bool`.\n\nIf the source type is `int` or `float`, then if the source value tests equal\nto 0, the result value is `false`; otherwise, the result value is `true`.\n\nIf the source value is `null`, the result value is `false`.\n\nIf the source is an empty string or the string \"0\", the result value is\n`false`; otherwise, the result value is `true`.\n\nIf the source is an array with zero elements, the result value is `false`;\notherwise, the result value is `true`.\n\nIf the source is an object, the result value is `true`.\n\nIf the source is a resource, the result value is `false`.\n\nThe library function [`boolval`](http://www.php.net/boolval) allows values to be converted to\n`bool`.\n\n## Converting to Integer Type\n\nNo non-`int` type can be converted implicitly to `int`. All other conversions must be explicit.\n\nThe [result type](http://docs.hhvm.com/manual/en/language.types.integer.php#language.types.integer.casting) is `int`.\n\nIf the source type is `bool`, then if the source value is `false`, the\nresult value is 0; otherwise, the result value is 1.\n\nIf the source type is `float`, for the values `INF`, `-INF`, and `NAN`, the\nresult value is implementation-defined. For all other values, if the\nprecision can be preserved, the fractional part is rounded towards zero\nand the result is well defined; otherwise, the result is undefined.\n\nIf the source value is `null`, the result value is 0.\n\nIf the source is a [numeric string or leading-numeric string](05-types.md#the-string-type)\nhaving integer format, if the precision can be preserved the result\nvalue is that string's integer value; otherwise, the result is\nundefined. If the source is a numeric string or leading-numeric string\nhaving floating-point format, the string's floating-point value is\ntreated as described above for a conversion from `float`. The trailing\nnon-numeric characters in leading-numeric strings are ignored.  For any\nother string, the result value is 0.\n\nIf the source is an array with zero elements, the result value is 0;\notherwise, the result value is 1.\n\nIf the source is a resource, the result is the resource's unique ID.\n\nThe library function [`intval`](http://docs.hhvm.com/manual/en/function.intval.php) allows values\nto be converted to `int`.\n\n## Converting to Floating-Point Type\n\nNo non-`float` type can be converted implicitly to `float`. All other \nconversions must be explicit.\n\nThe [result type](http://docs.hhvm.com/manual/en/language.types.float.php#language.types.float.casting) is `float`.\n\nIf the source type is `int`, if the precision can be preserved the result\nvalue is the closest approximation to the source value; otherwise, the\nresult is undefined.\n\nIf the source is a [numeric string or leading-numeric string](05-types.md#the-string-type)\nhaving integer format, the string's integer value is treated as\ndescribed above for a conversion from `int`. If the source is a numeric\nstring or leading-numeric string having floating-point format, the\nresult value is the closest approximation to the string's floating-point\nvalue. The trailing non-numeric characters in leading-numeric strings\nare ignored. For any other string, the result value is 0.\n\nIf the source is an array with zero elements, the result value is 0.0; \notherwise, the result value is 1.0.\n\nIf the source is a resource, the result is the resource's unique ID.\n\nThe library function [`floatval`](http://www.php.net/floatval) allows values to be converted to\nfloat.\n\n## Converting to Number Type\n\nThe only implicit conversions to type `num` are from the types `int` and\n`float`. There is no change in representation during such conversions. There are no explicit conversions.\n\nThe result type is `num`.\n\n## Converting to String Type\n\nExcept for the [`classname` type](05-types.md#the-classname-type), no non-`string` type can be converted implicitly to `string`. All other conversions must be explicit.\n\nThe [result type](http://docs.hhvm.com/manual/en/language.types.string.php#language.types.string.casting) is `string`.\n\nIf the source type is `bool`, then if the source value is `false`, the\nresult value is the empty string; otherwise, the result value is \"1\".\n\nIf the source type is `int` or `float`, then the result value is a string\ncontaining the textual representation of the source value (as specified\nby the library function [`sprintf`](http://www.php.net/sprintf).\n\nIf the source value is `null`, the result value is an empty string.\n\nIf the source is an object, then if that object's class has a\n[`__toString` method](16-classes.md#method-__tostring), the result value is the string returned\nby that method; otherwise, the conversion is invalid.\n\nIf the source is a resource, the result value is an\nimplementation-defined string.\n\nIf the source type is the [`classname` type](05-types.md#the-classname-type), the result value is a string containing the corresponding fully qualified class or interface name without any leading `\\`.\n\nThe library function [`strval`](http://www.php.net/strval) allows values to be converted to\n`string`.\n\n## Converting to Array Key Type\n\nThe only implicit conversions to type `arraykey` are from the types `int` \nand `string`. There is no change in representation during such conversions. \nThere are no explicit conversions.\n\nThe result type is `arraykey`.\n\n## Converting to Array Type\n\nFor arrays of different types, no implicit conversions exist. There are no \nexplicit conversions.\n\n## Converting to Object Type\n\nAn object type can be converted implicitly to any object type from which the first object type is derived directly or indirectly. There are no other implicit or explicit conversions.\n\n## Converting to Interface Type\n\nAn object type can be converted implicitly to any interface type that object \ntype implements directly or indirectly.\n\nAn interface type can be converted implicitly to any interface type from which \nthe first interface type is derived directly or indirectly.\n\nThere are no other implicit or explicit conversions.\n\n## Converting to Resource Type\n\nThe [predefined resource-like constants](05-types.md#resource-types)) `STDIN`, `STDOUT`, and \n`STDERR`, can be converted implicitly to resource. No other non-resource type \ncan be so converted. No explicit conversions exist.\n\n## Converting to Mixed Type\n\nAny type can be converted implicitly to [`mixed`](05-types.md#nullable-types). No explicit conversions\nexist.\n"
  },
  {
    "path": "spec/09-lexical-structure.md",
    "content": "# Lexical Structure\n\n## Scripts\n\nA [script](04-basic-concepts.md#program-structure) is an ordered sequence of characters. Typically, a\nscript has a one-to-one correspondence with a file in a file system, but\nthis correspondence is not required.\n\nConceptually, a script is translated using the following steps:\n\n1.  Transformation, which converts a script from a particular character\n    repertoire and encoding scheme into a sequence of 8-bit characters.\n\n2.  Lexical analysis, which translates a stream of input characters into\n    a stream of tokens. \n\n3.  Syntactic analysis, which translates the stream of tokens into\n    executable code.\n\nConforming implementations must accept scripts encoded with the UTF-8\nencoding form (as defined by the Unicode standard), and transform them\ninto a sequence of characters. Implementations can choose to accept and\ntransform additional character encoding schemes.\n\n## Grammars\n\nThis specification shows the syntax of the Hack programming language\nusing two grammars. The *lexical grammar* defines how source\ncharacters are combined to form white space, comments, and tokens. The\n*syntactic grammar* defines how the resulting tokens are combined to\nform Hack programs.\n\nThe grammars are presented using *grammar productions*, with each one\ndefining a non-terminal symbol and the possible expansions of that\nnon-terminal symbol into sequences of non-terminal or terminal symbols.\nIn productions, non-terminal symbols are shown in slanted type *like\nthis*, and terminal symbols are shown in a fixed-width font `like this`. \n\nThe first line of a grammar production is the name of the non-terminal\nsymbol being defined, followed by one colon for a syntactic grammar\nproduction, and two colons for a lexical grammar production. Each\nsuccessive indented line contains a possible expansion of the\nnon-terminal given as a sequence of non-terminal or terminal symbols.\nFor example, the production:\n\n<pre>\n  <i>single-line-comment::</i>\n    // input-characters<sub>opt</sub>\n    #  input-characters<sub>opt</sub>\n</pre>\n\ndefines the lexical grammar production *single-line-comment* as being\nthe terminals `//` or `#`, followed by an optional *input-characters*. Each\nexpansion is listed on a separate line.\n\nAlthough alternatives are usually listed on separate lines, when there\nis a large number, the shorthand phrase “one of” may precede a list of\nexpansions given on a single line. For example,\n\n<pre>\n  <i>hexadecimal-digit:: one of</i>\n    0   1   2   3   4   5   6   7   8   9\n    a   b   c   d   e   f\n    A   B   C   D   E   F\n</pre>\n\n## Grammar ambiguities\n\nIn general, lexical processing results in the creation of the longest possible\nlexical element. However, in certain cases involving generic type specifiers\n(and array specifiers, which use generic type notation), this is not the case.\nFor example, in type specifiers like `X<Y<int>>` and `array<array<int>>`, the\nsource characters `>` and `>` are treated as two separate tokens rather than\nas the right-shift operator `>>`.\n\n## Lexical Analysis\n\n### General\n\nThe production *input-file* is the root of the lexical structure for a\nscript. Each script must conform to this production.\n\n**Syntax**\n\n<pre>\n  <i>input-file::</i>\n    <i>input-element</i>\n    <i>input-file   input-element</i>\n  <i>input-element::</i>\n    <i>comment</i>\n    <i>white-space</i>\n    <i>token</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*comment*](09-lexical-structure.md#comments)\n* [*token*](09-lexical-structure.md#general-1)\n* [*white-space*](09-lexical-structure.md#white-space)\n\n**Semantics:**\n\nThe basic elements of a script are comments, white space, and tokens.\n\nThe lexical processing of a script involves the reduction of that script\ninto a sequence of [tokens](09-lexical-structure.md#tokens) that becomes the input to the\nsyntactic analysis. Tokens can be separated by [white space](09-lexical-structure.md#white-space) and\n[delimited comments](09-lexical-structure.md#comments).\n\nApart from the exception noted in [§§](09-lexical-structure.md#grammar-ambiguities), lexical processing always results in the creation of the longest\npossible lexical element. (For example, `$a+++++$b` must be parsed as\n`$a++ ++ +$b`, which syntactically is invalid.)\n\n### Comments\n\nTwo forms of comments are supported: *delimited comments* and\n*single-line comments*. \n\n**Syntax**\n\n<pre>\n  <i>comment::</i>\n    <i>single-line-comment</i>\n    <i>delimited-comment</i>\n\n  <i>single-line-comment::</i>\n    //   <i>input-characters<sub>opt</sub></i>\n    #    <i>input-characters<sub>opt</sub></i>\n\n  <i>input-characters::</i>\n    <i>input-character</i>\n    <i>input-characters   input-character</i>\n\n  <i>input-character::</i>\n    Any source character except new-line\n\n  <i>new-line::</i>\n    Carriage-return character (U+000D)\n    Line-feed character (U+000A)\n    Carriage-return character (U+000D) followed by line-feed character (U+000A)\n\n  <i>delimited-comment::</i>\n    /*   No characters or any source character sequence except /*   */\n</pre>\n\n**Semantics**\n\nExcept within a string literal or a comment, the characters /\\* start a\ndelimited comment, which ends with the characters \\*/. Except within a\nstring literal or a comment, the characters // or \\# start a single-line\ncomment, which ends with a new line. That new line is not part of the\ncomment. However, if the single-line comment is the last source element\nin an embedded script, the trailing new line can be omitted. (Note: this\nallows for uses like `<?hh ... // ... ?>`.)\n\nA delimited comment can occur in any place in a script in which [white\nspace](09-lexical-structure.md#white-space) can occur. (For example;\n`/*...*/$c/*...*/=/*...*/567/*...*/;/*...*/` is parsed as `$c=567;`, and\n`$k = $i+++/*...*/++$j;` is parsed as `$k = $i+++ ++$j;`.)\n\nA number of single-line, so-called special comments are recognized by a\nconforming implementation; they are:\n\n* [`// FALLTHROUGH`](11-statements.md#the-switch-statement)\n* [`// strict`](04-basic-concepts.md#program-structure)\n\nwhere horizontal white space is permitted between the `//` and the start of\nthe comment text.\n\n**Implementation Notes**\n\nDuring tokenizing, an implementation can treat a delimited comment as\nthough it was white space.\n\n### White Space\n\nWhite space consists of an arbitrary combination of one or more\nnew-line, space, and horizontal tab characters.\n\n**Syntax**\n\n<pre>\n  <i>white-space::</i>\n    <i>white-space-character</i>\n    <i>white-space   white-space-character</i>\n\n  <i>white-space-character::</i>\n    <i>new-line</i>\n    Space character (U+0020)\n    Horizontal-tab character (U+0009)\n</pre>\n\n**Defined elsewhere**\n\n* [*new-line*](09-lexical-structure.md#comments)\n\n**Semantics**\n\nThe space and horizontal tab characters are considered *horizontal\nwhite-space characters*.\n\n### Tokens\n\n#### General\n\nThere are several kinds of source tokens:\n\n**Syntax**\n\n<pre>\n  <i>token::</i>\n    <i>variable-name</i>\n    <i>name</i>\n    <i>keyword</i>\n    <i>literal</i>\n    <i>operator-or-punctuator</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*keyword*](09-lexical-structure.md#keywords)\n* [*literal*](09-lexical-structure.md#general-2)\n* [*name*](09-lexical-structure.md#names)\n* [*operator-or-punctuator*](09-lexical-structure.md#operators-and-punctuators)\n* [*variable-name*](09-lexical-structure.md#names)\n\n#### Names\n\n**Syntax**\n\n<pre>\n  <i>variable-name::</i>\n    $   <i>name</i>\n\n  <i>name::</i>\n    <i>name-nondigit</i>\n    <i>name   name-nondigit</i>\n    <i>name   digit</i>\n\n  <i>name-nondigit::</i>\n    <i>nondigit</i>\n    one of the characters U+007f–U+00ff\n\n  <i>nondigit::</i> one of\n    _\n    a   b   c   d   e   f   g   h   i   j   k   l   m\n    n   o   p   q   r   s   t   u   v   w   x   y   z\n    A   B   C   D   E   F   G   H   I   J   K   L   M\n    N   O   P   Q   R   S   T   U   V   W   X   Y   Z\n</pre>\n\n**Defined elsewhere**\n\n* [*digit*](09-lexical-structure.md#integer-literals)\n\n**Semantics:**\n\nNames are used to identify the following: [constants](06-constants.md#general), [variables](07-variables.md#general), [labels](11-statements.md#labeled-statements), [enumerated types](13-enums.md#enum-declarations), [functions](15-functions.md#function-definitions), [classes](16-classes.md#class-declarations), [class members](16-classes.md#class-members), [interfaces](17-interfaces.md#interface-declarations), [traits](18-traits.md#general), [type aliases](05-types.md#type-aliases), [namespaces](20-namespaces.md#general),\nnames in [heredoc comments](09-lexical-structure.md#heredoc-string-literals) and [nowdoc comments](09-lexical-structure.md#nowdoc-string-literals); and [attributes](21-attributes.md#attributes).\n\nA *name* begins with an underscore (_), *name-nondigit*, or extended\nname character in the range U+007f–U+00ff. Subsequent characters can\nalso include *digit*s. A *variable name* is a name with a leading\ndollar ($).\n\nThe name `$_`, referred to as the *placeholder variable*, is reserved for use in the ([`list` intrinsic](§10-expressions.md#list)) and the ([`foreach` statement](§11-statements.md#The-foreach-Statement)). This name does not actually designate any storage; instead, it’s an indication that the value that would otherwise be stored in a variable in that context, is ignored.\n\nUnless stated otherwise ([§§](14-generic-types-methods-and-functions.md#type-parameters), [§§](15-functions.md#function-calls), [§§](16-classes.md#class-declarations), [§§](18-traits.md#trait-members)),\nnames are case-sensitive, and every character in a name is significant.\n\nFunction and method names beginning with two underscores (__) are\nreserved by the Hack language.\n\n**Examples**\n\n```Hack\nconst int MAX_VALUE = 100;\npublic function getData(): array<string> { ... }\nclass Point { ... }\ninterface ICollection { ... }\n```\n\n**Implementation Notes**\n\nAn implementation is discouraged from placing arbitrary restrictions on\nname length or length of significance.\n\n#### Keywords\n\nA *keyword* is a name-like sequence of characters that is reserved, and\ncannot be used as a name.\n\n**Syntax**\n\n<pre>\n  <i>keyword::</i> one of\n    abstract   arraykey   as   async   await   break   case   catch   class   classname   clone   const   continue   default   do\n    echo   else   elseif   enum   extends   final   finally   for   foreach   function   if   implements\n    instanceof   insteadof   interface   mixed   namespace   new   newtype   noreturn   num   parent   private\n    protected   public   require   require_once   return   self   shape   static   switch   throw   trait   try\n    tuple   type   use   while   yield\n</pre>\n\n**Semantics**\n\nKeywords are case-sensitive.\n\nNote: Strictly speaking, `false`, `null`, and `true` are not keywords;\nhowever, they do have predefined meanings, and can be thought of as keywords.\nLikewise for the names of the [intrinsics](10-expressions.md#general-2).\n\n#### Literals\n\n##### General\n\nThe source code representation of a value is called a *literal*.\n\n**Syntax**\n\n<pre>\n  <i>literal::\n    <i>boolean-literal</i>\n    <i>integer-literal</i>\n    <i>floating-literal</i>\n    <i>string-literal</i>\n    <i>null-literal</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*boolean-literal*](09-lexical-structure.md#boolean-literals)\n* [*floating-literal*](09-lexical-structure.md#floating-point-literals)\n* [*integer-literal*](09-lexical-structure.md#integer-literals)\n* [*null-literal*](09-lexical-structure.md#the-null-literal)\n* [*string-literal*](09-lexical-structure.md#string-literals)\n\n##### Boolean Literals\n\n**Syntax**\n\n<pre>\n  <i>boolean-literal::</i>\n    true\n    false\n</pre>\n\n**Semantics**\n\nThe type of a *boolean-literal* is bool. The values `true` and `false`\nrepresent the Boolean values True and False, respectively.\n\n**Examples**\n\n```Hack\n$done = false;\ncomputeValues($table, true);\n```\n\n##### Integer Literals\n\n**Syntax**\n\n<pre>\n  <i>integer-literal::</i>\n    <i>decimal-literal</i>\n    <i>octal-literal</i>\n    <i>hexadecimal-literal</i>\n    <i>binary-literal</i>\n\n    <i>decimal-literal::</i>\n      <i>nonzero-digit</i>\n      <i>decimal-literal   digit</i>\n\n    <i>octal-literal::</i>\n      0\n      <i>octal-literal   octal-digit</i>\n\n    <i>hexadecimal-literal::</i>\n      <i>hexadecimal-prefix   hexadecimal-digit</i>\n      <i>hexadecimal-literal   hexadecimal-digit</i>\n\n    <i>hexadecimal-prefix:: one of</i>\n      0x  0X\n\n    <i>binary-literal::</i>\n      <i>binary-prefix   binary-digit</i>\n      <i>binary-literal   binary-digit</i>\n\n    <i>binary-prefix:: one of</i>\n      0b  0B\n\n    <i>digit:: one of</i>\n      0  1  2  3  4  5  6  7  8  9\n\n    <i>nonzero-digit:: one of</i>\n      1  2  3  4  5  6  7  8  9\n\n    <i>octal-digit:: one of</i>\n      0  1  2  3  4  5  6  7\n\n    <i>hexadecimal-digit:: one of</i>\n      0  1  2  3  4  5  6  7  8  9\n            a  b  c  d  e  f\n            A  B  C  D  E  F\n\n    <i>binary-digit:: one of</i>\n        0  1\n</pre>\n\n**Constraints**\n\nThe value of an integer literal must be representable by its type.\n\n**Semantics**\n\nThe value of a decimal integer literal is computed using base 10; that\nof an octal integer literal, base 8; that of a hexadecimal integer\nliteral, base 16; and that of a binary integer literal, base 2.\n\nThe type of an *integer-literal* is `int`.\n\nUsing a twos-complement system, can the smallest negative value\n(-9223372036854775808 for 64 bits) be\nrepresented as a decimal integer literal? No. Consider the\nexpression -5. This is made up of two tokens: a unary minus followed by\nthe integer literal 5. As such, **there is no such thing as a\nnegative-valued decimal integer literal in Hack**. Instead, there is the\nnon-negative value, which is then negated. Literals written using hexadecimal, octal, or binary\nnotations are considered to have non-negative values.\n\n**Examples**\n\n```Hack\n$count = 10      // decimal 10\n\n0b101010 >> 4    // binary 101010 and decimal 4\n\n0XAF << 023      // hexadecimal AF and octal 23\n```\n\n##### Floating-Point Literals\n\n**Syntax**\n\n<pre>\n  <i>ﬂoating-literal::</i>\n    <i>fractional-literal   exponent-part<sub>opt</sub></i>\n    <i>digit-sequence   exponent-part</i>\n\n  <i>fractional-literal::</i>\n    <i>digit-sequence<sub>opt</sub></i> . <i>digit-sequence</i>\n    <i>digit-sequence</i> .\n\n  <i>exponent-part::</i>\n    e  <i>sign<sub>opt</sub>   digit-sequence</i>\n    E  <i>sign<sub>opt</sub>   digit-sequence</i>\n\n  <i>sign:: one of</i>\n    +  -\n\n  <i>digit-sequence::</i>\n    <i>digit</i>\n    <i>digit-sequence   digit</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*digit*](09-lexical-structure.md#integer-literals)\n\n**Constraints**\n\nThe value of a floating-point literal must be representable by its type.\n\n**Semantics**\n\nThe type of a *floating-literal* is `float`.\n\nThe constants [`INF`](06-constants.md#core-predefined-constants) and [`NAN`](06-constants.md#core-predefined-constants) provide access to the floating-\npoint values for infinity and Not-a-Number, respectively.\n\n**Examples**\n\n```Hack\n$values = array(1.23, 3e12, 543.678E-23);\n```\n\n##### String Literals\n\n**Syntax**\n\n<pre>\n  <i>string-literal::</i>\n    <i>single-quoted-string-literal</i>\n    <i>double-quoted-string-literal</i>\n    <i>heredoc-string-literal</i>\n    <i>nowdoc-string-literal</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*double-quoted-string-literal*](09-lexical-structure.md#double-quoted-string-literals)\n* [*heredoc-string-literal*](09-lexical-structure.md#heredoc-string-literals)\n* [*nowdoc-string-literal*](09-lexical-structure.md#nowdoc-string-literals)\n* [*single-quoted-string-literal*](09-lexical-structure.md#single-quoted-string-literals)\n\nNote: By conventional standards, calling [*heredoc-string-literal*s](#heredoc-string-literals)\nand [*nowdoc-string-literal*s](#nowdoc-string-literals)) literals is a stretch, as\neach is hardly a single token. And given the variable substitution permitted in *double-quote-string-literals*, they are not really literals either.\n\n**Semantics**\n\nA string literal is a sequence of zero or more characters delimited in\nsome fashion. The delimiters are not part of the literal's content.\n\nThe type of a string literal is `string`.\n\n###### Single-Quoted String Literals\n\n**Syntax**\n\n<pre>\n  <i>single-quoted-string-literal::</i>\n    ' <i>sq-char-sequence<sub>opt</sub></i>  '\n\n  <i>sq-char-sequence::</i>\n    <i>sq-char</i>\n    <i>sq-char-sequence   sq-char</i>\n\n  <i>sq-char::</i>\n    <i>sq-escape-sequence</i>\n    \\<i><sub>opt</sub></i>   any member of the source character set except single-quote (') or backslash (\\)\n\n  <i>sq-escape-sequence:: one of</i>\n    \\'  \\\\\n</pre>\n\n**Semantics**\n\nA single-quoted string literal is a string literal delimited by\nsingle-quotes ('). The literal can contain any source character except\nsingle-quote (') and backslash (\\\\), which can only be represented by\ntheir corresponding escape sequence.\n\nA single-quoted string literal is a [c-constant](06-constants.md#general).\n\n**Examples**\n\n```Hack\n'This text is taken verbatim'\n\n'Can embed a single quote (\\') and a backslash (\\\\) like this'\n```\n\n###### Double-Quoted String Literals\n\n**Syntax**\n\n<pre>\n  <i>double-quoted-string-literal::</i>\n    \" <i>dq-char-sequence<sub>opt</sub></i>  \"\n\n  <i>dq-char-sequence::</i>\n    <i>dq-char</i>\n    <i>dq-char-sequence   dq-char</i>\n\n  <i>dq-char::</i>\n    <i>dq-escape-sequence</i>\n    any member of the source character set except double-quote (\") or backslash (\\)\n    \\  any member of the source character set except \"\\$efnrtvxX or octal-digit\n\n  <i>dq-escape-sequence::</i>\n    <i>dq-simple-escape-sequence</i>\n    <i>dq-octal-escape-sequence</i>\n    <i>dq-hexadecimal-escape-sequence</i>\n    <i>dq-unicode-escape-sequence</i>\n\n  <i>dq-simple-escape-sequence:: one of</i>\n    \\\"   \\\\   \\$   \\e   \\f   \\n   \\r   \\t   \\v\n\n  <i>dq-octal-escape-sequence::</i>\n    \\   <i>octal-digit</i>\n    \\   <i>octal-digit   octal-digit</i>\n    \\   <i>octal-digit   octal-digit   octal-digit</i>\n\n  <i>dq-hexadecimal-escape-sequence::</i>\n    \\x  <i>hexadecimal-digit   hexadecimal-digit<sub>opt</sub></i>\n    \\X  <i>hexadecimal-digit   hexadecimal-digit<sub>opt</sub></i>\n\n  <i>dq-unicode-escape-sequence::</i>\n    \\u{  codepoint-digits  }\n\n  <i>codepoint-digits::</i>\n     <i>hexadecimal-digit</i>\n     <i>hexadecimal-digit   codepoint-digits</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*hexadecimal-digit*](09-lexical-structure.md#integer-literals)\n* [*octal-digit*](09-lexical-structure.md#integer-literals)\n\n**Semantics**\n\nA double-quoted string literal is a string literal delimited by\ndouble-quotes (\"). The literal can contain any source character except\ndouble-quote (\") and backslash (\\\\), which can only be represented by\ntheir corresponding escape sequence. Certain other (and sometimes\nnon-printable) characters can also be expressed as escape sequences.\n\nAn escape sequence represents a single-character encoding, as described\nin the table below:\n\nEscape sequence | Character name | Unicode character\n--------------- | --------------| ------\n\\$  | Dollar sign | U+0024\n\\\"  | Double quote | U+0022\n\\\\  | Backslash | U+005C\n\\e  | Escape | U+001B\n\\f  | Form feed | U+000C\n\\n  | New line | U+000A\n\\r  | Carriage Return | U+000D\n\\t  | Horizontal Tab | U+0009\n\\v  | Vertical Tab | U+000B\n\\ooo |  1–3-digit octal digit value ooo |\n\\xhh or \\Xhh  | 1–2-digit hexadecimal digit value hh | U+00hh\n\\u{xxxxxx} | UTF-8 encoding of Unicode codepoint U+xxxxxx | U+xxxxxx\n\nWithin a double-quoted string literal, except when recognized as the\nstart of an escape sequence, a backslash (\\\\) is retained verbatim.\n\nWithin a double-quoted string literal a dollar ($) character not\nescaped by a backslash (\\\\) is handled using a variable substitution rules\ndescribed below.\n\nThe `\\u{xxxxxx}` escape sequence produces the UTF-8 encoding of the Unicode\ncodepoint with the hexadecimal number specified within the curly braces.\nImplementations MUST NOT allow Unicode codepoints beyond U+10FFFF as this is\noutside the range UTF-8 can encode (see\n[RFC 3629](http://tools.ietf.org/html/rfc3629#section-3)). If a codepoint\nlarger than U+10FFFF is specified, implementations MUST error.\nImplementations MUST pass through `\\u` verbatim and not interpret it as an\nescape sequence if it is not followed by an opening `{`, but if it is,\nimplementations MUST produce an error if there is no terminating `}` or the\ncontents are not a valid codepoint. Implementations MUST support leading zeroes,\nbut MUST NOT support leading or trailing whitespace for the codepoint between\nthe opening and terminating braces. Implementations MUST allow Unicode\ncodepoints that are not Unicode scalar values, such as high and low surrogates.\n\nA Unicode escape sequence cannot be created by variable substitution. For example, given `$v = \"41\"`,\n`\"\\u{$v}\"` results in `\"\\u41\"`, a string of length 4, while `\"\\u{0$v}\"` and `\"\\u{{$v}}\"` contain\nill-formed Unicode escape sequences.\n\n**Variable substitution**\n\nThe variable substitution accepts the following syntax:\n\n<pre>\n    <i>string-variable::</i>\n        <i>variable-name</i>   <i>offset-or-property<sub>opt</sub></i>\n\n    <i>offset-or-property::</i>\n        <i>offset-in-string</i>\n        <i>property-in-string</i>\n\n    <i>offset-in-string::</i>\n        [   <i>name</i>   ]\n        [   <i>variable-name</i>   ]\n        [   <i>integer-literal</i>   ]\n\n    <i>property-in-string::</i>\n        ->   <i>name</i>\n\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#general-6)\n* [*integer-literal*](#integer-literals)\n* [*name*](#names)\n* [*variable-name*](#names)\n\nAfter the variable defined by the syntax above is evaluated, its value is converted\nto string according to the rules of [string conversion](08-conversions.md#converting-to-string-type)\nand is substituted into the string in place of the variable substitution expression.\n\nSubscript or property access defined by *offset-in-string* and *property-in-string*\nis resolved according to the rules of the [subscript operator](10-expressions.md#subscript-operator)\nand [member selection operator](10-expressions.md#member-selection-operator) respectively.\nThe exception is that *name* inside *offset-in-string* is interpreted as a string literal even if it is not\nquoted.\n\nIf the character sequence following the `$` does not parse as *name* then the `$` character\nis instead interpreted verbatim and no variable substitution is performed.\n\nA double-quoted string literal is a [c-constant](06-constants.md#general) if it does not\ncontain any variable substitution.\n\n**Examples**\n\n```Hack\n$x = 123;\necho \">\\$x.$x\".\"<\"; // → >$x.123<\n// -----------------------------------------\n$colors = array(\"red\", \"white\", \"blue\");\n$index = 2;\necho \"\\$colors[$index] contains >$colors[$index]<\\n\";\n  // → $colors[2] contains >blue<\n// -----------------------------------------\nclass C {\n    public $p1 = 2;\n}\n$myC = new C();\necho \"\\$myC->p1 = >$myC->p1<\\n\";  // → $myC->p1 = >2<\n```\n\n###### Heredoc String Literals\n\n**Syntax**\n\n<pre>\n  <i>heredoc-string-literal::</i>\n    &lt;&lt;&lt;  <i>hd-start-identifier   new-line   hd-char-sequence<sub>opt</sub>  new-line hd-end-identifier</i>  ;<i><sub>opt</sub>   new-line</i>\n\n  <i>hd-start-identifier::</i>\n    <i>name</i>\n\n  <i>hd-end-identifier::</i>\n    <i>name</i>\n\n  <i>hd-char-sequence::</i>\n    <i>hd-char</i>\n    <i>hd-char-sequence   hd-char</i>\n\n  <i>hd-char::</i>\n    <i>hd-escape-sequence</i>\n    any member of the source character set except backslash (\\)\n    \\  any member of the source character set except \\$efnrtvxX or\noctal-digit\n\n  <i>hd-escape-sequence::</i>\n    <i>hd-simple-escape-sequence</i>\n    <i>dq-octal-escape-sequence</i>\n    <i>dq-hexadecimal-escape-sequence</i>\n    <i>dq-unicode-escape-sequence</i>\n\n  <i>hd-simple-escape-sequence:: one of</i>\n    \\\\   \\$   \\e   \\f   \\n   \\r   \\t   \\v\n</pre>\n\n**Defined elsewhere**\n\n* [*dq-hexadecimal-escape-sequence*](09-lexical-structure.md#double-quoted-string-literals)\n* [*dq-octal-escape-sequence*](09-lexical-structure.md#double-quoted-string-literals)\n* [*dq-unicode-escape-sequence*](09-lexical-structure.md#double-quoted-string-literals)\n* [*name*](09-lexical-structure.md#names)\n* [*new-line*](09-lexical-structure.md#comments)\n\n**Constraints**\n\nThe start and end identifier must be the same. Only horizontal white\nspace is permitted between `<<<` and the start identifier. No white\nspace is permitted between the start identifier and the new-line that\nfollows. No white space is permitted between the new-line and the end\nidentifier that follows. Except for an optional semicolon (`;`), no\ncharacters—not even comments or white space—are permitted between the\nend identifier and the new-line that terminates that source line.\n\n**Semantics**\n\nA heredoc string literal is a string literal delimited by\n\"`<<< name`\" and \"`name`\". The literal can contain any source\ncharacter. Certain other (and sometimes non-printable) characters can\nalso be expressed as escape sequences.\n\nA heredoc literal supports variable substitution as defined for\n[double-quoted string literals](09-lexical-structure.md#double-quoted-string-literals).\n\nA heredoc string literal is a [c-constant](06-constants.md#general) if it does not contain\nany variable substitution.\n\n**Examples**\n\n```Hack\n$v = 123;\n$s = <<<    ID\nS'o'me \"\\\"t e\\txt; \\$v = $v\"\nSome more text\nID;\necho \">$s<\";\n→ >S'o'me \"\\\"t e  xt; $v = 123\"\nSome more text<\n```\n\n###### Nowdoc String Literals\n\n**Syntax**\n\n<pre>\n  <i>nowdoc-string-literal::</i>\n    &lt;&lt;&lt;  '  <i>hd-start-identifier</i>  '  <i>new-line  hd-char-sequence<sub>opt</sub>   new-line hd-end-identifier</i>  ;<i><sub>opt</sub>   new-line</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*hd-char-sequence*](09-lexical-structure.md#heredoc-string-literals)\n* [*hd-end-identifier*](09-lexical-structure.md#heredoc-string-literals)\n* [*hd-start-identifier*](09-lexical-structure.md#heredoc-string-literals)\n* [*new-line*](09-lexical-structure.md#comments)\n\n**Constraints**\n\nNo white space is permitted between the start identifier and its\nenclosing single quotes ('). See also [§§](09-lexical-structure.md#heredoc-string-literals).\n\n**Semantics**\n\nA nowdoc string literal looks like a [heredoc string literal](09-lexical-structure.md#heredoc-string-literals) except that in the former the start identifier name is\nenclosed in single quotes ('). The two forms of string literal have the\nsame semantics and constraints except that a nowdoc string literal is\nnot subject to variable substitution.\n\nA nowdoc string literal is a [c-constant](06-constants.md#general).\n\n**Examples**\n\n```Hack\n$v = 123;\n$s = <<<    'ID'\nS'o'me \"\\\"t e\\txt; \\$v = $v\"\nSome more text\nID;\necho \">$s<\\n\\n\";\n→ >S'o'me \"\\\"t e\\txt; \\$v = $v\"\nSome more text<\n```\n\n##### The Null Literal\n\n<pre>\n  <i>null-literal::</i>\n    null\n</pre>\n\n**Semantics**\n\nThere is one null-literal value, `null`.\n\nA *null-literal* has the null type.\n\n#### Operators and Punctuators\n\n**Syntax**\n\n<pre>\n  <i>operator-or-punctuator:: one of</i>\n    [   ]    (   )   {    }   .   ->   ++   --   **   *   +   -   ~   !\n    $   /   %   &lt;&lt;   >>   &lt;   >   &lt;=   >=   ==   ===   !=   !==   ^   |\n    &amp;   &amp;&amp;   ||   ?   ??   :   ; =   **=   *=   /=   %=   +=   -=   .=   &lt;&lt;=\n    >>=   &amp;=   ^=   |=   ,   @   ::   =>   ==>   ?->   \\   ...    |>   $$\n</pre>\n\n**Semantics**\n\nOperators and punctuators are symbols that have independent syntactic\nand semantic significance. *Operators* are used in expressions to\ndescribe operations involving one or more *operands*, and that yield a\nresulting value, produce a side effect, or some combination thereof.\n*Punctuators* are used for grouping and separating.\n"
  },
  {
    "path": "spec/10-expressions.md",
    "content": "# Expressions\n\n## General\n\nAn *expression* involves one or more terms and zero or more operators.\n\nA *full expression* is an expression that is not part of another\nexpression.\n\nA *value side effect* is an action that changes the state of the execution\nenvironment. (Examples of such actions are modifying a variable, writing\nto a device or file, or calling a function that performs such\noperations.) Throughout this specification, this term is shortened to\n*side effect*, which should not be confused with [*type side effect*](05-types.md#type-side-effects).\n\nWhen an expression is evaluated, it produces a result. It might also\nproduce a side effect. Only a few operators produce side effects. (For\nexample, given the [expression statement](11-statements.md#expression-statements) `$v = 10`; the\nexpression 10 is evaluated to the result 10, and there is no side\neffect. Then the assignment operator is executed, which results in the\nside effect of `$v` being modified. The result of the whole expression is\nthe value of `$v` after the assignment has taken place. However, that\nresult is never used. Similarly, given the expression statement `++$v`;\nthe expression is evaluated to the result incremented-value-of-`$v`, and\nthe side effect is that `$v` is actually incremented. Again, the result\nis never used.)\n\nThe occurrence of value computation and side effects is delimited by\n*sequence points*, places in a program's execution at which all the\ncomputations and side effects previously promised are complete, and no\ncomputations or side effects of future operations have yet begun. There\nis a sequence point at the end of each full expression. The [logical and](10-expressions.md#logical-and-operator), [logical or](10-expressions.md#logical-inclusive-or-operator), [conditional](10-expressions.md#conditional-operator), and [function-call](#function-call-operator) operators each contain a sequence point. (For example, in the\nfollowing series of expression statements, `$a = 10; ++$a; $b = $a;`,\nthere is sequence point at the end of each full expression, so the\nassignment to $a is completed before `$a` is incremented, and the\nincrement is completed before the assignment to `$b`.)\n\nWhen an expression contains multiple operators, the *precedence* of\nthose operators controls the order in which those operators are applied.\n(For example, the expression `$a - $b / $c` is evaluated as\n`$a - ($b / $c)` because the / operator has higher precedence than the\nbinary - operator.) The precedence of an operator is defined by the\ndefinition of its associated grammar production.\n\nIf an operand occurs between two operators having the same precedence,\nthe order in which the operations are performed is defined by those\noperators' *associativity*. With *left-associative* operators,\noperations are performed left-to-right. (For example, `$a + $b - $c` is\nevaluated as `($a + $b) - $c.`) With *right-associative* operators,\noperations are performed right-to-left. (For example, `$a = $b = $c` is\nevaluated as `$a = ($b = $c)`.)\n\nPrecedence and associativity can be controlled using *grouping\nparentheses*. (For example, in the expression `($a - $b) / $c`, the\nsubtraction is done before the division. Without the grouping\nparentheses, the division would take place first.)\n\nWhile precedence, associativity, and grouping parentheses control the\norder in which operators are applied, they do *not* control the order of\nevaluation of the terms themselves. Unless stated explicitly in this\nspecification, the order in which the operands in an expression are\nevaluated relative to each other is unspecified. See the discussion\nabove about the operators that contain sequence points. (For example, in\nthe full expression `$list1[$i] = $list2[$i++]`, whether the value\nof `$i` on the left-hand side is the old or new `$i`, is unspecified.\nSimilarly, in the full expression `$j = $i + $i++`, whether the value\nof `$i` is the old or new `$i`, is unspecified. Finally, in the full\nexpression `f() + g() * h()`, the order in which the three functions are\ncalled, is unspecified.)\n\n**Implementation Notes**\n\nAn expression that contains no side effects and whose resulting value is\nnot used need not be evaluated. For example, the expression statements\n`6;, $i + 6;`, and `$i/$j`; are well formed, but they contain no side\neffects and their results are not used.\n\nA side effect need not be executed if it can be defined that no other\nprogram code relies on its having happened. (For example, in the cases\nof return `$a++`; and return `++$a`;, it is obvious what value must be\nreturned in each case, but if `$a` is a variable local to the enclosing\nfunction, `$a` need not actually be incremented.\n\n## Restrictions on Arithmetic Operations\n\nNo arithmetic operation can be performed on the value `null` or on a value of\ntype `bool`, `string` (not even if the string is numeric), or any nullable type (including nullable arithmetic types).\n\n## Operations on Operands Having One or More Subtypes\n\nNone of the subclauses in this Expressions clause discuss the use of operands\nof supertypes such as `num`, `arraykey`, or `?int`. Refer to [§§](05-types.md#type-side-effects) for a discussion of type side effects.\n\n## Primary Expressions\n\n### General\n\n**Syntax**\n\n<pre>\n  <i>primary-expression:</i>\n    <i>variable-name</i>\n    <i>qualified-name</i>\n    <i>literal</i>\n    <i>const-expression</i>\n    <i>intrinsic</i>\n    <i>collection-literal</i>\n    <i>tuple-literal</i>\n    <i>shape-literal</i>\n    <i>anonymous-function-creation-expression</i>\n    <i>awaitable-creation-expression</i>\n    (  <i>expression</i>  )\n    $this\n    $$\n</pre>\n\n**Defined elsewhere**\n\n* [*anonymous-function-creation-expression*](10-expressions.md#anonymous-function-creation)\n* [*awaitable-creation-expression*](10-expressions.md#async-blocks)\n* [*collection-literal*](10-expressions.md#collection-literals)\n* [*const-expression*](10-expressions.md#constant-expressions)\n* [*expression*](10-expressions.md#yield-operator)\n* [*intrinsic*](10-expressions.md#general-2)\n* [*literal*](09-lexical-structure.md#general-2)\n* [*qualified-name*](20-namespaces.md#defining-namespaces)\n* [*shape-literal*](10-expressions.md#shape-literals)\n* [*tuple-literal*](10-expressions.md#tuple-literals)\n* [*variable-name*](09-lexical-structure.md#names)\n\n**Semantics**\n\nThe type and value of a parenthesized expression are identical to those of\nthe un-parenthesized expression.\n\nThe variable `$this` is predefined inside any instance method,\nconstructor, or destructor when that method is called from within an object\ncontext. `$this` is a [handle](05-types.md#general) that points to the calling\nobject or to the object being constructed. The type of `$this` is\n[`this`](05-types.md#the-this-type). `$this` is a non-modifiable lvalue.\n\nThe *pipe variable* `$$` is predefined only within the\n*coalesce-expression* of a\n[*piped-expression*](10-expressions.md#pipe-operator). The type and value of\n`$$` is the type and value of that *coalesce-expression*. `$$` is a\nnon-modifiable lvalue.\n\n### Intrinsics\n\n#### General\n\n**Syntax**\n<pre>\n  <i>intrinsic:</i>\n    <i>array-intrinsic</i>\n    <i>echo-intrinsic</i>\n    <i>exit-intrinsic</i>\n    <i>invariant-intrinsic</i>\n    <i>list-intrinsic</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*array-intrinsic*](10-expressions.md#array)\n* [*echo-intrinsic*](10-expressions.md#echo)\n* [*exit-intrinsic*](10-expressions.md#exit)\n* [*invariant-intrinsic*](10-expressions.md#invariant)\n* [*list-intrinsic*](10-expressions.md#list)\n\n**Semantics**\n\nThe names in this series of subclauses are reserved and are\ncalled *intrinsics*. These names are not keywords; nor are they functions.\n\nNote: The initial Hack execution environment was built on top of that for PHP,\nwhich has an intrinsic called `empty`. And even though an intrinsic by that\nname is not supported by Hack strict mode, the case-indistinct name `empty` is\nreserved in Hack as well.\n\n#### array\n\n**Syntax**\n\n<pre>\n  <i>array-intrinsic:</i>\n    array ( <i>array-initializer<sub>opt</sub></i>  )\n</pre>\n\n**Defined elsewhere**\n\n* [*array-initializer*](10-expressions.md#array-creation-operator)\n\n**Semantics**\n\nThis intrinsic creates and initializes an array. It is equivalent to the\n[array-creation operator `[]`](10-expressions.md#array-creation-operator).\n\n#### echo\n\n**Syntax**\n\n<pre>\n  <i>echo-intrinsic:</i>\n    echo  <i>expression</i>\n    echo  (  <i>expression</i>  )\n    echo  <i>expression-list-two-or-more</i>\n\n  <i>expression-list-two-or-more:</i>\n    <i>expression</i>  ,  <i>expression</i>\n    <i>expression-list-two-or-more</i>  ,  <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Constraints**\n\n*expression* must not designate an array nor an instance of a type not\nhaving a [`__toString` method](16-classes.md#method-__tostring).\n\n**Semantics**\n\nAfter converting each of its *expression*s' values to strings, if\nnecessary, `echo` concatenates them in lexical order, and writes the\nresulting string to [`STDOUT`](05-types.md#resource-types).\n\nFor value substitution in string literals, see [§§](09-lexical-structure.md#double-quoted-string-literals) and\n[§§](09-lexical-structure.md#heredoc-string-literals). For conversion to string, see [§§](08-conversions.md#converting-to-string-type).\n\n**Examples**\n\n```Hack\n$v1 = true;\n$v2 = 123;\necho  '>>' . $v1 . '|' . $v2 . \"<<\\n\";    // outputs \">>1|123<<\"\necho  '>>' , $v1 , '|' , $v2 , \"<<\\n\";    // outputs \">>1|123<<\"\necho ('>>' . $v1 . '|' . $v2 . \"<<\\n\");   // outputs \">>1|123<<\"\n$v3 = \"qqq{$v2}zzz\";\necho \"$v3\\n\";\n```\n\n#### exit\n\n**Syntax**\n\n<pre>\n  <i>exit-intrinsic:</i>\n    exit  <i>expression<sub>opt</sub></i>\n    exit  (  <i>expression<sub>opt</sub></i>  )\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Constraints**\n\nWhen *expression* designates an integer, its value must be in the range\n0–254.\n\n**Semantics**\n\nThis intrinsic terminates the current script. If *expression* designates\na string, that string is written to [`STDOUT`](05-types.md#resource-types). If *expression*\ndesignates an integer, that represents the script's *exit status code*.\nCode 255 is reserved by Hack. Code 0 represents \"success\". The exit\nstatus code is made available to the execution environment. If\n*expression* is omitted or is a string, the exit status code is zero.\n`exit` does not have a resulting value.\n\n`exit` performs the following operations, in order:\n\n-   Writes the optional string to `STDOUT`.\n-   Calls any functions registered via the library function\n    [`register_shutdown_function`](http://www.php.net/register_shutdown_function) in their order of registration.\n-   Invokes [destructors](16-classes.md#destructors) for all remaining instances.\n\n**Examples**\n\n```Hack\nexit (\"Closing down\");\nexit (1);\nexit;\n```\n\n#### invariant\n\n**Syntax**\n\n<pre>\n  <i>invariant-intrinsic:</i>\n    invariant  (  <i>condition</i>  ,  <i>format</i>  )\n    invariant  (  <i>condition</i>  ,  <i>format</i>  ,  <i>values</i>  )\n</pre>\n\n**Constraints**\n\n*condition* can be any expression allowed as the operand of the [`!` operator](10-expressions.md#unary-arithmetic-operators). *format* is a string that can contain text and/or optional\nformatting information as understood by the library function [`sprintf`](http://www.php.net/sprintf).\nThe optional comma-separated list of values designated by *values* must match\nthe set of types expected by the optional formatting information inside\n*format*.\n\n\n**Semantics**\n\nIf *condition* tests true, the program continues execution; otherwise, the\nlibrary function [`invariant_violation`](http://www.php.net/invariant_violation) is called. That function does not\nreturn; instead, it either throws an exception of type\n`\\HH\\InvariantException`, or calls the handler previously registered by the\nlibrary function [`invariant_callback_register`](http://www.php.net/invariant_callback_register).\n\nThis intrinsic behaves like a function with a `void` return type. It is\nintended to indicate a programmer error for a condition that should never\noccur.\n\n**Examples**\n\n```Hack\ninvariant($interf instanceof B, \"Object must have type B\");\n// -----------------------------------------\ninvariant(!is_null($p), \"Value can't be null\");\n// -----------------------------------------\n$max = 100;\ninvariant(!is_null($p) && $p <= $max, \"Value %d must be <= %d\", $p, $max);\n```\n\n#### list\n\n**Syntax**\n\n<pre>\n  <i>list-intrinsic:</i>\n    list  (  <i>list-expression-list<sub>opt</sub></i>  )\n\n  <i>list-expression-list:</i>\n    <i>expression</i>\n    ,\n    <i>list-expression-list</i>  ,  <i>expression<sub>opt</sub></i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Constraints**\n\n*list-intrinsic* must be used as the left-hand operand in a\n[*simple-assignment-expression*](10-expressions.md#simple-assignment) of which the right-hand\noperand must be an expression that designates a vector-like array or an instance of the class types `Vector`, `ImmVector`, or `Pair` (the\n\"source\").\n\nEach *expression* in *list-expression-list* must designate a\nvariable (the \"target variable\").\n\nThere must not be fewer element candidates in the source than there are target\nvariables.\n\nOnly the right-most *list-or-variable* can be omitted.\n\n\n**Semantics**\n\nThis intrinsic assigns zero or more elements of the source to the\ntarget variables. On success, it returns a copy of the source.\n\nWhen the source is a vector-like array, the element having an `int` key of 0 is assigned to the first target\nvariable, the element having an `int` key of 1 is assigned to the second\ntarget variable, and so on, until all target variables have been\nassigned. Any elements having an `int` key outside the range 0–(*n*-1),\nwhere *n* is the number of target variables, are ignored.\n\nIf ([`$_`](09-lexical-structure.md#names) is used as a target variable, the value of the corresponding source element is ignored; no assignment takes place. Multiple target variables in the same list-expression-list may be `$_`.\n\nWhen the source is an instance of the classes `Vector`, `ImmVector`, or `Pair`, the\nelements in the source are assigned to the target variables in lexical order,\nuntil all target variables have been assigned.\n\nIf the source elements and the target variables overlap in any\nway, the behavior is unspecified.\n\n**Examples**\n\n```Hack\n// $min, $max, and $avg must be defined at this point\nlist($min, $max, $avg) = array(0, 100, 67);\n  // $min is 0, $max is 100, $avg is 67\n$a = array();\n$v = list($a[0], $a[2], $a[4]) = array(50, 5100, 567);\n  // $a[0] is 50, $a[2] is 5100, $a[4] is 567\nlist($min, $max, ) = array(10, 1100, 167);\n  // $min is 10, $max is 1100\n$v = Vector {1, 2, 3};\nlist($_, $b, $_) = $v; // $b is assigned 2; 1 and 3 are ignored\n```\n\n### Collection Literals\n\nNote: The term *literal* as used here is a misnomer; *cl-element-keys* and\n*cl-element-values* need not be compile-time constants.\n\n**Syntax**\n<pre>\n<i>collection-literal:</i>\n  <i>non-key-collection-class-type</i>  {  <i>cl-initializer-list-without-keys<sub>opt</sub></i>  }\n  <i>key-collection-class-type</i>  {  <i>cl-initializer-list-with-keys<sub>opt</sub></i>  }\n  <i>pair-type</i>  {  <i>cl-element-value</i>  ,  <i>cl-element-value</i>  }\n<i>non-key-collection-class-type:</i>\n  <i>qualified-name</i>\n<i>key-collection-class-type:</i>\n  <i>qualified-name</i>\n<i>pair-type:</i>\n  <i>qualified-name</i>\n<i>cl-initializer-list-without-keys:</i>\n  <i>cl-element-value</i>\n  <i>cl-initializer-list-without-keys</i>  ,  <i>cl-element-value</i>\n<i>cl-initializer-list-with-keys:</i>\n  <i>cl-element-key</i>  =>  <i>cl-element-value</i>\n  <i>cl-initializer-list-with-keys</i>  ,  <i>cl-element-key</i>  =>  <i>cl-element-value</i>\n<i>cl-element-key:</i>\n  <i>expression</i>\n<i>cl-element-value:</i>\n  <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Constraints**\n\nFor *key-collection-class-type*, *qualified-name* must designate the library\ntype `Map` or `ImmMap`, and in both cases, each *cl-element-key* must have\ntype `int` or `string`.\n\nFor *key-collection-class-type*, *qualified-name* must designate the library\ntype `Vector`, `ImmVector`, `Set`, or `ImmSet`, and in all such cases, each\n*cl-element-value* must have type `int` or `string`.\n\nFor *pair-type*, *qualified-name* must designate the library type `Pair`.\n\n**Semantics**\n\nFor *non-key-collection-class-types* `Vector` and `ImmVector`, an instance of\nthe corresponding class is created with elements having values as specified by\n*cl-initializer-list-without-keys*, inserted in that order, and assigned\nconsecutive keys starting at zero. If *cl-initializer-list-without-keys* is\nomitted, the resulting vector is empty.\n\nFor *non-key-collection-class-types* `Map` and `ImmMap`, an instance of the\ncorresponding class is created with elements having keys and values as\nspecified by *cl-initializer-list-with-keys*, inserted in that order. If\n*cl-initializer-list-with-keys* is omitted, the resulting map is empty. If two\nor more *cl-element-keys* in a *cl-initializer-list-with-keys* contain the\nsame key, the lexically right-most one is the one whose *cl-element-value* is\nused to initialize the element designated by that key.\n\nFor *non-key-collection-class-types* `Set` and `ImmSet`, an instance of the\ncorresponding class is created with elements having values as specified by\n*cl-initializer-list-without-keys*, inserted in that order. If\n*cl-initializer-list-without-keys* is omitted, the resulting set is empty.\nDuplicate *cl-element-values* are ignored.\n\nFor type `Pair`, an instance of that class is created with element 0 having\nthe value of the left-hand *cl-element-value*, and element 1 having the value\nof the right-hand *cl-element-value*.\n\n**Examples**\n\n```Hack\nVector {22, 33}                                 // size 2; 22, 33\n(Vector {})->addAll(array(3, 6, 9))             // size 0 then size 3; 3, 6, 9\nImmVector {5, $x, 15}                           // size 3; 5, ?, 15\nMap {'x' => -1, 'a' => -4, 'x' => 5, 'a' => 12} // size 2; 'x'/5, 'a'/12\nImmSet {1, 1, 1, 5, 10, 1, 'red', 1}            // size 4; 1, 5, 10, 'red'\nPair {55, new C()}\n```\n\n### Tuple Literals\n\nNote: The term *literal* as used here is a misnomer; the *expression*s in\n*expression-list* need not be compile-time constants.\n\n**Syntax**\n\n<pre>\n<i>tuple-literal:</i>\n  tuple  (  <i>expression-list-one-or-more</i>  )\n<i>expression-list-one-or-more:</i>\n  <i>expression</i>\n  <i>expression-list-one-or-more</i>  ,  <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Semantics**\n\nA *tuple-literal* creates a [tuple](05-types.md#tuple-types) with elements having values as\nspecified by *expression-list-one-or-more*, inserted in that order.\n\nThe type of a *tuple-literal* is \"tuple of type\n<*element type list in lexical order*>\".\n\nNote: Although a tuple of only one element can be created using a tuple\nliteral, a [*tuple-type-specifier*](05-types.md#tuple-types) must contain at least two elements.\n\n**Examples**\n\n```Hack\nreturn tuple(true, array(99, 88, 77), 10.5);\n$t1 = tuple(10, true, 2.3, 'abc', null, $p1, Vector {$p2 + 3, 12}, new C());\n$t2 = tuple(100, tuple('abc', false));\n```\n\n### Shape Literals\n\nNote: The term *literal* as used here is a misnomer; the *expression*s\nin *field-initializer* need not be compile-time constants.\n\n**Syntax**\n<pre>\n  <i>shape-literal:</i>\n    <i>shape  (  <i>field-initializer-list<sub>opt</sub></i>  )</i>\n  <i>field-initializer-list:</i>\n    <i>field-initializers</i>  ,<sub>opt</sub>\n  <i>field-initializers</i>:\n    <i>field-initializer</i>\n    <i>field-initializers</i>  ,  <i>field-initializer</i>\n  <i>field-initializer:</i>\n    <i>single-quoted-string-literal</i>  =>  <i>expression</i>\n    <i>integer-literal</i>  =>  <i>expression</i>\n    <i>qualified-name</i>  =>  <i>expression</i>\n    <i>scope-resolution-expression</i>  =>  <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n* [*integer-literal*](09-lexical-structure.md#integer-literals)\n* [*qualified-name*](20-namespaces.md#defining-namespaces)\n* [*scope-resolution-expression*](10-expressions.md#scope-resolution-operator)\n* [*single-quoted-string-literal*](09-lexical-structure.md#single-quoted-string-literals)\n\n**Constraints**\n\nEach string in the set of strings designated by all the\n*single-quoted-string-literals*, *qualified-names* and *scope-resolution-expressions* in a\n*field-initializer-list* must have a distinct value, and each string must\nmatch exactly a field name in the shape type's [*shape-specifier*](05-types.md#shape-types).\n\nEach integer in the set of *integer-literals*, *qualified-names* and *scope-resolution-expressions* in a\n*field-initializer-list* must have a distinct value, and each integer must\nmatch exactly a field name in the shape type's *shape-specifier*.\n\nThe number of *field-initializers* must match exactly the number of\n*field-specifiers* in the shape type's *shape-specifier*.\n\nThe type of *expression* in a *field-initializer* must be a subtype of the\ncorresponding field type in the shape type's *shape-specifier*.\n\n**Semantics**\n\nA *shape-literal* creates a [shape](05-types.md#shape-types) with fields having values as specified by *field-initializer-list*. The order of the\n*field-initializers* need not be the same as the order of the\n*field-specifiers* in the shape type's *shape-specifier*.\n\n**Examples**\n\n```Hack\nshape()\nshape('x' => $prevX, 'y' => getY())\nshape('id' => null, 'url' => null, 'count' => 0)\n```\n\n### Anonymous Function-Creation\n\n**Syntax**\n\n<pre>\n<i>anonymous-function-creation-expression:</i>\n  async<sub>opt</sub>  function  (  <i>anonymous-function-parameter-list<sub>opt<sub></i>  )  <i>anonymous-function-return<sub>opt</sub></i>  <i>anonymous-function-use-clause<sub>opt</sub></i>  <i>compound-statement</i>\n\n<i>anonymous-function-parameter-list:</i>\n  ...\n  <i>anonymous-function-parameter-declaration-list</i>\n  <i>anonymous-function-parameter-declaration-list</i>  ,\n  <i>anonymous-function-parameter-declaration-list</i>  ,  ...\n\n<i>anonymous-function-parameter-declaration-list:</i>\n  <i>anonymous-function-parameter-declaration</i>\n  <i>anonymous-function-parameter-declaration-list  </i>  ,  <i>anonymous-function-parameter-declaration</i>\n\n<i>anonymous-function-parameter-declaration:</i>\n  <i>attribute-specification<sub>opt</sub>  type-specifier<sub>opt</sub> variable-name  default-argument-specifier<sub>opt</sub></i>\n\n<i>anonymous-function-return:</i>\n  : <i>return-type</i>\n\n<i>anonymous-function-use-clause:</i>\n  use  (  <i>use-variable-name-list</i>  ,<sub>opt</sub> )\n\n<i>use-variable-name-list:</i>\n  <i>variable-name</i>\n  <i>use-variable-name-list</i>  ,  <i>variable-name</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*attribute-specification*](20-namespaces.md#name-lookup)\n* [*compound-statement*](11-statements.md#compound-statements)\n* [*default-argument-specifier*](15-functions.md#function-definitions)\n* [*return-type*](15-functions.md#function-definitions)\n* [*type-specifier*](05-types.md#general)\n* [*variable-name*](09-lexical-structure.md#names)\n\n**Constraints**\n\nEach *variable-name* in an *anonymous-function-parameter-declaration-list* must be distinct.\n\nIf any *anonymous-function-parameter-declaration* has a\n*default-argument-specifier*, then all subsequent\n*anonymous-function-parameter-declarations* in the same\n*anonymous-function-parameter-declaration-list* must also have a\n*default-argument-specifier*.\n\nIf the *type-specifier* in *anonymous-function-return* is `void`, the\n*compound-statement* must not contain any [`return` statements](11-statements.md#the-return-statement)\nhaving an *expression*. Otherwise, all `return` statements must contain an\n*expression* whose type is a subtype of the type indicated by *type-specifier*.\n\nIf `async` is present, *return-type* must be a type that implements\n[`Awaitable<T>`](17-interfaces.md#interface-awaitable).\n\n**Semantics**\n\nThis operator returns an object that encapsulates the [anonymous function](15-functions.md#anonymous-functions) defined within. An anonymous function is defined like, and behaves\nlike, a [named function](13-functions.md#function-definitions) except\nthat the former has no name and has an optional\n*anonymous-function-use-clause*.\n\nThe *use-variable-name-list* is a list of variables from the enclosing\nscope, which are to be made available by name to the body of the\nanonymous function. The values used for these variables are those at the time the closure object is created, not when it is used to call the function it\nencapsulates.\n\nAn anonymous function defined inside an instance method has access to\nthe variable `$this`.\n\nIf the *type-specifier* for a parameter is omitted, that type is inferred.\n\nIf *anonymous-function-return* is omitted, the return type is inferred.\n\nAn anonymous function can be [asynchronous](15-functions.md#asynchronous-functions).\n\nThe function-return types `this` and `noreturn` are described in ([§§](15-functions.md#function-definitions)).\n\n**Examples**\n\n```Hack\nfunction doit(int $value, (function (int): int) $process): int {\n  return $process($value);\n}\n$result = doit(5, function (int $p): int { return $p * 2; }); // doubles\n$result = doit(5, function (int $p): int { return $p * $p; });  // squares\n// -----------------------------------------\nfunction compute(array<int> $values): void {\n  $count = 5;\n  $callback = function () use ($count)\n  {\n    …\n  };\n  $callback();\n  …\n}\n```\n\n### Async Blocks\n\n**Syntax**\n\n<pre>\n<i>awaitable-creation-expression:</i>\n  async   {   <i>async-statement-list<sub>opt</sub></i>   }\n\n<i>async-statement-list:</i>\n  <i>statement</i>\n  <i>async-statement-list   statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*statement*](11-statements.md#general)\n\n**Constraints**\n\n*awaitable-creation-expression* must not be used as the *lambda-body* in a [*lambda-expression*](10-expressions.md#lambda-expressions).\n\n**Semantics**\n\nThe (possibly) asynchronous operations designated by *async-statement-list* are executed, in order.\n\nAn *awaitable-creation-expression* produces a result of type [`Awaitable<T>`](17-interfaces.md#interface-awaitable), where `T` is the return type of the final statement in *async-statement-list*. If *async-statement-list* is omitted, or its final statement is `return;`, or its final statement is not a `return` statement, the final statement is treated as being `return;`, `T` is `void`, and no value is wrapped into the `Awaitable` object. Otherwise, the final statement has the form `return` *expression*`;`, `T` is the type of *expression*, and the value of *expression* is wrapped into the `Awaitable` object.\n\n**Examples**\n\n```Hack\n$x = await async {\n  $y = await task1();\n  $z = await task2();\n  return $y + $z;\n};\n```\n\n## Postfix Operators\n\n### General\n\n**Syntax**\n\n<pre>\n  <i>postfix-expression:</i>\n    <i>primary-expression</i>\n    <i>clone-expression</i>\n    <i>object-creation-expression</i>\n    <i>array-creation-expression</i>\n    <i>subscript-expression</i>\n    <i>function-call-expression</i>\n    <i>member-selection-expression</i>\n    <i>null-safe-member-selection-expression</i>\n    <i>postfix-increment-expression</i>\n    <i>postfix-decrement-expression</i>\n    <i>scope-resolution-expression</i>\n    <i>exponentiation-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*array-creation-expression*](10-expressions.md#array-creation-operator)\n* [*clone-expression*](10-expressions.md#the-clone-operator)\n* [*exponentiation-expression*](10-expressions.md#exponentiation-operator)\n* [*function-call-expression*](10-expressions.md#function-call-operator)\n* [*member-selection-expression*](10-expressions.md#member-selection-operator)\n* [*null-safe-member-selection-expression*](10-expressions.md#null-safe-member-selection-operator)\n* [*object-creation-expression*](10-expressions.md#the-new-operator)\n* [*postfix-decrement-expression*](10-expressions.md#postfix-increment-and-decrement-operators)\n* [*postfix-increment-expression*](10-expressions.md#postfix-increment-and-decrement-operators)\n* [*primary-expression*](10-expressions.md#general-1)\n* [*scope-resolution-expression*](10-expressions.md#scope-resolution-operator)\n* [*subscript-expression*](10-expressions.md#subscript-operator)\n\n**Semantics**\n\nThese operators associate left-to-right.\n\n### The `clone` Operator\n\n**Syntax**\n\n<pre>\n  <i>clone-expression:</i>\n    clone  <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Constraints**\n\n*expression* must designate an object.\n\n**Semantics**\n\nThe `clone` operator creates a new object that is a [shallow copy](04-basic-concepts.md#cloning-objects) of the object designated by *expression*. Then, if the class type of *expression* has a method called [`__clone`](16-classes.md#method-__clone), that is called to perform a [deep copy](04-basic-concepts.md#cloning-objects). The result is a handle that points to the new object.\n\n**Examples**\n\nConsider a class `Employee`, from which is derived a class `Manager`. Let us\nassume that both classes contain properties that are objects. clone is\nused to make a copy of a Manager object, and behind the scenes, the\n`Manager` object uses clone to copy the properties for the base class,\n`Employee`.\n\n```Hack\nclass Employee\n{\n  ...\n  public function __clone(): void  {\n    // make a deep copy of Employee object\n  }\n}\nclass Manager extends Employee\n{\n  ...\n  public function __clone(): void\n  {\n    $v = parent::__clone();\n    // make a deep copy of Manager object\n\n  }\n}\n$obj1 = new Manager(\"Smith\", 23);\n$obj2 = clone $obj1;  // creates a new Manager that is a deep copy\n```\n\n### The `new` Operator\n\n**Syntax**\n\n<pre>\n  <i>object-creation-expression:</i>\n    new  <i>class-type-designator</i>  (  <i>argument-expression-list<sub>opt</sub></i>  )\n\n  <i>class-type-designator:</i>\n    parent\n    self\n    static\n    <i>member-selection-expression<i>\n    <i>null-safe-member-selection-expression<i>\n    <i>qualified-name</i>\n    <i>scope-resolution-expression</i>\n    <i>subscript-expression<i>\n    <i>variable-name</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*argument-expression-list*](10-expressions.md#function-call-operator)\n* [*member-selection-expression*](10-expressions.md#member-selection-operator)\n* [*null-safe-member-selection-expression*](10-expressions.md#null-safe-member-selection-operator)\n* [*qualified-name*](20-namespaces.md#defining-namespaces)\n* [*scope-resolution-expression*](10-expressions.md#scope-resolution-operator)\n* [*subscript-expression*](10-expressions.md#subscript-operator)\n* [*variable-name*](09-lexical-structure.md#names)\n\n**Constraints**\n\nIf the *class-type-designator* is a *scope-resolution-expression* then it must not have `class` as the right hand side of the `::` operator.\n\nOtherwise, if the *class-type-designator* is a *qualified-name* or *scope-resolution-expression* which resolves a qualified name, or `self`, or `parent`, then it must designate a class.\n\nOtherwise,the *class-type-designator* must be an expression evaluating to a value having the [`classname` type](05-types.md#the-classname-type).  Furthermore, it must designate a class that has the attribute  [`__ConsistentConstruct`](21-attributes.md#attribute-__consistentconstruct), or that has an abstract constructor or a final constructor.\n\nThe *class-type-designator* must not designate an [abstract class](16-classes.md#general).\n\nThe *class-type-designator* must not be a [generic type parameter](14-generic-types-methods-and-functions.md#type-parameters).\n\nThe *object-creation-expression* will invoke the constructor of the class designated by the *class-type-designator*. \n\n*argument-expression-list* must contain an argument for each parameter in the\n[constructor's definition](15-functions.md#function-definitions) not having a default value, and each\nargument's type must be a subtype of the corresponding parameter's type.\n\nIf the constructor is not variadic, the call must not contain more arguments\nthan there are corresponding parameters.\n\n**Semantics**\n\nThe `new` operator allocates memory for an object that is an instance of\nthe class specified by the *class-type-designator*.\n\nThe object is initialized by calling the class's constructor (16.8)\npassing it the optional *argument-expression-list*. If the class has no\nconstructor, the constructor that class inherits (if any) is used.\nOtherwise, each instance property having any nullable type takes on the value\n`null`.\n\nThe result of an *object-creation-expression* is a handle to an object\nof the type specified by the *class-type-designator*.\n\nFrom within a method, the use of `static` corresponds to the class in the\ninheritance context in which the method is called. The type of the object created by an expression of the form `new static` is [`this`](05-types.md#the-this-type).\n\nBecause a constructor call is a function call, the relevant parts of\n10.5.6 also apply.\n\n**Examples**\n\n```Hack\nclass Point\n{\n  public function __construct(float $x = 0, float $y = 0)\n  {\n    ...\n  }\n  ...\n}\n$p1 = new Point();     // create Point(0, 0)\n$p1 = new Point(12);   // create Point(12, 0)\n// -----------------------------------------\nclass C { ... }\nfunction f(classname<C> $clsname): void {\n  $w = new $clsname();\n  …\n}\n```\n\n### Array Creation Operator\n\nAn array is created and initialized by one of two equivalent ways: via\nthe array-creation operator `[]`, as described below, or the [intrinsic\n`array`](10-expressions.md#array).\n\n**Syntax**\n\n<pre>\n  <i>array-creation-expression:</i>\n    array  (  <i>array-initializer<sub>opt</sub></i>  )\n    [ <i>array-initializer<sub>opt</sub></i> ]\n\n  <i>array-initializer:</i>\n    <i>array-initializer-list</i>  ,<sub>opt</sub>\n\n  <i>array-initializer-list:</i>\n    <i>array-element-initializer</i>\n    <i>array-element-initializer  ,  array-initializer-list</i>\n\n  <i>array-element-initializer:</i>\n    <i>element-value</i>\n    element-key  =>  <i>element-value</i>\n\n  <i>element-key:</i>\n    <i>expression</i>\n\n  <i>element-value</i>\n    <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Constraints**\n\nIf any *array-element-initializer* in an *array-initializer-list* contains\nan *element-key*, then all *array-element-initializers* in that\n*array-initializer-list* must contain an *element-key*.\n\n**Semantics**\n\nThis operator creates an array. If *array-initializer* contains any\n*element-keys*, the resulting array is a map-like array; otherwise, it is a\nvector-like array. If *array-initializer* is omitted, the array has zero elements, and the resulting array is neither a vector-like nor a map-like\narray, although it is a subtype of both types.. For convenience, an\n*array-initializer* may have a trailing comma; however, this comma has no\npurpose. An *array-initializer-list* consists of a vector-like array. If\n*array-initializer* is omitted, the array has zero elements. For convenience,\nan *array-initializer* may have a trailing comma; however, this comma has no\npurpose. An *array-initializer-list* consists of a comma-separated list of\none or more *array-element-initializer*s, each of which is used to provide an\n*element-value* and an optional *element-key*.\n\nIf the value of *element-key* is neither `int` nor `string`, keys with `float`\nor `bool` values, or strings whose contents match exactly the pattern of\n[*decimal-literal*](09-lexical-structure.md#integer-literals), are [converted to `int`](08-conversions.md#converting-to-integer-type), and values\nof all other key types are [converted to `string`](08-conversions.md#converting-to-string-type).\n\nIf *element-key* is omitted from an *array-element-initializer*, an\nelement key of type `int` is associated with the corresponding\n*element-value*. The key associated is one more than the previously\nassigned `int` key for this array. However, if this is the first element\nwith an `int` key, key zero is associated.\n\nOnce the element keys have been converted to `int` or `string`, if two or more\n*array-element-initializer*s in an *array-initializer* contain the same\nkey, the lexically right-most one is the one whose element-value is used\nto initialize that element.\n\nThe result of this operator is a handle to the set of array elements.\n\n**Examples**\n\n```Hack\n$v = [];      // array has 0 elements\n$v = array(true);   // vector-like array has 1 element, true\n$v = [123, -56];  // vector-like array of two ints, with keys 0 and 1\n$v = [0 => 123, 1 => -56]; // map-like array of two ints, with keys 0 and 1\n$i = 10;\n$v = [$i - 10 => 123, $i - 9 => -56]; // key can be a runtime expression\n$i = 6; $j = 12;\n$v = [7 => 123, 3 => $i, 6 => ++$j];  // keys are in arbitrary order\n$v[4] = 99;   // extends array with a new element\n$v = [2 => 23, 1 => 10, 2 => 46, 1.9 => 6];\n     // map-like array has 2 elements, with keys 2 and 1, values 46 and 6\n$v = [\"red\" => 10, \"4\" => 3, 9.2 => 5, \"12.8\" => 111, null => 1];\n     // map-like array has 5 elements, with keys \"red\", 4, 9, \"12.8\", and \"\".\n$c = array(\"red\", \"white\", \"blue\");\n$v = array(10, $c, null, array(false, null, $c));\n$v = array(2 => true, 0 => 123, 1 => 34.5, -1 => \"red\");\nforeach($v as $e) { … } // iterates over keys 2, 0, 1, -1\nfor ($i = -1; $i <= 2; ++$i) { … $v[$i] } // retrieves via keys -1, 0, 1, 2\n```\n\n### Subscript Operator\n\n**Syntax**\n\n<pre>\n  <i>subscript-expression:</i>\n    <i>postfix-expression</i>  [  <i>expression<sub>opt</sub></i>  ]\n    <i>postfix-expression</i>  {  <i>expression<sub>opt</sub></i>  }   <b>[Deprecated form]</b>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n* [*postfix-expression*](10-expressions.md#general-3)\n\n**Constraints**\n\nIf *postfix-expression* designates a string, *expression* must not\ndesignate a string.\n\n*expression* can be omitted only if *subscript-expression* is used in a\nmodifiable-lvalue context and *postfix-expression* does not designate a\nstring.\n\nIf *subscript-expression* is used in a non-lvalue context, the element\nbeing designated must exist.\n\nWhen *postfix-expression* designates a vector-like array, *expression* must\nhave type `int`.\n\nWhen *postfix-expression* designates a map-like array, elements cannot be appended using empty `[]`.\n\nWhen *postfix-expression* designates a tuple, *expression* must be a constant.\n\nWhen *postfix-expression* designates a shape, *expression* must be a\n[*single-quoted-string-literal*](09-lexical-structure.md#single-quoted-string-literals) that specifies a key in that\nshape's [*shape-specifier*](05-types.md#shape-types).\n\nWhen postfix-expression designates an instance of a collection class:\n\n* The deprecated form, `{ … }`, is not supported.\n* `Vector` or `ImmVector`, *expression* must have type `int`.\n* `Vector`, if *expression* is omitted, *subscript-expression* must be the\nleft-hand side of a [*simple-assignment-expression*](10-expressions.md#simple-assignment).\n* `Map` or `ImmMap`, *expression* must have type `int` or `string`.\n* `Map`, if *expression* is omitted, *subscript-expression* must be the\nleft-hand side of a *simple-assignment-expression* whose right-hand operand\nhas type `Pair`.\n* `Set` or `ImmSet`, subscripting is not permitted.\n* `Pair`, *expression* must be either the literal 0 or 1.\n\n\n**Semantics**\n\nA *subscript-expression* designates a (possibly non-existent) element of\nan array, a string, a vector, a map, or a Pair. When *subscript-expression* designates an object of\na type that implements [`ArrayAccess`](17-interfaces.md#interface-arrayaccess), the minimal semantics are\ndefined below; however, they can be augmented by that object's methods\n[`offsetGet`](17-interfaces.md#interface-arrayaccess) and [`offsetSet`](17-interfaces.md#interface-arrayaccess).\n\nThe element key is designated by *expression*. If the value of\n*element-key* is neither `int` nor `string`, keys with `float` or `bool` values,\nor strings whose contents match exactly the pattern of [*decimal-literal*](09-lexical-structure.md#integer-literals), are [converted to `int`](08-conversions.md#converting-to-integer-type), and values of all other key\ntypes are [converted to `string`](08-conversions.md#converting-to-string-type).\n\nIf both *postfix-expression* and *expression* designate strings,\n*expression* is treated as if it specified the `int` key zero instead.\n\nA *subscript-expression* designates a modifiable lvalue if and only if\n*postfix-expression* designates a modifiable lvalue.\n\n*postfix-expression designates an array*\n\nIf *expression* is present, if the designated element exists, the type\nand value of the result is the type and value of that element;\notherwise, the result is `null`.\n\nIf *expression* is omitted, a new element is inserted. Its key has type\n`int` and is one more than the highest, previously assigned, non-negative\n`int` key for this array. If this is the first element with a non-negative\n`int` key, key zero is used. However, if the highest, previously assigned\n`int` key for this array is [`PHP_INT_MAX`](06-constants.md#core-predefined-constants), **no new element is\ninserted**. The type and value of the result is the type and value of\nthe new element.\n\n* If the usage context is as the left-hand side of a [*simple-assignment-expression*](10-expressions.md#simple-assignment): The value of the new element is the value of the right-hand side of that *simple-assignment-expression*.\n* If the usage context is as the left-hand side of a [*compound-assignment-expression*](10-expressions.md#compound-assignment): The expression `e1 op= e2` is evaluated as `e1 = null op (e2)`.\n* If the usage context is as the operand of a [postfix-](10-expressions.md#postfix-increment-and-decrement-operators) or [prefix-increment or decrement operator](10-expressions.md#prefix-increment-and-decrement-operators): The value of the new element is `null`.\n\n*postfix-expression designates a string*\n\nIf the designated element exists, the type and value of the result is\nthe type and value of that element; otherwise, the result is an empty\nstring.\n\n*postfix-expression designates a vector*\n\nFor a `Vector` or `ImmVector`, if *expression* is present, if the designated\nelement exists, the type and value of the result is the type and value of that\nelement; otherwise, an exception of type `\\OutOfBoundsException` is thrown.\n\nFor a `Vector`, if *expression* is omitted, a new element is inserted whose\nvalue is that of the right-hand side of the *simple-assignment-expression*.\nIts key has type `int` and is one more than the highest, previously assigned,\n`int` key for this `Vector`. If this is the first element, key zero is used.\nThe type and value of the result is the type and value of the new element.\n\n*postfix-expression designates a map*\n\nFor a `Map` or `ImmMap`, if *expression* is present, if the designated element\nexists, the type and value of the result is the type and value of that\nelement; otherwise, an exception of type `\\OutOfBoundsException` is thrown.\n\nFor a `Map`, if *expression* is omitted, the contents of the `Pair` right-hand\noperand of the *simple-assignment-expression* for which this\n*subscript-expression* is the left operand, is examined. Element 0 of that\nPair represents the key while element 1 represents the value. If the Map\nalready contains an element having that key, that element's value is changed\nto the value in the Pair; otherwise, a new element is inserted in the Map with\nthe key and value from the Pair. The type and value of the result is the type\nand value of the modified or new element.\n\n*postfix-expression designates a Pair*\n\nIf *expression* is the literal 0, the type and value of the result is the type\nand value of the first element in that `Pair`.\n\nIf *expression* is the literal 1, the type and value of the result is the type\nand value of the second element in that `Pair`.\n\n*postfix-expression designates an object of a type that implements*\n`ArrayAccess`\n\nIf *expression* is present,\n\n* If *subscript-expression* is used in a non-lvalue context, the object's method `offsetGet` is called with an argument of *expression*. The type and value of the result is the type and value returned by `offsetGet`.\n* If the usage context is as the left-hand side of a *simple-assignment-expression*: The object's method `offsetSet` is called with a first argument of *expression* and a second argument that is the value of the right-hand side of that *simple-assignment-expression*. The type and value of the result is the type and value of the right-hand side of that *simple-assignment-expression*.\n* If the usage context is as the left-hand side of a *compound-assignment-expression*: The expression `e1 op= e2` is evaluated as `e1 = offsetGet(expression) op (e2)`, which is then processed according to the rules for simple assignment immediately above.\n* If the usage context is as the operand of a [postfix-](10-expressions.md#postfix-increment-and-decrement-operators) or [prefix-increment or decrement operator](10-expressions.md#prefix-increment-and-decrement-operators): The object's method `offsetGet` is called with an argument of *expression*. However, this method has no way of knowing if an increment or decrement operator was used, or whether it was a prefix or postfix operator. The type and value of the result is the type and value returned by `offsetGet`.\n\nIf *expression* is omitted, \n\n* If the usage context is as the left-hand side of a *simple-assignment-expression*: The object's method [`offsetSet`](15-interfaces.md#interface-arrayaccess) is called with a first argument of `null` and a second argument that is the value of the right-hand side of that *simple-assignment-expression*. The type and value of the result is the type and value of the right-hand side of that *simple-assignment-expression*.\n* If the usage context is as the left-hand side of a *compound-assignment-expression*: The expression `e1 op= e2` is evaluated as `e1 = offsetGet(null) op (e2)`, which is then processed according to the rules for simple assignment immediately above.\n* If the usage context is as the operand of a [postfix-](10-expressions.md#postfix-increment-and-decrement-operators) or [prefix-increment or decrement operator](10-expressions.md#prefix-increment-and-decrement-operators): The object's method `offsetGet` is called with an argument of `null`. However, this method has no way of knowing if an increment or decrement operator was used, or whether it was a prefix or postfix operator. The type and value of the result is the type and value returned by `offsetGet`.\n\nNote: The brace (`{...}`) form of this operator has been deprecated. \n\n**Examples**\n\n```Hack\n$v = array(10, 20, 30);\n$v[1] = 1.234;    // change the value (and type) of element [1]\n$v[-10] = 19;     // insert a new element with int key -10\n$v[\"red\"] = true; // insert a new element with string key \"red\"\n[[2,4,6,8], [5,10], [100,200,300]][0][2]  // designates element with value 6\n[\"black\", \"white\", \"yellow\"][1][2]  // designates substring \"i\" in \"white\"\nfunction f(): array<int> { return [1000, 2000, 3000]; }\nf()[2]           // designates element with value 3000\n\"red\"[1.9]       // designates [1]\n\"red\"[0][0][0]   // designates [0]\n// -----------------------------------------\nclass MyVector implements ArrayAccess { … }\n$vect1 = new MyVector(array(10, 'A' => 2.3, \"up\"));\n$vect1[10] = 987; // calls MyVector::offsetSet(10, 987)\n$vect1[] = \"xxx\"; // calls MyVector::offsetSet(null, \"xxx\")\n$x = $vect1[1];   // calls MyVector::offsetGet(1)\n// -----------------------------------------\n$v1 = Vector {5, 10, 15};\n$v1[] = 20;       // add a new element with value 20 to the end\n$v1[0] = -5;      // change the value of existing element 0 to -5\n// -----------------------------------------\n$m1 = Map {'red' => 5, 'green' => 12};\n$m1['blue'] = 35;     // add an element with a new key\n$m1['red'] = 6;       // change the value of an existing element\n$m1[] = Pair {'black', 43};   // append value 43 with key 'black'\n$m1[] = Pair {'red', 123};    // replaces existing element's value with 123\n// -----------------------------------------\n$p1 = Pair {55, 'auto'};\necho \"\\$p1[0] = \" . $p1[0] . \"\\n\";  // outputs '$p1[0] = 55'\n```\n\n### Function Call Operator\n\n**Syntax**\n\n<pre>\n  <i>function-call-expression:</i>\n    <i>postfix-expression</i>  (  <i>argument-expression-list<sub>opt</sub></i>  )\n\n  <i>argument-expression-list:</i>\n    <i>argument-expressions</i>  ,<sub>opt</sub>\n\n  <i>argument-expressions:</i>\n    <i>expression</i>\n    <i>argument-expressions</i>  ,  <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n* [*postfix-expression*](10-expressions.md#general-3)\n\n\n**Constraints**\n\n*postfix-expression* must designate a function, by *name*, be a variable of\n[closure type](05-types.md#closure-types).\n\nThe function call must contain an argument for each parameter in the called\n[function's definition](15-functions.md#function-definitions) not having a default value, and the argument\ntype must be a subtype of the parameter type.\n\nIf the called function is not variadic, the function call must not contain\nmore arguments than there are corresponding parameters.\n\n**Semantics**\n\nIf *postfix-expression* is a [*null-safe-member-selection-expression*](10-expressions.md#null-safe-member-selection-operator), special handling occurs; see later below.\n\nAn expression of the form *function-call-expression* is a *function\ncall*. The postfix expression designates the *called function*, and\n*argument-expression-list* specifies the arguments to be passed to that\nfunction. Each argument corresponds to a parameter or the optional ellipsis in\nthe called function's definition. An argument can have any type. In a function\ncall, *postfix-expression* is evaluated first, followed by each\n*assignment-expression* in the order left-to-right. There is a [sequence\npoint](#general) right before the function is called. For details of the\ntype and value of a function call see [§§](11-statements.md#the-return-statement). The value of a function\ncall, if any, is a non-modifiable lvalue.\n\nIf the called function is variadic, the function call can have any number of\narguments, provided the function call has at least an argument for each\nparameter not having a default value.\n\nWhen an argument corresponds to the ellipsis in the called function's\ndefinition, the argument can have any type.\n\nWhen *postfix-expression* designates an instance method or constructor,\nthe instance used in that designation is used as the value of `$this` in\nthe invoked method or constructor. However, if no instance was used in\nthat designation (for example, in the call `C::instance_method()`) the\ninvoked instance has no `$this` defined.\n\nWhen a function is called, the value of each argument passed to it is\nassigned to the corresponding parameter in that function's definition,\nif such a parameter exists. The assignment of argument values to\nparameters is defined in terms of [simple assignment](10-expressions.md#simple-assignment). Any parameters having a\ndefault value but no corresponding argument, takes on that default value.\n\nIf an undefined variable is passed using byRef, that variable becomes\ndefined, with a default value of `null`.\n\nDirect and indirect recursive function calls are permitted.\n\nThe following discussion applies when *postfix-expression* is a\n*null-safe-member-selection-expression*: If *postfix-expression* is not\n`null`, the behavior is the same as if a [*member-selection-expression*](10-expressions.md#member-selection-operator) were used instead of a *null-safe-member-selection-expression*.\nOtherwise, no function is called, and the *function-call-expression*\nevaluates to `null`. The *expression*s in\n*argument-expression-list* are evaluated.\n\n**Examples**\n\n```Hack\nfunction f3(int $p1 = -1, float $p2 = 99.99, string $p3 = '??'): void { … }\nf3();                   // $p1 is -1, $p2 is 99.99, $p3 is ??\nf3(123);                // $p1 is 123, $p2 is 99.99, $p3 is ??\nf3(123, 3.14);          // $p1 is 123, $p2 is 3.14, $p3 is ??\nf3(123, 3.14, 'Hello'); // $p1 is 123, $p2 is 3.14, $p3 is Hello\n// -----------------------------------------\nfunction fx(int $p1, int $p2, int $p3, int $p4, int $p5): void { … }\nfunction fy(int $p1, int $p2, int $p3, int $p4, int $p5): void { … }\nfunction fz(int $p1, int $p2, int $p3, int $p4, int $p5): void { … }\n$funcTable = array(fun('fx'), fun('fy'), fun('fz')); // use lib function fun\n$i = 1;\n$funcTable[$i++]($i, ++$i, $i, $i = 12, --$i); // calls fy(2,3,3,12,11)\n// -----------------------------------------\n$anon = function (): void { … };  // store a closure in $anon\n$anon();  // call the anonymous function\n```\n\n### Member-Selection Operator\n\n**Syntax**\n\n<pre>\n  <i>member-selection-expression:</i>\n    <i>postfix-expression</i>  ->  <i>name</i>\n    <i>postfix-expression</i>  ->  <i>variable-name</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*name*](09-lexical-structure.md#names)\n* [*postfix-expression*](10-expressions.md#general-3)\n* [*variable-name*](09-lexical-structure.md#names)\n\n**Constraints**\n\n*postfix-expression* must designate an object. \n\n*name* must designate an instance property, or an instance\nmethod of the class designated by *postfix-expression*.\n\n*variable-name* must name a variable which when evaluated produces a string\ncontaining an instance property or an instance method of the class \ndesignated by *postfix-expression*.\n\n\n**Semantics**\n\nA *member-selection-expression* designates an instance property or an\ninstance method of the object designated by\n*postfix-expression*. For a property, the value is that of the property,\nand is a modifiable lvalue if *postfix-expression* is a modifiable\nlvalue.\n\n**Examples**\n\n```Hack\nclass Point {\n  private float $x;\n  private float $y;\n  public function move(float $x, float $y): void {\n    $this->x = $x;  // sets private property $x\n    $this->y = $y;  // sets private property $x\n  }\n  public function __toString(): string  {\n    return '(' . $this->x . ',' . $this->y . ')';\n  }     // get private properties $x and $y\n}\n$p1 = new Point();\n$p1->move(3, 9);  // calls public instance method move by name\n```\n\n### Null-Safe Member-Selection Operator\n\n**Syntax**\n<pre>\n<i>null-safe-member-selection-expression:</i>\n  <i>postfix-expression</i>  ?->  <i>name</i>\n  <i>postfix-expression</i>  ?->  <i>variable-name</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*name*](09-lexical-structure.md#names)\n* [*postfix-expression*](10-expressions.md#general-3)\n* [*variable-name*](09-lexical-structure.md#names)\n\n**Constraints**\n\n*postfix-expression* must designate a nullable-typed object.\n\n*name* must designate an instance property or an instance method of the class designated by *postﬁx-expression*.\n\n*variable-name* must name a variable which when evaluated produces a string\ncontaining an instance property or an instance method of the class \ndesignated by *postfix-expression*.\n\n**Semantics**\n\nIf *postﬁx-expression* is `null`, no property or method is selected and the \nresulting value is `null`. Otherwise, the behavior is like that of the \n[member-selection operator `->`](10-expressions.md#member-selection-operator), \nexcept that the resulting value is not an lvalue.\n\n### Postfix Increment and Decrement Operators\n\n**Syntax**\n\n<pre>\n  <i>postfix-increment-expression:</i>\n    <i>unary-expression</i>  ++\n\n  <i>postfix-decrement-expression:</i>\n    <i>unary-expression</i>  --\n</pre>\n\n**Defined elsewhere**\n\n* [*unary-expression*](10-expressions.md#general-4)\n\n**Constraints**\n\nThe operand of the postfix ++ and -- operators must be a modifiable\nlvalue that has arithmetic type.\n\n**Semantics**\n\nThese operators behave like their [prefix counterparts](10-expressions.md#prefix-increment-and-decrement-operators) except\nthat the value of a postfix ++ or -- expression is the value before any\nincrement or decrement takes place.\n\n**Examples**\n\n```Hack\n$i = 10; $j = $i-- + 100;   // old value of $i (10) is added to 100\n$a = array(100, 200); $v = $a[1]++; // old value of $ia[1] (200) is assigned\n```\n\n### Scope-Resolution Operator\n\n**Syntax**\n\n<pre>\n  <i>scope-resolution-expression:</i>\n    <i>scope-resolution-qualifier</i>  ::  <i>name</i>\n    <i>scope-resolution-qualifier</i>  ::  <i>variable-name</i>\n    <i>scope-resolution-qualifier</i>  ::  class\n\n  <i>scope-resolution-qualifier:</i>\n    <i>qualified-name</i>\n    <i>variable-name</i>\n    self\n    parent\n    static\n</pre>\n\n**Defined elsewhere**\n\n* [*name*](09-lexical-structure.md#names)\n* [*qualified-name*](20-namespaces.md#defining-namespaces)\n* [*variable-name*](09-lexical-structure.md#names)\n\n**Constraints**\n\nScope resolution expressions of the form <i>qualified-name</i>`::`<i>name</i> must have the name of an enum, class or interface type on the left of the `::`, and an enumeration constant or type member on the right.\n\nScope resolution expressions of the form <i>qualified-name</i>`::`<i>variable-name</i> must have the name of a class or interface type on the left of the `::`, and a static property of that type on the right.\n\nScope resolution expressions of the form <i>qualified-name</i>`::`class must have the name of a class or interface type on the left of the `::`.\n\nScope resolution expressions with a *variable-name* to the left of the `::` must name a variable having the [`classname` type](05-types.md#the-classname-type).\n\n*variable-name* `:: class` is not permitted.\n\n**Semantics**\n\nWhen *qualified-name* is the name of an enumerated type, *scope-resolution-expression* designates an enumeration constant within that type.\n\nFrom inside or outside a class or interface, operator `::` allows the\nselection of a constant. From inside or outside a class, this operator\nallows the selection of a static property, static method, or instance\nmethod. From within a class, it also allows the selection of an\noverridden property or method. For a property, the value is that of the\nproperty, and is a modifiable lvalue if *name* is\na modifiable lvalue.\n\nFrom within a class, `self::m` refers to the member `m` in that class,\nwhereas `parent::m` refers to the closest member `m` in the base-class\nhierarchy, not including the current class. From within a method,\n`static::m` refers to the member `m` in the class that corresponds to the\nclass inheritance context in which the method is called. This allows\n*late static binding*. Consider the following scenario:\n\n```Hack\nclass Base\n{\n  public function b(): void\n  {\n    static::f();  // calls the most appropriate f()\n  }\n  public function f(): void { ... }\n}\nclass Derived extends Base\n{\n  public function f(): void { ... }\n}\n$b1 = new Base();\n$b1->b(); // as $b1 is an instance of Base, Base::b() calls Base::f()\n$d1 = new Derived();\n$d1->b(); // as $d1 is an instance of Derived, Base::b() calls Derived::f()\n```\n\nThe value of the form of *scope-resolution-expression* ending in `::class`\nis a string containing the fully qualified name of the current class,\nwhich for a static qualifier, means the current class context.\n\n*variable-name* `::` *name* results in a constant whose value has the [`classname` type](05-types.md#the-classname-type) for the type designated by *variable-name*.\n\n**Examples**\n\n```Hack\nfinal class MathLibrary\nenum ControlStatus: int {\n  Stopped = 0;\n  Stopping = 1;\n  Starting = 2;\n  Started = 3;\n}\nfunction main(ControlStatus $p1): void {\n  switch ($p1)\n  {\n  case ControlStatus::Stopped:\n    …\n    break;\n  case ControlStatus::Stopping:\n    …\n    break;\n  …\n  }\n  …\n}\n// -----------------------------------------\nfinal class MathLibrary {\n  public static function sin(): float { … }\n  …\n}\n$v = MathLibrary::sin(2.34);  // call directly by class name\n// -----------------------------------------\nclass MyRangeException extends Exception {\n  public function __construct(string $message, …)\n  {\n    parent::__construct($message);\n    …\n  }\n  …\n}\n// -----------------------------------------\nclass Point {\n  private static int $pointCount = 0;\n  public static function getPointCount(): int {\n    return self::$pointCount;\n  }\n  …\n}\n```\n\n### Exponentiation Operator\n\n**Syntax**\n\n<pre>\n  <i>exponentiation-expression:</i>\n    <i>expression  **  expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Constraints**\n\nBoth *expression*s must have an arithmetic type.\n\n**Semantics**\n\nThe `**` operator produces the result of raising the value of the\nleft-hand operand to the power of the right-hand one. If both operands have non-negative integer\nvalues and the result can be represented as an `int`, the result has type\n`int`; otherwise, the result has type `float`.\n\n**Examples**\n\n```Hack\n2**3;   // int with value 8\n2**3.0;   // float with value 8.0\n\"2.0\"**\"3\"; // float with value 8.0\n```\n\n## Unary Operators\n\n### General\n\n**Syntax**\n\n<pre>\n  <i>unary-expression:</i>\n    <i>postfix-expression</i>\n    <i>prefix-increment-expression</i>\n    <i>prefix-decrement-expression</i>\n    <i>unary-op-expression</i>\n    <i>error-control-expression</i>\n    <i>cast-expression</i>\n    <i>await-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*await-expression*](10-expressions.md#await-operator)\n* [*cast-expression*](10-expressions.md#cast-operator)\n* [*error-control-expression*](10-expressions.md#error-control-operator)\n* [*postfix-expression*](10-expressions.md#general-3)\n* [*prefix-decrement-expression*](10-expressions.md#prefix-increment-and-decrement-operators)\n* [*prefix-increment-expression*](10-expressions.md#prefix-increment-and-decrement-operators)\n* [*unary-op-expression*](10-expressions.md#unary-arithmetic-operators)\n\n**Semantics**\n\nThese operators associate right-to-left.\n\n### Prefix Increment and Decrement Operators\n\n**Syntax**\n\n<pre>\n  <i>prefix-increment-expression:</i>\n    ++ <i>unary-expression</i>\n\n  <i>prefix-decrement-expression:</i>\n    -- <i>unary-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*unary-expression*](10-expressions.md#general-4)\n\n**Constraints**\n\nThe operand of the prefix `++` or `--` operator must be a modifiable lvalue\nthat has arithmetic type.\n\n**Semantics**\n\n*Arithmetic Operands*\n\nFor a prefix `++` operator, the [side effect](#general) of the operator is to increment by 1, as appropriate, the\nvalue of the operand. The result is the value of the operand after it\nhas been incremented. If an int operand's value is the largest\nrepresentable for that type, the type and value of [the result is implementation-defined](05-types.md#the-integer-type).\n\nFor a prefix `--` operator, the side\neffect of the operator is to decrement by 1, as appropriate, the value\nof the operand. The result is the value of the operand after it has been\ndecremented. If an int operand's value is the smallest representable for\nthat type, the type and value of [the result is implementation-defined](05-types.md#the-integer-type).\n\nFor a prefix `++` or `--` operator used with an operand having the value\n`INF`, `-INF`, or `NAN`, there is no side effect, and the result is the\noperand's value.\n\n**Examples**\n\n```Hack\n$i = 10; $j = --$i + 100;   // new value of $i (9) is added to 100\n$a = array(100, 200); $v = ++$a[1]; // new value of $ia[1] (201) is assigned\n```\n\n### Unary Arithmetic Operators\n\n**Syntax**\n\n<pre>\n  <i>unary-op-expression:</i>\n    <i>unary-operator cast-expression</i>\n\n  <i>unary-operator: one of</i>\n    +  -  !  ~\n</pre>\n\n**Defined elsewhere**\n\n* [*cast-expression*](10-expressions.md#cast-operator)\n\n**Constraints**\n\nThe operand of the unary `+` and unary `-` operators must have\narithmetic type.\n\nThe operand of the unary `!` operator must have arithmetic or enumerated type. (**The validity of allowing this operator to have an enumerated type operand is questionable; avoid such usage lest support for it disappears.**)\n\nThe operand of the unary `~` operator must have integer type.\n\n**Semantics**\n\nFor a unary `+` operator, the type and\nvalue of the result is the type and value of the operand. \n\nFor a unary `-` operator, the value of the\nresult is the negated value of the operand. However, if an int operand's\noriginal value is the smallest representable for that type, the type and\nvalue of [the result is implementation-defined](05-types.md#the-integer-type).\n\nFor a unary `!` operator, the type of the\nresult is `bool`. The value of the result is `true` if the value of the\noperand is non-zero (or for a string-based enumeration, a non-empty string); otherwise, the value of the result is `false`. For\nthe purposes of this operator, `NAN` is considered a non-zero value. The\nexpression `!E` is equivalent to `(E == 0)`.\n\nFor a unary `~` operator, the type of the result\nis `int`. The value of the result is the bitwise complement of the value\nof the operand (that is, each bit in the result is set if and only if\nthe corresponding bit in the operand is clear).\n\n**Examples**\n\n```Hack\n$v = +10;\nif ($v1 > -5) ...\n$t = true;\nif (!$t) ...\n$v = ~0b1010101;\n```\n\n### Error Control Operator\n\n**Syntax**\n\n<pre>\n  <i>error-control-expression:</i>\n    @  <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Semantics**\n\nOperator `@` suppresses any error messages generated by the evaluation of\n*expression*.\n\nIf a custom error-handler has been established using the library\nfunction [`set_error_handler`](http://docs.hhvm.com/manual/en/function.set-error-handler.php) that handler is\nstill called.\n\n**Examples**\n\n```Hack\n$infile = @fopen(\"NoSuchFile.txt\", 'r');\n```\n\nOn open failure, the value returned by `fopen` is `false`, which is\nsufficient to know to handle the error. There is no need to have any\nerror message displayed.\n\n### Cast Operator\n\n**Syntax**\n\n<pre>\n  <i>cast-expression:</i>\n    (  <i>cast-type</i>  ) <i>unary-expression</i>\n\n  <i>cast-type: one of</i>\n    bool  int  float  string\n</pre>\n\n**Defined elsewhere**\n\n* [*unary-expression*](10-expressions.md#general-4)\n\n**Semantics**\n\nThe\nvalue of the operand *cast-expression* is converted to the type\nspecified by *cast-type*, and that is the type and value of the result.\nThis construct is referred to a *cast,* and is used as the verb, \"to\ncast\". If no conversion is involved, the type and value of the result\nare the same as those of *cast-expression*.\n\nA cast can result in a loss of information.\n\nA *cast-type* of `bool` results in a conversion to type `bool`.\nSee [§§](08-conversions.md#converting-to-boolean-type) for details.\n\nA *cast-type* of `int` results in a conversion to type `int`. See [§§](08-conversions.md#converting-to-integer-type) for details.\n\nA *cast-type* of `float` results in a conversion to type `float`. See [§§](08-conversions.md#converting-to-floating-point-type) for details.\n\nA *cast-type* of `string` results in a conversion to type `string`. See [§§](08-conversions.md#converting-to-string-type)\nfor details.\n\nNote that *cast-type* cannot be a [generic type parameter](14-generic-types-methods-and-functions.md#type-parameters).\n\n**Examples**\n\n```Hack\n(int)(10/3)          // results in the int 3 rather than the float 3.333...\n```\n\n### Await Operator\n\n**Syntax**\n\n<pre>\n  <i>await-expression:</i>\n    await  <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Constraints**\n\nThis operator must be used within an[ asynchronous function](15-functions.md#asynchronous-functions).\n\n*expression* must have a type that implements [`Awaitable<T>`(17-interfaces.md#interface-awaitable).\n\nThe return type of the function containing a use of this operator must be a type that implements `Awaitable<T>`.\n\n*await-expression* can only be used in the following contexts:\n*\tAs an [*expression-statement*](11-statements.md#expression-statements)\n*\tAs the *assignment-expression* in a [*simple-assignment-expression*](10-expressions.md#simple-assignment)\n*\tAs *expression* in a [*return-statement*](11-statements.md#the-return-statement)\n\n**Semantics**\n\n`await` suspends the execution of an async function until the result of the asynchronous operation represented by *expression* is available. See [§§](15-functions.md#asynchronous-functions) for more information.\n\nThe resulting value is the value of type `T` that was wrapped in the object of type `Awaitable<T>`` returned from the async function. Consider the following:\n\n```Hack\nasync function f(): Awaitable<int> {…}\n\n$x = await f();\t\t// $x is an int\n$x = f();\t\t\t// $x is an Awaitable<int>\n```\n\n**Examples**\n\n```Hack\nasync function f(): Awaitable<int> {\n  …\n  $r1 = await g();\n  …\n  return $r1;\n}\n\nasync function g(): Awaitable<int> {\n  …\n  return $r2;\n}\n\nfunction main (): void {\n  …\n  $v = f();\n  …\n}\n```\n\nFunction `main` calls async function `f`, which in turn awaits on async function `g`. When `g` terminates normally, the `int` value returned is automatically wrapped in an object of type `Awaitable<int>`. Back in function `f`, that object is unwrapped, and the `int` it contained is extracted and assigned to local variable `$r1`. When `f` terminates normally, the `int` value returned is automatically wrapped in an object of type `Awaitable<int>`. Back in function `main`, that object is assigned to local variable `$v`.\n\n## `instanceof` Operator\n\n**Syntax**\n\n<pre>\n<i>instanceof-expression:</i>\n  <i>unary-expression</i>\n  <i>instanceof-subject</i>  instanceof   <i>instanceof-type-designator</i>\n\n<i>instanceof-subject:</i>\n  <i>expression</i>\n\n<i>instanceof-type-designator:</i>\n  <i>qualified-name</i>\n  <i>variable-name</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n* [*qualified-name*](20-namespaces.md#defining-namespaces)\n* [*unary-expression*](10-expressions.md#general-4)\n* [*variable-name*](09-lexical-structure.md#names)\n\n**Constraints**\n\nThe *expression* in *instanceof-subject* must designate a variable.\n\n*qualified-name* must be the name of a class or interface type.\n\n*variable-name* must name a value having the [`classname` type](05-types.md#the-classname-type).\n\n**Semantics**\n\nOperator `instanceof` returns `true` if the variable designated by\n*expression* in *instanceof-subject* is an object having type\n*qualified-name* or *variable-name*, is an object whose type is derived from type\n*qualified-name* or *variable-name*, or is an object whose type implements interface\n*qualified-name* or *variable-name*. Otherwise, it returns `false`.\n\nIf either *expression* is not an instance, `false` is returned.\n\nNote: This operator supersedes the library function [`is_a`](http://www.php.net/is_a), which\nhas been deprecated.\n\n**Examples**\n\n```Hack\nclass C1 { … } $c1 = new C1();\nclass C2 { … } $c2 = new C2();\nclass D extends C1 { … } $d = new D();\n$d instanceof C1      // true\n$d instanceof C2      // false\n$d instanceof D       // true\n// -----------------------------------------\ninterface I1 { … }\ninterface I2 { … }\nclass E1 implements I1, I2 { … }\n$e1 = new E1();\n$e1 instanceof I1     // true\n```\n\n## Multiplicative Operators\n\n**Syntax**\n\n<pre>\n  <i>multiplicative-expression:</i>\n    <i>instanceof-expression</i>\n    <i>multiplicative-expression</i>  *  <i>instanceof-expression</i>\n    <i>multiplicative-expression</i>  /  <i>instanceof-expression</i>\n    <i>multiplicative-expression</i>  %  <i>instanceof-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*instanceof-expression*](10-expressions.md#instanceof-operator)\n\n**Constraints**\n\nThe operands of the `*` and `/` operators must have arithmetic type.\n\nThe operands of the `%` operator must have integer type.\n\nThe right-hand operand of operator `/` and operator `%` must not be zero.\n\n**Semantics**\n\nThe binary `*` operator produces the product of its operands. If either operand has type\n`float`, the other is converted to that type, and the result has type\n`float`. Otherwise, both operands have type `int`, in which case, if the\nresulting value can be represented in type `int` that is the result type.\nOtherwise, the type and value of [the result is implementation-defined](05-types.md#the-integer-type).\n\nDivision by zero results in a diagnostic followed by a `bool` result\nhaving value `false`. (The values +/- infinity and NaN cannot be generated\nvia this operator; instead, use the predefined constants `INF` and `NAN`.)\n\nThe binary `/` operator produces the quotient from dividing the left-hand\noperand by the right-hand one. If either operand has type `float`, the other is\nconverted to that type, and the result has type `float`. Otherwise, both\noperands have type `int`, in which case, if the mathematical value of the\ncomputation can be preserved using type `int`, that is the result type;\notherwise, the type of the result is `float`.\n\nThe binary `%` operator produces the remainder from dividing the left-hand\noperand by the right-hand one. The result has type `int`.\n\nThese operators associate left-to-right.\n\n**Examples**\n\n```Hack\n-10 * 100 → int with value -1000\n100 * -3.4e10 → float with value -3400000000000\n\"123\" * \"2e+5\" → float with value 24600000\n100 / 100 → int with value 1\n100 / 123 → float with value 0.8130081300813\n123 % 100 → int with value 23\n```\n\n## Additive Operators\n\n**Syntax**\n\n<pre>\n  <i>additive-expression:</i>\n    <i>multiplicative-expression</i>\n    <i>additive-expression</i>  +  <i>multiplicative-expression</i>\n    <i>additive-expression</i>  -  <i>multiplicative-expression</i>\n    <i>additive-expression</i>  .  <i>multiplicative-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*multiplicative-expression*](#multiplicative-operators)\n\n**Constraints**\n\nIf either operand has array type, the other operand must also have array\ntype, and the two types must have a subtype relationship.\n\nIf the operands of the `*` and `/` operators do not both have array type, they must both have arithmetic type.\n\n**Semantics**\n\nFor non-array operands, the binary `+` operator produces the sum of those\noperands, while the binary `- `operator produces the difference of its\noperands when subtracting the right-hand operand from the left-hand one.\nIf either operand has type `float`, the other is converted to that type, and\nthe result has type `float`. Otherwise, both operands have type `int`, in\nwhich case, if the resulting value can be represented in type `int` that\nis the result type. Otherwise, the type and value of [the result is implementation-defined](05-types.md#the-integer-type).\n\nIf both operands have array type, the binary `+` operator produces a new\narray that is the union of the two operands. The result is a copy of the\nleft-hand array with elements inserted at its end, in order, for each\nelement in the right-hand array whose key does not already exist in the\nleft-hand array. Any element in the right-hand array whose key exists in\nthe left-hand array is ignored. In this context, this operator is not commutative.\n\nThe binary `.` operator creates a string that is the concatenation of the\nleft-hand operand and the right-hand operand, in that order. If either\nor both operands have types other than `string`, their values are\nconverted to type `string`. The result has type `string`.\n\nThese operators associate left-to-right.\n\n**Examples**\n\n```Hack\n-10 + 100 → int with value 90\n100 + -3.4e10 → float with value -33999999900\n100 - 123 → int with value 23\n-3.4e10 - abc → float with value -34000000000\n// -----------------------------------------\narray(66) + array(100, 200) → array(66, 200)\narray(2 => 'aa') + array(-4 => 'bb', 6 => 'cc') → array(2 => 'aa', -4 => 'bb', 6 => 'cc')\narray('red' => 12, 'green' => 7) + array('blue' => 3) → array('red' => 12, 'green' => 7, 'blue' => 3)\n// -----------------------------------------\n-10 . NAN → string with value \"-10NAN\"\nINF . \"2e+5\" → string with value \"INF2e+5\"\ntrue . null → string with value \"1\"\n10 + 5 . 12 . 100 - 50 → int with value 1512050; ((((10 + 5).12).100)-50)\n```\n\n## Bitwise Shift Operators\n\n**Syntax**\n\n<pre>\n  <i>shift-expression:</i>\n    <i>additive-expression</i>\n    <i>shift-expression</i>  &lt;&lt;  <i>additive-expression</i>\n    <i>shift-expression</i>  &gt;&gt;  <i>additive-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*additive-expression*](10-expressions.md#additive-operators)\n\n**Constraints**\n\nEach of the operands must have `int` type.\n\n**Semantics**\n\nGiven the expression `e1 << e2`, the bits in the value of `e1` are shifted\nleft by `e2` positions. Bits shifted off the left end are discarded, and\nzero bits are shifted on from the right end. Given the expression\n`e1 >> e2`, the bits in the value of `e1` are shifted right by\n`e2` positions. Bits shifted off the right end are discarded, and the sign\nbit is propagated from the left end. \n\nThe type of the result is `int`, and the value of the result is that after\nthe shifting is complete. The values of `e1` and `e2` are unchanged.\n\nIf the shift count is negative, the actual shift applied is `n -\n(-shift count % n)`, where `n` is the number of bits per `int`. If the\nshift count is greater than the number of bits in an `int`, the actual\nshift applied is shift count `% n`.\n\nThese operators associate left-to-right.\n\n**Examples**\n\n```Hack\n1000 >> 2   // 3E8 is shifted right 2 places\n-1000 << 2      // FFFFFC18 is shifted left 5 places\n123 >> 128      // adjusted shift count = 0\n123 << 33   // For a 32-bit int, adjusted shift count = 1; otherwise, 33\n```\n\n## Relational Operators\n\n**Syntax**\n\n<pre>\n  <i>relational-expression:</i>\n    <i>shift-expression</i>\n    <i>relational-expression</i>  &lt;   <i>shift-expression</i>\n    <i>relational-expression</i>  &gt;   <i>shift-expression</i>\n    <i>relational-expression</i>  &lt;=  <i>shift-expression</i>\n    <i>relational-expression</i>  &gt;=  <i>shift-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*shift-expression*](10-expressions.md#bitwise-shift-operators)\n\n**Constraints**\n\nIf either operand has an enumerated type, the other operand must have the exact same type.\n\n**Semantics**\n\nOperator `<` represents *less-than*, operator `>` represents\n*greater-than*, operator `<=` represents *less-than-or-equal-to*, and\noperator `>=` represents *greater-than-or-equal-to*.\n\nThe type of the result is `bool`. \n\nThe operands are processed using the following steps, in order:\n\n1.  If the operands both have arithmetic type, the result is the numerical comparison of the two operands after conversion.\n2.  If both operands are non-numeric strings, the result is the lexical comparison of the two operands. Specifically, the strings are compared byte-by-byte starting with their first byte. If the two bytes compare equal and there are no more bytes in either string, the strings are equal and the comparison ends; otherwise, if this is the final byte in one string, the shorter string compares less-than the longer string and the comparison ends. If the two bytes compare unequal, the string having the lower-valued byte compares less-than the other string, and the comparison ends. If there are more bytes in the strings, the process is repeated for the next pair of bytes.\n3.  If both operands are numeric strings, the result is the numeric comparison of the two operands after conversion.\n4.  If both operands have vector-like or map-like array type, if the arrays have different numbers of elements, the one with the fewer is considered less-than the other one—regardless of the keys and values in each—, and the comparison ends. For arrays having the same numbers of elements, if the next key in the left-hand operand exists in the right-hand operand, the corresponding values are compared. If they are unequal, the array containing the lesser value is considered less-than the other one, and the comparison ends; otherwise, the process is repeated with the next element. If the next key in the left-hand operand does not exist in the right-hand operand, the arrays cannot be compared and `false` is returned. For array comparison, the order of insertion of the elements into those arrays is irrelevant.\n5.  If the operands have the same object type, the result is decided by comparing the lexically first-declared instance property in each object. If those properties have object type, the comparison is applied recursively.\n\nRegarding operands having the same enumeration type, for an `int`-based enumeration the enumeration is compared using its value directly as an `int`. For a `string`-based enumeration, the enumeration is compared using its value directly as a `string`. (**The validity of allowing these operators to have an enumerated type as an operand is questionable; avoid such usage lest support for it disappears.**)\n\nThese operators associate left-to-right.\n\n**Examples**\n\n```Hack\n\"\" < \"ab\"       → result has value true\n\"a\" > \"A\"       → result has value true\n\"a0\" < \"ab\"     → result has value true\n\"aA <= \"abc\"    → result has value true\n// -----------------------------------------\n10 <= 0         → result has value false\n'123' <= '4') → false; is doing a numeric comparison\n'X123' <= 'X4'  → true; is doing a string comparison\n// -----------------------------------------\n[100] < [10,20,30] → result has value true (LHS array is shorter)\n```\n\n**Notes**\n\nIdeally, one might expect some constraints on the combination of operand types. However, for historical reasons, other behaviors from PHP have been retained, as documented.\n\n## Equality Operators\n\n**Syntax**\n\n<pre>\n  <i>equality-expression:</i>\n    <i>relational-expression</i>\n    <i>equality-expression</i>  ==  <i>relational-expression</i>\n    <i>equality-expression</i>  !=  <i>relational-expression</i>\n    <i>equality-expression</i>  ===  <i>relational-expression</i>\n    <i>equality-expression</i>  !==  <i>relational-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*relational-expression*](10-expressions.md#relational-operators)\n\n**Semantics**\n\nOperator `==` represents *value-equality*, operator `!=` represents *value-inequality*, operator `===` represents\n*same-type-and-value-equality*, and operator `!==` represents\n*not-same-type-and-value-equality*. However, when comparing two objects,\noperator `===` represents *identity* and operator `!==` represents\n*non-identity*. Specifically, in this context, these operators check to\nsee if the two operands are the exact same object, not two different\nobjects of the same type and value.\n\nThe type of the result is `bool`. \n\nThe operands are processed using the following steps, in order:\n\n1.  For operators `==`, `!=`, and `<>`, if either operand has the value\n    `null`, then if the other operand has type string, the `null` is\n    converted to the empty string (\"\"); otherwise, the `null` is converted\n    to type bool.\n2.  If both operands are non-numeric strings or one is a numeric string\n    and the other a leading-numeric string, the result is the lexical\n    comparison of the two operands. Specifically, the strings are\n    compared byte-by-byte starting with their first byte. If the two\n    bytes compare equal and there are no more bytes in either string,\n    the strings are equal and the comparison ends; otherwise, if this is\n    the final byte in one string, the shorter string compares less-than\n    the longer string and the comparison ends. If the two bytes compare\n    unequal, the string having the lower-valued byte compares less-than\n    the other string, and the comparison ends. If there are more bytes\n    in the strings, the process is repeated for the next pair of bytes.\n3.  If either operand has type bool, for operators `==` and `!=`, the\n    other operand is converted to that type. The result is the logical\n    comparison of the two operands after any conversion, where `false` is\n    defined to be less than `true`.\n4.  If the operands both have arithmetic type, string type, or are\n    resources, for operators `==` and `!=`, they are converted to the\n    corresponding arithmetic type [§§](08-conversions.md#converting-to-integer-type) and [§§](08-conversions.md#converting-to-floating-point-type)). The result is the\n    numerical comparison of the two operands after any conversion.\n5.  If both operands have array type, for operators `==` and `!=`,\n    the arrays are equal if they have the same set of key/value pairs and the corresponding values have the same type,\n    after element type conversion, without regard to the order of\n    insertion of their elements. For operators `===` and `!==` the arrays\n    are equal if they have the same set of key/value pairs, the\n    corresponding values have the same type, and the order of insertion\n    of their elements are the same.\n6.  If only one operand has object type, the two operands are never\n    equal.\n7.  If only one operand has array type, the two operands are never\n    equal.\n8.  If the operands have different object types, the two operands are\n    never equal except that a `Vector` and an `ImmVector` having the same member type and value set can be equal, as can a `Map` and an `ImmMap`, and a `Set` and an `ImmSet`.\n9.  If the operands have the same object type, the two operands are\n    equal if the instance properties in each object have the same\n    values. Otherwise, the objects are unequal. The instance properties\n    are compared, one at a time, in the lexical order of their\n    declaration. For properties that have object type, the comparison is\n    applied recursively.\n\nThese operators associate left-to-right.\n\n**Examples**\n\n```Hack\n\"a\" <> \"aa\" // result has value true\n// -----------------------------------------\nnull == 0   // result has value true\nnull === 0  // result has value false\ntrue != 100  // result has value false\ntrue !== 100  // result has value true\n// -----------------------------------------\n\"10\" != 10  // result has value false\n\"10\" !== 10 // result has value true\n// -----------------------------------------\n[10,20] == [10,20.0]  // result has value true\n[10,20] === [10,20.0] // result has value false\n[\"red\"=>0,\"green\"=>0] === [\"red\"=>0,\"green\"=>0] // result has value true\n[\"red\"=>0,\"green\"=>0] === [\"green\"=>0,\"red\"=>0] // result has value false\n```\n\n**Notes**\n\nIdeally, one might expect some constraints on the combination of operand types. However, for historical reasons, other behaviors from PHP have been retained, as documented.\n\n# # Bitwise AND Operator\n\n**Syntax**\n\n<pre>\n  <i>bitwise-AND-expression:</i>\n    <i>equality-expression</i>\n    <i>bit-wise-AND-expression</i>  &amp;  <i>equality-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*equality-expression*](10-expressions.md#equality-operators)\n\n**Constraints**\n\nEach of the operands must have `int` type.\n\n**Semantics**\n\nThe result of this operator is the bitwise-AND of the two operands, and\nthe type of that result is `int`.\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```Hack\n0b101111 & 0b101          // 0b101\n$lLetter = 0x73;          // letter 's'\n$uLetter = $lLetter & ~0x20;  // clear the 6th bit to make letter 'S'\n```\n\n## Bitwise Exclusive OR Operator\n\n**Syntax**\n\n<pre>\n  <i>bitwise-exc-OR-expression:</i>\n    <i>bitwise-AND-expression</i>\n    <i>bitwise-exc-OR-expression</i>  ^   <i>bitwise-AND-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*bitwise-AND-expression*](10-expressions.md#bitwise-and-operator)\n\n**Constraints**\n\nEach of the operands must have `int` type.\n\n**Semantics**\n\nThe result of this operator is the bitwise exclusive-OR of the two\noperands, and the type of that result is `int`.\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```Hack\n0b101111 | 0b101    // 0b101010\n$v1 = 1234; $v2 = -987; // swap two integers having different values\n$v1 = $v1 ^ $v2;\n$v2 = $v1 ^ $v2;\n$v1 = $v1 ^ $v2;    // $v1 is now -987, and $v2 is now 1234\n```\n\n## Bitwise Inclusive OR Operator\n\n**Syntax**\n\n<pre>\n  <i>bitwise-inc-OR-expression:</i>\n    <i>bitwise-exc-OR-expression</i>\n    <i>bitwise-inc-OR-expression</i>  |  <i>bitwise-exc-OR-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*bitwise-exc-OR-expression*](10-expressions.md#bitwise-exclusive-or-operator)\n\n**Constraints**\n\nEach of the operands must have `int` type.\n\n**Semantics**\n\nThe result of this operator is the bitwise inclusive-OR of the two\noperands, and the type of that result is `int`.\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```Hack\n0b101111 | 0b101      // 0b101111\n$uLetter = 0x41;      // letter 'A'\n$lLetter = $upCaseLetter | 0x20;  // set the 6th bit to make letter 'a'\n```\n\n## Logical AND Operator\n\n**Syntax**\n\n<pre>\n  <i>logical-AND-expression:</i>\n    <i>bitwise-inc-OR-expression</i>\n    <i>logical-AND-expression</i>  &amp;&amp;  <i>bitwise-inc-OR-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*bitwise-inc-OR-expression*](10-expressions.md#bitwise-inclusive-or-operator)\n\n**Constraints**\n\nEach of the operands must have scalar type.\n\n**Semantics**\n\nIf either operand does not have type bool, its value is first converted\nto that type. An `int`-based enumeration with value zero is converted to `false`, while a non-zero value is converted to `true`. Likewise, a `string`-based enumeration with value empty string is converted to `false`, while a non-empty value is converted to `true`. (**The validity of allowing this operator to have an enumerated type operand is questionable; avoid such usage lest support for it disappears.**)\n\nGiven the expression `e1 && e2, e1` is evaluated first. If `e1` is `false`, `e2` is not evaluated, and the result has type `bool`, value `false`. Otherwise, `e2` is evaluated. If `e2` is `false`, the result has type bool, value `false`; otherwise, it has type `bool`, value `true`. There is a sequence point after the evaluation of `e1`.\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```Hack\nif ($month > 1 && $month <= 12) ...\n```\n\n## Logical Inclusive OR Operator\n\n**Syntax**\n\n<pre>\n  <i>logical-inc-OR-expression:</i>\n    <i>logical-AND-expression</i>\n    <i>logical-inc-OR-expression</i>  ||  <i>logical-AND-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*logical-AND-expression*](10-expressions.md#logical-and-operator)\n\n**Constraints**\n\nEach of the operands must have scalar type.\n\n**Semantics**\n\nIf either operand does not have type bool, its value is first converted\nto that type. An `int`-based enumeration with value zero is converted to `false`, while a non-zero value is converted to `true`. Likewise, a `string`-based enumeration with value empty string is converted to `false`, while a non-empty value is converted to `true`. (**The validity of allowing this operator to have an enumerated type operand is questionable; avoid such usage lest support for it disappears.**)\n\nGiven the expression `e1 || e2`, `e1` is evaluated first. If `e1` is true, `e2` is not evaluated, and the result has type `bool`, value `true`. Otherwise, `e2` is evaluated. If `e2` is `true`, the result has type `bool`, value `true`; otherwise, it has type `bool`, value `false`. There is a sequence point after the evaluation of `e1`.\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```Hack\nif ($month < 1 || $month > 12) ...\n```\n\n## Conditional Operator\n\n**Syntax**\n\n<pre>\n  <i>conditional-expression:</i>\n    <i>logical-inc-OR-expression</i>\n    <i>logical-inc-OR-expression</i>  ?  <i>expression<sub>opt</sub></i>  :  <i>conditional-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n* [*logical-inc-OR-expression*](10-expressions.md#logical-inclusive-or-operator)\n\n**Semantics**\n\nGiven the expression `e1 ? e2 : e3`, if `e1` is `true`, then and only then is `e2` evaluated, and the result and its type become the result and type of\nthe whole expression. Otherwise, then and only then is `e3` evaluated, and\nthe result and its type become the result and type of the whole\nexpression. There is a sequence point after the evaluation of `e1`. If `e2`\nis omitted, the result and type of the whole expression is the value and\ntype of `e1` when it was tested.\n\nRegarding a left-most operand that is an enumeration, an `int`-based enumeration with value zero is converted to `false`, while a non-zero value is converted to `true`. Likewise, a string-based enumeration with value empty string is converted to `false`, while a non-empty value is converted to `true`. (**The validity of allowing this operator to have an enumerated type as its first operand is questionable; avoid such usage lest support for it disappears.**)\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```Hack\nfor ($i = -5; $i <= 5; ++$i)\n  echo \"$i is \".(($i & 1 == true) ? \"odd\\n\" : \"even\\n\");\n// -----------------------------------------\n$a = 10 ? : \"Hello\";  // result is int with value 10\n$a = 0 ? : \"Hello\";     // result is string with value \"Hello\"\n$i = PHP_INT_MAX;\n$a = $i++ ? : \"red\";  // result is int with value 2147483647 (on a 32-bit\n                // system) even though $i is now the float 2147483648.0\n// -----------------------------------------\n$i++ ? f($i) : f(++$i); // the sequence point makes this well-defined\n// -----------------------------------------\nfunction factorial(int $int): int\n{\n  return ($int > 1) ? $int * factorial($int - 1) : $int;\n}\n```\n\n## Coalesce Operator\n\n**Syntax**\n\n<pre>\n  <i>coalesce-expression:</i>\n    <i>logical-inc-OR-expression</i>  ??  <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n* [*logical-inc-OR-expression*](#logical-inclusive-or-operator)\n\n**Semantics**\n\nGiven the expression `e1 ?? e2`, if `e1` is set and not `null`, then the result is `e1`. Otherwise, then and only then is `e2`\nevaluated, and the result becomes the result of the whole expression. There is a sequence point after the evaluation of `e1`.\n\nThis operator associates right-to-left.\n\n**Examples**\n\n```PHP\nfunction foo(): void {\n  echo \"executed!\", PHP_EOL;\n}\n\nfunction main(): void {\n  $arr = [\"foo\" => \"bar\", \"qux\" => null];\n  $obj = (object)$arr;\n\n  $a = $arr[\"foo\"] ?? \"bang\"; // \"bar\" as $arr[\"foo\"] is set and not null\n  $a = $arr[\"qux\"] ?? \"bang\"; // \"bang\" as $arr[\"qux\"] is null\n  $a = $arr[\"bing\"] ?? \"bang\"; // \"bang\" as $arr[\"bing\"] is not set\n\n  $a = $obj->foo ?? \"bang\"; // \"bar\" as $obj->foo is set and not null\n  $a = $obj->qux ?? \"bang\"; // \"bang\" as $obj->qux is null\n  $a = $obj->bing ?? \"bang\"; // \"bang\" as $obj->bing is not set\n\n  $a = null ?? $arr[\"bing\"] ?? 2; // 2 as null is null, and $arr[\"bing\"] is not set\n  var_dump(true ?? foo()); // outputs bool(true), \"executed!\" does not appear as it short-circuits\n}\n```\n\n## Pipe Operator\n\n**Syntax**\n<pre>\n<i>piped-expression:</i>\n  <i>coalesce-expression</i>\n  <i>piped-expression</i>   |>   <i>coalesce-expression</i>\n</pre>\n\n*coalesce-expression* is defined in [§§](10-expressions.md#coalesce-operator).\n\n**Constraints**\n\n*piped-expression* cannot be used as the right-hand operand of an assignment operator.\n\n*coalesce-expression* must contain at least one occurrence of the pipe variable `$$`.\n\n**Semantics**\n\n*piped-expression* is evaluated with the result being stored in the pipe variable `$$`. There is a sequence point after the evaluation of *piped-expression*. Then *coalesce-expression* is evaluated, and its type and value become the type and value of the result.\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```PHP\nclass Widget { … }\nfunction pipe_operator_example(array<Widget> $arr): int {\n  return $arr\n    |> array_map($x ==> $x->getNumber(), $$)\n    |> array_filter($$, $x ==> $x % 2 == 0)\n    |> count($$);\n}\n```\n\n## Lambda Expressions\n\n**Syntax**\n<pre>\n<i>lambda-expression:</i>\n  <i>piped-expression</i>\n  async<sub>opt</sub>  <i>lambda-function-signature</i>  ==>  <i>lambda-body</i>\n\n<i>lambda-function-signature:</i>\n  <i>variable-name</i>\n  (  <i>anonymous-function-parameter-list<sub>opt</sub></i>  )  <i>anonymous-function-return<sub>opt</sub></i>\n\n<i>lambda-body:</i>\n  <i>expression</i>\n  <i>compound-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*anonymous-function-parameter-list*](10-expressions.md#anonymous-function-creation)\n* [*anonymous-function-return*](10-expressions.md#anonymous-function-creation)\n* [*coalesce-expression*](10-expressions.md#coalesce-operator)\n* [*compound-statement*](11-statements.md#compound-statements)\n* [*conditional-expression*](10-expressions.md#conditional-operator)\n* [*expression*](10-expressions.md#yield-operator)\n* [*piped-expression*](10-expressions.md#pipe-operator)\n* [*variable-name*](09-lexical-structure.md#names)\n\n**Constraints**\n\nEach variable-name in an *anonymous-function-parameter-list* must be distinct.\n\nIf any *anonymous-function-parameter-declaration* has a *default-argument-specifier*, then all subsequent *anonymous-function-parameter-declarations* in the same *anonymous-function-parameter-declaration-list* must also have a *default-argument-specifier*.\n\nIf the *type-specifier* in *anonymous-function-return* is `void`, the *compound-statement* must not contain any [`return` statements](11-statements.md#the-return-statement) having an *expression*. Otherwise, if that *type-specifier* is not omitted, the *expression* in *lambda-body*, or all `return` statements in *compound-statement* must contain an *expression* whose type is a subtype of the type indicated by the return type's *type-specifier*.\n\nIf `async` is present, *return-type* must be a type that implements [`Awaitable<T>`](17-interfaces.md#interface-awaitable).\n\n**Semantics**\n\nA lambda expression is an anonymous function implemented using an operator. In many cases, the lambda-expression version is simpler to writer and easier to read, as is shown in the following:\n\n```Hack\n$doublerl = ($p) ==> $p * 2;\n$doubler2 = function ($p) { return $p * 2; };\n```\n\nLambda expressions automatically capture any variables appearing in their body that also appear in the enclosing lexical function scopes transitively (i.e., nested lambda expressions can refer to variables from several levels out, with intermediate lambda expressions capturing that variable so it can be forwarded to the inner lambda expression). Variables are only captured when they are statically visible as names in the enclosing scope; i.e., the capture list is computed statically, not based on dynamically defined names in the scope. A lambda expression's captured variables are captured with the same by-value semantics that are used for variables in an *anonymous-function-use-clause* of an [*anonymous-function-creation-expression*](10-expressions.md#anonymous-function-creation).\n\nThis operator is right-associative and lambda-expressions can be chained together, allowing expressions of the form `$f = $x ==> $y ==> $x + $y`.\n\nWhen a lambda expression is executed, it creates an object of some, unspecified closure type.\n\nIf the *type-specifier* for a parameter is omitted, that type is inferred.\n\nIf *anonymous-function-return* is omitted, the return type is inferred.\n\nThe anonymous function in a *lambda-expression* can be [asynchronous](15-functions.md#asynchronous-functions).\n\n**Examples**\n\n```Hack\n// returns 73\n$fn = $x ==> $x + 1; $fn(12); // returns 13$fn = () ==> 73; $n();\n$fn = ($a = -1, ...): int ==> $a * 2;\n// -----------------------------------------\n$dump_map = ($name, $x) ==> {\n  echo \"Map $name has:\\n\";\n  foreach ($x as $k => $v) {\n    echo \"  $k => $v\\n\";\n  }\n};\n// -----------------------------------------\n$fn1 = $x ==> $y ==> $x + $y;\n$fn2 = $fn1(10); $res = $fn2(7);  // result is 17\n```\n\n## Assignment Operators\n\n### General\n\n**Syntax**\n\n<pre>\n  <i>assignment-expression:</i>\n    <i>lambda-expression</i>\n    <i>simple-assignment-expression</i>\n    <i>compound-assignment-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*compound-assignment-expression*](10-expressions.md#compound-assignment)\n* [*lambda-expression*](10-expressions.md#lambda-expressions)\n* [*simple-assignment-expression*](10-expressions.md#simple-assignment)\n\n**Constraints**\n\nThe left-hand operand of an assignment operator must be a modifiable\nlvalue.\n\n**Semantics**\n\nThese operators associate right-to-left.\n\n### Simple Assignment\n\n**Syntax**\n\n<pre>\n  <i>simple-assignment-expression:</i>\n    <i>unary-expression</i>  =  <i>assignment-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*assignment-expression*](10-expressions.md#general-5)\n* [*unary-expression*](10-expressions.md#general-4)\n\n**Constraints**\n\nIf the location designated by the left-hand operand is a string element,\nthe key must not be a negative-valued `int`, and the right-hand operand\nmust have type `string`.\n\nIf *unary-expression* is a [*subscript-expression*](10-expressions.md#subscript-operator) whose *postfix-expression* designates a vector-like array and whose *expression* is present, if *expression* designates a non-existent element, the behavior is unspecified.\n\nIf *unary-expression* is a *subscript-expression* whose *postfix-expression* designates a `Map` and whose *expression* is omitted, *assignment-expression* must designate a `Pair`.\n\n\n**Semantics**\n\nIf *assignment-expression* designates an expression having value type,\nsee [§§](04-basic-concepts.md#value-assignment-of-scalar-types-to-a-local-variable). If *assignment-expression*\ndesignates an expression having a handle, see [§§](04-basic-concepts.md#byref-assignment-for-scalar-types-with-local-variables). If\n*assignment-expression* designates an expression having array type, see\n[§§](04-basic-concepts.md#value-assignment-of-array-types-to-local-variables). If *assignment-expression* designates an expression having a shape type, it is treated as if it had array type.\n\nThe type and value of the result is the type and value of the left-hand\noperand after the store (if any [see below]) has taken place. The result\nis not an lvalue.\n\nIf the location designated by the left-hand operand is a non-existent\narray element, a new element is inserted with the designated key and\nwith a value being that of the right-hand operand.\n\nIf the location designated by the left-hand operand is a string element,\nthen if the key is a negative-valued `int`, there is no side effect.\nOtherwise, if the key is a non-negative-valued `int`, the left-most single\ncharacter from the right-hand operand is stored at the designated\nlocation; all other characters in the right-hand operand string are\nignored.  If the designated location is beyond the end of the\ndestination string, that string is extended to the new length with\nspaces (U+0020) added as padding beyond the old end and before the newly\nadded character. If the right-hand operand is an empty string, the null\ncharacter \\\\0 (U+0000) is stored.\n\n**Examples**\n\n```Hack\n$a = $b = 10    // equivalent to $a = ($b = 10)\n$v = array(10, 20, 30);\n$v[-10] = 19;   // insert a new element with int key -10\n$s = \"red\";\n$s[1] = \"X\";    // OK; \"e\" -> \"X\"\n$s[-5] = \"Y\";   // warning; string unchanged\n$s[5] = \"Z\";    // extends string with \"Z\", padding with spaces in [3]-[5]\n$s = \"red\";\n$s[0] = \"DEF\";  // \"r\" -> \"D\"; only 1 char changed; \"EF\" ignored\n$s[0] = \"\";     // \"D\" -> \"\\0\"\n$s[\"zz\"] = \"Q\"; // warning; defaults to [0], and \"Q\" is stored there\n// -----------------------------------------\nclass C { … }\n$a = new C();   // make $a point to the allocated object  \n```\n\n### Compound Assignment\n\n**Syntax**\n\n<pre>\n  <i>compound-assignment-expression:</i>\n    <i>unary-expression   compound-assignment-operator   assignment-expression</i>\n\n  <i>compound-assignment-operator: one of</i>\n    **=  *=  /=  %=  +=  -=  .=  &lt;&lt;=  >>=  &amp;=  ^=  |=\n</pre>\n\n**Defined elsewhere**\n\n* [*assignment-expression*](10-expressions.md#general-5)\n* [*unary-expression*](10-expressions.md#general-4)\n\n**Constraints**\n\nAny constraints that apply to the corresponding postfix or binary\noperator apply to the compound-assignment form as well.\n\n**Semantics**\n\nThe expression `e1 op= e2` is equivalent to `e1 = e1 op (e2)`, except\nthat `e1` is evaluated once only.\n\n**Examples**\n\n```Hack\n$v = 10;\n$v += 20;   // $v = 30\n$v -= 5;    // $v = 25\n$v .= 123.45  // $v = \"25123.45\"\n$a = [100, 200, 300];\n$i = 1;\n$a[$i++] += 50; // $a[1] = 250, $i → 2\n```\n\n## `yield` Operator\n\n**Syntax**\n\n<pre>\n  <i>expression:</i>\n    <i>assignment-expression</i>\n    yield  <i>array-element-initializer</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*array-element-initializer*](#array-creation-operator)\n* [*assignment-expression*](10-expressions.md#general-5)\n\n**Constraints**\n\n`yield` must not be used inside an [async function, method, or closure](15-functions.md#asynchronous-functions).\n\n**Semantics**\n\nAny function containing a yield operator is a *generator function*.\nA generator function generates a collection of zero or more key/value\npairs where each pair represents the next in some series. For example, a\ngenerator might *yield* random numbers or the series of Fibonacci\nnumbers. When a generator function is called explicitly, it returns an\nobject of type `Generator` (see below and [§§](16-classes.md#class-generator)), which implements the interface\n[`Iterator`](15-interfaces.md#interface-iterator). As such, this allows that object to be iterated over\nusing the [`foreach` statement](11-statements.md#the-foreach-statement). During each iteration, the Engine\ncalls the generator function implicitly to get the next key/value pair.\nThen the Engine saves the state of the generator for subsequent\nkey/value pair requests.\n\nThis operator produces the result `null` unless the method\n[`Generator->send`](16-classes.md#class-generator) was called to provide a result value. This\noperator has the side effect of generating the next value in the\ncollection.\n\nBefore being used, an *element-key* must have, or be converted to, type\n`int` or `string`. Keys with `float` or `bool` values, or strings whose contents\nmatch exactly the pattern of [*decimal-literal*](09-lexical-structure.md#integer-literals), are\n[converted to `int`](08-conversions.md#converting-to-integer-type). Values of all other key types are [converted to `string`](08-conversions.md#converting-to-string-type).\n\nIf *element-key* is omitted from an *array-element-initializer*, an\nelement key of type `int` is associated with the corresponding\n*element-value*. The key associated is one more than the previously\nassigned int key for this collection. However, if this is the first\nelement in this collection with an `int` key, key zero is used. If\n*element-key* is provided, it is associated with the corresponding\n*element-value*. The resulting key/value pair is made available by\n`yield`.\n\nIf *array-element-initializer* is omitted, default int-key assignment is\nused and each value is `null`.\n\nA generator function's return type is `Generator<Tk, Tv, Ts>`, where `Tk` is the type of \"key\" (must be `int` if there is no key), `Tv` is the type of \"value\", and \"`?Ts`\" is the result of the entire yield expression. `Continuation<T>` is an alias for `Generator<int, T, void>`; the two are interchangeable. For a generator function that always returns a single value of the same type `T`, declare the return type as `Continuation<T>`.\n\n**Examples**\n\n```Hack\nfunction getTextFileLines(string $filename): Continuation<string> {\n  $infile = fopen($filename, 'r');\n  if ($infile == false) { /* deal with the file-open failure */ }\n\n  try {\n    while ($textLine = fgets($infile))  // while not EOF {\n      $textLine = rtrim($textLine, \"\\r\\n\"); // strip off terminator\n      yield $textLine;\n    }\n  } finally {\n    fclose($infile);\n  }\n}\nforeach (getTextFileLines(\"Testfile.txt\") as $line) { /* process each line */ }\n// -----------------------------------------\nfunction series(int $start, int $end, string $keyPrefix = \"\"):\n  Generator<string, int, void> {\n  for ($i = $start; $i <= $end; ++$i) {\n    yield $keyPrefix . $i => $i;  // generate a key/value pair\n  }\n}\nforeach (series(1, 5, \"X\") as $key => $val) { /* process each key/val pair */ }\n```\n\n## Constant Expressions\n\n**Syntax**\n\n<pre>\n  <i>constant-expression:</i>\n    <i>array-creation-expression</i>\n    <i>collection-literal</i>\n    <i>tuple-literal</i>\n    <i>shape-literal</i>\n    <i>const-expression</i>\n\n  <i>const-expression:</i>\n    <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*array-creation-expression*](10-expressions.md#array-creation-operator)\n* [*collection-literal*](10-expressions.md#collection-literals)\n* [*expression*](10-expressions.md#yield-operator)\n* [*shape-literal*](10-expressions.md#shape-literals)\n* [*tuple-literal*](10-expressions.md#tuple-literals)\n\n**Constraints:**\n\nAll of the *element-key* and *element-value* *expression*s in\n[*array-creation-expression*](10-expressions.md#array-creation-operator) must be [*literals*](09-lexical-structure.md#general-2), or *tuple-literals* and/or *shape-literals* containing only *literals*.\n\nAll of the *expression*s in a *collection-literal* must be *literals*.\n\nAll of the *expression*s in *tuple-literal* must be *literals*.\n\nAll of the *expression*s in *shape-literal* must be *literals*.\n\n*expression* must have a scalar type, and be a literal or the name of an\nexisting [c-constant](06-constants.md#general) that is currently in scope.\n\n**Semantics:**\n\nA *const-expression* is the value of a c-constant. A *const-expression*\nis required in several contexts, such as in initializer values in a\n[*const-declaration*](16-classes.md#constants) and default initial values in a [function\ndefinition](15-functions.md#function-definitions).\n"
  },
  {
    "path": "spec/11-statements.md",
    "content": "# Statements\n\n## General\n\n**Syntax**\n\n<pre>\n  <i>statement:</i>\n    <i>function-static-declaration</i>\n    <i>compound-statement</i>\n    <i>labeled-statement</i>\n    <i>expression-statement</i>\n    <i>selection-statement</i>\n    <i>iteration-statement</i>\n    <i>jump-statement</i>\n    <i>try-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*compound-statement*](#compound-statements)\n* [*expression-statement*](#expression-statements)\n* [*function-static-declaration*](07-variables.md#function-statics)\n* [*iteration-statement*](#general-2)\n* [*jump-statement*](#general-3)\n* [*labeled-statement*](#labeled-statements)\n* [*selection-statement*](#general-1)\n* [*try-statement*](11-statements.md#the-try-statement)\n\n## Compound Statements\n\n**Syntax**\n\n<pre>\n  <i>compound-statement:</i>\n    {  <i>statement-list<sub>opt</sub></i>  }\n\n  <i>statement-list:</i>\n    <i>statement</i>\n    <i>statement-list   statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*statement*](#general)\n\n**Semantics**\n\nA *compound statement* allows a group of zero or more statements to be\ntreated syntactically as a single statement. A compound statement is\noften referred to as a *block*.\n\n**Examples**\n\n```Hack\nif (condition)\n{\t// braces are needed as the true path has more than one statement\n\t// statement-1\n\t// statement-2\n}\nelse\n{\t// braces are optional as the false path has only one statement\n\t// statement-3\n}\n// -----------------------------------------\nwhile (condition)\n{\t// the empty block is equivalent to a null statement\n}\n```\n\n## Labeled Statements\n\n**Syntax**\n\n<pre>\n  <i>labeled-statement:</i>\n    <i>case-label</i>\n    <i>default-label</i>\n\n  <i>case-label:</i>\n    case   <i>expression</i>  :  <i>statement</i>\n\n  <i>default-label:</i>\n    default  :  <i>statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n* [*statement*](#general)\n\n**Constraints**\n\n*case-label* and *default-label* must only occur inside a [`switch` statement](#the-switch-statement).\n\n**Semantics**\n\nSee the `switch` statement.\n\n## Expression Statements\n\n**Syntax**\n\n<pre>\n   <i>expression-statement:</i>\n     <i>expression<sub>opt</sub></i>  ;\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Semantics**\n\nIf present, *expression* is evaluated for its side effects, if any, and\nany resulting value is discarded. If *expression* is omitted, the\nstatement is a *null statement*, which has no effect on execution.\n\n**Examples**\n\n```Hack\n$i = 10;  // $i is assigned the value 10; result (10) is discarded\n++$i; // $i is incremented; result (11) is discarded\n$i++; // $i is incremented; result (11) is discarded\nDoIt(); // function DoIt is called; result (return value) is discarded\n// -----------------------------------------\n$i;   // no side effects, result is discarded. Vacuous but permitted\n123;  // likewise for this one and the two statements following\n34.5 * 12.6 + 11.987;\ntrue;\n```\n\n## Selection Statements\n\n### General\n\n**Syntax**\n\n<pre>\n  <i>selection-statement:</i>\n    <i>if-statement</i>\n    <i>switch-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*if-statement*](#the-if-statement)\n* [*switch-statement*](#the-switch-statement)\n\n**Semantics**\n\nBased on the value of a controlling expression, a selection statement\nselects among a set of statements.\n\n### The `if` Statement\n\n**Syntax**\n\n<pre>\n  <i>if-statement:</i>\n    if   (   <i>expression</i>   )   <i>statement   elseif-clauses-opt   else-clause-opt</i>\n\n  <i>elseif-clauses:</i>\n    <i>elseif-clause</i>\n    <i>elseif-clauses   elseif-clause</i>\n\n  <i>elseif-clause:</i>\n    elseif   (   <i>expression</i>   )   <i>statement</i>\n\n  <i>else-clause:</i>\n    else   <i>statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n* [*statement*](#general)\n\n**Constraints**\n\nThe controlling expression *expression* must have type `bool` or be\nimplicitly convertible to that type.\n\n**Semantics**\n\nThe two forms of the `if` statement are equivalent; they simply provide\nalternate styles.\n\nIf *expression* tests `true`, the *statement* that follows immediately is\nexecuted. Otherwise, if an `elseif` clause is present the *statement*\nimmediately following the `elseif` is executed. Otherwise, any other\n`elseif` *expression*s are evaluated. If none of those tests `true`, if an\n`else` clause is present the *statement* immediately following the `else` is\nexecuted.\n\nAn `else` clause is associated with the lexically nearest preceding `if` or\n`elseif` that is permitted by the syntax.\n\n**Examples**\n```Hack\nif ($count > 0) {\n  …\n} else {\n  …\n}\n// -----------------------------------------\nif (1)\n  …\n  if (0)\n    …\nelse  // this else does NOT go with the outer if\n  …\n\nif (1) {\n  …\n  if (0)\n    …\n} else  // this else does go with the outer if\n  …\n```\n\n### The `switch` Statement\n\n**Syntax**\n\n<pre>\n  <i>switch-statement:</i>\n    switch  (  <i>expression</i>  )  <i>compound-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*compound-statement*](#compound-statements)\n* [*expression*](10-expressions.md#yield-operator)\n\n**Constraints**\n\nThe controlling expression *expression* must have scalar type.\n\nThere must be at most one default label.\n\nEach label expression's type must be a subtype of the switch *expression* type.\n\nThe compound statement may be empty; if it is not, then the first statement in \nit must be a labeled statement.\n\n**Semantics**\n\nBased on the value of its *expression*, a `switch` statement transfers\ncontrol to a [case label](#labeled-statements); to a [default label](#labeled-statements), if one\nexists; or to the statement immediately following the end of the `switch`\nstatement. A case or default label is only reachable directly within its\nclosest enclosing `switch` statement.\n\nOn entry to the `switch` statement, the controlling expression is\nevaluated and then compared with the value of the case-label-expression\nvalues, in lexical order. If one matches, control transfers to the\nstatement following the corresponding case label. If there is no match,\nthen if there is a default label, control transfers to the statement\nfollowing that; otherwise, control transfers to the statement\nimmediately following the end of the `switch` statement. If a `switch`\ncontains more than one case label whose values compare equal to the\ncontrolling expression, the first in lexical order is considered the\nmatch.\n\nAn arbitrary number of statements can be associated with any case or\ndefault label. In the absence of a [`break` statement](11-statements.md#the-break-statement) at the end\nof a set of such statements, control drops through into any following\ncase or default label. Thus, if all cases and the default end in break\nand there are no duplicate-valued case labels, the order of case and\ndefault labels is insignificant.\n\nIn no break *statement* is seen for a case or default before a subsequent case label, default label, or the switch-terminating `}` is encountered, an implementation might issue a warning. However, such a warning can be suppressed by placing a source line containing the special comment [`// FALLTHROUGH`](09-lexical-structure.md#comments), at the end of that case or default statement group.\n\nCase-label values can be runtime expressions, and the types of sibling\ncase-label values need not be the same.\n\nSwitches may be nested, in which case, each `switch` has its own set of\n`switch` clauses.\n\n**Examples**\n\n```Hack\n$v = 10;\nswitch ($v) {\ndefault:\n  echo \"default case: \\$v is $v\\n\";\n  break;    // break ends \"group\" of default statements\ncase 20:\n  echo \"case 20\\n\";\n  break;    // break ends \"group\" of case 20 statements\ncase 10:\n  echo \"case 10\\n\"; // no break, so control drops into next label's \"group\"\n  // FALLTHROUGH\ncase 30:\n  echo \"case 30\\n\"; // no break, but then none is really needed either\n}\n// -----------------------------------------\n$v = 30;\nswitch ($v) {\ncase 30.0:  // <===== this case matches with 30\n  echo \"case 30.0\\n\";\n  break;\ndefault:\n  echo \"default case: \\$v is $v\\n\";\n  break;\ncase 30:    // <===== rather than this case matching with 30\n  echo \"case 30\\n\";\n  break;\n}\n// -----------------------------------------\nenum ControlStatus: int {\n  Stopped = 0;\n  Stopping = 1;\n  Starting = 2;\n  Started = 3;\n}\n…\nswitch ($p1) {\ncase ControlStatus::Stopped:\n  echo \"Stopped: $p1\\n\";\n  break;\n…\ncase ControlStatus::Started:\n  echo \"Started: $p1\\n\";\n  break;\n}\n```\n\n## Iteration Statements\n\n### General\n\n**Syntax**\n\n<pre>\n  <i>iteration-statement:</i>\n    <i>while-statement</i>\n    <i>do-statement</i>\n    <i>for-statement</i>\n    <i>foreach-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*do-statement*](#the-do-statement)\n* [*for-statement*](#the-for-statement)\n* [*foreach-statement*§](#the-foreach-statement)\n* [*while-statement*](#the-while-statement)\n\n### The `while` Statement\n\n**Syntax**\n\n<pre>\n  <i>while-statement:</i>\n    while  (  <i>expression</i>  )  <i>statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n* [*statement*](#general)\n\n**Constraints**\n\nThe controlling expression *expression* must have type `bool` or be\nimplicitly convertible to that type.\n\n**Semantics**\n\nIf *expression* tests `true`, the *statement* that follows immediately is\nexecuted, and the process is repeated. If *expression* tests `false`,\ncontrol transfers to the point immediately following the end of the\n`while` statement. The loop body, *statement*, is executed zero or more\ntimes.\n\n**Examples**\n\n```Hack\n$i = 1;\nwhile ($i <= 10) {\n  echo \"$i\\t\".($i * $i).\"\\n\"; // output a table of squares\n  ++$i;\n}\n// -----------------------------------------\nwhile (true) {\n  …\n  if ($done)\n    break;  // break out of the while loop\n  …\n}\n```\n\n### The `do` Statement\n\n**Syntax**\n\n<pre>\n  <i>do-statement:</i>\n    do  <i>statement</i>  while  (  <i>expression</i>  )  ;\n</pre>\n\n**Defined elsewhere**\n\n* [*statement*](#general)\n* [*expresion*](10-expressions.md#yield-operator)\n\n(Note: There is no `:/enddo` alternate syntax.)\n\n**Constraints**\n\nThe controlling expression *expression* must have type `bool` or be\nimplicitly convertible to that type.\n\n**Semantics**\n\nFirst, *statement* is executed and then *expression* is tested. If its\nvalue is `true`, the process is repeated. If *expression* tests `false`,\ncontrol transfers to the point immediately following the end of the `do`\nstatement. The loop body, *statement*, is executed one or more times.\n\n**Examples**\n\n```Hack\n$i = 1;\ndo {\n  echo \"$i\\t\".($i * $i).\"\\n\"; // output a table of squares\n  ++$i;\n}\nwhile ($i <= 10);\n```\n\n### The `for` Statement\n\n**Syntax**\n\n<pre>\n  <i>for-statement:</i>\n    for   (   <i>for-initializeropt</i>   ;   <i>for-controlopt</i>   ;   <i>for-end-of-loopopt</i>   )   <i>statement</i>\n\n  <i>for-initializer:</i>\n    <i>for-expression-group</i>\n\n  <i>for-control:</i>\n    <i>for-expression-group</i>\n\n  <i>for-end-of-loop:</i>\n    <i>for-expression-group</i>\n\n  <i>for-expression-group:</i>\n    <i>expression</i>\n    <i>for-expression-group</i>   ,   <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n* [*statement*](#general)\n\nNote: Unlike C/C++, Hack does not support a comma operator, per se.\nHowever, the syntax for the `for` statement has been extended from that of\nC/C++ to achieve the same results in this context.\n\n**Constraints**\n\nThe controlling expression—the right-most *expression* in\n*for-control*—must have type `bool` or be implicitly convertible to that\ntype.\n\n**Semantics**\n\nThe group of expressions in *for-initializer* is evaluated once,\nleft-to-right, for their side effects. Then the group of expressions in\n*for-control* is evaluated left-to-right (with all but the right-most\none for their side effects only), with the right-most expression's value\nbeing tested. If that tests `true`, *statement* is executed, and the group\nof expressions in *for-end-of-loop* is evaluated left-to-right, for\ntheir side effects only. Then the process is repeated starting with\n*for-control*. If the right-most expression in *for-control* tests\n`false`, control transfers to the point immediately following the end of\nthe `for` statement. The loop body, *statement*, is executed zero or more\ntimes.\n\nIf *for-initializer* is omitted, no action is taken at the start of the\nloop processing. If *for-control* is omitted, this is treated as if\n*for-control* was an expression with the value `true`. If\n*for-end-of-loop* is omitted, no action is taken at the end of each\niteration.\n\n**Examples**\n\n```Hack\nfor ($i = 1; $i <= 10; ++$i) {\n  echo \"$i\\t\".($i * $i).\"\\n\"; // output a table of squares\n}\n// -----------------------------------------\n// omit 1st and 3rd expressions\n\n$i = 1;\nfor (; $i <= 10;) {\n  echo \"$i\\t\".($i * $i).\"\\n\"; // output a table of squares\n  ++$i;\n}\n// -----------------------------------------\n// omit all 3 expressions\n\n$i = 1;\nfor (;;) {\n  if ($i > 10)\n    break;\n  echo \"$i\\t\".($i * $i).\"\\n\"; // output a table of squares\n  ++$i;\n}\n// -----------------------------------------\n//  use groups of expressions\n\nfor ($a = 100, $i = 1; ++$i, $i <= 10; ++$i, $a -= 10) {\n  echo \"$i\\t$a\\n\";\n}\n```\n\n### The `foreach` Statement\n\n**Syntax**\n\n<pre>\n  <i>foreach-statement:</i>\n    foreach  (  <i>foreach-collection-name</i>  as  <i>foreach-key<sub>opt</sub>  foreach-value</i>  )   <i>statement</i>\n    foreach  (  <i>foreach-collection-name</i>  await as  <i>foreach-key<sub>opt</sub>  foreach-value</i>  )   <i>statement</i>\n\n  <i>foreach-collection-name</i>:\n    <i>expression</i>\n\n  <i>foreach-key:</i>\n    <i>expression</i>  =>\n\n  <i>foreach-value:<i>\n    <i>expression</i>\n    <i>list-intrinsic</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n* [*list-intrinsic*](10-expressions.md#list)\n* [*statement*](#general)\n\n**Constraints**\n\nThe variable designated by *foreach-collection-name* must be a\ncollection.\n\nEach *expression* must designate a variable name.\n\nFor the “await as” form, the type of *foreach-collection-name* must implement interface [`AsyncIterator`](17-interfaces.md#interface-AsyncIterator) or interface [`AsyncKeyedIterator`](17-interfaces.md#interface-AsyncKeyedIterator).\n\n**Semantics**\n\nThe *foreach* statement iterates over the set of elements in the\ncollection designated by *foreach-collection-name*, starting at the\nbeginning, executing *statement* each iteration. On each iteration, the value of the current element is assigned to the\ncorresponding variable designated by *foreach-value*, provided *foreach-value*’s *expression* is not ([`$_`](§09-lexical-structure.md#names); otherwise, the value of the current element is ignored. The loop body, *statement*, is executed zero or\nmore times.\n\nIf *foreach-key* is present and its *expression* is `$_`, the current element's key value is ignored. If *foreach-key* is present and *expression* is not `$_`,  the variable designated by its *expression*\nis assigned the current element's key value.\n\nIn the *list-intrinsic* case, a value that is an array is split into\nindividual elements.\n\n**Examples**\n\n```Hack\n$colors = array(\"red\", \"white\", \"blue\");\nforeach ($colors as $color) {\n   …\n};\n// -----------------------------------------\nforeach ($colors as $key => $color) {\n  …\n}\n// -----------------------------------------\n// Modify the local copy of an element's value\n\nforeach ($colors as $color) {\n  $color = \"black\";\n}\n// -----------------------------------------\n  $a = array('a' => 10, 'f' => 30);\n  foreach ($a as $key => $_) { // 10 and 30 are ignored\n    …\n  }\n// -----------------------------------------\nasync function countdown1(int $start): AsyncIterator<int> {\n  for ($i = $start; $i >= 0; --$i) {\n    await \\HH\\Asio\\usleep(1000000); // Sleep for 1 second\n    yield $i;\n  }\n}\n\nasync function use_countdown1(): Awaitable<void> {\n  $async_gen = countdown1(3);\n  foreach ($async_gen await as $value) {\n    // $value is of type int here\n    // …\n  }\n}\n\nasync function countdown2(int $start): AsyncKeyedIterator<int, string> {\n  for ($i = $start; $i >= 0; --$i) {\n    await \\HH\\Asio\\usleep(1000000);\n    yield $i => (string)$i;\n  }\n}\n\nasync function use_countdown2(): Awaitable<void> {\n  foreach (countdown2(3) await as $num => $str) {\n    // $num is of type int, $str is of type string\n    // …\n  }\n}\n```\n\n## Jump Statements\n\n### General\n\n**Syntax**\n\n<pre>\n  <i>jump-statement:</i>\n    <i>continue-statement</i>\n    <i>break-statement</i>\n    <i>return-statement</i>\n    <i>throw-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*break-statement*](#the-break-statement)\n* [*continue-statement*](#the-continue-statement)\n* [*return-statement*](#the-return-statement)\n* [*throw-statement*](#the-throw-statement)\n\n### The `continue` Statement\n\n**Syntax**\n\n<pre>\n  <i>continue-statement:</i>\n    continue  ;\n</pre>\n\n**Constraints**\n\nA `continue` statement must not attempt to break out of a [finally-block](#the-try-statement).\n\n**Semantics**\n\nA `continue` statement terminates the execution of the innermost enclosing\n[iteration](#iteration-statements) or [`switch`](#the-switch-statement) statement.\n\nA `continue` statement may break out of a construct that is fully\ncontained within a finally-block.\n\n**Examples**\n\n```Hack\nfor ($i = 1; $i <= 5; ++$i) {\n  if (($i % 2) == 0)\n    continue;\n  echo \"$i is odd\\n\";\n}\n```\n\n### The `break` Statement\n\n**Syntax**\n\n<pre>\n  <i>break-statement:</i>\n    break  ;\n</pre>\n\n**Constraints**\n\nA `break` statement must not attempt to break out of a [finally-block](#the-try-statement).\n\n**Semantics**\n\nA `break` statement terminates the execution of one or more enclosing\n[iteration](#iteration-statements) or [`switch`](#the-switch-statement) statements.\n\nA `break` statement may break out of a construct that is fully contained\nwithin a finally-block.\n\n**Examples**\n\n```Hack\n$i = 1;\nfor (;;) {\n  if ($i > 10)\n    break;\n  …\n  ++$i;\n}\n```\n\n### The `return` Statement\n\n**Syntax**\n\n<pre>\n  <i>return-statement:</i>\n    return  <i>expression<sub>opt</sub></i>  ;\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Constraints**\n\nThe *expression* in a *return-statement* in a [generator function](10-expressions.md#yield-operator) must be the literal `null`.\n\nA `return` statement must not occur in a [finally-block](11-statements.md#the-try-statement) or in the *compound-statement* of a *function-definition* for a function with [*return-type* `noreturn`](15-functions.md#function-definitions).\n\nFor a non-async function, the type of *expression* (or any implicitly returned `null`) must be assignment-compatible with the return type of the [enclosing function](15-functions.md#function-definitions). For an async function, the type of *expression* must be a subtype of the parameter type of the `Awaitable` *return-type* for the enclosing function. However, if `Awaitable`’s parameter type is `void`, *expression* must be omitted.\n\n**Semantics**\n\nA `return` statement from within a function terminates the execution of that function normally. If *expression* is omitted, for a non-async function, no value is returned. For a sync function, an object of type `Awaitable<void>` is returned. If *expression* is present, for a non-async function, the value of *expression* is returned by value. For a sync function, the value of expression is wrapped in an object of type `Awaitable<T>` (where `T` is the type of *expression*), which is returned.\n\nIf execution flows into the closing brace (`}`) of a function, `return;` is implied.\n\nA function may have any number of `return` statements, whose returned\nvalues may have different types.\n\nA `return` statement is permitted in a [try-block](#the-try-statement) and a [catch-block](#the-try-statement).\n\nReturning from a constructor or destructor behaves just like returning\nfrom a function having a return type of `void`.\n\nA `return` statement inside a generator function causes the generator to\nterminate.\n\nReturn statements can be used in the body of anonymous functions.\n\n**Examples**\n\n```Hack\nfunction f(): int { return 100; } // f explicitly returns a value\nfunction h(): void { }    // h implicitly returns null\n// -----------------------------------------\n// j returns one of three dissimilarly-typed values\nfunction j(int $x): mixed {\n  if ($x > 0) {\n    return \"Positive\";\n  } else if ($x < 0) {\n    return -1;\n  }\n  // for zero, implied return null\n}\n// -----------------------------------------\nclass Point {\n  private static int $pointCount = 0;\n  public static function getPointCount(): int {\n    return self::$pointCount;\n  }\n  …\n}\n```\n\n**Implementation Notes**\n\nAlthough *expression* is a [full expression](10-expressions.md#general), and there is a\n[sequence point](10-expressions.md#general) at the end of that expression, as stated in\n[§§](10-expressions.md#general), a side effect need not be executed if it can be decided that\nno other program code relies on its having happened. (For example, in\nthe cases of `return $a++;` and `return ++$a;`, it is obvious what value\nmust be returned in each case, but if `$a` is a variable local to the\nenclosing function, `$a` need not actually be incremented.\n\n### The `throw` Statement\n\n**Syntax**\n\n<pre>\n  <i>throw-statement:</i>\n    throw  <i>expression</i>  ;\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Constraints**\n\nThe type of *expression* must be [[\\Exception](19-exception-handling.md#class-exception) or a subclass of that\nclass.\n\n*expression* must be such that an alias to it can be created. \n\n**Semantics**\n\nA `throw` statement throws an exception immediately and unconditionally.\nControl never reaches the statement immediately following the throw. See\n[§§](19-exception-handling.md#general) and [§§](#the-try-statement) for more details of throwing and catching exceptions,\nand how uncaught exceptions are dealt with.\n\nRather than handle an exception, a catch-block may (re-)throw the same\nexception that it caught, or it can throw an exception of a different\ntype.\n\n**Examples**\n\n```Hack\nthrow new Exception;\nthrow new Exception(\"Some message\", 123);\nclass MyException extends Exception { ... }\nthrow new MyException;\n```\n\n## The `try` Statement\n\n**Syntax**\n\n<pre>\n  <i>try-statement:</i>\n    try  <i>compound-statement   catch-clauses</i>\n    try  <i>compound-statement   finally-clause</i>\n    try  <i>compound-statement   catch-clauses   finally-clause</i>\n\n  <i>catch-clauses:</i>\n    <i>catch-clause</i>\n    <i>catch-clauses   catch-clause</i>\n\n  <i>catch-clause:</i>\n    catch  (  <i>type-specifier</i>  <i>variable-name</i>  )  <i>compound-statement</i>\n\n  <i>finally-clause:</i>\n    finally   <i>compound-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*compound-statement*](#compound-statements)\n* [*type-specifier*](05-types.md#general).\n* [*variable-name*](09-lexical-structure.md#names)\n\n**Constraints**\n\nIn a *catch-clause* the type referred to by the *type-specifier* \nmust be [`\\Exception`](19-exception-handling.md#class-exception) or a type derived from\nthat class.\n\n**Semantics**\n\nIn a *catch-clause*, the *variable-name* designates an *exception variable*\npassed in by value. This variable corresponds to a local variable with a\nscope that extends over the catch-block. During execution of the\ncatch-block, the exception variable represents the exception currently\nbeing handled.\n\nOnce an exception is thrown, the Engine searches for the nearest\ncatch-block that can handle the exception. The process begins at the\ncurrent function level with a search for a try-block that lexically\nencloses the throw point. All catch-blocks associated with that\ntry-block are considered in lexical order. If no catch-block is found\nthat can handle the run-time type of the exception, the function that\ncalled the current function is searched for a lexically enclosing\ntry-block that encloses the call to the current function. This process\ncontinues until a catch-block is found that can handle the current\nexception. \n\nIf a matching catch-block is located, the Engine prepares to transfer\ncontrol to the first statement of that catch-block. However, before\nexecution of that catch-block can start, the Engine first executes, in\norder, any finally-blocks associated with try-blocks nested more deeply\nthan the one that caught the exception. \n\nIf no matching catch-block is found, the behavior is\nimplementation-defined.\n\n**Examples**\n\n```Hack\nfunction getTextLines(string $filename): Continuation<string> {\n  $infile = fopen($filename, 'r');\n  if ($infile == false) { /* deal with an file-open failure */ }\n  try {\n    while ($textLine = fgets($infile)) {  // while not EOF\n      yield $textLine;  // leave line terminator attached\n    }\n  } finally {\n    fclose($infile);\n  }\n}\n// -----------------------------------------\nclass DeviceException extends Exception { … }\nclass DiskException extends DeviceException { … }\nclass RemovableDiskException extends DiskException { … }\nclass FloppyDiskException extends RemovableDiskException { … }\n\ntry {\n  process(); // call a function that might generate a disk-related exception\n}\ncatch (FloppyDiskException $fde) { … }\ncatch (RemovableDiskException $rde) { … }\ncatch (DiskException $de) { … }\ncatch (DeviceException $dve) { … }\nfinally { … }\n```\n"
  },
  {
    "path": "spec/12-script-inclusion.md",
    "content": "# Script Inclusion Operators\n\n## General\n\n**Syntax**\n\n<pre>\n  <i>inclusion-directive:</i>\n    <i>require-multiple-directive</i>\n    <i>require-once-directive</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*require-multiple-directive*](12-script-inclusion.md#the-require-directive)\n* [*require-once-directive*](12-script-inclusion.md#the-require_once-directive)\n\n**Semantics:**\n\nWhen creating large applications or building component libraries, it is\nuseful to be able to break up the source code into small, manageable\npieces each of which performs some specific task, and which can be\nshared somehow, and tested, maintained, and deployed individually. For\nexample, a programmer might define a series of useful constants and use\nthem in numerous and possibly unrelated applications. Likewise, a set of\nclass definitions can be shared among numerous applications needing to\ncreate objects of those types.\n\nAn *include file* is a script that is suitable for *inclusion* by\nanother script. The script doing the including is the *including file*,\nwhile the one being included is the *included file*. A script can be an\nincluding file and an included file, either, or neither.\n\nIt is important to understand that unlike the C/C++ (or similar)\npreprocessor, script inclusion in PHP is not a text substitution\nprocess. That is, the contents of an included file are not treated as if\nthey directly replaced the inclusion operation source in the including\nfile.\n\nThe name used to specify an include file may contain an absolute or\nrelative path. In the latter case, an implementation may use the\nconfiguration directive\n[`include_path`](http://docs.hhvm.com/manual/en/ini.core.php#ini.include-path)\nto resolve the include file's location.\n\n## The `require` Directive\n\n**Syntax**\n\n<pre>\n<i>require-multiple-directive:</i>\n  require  <i>include-filename</i>  ;\n\n<i>include-filename:</i>\n  <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*expression*](10-expressions.md#yield-operator)\n\n**Constraints**\n\n*expression* must be a string that designates a file that exists, is accessible, and whose format is suitable for inclusion (that is, starts with a [Hack start-tag](04-basic-concepts.md#program-structure)).\n\n**Semantics:**\n\nIf the designated file is not accessible, execution is terminated.\n\nVariables defined in an included file take on scope of the source line on which the inclusion occurs in the including file. However, functions and classes defined in the included file are given global scope.\n\nThe library function [`get_included_files`](http://www.php.net/get_included_files) provides the names of\nall files included or required.\n\n**Examples**\n\n```Hack\nrequire 'Point.php';\nrequire ('Circle.php');\n```\n\n## The `require_once` Directive\n\n**Syntax**\n\n<pre>\n  <i>require-once-directive:</i>\n    require_once  <i>include-filename</i>  ;\n</pre>\n\n**Defined elsewhere**\n\n* [*include-filename*](12-script-inclusion.md#the-require-directive)\n\n**Semantics:**\n\nThis operator is identical to operator [`require`](12-script-inclusion.md#the-require-directive) except that in\nthe case of `require_once`, the include file is included once only during\nprogram execution.\n\n**Examples**\n\n```Hack\n// Point.php\n<?hh …\nclass Point { … }\n\n// Circle.php\n<?hh …\nrequire_once 'Point.php';\nclass Circle { /* uses Point somehow */ }\n\n// MyApp.php\nrequire_once 'Point.php';    // Point.php included directly\nrequire_once 'Circle.php';   // Point.php now not included indirectly\n$p1 = new Point(10, 20);\n$c1 = new Circle(9, 7, 2.4);\n```\n"
  },
  {
    "path": "spec/13-enums.md",
    "content": "# Enums\n\n## General\n\nAn *enumeration* consists of a set of zero or more named, constant values called *enumeration* constants having type `int` or `string`. Each distinct enumeration constitutes a different *enumerated* type. An instance of an enumerated type is called an `enum`. Each enumerated type has a corresponding type called the *underlying type* of that enumerated type. That underlying type is limited to `int` or `string`.\n\n## Enum Declarations\n\n**Syntax**\n<pre>\n<i>enum-declaration:</i>\n  enum  <i>name</i>  <i>enum-base</i>  <i>type-constraint<sub>opt</sub></i>  {  <i>enumerator-list<sub>opt</sub></i>  }\n<i>enum-base:</i>\n  :  int\n  :  string\n<i>enumerator-list:</i>\n  <i>enumerator</i> \n  <i>enumerator-list</i>  <i>enumerator</i> \n<i>enumerator:</i>\n  <i>enumerator-constant</i>  =  <i>constant-expression</i> ;\n<i>enumerator-constant:</i>\n  <i>name</i>\n</pre>\n\n*name* is defined in [§§](09-lexical-structure.md#names); *type-constraint* is defined in [§§](05-types.md#general); and *constant-expression* is defined in [§§](10-expressions.md#constant-expressions).\n\n**Constraints**\n\nThe underlying type designated by *enum-base* must be able to represent all the values of the enumerators defined in the *enumerator-list*.\n\nIf *type-constraint* is present, *enum-base* must be a subtype ([§§](05-types.md#supertypes-and-subtypes)) of *type-constraint*s *type-specifier*.\n\nEach *constant-expression* must have type `int` or `string`.\n\nThe *names* of *enumeration-constants* declared in the same *enum-declaration* must be distinct.\n\nA *constant-expression* must not refer directly or indirectly to the *name* of its own *enumeration-constant*.\n\n**Semantics**\n\nAn *enum-declaration* defines an enumerated type by the name *name*. Enumerated type names are case-preserved ([§§](03-terms-and-definitions.md). \n\nThe *name*s in an *enumerator-list* are declared as constants. Multiple *enumeration-constants* declared in the same *enum-declaration* may have the same *constant-expression* value. Different enumerated types can have *enumeration-constants* with the same *name*. When used, each *name* is qualified by prepending its parent enumerated type *name* and \"`::`\", in that order.\n\nThe type of each *enumeration-constant* is the type specified by *type-constraint*, if present; otherwise, the type of each *enumeration-constant* is the enumerated type in which it is defined.\n\nAn *enumeration-constant* can be used in any read-only context for an expression of its type.\n\nA *constant-expression* can refer to the *name*s of other *enumeration-constants* in the same enumerated type. However, it must use their qualified names.\n\n**Examples**\n\n```Hack\nenum BitFlags: int as int {\n  F1 = 1;\n  F2 = BitFlags::F1 << 1;\n  F3 = BitFlags::F2 << 1;\n}\n// -----------------------------------------\nenum ControlStatus: int {\n  Stopped = 0;\n  Stopping = 1;\n  Starting = 2;\n  Started = 3;\n}\nfunction processStatus(ControlStatus $cs): void {\n  switch ($cs) {\n  case ControlStatus::Started:\n    …\n    break;\n  case ControlStatus::Starting:\n    …\n    break;\n  case ControlStatus::Stopped:\n    …\n    break;\n  case ControlStatus::Stopping:\n    …\n    break;\n  }\n}\n```\n\nThis example defines `ControlStatus` to be an enumerated type with an underlying type of `int`. The enumerated type has the four named enumeration constants `Stopped`, `Stopping`, `Starting`, and `Started`. Each enumeration constant is initialized with the integer constant value, as shown. When called, the function `processStatus` is passed an enum having one of the four possible enumeration constant values.\n\n```Hack\nenum Permission: string {\n  Read = 'R';\n  Write = 'W';\n  Execute = 'E';\n  Delete = 'D';\n}\nenum Colors: int {\n  Red = 3;\n  White = 5;\n  Blue = 10;\n  Default = 3;  // duplicate value is okay\n}\n```\n\n## The Predefined Enumerated Type Methods\n\nAll enumerated types behave as if they contained the following family of public, static methods.\n\n```Hack\npublic static function assert(mixed $value): XXX\npublic static function assertAll(Traversable<mixed> $values): Container<XXX>\npublic static function coerce(mixed $value): ?XXX\npublic static function getNames(): array<XXX, string>\npublic static function getValues(): array<string, XXX>\npublic static function isValid(mixed $value): bool\n```\n\nwhere *XXX* is the enumeration type through which these methods are called.\n\nNote: When called on an enumerated type that contains multiple enumeration constants having the same *constant-expression* value, `getNames` throws an exception of type `\\HH\\InvariantException`.\n\nThe methods are defined below:\n\nName  |  Purpose\n----  |  -------\n`assert`  |  Converts the given $value to the enum’s underlying type.\n`assertAll`  |  Converts the given `Traversable` of values to the enum’s underlying type.\n`coerce`  |  Converts the given `$value` to the enum’s underlying type.\n`getNames`  |  Returns a map-like array of enumeration constant values and their names.\n`getValues`  |  Returns a map-like array of enumeration constant names and their values.\n`isValid`  |  Indicated whether the given `$value` is one of the values in the enum.\n"
  },
  {
    "path": "spec/14-generic-types-methods-and-functions.md",
    "content": "# Generic Types, Methods, and Functions\n\n## General\n\nCertain types (classes, interfaces, and traits) and their methods can be *parameterized*; that is, their declarations can have one or more placeholder names—called *type parameters*—that are associated with types via *type arguments* when a class is instantiated or a method is called. A type or method having such placeholder names is called a *generic type* or *generic method*, respectively. Top-level functions can also be parameterized giving rise to *generic functions*.\n\nGenerics allow programmers to write a class or method with the ability to be parameterized to any set of types, all while preserving type safety.\n\nConsider the following example in which `Stack` is a generic class having one type parameter, `T`:\n\n```Hack\nclass StackUnderflowException extends Exception {}\n\nclass Stack<T> {\n  private array<T> $stack;\n  private int $stackPtr;\n\n  public function __construct() {\n    $this->stackPtr = 0;\n    $this->stack = array();\n  }\n\n  public function push(T $value): void {\n    $this->stack[$this->stackPtr++] = $value;\n  }\n\n  public function pop(): T {\n    if ($this->stackPtr > 0) {\n      return $this->stack[--$this->stackPtr];\n    } else {\n      throw new StackUnderflowException();\n    }\n  }\n}\n```\n\nAs shown, the type parameter `T` is used in the declaration of the instance property `$stack`, as the parameter type of the instance method `push`, and as the return type of the instance method `pop`. Note that although `push` and `pop` use the type parameter, they are not themselves generic methods. \n\n```Hack\nfunction useIntStack(Stack<int> $stInt): void {\n  $stInt->push(10);\n  $stInt->push(20);\n  $stInt->push(30);\n  echo 'pop => ' . $stInt->pop() . \"\\n\";\n//  $stInt->push(10.5); // rejected as not being type-safe\n}\n```\n\nThe line commented-out, attempts to call push with a non-`int` argument. This is rejected, because `$stInt` is a stack of `int`.\n\nThe *arity* of a generic type or method is the number of type parameters declared for that type or method. As such, class `Stack` has arity 1. The Hack library generic container class `Map` implements an ordered, dictionary-style collection. This type has arity 2, and utilizes a key type and a value type, so the type `Map<int, Employee>`, for example, could be used to represent a group of `Employee` objects indexed by an integer employee number.\n\nHere is an example of a generic function, `maxVal`, having one type parameter, `T`:\n\n```Hack\nfunction maxVal<T>(T $p1, T $p2): T {\n  return $p1 > $p2 ? $p1 : $p2;\n}\n```\n\nThe function returns the larger of the two arguments passed to it. In the case of the call `maxVal(10, 20)`, given that the type of both arguments is `int`, that is inferred as the type corresponding to the type parameter `T`, and an `int` value is returned. In the case of the call `maxVal(15.6, -20.78)`, `T` is inferred as `float`, while in `maxVal('red', 'green')`, `T` is inferred as `string`.\n\nType parameters are discussed further in [§§](14-generic-types-methods-and-functions.md#type-parameters), and type arguments are discussed further in [§§](14-generic-types-methods-and-functions.md#type-arguments).\n\n## Type Parameters\n\n**Syntax**\n<pre>\n<i>generic-type-parameter-list:</i>\n  &lt;  <i>generic-type-parameters</i>  ,<sub>opt</sub>  &gt;\n<i>generic-type-parameters:</i>\n  <i>generic-type-parameter</i>\n  <i>generic-type-parameters</i>  ,  <i>generic-type-parameter</i>\n<i>generic-type-parameter:</i>\n  <i>generic-type-parameter-variance<sub>opt</sub></i>  <i>generic-type-parameter-name</i>  <i>type-constraint<sub>opt</sub></i>\n<i>generic-type-parameter-name:</i>\n  <i>name</i>\n<i>generic-type-parameter-variance:</i>\n  +\n  -\n</pre>\n\n*name* is defined in [§§](09-lexical-structure.md#names) and *type-constraint* is described in [§§](05-types.md#general).\n\n**Constraints**\n\nWithin a *generic-type-parameter-list*, *name*s must be distinct.\n\nAll *name*s must begin with the letter T.\n\nA *name* used in a *generic-type-parameter* of a method must not be the same as that used in a *generic-type-parameter* for an enclosing class, interface, or trait.\n\n*generic-type-parameter-variance* must not be present in a *function-definition* ([§§](15-functions.md#function-definitions)). \n\nThe *type-specifier* in *generic-type-constraint* must not be `this` or `?this`.\n\n**Semantics**\n\nA type parameter is a placeholder for a type that is supplied when the generic type is instantiated or the generic method or function is invoked.\n\nA type parameter is a compile-time construct. At run-time, each type parameter is matched to a run-time type that was specified by a type argument. Therefore, a type declared with a type parameter will, at run-time, be a closed generic type ([§§](14-generic-types-methods-and-functions.md#open-and-closed-generic-types)), and execution involving a type parameter uses the actual type that was supplied as the type argument for that type parameter.\n\nThe *name* of a type parameter is visible from its point of definition through the end of the type, method, or function declaration on which it is defined. However, the *name* does not conflict with a *name* of the same spelling used in non-type contexts (such as the names of a class constant, an attribute, a method, an enum constant, or a namespace).\n\nGeneric type constraints are discussed in [§§](14-generic-types-methods-and-functions.md#type-constraints).\n\n*generic-type-parameter-variance* indicates the variance for that parameter: `+` for covariance, `- `for contravariance. If *generic-type-parameter-variance* is omitted, covariance is assumed.\n\n\n**Examples**\n\nIn the following case, class `Vector` has one type parameter, `Tv`. Method `map` also has one type parameter, `Tu`.\n\n```Hack\nfinal class Vector<Tv> implements MutableVector<Tv> {\n  …\n  public function map<Tu>((function(Tv): Tu) $callback): Vector<Tu> { … }\n}\n```\n\nIn the following case, class `Map` has two type parameters, `Tk` and `Tv`. Method `zip` has one, `Tu`.\n\n```Hack\nfinal class Map<Tk, Tv> implements MutableMap<Tk, Tv> {\n  …\n  public function zip<Tu>(Traversable<Tu> $iter): Map<Tk, Pair<Tv, Tu>> { … }\n}\n```\n\nIn the following case, function `maxValue` has one type parameter, `T`.\n\n```Hack\nfunction maxValue<T>(T $p1, T $p2): T { … }\n```\n\n## Type Constraints\n\nA *type-constraint* ([§§](05-types.md#general)) in a *generic-type-parameter* indicates a requirement that a type must fulfill in order to be accepted as a type argument for a given type parameter. (For example, it might have to be a given class type or a subtype of that class type, or it might have to implement a given interface.)\n\nConsider the following example in which class `Complex` has one type parameter, `T`, and that has a constraint:\n\n```Hack\nclass Complex<T as num> {\n  private T $real;\n  private T $imag;\n  public function __construct(T $real, T $imag) {\n    $this->real = $real;\n    $this->imag = $imag;\n  }\n  public static function add(Complex<T> $z1, Complex<T> $z2): Complex<T> {\n    return new Complex($z1->real + $z2->real, $z1->imag + $z2->imag);\n  }\n  …\n  public function __toString(): string {\n    if ($this->imag < 0.0) {                                                       \n      return \"(\" . $this->real . \" - \" . (-$this->imag) . \"i)\";\n    }\n    …\n  }\n}\n```\n\nWithout the `num` constraint, a number of errors are reported, including the following: \n* The `return` statement in method add performs arithmetic on a value of unknown type `T`, yet arithmetic isn't defined for all possible type arguments.\n* The `if` statement in method `__toString` compares a value of unknown type `T` with a `float`, yet such a comparison isn't defined for all possible type arguments.\n* The return statement in method `__toString` negates a value of unknown type `T`, yet such an operation isn't defined for all possible type arguments. Similarly, a value of unknown type `T` is being concatenated with a `string`.\n\nThe following code creates `float` and `int` instances, respectively, of class `Complex`:\n\n```Hack\n$c1 = new Complex(10.5, 5.67);\necho \"\\$c1 + \\$c2 = \" . Complex::add($c1, $c2) . \"\\n\";\n$c3 = new Complex(5, 6);\necho \"\\$c3 + \\$c4 = \" . Complex::add($c3, $c4) . \"\\n\";\n```\n\n## Type Arguments\n\n**Syntax**\n<pre>\n<i>generic-type-argument-list:</i>\n  &lt;  <i>generic-type-arguments</i>  ,<sub>opt</sub>  &gt;\n<i>generic-type-arguments:</i>\n  <i>generic-type-argument</i>\n  <i>generic-type-arguments</i>  ,  <i>generic-type-argument</i>\n<i>generic-type-argument:</i>\n  <i>type-specifier</i>\n  <i>name</i>\n</pre>\n\n*name* is defined in [§§](09-lexical-structure.md#names) and *type-specifier* is described in [§§](05-types.md#general).\n\n**Constraints**\n\nEach *generic-type-argument* must satisfy any constraint on the corresponding type parameter ([§§](14-generic-types-methods-and-functions.md#type-parameters)).\n\n**Semantics**\n\nA *generic-type-argument* can be a *type-specifier* or a *name* that is a *type-parameter*. Either way, at runtime, it is used in place of the corresponding type parameter. A *generic-type-argument* can either be open or closed ([§§](14-generic-types-methods-and-functions.md#open-and-closed-generic-types)).\n\n**Examples**\n\n```Hack\nfinal class Pair<Tv1, Tv2> implements ConstVector<mixed> {\n  …\n  public function getIterator(): KeyedIterator<int, mixed> { … }\n  public function keys(): Vector<int> { … }\n  public function toMap(): Map<int, mixed> { … }\n  public function zip<Tu>(Traversable<Tu> $iter): Vector<Pair<mixed, Tu>> {…}\n}\n```\n\nIn this case, the type specifiers `ConstVector<mixed>`, `KeyedIterator<int, mixed>`, `Vector<int>`, `Map<int, mixed>`, `Traversable<Tu>`, `Vector<Pair<mixed, Tu>>`, and `Tu`, and are type arguments.\n\n## Open and Closed Generic Types\n\nA type parameter is introduced in the corresponding type, method, or function declaration. All other uses of that type parameter occur in *type-specifiers* ([§§](05-types.md#general)) for the declaration of properties, function parameters, and function returns. Each such use can be classified as follows: An *open generic type* is a type that contains one or more type parameters; a *closed generic type* is a type that is not an open generic type.\n\nAt run-time, all of the code within a generic type, method, or function declaration is executed in the context of the closed generic type that was created by applying type arguments to that generic declaration. Each type parameter within the generic type, method, or function is associated to a particular run-time type. The run-time processing of all statements and expressions always occurs with closed generic types, and open generic types occur only during compile-time processing.\n\nTwo closed generic types are the same type if they are created from the same generic type declaration, and their corresponding type arguments have the same type.\n\nConsider the following:\n\n```Hack\nfinal class Vector<Tv> implements MutableVector<Tv> {\n  …\n  public function zip<Tu>(Traversable<Tu> $it): Vector<Pair<Tv, Tu>> { … }\n}\n```\n\nThe type parameter `Tv` is introduced in the declaration of the generic type `Vector`. That type parameter is then used in the type-specifiers `MutableVector<Tv>` and `Vector<Pair<Tv, Tu>>`, both of which are open generic types. The type parameter `Tu` is introduced in the declaration of the generic function `zip`. That type parameter is then used in the type-specifiers `Traversable<Tu>` and `Vector<Pair<Tv, Tu>>`, both of which are open generic types.\n\nIn the following case:\n\n```Hack\nfinal class Pair<Tv1, Tv2> implements ConstVector<mixed> {\n  …\n  public function getIterator(): KeyedIterator<int, mixed> { … }\n  public function keys(): Vector<int> { … }\n  public function toMap(): Map<int, mixed> { … }\n  public function zip<Tu>(Traversable<Tu> $iter): Vector<Pair<mixed, Tu>> {…}\n}\n```\n\nthe type specifiers `Traversable<Tu>`, `Tu`, and `Vector<Pair<mixed, Tu>>` are all open generic types, while the type specifiers `ConstVector<mixed>`, `KeyedIterator<int, mixed>`, `Vector<int>`, and `Map<int, mixed>` are all closed generic types.\n\nStatic properties specified in a generic type are properties of an open generic type. Type arguments of a static are not associated with a particular run-time type, and thus it is an error to have a static property within a generic type.\n\nConsider the following case:\n\n```Hack\nfinal class Foo<T> {\n  public static T $x;\n}\n\nfunction main(): void {\n  $i = new Foo(4);\n  $s = new Foo(\"Hi\");\n}\n```\n\nSince the static `$x` is part of the open generic type, there is no way to bind `$x` to a particular type (in this case an `int` or `string`).\n\n## Type Inferencing Revisited\n\nSee [§§](05-types.md#type-inferencing) for an introduction to type inferencing.\n\nThe examples in this section use the generic class `Stack` defined in [§§](14-generic-types-methods-and-functions.md#general).\n\nSome languages require the type arguments associated with a generic class to be specified at instantiation time, using syntax something like new `Stack<int>()` to create a `Stack` of `int`. However, that is **not** permitted in Hack. As such, what is being allocated here is a stack of unknown type. When method `push` is called with an int argument, the implementation infers that the stack can hold values of that type. Then when `push` is called with a `float` argument, the implementation infers that the stack can also hold values of that type. Values of yet other types can also be pushed.\n\nIn the following example, the type of the `Stack` designated by `$st` is not fixed (i.e., established) until that `Stack` is made available outside of its creating function, in this case, when the creating function returns to its caller:\n\n```Hack\nfunction f1(): Stack<num> {\n  $st = new Stack();\n  $st->push(100);       // allows ints to be pushed\n  $st->push(10.5);      // allows floats to be pushed\n  return $st;           // fixes the type as Stack<num>\n}\n```\n\nNow consider the following example:\n\n```Hack\nfunction f2(): void {\n  $st = new Stack();\n  $st->push(100);\n  process($st);         // fixes the type as Stack<int>\n  $st->push(10.5);      // rejected once stack type fixed\n}\n```\n\nWhen the `Stack` is passed to function process, the `Stack`'s type is fixed as `Stack<int>`, and the subsequent attempt to push on a `float` is rejected.\n\nNote that a similar situation occurs with objects created from collection literals ([§§](10-expressions.md#collection-literals)) having no initial values, as in `Vector {}` and `Map {}`.\n\n\n"
  },
  {
    "path": "spec/15-functions.md",
    "content": "# Functions\n\n## General\n\nWhen a function is called, information may be passed to it by the caller\nvia an *argument list*, which contains one or more *argument\nexpressions*, or more simply, *arguments*. These correspond by position\nto the *parameters* in a *parameter list* in the called [function's\ndefinition](15-functions.md#function-definitions). Hack supports *variadic functions*; that is, functions that can be called with a variable number of arguments. \n\nAny function containing [`yield`](10-expressions.md#yield-operator) is a *generator function*.\n\n## Function Calls\n\nA function is called via the [function-call operator `()`](10-expressions.md#function-call-operator).\n\n## Function Definitions\n\n**Syntax**\n\n<pre>\n  <i>function-definition:</i>\n    <i>attribute-specification<sub>opt</sub>   function-definition-no-attribute</i>\n\n  <i>function-definition-no-attribute:</i>\n    <i>function-definition-header  compound-statement</i>\n\n  <i>function-definition-header:</i>\n    async<sub>opt</sub>  function <i>name</i>  <i>generic-type-parameter-list<sub>opt</sub></i>  (  <i>parameter-list<sub>opt</sub></i>  ) :  <i>return-type</i>\n\n  <i>parameter-list:</i>\n    ...\n    <i>parameter-declaration-list</i>  ,<sub>opt</sub>\n    <i>parameter-declaration-list</i>  ,  ...\n\n  <i>parameter-declaration-list:</i>\n    <i>parameter-declaration</i>\n    <i>parameter-declaration-list</i>  ,  <i>parameter-declaration</i>\n\n  <i>parameter-declaration:</i>\n    <i>attribute-specification<sub>opt</sub></i>  <i>type-specifier</i>  <i>variable-name  default-argument-specifier<sub>opt</sub></i>\n\n  <i>default-argument-specifier:</i>\n    =  <i>const-expression</i>\n\n  <i>return-type:</i>\n    <i>type-specifier</i>\n    noreturn\n</pre>\n\n**Defined elsewhere**\n\n* [*attribute-specification*](21-attributes.md#attribute-specification)\n* [*compound-statement*](11-statements.md#compound-statements)\n* [*const-expression*](10-expressions.md#constant-expressions)\n* [*generic-type-parameter-list*](14-generic-types-methods-and-functions.md#type-parameters)\n* [*name*](09-lexical-structure.md#names)\n* [*type-specifier*](05-types.md#general)\n* [*variable-name*](09-lexical-structure.md#names)\n\n**Constraints**\n\nThe name of a method must not be the same as that of its parent class.\n\nEach *variable-name* in a *parameter-declaration-list* must be distinct.\n\nIf any *parameter-declaration* has a *default-argument-specifier*, then all subsequent *parameter-declarations* in the same *parameter-declaration-list* must also have a *default-argument-specifier*.\n\nIf *return-type* is `noreturn`, the *compound-statement* must not contain any [`return` statements](11-statements.md#the-return-statement).\n\nIf the *type-specifier* in *return-type* is `void`, the *compound-statement* must not contain any [`return` statements](11-statements.md#the-return-statement) having an *expression*. Otherwise, all `return` statements must contain an *expression* whose type is a subtype of the type indicated by *type-specifier*.\n\nIf *async* is present, *return-type* must be a type that implements [`Awaitable<T>`](17-interfaces.md#interface-awaitable). \n\nA generic function and a non-generic function in the same scope cannot have the same *name*.\n\nIf the function being defined is an overriding method in a derived class, the *return-type* of the derived-class method must be a subtype of the *return-type* of the base-class method.\n\nA function that is not a method must not have a *return-type* of `this`.\n\n**Semantics**\n\nA *function-definition* defines a function called *name*. A function can be defined with zero or more parameters, each of which is specified in its own *parameter-declaration* in a *parameter-declaration-list*. Each parameter has a name (*variable-name*), a type (*type-specifier*), and optionally, a *default-argument-specifier*. \n\nIf *parameter-list* contains an ellipses (`...`), the function is variadic, in which case, *parameter-declaration-list* (if any) to the left of this ellipse represents the *fixed parameter list*. The ellipsis represents the *variable parameter list*. A non-variadic function has only a fixed parameter list. If *parameter-list* is omitted, the function has no parameters, in which case, both the fixed and the variable parameter lists are empty.\n\nWhen the function is called, if there exists a parameter for which there is a corresponding argument, the argument is assigned to the parameter variable. If that parameter has no corresponding argument, but the parameter has a *default-argument-specifier*, the default value is assigned to the parameter variable. After all parameters have been assigned initial values, the body of the function, *compound-statement*, is executed. This execution may [terminate normally](04-basic-concepts.md#program-termination) or [abnormally](04-basic-concepts.md#program-termination).\n\nEach parameter is a variable local to the parent function, it is a modifiable lvalue, and its type can change. A parameter's *type-specifier* constrains the type of any corresponding argument in a call to that function and in subsequent uses of that parameter's name in a non-lvalue context, provided that parameter is not used in an lvalue context. However, the *type-specifier* does not constrain the use of that parameter's name in an lvalue context. For example, a parameter *$p1* having a *type-specifier* of `int` could have assigned to it in the *compound-statement* the value of a `float`, in which case, being a local variable, `$p1` takes on that type instead.\n\nThere may be more arguments than parameters, in which case, the library functions [`func_num_args`](http://www.php.net/func_num_args), [`func_get_arg`](http://www.php.net/func_get_arg), and [`func_get_args`](http://www.php.net/func_get_args) can be used to get access to the complete argument list that was passed.\n\nThe presence of the `async` modifier declares the function to be [asynchronous](15-functions.md#asynchronous-functions). For an async function, control may be transferred back to the caller before the flow of execution reaches any `return` statement or the function-closing brace. In such a case, the awaitable object that will be returned to the caller later on acts like a placeholder that will eventually be filled with the return result.\n\nA function having a *return-type* of `noreturn` never returns. Instead, it, or a function it calls directly or indirectly, terminates in some other manner, such as by throwing an exception or by calling the non-returning library function `exit`.\n\nA method having a *return-type* of `this` allows that method to return an [object created via `new static`](10-expressions.md#the-new-operator). In such cases, the type actually returned depends on whether the method is called on an instance of its own class or on one that is an instance of a derived class. (See [§§](21-attributes.md#attribute-__consistentconstruct) for an example.)\n\n**Examples**\n\n```Hack\nfunction square(num $v): num {\n  return $v * $v;\n}\n// -----------------------------------------\nfunction break_string_into_substrings(string $str, string $separator = ';'):\n  array<string> {\n  $result = array();\n  …\n  return $result;\n}\n// -----------------------------------------\nfunction addVector(Vector<int> $v1, Vector<int> $v2): Vector<int> {\n  $result = Vector{};\n  // add two vectors\n  return $result;\n}\n// -----------------------------------------\nfunction factorial(int $i): int   // contains a recursive call {\n  return ($i > 1) ? $i * factorial($i - 1) : $i;\n}\n// -----------------------------------------\nfunction variable_args(...): void {   // variadic function\n  $argList = func_get_args();\n  echo \"# arguments passed is \" . count($argList).\"\\n\";\n\n  foreach ($argList as $k => $e) {\n    echo \"\\targ[$k] = >$e<\\n\";\n  }\n}\n// -----------------------------------------\nfunction f6(int $p): noreturn { \n  if ($p < 0) throw new ExceptionA();\n  else if ($p > 0) throw new ExceptionB();\n  else exit(10);\n}                         // Okay; no path returns\n\nfunction f7c(int $p): noreturn { \n  f6($p);\n}                         // implicit return nothing is allowed\n```\n\n## Anonymous Functions\n\nAn *anonymous function*, also known as a *closure*, is a function\ndefined with no name. As such, it must be defined in the context of an\nexpression whose value is used immediately to call that function, or\nthat is saved in a variable of [closure type](05-types.md#closure-types) for later execution. An anonymous function\nis defined via the [anonymous function-creation operator](10-expressions.md#anonymous-function-creation).\n\nFor both [`__FUNCTION__` and `__METHOD__`](06-constants.md#context-dependent-constants), an anonymous\nfunction's name is `{closure}`. All anonymous functions created in the\nsame scope have the same name.\n\n## Asynchronous Functions\n\nThe term *asynchronous programming* generally refers to design patterns that allow for cooperative transfer of control between several distinct tasks on a given thread of execution (or possibly a pool of threads) in a manner that isolates tasks from each other and minimizes unnecessary dependencies and interactions between tasks. Asynchronous programming is often used in the context of I/O, and with tasks that depend on I/O. Using asynchronous programming can make it significantly easier for a program to batch work together when calling synchronous I/O APIs (APIs that cause the thread to block until the I/O operation is complete) and it can make it easier to use asynchronous APIs (APIs that allow a thread to continue executing while the I/O operation is in progress).\n\nA function (or method) is declared to be asynchronous via the function modifier [`async`](15-functions.md#function-definitions). The execution of an asynchronous function can be *suspended*; that is, control is returned to its caller, until a designated *await condition* is satisfied. This condition is specified via the operator [`await`](10-expressions.md#await-operator).\n\nWhen an async function is compiled, a special transformation is performed, so that an object that implements [`Awaitable<T>`](17-interfaces.md#interface-awaitable) is returned to the caller (where `T` is the function's *return-type*). This object is used to keep track of the state of execution for the async function and to keep track of dependencies on other tasks. Each time a given async function is called, a newly allocated object is returned to the caller.\n\nWhen an async function is invoked, it executes synchronously until it returns normally, it throws an error/exception, or it reaches an await operation.\n\nThe await operation provides a way for an async function to yield control in cases where further progress cannot be made until the result of a dependency is available.\n\nAn await operation takes a single operand called the *dependency*, which must be an object that implements the `Awaitable` interface. (Such an object is called an *awaitable*.) When an await operation executes, it checks the status of the dependency. If the result of the dependency is available, the await operation produces the result (without yielding control elsewhere) and the current async function continues executing. If the dependency has failed due to an exception, the await operation re-throws this exception. Otherwise, the await operation updates the current async function's `Awaitable` to reflect its dependence on the dependency and then yields control. The async function will be considered *blocked* and ineligible to resume execution until the result of the dependency is available.\n\nIt is possible to wait on multiple dependencies by having their awaitables be combined in a single awaitable using functions `HH\\Asio\\v` or `HH\\Asio\\map`, as appropriate. In such cases, if one of the awaitables throws an exception, the combined awaitable will rethrow that exception. If multiple component awaitables throw exceptions, the combined awaitable will rethrow only one of them. The library function `HH\\Asio\\wrap` can help deal with this.\n\nWhen yielding control, the implementation of `await` may choose to yield control back to the current async function's caller. Alternatively, if the dependency is a task and its async function is not blocked (i.e., it is eligible to resume execution), the implementation may choose (for optimization purposes) to perform an invocation to resume the dependency's async function to make further progress and then check again if the result of the dependency is available.\n\nIf an await operation would result in a dependency cycle (i.e., a task waiting on itself, or a group of two or more tasks that wait on each other in a cycle), the await operation will fail and an exception will be thrown.\n\nWhen a `return` statement executes inside an async function, typically, control is transferred back to the caller. However, the implementation may choose (for scheduling or optimization reasons) to perform invocations to resume other dependent async functions that are now eligible to execute before ultimately transferring control back to the caller.\n\nIf an async function returns a value of type `T`, the return type visible to its callers is `Awaitable<T>`. (If an async function returns no value, the return type visible to its callers is `Awaitable<void>`.)\n\nThe term *asynchronous function* includes asynchronous [anonymous functions](15-functions.md#anonymous-functions) and asynchronous [lambda expressions](10-expressions.md#lambda-expressions).\n"
  },
  {
    "path": "spec/16-classes.md",
    "content": "# Classes\n\n## General\n\nA class is a type that may contain zero or more explicitly declared\n*members*, which can be any combination of [*class constants*](16-classes.md#constants);\ndata members, called [*properties*](16-classes.md#properties); function members, called\n[*methods*](16-classes.md#methods); and [*type constants*](16-classes.md#type-constants). (The ability to add methods to an\ninstance at runtime is described in [§§](16-classes.md#dynamic-methods).) An object (often called an\n*instance*) of a class type is created (i.e., *instantiated*) via the\n[new operator](10-expressions.md#the-new-operator).\n\nHack supports [inheritance](16-classes.md#class-declarations), a means by which a *derived class* can\n*extend* and specialize a single *base class*. However, unlike numerous\nother languages, classes in Hack are **not** all derived from a common\nancestor. An [*abstract* class](16-classes.md#class-declarations) is a base type intended for\nderivation, but which cannot be instantiated directly. A *concrete*\nclass is a class that is not abstract. A [*final* class](16-classes.md#class-declarations) is one\nfrom which other classes cannot be derived.\n\nA class may *implement* one or more *interfaces* ([§§](16-classes.md#class-declarations), [§§](17-interfaces.md#general)), each of\nwhich defines a contract.\n\nA class can *use* one or more [traits](18-traits.md#general), which allows a class to\nhave some of the benefits of multiple inheritance.\n\nA [*constructor*](16-classes.md#constructors) is a special method that is used to initialize\nan instance immediately after it has been created. A [*destructor*](16-classes.md#destructors) is a special method that is used to free resources when an\ninstance is no longer needed. Other special methods exist; they are\ndescribed in ([§§](16-classes.md#methods-with-special-semantics)).\n\nThe members of a class each have a default or explicitly declared\n*visibility*, which decides what source code can access them. A\nmember with `private` visibility may be accessed only from within its own\nclass. A member with `protected` visibility may be accessed only from\nwithin its own class and from classes derived from that class. Access to\na member with `public` visibility is unrestricted. \n\nThe *signature* of a method is a combination of the parent class name,\nthat method's name, and its parameter types.\n\nThe members of a base class can be *overridden* in a\nderived class by redeclaring them with the same signature defined in the\nbase class. However, overridden constructors are exempt from this requirement ([§§](16-classes.md#constructors)).\n\nWhen an instance is allocated, new returns a handle that points to that\nobject. As such, assignment of a handle does not copy the object itself.\n(See [§§](04-basic-concepts.md#cloning-objects) for a discussion of shallow and deep copying.)\n\n## Class Declarations\n\n**Syntax**\n\n<pre>\n  <i>class-declaration:</i>\n    <i>attribute-specification<sub>opt</sub></i>  <i>class-modifier<sub>opt</sub></i>  class  <i>name  generic-type-parameter-list<sub>opt</sub></i>  <i>class-base-clause<sub>opt</sub></i>\n      <i>class-interface-clause<sub>opt</sub></i>  {  <i>trait-use-clauses<sub>opt</sub>  class-member-declarations<sub>opt</sub></i>  }\n\n  <i>class-modifier:</i>\n    abstract\n    final\n    abstract final\n\n  <i>class-base-clause:</i>\n    extends  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n\n  <i>class-interface-clause:</i>\n    implements  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n    <i>class-interface-clause</i>  ,  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n</pre>\n\n**Defined elsewhere**\n\n* [*attribute-specification*](21-attributes.md#attribute-specification)\n* [*class-member-declarations*](16-classes.md#class-members)\n* [*generic-type-argument-list*](14-generic-types-methods-and-functions.md#type-parameters)\n* [*generic-type-parameter-list*](14-generic-types-methods-and-functions.md#type-parameters)\n* [*name*](09-lexical-structure.md#names)\n* [*qualified-name*](20-namespaces.md#defining-namespaces)\n* [*trait-use-clauses*](18-traits.md#trait-declarations)\n\n**Constraints**\n\nA class must not be derived directly or indirectly from itself.\n\nA *class-declaration* containing any *class-member-declarations* that\nhave the modifier `abstract` must itself have an `abstract`\n*class-modifier*.\n\n*class-base-clause* must not name a final class.\n\n*qualified-name* in *class-base-clause* must name a class type, and must\nnot be `parent`, `self`, or `static`.\n\nA concrete class must implement each of the methods from all the\n[interfaces](17-interfaces.md#general) specified in *class-interface-clause*, using the\nexact same signature as defined in each interface.\n\n*qualified-name* in *class-interface-clause* must name an interface\ntype.\n\nA generic class and a non-generic class in the same scope cannot have the same *name*.\n\n**Semantics**\n\nA *class-declaration* defines a class type by the name *name*. Class\nnames are [case-preserved](03-terms-and-definitions.md).\n\nThe `abstract` modifier declares a class usable only as a base class; the\nclass cannot be instantiated directly. An abstract class may contain one\nor more abstract members, but it is not required to do so. When a\nconcrete class is derived from an abstract class, the concrete class\nmust include an implementation for each of the abstract members it\ninherits.\n\nThe `final` modifier prevents a class from being used as a base class.\n\nThe optional *class-base-clause* specifies the one base class from which\nthe class being defined is derived. In such a case, the derived class\ninherits all the members from the base class.\n\nThe optional *class-interface-clause* specifies the one or more\ninterfaces that are implemented by the class being defined.\n\nA class is required to implement a given interface in either of the following cases:\n* If its *class-declaration* specifies that interface directly in a *class-interface-clause*; or\n* If that class contains a *trait-use-clause* for a trait whose *trait-declaration* contains a *class-interface-clause* naming that interface; or\n* Both.\n\nA class can use one or more traits via a *trait-use-clauses*; see [§§](18-traits.md#general)\nand [§§](18-traits.md#trait-declarations).\n\n**Examples**\n\n```Hack\nabstract class Vehicle {\n  public abstract function getMaxSpeed(): int;\n  …\n}\nabstract class Aircraft extends Vehicle {\n  public abstract function getMaxAltitude(): int;\n  …\n}\nclass PassengerJet extends Aircraft {\n  public function getMaxSpeed(): int {\n    // implement method\n  }\n  public function getMaxAltitude(): int {\n    // implement method\n  }\n  …\n}\n$pj = new PassengerJet(…);\necho \"\\$pj's maximum speed: \" . $pj->getMaxSpeed() . \"\\n\";\necho \"\\$pj's maximum altitude: \" . $pj->getMaxAltitude() . \"\\n\";\n// -----------------------------------------\nfinal class MathLibrary {\n  private function MathLibrary() {} // disallows instantiation\n  public static function sin(float $p): float { … }\n  …\n}\n$v = MathLibrary::sin(2.34);\n// -----------------------------------------\ninterface MyCollection {\n  function put(int $item): void;\n  function get(): int;\n}\nclass MyList implements MyCollection {\n  public function put(int $item): void  {\n    // implement method\n  }\n  public function get(): int {\n    // implement method\n  }\n  …\n}\n```\n\n## Class Members\n\n**Syntax**\n\n<pre>\n  <i>class-member-declarations:</i>\n    <i>class-member-declaration</i>\n    <i>class-member-declarations   class-member-declaration</i>\n\n   <i>class-member-declaration:</i>\n     <i>const-declaration</i>\n     <i>property-declaration</i>\n     <i>method-declaration</i>\n     <i>constructor-declaration</i>\n     <i>destructor-declaration</i>\n     <i>type-constant-declaration</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*const-declaration*](16-classes.md#constants)\n* [*constructor-declaration*](16-classes.md#constructors)\n* [*destructor-declaration*](16-classes.md#destructors)\n* [*method-declaration*](16-classes.md#methods)\n* [*property-declaration*](16-classes.md#properties)\n* [*type-constant-declaration*](16-classes.md#type-constants)\n\n**Semantics**\n\nThe members of a class are those specified by its\n*class-member-declaration*s, and the members inherited from its base\nclass, from the interfaces it implements, and from the traits that it uses. (A class may also contain dynamic members, as described in [§§](16-classes.md#dynamic-methods).\nHowever, as these have no compile-time names, they can only be accessed\nvia method calls.)\n\nA class may contain the following members:\n\n* [Constants](16-classes.md#constants) – the constant values associated with the class.\n* [Properties](16-classes.md#properties) – the variables of the class.\n* [Methods](16-classes.md#methods) – the computations and actions that can be performed by the class (see also [§§](16-classes.md#methods-with-special-semantics)).\n* [Constructor](16-classes.md#constructors) – the actions required to initialize an instance of the class.\n* [Destructor](16-classes.md#destructors) – the actions to be performed when an instance of the class is no longer needed.\n*\t[Type constant](16-classes.md#type-constants) – a way of parameterizing class types without using generics.\n\nA number of names are reserved for methods with special semantics, which\nuser-defined versions must follow. These are described in ([§§](16-classes.md#methods-with-special-semantics)).\n\nMethods and properties can either be *static* or *instance* members. A\nstatic member is declared using `static`. An instance member is one that\nis not static. The name of a static method or property can never be used\non its own; it must always be used as the right-hand operand of the\n[scope resolution operator](10-expressions.md#scope-resolution-operator). The name of an instance method or\nproperty can never be used on its own; it must always be used as the\nright-hand operand of the[ member selection operator](10-expressions.md#member-selection-operator).\n\nEach instance of a class contains its own, unique set of instance\nproperties of that class. An instance member is accessed via the\n[`->` operator](10-expressions.md#member-selection-operator). In contrast, a static property designates\nexactly one VSlot for its class, which does not belong to any instance,\nper se. A static property exists whether or not any instances of that\nclass exist. A static member is accessed via the [`::` operator](10-expressions.md#scope-resolution-operator).\n\nWhen any instance method operates on a given instance of a class, within\nthat method that object can be accessed via [`$this`](10-expressions.md#general-1). As a\nstatic method does not operate on a specific instance, it has no `$this`.\n\n**Examples**\n\n```Hack\nclass Point {\n  private static int $pointCount = 0;     // static property\n\n  private float $x;           // instance property\n  private float $y;           // instance property\n\n  public static function getPointCount(): int { // static method\n    return self::$pointCount;     // access static property\n  }\n  public function move(num $x, num $y): void {// instance method\n    $this->x = (float)$x;\n    $this->y = (float)$y;\n  }\n  public function __construct(num $x = 0, num $y = 0) { // instance method\n    $this->x = (float)$x;         // access instance property\n    $this->y = (float)$y;         // access instance property\n    ++self::$pointCount;        // access static property\n  }\n  public function __destruct() {        // instance method\n    --self::$pointCount;        // access static property\n    …\n  }\n  …\n}\necho \"Point count = \" . Point::getPointCount() . \"\\n\";\n$cName = 'Point';\necho \"Point count = \" . $cName::getPointCount() . \"\\n\";\n```\n\n## Dynamic Methods\n\nOrdinarily, all of the instance methods of a class are\ndeclared explicitly in that class's definition. However, under certain circumstances, *dynamic\nmethods* can be added to a particular instance of a class or to the\nclass as a whole at runtime.\n\nWith a dynamic method, no method is really added to the\ninstance or the class. However, the illusion of doing that is achieved\nby allowing a call to an instance or static method, but one which is not\ndeclared in that instance's class, to be accepted, intercepted by a\nmethod called [`__call`](16-classes.md#method-__call) or [`__callStatic`](16-classes.md#method-__callstatic), and\ndealt with under program control. \n\nConsider the following code fragment, in which class Widget has neither\nan instance method called `iMethod` nor a static method called `sMethod`,\nbut that class has made provision to deal with dynamic methods:\n\n```Hack\n$obj = new Widget();\n$obj->iMethod(10, true, \"abc\");\nWidget::sMethod(null, 1.234);\n```\n\nThe call to `iMethod` is treated as if it were\n\n```Hack\n$obj->__call('iMethod', array(10, true, \"abc\"))\n```\n\nand the call to `sMethod` is treated as if it were\n\n```Hack\nWidget::__callStatic('sMethod', array(null, 1.234))\n```\n\n## Constants\n\n**Syntax**\n\n<pre>\n  <i>const-declaration:</i>\n    abstract<i><sub>opt</sub></i>  const  <i>type-specifier<sub>opt</sub></i>  <i>constant-declarator-list</i>  ;\n  <i>constant-declarator-list:</i>\n    <i>constant-declarator</i>\n    <i>constant-declarator-list</i>  ,  <i>constant-declarator</i>\n  <i>constant-declarator:</i>\n    <i>name</i>  <i>constant-initializer<sub>opt</sub></i>\n\n  <i>constant-initializer:</i>\n    =  <i>const-expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*const-expression*](10-expressions.md#constant-expressions)\n* [*name*](09-lexical-structure.md#names)\n* [*type-specifier*](05-types.md#general)\n\n**Constraints**\n\nA *const-declaration* must be\na *class constant* (inside a [*class-definition*](16-classes.md#class-members) or be an\n*interface constant* (inside an [*interface-definition*](17-interfaces.md#interface-members).\n\nIf `abstract` is present, no *constant-initializer*s are permitted. If `abstract` is absent, each *constant-declarator* must have a *constant-initializer*.\n\n**Semantics**\n\nA *const-declaration* defines a c-constant.\n\nAll class constants have public visibility.\n\nAll constants are implicitly `static`.\n\nIf *type-specifier* is omitted, the type is inferred from *const-expression*.\n\nNote: Although the grammar allows a class constant to have any type, there is no way to write a *constant-expression* for closures, tuples, or shapes.\n\n**Examples:**\n\n```Hack\nclass Automobile {\n  const DEFAULT_COLOR = \"white\";\n  …\n}\n$col = Automobile::DEFAULT_COLOR;\n```\n\n## Properties\n\n**Syntax**\n\n<pre>\n  <i>property-declaration:</i>\n    <i>property-modifier</i>  <i>type-specifier</i>  <i>property-declarator-list</i>  ;\n\n  <i>property-declarator-list:</i>\n    <i>property-declarator</i>\n    <i>property-declarator-list</i>  ,  <i>property-declarator</i>\n\n  <i>property-declarator:</i>\n    <i>variable-name</i>  <i>property-initializer<sub>opt</sub></i>\n\n  <i>property-modifier:</i>\n    <i>visibility-modifier</i>  <i>static-modifier<sub>opt</sub></i>\n    <i>static-modifier</i>  <i>visibility-modifier</i>\n\n  <i>visibility-modifier:</i>\n    public\n    protected\n    private\n\n  <i>static-modifier:</i>\n    static\n\n  <i>property-initializer:</i>\n    =  <i>expression</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*constant-expression*](10-expressions.md#yield-operator)\n* [*type-specifier*](05-types.md#general)\n* [*variable-name*](09-lexical-structure.md#names)\n\n**Constraints**\n\nA static property cannot have a *type-specifier* of the form `this` `::` *name*.\n\nA static property cannot have a *type-specifier* of `this` or `?this`.\n\n**Semantics**\n\nA *property-declaration* defines an instance or static property called *variable-name*.\n\nThe visibility modifiers are described in [§§](16-classes.md#general). The `static` modifier is described in [§§](16-classes.md#class-members).\n\nThe *property-initializer*s for instance properties are applied prior to\nthe class's constructor being called. \n\nAll properties of non-nullable type must be initialized explicitly either by a *property-initializer* or by the constructor. Properties of nullable type that are not explicitly initialized take on the value `null`.\n\n**Examples**\n\n```Hack\nclass Point {\n  private static int $pointCount = 0; // static property with initializer\n  private float $x;         // instance property\n  private float $y;         // instance property\n  …\n}\n```\n\n## Methods\n\n**Syntax**\n\n<pre>\n  <i>method-declaration:</i>\np\n  <i>attribute-specification<sub>opt</sub></i> <i>method-modifiers</i>  <i>function-definition-no-attribute</i>\n  <i>attribute-specification<sub>opt</sub></i> <i>method-modifiers</i>  <i>function-definition-header</i>  ;\n\n  <i>method-modifiers:</i>\n    <i>method-modifier</i>\n    <i>method-modifiers</i>  <i>method-modifier</i>\n\n  <i>method-modifier:</i>\n    <i>visibility-modifier</i>\n    <i>static-modifier</i>\n    abstract\n    final\n</pre>\n\n**Defined elsewhere**\n\n* [*function-definition*](15-functions.md#function-definitions)\n* [*function-definition-header*](15-functions.md#function-definitions)\n* [*static-modifier*](16-classes.md#class-members)\n* [*visibility-modifier*](16-classes.md#general)\n\n**Constraints**\n\nWhen defining a concrete class that inherits from an abstract class, the\ndefinition of each abstract method inherited by the derived class must\nhave the same or a\nless-restricted [visibility](http://docs.hhvm.com/manual/en/language.oop5.visibility.php)\nthan in the corresponding abstract declaration. Furthermore, the\nsignature of a method definition must match that of its abstract\ndeclaration.\n\nThe *method-modifiers* preceding a *function-definition* must not contain\nthe `abstract` modifier.\n\nThe *method-modifiers* preceding a *function-definition-header* must\ncontain the `abstract` modifier.\n\nA method must not have the same modifier specified more than once. A\nmethod must not have more than one *visibility-modifier*. A method must\nnot have both the modifiers `abstract` and `private`, or `abstract` and `final`.\n\nAn abstract method must not also be asynchronous. However, an abstract method can have a return-type of `Awaitable<T>`, so an async concrete implementation can be provided.\n\n**Semantics**\n\nA *method-declaration* defines an instance or static method. A method is\na function that is defined inside a class. However, the presence of\n`abstract` indicates an abstract method, in which case, no implementation\nis provided. The absence of `abstract` indicates a concrete method, in\nwhich case, an implementation is provided.\n\nThe presence of `final` indicates the method cannot be overridden in a\nderived class.\n\n**Examples**\n\nSee [§§](16-classes.md#class-members) for examples of instance and static methods. See [§§](16-classes.md#class-declarations) for\nexamples of abstract methods and their subsequent definitions.\n\n## Constructors\n\n**Syntax**\n\n<pre>\n  <i>constructor-declaration:</i>\n    <i>attribute-specification<sub>opt</sub></i>  <i>constructor-modifiers</i>  function  __construct  (\n      <i>constructor-parameter-declaration-list<sub>opt</sub></i>  ) <i>void-return<sub>opt</sub></i>  <i>compound-statement</i>\n  <i>constructor-parameter-declaration-list:</i>\n    <i>constructor-parameter-declaration</i>\n    <i>constructor-parameter-declaration-list</i>  ,  <i>constructor-parameter-declaration</i>\n  <i>constructor-parameter-declaration:</i>\n    <i>visibility-modifier<sub>opt</sub></i>  <i>type-specifier</i>  <i>variable-name</i> <i>default-argument-specifier<sub>opt</sub></i>\n  <i>constructor-modifiers:</i>\n    <i>constructor-modifier</i>\n    <i>constructor-modifiers</i>  <i>constructor-modifier</i>\n\n  <i>constructor-modifier:</i>\n    <i>visibility-modifier</i>\n    abstract\n    final\n</pre>\n\n**Defined elsewhere**\n\n* [*attribute-specification*](21-attributes.md#attribute-specification)\n* [*compound-statement*](11-statements.md#compound-statements)\n* [*default-argument-specifier*](14-generic-types-methods-and-functions.md#type-constraints)\n* [*type-specifier*](05-types.md#general)\n* [*variable-name*](09-lexical-structure.md#names)\n* [*visibility-modifier*](16-classes.md#properties)\n\n**Constraints**\n\nAn overriding constructor in a derived class must have the same or a\nless-restricted [visibility](http://docs.hhvm.com/manual/en/language.oop5.visibility.php)\nthan that being overridden in the base class.\n\nThe *variable-name* in a *constructor-parameter-declaration* containing a *visibility-modifier* must not be the same as an explicitly declared property in this class.\n\n*compound-statement* must not contain a call to a non-private method in the same class.\n\n**Semantics**\n\nA constructor is a specially named [instance method](16-classes.md#methods) that is used\nto initialize an instance immediately after it has been created. Any\ninstance properties of nullable type not explicitly initialized by a constructor take on\nthe value `null`.\n\nConstructors can be overridden in a derived class by redeclaring them.\nHowever, an overriding constructor need not have the same signature as\ndefined in the base class. \n\nConstructors are called by [*object-creation-expression*s](10-expressions.md#the-new-operator)\nand from within other constructors.\n\nThe `abstract` and `final` modifiers are described in [§§](16-classes.md#methods).\n\nIf classes in a derived-class hierarchy have constructors, it is the\nresponsibility of the constructor at each level to call the constructor\nin its base-class explicitly, using the notation\n`parent::__construct(...)`. If a constructor calls its base-class\nconstructor, it should do so as the first statement in\n*compound-statement*, so the object hierarchy is built from the\nbottom-up. A constructor should not call its base-class constructor more\nthan once. A call to a base-class constructor searches for the nearest\nconstructor in the class hierarchy. Not every level of the hierarchy\nneed have a constructor.\n\nWhen a *constructor-parameter-declaration* contains a *visibility-modifier*, a property called *variable-name* with visibility *visibility-modifier* is added to the current class. When that constructor is called, the value of the argument for that parameter is assigned to the added property. Note: This feature simply provides a programming shortcut by having the implementation declare and initialize such properties.\n\nA constructor does not require a return type annotation; if one is included, it must be void.\n\n**Examples**\n\n```Hack\nclass Point {\n  private static int $pointCount = 0;\n  public function __construct(private float $x = 0.0, private float $y = 0.0) {\n    // private properties $x and $y are created and initialized\n        ++self::$pointCount;\n  }\n  public function __destruct() {\n    --self::$pointCount;\n    …\n  }\n  …\n}\n// -----------------------------------------\nclass MyRangeException extends Exception {\n  public function __construct(string $message, /* whatever */ ) {\n    parent::__construct($message);\n    …\n  }\n  …\n}\n```\n\n## Destructors\n\n**Syntax**\n\n<pre>\n  <i>destructor-declaration:</i>\n    <i>attribute-specification<sub>opt</sub></i>  <i>visibility-modifier</i>  function  __destruct  ( )  <i>void-return<sub>opt</sub></i>  <i>compound-statement</i>\n\n  <i>void-return:</i>\n    : void\n\n</pre>\n\n**Defined elsewhere**\n\n* [*attribute-specification*](21-attributes.md#attribute-specification)\n* [*compound-statement*](11-statements.md#compound-statements)\n* [*visibility-modifier*](16-classes.md#general)\n\n**Constraints**\n\nAn overriding destructor in a derived class must have the same or a\nless-restricted [visibility](http://www.php.net/manual/en/language.oop5.visibility.php)\nthan that being overridden in the base class.\n\n**Semantics**\n\nA destructor is a special-named [instance method](16-classes.md#methods) that is used to\nfree resources when an instance is no longer needed. The destructors for\ninstances of all classes are called automatically once there are no\nhandles pointing to those instances or in some unspecified order during\nprogram shutdown.\n\nDestructors can be overridden in a derived class by redeclaring them. \n\nDestructors are called by the Engine or from within other destructors.\n\nIf classes in a derived-class hierarchy have destructors, it is the\nresponsibility of the destructor at each level to call the destructor in\nthe base-class explicitly, using the notation `parent::__destruct()`. If\na destructor calls its base-class destructor, it should do so as the\nlast statement in *compound-statement*, so the object hierarchy is\ndestructed from the top-down. A destructor should not call its\nbase-class destructor more than once. A call to a base-class destructor\nsearches for the nearest destructor in the class hierarchy. Not every\nlevel of the hierarchy need have a destructor. A `private` destructor\ninhibits destructor calls from derived classes.\n\nA destructor does not require a return type annotation; if one is included, it must be void.\n\n**Examples**\n\nSee [§§](#constructors) for an example of a constructor and destructor.\n\n## Type Constants\n\n**Syntax**\n\n<pre>\n  <i>type-constant-declaration:</i>\n    <i>abstract-type-constant-declaration</i>\n    <i>concrete-type-constant-declaration</i>\n  <i>abstract-type-constant-declaration:</i>\n    abstract  const  type  <i>name</i>  <i>type-constraint<sub>opt</sub></i>  ;\n  <i>concrete-type-constant-declaration:</i>\n    const  type  name  <i>type-constraint<sub>opt</sub></i>  =  <i>type-specifier</i>  ;\n</pre>\n\n**Defined elsewhere**\n\n* [*name*](09-lexical-structure.md#names)\n* [*type-constraint*](05-types.md#general)\n* [*type-specifier*](05-types.md#general)\n\n**Constraints**\n\nA class or interface must not have multiple *type-constant-declaration*s for the same *name*.\n\nA class having an *abstract-type-constant-declaration* must be abstract. (Any class that defines an abstract type constant must be abstract itself, and any class that inherits an abstract type constant must be either abstract itself or override it with a concrete type constant.\n\nAn interface must not contain a *concrete-type-constant-declaration* that has a *type-constraint*.\n\nWhen overriding a type constant having a *type-constraint*, the overriding type must be a subtype of the constraint type.\n\nA concrete type constant without a *type-constraint* cannot be overridden.\n\n*type-specifier* cannot designate a class type parameter.\n\nBy convention, *name* should begin with an uppercase `T`.\n\n**Semantics**\n\nType constants provide an alternative to [parameterized types](14-generic-types,-methods,-and-functions.md#general). For example, a base class can define an abstract type constant---essentially a name without a concrete type attached---and subclasses each override that with a concrete type constant. Conceptually, type constants are to types, as abstract methods are to methods.\n\nA type constant has public [visibility](16-classes.md#general) and is implicitly [static](16-classes.md#class-members).\n\n*type-constraint* restricts the type by which a type constant can be overridden.\n\nIn an *abstract-type-constant-declaration*, the absence of a *type-constraint* is the same as the presence of one with a type of `mixed`. In a *concrete-type-constant-declaration*, the absence of a *type-constraint* prevents name from being overridden.\n\n**Examples**\n\n```Hack\ninterface I1 {\n  abstract const type T1 as arraykey;\n  public function getID1(): this::T1;\n  const type T4a = int;\n}\n\ninterface I2 {\n  abstract const type T2;\n  public function getID2(this::T2 $p): void;\n  abstract const type T3;\n  const type T4c = string;\n}\n\ninterface I3 extends I2 {\n  public function f(this::T2 $p): void;\n}\n\nclass Ctc6 implements I1, I2 {\n  const type T1 = int;\n  public function __construct(private this::T1 $id) {}\n  public function getID1(): this::T1 {\n    return $this->id;\n  }\n  const type T2 = string;\n  public function getID2(this::T2 $p): void {}\n  const type T3 = float;\n  public function f(this::T4a $p1, this::T4c $p2): void {}\n}\n// -----------------------------------------\nabstract class CBase {\n  abstract const type T;\n  public function __construct(protected this::T $value) {}\n}\n\nclass Cstring extends CBase {\n  const type T = string;\n  public function getString(): string {\n    return $this->value;\t// gets the string\n  }\n}\n\nclass Cint extends CBase {\n  const type T = int;\n  public function getInt(): int {\n    return $this->value;\t// gets the int\n  }\n}\n\nfunction run2(): void {\n  var_dump((new Cstring('abc'))->getString());\n  var_dump((new Cint(123))->getInt());\n}\n```\n\n## Methods with Special Semantics\n\n### General\n\nIf a class contains a definition for a method having one of the\nfollowing names, that method must have the prescribed visibility,\nsignature, and semantics:\n\nMethod Name\t| Description\n------------|-------------\n[`__call`](16-classes.md#method-__call) | Calls a dynamic method in the context of an instance-method call\n[`__callStatic`](16-classes.md#method-__callstatic) | Calls a dynamic method in the context of a static-method call\n[`__clone`](16-classes.md#method-__clone) | Typically used to make a deep copy of an object\n[`__construct`](16-classes.md#constructors) | A constructor\n[`__destruct`](16-classes.md#destructors) | A destructor\n[`__sleep`](16-classes.md#method-__sleep) | Executed before [serialization](16-classes.md#serialization) of an instance of this class\n[`__toString`](16-classes.md#method-__tostring) | Returns a string representation of the instance on which it is called\n[`__wakeup`](16-classes.md#method-__wakeup) | Executed after [unserialization](16-classes.md#serialization) of an instance of this class\n\n### Method `__call`\n\n**Syntax**\n\n<pre>\n  public  function  __call  (  string  <i>$name</i>  ,  array&lt;mixed&gt;  <i>$arguments</i>  )  :  mixed  <i>compound-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*compound-statement*](11-statements.md#compound-statements)\n\n**Semantics**\n\nThis instance method is called to invoke the [dynamic method](16-classes.md#dynamic-methods)\ndesignated by `$name` using the arguments specified by the elements of\nthe array designated by `$arguments`. It can return any value deemed\nappropriate.\n\nTypically, `__call` is called implicitly, when the [`->` operator](10-expressions.md#member-selection-operator) is used to call an instance method that is not visible.\n\nWhile a method-name source token has a prescribed syntax, there are no\nrestrictions on the spelling of the dynamic method name designated by\n*$name*. Any source character is allowed here.\n\n**Examples**\n\n```Hack\nclass Widget {\n  public function __call(string $name, array<mixed> $arguments): mixed {\n    // using the method name and argument list, redirect/process\n    // the method call, as desired.\n  }\n  …\n}\n$obj = new Widget;\n$obj->iMethod(10, true, \"abc\"); // $obj->__call('iMethod', array(…))\n```\n\n### Method `__callStatic`\n\n**Syntax**\n\n<pre>\n  public  static  function  __callStatic  (  string  <i>$name</i>  ,  array&lt;mixed&gt;  <i>$arguments</i>  )  :  mixed\n    <i>compound-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*compound-statement*](11-statements.md#compound-statements)\n\n**Semantics**\n\nThis static method is called to invoke the [dynamic method](16-classes.md#dynamic-methods)\ndesignated by `$name` using the arguments specified by the elements of\nthe array designated by `$arguments`. It can return any value deemed\nappropriate.\n\nTypically, `__callStatic` is called implicitly, when the [`::` operator](10-expressions.md#scope-resolution-operator) is used to call a static method that is not visible. Now while\n`__callStatic` can be called explicitly, the two scenarios do not\nnecessarily produce the same result. Consider the expression `C::m(...)`,\nwhere `C` is a class and `m` is a static-method name. If `m` is the name of a\nvisible method, `C::m(...)` does not result in `__callStatic`'s being\ncalled. Instead, the visible method is used. On the other hand, the\nexpression `C::__callStatic('m',array(...))` always calls the named\ndynamic method, ignoring the fact that a static visible method having\nthe same name might exist. If m is not the name of a visible method, the\ntwo expressions are equivalent; that is; when handling `C::m(...)`, if no\nvisible method by that name is found, a dynamic method is assumed, and\n`__callStatic` is called. (Note: While it would be unusual to create\ndeliberately a static dynamic method with the same name as a static\nvisible one, the visible method might be added later. This name\n\"duplication\" is convenient when adding a dynamic method to a class\nwithout having to worry about a name clash with any method names that\nclass inherits.)\n\nWhile a method-name source token has a prescribed syntax, there are no\nrestrictions on the spelling of the dynamic method name designated by\n`$name`. Any source character is allowed here.\n\n**Examples**\n\n```Hack\nclass Widget {\n  public static function __callStatic(string $name,\n    array<mixed> $arguments): mixed {\n    // using the method name and argument list, redirect/process\n    // the method call, as desired.\n  }\n  …\n}\nWidget::sMethod(null, 1.234); // Widget::__callStatic('sMethod', array(…))\n```\n\n### Method `__clone`\n\n**Syntax**\n\n<pre>\n  public  function  __clone  (  )  :  void  <i>compound-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*compound-statement*](11-statements.md#compound-statements)\n\n**Semantics**\n\nThis instance method is called by the [`clone` operator](10-expressions.md#the-clone-operator),\n(typically) to make a [deep copy](04-basic-concepts.md#cloning-objects) of the current class component of the instance on which it is\ncalled. (Method `__clone` cannot be called directly by the program.) \n\nConsider a class `Employee`, from which is derived a class `Manager`. Let us\nassume that both classes contain properties that are objects. To make a\ncopy of a `Manager` object, its `__clone` method is called to do whatever\nis necessary to copy the properties for the `Manager` class. That method\nshould, in turn, call the `__clone` method of its parent class,\n`Employee`, so that the properties of that class can also be copied (and\nso on, up the derived-class hierarchy).\n\nTo clone an object, the `clone` operator makes a [shallow copy](04-basic-concepts.md#cloning-objects)) of the object on which it is called.\nThen, if the class of the instance being cloned has a method called\n`__clone`, that method is automatically called to make a deep copy.\nMethod `__clone` cannot be called directly from outside a class; it can\nonly be called by name from within a derived class, using the notation\n`self::__clone()`. This method can return a value; however, if it does\nso and control returns directly to the point of invocation via the `clone`\noperator, that value will be ignored. The value returned to a\n`self::__clone()` call can, however, be retrieved.\n\nWhile cloning creates a new object, it does so without using a\nconstructor, in which case, code may need to be added to the `__clone`\nmethod to emulate what happens in a corresponding constructor. (See the\n`Point` example below.)\n\n**Examples**\n\n```Hack\nclass Employee {\n  …\n  public function __clone(): void {\n    // do what it takes here to make a copy of Employee object properties\n  }\n}\nclass Manager extends Employee {\n  …\n  public function __clone(): void {\n    parent::__clone(); // request cloning of the Employee properties\n    // do what it takes here to make a copy of Manager object properties\n  }\n  …\n}\n// -----------------------------------------\nclass Point {\n  private static int $pointCount = 0;\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    …\n    ++self::$pointCount;\n  }\n  public function __clone(): void {\n    ++self::$pointCount; // emulate the constructor\n  }\n  …\n}\n$p1 = new Point();  // created using the constructor\n$p2 = clone $p1;  // created by cloning\n```\n\n### Method `__sleep`\n\n**Syntax**\n\n<pre>\npublic  function  __sleep  ( )  :  array&lt;string&gt;  <i>compound-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*compound-statement*](11-statements.md#compound-statements)\n\n**Semantics**\n\nThe instance methods [`__sleep` and `__wakeup`](16-classes.md#method-__wakeup) support\n[serialization](16-classes.md#serialization).\n\nIf a class has a `__sleep` method, the library function [`serialize`](http://www.php.net/serialize)\ncalls that method to find out which visible instance properties it\nshould serialize. (In the absence of a `__sleep` or `serialize` method,\nall such properties are serialized.) This information is returned by `__sleep` as an array of zero\nor more elements, where each element's value is distinct and is the name\nof a visible instance property. These properties' values are serialized\nin the order in which the elements are inserted in the array. If\n`__sleep` does not return a value explicitly, `null` is returned, and that\nvalue is serialized.\n\nBesides creating the array of property names, `__sleep` can do whatever\nelse might be needed before serialization occurs.\n\nConsider a `Point` class that not only contains x- and y-coordinates, it\nalso has an `id` property; that is, each distinct `Point` created during a\nprogram's execution has a unique numerical id. However, there is no need\nto include this when a `Point` is serialized. It can simply be recreated\nwhen that `Point` is unserialized. This information is transient and need\nnot be preserved across program executions. (The same can be true for\nother transient properties, such as those that contain temporary results\nor run-time caches.)\n\nIn the absence of methods `__sleep` and `__wakeup`, instances of derived\nclasses can be serialized and unserialized. However, it is not possible\nto perform customize serialization using those methods for such\ninstances. For that, a class must implement the interface [`Serializable`](17-interfaces.md#interface-iteratoraggregate).\n\n**Examples**\n\n```Hack\nclass Point {\n  private static int $nextId = 1;\n  private float $x;\n  private float $y;\n  private int $id;\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    $this->x = $x;\n    $this->y = $y;\n    $this->id = self::$nextId++;  // assign the next available id\n  }\n  public function __sleep(): array<string> {\n    return array('y', 'x'); // serialize only $y and $x, in that order\n  }\n  public function __wakeup(): void {\n    $this->id = self::$nextId++;  // assign a new id\n  }\n  …\n}\n$p = new Point(-1, 0);\n$s = serialize($p);   // serialize Point(-1,0)\n$v = unserialize($s);   // unserialize Point(-1,0)\n```\n\n### Method `__toString`\n\n**Syntax**\n\n<pre>\npublic  function  __toString  ( )  :  string  <i>compound-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*compound-statement*](11-statements.md#compound-statements)\n\n**Constraints**\n\nThis function must not throw any exceptions.\n\n**Semantics**\n\nThis instance method is intended to create a string representation of\nthe instance on which it is called. If the instance's class is derived\nfrom a class that has or inherits a `__toString` method, the result of\ncalling that method should be prepended to the returned string.\n\n`__toString` is called by a number of language and library facilities,\nincluding `echo`, when an object-to-string conversion is needed.\n`__toString` can be called directly.\n\n**Examples**\n\n```Hack\nclass Point {\n  private float $x;\n  private float $y;\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    $this->x = $x;\n    $this->y = $y;\n  }\n  public function __toString(): string {\n    return '(' . $this->x . ',' . $this->y . ')';\n  }\n  …\n}\n$p1 = new Point(20, 30);\necho $p1 . \"\\n\";  // implicit call to __toString() returns \"(20,30)\"\n// -----------------------------------------\nclass MyRangeException extends Exception {\n  public function __toString(): string {\n    return parent::__toString()\n      . string-representation-of-MyRangeException\n  }\n  …\n}\n```\n\n### Method `__wakeup`\n\n**Syntax**\n\n<pre>\npublic  function  __wakeup  ( )  : void  <i>compound-statement</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*compound-statement*](11-statements.md#compound-statements)\n\n**Semantics**\n\nThe instance methods [`__sleep` and `__wakeup`](16-classes.md#method-__sleep) support\n[serialization](16-classes.md#serialization)).\n\nWhen the library function [`unserialize`](http://www.php.net/unserialize) is called on the string\nrepresentation of an object, as created by the library function\n[`serialize`](http://www.php.net/serialize), `unserialize` creates an instance of that object's type\n**without calling a constructor**, and then calls that class's\n`__wakeup` method, if any, to initialize the instance. In the absence of\na `__wakeup` method, all that is done is that the values of the instance\nproperties encoded in the serialized string are restored.\n\nConsider a `Point` class that not only contains x- and y-coordinates, it\nalso has an `id` property; that is, each distinct `Point` created during a\nprogram's execution has a unique numerical id. However, there is no need\nto include this when a `Point` is serialized. It can simply be recreated\nby `__wakeup` when that `Point` is unserialized. This means that\n`__wakeup` must emulate the constructor, as appropriate.\n\n**Examples**\n\nSee [§§](16-classes.md#method-__sleep).\n\n## Serialization\n\nIn Hack, variables can be converted into some external form suitable for\nuse in file storage or inter-program communication. The process of\nconverting to this form is known as *serialization* while that of\nconverting back again is known as *unserialization*. These facilities\nare provided by the library functions [`serialize`](http://www.php.net/serialize) and [`unserialize`](http://www.php.net/unserialize), respectively. (Library function [`serialize_memoize_param`](http://www.php.net/serialize_memoize_param) helps when serializing parameters to async functions.)\n\nIn the case of variables that are objects, on their own, these two\nfunctions serialize and unserialize all the instance properties, which\nmay be sufficient for some applications. However, if the programmer\nwants to customize these processes, they can do so in one of two,\nmutually exclusive ways. The first approach is to define methods called\n`__sleep` and `__awake`, and have them get control before serialization\nand after serialization, respectively. For information on this approach,\nsee [§§](16-classes.md#method-__sleep) and [§§](16-classes.md#method-__wakeup). The second approach involves implementing\nthe interface [`Serializable`](17-interfaces.md#interface-Serializable) by defining two methods, `serialize`\nand `unserialize`.\n\nConsider a `Point` class that not only contains x- and y-coordinates, it\nalso has an `id` property; that is, each distinct `Point` created during a\nprogram's execution has a unique numerical id. However, there is no need\nto include this when a `Point` is serialized. It can simply be recreated\nwhen that `Point` is unserialized. This information is transient and need\nnot be preserved across program executions. (The same can be true for\nother transient properties, such as those that contain temporary results\nor run-time caches.) Furthermore, consider a class `ColoredPoint` that\nextends `Point` by adding a `color` property. The following code shows how\nthese classes need be defined in order for both `Points` and `ColoredPoints`\nto be serialized and unserialized:\n\n```Hack\nclass Point implements Serializable { // note the interface\n  private static int $nextId = 1;\n  private float $x;\n  private float $y;\n  private int $id;  // transient property; not serialized\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    $this->x = $x;\n    $this->y = $y;\n    $this->id = self::$nextId++;\n  }\n  public function __toString(): string {\n    return 'ID:' . $this->id . '(' . $this->x . ',' . $this->y . ')';\n  }\n  public function serialize(): string {\n    return serialize(array('y' => $this->y, 'x' => $this->x));\n  }\n```\n\nThe custom method `serialize` calls the library function `serialize` to\ncreate a string version of the array, whose keys are the names of the\ninstance properties to be serialized. The insertion order of the array\nis the order in which the properties are serialized in the resulting\nstring. The array is returned.\n\n```Hack\n  public function unserialize(string $data): void {\n    $data = unserialize($data);\n    $this->x = $data['x'];\n    $this->y = $data['y'];\n    $this->id = self::$nextId++;\n  }\n}\n```\n\nThe custom method `unserialize` converts the serialized string passed to\nit back into an array. Because a new object is being created, but\nwithout any constructor being called, the `unserialize` method must\nperform the tasks ordinarily done by a constructor. In this case, that\ninvolves assigning the new object a unique id.\n\n```Hack\n$p = new Point(2, 5);\n$s = serialize($p);\n```\n\nThe call to the library function `serialize` calls the custom `serialize`\nmethod. Afterwards, the variable `$s` contains the serialized version of\nthe `Point(2,5)`, and that can be stored in a database or transmitted to a\ncooperating program. The program that reads or receives that serialized\nstring can convert its contents back into the corresponding variable(s),\nas follows:\n\n```Hack\n$v = unserialize($s);\n```\n\nThe call to the library function `unserialize` calls the custom\n`unserialize` method. Afterwards, the variable `$s` contains a new\n`Point(2,5)`.\n\n\n```Hack\nclass ColoredPoint extends Point implements Serializable {\n  const RED = 1;\n  const BLUE = 2;\n  private int $color; // an instance property\n\n  public function __construct(float $x = 0.0, float $y = 0.0,\n    int $color = ColoredPoint::RED) {\n    parent::__construct($x, $y);\n    $this->color = $color;\n  }\n\n  public function __toString(): string {\n    return parent::__toString() . $this->color;\n  }\n\n  public function serialize(): string {\n    return serialize(array(\n      'color' => $this->color,\n      'baseData' => parent::serialize()\n    ));\n  }\n```\n\nAs with class `Point`, this custom method returns an array of the instance\nproperties that are to be serialized. However, in the case of the second\nelement, an arbitrary key name is used, and its value is the serialized\nversion of the base Point within the current `ColoredPoint` object. The\norder of the elements is up to the programmer.\n\n```Hack\n  public function unserialize(string $data): void {\n    $data = unserialize($data);\n    $this->color = $data['color'];\n    parent::unserialize($data['baseData']);\n  }\n}\n```\n\nAs `ColoredPoint` has a base class, it unserializes its own instance\nproperties before calling the base class's custom method, so it can\nunserialize the `Point` properties.\n\n```Hack\n$cp = new ColoredPoint(9, 8, ColoredPoint::BLUE);\n$s = serialize($cp);\n...\n$v = unserialize($s);\n```\n\n## Predefined Classes\n\n### Class `AsyncGenerator`\n\nThis class supports the `yield` operator when dealing with asynchronous operations. This class cannot be instantiated directly. It is defined, as follows:\n\n```Hack\nclass AsyncGenerator<Tk,Tv,Ts> implements AsyncKeyedIterator {\n  public function next(): Awaitable<?tuple<Tk,Tv>>;\n  public function raise(Exception $e): Awaitable<?tuple<Tk,Tv>>;\n  public function send(?Ts $v): Awaitable<?tuple<Tk,Tv>>;\n}\n```\n\nThe class members are defined below:\n\nName | Purpose\n---- | -------\n`next` | Returns the `Awaitable<T>` associated with the next key/value tuple in the async generator, or `null` if the end of the iteration has been reached. (The result should always be subject to an `awai`t to get the actual key/value tuple. This function cannot be called without having the value returned from a previous call to `next`, `send`, or `raise` having first been the subject of an `await`.)\n`raise` | Raises exception *$e* to the async generator. (This function cannot be called without having the value returned from a previous call to `next`, `send`, or `raise` having first been the subject of an `await`.)\n`send` | Sends value *$v* to the async generator and resumes execution of that generator. (This function cannot be called without having the value returned from a previous call to `next`, `send`, or `raise` having first been the subject of an `await`.) If *$v* is `null`, the call is equivalent to calling `next`.\n\n### Class `Generator`\n\nThis class supports the [`yield` operator](10-expressions.md#yield-operator). This class cannot be\ninstantiated directly. It is defined, as follows:\n\n```Hack\nclass Generator implements Iterator {\n  public function current(): mixed;\n  public function key(): mixed;\n  public function next(): void;\n  public function rewind(): void;\n  public function send(mixed $value): mixed;\n  public function throw(Exception $exception): mixed;\n  public function valid(): bool;\n  public function __wakeup(): void;\n```\nThe type `Continuation<T>` is an alias for `Generator<int, T, void>`.\n\nThe class members are defined below:\n\nName | Purpose\n---- | -------\n`current` | An implementation of the instance method [`Iterator::current`](17-interfaces.md#interface-Iterator).\n`key` | An implementation of the instance method [`Iterator::key`](17-interfaces.md#interface-Iterator).\n`next` | An implementation of the instance method [`Iterator::next`](17-interfaces.md#interface-Iterator).\n`rewind` | An implementation of the instance method [`Iterator::rewind`](17-interfaces.md#interface-Iterator).\n`send` | This instance method sends the value designated by `$value` to the generator as the result of the current [`yield`](http://us2.php.net/manual/en/ language.generators.syntax.php#control-structures.yield) expression, and resumes execution of the generator. `$value` is the return value of the [`yield`](http://us2.php.net/manual/en/language.generators.syntax.php#control-structures.yield) expression the generator is currently at. If the generator is not at a [`yield`](http://us2.php.net/manual/en/language.generators.syntax.php#control-structures.yield) expression when this method is called, it will first be let to advance to the first [`yield`](http://us2.php.net/manual/en/language.generators.syntax.php#control-structures.yield) expression before sending the value. This method returns the yielded value.\n`throw` | This instance method throws an exception into the generator and resumes execution of the generator. The behavior is as if the current [`yield`](http://us2.php.net/manual/en/language.generators.syntax.php#control-structures.yield) expression was replaced with throw `$exception`. If the generator is already closed when this method is invoked, the exception will be thrown in the caller's context instead. This method returns the yielded value.\n`valid` |  An implementation of the instance method [`Iterator::valid`](17-interfaces.md#interface-Iterator).\n`__wakeup` | An implementation of the special instance method [`__wakeup`](16-classes.md#method-__wakeup). As a generator can't be serialized, this method throws an exception of an unspecified type. It returns no value.\n\n### Class `__PHP_Incomplete_Class`\n\nThere are certain circumstances in which a program can generate an\ninstance of this class, which on its own contains no members. One\ninvolves an attempt to unserialize ([§§](#method-__wakeup), [§§](#serialization)) a string that\nencodes an instance of a class for which there is no definition in\nscope. Consider the following class, which supports a two-dimensional\nCartesian point:\n\n```Hack\nclass Point {\n  private float $x;\n  private float $y;\n  …\n}\n$p = new Point(2, 5);\n$s = serialize($p); // properties $x and $y are serialized, in that order\n```\n\nLet us assume that the serialized string is stored in a database from\nwhere it is retrieved by a separate program. That program contains the\nfollowing code, but does not contain a definition of the class Point:\n\n```Hack\n$v = unserialize($s);\n```\n\nInstead of returning a point, `Point(2, 5`), an instance of\n`__PHP_Incomplete_Class` results, with the following contents:\n\n```Hack\n__PHP_Incomplete_Class {\n   __PHP_Incomplete_Class_Name => \"Point\"\n  x:Point:private => 2\n  y:Point:private => 5\n}\n```\n\nThe three properties contain the name of the unknown\nclass, and the name, visibility, and value of each property that was\nserialized, in order of serialization.\n\n### Class `Shapes`\n\nThis class provides some shape-related methods. It is defined, as follows:\n\n```Hack\nabstract final class Shapes {\n  public static function idx(S $shape, arraykey $index) : ?Tv;\n  public static function idx(S $shape, arraykey $index, Tv $default) : Tv;\n  public static function keyExists(S $shape, arraykey $index): bool;\n  public static function removeKey(S $shape, arraykey $index): void;\n  public static function toArray(S $shape): array<arraykey, mixed>;\n}\n```\n\nwhere S is any shape type.\n\nThe class members are defined below:\n\nName | Purpose\n---- | -------\n`idx` | This method searches shape `$shape` for the field named `$index`. If the field exists, its value is returned; otherwise, a default value is returned. For a field of type `T`, the function returns a value of type `?T`. A default value `$default` can be provided; however, if that argument is omitted, the value `null` is used. `$index` must be a single-quoted string or a class constant of type `string` or `int`.\n`keyExists` | This method searches shape `$shape` for the field named `$index`. If the field exists, `true` is returned; otherwise, `false` is returned. `$index` must be a single-quoted string or a class constant of type `string` or `int`.\n`removeKey` | Given a shape `$shape` and a field name `$index`, this method removes the specified field from that shape. If the field specified does not exist, the removal request is ignored. `$index` must be a single-quoted string or a class constant of type `string` or `int`.\n`toArray` | This method returns an array of type `array<arraykey, mixed>` containing one element for each field in the shape `$shape`. Each element's key and value are the name and value, respectively, of the corresponding field.\n\n### Class `stdClass`\n\nThis class contains no members. It can be instantiated and used as a\nbase class.\n"
  },
  {
    "path": "spec/17-interfaces.md",
    "content": "# Interfaces\n\n## General\n\nA class can implement a set of capabilities—herein called a\n*contract*—through what is called an interface. An *interface* is a set\nof method declarations and constants.  Note that the methods are only\ndeclared, not defined; that is, an interface defines a type consisting\nof abstract methods, where those methods are implemented by client\nclasses as they see fit. An interface allows unrelated classes to\nimplement the same facilities with the same names and types without\nrequiring those classes to share a common base class.\n\nAn interface can extend one or more other interfaces, in which case, it\ninherits all members from its *base interface(s)*.\n\n## Interface Declarations\n\n**Syntax**\n\n<pre>\n  <i>interface-declaration:</i>\n    <i>attribute-specification<sub>opt</sub></i>  interface  <i>name</i>  <i>generic-type-parameter-list<sub>opt</sub></i>  <i>interface-base-clause<sub>opt</sub></i> {\n      <i>interface-member-declarations<sub>opt</sub></i>  }\n\n  <i>interface-base-clause:</i>\n    extends  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n    <i>interface-base-clause</i>  ,  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n</pre>\n\n**Defined elsewhere**\n\n* [*attribute-specification*](21-attributes.md#attribute-specification)\n* [*generic-type-parameter-list*](14-generic-types-methods-and-functions.md#type-parameters)\n* [*generic-type-argument-list*](14-generic-types-methods-and-functions.md#type-parameters)\n* [*interface-member-declarations*](17-interfaces.md#interface-members)\n* [*name*](09-lexical-structure.md#names)\n* [*qualified-name*](20-namespaces.md#defining-namespaces)\n\n**Constraints**\n\nAn interface must not be derived directly or indirectly from itself.\n\n*qualified-name* must name an interface type.\n\nA generic interface and a non-generic interface in the same scope cannot have the same *name*.\n\n**Semantics**\n\nAn interface-declaration defines a contract that one or more classes can\nimplement.\n\nInterface names are case-insensitive.\n\nThe optional *interface-base-clause* specifies the base interfaces from\nwhich the interface being defined is derived. In such a case, the\nderived interface inherits all the members from the base interfaces.\n\n**Examples**\n\n```Hack\ninterface MyCollection<T> {\n  const MAX_NUMBER_ITEMS = 1000;\n  public function put(T $item): void;\n  public function get(): T;\n}\nclass MyList<T> implements MyCollection<T> {\n  public function put(T $item): void    { /* implement method */ }\n  public function get(): T          { /* implement method */ }\n  …\n}\nclass MyQueue<T> implements MyCollection<T> {\n  public function put(T $item): void    { /* implement method */ }\n  public function get(): T          { /* implement method */ }\n  …\n}\nfunction processCollection<T>(MyCollection<T> $p1): void {\n  … /* can process any object whose class implements MyCollection\n}\nprocessCollection(new MyList(…));\nprocessCollection(new MyQueue(…));\n```\n\n## Interface Members\n\n**Syntax**\n\n<pre>\n  <i>interface-member-declarations:</i>\n    <i>interface-member-declaration</i>\n    <i>interface-member-declarations   interface-member-declaration</i>\n  <i>interface-member-declaration:</i>\n    <i>require-extends-clause</i>\n    <i>const-declaration</i>\n    <i>method-declaration</i>\n    <i>type-constant-declaration</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*const-declaration*](16-classes.md#constants)\n* [*method-declaration*](16-classes.md#methods)\n* [*require-extends-clause*](18-traits.md#trait-members)\n* [*type-constant-declaration*](16-classes.md#type-constants)\n\n**Constraints**\n\nThe *qualified-name* in *requires-extends-clause* must designate a class name.\n\n**Semantics**\n\nThe members of an interface are those specified by its\n*interface-member-declaration*s, and the members inherited from its base\ninterfaces.\n\nAn interface may contain the following members:\n\n* *require-extends-clauses* each of which requires the class implementing this interface to directly or indirectly extend the class type designated by *qualified-name*.\n* [Constants](17-interfaces.md#constants) – the constant values associated with the interface.\n* [Methods](17-interfaces.md#methods) – placeholders for the computations and actions that can be performed by implementers of the interface.\n*\t[Type constants](16-classes.md#type-constants) – a way of parameterizing class types without using generics.\n\nAn *interface-member-declarations* may contain multiple *require-extends-clause*s that designate the same class, in which case, the duplicates are redundant. \n\n## Constants\n\n**Semantics**\n\nAn interface constant is just like a [class constant](16-classes.md#constants), except that\nan interface constant cannot be overridden by a class that implements it\nnor by an interface that extends it.\n\n**Examples:**\n\n```Hack\ninterface MyCollection<T> {\n  const MAX_NUMBER_ITEMS = 1000;\n  public function put(T $item): void;\n  public function get(): T;\n}\n```\n\n## Methods\n\n**Constraints**\n\nMethods declared in an interface must not be declared `abstract`.\n\nAn interface method must not also be asynchronous. However, a method can have a return-type of `Awaitable<T>`, so an async concrete implementation can be provided.\n\n**Semantics:**\n\nAn interface method is just like an [abstract method](16-classes.md#methods).\n\n**Examples:**\n\n```Hack\ninterface MyCollection<T> {\n  const MAX_NUMBER_ITEMS = 1000;\n  public function put(T $item): void;\n  public function get(): T;\n}\n```\n\n## Predefined Interfaces\n\n### Interface `ArrayAccess`\n\nThis interface allows an instance of an implementing class to be\naccessed using array-like notation. This interface is defined, as\nfollows:\n\n```Hack\ninterface ArrayAccess<string, T> {\n  public function offsetExists(string $offset): bool;\n  public function offsetGet(string $offset): T;\n  public function offsetSet(string $offset, T $value): this;\n  public function offsetUnset(string $offset): this;\n```\n\nThe interface members are defined below:\n\nName\t|   Purpose\n----    |   -------\n`offsetExists`  |\tThis instance method returns `true` if the instance contains an element with key `$offset`, otherwise, `false`.\n`offsetGet`\t|  This instance method gets the value having key `$offset`. This method is called when an instance of a class that implements this interface is [subscripted](10-expressions.md#subscript-operator) in a non-lvalue context.\n`offsetSet`\t| This instance method sets the value having key `$offset` to $value. This method is called when an instance of a class that implements this interface is [subscripted](10-expressions.md#subscript-operator) in a modifiable-lvalue context.\n`offsetUnset`\t| This instance method removes the value having key `$offset`.\n\n### Interface `AsyncIterator`\n\nThis interface supports iteration over the values returned from an [asynchronous generator function](10-expressions.md#yield-operator). It is defined, as follows:\n\n```Hack\ninterface AsyncIterator<Tv> {\n  public function next(): Awaitable<?tuple<mixed,Tv>> \n}\n```\n\nThe interface members are defined below:\n\nName  |  Purpose\n----  |  -------\n`next` | This instance method moves the async iterator to the next `Awaitable` position.\n\n### Interface `AsyncKeyedIterator`\n\nThis interface supports iteration over the keys and values returned from an [asynchronous generator function](10-expressions.md#yield-operator). It is defined, as follows:\n\n```Hack\ninterface AsyncKeyedIterator<Tk,Tv> implements AsyncIterator<Tv> {\n  public function next(): Awaitable<?tuple<Tk,Tv>> \n}\n```\n\nThe interface members are defined below:\n\nName  |  Purpose\n----  |  -------\n`next` | This instance method moves the async iterator to the next `Awaitable` position.\n\n### Interface `Awaitable`\n\nAn instance of this interface is an awaitable object. Such objects are used in support of [asynchronous functions](15-functions.md#asynchronous-functions) and [await](10-expressions.md#await-operator). This interface is defined, as follows:\n\n```Hack\ninterface Awaitable<T> {\n  // unspecified\n}\n```\n\nThe interface members are unspecified.\n\n### Interface `Container`\n\nThis interface is a marker for the predefined types `Vector`, `ImmVector`, `Map`, `ImmMap`, `Set`, `ImmSet`, and `Pair` and all array types. This interface is defined, as follows:\n\n```Hack\ninterface Container<Tv> extends Traversable<Tv> {\n}\n```\n\nThis interface has no members.\n\n### Interface `IMemoizeParam`\n\nInstances of classes that implement this interface can be passed to `serialize_memoize_param` and to functions having the [`__Memoize` attribute](21-attributes.md#Attribute-__Memoize). It is defined, as follows:\n\n```Hack\ninterface IMemoizeParam implements AsyncIterator<Tv> {\n  public function getInstanceKey(): string;\n}\n```\n\nThe interface members are defined below:\n\nName  |  Purpose\n----  |  -------\n`getInstanceKey` | Serializes the object to a string that can be used as a dictionary key to differentiate instances of this class.\n\n### Interface `Iterator`\n\nThis interface allows instances of an implementing class to be treated\nas a collection. This interface is defined, as follows:\n\n```Hack\ninterface Iterator<Tv> extends Traversable<Tv> {\n  public function current(): Tv;\n  public function next(): void;\n  public function rewind(): void;\n  public function valid(): bool;\n}\n```\n\nThe interface members are defined below:\n\nName | Purpose\n---- | -------\n`current` | This instance method returns the element at the current position.\n`next` | This instance method moves the current position forward to the next element. From within a `foreach` statement, this method is called after each loop.\n`rewind` |  This instance method resets the current position to the first element. From within a `foreach` statement, this method is called once, at the beginning.\n`valid` | This instance method checks if the current position is valid. It takes no arguments. It returns a bool value of `true` to indicate the current position is valid; `false`, otherwise. This method is called after each call to [`Iterator::rewind()`](http://docs.hhvm.com/manual/en/iterator.rewind.php) and [`Iterator::next()`](http://docs.hhvm.com/manual/en/iterator.next.php).\n\n### Interface `IteratorAggregate`\n\nThis interface allows the creation of an external iterator. This\ninterface is defined, as follows:\n\n```Hack\ninterface IteratorAggregate<Tv> extends Traversable<Tv> {\n  public function getIterator(): Iterator<Tv>;\n}\n```\nThe interface members are defined below:\n\nName    |   Purpose\n----    |   -------\n`getIterator` | This instance method retrieves an iterator, which implements `Iterator` or `Traversable`. It throws an `\\Exception` on failure.\n\n### Interface `KeyedContainer`\n\nThis interface is a marker for the predefined types `Vector`, `ImmVector`, `Map`, `ImmMap`, and `Pair` and all array types. This interface is defined, as follows:\n\n```Hack\ninterface KeyedContainer<Tk, Tv> extends Container<Tv>, \n  KeyedTraversable<Tk, Tv> {\n}\n```\n\nThis interface has no members.\n\n### Interface `KeyedTraversable`\n\nThis interface detects if a class is traversable using `foreach`. This interface is defined, as follows:\n\n```Hack\nKeyedTraversable<Tk, Tv> extends Traversable<Tv> {\n}\n```\n\nThis interface has no members.\n\nThis interface has no members.\n\n### Interface  `Serializable`\n\nThis interface provides support for custom serialization. It is defined,\nas follows:\n\n```Hack\ninterface Serializable {\n  public function serialize(): string;\n  public function unserialize (string $serialized): void;\n}\n```\n\nThe interface members are defined below:\n\nName |\tPurpose\n-----|  -------\n`serialize` | This instance method returns a string representation of the current instance. On failure, it returns `null`.\n`unserialize` | This instance method constructs an object from its string form designated by `$serialized`.\n\n### Interface `Stringish`\n\nThis interface requires an implementing class to provide a conversion to string representation. It is defined, as follows:\n\n```Hack\ninterface Stringish {\n  public function __toString(): string;\n}\n```\n\nThe interface members are defined below:\n\n### Interface `Traversable`\n\nThis interface is intended as the base interface for all traversable\nclasses. This interface is defined, as follows:\n\n```Hack\nTraversable<Tv>\n{\n}\n```\n\n"
  },
  {
    "path": "spec/18-traits.md",
    "content": "# Traits\n\n## General\n\nHack's class model allows [single inheritance](16-classes.md#general) with contracts\nbeing enforced separately via [interfaces](17-interfaces.md#general). A *trait* can provide\nboth implementation and contracts. Specifically, a class can inherit\nfrom a base class while getting implementation from one or more traits.\nAt the same time, that class can implement contracts from one or more\ninterfaces as well as from one or more traits. The use of a trait by a\nclass does not involve any inheritance hierarchy, so unrelated classes\ncan use the same trait. In summary, a trait is a set of methods and/or\nstate information that can be reused.\n\nTraits are designed to support classes; a trait cannot be instantiated\ndirectly.\n\nThe members of a trait each have [visibility](16-classes.md#general), which applies once\nthey are used by a given class. The class that uses a trait can change\nthe visibility of any of that trait's members, by either widening or\nnarrowing that visibility. For example, a private trait member can be\nmade public in the using class, and a public trait member can be made\nprivate in that class.\n\nOnce implementation comes from both a base class and one or more traits,\nname conflicts can occur. However, trait usage provides a means of\ndisambiguating such conflicts. Names gotten from a trait can also be\ngiven aliases.\n\nA class member with a given name overrides one with the same name in any\ntraits that class uses, which, in turn, overrides any such name from\nbase classes. \n\nTraits can contain both instance and static members, including both\nmethods and properties. In the case of a trait with a static property,\neach class using that trait has its own instance of that property.\n\nMethods in a trait have full access to all members of any class in which\nthat trait is used.\n\n## Trait Declarations\n\n**Syntax**\n\n<pre>\n  <i>trait-declaration:</i>\n   <i>attribute-specification<sub>opt</sub></i>  trait  <i>name</i>  <i>generic-type-parameter-list<sub>opt</sub></i>  <i>class-interface-clause<sub>opt</sub></i>  {\n     <i>trait-use-clauses<sub>opt</sub>  trait-member-declarations<sub>opt</sub></i>  }\n\n  <i>trait-use-clauses:</i>\n    <i>trait-use-clause</i>\n    <i>trait-use-clauses</i>  <i>trait-use-clause</i>\n\n  <i>trait-use-clause:</i>\n    use  <i>trait-name-list</i>  ;\n\n  <i>trait-name-list:</i>\n    <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n    <i>trait-name-list</i>  ,  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n</pre>\n\n**Defined elsewhere**\n\n* [*attribute-specification*](21-attributes.md#attribute-specification)\n* [*class-interface-clause*](16-classes.md#class-declarations)\n* [*generic-type-argument-list*](14-generic-types-methods-and-functions.md#type-parameters)\n* [*generic-type-parameter-list*](14-generic-types-methods-and-functions.md#type-parameters)\n* [*name*](09-lexical-structure.md#names)\n* [*trait-member-declarations*](18-traits.md#trait-members)\n\n**Constraints**\n\nThe *name*s in *trait-name-list* must designate trait names, excluding\nthe name of the trait being declared.\n\nA generic trait and a non-generic trait in the same scope cannot have the same name.\n\n**Semantics**\n\nA *trait-declaration* defines a named set of members, which are made\navailable to any class that uses that trait.\n\nTrait names are [case-preserved](03-terms-and-definitions.md).\n\nA *trait-declaration* may also use other traits. This is done via one or\nmore *trait-use-clause*s, each of which contains a comma-separated list\nof trait names.\n\nThe optional *class-interface-clause* specifies the one or more interfaces that must be implemented by any class that uses this trait.\n\n**Examples**\n\n```Hack\ntrait T1 { public function compute( … ) : … { … } }\ntrait T2 { public function compute( … ) : … { … } }\ntrait T1 { public function sort( … ) : … { … } }\ntrait T4 {\n  use T3;\n  use T1, T2;\n}\n```\n\n## Trait Members\n\n**Syntax**\n\n<pre>\n  <i>trait-member-declarations:</i>\n    <i>trait-member-declaration</i>\n    <i>trait-member-declarations   trait-member-declaration</i>\n\n  <i>trait-member-declaration:</i>\n    <i>require-extends-clause</i>\n    <i>require-implements-clause</i>\n    <i>property-declaration</i>\n    <i>method-declaration</i>\n    <i>constructor-declaration</i>\n    <i>destructor-declaration</i>\n\n  <i>require-extends-clause:</i>\n    require  extends  <i>qualified-name</i>  ;\n  <i>require-implements-clause:</i>\n    require  implements  <i>qualified-name</i>  ;\n</pre>\n\n**Defined elsewhere**\n\n* [*constructor-declaration*](16-classes.md#constructors)\n* [*destructor-declaration*](16-classes.md#destructors)\n* [*method-declaration*](16-classes.md#methods)\n* [*property-declaration*](16-classes.md#properties)\n* [*qualified-name*](20-namespaces.md#defining-namespaces)\n\n**Constraints**\n\nThe *qualified-name* in *require-extends-clause* must designate the name of a class that does not directly use the trait being defined.\n\nThe *qualified-name* in *require-implements-clause* must designate the name of an interface that does not directly use the trait being defined.\n\n**Semantics**\n\nThe members of a trait are those specified by its\n*trait-member-declaration*s, and the members from any other traits it\nuses.\n\nA trait may contain the following members:\n\n* *require-extends-clauses* each of which requires the class using this trait to directly or indirectly extend the class type designated by *qualified-name*.\n* *require-implements-clauses* each of which requires the class using this trait to directly or indirectly implement the interface type designated by *qualified-name*.\n* [Properties](16-classes.md#properties) – the variables made available to the class in which the trait is used.\n* [Methods](16-classes.md#methods) – the computations and actions that can be performed by the class in which the trait is used. See also [§§](16-classes.md#methods-with-special-semantics).\n* [Constructor](16-classes.md#constructors) – the actions required to initialize an instance of the class in which the trait is used.\n* [Destructor](16-classes.md#destructors) – the actions to be performed when an instance of the class in which the trait is used is no longer needed.\n\n*trait-member-declarations* may contain multiple *require-extends-clauses* that designate the same class, in which case, the duplicates are redundant. \n\n*trait-member-declarations* may contain multiple *require-implements-clauses* that designate the same interface, in which case, the duplicates are redundant.\n\n**Examples**\n\n```Hack\ntrait T {\n  require extends C1;\n  private int $prop1 = 1000;\n  require implements I1;\n  protected static int $prop2;\n  public function compute( … ): void { … }\n  public static function getData( … ): void { … }\n}\n```\n\n\n"
  },
  {
    "path": "spec/19-exception-handling.md",
    "content": "# Exception Handling\n\n## General\n\nAn *exception* is some unusual condition in that it is outside the\nordinary expected behavior. (Examples include dealing with situations in\nwhich a critical resource is needed, but is unavailable, and detecting\nan out-of-range value for some computation.) As such, exceptions require\nspecial handling. This chapter describes how exceptions can be created\nand handled.\n\nWhenever some exceptional condition is detected at runtime, an exception\nis *thrown*. A designated exception handler can *catch* the thrown\nexception and service it. Among other things, the handler might recover\nfrom the situation completely (allowing the script to continue\nexecution), it might perform some recovery and then throw an exception\nto get further help, or it might perform some cleanup action and\nterminate the script. Exceptions may be thrown on behalf of the Engine\nor by explicit code source code in the script.\n\nException handling involves the use of the following keywords:\n\n* [`try`](11-statements.md#the-try-statement), which allows a *try-block* of code containing one or more possible exception generations, to be tried\n* [`catch`](11-statements.md#the-try-statement), which defines a handler for a specific type of exception thrown from the corresponding try-block or from some function it calls\n* [`finally`](11-statements.md#the-try-statement), which allows the *finally-block* of a try-block to be executed (to perform some cleanup, for example), whether or not an exception occurred within that try-block\n* [`throw`](11-statements.md#the-throw-statement), which generates an exception of a given type, from a place called a *throw point*.\n\nWhen an exception is thrown, an *exception object* of type [`\\Exception`](19-exception-handling.md#class-exception), or of a subclass of that type, is created and made available to\nthe first catch-handler that can catch it. Among other things, the\nexception object contains an *exception message* and an *exception\ncode*, both of which can be used by a handler to decide how to handle\nthe situation.\n\n## Class `Exception`\n\nClass `Exception` is the base class of all exception types. This class is\ndefined, as follows:\n\n```Hack\nclass Exception {\n  protected string $message = 'Unknown exception';\n  protected int $code = 0;\n  protected string $file;\n  protected int $line;\n  protected ?Exception $previous = null;\n\n  public function __construct(string $message = \"\", int $code = 0,\n    ?Exception $previous = null);\n\n  final private function __clone(): void;\n\n  final public function getMessage(): string;\n  final public function getCode(): int;\n  final public function getFile(): string;\n  final public function getLine(): int;\n  final public function getTrace(): array<mixed>;\n  final public function getPrevious(): ?Exception;\n  final public function getTraceAsString(): string;\n  public function __toString(): string;\n}\n```\n\nFor information about exception trace-back, see [§§](19-exception-handling.md#tracing-exceptions). For information\nabout nested exceptions, see [§§](19-exception-handling.md#tracing-exceptions). \n\nThe class members are defined below:\n\nName\t| Purpose\n----    | -------\n`$code`\t| The exception code (as provided by the constructor)\n`$file`\t| The name of the script where the exception was generated\n`$line`\t| The source line number in the script where the exception was generated\n`$message`\t| The exception message (as provided by the constructor)\n`$previous`\t| The previous exception in the chain, if this is a nested exception; otherwise, `null`\n`$string`\t| Work area for `__toString`\n`$trace`\t| Work area for function-call tracing\n`__construct`\t| Takes three (optional) arguments – `string`: the exception message (defaults to \"\"), `int`: the exception code (defaults to 0), and `\\Exception`: the previous exception in the chain (defaults to `null`)\n`__clone`\t| Present to inhibit the cloning of exception objects\n`__toString`\t| Retrieves a string representation of the exception in some unspecified format\n`getCode`\t| Retrieves the exception code (as set by the constructor).\n`getFile`\t| Retrieves the name of the script where the exception was generated\n`getLine`\t| Retrieves the source line number in the script where the exception was generated\n`getMessage`\t| Retrieves the exception message\n`getPrevious`\t| Retrieves the previous exception (as set by the constructor), if one exists; otherwise, `null`\n`getTrace`\t| Retrieves the function stack trace information (see [§§](19-exception-handling.md#tracing-exceptions))\n`getTraceAsString`\t| Retrieves the function stack trace information formatted as a single string in some unspecified format\n\n## Tracing Exceptions\n\nWhen an exception is caught, the `get*` functions in class `\\Exception`\nprovide useful information. If one or more nested function calls were\ninvolved to get to the place where the exception was generated, a record\nof those calls is also retained, and made available by getTrace, through\nwhat is referred to as the *function stack trace*, or simply, `*trace*`.\n\nLet's refer to the top level of a script as *function-level* 0.\nFunction-level 1 is inside any function called from function-level 0.\nFunction-level 2 is inside any function called from function-level 1,\nand so on. The library function `getTrace` returns an array. Exceptions\ngenerated at function-level 0 involve no function call, in which case,\nthe array returned by `getTrace` has zero elements.\n\nEach element of the array returned by `getTrace` provides information\nabout a given function level. Let us call this array *trace-array* and\nthe number of elements in this array *call-level*. The key for each of\ntrace-array's elements has type int, and ranges from 0 to\ncall-level - 1. For example, when a top-level script calls function `f1`,\nwhich calls function `f2`, which calls function `f3`, which then generates\nan exception, there are four function levels, 0–3, and there are three\nlots of trace information, one per call level. That is, trace-array\ncontains three elements, and they each correspond to the reverse order\nof the function calls. For example, trace-array[0] is for the call to\nfunction `f3`, trace-array[1] is for the call to function `f2`, and\ntrace-array[2] is for the call to function `f1`.\n\nEach element in trace-array is itself an array that contains elements\nwith the following key/value pairs:\n\nKey\t| Value Type\t| Value\n--- | ----------    | -----\n\"args\"\t| `array`\t| The set of arguments passed to the function\n\"class\"\t| `string` |\tThe name of the function's parent class\n\"file\"\t| `string` |\tThe name of the script where the function was called\n\"function\"\t| `string` |\tThe name of the function or class method\n\"line\"\t| `int` |\tThe line number in the source where the function was called\n\"object\" |\t`object` | The current object\n\"type\"\t| `string` |\tType of call; `->` for an instance method call, `::` for a static method call, ordinary function call, \"\" is returned.\n\nAs to whether extra elements with other keys are provided is\nunspecified.\n\nThe key `args` has a value that is yet another array, which we shall\ncall *argument-array*. That array contains a set of values that\ncorresponds directly to the set of values passed as arguments to the\ncorresponding function. Regarding element order, argument-array[0]\ncorresponds to the left-most argument, argument-array[1] corresponds to\nthe next argument to the right, and so on.\n\nConsider the case in which a function has a default argument value\ndefined for a parameter. If that function is called without an argument\nfor the parameter having the default value, no corresponding argument\nexists in array-argument. Only arguments present at the function-call\nsite have their values recorded in array-argument. \n\nSee also, library functions [`debug_backtrace`](http://www.php.net/debug_backtrace) and\n[`debug_print_backtrace`](http://www.php.net/debug_print_backtrace).\n\n## User-Defined Exception Classes\n\nAn exception class is defined simply by having it extend class [`\\Exception`](19-exception-handling.md#class-exception). However, as that class's `__clone` method is declared [`final`](16-classes.md#methods), exception objects cannot be cloned.\n\nWhen an exception class is defined, typically, its constructors call the\nparent class' constructor as their first operation to ensure the\nbase-class part of the new object is initialized appropriately. They\noften also provide an augmented implementation of\n[`__toString`](http://docs.hhvm.com/manual/en/language.oop5.magic.php) \n([§§](16-classes.md#method-__tostring)).\n\n\n"
  },
  {
    "path": "spec/20-namespaces.md",
    "content": "# Namespaces\n\n## General\n\nA problem encountered when managing large projects is that of avoiding\nthe use of the same name in the same scope for different purposes. This\nis especially problematic in a language that supports modular design and\ncomponent libraries.\n\nA *namespace* is a container for a set of (typically related)\ndefinitions of classes, interfaces, traits, functions, and constants.\nNamespaces serve two purposes:\n\n* They help avoid name collisions.\n* They allow certain long names to be accessed via shorter, more convenient and readable, names.\n\nA namespace may have *sub-namespaces*, where a sub-namespace name shares\na common prefix with another namespace. For example, the namespace\n`Graphics` might have sub-namespaces `Graphics\\D2` and `Graphics\\D3`, for\ntwo- and three-dimensional facilities, respectively. Apart from their\ncommon prefix, a namespace and its sub-namespaces have no special\nrelationship. The namespace whose prefix is part of a sub-namespace need\nnot actually exist for the sub-namespace to exist. That is, `NS1\\Sub` can\nexist without `NS1`.\n\nIn the absence of any namespace definition, the names of subsequent\nclasses, interfaces, traits, functions, and constants are in the\n*default namespace*, which has no name, per se.\n\nThe namespaces HH, PHP, php, and sub-namespaces beginning with those\nprefixes are reserved for use by Hack.\n\n## Name Lookup\n\nWhen an existing name is used in source code, the Engine must decide\nhow that name is found with respect to namespace lookup. For this\npurpose, names can have one of the three following forms:\n\n* Unqualified name: Such names are just simple names without any prefix, as in the class name `Point` in the following expression: `$p = new Point(3,5)`. If the current namespace is `NS1`, the name `Point` resolves to `NS1\\Point`. If the current namespace is the [default namespace](20-namespaces.md#general), the name `Point` resolves to `Point`. In the case of an unqualified function or constant name, if that name does not exist in the current namespace, a global function or constant by that name is used.\n* Qualified name: Such names have a prefix consisting of a namespace name and/or one or more levels of sub-namespace names, and, possibly, a class, interface, trait, function, or constant name. Such names are relative. For example, `D2\\Point` could be used to refer to the class Point in the sub-namespace `D2` of the current namespace. One special case of this is when the first component of the name is the keyword `namespace`. This means \"the current namespace\".\n* Fully qualified name: Such names begin with a backslash (`\\`) and are followed optionally by a namespace name and one or more levels of sub-namespace names, and, finally, a class, interface, trait, function, or constant name. Such names are absolute. For example, `\\Graphics\\D2\\Point` could be used to refer unambiguously to the class `Point` in namespace `Graphics`, sub-namespace `D2`.\n   \nThe names of the standard types that come with PHP (such as `Exception`), constants (such as\n`PHP_INT_MAX`), and library functions (such as `is_null`) are defined outside\nany namespace. To refer unambiguously to such names, one can prefix them\nwith a backslash (`\\`), as in `\\Exception`, `\\PHP_INT_MAX`, and `\\is_null`. The names of the standard types that are introduced with Hack (such as `Vector` and `Map`), are treated implicitly as belonging to namespace HH. Such names are resolved through a process known as *auto importation*.\n\n## Defining Namespaces\n\n**Syntax**\n\n<pre>\n  <i>namespace-definition:</i>\n    namespace  <i>namespace-name</i>  ;\n    namespace  <i>namespace-name<sub>opt</sub></i>  { <i>declaration-list<sub>opt</sub></i> }\n\n  <i>namespace-name:</i>\n    <i>name </i>\n    <i>namespace-name</i>   \\   </i>name</i>\n\n  <i>namespace-name-as-a-prefix:</i>\n    \\\n    \\<sub>opt</sub>   <i>namespace-name</i>   \\\n    namespace   \\\n    namespace   \\   <i>namespace-name</i>   \\\n\n  <i>qualified-name:</i>\n    <i>namespace-name-as-a-prefix<sub>opt</sub>   name</i>\n</pre>\n\n**Defined elsewhere**\n\n* [*declaration-list*](04-basic-concepts.md)\n* [*name*](09-lexical-structure.md#names)\n\n**Constraints**\n\nExcept for white space, the\nfirst occurrence of a *namespace-definition* in a script must be the\nfirst thing in that script.\n\nAll occurrence of a *namespace-definition* in a script must have the\n*declaration-list* form or must have the \"semicolon\" form; the two forms\ncannot be mixed.\n\nWhen a script contains source code that is not inside a namespace, and\nsource code that is inside one or namespaces, the namespaced code must\nuse the *declaration-list* form of *namespace-definition*.\n\nThe *declaration-list* must not contain a *namespace-definition*.\n\n**Semantics**\n\nNamespace and sub-namespace names are [case-preserved](03-terms-and-definitions.md).\n\nThe pre-defined constant [`__NAMESPACE__`](06-constants.md#context-dependent-constants) contains the name of\nthe current namespace.\n\nWhen the same namespace is defined in multiple scripts, and those\nscripts are combined into the same program, the namespace is considered\nthe merger of its individual contributions.\n\nIn the \"semicolon\" form of *namespace-definition* the given \nnamespace extends until the end of the script, or until the lexically next\n*namespace-definition*, whichever comes first. In the *declaration-list*\nform the namespace extends from the opening brace to the closing brace.\n\n**Examples**\n\nScript1.php:\n```Hack\nnamespace NS1;\n...\t\t\t\t// __NAMESPACE__ is \"NS1\"\nnamespace NS3\\Sub1;\n...\t\t\t\t// __NAMESPACE__ is \"NS3\\Sub1\"\n```\n\nScript2.php:\n```Hack\nnamespace NS1\n{\n...\t\t\t\t// __NAMESPACE__ is \"NS1\"\n}\nnamespace\n{\n...\t\t\t\t// __NAMESPACE__ is \"\"\n}\nnamespace NS3\\Sub1;\n{\n...\t\t\t\t// __NAMESPACE__ is \"NS3\\Sub1\"\n}\n```\n\n## Namespace Use Declarations**\n\n**Syntax**\n\n<pre>\n  <i>namespace-use-declaration:</i>\n    use <i>namespace-use-kind<sub>opt</sub></i>  <i>namespace-use-clauses</i>  ;\n    use <i>namespace-use-kind</i>  <i>namespace-name-as-a-prefix</i>  { <i>namespace-use-clauses</i>  }  ;\n    use <i>namespace-name-as-a-prefix</i>  { <i>namespace-use-kind-clauses</i>  }  ;\n\n  <i>namespace-use-clauses:</i>\n    <i>namespace-use-clause</i>\n    <i>namespace-use-clauses</i>  ,  <i>namespace-use-clause</i>\n\n  <i>namespace-use-clause:</i>\n    <i>qualified-name  namespace-aliasing-clause<sub>opt</sub></i>\n\n  <i>namespace-use-kind-clauses:</i>\n    <i>namespace-use-kind-clause</i>\n    <i>namespace-use-kind-clauses</i>  ,  <i>namespace-use-kind-clause</i>\n\n  <i>namespace-use-kind-clause:</i>\n    <i>namespace-use-kind<sub>opt</sub></i>  <i>qualified-name  namespace-aliasing-clause<sub>opt</sub></i>\n\n  <i>namespace-aliasing-clause:</i>\n    as  <i>name</i>\n\n  <i>namespace-use-kind</i>:\n    function\n    const\n</pre>\n\n**Defined elsewhere**\n\n* [*name*](09-lexical-structure.md#names)\n* [*qualified-name*](#defining-namespaces)\n\n**Constraints**\n\nA *namespace-use-declaration* must not occur except at the pseudomain\nlevel.\n\nIf the same *qualified-name* is imported multiple times in the same\nscope, each occurrence must have a different alias.\n\n**Semantics**\n\nIf a *namespace-use-kind* is specified before the clauses or group prefix, \nthen all subsequent clauses must name constants or functions, as appropriate.\n\nOtherwise, if a *namespace-use-kind* is specified in a *namespace-use-kind-clause*\nthen the clause must name a constant or function, as appropriate.\n\nOtherwise, the clause must name a namespace, class, interface or trait.\n\nA *namespace-use-declaration* *imports*—that is, makes available—one or\nmore names into a scope, optionally giving them each an alias. Each of\nthose names may designate a namespace, a sub-namespace, a class, an\ninterface, or a trait. If a namespace-alias-clause is present, its\n*name* is the alias for *qualified-name*. Otherwise, the right-most name\nin *qualified-name* is the implied alias for *qualified-name*.\n\nThe \"group\" form of a *namespace-use-declaration* is a convenient syntax when\nimporting many members of a given namespace. The \"group\" form logically concatenates\nthe prefix onto the *qualified-name* in each clause. See the following section for \nan example.\n\n**Examples**\n\n```Hack\nnamespace NS1 {\n  function f(): void { … }\n  class C { … }\n  interface I { … }\n  trait T { … }\n}\n\nnamespace NS2 {\n  use \\NS1\\C, \\NS1\\I, \\NS1\\T;\n  class D extends C implements I {\n    use T;\n  }\n  \\NS1\\f();     // explicit namespace\n\n  use \\NS1\\C as C2; // C2 is an alias for the class name \\NS1\\C\n  $c2 = new C2;\n}\n```\nThe *namespace-use-declaration* in the example above could also be written in \n\"group\" form as:\n\n```\n  use \\NS1\\ { C, I, T };\n```\n"
  },
  {
    "path": "spec/21-attributes.md",
    "content": "# Attributes\n\n## General\n\nProgrammers can invent a new kind of declarative information, called an *attribute*. Attributes can be attached to various program entities, and information about those attribute can be retrieved at run-time via reflection (see library class `Reflection`, et al).\n\nConsider the following example:\n\n```Hack\n<<Help(\"http://www.MyOnlineDocs.com/Widget.html\")>>\nclass Widget {\n  …\n}\n\n$rc = new ReflectionClass('Widget');\n$attrHelp = $rc->getAttribute('Help');\n```\n\nThe method `getAttribute` returns an array containing the values corresponding to an attribute, in lexical order of their specification. As the `Help` attribute on class `Widget` has only one value, a string, array element 0 is the string containing that string, in this case, a URL at which the corresponding help information can be found.\n\nA number of predefined attributes ([§§](21-attributes.md#predefined-attributes)) affect the way in which source code is compiled.\n\n## Attribute Specification\n\n**Syntax**\n<pre>\n<i>attribute-specification:</i>\n  &lt;&lt;  <i>attribute-list</i>  &gt;&gt;\n<i>attribute-list:</i>\n  <i>attribute</i>\n  <i>attribute-list</i>  ,  <i>attribute</i>\n<i>attribute:</i>\n  <i>attribute-name</i>  <i>attribute-value-list<sub>opt</sub></i>\n<i>attribute-name:</i>\n  <i>name</i>\n<i>attribute-value-list:</i>\n  (  <i>attribute-values<sub>opt</sub></i>  )\n<i>attribute-values</i>\n  <i>attribute-value</i>\n  <i>attribute-values</i>  ,  <i>attribute-value</i>\n<i>attribute-value:</i>\n  <i>expression</i>\n</pre>\n\n*name* is defined in [§§](09-lexical-structure.md#names); and *expression* is defined in [§§](10-expressions.md#yield-operator).\n\n**Constraints**\n\nThe *name*s in an *attribute-list* must be distinct.\n\nThe *expression*s in an *attribute-list* must be *constant-expressions* ([§§](10-expressions.md#constant-expressions)).\n\n**Semantics**\n\nA *name* in a user-defined attribute means whatever the programmer wants.\n\nThe *name*s do not have any scope, per se. They appear only in the context of an *attribute-specification*, and do not hide nor conflict with the same names used in other contexts.  \n\nOmitting *attribute-value-list* is equivalent to specifying it without *attribute-values*.\n\n**Examples**\n\n```Hack\n<<A1(123), A2>>\nclass C {\n  <<A3(true, 100)>> public function __construct() { … }\n  <<A4>> public function doit(): void { … }\n}\n```\n\n## Predefined Attributes\n\n### General\n\nThe following attributes are recognized by a conforming implementation:\n* `__ConsistentConstruct` ([§§](21-attributes.md#attribute-__consistentconstruct))\n* `__Memoize` ([§§](21-attributes.md#attribute-__memoize))\n* `__Override` ([§§](21-attributes.md#attribute-__override))\n\n### Attribute `__ConsistentConstruct`\n\nThis attribute can be applied to classes; it has no attribute values.\n\nWhen a method is overridden in a derived class, it must have exactly the same number, type, and order of parameters as that in the base class ([§§](16-classes.md#general)). However, that is not the case for constructors ([§§](16-classes.md#constructors)). Having a family of constructors with different signatures can cause a problem, however, especially when using `new static` ([§§](10-expressions.md#the-new-operator)).\n\nConsider the following example:\n\n```Hack\n<<__ConsistentConstruct>>\nclass Base {\n  public function __construct() { … }\n\n  public static function make(): this {\n    return new static();\n  }\n}\n\nclass Derived extends Base {\n  public function __construct() {\n    …\n    parent::__construct();\n  }\n}\n\n$v2 = Derived::make();\n```\n\nWhen `make` is called on a `Derived` object, `new static` results in `Derived`'s constructor being called knowing only the parameter list of `Base`'s constructor. As such, `Derived`'s constructor must either have the exact same signature as `Base`'s constructor, or the same plus an ellipses ([§§](15-functions.md#function-definitions)) indicating a trailing variable-argument list.\n\n### Attribute `__Memoize`\n\nThis attribute can be applied to functions and static or instance methods; it has no attribute values.\n\nThe presence of this attribute causes the designated method to cache automatically each value it looks up and returns, so future requests for that same lookup can be retrieved more efficiently. The set of parameters is hashed into a single hash key, so changing the type, number, and/or order of the parameters can change that key.\n\nConsider the following example:\n\n```Hack\nclass Item {\n  <<__Memoize>>\n  public static function getNameFromProductCode(int $productCode): string {\n    return Item::getNameFromStorage($productCode);  // conditional call\n  }\n  private static function getNameFromStorage(int $productCode): string {\n    // get name from alternate store\n    return …;\n  }\n}\n```\n\n`Item::getNameFromStorage` will only be called if the given product code is not in the cache.\n\nThe types of the parameters are restricted to the following: `null`, `bool`, `int`, `float`, `string`, any object type that implements `IMemoizeParaminterface`, enum constants, tuples, shapes, and arrays/collections containing any supported element type.\n\nThe interface type `IMemoizeParam` ([§§](17-interfaces.md#interface-IMemoizeParam)) assists with memorizing objects passed to async functions.\n\n### Attribute `__Override`\n\nThis attribute can be applied to static or instance methods; it has no attribute values.\n\nThe presence of this attribute indicates that the designated method is intended to override a method having the same name in a direct or indirect base class. If no such base-class method exists, a compile-time error occurs.\n\nConsider the following example:\n\n```Hack\nclass Button {\n  public function draw(): void { /* … */ }\n}\nclass CustomButton extends Button {\n  <<__Override>>\n  public function draw(): void { /* … */ }\n}\n```\n\nIf a subsequent refactoring of class `Button` results in the removal of method draw, the presence of the attribute in class `CustomButton` will cause the dependence to be reported.\n\nWhen `__Override` is applied to a method in a trait, the check for whether the overridden method exists takes place when a class uses that trait.\n\n"
  },
  {
    "path": "spec/22-grammar.md",
    "content": "# Grammar\n\n## General\n\nThe grammar notation is described in [§§](09-lexical-structure.md#grammars).\n\n## Lexical Grammar\n\n### General\n\n<pre>\n  <i>input-file::\n    <i>input-element\n    <i>input-file   input-element\n  <i>input-element::</i>\n    <i>comment</i>\n    <i>white-space</i>\n    <i>token</i>\n</pre>\n\n### Comments\n\n<pre>\n  <i>comment::</i>\n    <i>single-line-comment</i>\n    <i>delimited-comment</i>\n\n  <i>single-line-comment::</i>\n    //  <i>input-characters<sub>opt</sub></i>\n    #  <i>input-characters<sub>opt</sub></i>\n\n  <i>input-characters::</i>\n    <i>input-character</i>\n    <i>input-characters   input-character</i>\n\n  <i>input-character::</i>\n    Any source character except new-line\n\n  <i>new-line::</i>\n    Carriage-return character (U+000D)\n    Line-feed character (U+000A)\n    Carriage-return character (U+000D) followed by line-feed character (U+000A)\n\n  <i>delimited-comment::</i>\n    /*   No characters or any source character sequence except /*   */\n</pre>\n\n### White Space\n\n<pre>\n  <i>white-space::</i>\n    <i>white-space-character</i>\n    <i>white-space   white-space-character</i>\n\n  <i>white-space-character::</i>\n    <i>new-line</i>\n    Space character (U+0020)\n    Horizontal-tab character (U+0009)\n</pre>\n\n### Tokens\n\n#### General\n\n<pre>\n  <i>token::</i>\n    <i>variable-name</i>\n    <i>name</i>\n    <i>keyword</i>\n    <i>literal</i>\n    <i>operator-or-punctuator</i>\n</pre>\n\n#### Names\n\n<pre>\n  <i>variable-name::</i>\n    $   <i>name</i>\n\n  <i>name::</i>\n    <i>name-nondigit</i>\n    <i>name   name-nondigit</i>\n    <i>name   digit</i>\n\n  <i>name-nondigit::</i>\n    <i>nondigit</i>\n    one of the characters U+007f–U+00ff\n\n  <i>nondigit::</i> one of\n    _\n    a   b   c   d   e   f   g   h   i   j   k   l   m\n    n   o   p   q   r   s   t   u   v   w   x   y   z\n    A   B   C   D   E   F   G   H   I   J   K   L   M\n    N   O   P   Q   R   S   T   U   V   W   X   Y   Z\n</pre>\n\n### Keywords\n\n<pre>\n  <i>keyword::</i> one of\n    abstract  arraykey  as  async  break  case  catch  class  classname clone  const  continue  default  do\n    echo  else  elseif  enum  extends  final  finally  for  foreach  function  if  implements\n    instanceof  insteadof  interface  mixed  namespace  new  newtype  noreturn   num  parent  private\n    protected  public  require  require_once  return  self  shape  static  switch  throw  trait  try\n    tuple  type  use  while  yield\n</pre>\n\n### Literals\n\n#### General\n\n<pre>\n  <i>literal::\n    <i>boolean-literal</i>\n    <i>integer-literal</i>\n    <i>floating-literal</i>\n    <i>string-literal</i>\n    <i>null-literal</i>\n</pre>\n\n#### Boolean Literals\n\n<pre>\n  <i>boolean-literal::</i>\n    true\n    false\n</pre>\n\n#### Integer Literals\n\n<pre>\n  <i>integer-literal::</i>\n    <i>decimal-literal</i>\n    <i>octal-literal</i>\n    <i>hexadecimal-literal</i>\n    <i>binary-literal</i>\n\n    <i>decimal-literal::</i>\n      <i>nonzero-digit</i>\n      <i>decimal-literal   digit</i>\n\n    <i>octal-literal::</i>\n      0\n      <i>octal-literal   octal-digit</i>\n\n    <i>hexadecimal-literal::</i>\n      <i>hexadecimal-prefix   hexadecimal-digit</i>\n      <i>hexadecimal-literal   hexadecimal-digit</i>\n\n    <i>hexadecimal-prefix:: one of</i>\n      0x  0X\n\n    <i>binary-literal::</i>\n      <i>binary-prefix   binary-digit</i>\n      <i>binary-literal   binary-digit</i>\n\n    <i>binary-prefix:: one of</i>\n      0b  0B\n\n    <i>digit:: one of</i>\n      0  1  2  3  4  5  6  7  8  9\n\n    <i>nonzero-digit:: one of</i>\n      1  2  3  4  5  6  7  8  9\n\n    <i>octal-digit:: one of</i>\n      0  1  2  3  4  5  6  7\n\n    <i>hexadecimal-digit:: one of</i>\n      0  1  2  3  4  5  6  7  8  9\n            a  b  c  d  e  f\n            A  B  C  D  E  F\n\n    <i>binary-digit:: one of</i>\n        0  1\n</pre>\n\n#### Floating-Point Literals\n\n<pre>\n  <i>ﬂoating-literal::</i>\n    <i>fractional-literal   exponent-part<sub>opt</sub></i>\n    <i>digit-sequence   exponent-part</i>\n\n  <i>fractional-literal::</i>\n    <i>digit-sequence<sub>opt</sub></i> . <i>digit-sequence</i>\n    <i>digit-sequence</i> .\n\n  <i>exponent-part::</i>\n    e  <i>sign<sub>opt</sub>   digit-sequence</i>\n    E  <i>sign<sub>opt</sub>   digit-sequence</i>\n\n  <i>sign:: one of</i>\n    +  -\n\n  <i>digit-sequence::</i>\n    <i>digit</i>\n    <i>digit-sequence   digit</i>\n</pre>\n\n#### String Literals\n\n<pre>\n  <i>string-literal::</i>\n    <i>single-quoted-string-literal</i>\n    <i>double-quoted-string-literal</i>\n    <i>heredoc-string-literal</i>\n    <i>nowdoc-string-literal</i>\n\n  <i>single-quoted-string-literal::</i>\n    b<i><sub>opt</sub></i>  ' <i>sq-char-sequence<sub>opt</sub></i>  '\n\n  <i>sq-char-sequence::</i>\n    <i>sq-char</i>\n    <i>sq-char-sequence   sq-char</i>\n\n  <i>sq-char::</i>\n    <i>sq-escape-sequence</i>\n    \\<i><sub>opt</sub></i>   any member of the source character set except single-quote (') or backslash (\\)\n\n  <i>sq-escape-sequence:: one of</i>\n    \\'  \\\\\n\n  <i>double-quoted-string-literal::</i>\n    b<i><sub>opt</sub></i>  \" <i>dq-char-sequence<sub>opt</sub></i>  \"\n\n  <i>dq-char-sequence::</i>\n    <i>dq-char</i>\n    <i>dq-char-sequence   dq-char</i>\n\n  <i>dq-char::</i>\n    <i>dq-escape-sequence</i>\n    any member of the source character set except double-quote (\") or backslash (\\)\n    \\  any member of the source character set except \"\\$efnrtvxX or\noctal-digit\n\n  <i>dq-escape-sequence::</i>\n    <i>dq-simple-escape-sequence</i>\n    <i>dq-octal-escape-sequence</i>\n    <i>dq-hexadecimal-escape-sequence</i>\n\n  <i>dq-simple-escape-sequence:: one of</i>\n    \\\"   \\\\   \\$   \\e   \\f   \\n   \\r   \\t   \\v\n\n  <i>dq-octal-escape-sequence::</i>\n    \\   <i>octal-digit</i>\n    \\   <i>octal-digit   octal-digit</i>\n    \\   <i>octal-digit   octal-digit   octal-digit</i>\n\n  <i>dq-hexadecimal-escape-sequence::</i>\n    \\x  <i>hexadecimal-digit   hexadecimal-digit<sub>opt</sub></i>\n    \\X  <i>hexadecimal-digit   hexadecimal-digit<sub>opt</sub></i>\n\n  <i>heredoc-string-literal::</i>\n    &lt;&lt;&lt; <i>hd-start-identifier   new-line   hd-char-sequence<sub>opt</sub>  new-line hd-end-identifier</i>  ;<i><sub>opt</sub>   new-line</i>\n\n  <i>hd-start-identifier::</i>\n    <i>name</i>\n\n  <i>hd-end-identifier::</i>\n    <i>name</i>\n\n  <i>hd-char-sequence::</i>\n    <i>hd-char</i>\n    <i>hd-char-sequence   hd-char</i>\n\n  <i>hd-char::</i>\n    <i>hd-escape-sequence</i>\n    any member of the source character set except backslash (\\)\n    \\  any member of the source character set except \\$efnrtvxX or\noctal-digit\n\n  <i>hd-escape-sequence::</i>\n    <i>hd-simple-escape-sequence</i>\n    <i>dq-octal-escape-sequence</i>\n    <i>dq-hexadecimal-escape-sequence</i>\n\n  <i>hd-simple-escape-sequence:: one of</i>\n    \\\\   \\$   \\e   \\f   \\n   \\r   \\t   \\v\n\n\n  <i>nowdoc-string-literal::</i>\n    &lt;&lt;&lt; '  <i>hd-start-identifier</i>  '  <i>new-line  hd-char-sequence<sub>opt</sub>   new-line hd-end-identifier</i>  ;<i><sub>opt</sub>   new-line</i>     \n</pre>\n\n#### The Null Literal\n\n<pre>\n  <i>null-literal::</i>\n    null\n</pre>\n\n### Operators and Punctuators\n\n<pre>\n  <i>operator-or-punctuator:: one of</i>\n    [   ]    (   )   {    }   .   -&gt;   ++   --   **   *   +   -   ~   !\n    $   /   %   &lt;&lt;   &gt;&gt;   &lt;   &gt;   &lt;=   &gt;=   ==   ===   !=   !==   ^   |\n    &amp;   &amp;&amp;   ||   ?   ??   :   ; =   **=   *=   /=   %=   +=   -=   .=   &lt;&lt;=\n    &gt;&gt;=   &amp;=   ^=   |=   ,   @   ::   =>   ==>   ?->   \\   ...   |>   $$\n</pre>\n\n## Syntactic Grammar\n\n### Program Structure\n\n<pre>\n<i>script:\n  </i>&lt;?hh // strict\n  <i>declaration-list<sub>opt</sub></i>\n\n<i>declaration-list:</i>\n  <i>declaration</i>\n  <i>declaration-list</i> <i>declaration</i>\n\n<i>declaration:</i>\n  <i>inclusion-directive</i>\n  <i>enum-declaration</i>\n  <i>function-definition</i>\n  <i>class-declaration</i>\n  <i>interface-declaration</i>\n  <i>trait-declaration</i>\n  <i>namespace-definition</i>\n  <i>namespace-use-declaration</i>\n  <i>alias-declaration</i>\n</pre>\n\n### Types\n\n#### General\n\n<pre>\n<i>type-specifier:</i>\n  bool\n  int\n  float\n  num\n  string\n  arraykey\n  void\n  resource\n  <i>alias-type-specifier</i>\n  <i>vector-like-array-type-specifier</i>\n  <i>map-like-array-type-specifier</i>\n  <i>enum-specifier</i>\n  <i>class-interface-trait-specifier</i>\n  <i>tuple-type-specifier</i>\n  <i>shape-specifier</i>\n  <i>closure-type-specifier</i>\n  <i>nullable-type-specifier</i>\n  <i>generic-type-parameter-name</i>\n  this\n  <i>classname-type-specifier</i>\n  <i>type-constant-type-name</i>\n\n<i>alias-type-specifier:</i>\n  <i>qualified-name</i>\n\n<i>enum-specifier:</i>\n  <i>qualified-name\n\n<i>class-interface-trait-specifier:</i>\n  <i>qualified-name generic-type-argument-list<sub>opt</sub></i>\n\n<i>type-specifier-list:</i>\n  <i>type-specifiers</i>  ,<sub>opt</sub>\n\n<i>type-specifiers:</i>\n  <i>type-specifier</i>\n  <i>type-specifiers</i>  ,  <i>type-specifier</i>\n\n<i>type-constraint:</i>\n  as  <i>type-specifier</i>\n\n<i>type-constant-type-name:</i>\n  <i>name</i>  ::  <i>name</i>\n  self  ::  <i>name</i>\n  this  ::  <i>name</i>\n  <i>type-constant-type-name</i>  ::  <i>name</i>\n</pre>\n\n#### Array Types\n\n<pre>\n<i>vector-like-array-type-specifier:</i>\n  array &lt; <i>array-value-type-specifier</i> &gt;\n\n<i>map-like-array-type-specifier:</i>\n  array &lt; <i>array-value-type-specifier</i> , <i>array-value-type-specifier</i> &gt;\n\n<i>array-value-type-specifier:</i>\n  <i>type-specifier</i>\n\n<i>array-key-type-specifier:</i>\n  <i>type-specifier</i>\n</pre>\n\n#### Tuple Types\n\n<pre>\n<i>tuple-type-specifier:</i>\n  ( <i>type-specifier</i>  ,  <i>type-specifier-list</i>  )\n</pre>\n\n#### Shape Types\n\n<pre>\n<i>shape-specifier:</i>\n  shape ( <i>field-specifier-list<sub>opt</sub></i> )\n\n<i>field-specifier-list:</i>\n  <i>field-specifier</i>\n  <i>field-specifier-list</i>  ,  <i>field-specifier</i>\n\n<i>field-specifier:</i>\n  <i>single-quoted-string-literal</i>  =>  <i>type-specifier</i>\n  <i>qualified-name</i>  =>  <i>type-specifier</i>\n  <i>scope-resolution-expression</i>  =>  <i>type-specifier</i>\n</pre>\n\n#### Closure Types\n\n<pre>\n<i>closure-type-specifier:</i>\n( function ( <i>type-specifier-list<sub>opt</sub></i> ) : <i>type-specifier</i> )\n</pre>\n\n#### Nullable Types\n\n<pre>\n<i>nullable-type-specifier:</i>\n  ? <i>type-specifier</i>\n  mixed\n</pre>\n\n#### The Classname Type\n\n<pre>\n<i>classname-type-specifier:</i>\n  classname   <   <i>qualified-name<i>  <i>generic-type-argument-list<sub>opt</sub></i>  >\n</pre>\n\n#### Type Aliases\n\n<pre>\n<i>alias-declaration:</i>\n  <i>attribute-specification<sub>opt</sub>  type  <i>name</i>  <i>generic-type-parameter-list</i><sub>opt</sub>  =  <i>type-specifier</i>  ;\n  <i>attribute-specification<sub>opt</sub>  newtype  <i>name</i>  <i>generic-type-parameter-list</i><sub>opt</sub>  <i>type-constraint<sub>opt</sub></i>  =  <i>type-specifier</i>  ;\n</pre>\n\n### Variables\n\n<pre>\n  <i>function-static-declaration:</i>\n    static <i>static-declarator-list</i>  ;\n  <i>static-declarator-list:</i>\n    <i>static-declarator</i>  \n    <i>static-declarator-list</i>  ,  <i>static-declarator</i>\n  <i>static-declarator:</i>\n    <i>variable-name</i>  <i>function-static-initializer<sub>opt</sub></i>\n  <i>function-static-initializer:</i>\n    = <i>const-expression</i>\n</pre>\n\n### Expressions\n\n#### Primary Expressions\n\n<pre>\n  <i>primary-expression:</i>\n    <i>variable-name</i>\n    <i>qualified-name</i>\n    <i>literal</i>\n    <i>const-expression</i>\n    <i>intrinsic</i>\n    <i>collection-literal</i>\n    <i>tuple-literal</i>\n    <i>shape-literal</i>\n    <i>anonymous-function-creation-expression</i>\n    <i>awaitable-creation-expression</i>\n    (  <i>expression</i>  )\n    $this\n    $$\n\n  <i>intrinsic:</i>\n    <i>array-intrinsic</i>\n    <i>echo-intrinsic</i>\n    <i>exit-intrinsic</i>\n    <i>invariant-intrinsic</i>\n    <i>list-intrinsic</i>\n\n  <i>array-intrinsic:</i>\n    array ( <i>array-initializer<sub>opt</sub></i>  )\n\n  <i>echo-intrinsic:</i>\n    echo  <i>expression</i>\n    echo  (  <i>expression</i>  )\n    echo  <i>expression-list-two-or-more</i>\n\n  <i>expression-list-two-or-more:</i>\n    <i>expression</i>  ,  <i>expression</i>\n    <i>expression-list-two-or-more</i>  ,  <i>expression</i>\n\n  <i>exit-intrinsic:</i>\n    exit  <i>expression<sub>opt</sub></i>\n    exit  (  <i>expression<sub>opt</sub></i>  )\n\n  <i>invariant-intrinsic:</i>\n    invariant  (  <i>condition</i>  ,  <i>format</i>  )\n    invariant  (  <i>condition</i>  ,  <i>format</i>  ,  <i>values</i>  )\n\n  <i>list-intrinsic:</i>\n    list  (  <i>list-expression-list<sub>opt</sub></i>  )\n\n  <i>list-expression-list:</i>\n    <i>expression</i>\n    ,\n    <i>list-expression-list</i>  ,  <i>expression<sub>opt</sub></i>\n\n  <i>collection-literal:</i>\n    <i>non-key-collection-class-type</i>  {  <i>cl-initializer-list-without-keys<sub>opt</sub></i>  }\n    <i>key-collection-class-type</i>  {  <i>cl-initializer-list-with-keys<sub>opt</sub></i>  }\n    <i>pair-type</i>  {  <i>cl-element-value</i>  ,  <i>cl-element-value</i>  }\n\n  <i>non-key-collection-class-type:</i>\n    <i>qualified-name non-key-collection-class-type-hint<sub>opt</sub></i>\n\n  <i>key-collection-class-type:</i>\n    <i>qualified-name key-collection-class-type-hint<sub>opt</sub></i>\n\n  <i>non-key-collection-class-type-hint:</i>\n    <i>&lt; type-specifier &rt;</i>\n  \n  <i>key-collection-class-type-hint:</i>\n    <i>&lt; type-specifier , type-specifier &rt;</i>\n\n  <i>pair-type:</i>\n    <i>qualified-name</i>\n\n  <i>cl-initializer-list-without-keys:</i>\n    <i>cl-element-value</i>\n    <i>cl-initializer-list-without-keys</i>  ,  <i>cl-element-value</i>\n\n  <i>cl-initializer-list-with-keys:</i>\n    <i>cl-element-key</i>  =>  <i>cl-element-value</i>\n    <i>cl-initializer-list-with-keys</i>  ,  <i>cl-element-key</i>  =>  <i>cl-element-value</i>\n\n  <i>cl-element-key:</i>\n    <i>expression</i>\n\n  <i>cl-element-value:</i>\n    <i>expression</i>\n\n  <i>tuple-literal:</i>\n    tuple  (  <i>expression-list-one-or-more</i>  )\n\n  <i>expression-list-one-or-more:</i>\n    <i>expression</i>\n    <i>expression-list-one-or-more</i>  ,  <i>expression</i>\n\n  <i>shape-literal:</i>\n    <i>shape</i>  (  <i>field-initializer-list<sub>opt</sub></i>  )\n\n  <i>field-initializer-list:</i>\n    <i>field-initializers</i>  ,<sub>opt</sub>\n\n  <i>field-initializers</i>:\n    <i>field-initializer</i>\n    <i>field-initializers</i>  ,  <i>field-initializer</i>\n\n  <i>field-initializer:</i>\n    <i>single-quoted-string-literal</i>  =>  <i>expression</i>\n    <i>integer-literal</i>  =>  <i>expression</i>\n    <i>qualified-name</i>  =>  <i>expression</i>\n    <i>scope-resolution-expression</i>  =>  <i>expression</i>\n\n  <i>anonymous-function-creation-expression:</i>\n    async<sub>opt</sub>  function  (  <i>anonymous-function-parameter-list<sub>opt<sub></i>  )  <i>anonymous-function-return<sub>opt</sub></i>  <i>anonymous-function-use-clause<sub>opt</sub></i>  <i>compound-statement</i>\n\n  <i>anonymous-function-parameter-list:</i>\n    ...\n    <i>anonymous-function-parameter-declaration-list</i>\n    <i>anonymous-function-parameter-declaration-list</i>  ,\n    <i>anonymous-function-parameter-declaration-list</i>  ,  ...\n  \n  <i>anonymous-function-parameter-declaration-list:</i>\n    <i>anonymous-function-parameter-declaration</i>\n    <i>anonymous-function-parameter-declaration-list</i>  ,  <i>anonymous-function-parameter-declaration</i>\n\n  <i>anonymous-function-parameter-declaration:</i>\n    <i>attribute-specification<sub>opt</sub>  type-specifier<sub>opt</sub> variable-name  default-argument-specifier<sub>opt</sub></i>\n\n  <i>anonymous-function-return:</i>\n    : <i>return-type</i>\n\n  <i>anonymous-function-use-clause:</i>\n    use  (  <i>use-variable-name-list</i>  ,<sub>opt</sub> )\n\n  <i>use-variable-name-list:</i>\n    <i>variable-name</i>\n    <i>use-variable-name-list</i>  ,  <i>variable-name</i>             \n\n  <i>awaitable-creation-expression:</i>\n    async   {   <i>async-statement-list<sub>opt</sub></i>   }\n\n  <i>async-statement-list:</i>\n    <i>statement</i>\n    <i>async-statement-list   statement</i>\n</pre>\n\n#### Postfix Operators\n\n<pre>\n  <i>postfix-expression:</i>\n    <i>-expression</i>\n    <i>clone-expression</i>\n    <i>object-creation-expression</i>\n    <i>array-creation-expression</i>\n    <i>subscript-expression</i>\n    <i>function-call-expression</i>\n    <i>member-selection-expression</i>\n    <i>null-safe-member-selection-expression</i>\n    <i>postfix-increment-expression</i>\n    <i>postfix-decrement-expression</i>\n    <i>scope-resolution-expression</i>\n    <i>exponentiation-expression</i>\n\n\n  <i>clone-expression:</i>\n    clone  <i>expression</i>\n\n  <i>object-creation-expression:</i>\n    new  <i>class-type-designator</i>  (  <i>argument-expression-list<sub>opt</sub></i>  )\n\n  <i>class-type-designator:</i>\n    parent\n    self\n    static\n    <i>member-selection-expression</i>\n    <i>null-safe-member-selection-expression</i>\n    <i>qualified-name</i>\n    <i>scope-resolution-expression</i>\n    <i>subscript-expression</i>\n    <i>variable-name</i>\n\n  <i>array-creation-expression:</i>\n    array  (  <i>array-initializer<sub>opt</sub></i>  )\n    [ <i>array-initializer<sub>opt</sub></i> ]\n\n  <i>array-initializer:</i>\n    <i>array-initializer-list</i>  ,<sub>opt</sub>\n\n  <i>array-initializer-list:</i>\n    <i>array-element-initializer</i>\n    <i>array-element-initializer  ,  array-initializer-list</i>\n\n  <i>array-element-initializer:</i>\n    <i>element-value</i>\n    element-key  =>  <i>element-value</i>\n\n  <i>element-key:</i>\n    <i>expression</i>\n\n  <i>element-value</i>\n    <i>expression</i>\n\n  <i>subscript-expression:</i>\n    <i>postfix-expression</i>  [  <i>expression<sub>opt</sub></i>  ]\n    <i>postfix-expression</i>  {  <i>expression<sub>opt</sub></i>  }   <b>[Deprecated form]</b>\n\n  <i>function-call-expression:</i>\n    <i>postfix-expression</i>  (  <i>argument-expression-list<sub>opt</sub></i>  )\n\n  <i>argument-expression-list:</i>\n    <i>argument-expressions</i>  ,<sub>opt</sub>\n\n  <i>argument-expressions:</i>\n    <i>expression</i>\n    <i>argument-expressions</i>  ,  <i>expression</i>\n\n  <i>member-selection-expression:</i>\n    <i>postfix-expression</i>  ->  <i>name</i>\n    <i>postfix-expression</i>  ->  <i>variable-name</i>\n\n  <i>null-safe-member-selection-expression:</i>\n    <i>postfix-expression</i>  ?->  <i>name</i>\n    <i>postfix-expression</i>  ?->  <i>variable-name</i>\n\n  <i>postfix-increment-expression:</i>\n    <i>unary-expression</i>  ++\n\n  <i>postfix-decrement-expression:</i>\n    <i>unary-expression</i>  --\n\n  <i>scope-resolution-expression:</i>\n    <i>scope-resolution-qualifier</i>  ::  <i>name</i>\n    <i>scope-resolution-qualifier</i>  ::  <i>variable-name</i>\n    <i>scope-resolution-qualifier</i>  ::  class\n\n  <i>scope-resolution-qualifier:</i>\n    <i>qualified-name</i>\n    <i>variable-name</i>\n    self\n    parent\n    static\n\n  <i>exponentiation-expression:</i>\n    <i>expression  **  expression</i>                   \n</pre>\n\n#### Unary Operators\n\n<pre>\n  <i>unary-expression:</i>\n    <i>postfix-expression</i>\n    <i>prefix-increment-expression</i>\n    <i>prefix-decrement-expression</i>\n    <i>unary-op-expression</i>\n    <i>error-control-expression</i>\n    <i>cast-expression</i>\n    <i>await-expression</i>\n\n  <i>prefix-increment-expression:</i>\n    ++ <i>unary-expression</i>\n\n  <i>prefix-decrement-expression:</i>\n    -- <i>unary-expression</i>\n\n  <i>unary-op-expression:</i>\n    <i>unary-operator cast-expression</i>\n\n  <i>unary-operator: one of</i>\n    +  -  !  ~\n\n  <i>error-control-expression:</i>\n    @  <i>expression</i>\n\n  <i>cast-expression:</i>\n    (  <i>cast-type</i>  ) <i>unary-expression</i>\n\n  <i>cast-type: one of</i>\n    bool  int  float  string\n\n  <i>await-expression:</i>\n    await  <i>expression</i>\n\n</pre>\n\n#### instanceof Operator\n\n<pre>\n  <i>instanceof-expression:</i>\n    <i>unary-expression</i>\n    <i>instanceof-subject</i>  instanceof   <i>instanceof-type-designator</i>\n\n  <i>instanceof-subject:</i>\n    <i>expression</i>\n\n  <i>instanceof-type-designator:</i>\n    <i>qualified-name</i>\n    <i>variable-name</i>\n</pre>\n\n#### Multiplicative Operators\n\n<pre>\n  <i>multiplicative-expression:</i>\n    <i>instanceof-expression</i>\n    <i>multiplicative-expression</i>  *  <i>instanceof-expression</i>\n    <i>multiplicative-expression</i>  /  <i>instanceof-expression</i>\n    <i>multiplicative-expression</i>  %  <i>instanceof-expression</i>\n</pre>\n\n#### Additive Operators\n\n<pre>\n  <i>additive-expression:</i>\n    <i>multiplicative-expression</i>\n    <i>additive-expression</i>  +  <i>multiplicative-expression</i>\n    <i>additive-expression</i>  -  <i>multiplicative-expression</i>\n    <i>additive-expression</i>  .  <i>multiplicative-expression</i>\n</pre>\n\n#### Bitwise Shift Operators\n\n<pre>\n  <i>shift-expression:</i>\n    <i>additive-expression</i>\n    <i>shift-expression</i>  &lt;&lt;  <i>additive-expression</i>\n    <i>shift-expression</i>  &gt;&gt;  <i>additive-expression</i>\n</pre>\n\n#### Relational Operators\n\n<pre>\n  <i>relational-expression:</i>\n    <i>shift-expression</i>\n    <i>relational-expression</i>  &lt;   <i>shift-expression</i>\n    <i>relational-expression</i>  &gt;   <i>shift-expression</i>\n    <i>relational-expression</i>  &lt;=  <i>shift-expression</i>\n    <i>relational-expression</i>  &gt;=  <i>shift-expression</i>\n</pre>\n\n#### Equality Operators\n\n<pre>\n  <i>equality-expression:</i>\n    <i>relational-expression</i>\n    <i>equality-expression</i>  ==  <i>relational-expression</i>\n    <i>equality-expression</i>  !=  <i>relational-expression</i>\n    <i>equality-expression</i>  ===  <i>relational-expression</i>\n    <i>equality-expression</i>  !==  <i>relational-expression</i>\n</pre>\n\n#### Bitwise Logical Operators\n\n<pre>\n  <i>bitwise-AND-expression:</i>\n    <i>equality-expression</i>\n    <i>bit-wise-AND-expression</i>  &amp;  <i>equality-expression</i>\n\n  <i>bitwise-exc-OR-expression:</i>\n    <i>bitwise-AND-expression</i>\n    <i>bitwise-exc-OR-expression</i>  ^   <i>bitwise-AND-expression</i>\n\n  <i>bitwise-inc-OR-expression:</i>\n    <i>bitwise-exc-OR-expression</i>\n    <i>bitwise-inc-OR-expression</i>  |  <i>bitwise-exc-OR-expression</i>\n</pre>\n\n#### Logical Operators\n\n<pre>\n  <i>logical-AND-expression:</i>\n    <i>bitwise-inc-OR-expression</i>\n    <i>logical-AND-expression</i>  &amp;&amp;  <i>bitwise-inc-OR-expression</i>\n\n  <i>logical-inc-OR-expression:</i>\n    <i>logical-AND-expression</i>\n    <i>logical-inc-OR-expression</i>  ||  <i>logical-AND-expression</i>\n</pre>\n\n#### Conditional Operator\n\n<pre>\n  <i>conditional-expression:</i>\n    <i>logical-inc-OR-expression</i>\n    <i>logical-inc-OR-expression</i>  ?  <i>expression<sub>opt</sub></i>  :  <i>conditional-expression</i>\n</pre>\n\n#### Pipe Operator\n\n<pre>\n  <i>piped-expression:</i>\n    <i>coalesce-expression</i>\n    <i>piped-expression</i>   |>   <i>coalesce-expression</i>\n</pre>\n\n#### Lambda Expressions\n\n<pre>\n<i>lambda-expression:</i>\n  <i>piped-expression</i>\n  async<sub>opt</sub>  <i>lambda-function-signature</i>  ==>  <i>lambda-body</i>\n\n<i>lambda-function-signature:</i>\n  <i>variable-name</i>\n  (  <i>anonymous-function-parameter-declaration-list<sub>opt</sub></i>  )  <i>anonymous-function-return<sub>opt</sub></i>\n\n<i>lambda-body:</i>\n  <i>expression</i>\n  <i>compound-statement</i>\n</pre>\n\n#### Assignment Operators\n\n<pre>\n  <i>assignment-expression:</i>\n    <i>lambda-expression</i>\n    <i>simple-assignment-expression</i>\n    <i>compound-assignment-expression</i>\n\n  <i>simple-assignment-expression:</i>\n    <i>unary-expression</i>  =  <i>assignment-expression</i>\n\n  <i>byref-assignment-expression:</i>\n    <i>unary-expression</i>  =  &  <i>assignment-expression</i>\n\n  <i>compound-assignment-expression:</i>\n    <i>unary-expression   compound-assignment-operator   assignment-expression</i>\n\n  <i>compound-assignment-operator: one of</i>\n    **=  *=  /=  %=  +=  -=  .=  &lt;&lt;=  >>=  &amp;=  ^=  |=\n</pre>\n\n#### yield Operator\n\n<pre>\n  <i>expression:</i>\n    <i>assignment-expression</i>\n    yield  <i>array-element-initializer</i>\n</pre>\n\n#### Constant Expressions\n\n<pre>\n  <i>constant-expression:</i>\n    <i>array-creation-expression</i>\n    <i>collection-literal</i>\n    <i>tuple-literal</i>\n    <i>shape-literal</i>\n    <i>const-expression</i>\n\n  <i>const-expression:</i>\n    <i>expression</i>\n</pre>\n\n### Statements\n\n#### General\n\n<pre>\n  <i>statement:</i>\n    <i>function-static-declaration</i>\n    <i>compound-statement</i>\n    <i>labeled-statement</i>\n    <i>expression-statement</i>\n    <i>selection-statement</i>\n    <i>iteration-statement</i>\n    <i>jump-statement</i>\n    <i>try-statement</i>\n</pre>\n\n#### Compound Statements\n\n<pre>\n  <i>compound-statement:</i>\n    {  <i>statement-list<sub>opt</sub></i>  }\n\n  <i>statement-list:</i>\n    <i>statement</i>\n    <i>statement-list   statement</i>\n</pre>\n\n#### Labeled Statements\n\n<pre>\n  <i>labeled-statement:</i>\n    <i>case-label</i>\n    <i>default-label</i>\n\n  <i>case-label:</i>\n    case   <i>expression</i>  :  <i>statement</i>\n\n  <i>default-label:</i>\n    default  :  <i>statement</i>\n</pre>\n\n#### Expression Statements\n\n<pre>\n   <i>expression-statement:</i>\n     <i>expression<sub>opt</sub></i>  ;\n\n  <i>selection-statement:</i>\n    <i>if-statement</i>\n    <i>switch-statement</i>\n\n  <i>if-statement:</i>\n    if   (   <i>expression</i>   )   <i>statement   elseif-clauses-opt   else-clause-opt</i>\n\n  <i>elseif-clauses:</i>\n    <i>elseif-clause</i>\n    <i>elseif-clauses   elseif-clause</i>\n\n  <i>elseif-clause:</i>\n    elseif   (   <i>expression</i>   )   <i>statement</i>\n\n  <i>else-clause:</i>\n    else   <i>statement</i>\n\n  <i>switch-statement:</i>\n    switch  (  <i>expression</i>  )  <i>compound-statement</i>     \n</pre>\n\n#### Iteration Statements\n\n<pre>\n  <i>iteration-statement:</i>\n    <i>while-statement</i>\n    <i>do-statement</i>\n    <i>for-statement</i>\n    <i>foreach-statement</i>\n\n  <i>while-statement:</i>\n    while  (  <i>expression</i>  )  <i>statement</i>\n\n  <i>do-statement:</i>\n    do  <i>statement</i>  while  (  <i>expression</i>  )  ;\n\n  <i>for-statement:</i>\n    for   (   <i>for-initializeropt</i>   ;   <i>for-controlopt</i>   ;   <i>for-end-of-loopopt</i>   )   <i>statement</i>\n\n  <i>for-initializer:</i>\n    <i>for-expression-group</i>\n\n  <i>for-control:</i>\n    <i>for-expression-group</i>\n\n  <i>for-end-of-loop:</i>\n    <i>for-expression-group</i>\n\n  <i>for-expression-group:</i>\n    <i>expression</i>\n    <i>for-expression-group</i>   ,   <i>expression</i>\n\n  <i>foreach-statement:</i>\n    foreach  (  <i>foreach-collection-name</i>  as  <i>foreach-key<sub>opt</sub>  foreach-value</i>  )   statement\n    foreach  (  <i>foreach-collection-name</i>  await  as  <i>foreach-key<sub>opt</sub>  foreach-value</i>  )   statement\n\n  <i>foreach-collection-name</i>:\n    <i>expression</i>\n\n  <i>foreach-key:</i>\n    <i>expression</i>  =>\n\n  <i>foreach-value:<i>\n    <i>expression</i>\n    <i>list-intrinsic</i>\n\n</pre>\n\n#### Jump Statements\n\n<pre>\n  <i>jump-statement:</i>\n    <i>continue-statement</i>\n    <i>break-statement</i>\n    <i>return-statement</i>\n    <i>throw-statement</i>\n\n  <i>continue-statement:</i>\n    continue  ;\n\n  <i>break-statement:</i>\n    break  ;\n\n  <i>return-statement:</i>\n    return  <i>expression<sub>opt</sub></i>  ;\n\n  <i>throw-statement:</i>\n    throw  <i>expression</i>  ;\n</pre>\n\n#### The try Statement\n\n<pre>\n  <i>try-statement:</i>\n    try  <i>compound-statement   catch-clauses</i>\n    try  <i>compound-statement   finally-clause</i>\n    try  <i>compound-statement   catch-clauses   finally-clause</i>\n\n  <i>catch-clauses:</i>\n    <i>catch-clause</i>\n    <i>catch-clauses   catch-clause</i>\n\n  <i>catch-clause:</i>\n    catch  (  <i>type-specifier</i>  <i>variable-name</i>  )  <i>compound-statement</i>\n\n  <i>finally-clause:</i>\n    finally   <i>compound-statement</i>\n</pre>\n\n### Script Inclusion\n\n<pre>\n  <i>inclusion-directive:</i>\n    <i>require-multiple-directive</i>\n    <i>require-once-directive</i>\n\n  <i>require-multiple-directive:</i>\n    require  <i>include-filename</i>  ;\n\n  <i>include-filename:</i>\n    <i>expression</i>  \n\n  <i>require-once-directive:</i>\n    require_once  <i>include-filename</i>  ;\n</pre>  \n\n### Enums\n\n<pre>\n  <i>enum-declaration:</i>\n  enum  <i>name</i>  <i>enum-base</i>  <i>type-constraint<sub>opt</sub></i>  {  <i>enumerator-list<sub>opt</sub></i>  }\n\n  <i>enum-base:</i>\n    :  int\n    :  string\n\n  <i>enumerator-list:</i>\n    <i>enumerator</i>\n    <i>enumerator-list</i>  <i>enumerator</i>\n\n  <i>enumerator:</i>\n    <i>enumerator-constant</i>  =  <i>constant-expression</i>  ;\n\n  <i>enumerator-constant:</i>\n    <i>name</i>\n</pre>\n\n### Generic Types, Methods and Functions\n\n<pre>\n  <i>generic-type-parameter-list:</i>\n    &lt;  <i>generic-type-parameters</i>  ,<sub>opt</sub>  &gt;\n\n  <i>generic-type-parameters:</i>\n    <i>generic-type-parameter</i>\n    <i>generic-type-parameters</i>  ,  <i>generic-type-parameter</i>\n\n  <i>generic-type-parameter:</i>\n    <i>generic-type-parameter-variance<sub>opt</sub></i>  <i>generic-type-parameter-name</i>  <i>type-constraint<sub>opt</sub></i>\n\n  <i>generic-type-parameter-name:</i>\n    <i>name</i>\n\n  <i>generic-type-parameter-variance:</i>\n    +\n    -\n\n  <i>generic-type-argument-list:</i>\n    &lt;  <i>generic-type-arguments</i>  ,<sub>opt</sub>  &gt;\n\n  <i>generic-type-arguments:</i>\n    <i>generic-type-argument</i>\n    <i>generic-type-arguments</i>  ,  <i>generic-type-argument</i>\n\n  <i>generic-type-argument:</i>\n    <i>type-specifier</i>\n    <i>name</i>\n</pre>\n\n### Functions\n\n<pre>\n  <i>function-definition:</i>\n    <i>attribute-specification<sub>opt</sub>   function-definition-no-attribute</i>\n\n  <i>function-definition-no-attribute:</i>\n    <i>function-definition-header  compound-statement</i>\n\n  <i>function-definition-header:</i>\n    async<sub>opt</sub>  function <i>name</i>  <i>generic-type-parameter-list<sub>opt</sub></i>  (  <i>parameter-list<sub>opt</sub></i>  ) :  <i>return-type</i>\n\n  <i>parameter-list:</i>\n    ...\n    <i>parameter-declaration-list</i>  ,<sub>opt</sub>\n    <i>parameter-declaration-list</i>  ,  ...\n\n  <i>parameter-declaration-list:</i>\n    <i>parameter-declaration</i>\n    <i>parameter-declaration-list</i>  ,  <i>parameter-declaration</i>\n\n  <i>parameter-declaration:</i>\n    <i>attribute-specification<sub>opt</sub></i>  <i>type-specifier</i>  <i>variable-name  default-argument-specifier<sub>opt</sub></i>\n\n  <i>default-argument-specifier:</i>\n    =  <i>const-expression</i>\n\n  <i>return-type:</i>\n    <i>type-specifier</i>\n    noreturn\n</pre>\n\n### Classes\n\n<pre>\n  <i>class-declaration:</i>\n    <i>attribute-specification<sub>opt</sub></i>  <i>class-modifier<sub>opt</sub></i>  class  <i>name  generic-type-parameter-list<sub>opt</sub></i>  <i>class-base-clause<sub>opt</sub></i>\n      <i>class-interface-clause<sub>opt</sub></i>  {  <i>trait-use-clauses<sub>opt</sub>  class-member-declarations<sub>opt</sub></i>  }\n\n  <i>class-modifier:</i>\n    abstract\n    final\n    abstract final\n\n  <i>class-base-clause:</i>\n    extends  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n\n  <i>class-interface-clause:</i>\n    implements  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n    <i>class-interface-clause</i>  ,  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n\n  <i>class-member-declarations:</i>\n    <i>class-member-declaration</i>\n    <i>class-member-declarations   class-member-declaration</i>\n\n   <i>class-member-declaration:</i>\n     <i>const-declaration</i>\n     <i>property-declaration</i>\n     <i>method-declaration</i>\n     <i>constructor-declaration</i>\n     <i>destructor-declaration</i>\n     <i>type-constant-declaration</i>\n\n  <i>const-declaration:</i>\n    abstract<i><sub>opt</sub></i>  const  <i>type-specifier<sub>opt</sub></i>  <i>constant-declarator-list</i>  ;\n\n  <i>constant-declarator-list:</i>\n    <i>constant-declarator</i>\n    <i>constant-declarator-list</i>  ,  <i>constant-declarator</i>\n\n  <i>constant-declarator:</i>\n    <i>name</i>  <i>constant-initializer<sub>opt</sub></i>\n\n  <i>constant-initializer:</i>\n    =  <i>const-expression</i>\n\n  <i>property-declaration:</i>\n    <i>property-modifier</i>  <i>type-specifier</i>  <i>property-declarator-list</i>  ;\n\n  <i>property-declarator-list:</i>\n    <i>property-declarator</i>\n    <i>property-declarator-list</i>  ,  <i>property-declarator</i>\n\n  <i>property-declarator:</i>\n    <i>variable-name</i>  <i>property-initializer<sub>opt</sub></i>\n\n  <i>property-modifier:</i>\n    <i>visibility-modifier</i>  <i>static-modifier<sub>opt</sub></i>\n    <i>static-modifier</i>  <i>visibility-modifier</i>\n\n  <i>visibility-modifier:</i>\n    public\n    protected\n    private\n\n  <i>static-modifier:</i>\n    static\n\n  <i>property-initializer:</i>\n    =  <i>expression</i>\n\n  <i>method-declaration:</i>\n    <i>attribute-specification<sub>opt</sub></i> <i>method-modifiers</i>  <i>function-definition-no-attribute</i>\n    <i>attribute-specification<sub>opt</sub></i> <i>method-modifiers</i>  <i>function-definition-header</i>  ;\n\n  <i>method-modifiers:</i>\n    <i>method-modifier</i>\n    <i>method-modifiers</i>  <i>method-modifier</i>\n\n  <i>method-modifier:</i>\n    <i>visibility-modifier</i>\n    <i>static-modifier</i>\n    abstract\n    final\n\n  <i>constructor-declaration:</i>\n  <i>attribute-specification<sub>opt</sub></i>  <i>constructor-modifiers</i>  function  __construct  (\n    <i>constructor-parameter-declaration-list<sub>opt</sub></i>  )  <i>void-return<sub>opt</sub></i>  <i>compound-statement</i>\n\n  <i>constructor-parameter-declaration-list:</i>\n    <i>constructor-parameter-declaration</i>\n    <i>constructor-parameter-declaration-list</i>  ,  <i>constructor-parameter-declaration</i>\n\n  <i>constructor-parameter-declaration:</i>\n    <i>visibility-modifier<sub>opt</sub></i>  <i>type-specifier</i>  <i>variable-name</i> <i>default-argument-specifier<sub>opt</sub></i>\n\n  <i>constructor-modifiers:</i>\n    <i>constructor-modifier</i>\n    <i>constructor-modifiers</i>  <i>constructor-modifier</i>\n\n  <i>constructor-modifier:</i>\n    <i>visibility-modifier</i>\n    abstract\n    final\n\n  <i>destructor-declaration:</i>\n    <i>attribute-specification<sub>opt</sub></i>  <i>visibility-modifier</i>  function  __destruct  ( )  <i>void-return<sub>opt</sub></i>  <i>compound-statement</i>\n\n  <i>void-return</i>:\n    : void \n\n  <i>type-constant-declaration:</i>\n    <i>abstract-type-constant-declaration</i>\n    <i>concrete-type-constant-declaration</i>\n  <i>abstract-type-constant-declaration:</i>\n    abstract  const  type  name  <i>type-constraint<sub>opt</sub></i>  ;\n  <i>concrete-type-constant-declaration:</i>\n    const  type  name  <i>type-constraint<sub>opt</sub><i>  =  <i>type-specifier</i>  ;\n</pre>\n\n### Interfaces\n\n<pre>\n  <i>interface-declaration:</i>\n    <i>attribute-specification<sub>opt</sub></i>  interface  <i>name</i>  <i>generic-type-parameter-list<sub>opt</sub></i>  <i>interface-base-clause<sub>opt</sub></i> {\n      <i>interface-member-declarations<sub>opt</sub></i>  }\n\n  <i>interface-base-clause:</i>\n    extends  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n    <i>interface-base-clause</i>  ,  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n\n  <i>interface-member-declarations:</i>\n    <i>interface-member-declaration</i>\n    <i>interface-member-declarations   interface-member-declaration</i>\n\n  <i>interface-member-declaration:</i>\n    <i>require-extends-clause</i>\n    <i>const-declaration</i>\n    <i>method-declaration</i>\n    <i>type-constant-declaration</i>\n</pre>\n\n### Traits\n\n<pre>\n  <i>trait-declaration:</i>\n   <i>attribute-specification<sub>opt</sub></i>  trait  <i>name</i>  <i>generic-type-parameter-list<sub>opt</sub></i>  <i>class-interface-clause<sub>opt</sub></i>  {\n     <i>trait-use-clauses<sub>opt</sub>  trait-member-declarations<sub>opt</sub></i>  }\n\n  <i>trait-use-clauses:</i>\n    <i>trait-use-clause</i>\n    <i>trait-use-clauses</i>  <i>trait-use-clause</i>\n\n  <i>trait-use-clause:</i>\n    use  <i>trait-name-list</i>  ;\n\n  <i>trait-name-list:</i>\n    <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n    <i>trait-name-list</i>  ,  <i>qualified-name</i>  <i>generic-type-argument-list<sub>opt</sub></i>\n\n  <i>trait-member-declarations:</i>\n    <i>trait-member-declaration</i>\n    <i>trait-member-declarations   trait-member-declaration</i>\n\n  <i>trait-member-declaration:</i>\n    <i>require-extends-clause</i>\n    <i>require-implements-clause</i>\n    <i>property-declaration</i>\n    <i>method-declaration</i>\n    <i>constructor-declaration</i>\n    <i>destructor-declaration</i>\n\n  <i>require-extends-clause:</i>\n    require  extends  <i>qualified-name</i>  ;\n\n  <i>require-implements-clause:</i>\n    require  implements  <i>qualified-name</i>  ;\n</pre>\n\n### Namespaces\n\n<pre>\n  <i>namespace-definition:</i>\n    namespace  <i>namespace-name</i>  ;\n    namespace  <i>namespace-name<sub>opt</sub></i> { <i>declaration-list<sub>opt</sub></i> }\n\n  <i>namespace-use-declaration:</i>\n    use <i>namespace-use-kind<sub>opt</sub></i>  <i>namespace-use-clauses</i>  ;\n    use <i>namespace-use-kind</i>  <i>namespace-name-as-a-prefix</i>  { <i>namespace-use-clauses</i>  }  ;\n    use <i>namespace-name-as-a-prefix</i>  { <i>namespace-use-kind-clauses</i>  }  ;\n\n  <i>namespace-use-clauses:</i>\n    <i>namespace-use-clause</i>\n    <i>namespace-use-clauses</i>  ,  <i>namespace-use-clause</i>\n\n  <i>namespace-use-clause:</i>\n    <i>qualified-name  namespace-aliasing-clause<sub>opt</sub></i>\n\n  <i>namespace-use-kind-clauses:</i>\n    <i>namespace-use-kind-clause</i>\n    <i>namespace-use-kind-clauses</i>  ,  <i>namespace-use-kind-clause</i>\n\n  <i>namespace-use-kind-clause:</i>\n    <i>namespace-use-kind<sub>opt</sub></i>  <i>qualified-name  namespace-aliasing-clause<sub>opt</sub></i>\n\n  <i>namespace-aliasing-clause:</i>\n    as  <i>name</i>\n\n  <i>namespace-use-kind</i>:\n    function\n    const\n\n  <i>namespace-name:</i>\n    <i>name </i>\n    <i>namespace-name   \\   name</i>\n\n  <i>namespace-name-as-a-prefix:</i>\n    \\\n    \\<sub>opt</sub>   <i>namespace-name</i>   \\\n    namespace   \\\n    namespace   \\   <i>namespace-name</i>   \\\n\n  <i>qualified-name:</i>\n    <i>namespace-name-as-a-prefix<sub>opt</sub>   name</i>\n</pre>\n\n### Attributes\n<pre>\n\n<i>attribute-specification:</i>\n  &lt;&lt;  <i>attribute-list</i>  &gt;&gt;\n\n<i>attribute-list:</i>\n  <i>attribute</i>\n  <i>attribute-list</i>  ,  <i>attribute</i>\n\n<i>attribute:</i>\n  <i>attribute-name</i>  <i>attribute-value-list<sub>opt</sub></i>\n\n<i>attribute-name:</i>\n  <i>name</i>\n\n<i>attribute-value-list:</i>\n  (  <i>attribute-values<sub>opt</sub></i>  )\n\n<i>attribute-values</i>\n  <i>attribute-value</i>\n  <i>attribute-values</i>  ,  <i>attribute-value</i>\n\n<i>attribute-value:</i>\n  <i>expression</i>\n</pre>\n"
  },
  {
    "path": "spec/23-differences-from-php.md",
    "content": "# Differences from PHP\n\n## General\nThis annex identifies the PHP features that are either not supported in Hack or that have different semantics.\n\n## Program Start-Up\nHack's strict mode does not allow access to any of the following: `$argc`, `$argv`, `$_COOKIE`,` $_ENV`, `$_FILES`, `$_GET`, `$GLOBALS`, `$_POST`, `$_REQUEST`, `$_SERVER`, or `$_SESSION`.\n\n## Constants\nConstants cannot be defined at the top level.\n\nRegarding `define()`'s names, lookup doesn’t work like in PHP. In Hack, have to use function `constant('name')` to refer to a defined name.\n\n`__CLASS__` cannot be used outside a class or trait.\n\n`__TRAIT__` cannot be used outside a trait.\n\n## Variables\nConstants are not supported except in classes and interfaces.\n\nGlobal variables are not supported.\n\nSuperglobals don’t exist.\n\n## Conversions\nUnlike PHP, Hack's conversion rules are very strict. As such, they may invalidate existing PHP code in the contexts of assignment, argument passing, and value returning. Specifically:\n* No non-`bool` type can be converted implicitly to `bool`. All other conversions must be explicit.\n* No non-`int` type can be converted implicitly to `int`. All other conversions must be explicit.\n* No non-`float` type can be converted implicitly to `float`. All other conversions must be explicit.\n* No non-`string` type can be converted implicitly to `string`. All other conversions must be explicit.\n* For arrays of different types, no implicit conversions exist. There are no explicit conversions to any array type.\n* An object type can be converted implicitly to any object type from which the first object type is directly or indirectly derived. There are no other implicit or explicit conversions.\n* An object type can be converted implicitly to any interface type that object type implements directly or indirectly. An interface type can be converted implicitly to any interface type from which the first interface type is directly or indirectly derived. There are no other implicit or explicit conversions.\n* No non-`resource` type can be converted implicitly to `resource`. No explicit conversions exist.\n\n## Lexical Structure\n\n### Comments\nHack treats comments of the forms `// strict` and `// FALLTHROUGH` in a special way.\n\n### Names\nIn Hack, function and method names are case-sensitive.\n\n### Keywords\nThe following PHP identifiers are keywords in Hack: `arraykey`, `async`, `enum`, `mixed`, `newtype`, `num`, `parent`, `self`, `shape`, `tuple`, and `type`.\n\n## Expressions\n\n### Primary Expressions\n\n#### General\nThe name of a function cannot be used as an expression without the function-call operator. Unlike in PHP, that name is not treated as a string containing that function's name.\n\n#### Intrinsics\nThe following intrinsics are not supported: `empty`, `eval`, `die`, `isset`, `print`, and `unset`.\n\nFor the intrinsic `list`, the target variables must be defined; the right-hand operand cannot be a map-like array; there must not be fewer element candidates in the source than there are target variables; and only the right-most variable can be omitted. Lists of lists are not permitted.\n\n#### Anonymous Function-Creation\nThe `&` byRef notation is not permitted on the function's return type nor in the use clause.\n\n### Postfix Operators\n\n#### The `new` Operator\nA call to a constructor without any arguments requires the function-call parentheses.\n\nThe *class-type-designator* cannot be a string containing a class name; it must be the class name itself.\n\n#### Array Creation Operator\nThe `&` byRef notation is not permitted.\n\nWith the distinction between vector-like arrays and map-like arrays, either all of the initializers must contain keys or none of them can have keys.\n\n#### Function call operator\nThe caller must pass an argument for each parameter not having a default value.\n\nEach argument passed is type-checked against the corresponding parameter.\n\nVariable functions are not permitted; however, the same thing can be achieved via the library function `fun`.\n\n#### Member-Selection Operator\nThe member name must be hard-coded; it cannot be expressed as a string.\n\nThis operator cannot be used to access a static method via an instance.\n\n#### Postfix Increment and Decrement Operators\nThe operand must have arithmetic type.\n\n#### Exponentiation Operator\nBoth operands must have arithmetic type.\n\n### Unary Operators\n\n#### Prefix Increment and Decrement Operators\nThe operand must have arithmetic type.\n\n#### Unary Arithmetic Operators\nThe operand must have arithmetic type.\n\n#### Shell Command Operator\nThis operator is not supported.\n\n#### Cast Operator\nHack does not allow casts to `array`, `binary`, `boolean`, `double`, `integer`, `object`, `real`, or `unset`.\n\n#### Variable-Name Creation Operator\n\nPHP allows variables to reference each other by means of a \"variable variable\". There are two syntaxes in PHP; if `$y` is equal to the string `\"x\"` then `$$y` and `${$y}` are both aliases for `$x`. This operator is not supported.\n\n### `instanceof` Operator\nThe right-hand operand cannot be a string.\n\n### Multiplicative Operators\nThe operands of the `*` and `/` operators must have arithmetic type.\n\nThe operands of the `%` operator must have integer type.\n\n### Bitwise Shift Operators\nBoth operands must have type `int`; there is no implicit conversion.\n\n### Bitwise `AND` Operator\nBoth operands must have type `int`; there is no implicit conversion.\n\n### Bitwise Exclusive `OR` Operator\nBoth operands must have type `int`; there is no implicit conversion.\n\n### Bitwise Inclusive `OR` Operator\nBoth operands must have type `int`; there is no implicit conversion.\n\n### Assignment Operators\n\n#### byRef Assignment\nThis is not supported.\n\n### Logical `AND`, `OR`, `XOR` Operators (Alternate Forms)\nThe `and`, `xor`, and `or` alternate forms are not supported.\n\n### String Literals\n\nPHP allows the syntax `\"${ expression }\"` in a double-quoted string literal, where the expression can be the name of a variable, or any expression which evaluates to a string naming a variable. This is an invalid string interpolation syntax in Hack.\n\n## Statements\n\n### General\nStatements cannot exist at the top level of a script.\n\n### Labeled Statements\nThere are no named labels or `goto` statement.\n\n### The `if` Statement\nThe alternate `: endif;` syntax is not supported.\n\n### The `switch` Statement\nThe alternate `: endswitch;` syntax is not supported.\n\nUnlike PHP, in Hack, each label expression's type must be a subtype of the switch expression type. For example, `switch(10)` won’t work with case `$a < $b:`.\n\n### The `while` Statement\nThe alternate `: endwhile;` syntax is not supported.\n\n### The `for` Statement\nThe alternate `: endfor;` syntax is not supported.\n\n### The `foreach` Statement\nThe alternate` : endforeach;` syntax is not supported.\n\nUnlike PHP, given `foreach ($colors as $index => $color)`, in Hack, the names `$index` and `$color` are not in scope outside the `foreach` body.\n\n### The `goto` Statement\nThis statement is not supported.\n\n### The `continue` Statement\n`continue n;` is not supported.\n\nIn PHP, `continue;` inside a `switch` statement is equivalent to` break;`. Hack does not emulate this.\n\n### The `break` Statement\n`break n;` is not supported.\n\n### The `return` Statement\nThis can't appear in a finally block.\n\nThis can’t be used to terminate a require file.\n\n### The declare Statement\nThis is not supported.\n\n## Script Inclusion\n`include` and `include_once` are not supported.\n\n`require` and `require_once` can be used only at the top level. They are not operators, so they do not produce a value.\n\n## Functions\nNested/conditional functions are not supported; except for anonymous functions, functions can only be defined at the top level.\n\nPassing and/or return by reference is not supported.\n\nThe `array` and `callable` type hints are not supported.\n\nEvery parameter must have a type.\n\nIf any parameter has a default argument value, then all parameters following it must also have one.\n\nAn empty parameter list means, \"no arguments can be passed\".\n\nA return type is required and a return type of `void` won’t let a value be returned. A non-`void` return type requires a return value of some subtype.\n\n## Classes\n\n### Class Members\nAll members except `const` must have a visibility modifier; there is no defaulting.\n\n### Dynamic Members\nDynamic properties are not supported.\n\nDynamic methods are supported, but `__call` cannot be called directly.\n\n### Properties\nA type specifier is needed.\n\nThe `var` modifier is not supported.\n\nAll properties of non-nullable type must be initialized explicitly either by a *property-initializer* or by the constructor. Properties of nullable type that are not explicitly initialized take on the value null. (as with PHP).\n\n### Methods\nHack requires parameter and return-type type specifiers.\n\n###  Constructors\nThe deprecated form of constructor name (using the name of the class) is not supported.\n\n### Methods with Special Semantics\n\n#### General\nHack requires parameter and return-type type specifiers.\n\n#### Method `__call`\nIt works, but it can't be called directly.\n\n#### Method `__get`\nThis method does not exist, as dynamic properties are not supported.\n\n#### Method `__invoke`\nUsing an instance like a function call is not supported.\n\n#### Method __isset\nThis method does not exist, as dynamic properties are not supported.\n\n#### Method __set\nThis method does not exist, as dynamic properties are not supported.\n\n#### Method __set_state\nThis is not useful, as the intrinsic `eval` is not supported.\n\n#### Method __unset\nThis method does not exist, as dynamic properties are not supported.\n\n### Predefined Classes\n\n#### Class Closure\nThis type does not exist.\n\n## Interfaces\n\n### Interface Members\nAll members except `const` must have a visibility modifier; there is no defaulting.\n\n### Methods\nHack requires parameter and return-type type specifiers.\n\n### Predefined Interfaces\nThe interfaces `ArrayAccess`, `Iterator`, `IteratorAggregate`, and `Traversable` are now generic interfaces.\n\n## Traits\n\n### Trait Declarations\nHack doesn’t support aliases and selection in a trait.\n\n## Namespaces\n\n### Namespace Use Declarations\nCan’t have a use clause, with or without an “as” at other than the top level of a script.\n"
  },
  {
    "path": "spec/24-bibliography.md",
    "content": "# Bibliography\n\nThe following documents are useful references for implementers and users\nof this specification:\n\nIEC 60559:1989, *Binary floating-point arithmetic for microprocessor\nsystems* (previously designated IEC 559:1989). (This standard is widely\nknown by its U.S. national designation, ANSI/IEEE Standard 754-1985,\nIEEE Standard for Binary Floating-Point Arithmetic.)\n\nThe Unicode Consortium. *The Unicode Standard, Version 5.0*,\n[www.Unicode.org](http://www.Unicode.org)).\n\n"
  },
  {
    "path": "spec/hack-spec-draft.md",
    "content": "# Specification for PHP\nFacebook has dedicated all copyright to this specification to the public\ndomain worldwide under the CC0 Public Domain Dedication located at\n<http://creativecommons.org/publicdomain/zero/1.0/>. This specification\nis distributed without any warranty.\n\n(Initially written in 2014 by Facebook, Inc., July 2014)\n\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](http://doctoc.herokuapp.com/)*\n\n- [Introduction](#introduction)\n- [Conformance](#conformance)\n- [Terms and Definitions](#terms-and-definitions)\n- [Basic Concepts](#basic-concepts)\n  - [Program Structure](#program-structure)\n  - [Program Start-Up](#program-start-up)\n  - [Program Termination](#program-termination)\n  - [The Memory Model](#the-memory-model)\n    - [General](#general)\n    - [Reclamation and Automatic Memory Management](#reclamation-and-automatic-memory-management)\n    - [Assignment](#assignment)\n      - [General](#general-1)\n      - [Value Assignment of Scalar Types to a Local Variable](#value-assignment-of-scalar-types-to-a-local-variable)\n      - [Value Assignment of Object and Resource Types to a Local Variable](#value-assignment-of-object-and-resource-types-to-a-local-variable)\n      - [ByRef Assignment for Scalar Types with Local Variables](#byref-assignment-for-scalar-types-with-local-variables)\n      - [Byref Assignment of Non-Scalar Types with Local Variables](#byref-assignment-of-non-scalar-types-with-local-variables)\n      - [Value Assignment of Array Types to Local Variables](#value-assignment-of-array-types-to-local-variables)\n      - [Deferred Array Copying](#deferred-array-copying)\n      - [General Value Assignment](#general-value-assignment)\n      - [General ByRef Assignment](#general-byref-assignment)\n    - [Argument Passing](#argument-passing)\n    - [Value Returning](#value-returning)\n    - [Cloning objects](#cloning-objects)\n  - [Scope](#scope)\n  - [Storage Duration](#storage-duration)\n- [Types](#types)\n  - [General](#general-2)\n  - [Scalar Types](#scalar-types)\n    - [General](#general-3)\n    - [The Boolean Type](#the-boolean-type)\n    - [The Integer Type](#the-integer-type)\n    - [The Floating-Point Type](#the-floating-point-type)\n    - [The String Type](#the-string-type)\n    - [The Null Type](#the-null-type)\n  - [Composite Types](#composite-types)\n    - [Array Types](#array-types)\n    - [Object Types](#object-types)\n    - [Resource Types](#resource-types)\n- [Constants](#constants)\n  - [General](#general-4)\n  - [Context-Dependent Constants](#context-dependent-constants)\n  - [Core Predefined Constants](#core-predefined-constants)\n  - [User-Defined Constants](#user-defined-constants)\n- [Variables](#variables)\n  - [General](#general-5)\n  - [Kinds of Variables](#kinds-of-variables)\n    - [Constants](#constants-1)\n    - [Local Variables](#local-variables)\n    - [Array Elements](#array-elements)\n    - [Function Statics](#function-statics)\n    - [Global Variables](#global-variables)\n    - [Instance Properties](#instance-properties)\n    - [Static Properties](#static-properties)\n    - [Class and Interface Constants](#class-and-interface-constants)\n  - [Predefined Variables](#predefined-variables)\n- [Conversions](#conversions)\n  - [General](#general-6)\n  - [Converting to Boolean Type](#converting-to-boolean-type)\n  - [Converting to Integer Type](#converting-to-integer-type)\n  - [Converting to Floating-Point Type](#converting-to-floating-point-type)\n  - [Converting to String Type](#converting-to-string-type)\n  - [Converting to Array Type](#converting-to-array-type)\n  - [Converting to Object Type](#converting-to-object-type)\n- [Lexical Structure](#lexical-structure)\n  - [Scripts](#scripts)\n  - [Grammars](#grammars)\n  - [Lexical analysis](#lexical-analysis)\n  - [General](#general-7)\n  - [Comments](#comments)\n    - [White Space](#white-space)\n    - [Tokens](#tokens)\n      - [General](#general-8)\n      - [Names](#names)\n      - [Keywords](#keywords)\n      - [Literals](#literals)\n        - [General](#general-9)\n        - [Boolean Literals](#boolean-literals)\n        - [Integer Literals](#integer-literals)\n        - [Floating-Point Literals](#floating-point-literals)\n        - [String Literals](#string-literals)\n          - [Single-Quoted String Literals](#single-quoted-string-literals)\n          - [Double-Quoted String Literals](#double-quoted-string-literals)\n          - [Heredoc String Literals](#heredoc-string-literals)\n          - [Nowdoc String Literals](#nowdoc-string-literals)\n        - [The Null Literal](#the-null-literal)\n      - [Operators and Punctuators](#operators-and-punctuators)\n- [Expressions](#expressions)\n  - [General](#general-10)\n  - [Primary Expressions](#primary-expressions)\n    - [General](#general-11)\n    - [Intrinsics](#intrinsics)\n      - [General](#general-12)\n      - [array](#array)\n      - [echo](#echo)\n      - [empty](#empty)\n      - [eval](#eval)\n      - [exit/die](#exitdie)\n      - [isset](#isset)\n      - [list](#list)\n      - [print](#print)\n      - [unset](#unset)\n    - [Anonymous Function-Creation](#anonymous-function-creation)\n  - [Postfix Operators](#postfix-operators)\n    - [General](#general-13)\n    - [The `clone` Operator](#the-clone-operator)\n    - [The `new` Operator](#the-new-operator)\n    - [Array Creation Operator](#array-creation-operator)\n    - [Subscript Operator](#subscript-operator)\n    - [Function Call Operator](#function-call-operator)\n    - [Member-Selection Operator](#member-selection-operator)\n    - [Postfix Increment and Decrement Operators](#postfix-increment-and-decrement-operators)\n    - [Scope-Resolution Operator](#scope-resolution-operator)\n    - [Exponentiation Operator](#exponentiation-operator)\n  - [Unary Operators](#unary-operators)\n    - [General](#general-14)\n    - [Prefix Increment and Decrement Operators](#prefix-increment-and-decrement-operators)\n    - [Unary Arithmetic Operators](#unary-arithmetic-operators)\n    - [Error Control Operator](#error-control-operator)\n    - [Shell Command Operator](#shell-command-operator)\n    - [Cast Operator](#cast-operator)\n    - [Variable-Name Creation Operator](#variable-name-creation-operator)\n  - [`instanceof` Operator](#instanceof-operator)\n  - [Multiplicative Operators](#multiplicative-operators)\n  - [Additive Operators](#additive-operators)\n  - [Bitwise Shift Operators](#bitwise-shift-operators)\n  - [Relational Operators](#relational-operators)\n  - [Equality Operators](#equality-operators)\n  - [Bitwise AND Operator](#bitwise-and-operator)\n  - [Bitwise Exclusive OR Operator](#bitwise-exclusive-or-operator)\n  - [Bitwise Inclusive OR Operator](#bitwise-inclusive-or-operator)\n  - [Logical AND Operator (form 1)](#logical-and-operator-form-1)\n  - [Logical Inclusive OR Operator (form 1)](#logical-inclusive-or-operator-form-1)\n  - [Conditional Operator](#conditional-operator)\n  - [Assignment Operators](#assignment-operators)\n    - [General](#general-15)\n    - [Simple Assignment](#simple-assignment)\n    - [byRef Assignment](#byref-assignment)\n  - [Compound Assignment](#compound-assignment)\n  - [Logical AND Operator (form 2)](#logical-and-operator-form-2)\n  - [Logical Exclusive OR Operator](#logical-exclusive-or-operator)\n  - [Logical Inclusive OR Operator (form 2)](#logical-inclusive-or-operator-form-2)\n  - [`yield` Operator](#yield-operator)\n  - [Script Inclusion Operators](#script-inclusion-operators)\n    - [General](#general-16)\n    - [The `include` Operator](#the-include-operator)\n    - [The `include_once` Operator](#the-include_once-operator)\n    - [The `require` Operator](#the-require-operator)\n    - [The `require_once` Operator](#the-require_once-operator)\n  - [Constant Expressions](#constant-expressions)\n- [Statements](#statements)\n  - [General](#general-17)\n  - [Compound Statements](#compound-statements)\n  - [Labeled Statements](#labeled-statements)\n  - [Expression Statements](#expression-statements)\n  - [Selection Statements](#selection-statements)\n    - [General](#general-18)\n    - [The `if` Statement](#the-if-statement)\n    - [The `switch` Statement](#the-switch-statement)\n  - [Iteration Statements](#iteration-statements)\n    - [General](#general-19)\n  - [The `while` Statement](#the-while-statement)\n  - [The `do` Statement](#the-do-statement)\n  - [The `for` Statement](#the-for-statement)\n  - [The `foreach` Statement](#the-foreach-statement)\n  - [Jump Statements](#jump-statements)\n    - [General](#general-20)\n    - [The `goto` Statement](#the-goto-statement)\n    - [The `continue` Statement](#the-continue-statement)\n  - [The `break` Statement](#the-break-statement)\n    - [The `return` Statement](#the-return-statement)\n    - [The `throw` Statement](#the-throw-statement)\n  - [The `try` Statement](#the-try-statement)\n  - [The `declare` Statement](#the-declare-statement)\n- [Arrays](#arrays)\n  - [General](#general-21)\n  - [Array Creation and Initialization](#array-creation-and-initialization)\n  - [Element Access and Insertion](#element-access-and-insertion)\n- [Functions](#functions)\n  - [General](#general-22)\n  - [Function Calls](#function-calls)\n  - [Function Definitions](#function-definitions)\n  - [Variable Functions](#variable-functions)\n  - [Anonymous Functions](#anonymous-functions)\n- [Classes](#classes)\n  - [General](#general-23)\n  - [Class Declarations](#class-declarations)\n  - [Class Members](#class-members)\n  - [Dynamic Members](#dynamic-members)\n  - [Constants](#constants-2)\n  - [Properties](#properties)\n  - [Methods](#methods)\n  - [Constructors](#constructors)\n  - [Destructors](#destructors)\n  - [Methods with Special Semantics](#methods-with-special-semantics)\n    - [General](#general-24)\n    - [Method `__call`](#method-__call)\n    - [Method `__callStatic`](#method-__callstatic)\n    - [Method `__clone`](#method-__clone)\n    - [Method `__get`](#method-__get)\n    - [Method `__invoke`](#method-__invoke)\n    - [Method `__isset`](#method-__isset)\n    - [Method `__set`](#method-__set)\n    - [Method `__set_state`](#method-__set_state)\n    - [Method `__sleep`](#method-__sleep)\n    - [Method `__toString`](#method-__tostring)\n    - [Method `__unset`](#method-__unset)\n    - [Method `__wakeup`](#method-__wakeup)\n  - [Serialization](#serialization)\n  - [Predefined Classes](#predefined-classes)\n    - [Class `Closure`](#class-closure)\n    - [Class `Generator`](#class-generator)\n    - [Class `__PHP_Incomplete_Class`](#class-__php_incomplete_class)\n    - [Class `stdClass`](#class-stdclass)\n- [Interfaces](#interfaces)\n  - [General](#general-25)\n  - [Interface Declarations](#interface-declarations)\n  - [Interface Members](#interface-members)\n  - [Constants](#constants-3)\n  - [Methods](#methods-1)\n  - [Predefined Interfaces](#predefined-interfaces)\n    - [Interface `ArrayAccess`](#interface-arrayaccess)\n    - [Interface `Iterator`](#interface-iterator)\n    - [Interface `IteratorAggregate`](#interface-iteratoraggregate)\n    - [Interface `Traversable`](#interface-traversable)\n    - [Interface  `Serializable`](#interface--serializable)\n- [Traits](#traits)\n  - [General](#general-26)\n  - [Trait Declarations](#trait-declarations)\n  - [Trait Members](#trait-members)\n- [Exception Handling](#exception-handling)\n  - [General](#general-27)\n  - [Class `Exception`](#class-exception)\n  - [Tracing Exceptions](#tracing-exceptions)\n  - [User-Defined Exception Classes](#user-defined-exception-classes)\n- [Namespaces](#namespaces)\n  - [General](#general-28)\n  - [Name Lookup](#name-lookup)\n  - [Defining Namespaces](#defining-namespaces)\n  - [Namespace Use Declarations**](#namespace-use-declarations)\n- [Grammar](#grammar)\n  - [General](#general-29)\n  - [Lexical Grammar](#lexical-grammar)\n    - [General](#general-30)\n    - [Comments](#comments-1)\n    - [White Space](#white-space-1)\n    - [Tokens](#tokens-1)\n      - [General](#general-31)\n      - [Names](#names-1)\n    - [Keywords](#keywords-1)\n    - [Literals](#literals-1)\n      - [General](#general-32)\n      - [Boolean Literals](#boolean-literals-1)\n      - [Integer Literals](#integer-literals-1)\n      - [Floating-Point Literals](#floating-point-literals-1)\n      - [String Literals](#string-literals-1)\n      - [The Null Literal](#the-null-literal-1)\n    - [Operators and Punctuators](#operators-and-punctuators-1)\n  - [Syntactic Grammar](#syntactic-grammar)\n    - [Program Structure](#program-structure-1)\n    - [Variables](#variables-1)\n    - [Expressions](#expressions-1)\n      - [Primary Expressions](#primary-expressions-1)\n      - [Postfix Operators](#postfix-operators-1)\n      - [Unary Operators](#unary-operators-1)\n      - [instanceof Operator](#instanceof-operator)\n      - [Multiplicative Operators](#multiplicative-operators-1)\n      - [Additive Operators](#additive-operators-1)\n      - [Bitwise Shift Operators](#bitwise-shift-operators-1)\n      - [Relational Operators](#relational-operators-1)\n      - [Equality Operators](#equality-operators-1)\n      - [Bitwise Logical Operators](#bitwise-logical-operators)\n      - [Logical Operators (form 1)](#logical-operators-form-1)\n      - [Conditional Operator](#conditional-operator-1)\n      - [Assignment Operators](#assignment-operators-1)\n      - [Logical Operators (form 2)](#logical-operators-form-2)\n      - [yield Operator](#yield-operator)\n      - [Script Inclusion Operators](#script-inclusion-operators-1)\n      - [Constant Expressions](#constant-expressions-1)\n    - [Statements](#statements-1)\n      - [General](#general-33)\n      - [Compound Statements](#compound-statements-1)\n      - [Labeled Statements](#labeled-statements-1)\n      - [Expression Statements](#expression-statements-1)\n      - [Iteration Statements](#iteration-statements-1)\n      - [Jump Statements](#jump-statements-1)\n      - [The try Statement](#the-try-statement)\n      - [The declare Statement](#the-declare-statement)\n    - [Functions](#functions-1)\n    - [Classes](#classes-1)\n    - [Interfaces](#interfaces-1)\n    - [Traits](#traits-1)\n    - [Namespaces](#namespaces-1)\n- [Bibliography](#bibliography)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n\n# Introduction\nThis specification is intended to provide a complete and concise\ndefinition of the syntax and semantics of the PHP language, suitable for\nuse by the following:\n\n-   Implementers of a PHP compiler\n-   Implementers of a test suite for the PHP language\n-   Programmers writing PHP code\n\nFor now, the runtime library has been excluded, as that is documented at\n[www.php.net](http://www.php.net). As such, all forward references to library facilities have placeholders of the form (§xx).\n\n# Conformance\nIn this specification, \"must\" is to be interpreted as a requirement on\nan implementation or on a program; conversely, \"must not\" is to be\ninterpreted as a prohibition.\n\nIf a \"must\" or \"must not\" requirement that appears outside of a\nconstraint is violated, the behavior is undefined. Undefined behavior is\notherwise indicated in this specification by the words \"undefined\nbehavior\" or by the omission of any explicit definition of behavior.\nThere is no difference in emphasis among these three; they all describe\n\"behavior that is undefined\".\n\nThe word \"may\" indicates \"permission\", and is never used to mean\n\"might\".\n\nA *strictly conforming program* must use only those features of the\nlanguage described in this specification. In particular, it must not\nproduce output dependent on any unspecified, undefined, or\nimplementation-defined behavior.\n\nA *conforming implementation* must accept any strictly conforming\nprogram. A conforming implementation may have extensions, provided they\ndo not alter the behavior of any strictly conforming program.\n\nA *conforming program* is one that is acceptable to a conforming\nimplementation.\n\nA conforming implementation must be accompanied by a document that\ndefines all implementation-defined characteristics and all extensions.\n\nSome Syntax sections are followed by a Constraints section, which\nfurther restricts the grammar. After issuing a diagnostic for a\nconstraint violation, a conforming implementation may continue program\nexecution. In some cases, such continuation behavior is documented (for\nexample, what happens when passing too few arguments to a function).\nMaking such things constraint violations simply forces the issuance of a\ndiagnostic; it does not require that program execution terminate.\n\nThis specification contains explanatory material—called *informative* or\n*non-normative* text—that, strictly speaking, is not necessary in a\nformal language specification. Examples are provided to illustrate\npossible forms of the constructions described. References are used to\nrefer to related clauses. Notes and Implementer Notes are provided to\ngive advice or guidance to implementers or programmers. Informative\nannexes provide additional information and summarize the information\ncontained in this specification. All text not marked as informative is\n*normative*.\n\nCertain features are marked as *deprecated*. While these are normative\nfor the current edition of this specification, they are not guaranteed\nto exist in future revisions. Usually, they are old approaches that have\nbeen superseded by new ones, and use of the old approach is discouraged.\n(Examples of this include the use of braces ({ }) for subscripting, and\nthe use of old-style constructor names.)\n\n# Terms and Definitions\nFor the purposes of this document, the following terms and definitions\napply:\n\n**argument** – an expression passed to a function, that is intended to\nmap to a corresponding parameter.\n\n**behavior** – external appearance or action.\n\n**behavior, implementation-defined** – behavior specific to an\nimplementation, where that implementation must document that behavior.\n\n**behavior, undefined** – behavior on handling an erroneous program\nconstruct or data.\n\n**behavior, unspecified** – behavior for which this specification\nprovides no requirements.\n\n**constraint** – restriction, either syntactic or semantic, on how\nlanguage elements can be used.\n\n**error, fatal** – a translation or runtime condition from which the\ntranslator or engine cannot recover.\n\n**error, fatal, catchable** – a fatal error that can be caught by a\nuser-defined handler.\n\n**error, non-fatal** – an error that is not fatal.\n\n**lvalue** – an expression that designates a memory location having a\ntype.\n\n**lvalue, modifiable** – an lvalue whose value can be changed.\n\n**lvalue, non-modifiable** – an lvalue whose value cannot be changed.\n\n**parameter** – a variable declared in the parameter list of a function\nthat is intended to map to a corresponding argument in a call to that\nfunction.\n\n**PHP Run-Time Engine** – the machinery that executes a PHP program.\nReferred to as *the Engine* throughout this specification.\n\n**value** – precise meaning of the contents of a memory location when\ninterpreted as having a specific type.\n\nOther terms are defined throughout this specification, as needed, with\nthe first usage being typeset *like this*.\n\n\n# Basic Concepts\n# # Program Structure\nA PHP *program* consists of one or more source files, known formally as\n*scripts*.\n\n<pre>\n<i>script:</i>\n<i> script-section</i>\n<i> script   script-section</i>\n\n<i>script-section:</i>\n  <i> text<sub>opt</sub></i> &lt;?php <i>statement-list<sub>opt</sub></i> ?&gt;<sub>opt</sub> <i>text<sub>opt</sub></i>\n\n<i>text:</i>\n  arbitrary text not containing the sequence &lt;?php\n</pre>\n\nAll of the sections in a script are treated as though they belonged to\none continuous section, except that any intervening text is treated as\nthough it were a string literal given to the intrinsic `echo` ([§§](#echo)). \n\nA script can import another script via a script inclusion operator ([§§](#script-inclusion-operators)).\n\n*statement-list* is defined in [§§](#compound-statements).\n\nThe top level of a script is simply referred to as the *top level*.\n\n# # Program Start-Up\nA program begins execution at the start of a script ([§§](#program-structure)) designated in\nsome unspecified manner. This script is called the *start-up script*.\n\nOnce a program is executing, it has access to certain environmental\ninformation ([§§](#predefined-variables)), as follows:\n\n-   The number of *command-line arguments*, via the predefined variable\n    `$argc`.\n-   A series of one or more command-line arguments as strings, via the\n    predefined variable `$argv`.\n-   A series of *environment variable* names and their definitions.\n\nWhen a top level ([§§](#program-structure)) is the main entry point for a script, it gets\nthe global variable environment. When a top level is invoked via\n`include/require` ([§§](#general-16)), it inherits the variable environment of its caller. Thus,\nwhen looking at one top level in isolation, it's not\npossible to tell statically whether it will have the global\nvariable environment or some local variable environment. It depends on how the\npseudo-main is invoked and it depends on the runtime state of the program\nwhen it's invoked.\n\n# # Program Termination\nA program may terminate normally in the following ways:\n\n-   Execution reaches the end of the start-up script ([§§](#program-start-up)).\n-   A `return` statement ([§§](#the-return-statement)) in the start-up script is executed.\n-   The intrinsic `exit` ([§§](#exitdie)) is called explicitly.\n\nThe behavior of the first two cases is equivalent to corresponding calls\nto exit.\n\nA program may terminate abnormally under various circumstances, such as\nthe detection of an uncaught exception, or the lack of memory or other\ncritical resource. If execution reaches the end of the start-up script\nvia a fatal error, or via an uncaught exception and there is no uncaught\nexception handler registered by `set_exception_handler`, that is\nequivalent to `exit(255)`. If execution reaches the end of the start-up\nscript via an uncaught exception and an uncaught exception handler was\nregistered by `set_exception_handler`, that is equivalent to exit(0). It\nis unspecified whether object destructors ([§§](#destructors)) are run. In all other cases, the\nbehavior is unspecified.\n\n# # The Memory Model\n## # General\nThis subclause and those immediately following it describe the abstract\nmemory model used by PHP for storing variables. A conforming\nimplementation may use whatever approach is desired as long as from any\ntestable viewpoint it appears to behave as if it follows the abstract\nmodel. The abstract model makes no explicit or implied restrictions or\nclaims about performance, memory consumption, and machine resource\nusage.\n\nThe abstract model presented here defines three kinds of abstract memory\nlocations:\n\n-   A *value storage location* (VStore) is used to represent a program\n    value, and is created by the Engine as needed. A VStore can contain\n    a scalar value such as an integer or a Boolean, or it can contain a\n    handle pointing to an HStore (see below).\n-   A *variable slot* (VSlot) is used to represent a variable named by\n    the programmer in the source code, such as a local variable, an\n    array element, an instance property of an object, or a static\n    property of a class. A VSlot comes into being based on explicit\n    usage of a variable in the source code. A VSlot contains a pointer\n    to a VStore.\n-   A *heap storage location* (HStore) is used to represent the contents\n    of any non-scalar value, and is created by the Engine as needed.\n\nEach existing variable has its own VSlot, which at any time contains a\npointer to a VStore. A VSlot cannot contain a null pointer. A VSlot can\nbe changed to point to different VStores over time. Multiple VSlots may\nsimultaneously point to the same VStore. When a new VSlot is created, a\nnew VStore is also created and the VSlot is initially set to point to\nthe new VStore.\n\nA VStore can be changed to contain different scalar values and handles\nover time. Multiple VStores may simultaneously contain handles that\npoint to the same HStore. When a VStore is created it initially contains\nthe scalar value NULL unless specified otherwise. In addition to\ncontaining a value, VStores also carry a *type tag* that indicates the\ntype ([§§](#types)) of the VStore’s value. A VStore’s type tag can be changed over\ntime. At any given time a VStore’s type tag may be one of the following:\n`Null`, `Bool`, `Int`, `Float`, `Str`, `Arr`, `Arr-D` (see [§§](#deferred-array-copying)), `Obj`, or `Res`.\n\nAn HStore represents the contents of a non-scalar value, and it may\ncontain zero or more VSlots. At run time, the Engine may add new VSlots\nand it may remove and destroy existing VSlots as needed to support\nadding/removing array elements (for arrays) and to support\nadding/removing instance properties (for objects). HStores that\nrepresent the contents of arrays and objects have some unspecified way\nto identify and retrieve a contained VSlot using a dictionary scheme\n(such as having values with integer keys or case-sensitive string keys).\nWhether an HStore is a fixed-size during its whole lifetime or whether\nit can change size, is unspecified. Whether it allocates auxiliary\nchunks of memory or not, is unspecified. Whether it organizes it's\ncontained VSlots in a linked list or some other manner is unspecified.\n\nAn HStore’s VSlots (i.e., the VSlots contained within the HStore) point\nto VStores, and each VStore contains a scalar value or a handle to an\nHStore, and so on through arbitrary levels, allowing arbitrarily complex\ndata structures to be represented. For example, a singly linked list\nmight consist of a variable called `$root`, which is represented by a\nVSlot pointing to a VStore containing a handle to the first node. Each\nnode is represented by an HStore that contains the data for that node in\none or more VSlots, as well as a VSlot pointing to VStore containing a\nhandle to the next node. Similarly, a binary tree might consist of a\nvariable called `$root`, which is represented by a VSlot pointing to a\nVStore containing a handle to the root node. Each node is represented by\nan HStore that contains the data for that node in one or more VSlots, as\nwell as a pair of VSlots pointing to VStores containing the handles to\nthe left and right branch nodes. The leaves of the tree would be VStores\nor HStores, as needed.\n\nVSlots cannot contain pointers to VSlots or handles to HStores. VStores\ncannot contain pointers to VSlots or VStores. HStores cannot directly\ncontain any pointers or handles to any abstract memory location; HStores\ncan only directly contain VSlots.\n\nHere is an example demonstrating one possible arrangement of VSlots,\nVStores, and HStores:\n\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                                        |            |\n                                                        V            V\n                                                [VStore Int 1]  [VStore Int 3]\n</pre>\n\nIn this picture the VSlot in the upper left corner represents the\nvariable `$a`, and it points to a VStore that represents `$a`’s current\nvalue. This VStore contains a handle to an HStore which represents the\ncontents of an object of type Point with two instance properties `$x`\nand `$y`. This HStore contains two VSlots representing instance\nproperties `$x` and `$y`, and each of these VSlots points to a distinct\nVStore which contains an integer value. \n\n***Implementation Notes:*** php.net’s implementation can be mapped roughly\nonto the abstract memory model as follows: `zval pointer => VSlot, zval\n=> VStore, HashTable => HStore`, and\n`zend_object/zend_object_handlers => HStore`. Note, however, that the\nabstract memory model is not intended to exactly match the php.net\nimplementation’s model, and for generality and simplicity there are some\nsuperficial differences between the two models.\n\nFor most operations, the mapping between VSlots and VStores remains the\nsame. Only the following program constructs can change a VSlot to point\nto different VStore, all of which are *byRef-aware* operations and all\nof which (except unset) use the & punctuator:\n\n-   byRef assignment ([§§](#byref-assignment))\n-   byRef parameter declaration ([§§](#function-definitions))\n-   byRef function return ([§§](#the-return-statement), [§§](#function-definitions))\n-   byRef value in a foreach statement ([§§](#the-foreach-statement))\n-   byRef initializer for an array element ([§§](#array-creation-operator))\n-   byRef variable-use list in an anonymous function ([§§](#anonymous-function-creation))\n-   unset ([§§](#unset))\n\n## # Reclamation and Automatic Memory Management\nThe Engine is required to manage the lifetimes of VStores and HStores\nusing some form of automatic memory management.\n\nWhen dealing with VStores and HStores, the Engine is required to implement\nsome form of automatic memory management. When a VStore or HStore\nis created, memory is allocated for it, and for an HStore that represents\nan object ([§§](#object-types)), its constructor ([§§](#constructors)) is invoked.\n\nLater, if a VStore or HStore becomes unreachable through any existing\nvariable, they become eligible for reclamation to release the memory\nthey occupy. The engine may reclaim a VStore or HStore at any time\nbetween when it becomes eligible for reclamation and when the script\nexits. Before reclaiming an HStore that represents an object ([§§](#object-types)),\nthe Engine will invoke the object’s destructor ([§§](#constructors)) if one is defined.\n\nThe Engine must reclaim each VSlot when the storage duration ([§§](#storage-duration)) of its\ncorresponding variable ends, when the variable is explicitly unset by the\nprogrammer, or when the script exits, whichever comes first. In the case where\na VSlot is contained within an HStore (i.e. an array element or an object\ninstance property), the engine must immediate reclaim the VSlot when it is\nexplicitly unset by the programmer, when the containing HStore is reclaimed,\nor when the script exits, whichever comes first.\n\nThe precise form of automatic memory management used by the Engine is\nunspecified, which means that the time and order of the reclamation of\nVStores and HStores is unspecified.\n\nA VStore’s refcount is defined as the number of unreclaimed VSlots that point\nto the VStore. Because the precise form of automatic memory management is not\nspecified, a VStore’s refcount at a given time may differ between\nconforming implementations due to VSlots, VStores, and HStores being\nreclaimed at different times. Despite the use of the term refcount,\nconforming implementations are not required to use a reference\ncounting-based implementation for automatic memory management.\n\n**(dead)**: In some pictures, storage-location boxes are shown as (dead).\nFor a VStore or an HStore this indicates that the VStore or HStore is no\nlonger reachable through any variable and is eligible for reclamation. For\na VSlot, this indicates that the VSlot has been reclaimed or, in the case\nof a VSlot contained with an HStore, that the containing HStore has been\nreclaimed or is eligible for reclamation.\n\n## # Assignment\n### # General\nThis subclause and those immediately following it describe the abstract\nmodel’s implementation of *value assignment* and *byRef assignment*.\nValue assignment of non-array types to local variables is described\nfirst, followed by byRef assignment with local variables, followed by\nvalue assignment of array types to local variables, and ending with\nvalue assignment with complex left-hand side expressions, and byRef\nassignment with complex expressions on the left- or right-hand side.\n\nValue assignment and byRef assignment are core to the PHP language, and\nmany other operations in this specification are described in terms of\nvalue assignment and byRef assignment.\n\n### # Value Assignment of Scalar Types to a Local Variable\nValue assignment is the primary means by which the programmer can create\nlocal variables. If a local variable appears on the left-hand side of\nvalue assignment does not exist, the engine will bring a new local\nvariable into existence and create a VSlot and initial VStore for\nstoring the local variable’s value.\n\nConsider the following example of value assignment ([§§](#simple-assignment)) of scalar\nvalues to local variables:\n\n```\n$a = 123;\n\n$b = false;\n```\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n\n[VSlot $b *]-->[VStore Bool false]\n</pre>\n\nVariable `$a` comes into existence and is represented by a newly created\nVSlot pointing to a newly created VStore. Then the integer value 123 is\nwritten to the VStore. Next, `$b` comes into existence represented by a\nVSlot and corresponding VStore, and the Boolean value false is written\nto the VStore.\n\nNext consider the value assignment `$b = $a`:\n\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n\n[VSlot $b *]-->[VStore Int 123 (Bool false was overwritten)]\n</pre>\n\nThe integer value 123 is read from `$a`’s VStore and is written into\n`$b`’s VStore, overwriting its previous contents. As we can see, the two\nvariables are completely self-contained; each has its own VStore\ncontaining a separate copy of the integer value 123. Value assignment\nreads the contents of one VStore and overwrites the contents of the\nother VStore, but the relationship of VSlots to VStores remains\nunchanged. Changing the value of `$b` has no effect on `$a`, and vice\nversa.\n\nUsing literals or arbitrarily complex expressions on the right hand side\nof value assignment value works the same as it does for variables,\nexcept that the literals or expressions don’t have their own VSlots or\nVStores. The scalar value or handle produced by the literal or\nexpression is written into the VStore of the left hand side, overwriting\nits previous contents.\n\n***Implementation Notes:*** For simplicity, the abstract model’s\ndefinition of value assignment never changes the mapping from VSlots to\nVStores. This aspect of the abstract model is superficially different\nfrom the php.net implementation’s model, which in some cases will set\ntwo variable slots to point to the same zval when performing value\nassignment. Despite this superficial difference, php.net’s\nimplementation produces the same observable behavior as the abstract\nmodel presented here.\n\nTo illustrate the semantics of value assignment further, consider `++$b`:\n\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n\n[VSlot $b *]-->[VStore Int 124 (123 was overwritten)]\n</pre>\n\nNow consider `$a = 99`:\n\n<pre>\n[VSlot $a *]-->[VStore Int 99 (123 was overwritten)]\n\n[VSlot $b *]-->[VStore Int 124]\n</pre>\n\nIn both of these examples, one variable’s value is changed without\naffecting the other variable’s value. While the above examples only\ndemonstrate value assignment for integer and Boolean values, the same\nmechanics apply for all scalar types.\n\nNote that strings are also considered scalar values for the purposes of\nthe abstract memory model. Unlike non-scalar types which are represented\nusing a VStore pointing to an HStore containing the non-scalar value’s\ncontents, the abstract model assumes that a string’s entire contents\n(i.e., the string’s characters and its length) can be stored in a VStore\nand that value assignment for a string eagerly copies a string’s entire\ncontents to the VStore being written to. Consider the following example:\n\n```\n$a = 'gg';\n\n$b = $a;\n```\n\n<pre>\n[VSlot $a *]-->[VStore Str 'gg']\n\n[VSlot $b *]-->[VStore Str 'gg']\n</pre>\n\n`$a`’s string value and `$b`’s string values are distinct from each other,\nand mutating `$a`’s string will not affect `$b`. Consider `++$b`, for\nexample:\n\n<pre>\n[VSlot $a *]-->[VStore Str 'gg']\n\n[VSlot $b *]-->[VStore Str 'gh']\n</pre>\n\n***Implementation Notes:*** For simplicity, the abstract model represents\na string as a scalar value that can be entirely contained within VStore.\nThis aspect of the abstract model is superficially different from the\nphp.net implementation’s model, where a zval points to a separate buffer\nin memory containing a string’s characters and in the common case\nmultiple slots point to the same zval that holds the string. Despite\nthis superficial difference, php.net’s implementation produces the same\nobservable behavior (excluding performance and resource consumption) as\nthe abstract model presented here.\n\nBecause a string’s content can be arbitrarily large, copying a string’s\nentire contents for value assignment can be expensive. In practice an\napplication written in PHP may rely on value assignment of strings being\nrelatively inexpensive (in order to deliver acceptable performance), and\nas such it is common for an implementation to use a deferred copy\nmechanism to reduce the cost of value assignment for strings. Deferred\ncopy mechanisms work by not copying a string during value assignment and\ninstead allowing multiple variables to share the string’s contents\nindefinitely until a mutating operation (such as the increment operator)\nis about to be executed on the string, at which time some or all of the\nstring’s contents are copied. A conforming implementation may choose to\ndefer copying a string’s contents for value assignment so long as it has\nno observable effect on behavior from any testable viewpoint (excluding\nperformance and resource consumption).\n\n### # Value Assignment of Object and Resource Types to a Local Variable\n\nTo demonstrate value assignment of objects to local variables, consider\nthe case in which we have a Point class that supports a two-dimensional\nCartesian system. An instance of Point contains two instance properties,\n`$x` and `$y`, that store the x- and y-coordinates, respectively. A\nconstructor call ([§§](#constructors)) of the form `Point(x, y)` used with operator `new` ([§§](#the-new-operator))\ncreates a new point at the given location, and a method call\nof the form `move(newX, newY)` moves a `Point` to the new location.\n\nWith the `Point` class, let us consider the value assignment `$a = new\nPoint(1, 3)`:\n\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                                        |            |\n                                                        V            V\n                                                 [VStore Int 1]  [VStore Int 3]\n</pre>\n\nVariable `$a` is given its own VSlot, which points to a VStore that\ncontains a handle pointing to an HStore allocated by `new` ([§§](#the-new-operator)) and\nthat is initialized by `Point`'s constructor.\n\nNow consider the value assignment `$b = $a`:\n\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                  ^                     |            |\n                                  |                     V            V\n[VSlot $b *]-->[VStore Obj *]-----+             [VStore Int 1] [VStore Int 3]\n</pre>\n\n`$b`‘s VStore contains a handle that points to the same object as does\n`$a`‘s VStore’s handle. Note that the Point object itself was not copied,\nand note that `$a`’s and `$b`’s VSlots point to distinct VStores.\n\nLet's modify the value of the Point whose handle is stored in `$b` using\n`$b->move(4, 6)`:\n\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                  ^                     |            |\n                                  |                     V            V\n[VSlot $b *]-->[VStore Obj *]-----+         [VStore Int 4] [VStore Int 6]\n                                       (1 was overwritten) (3 was overwritten)\n</pre>\n\nAs we can see, changing `$b`'s Point changes `$a`'s as well.\n\nNow, let's make `$a` point to a different object using `$a = new Point(2,\n1)`:\n\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                                        |            |\n[VSlot $b *]-->[VStore Obj *]-----+                     V            V\n                                  |             [VStore Int 2] [VStore Int 1]\n                                  V\n                                [HStore Point [VSlot $x *] [VSlot $y *]]\n                                                        |            |\n                                                        V            V\n                                                [VStore Int 4] [VStore Int 6]\n</pre>\n\nBefore `$a` can take on the handle of the new `Point`, its handle to the\nold `Point` must be removed, which leaves the handles of `$a` and `$b`\npointing to different Points.\n\nWe can remove all these handles using `$a = NULL` and `$b = NULL`:\n<pre>\n[VSlot $a *]-->[VStore Null]    [HStore Point [VSlot $x *] [VSlot $y *] (dead)]\n                                                        |            |\n[VSlot $b *]-->[VStore Null]    [VStore Int 2 (dead)]&lt;--+            V\n                                                          [VStore Int 1 (dead)]\n                                                          \n                                [HStore Point [VSlot $x *] [VSlot $y *] (dead)]\n                                                        |            |\n                                [VStore Int 4 (dead)]&lt;--+            V\n                                                        [VStore Int 6 (dead)]\n</pre>\n\nBy assigning null to `$a`, we remove the only handle to `Point(2,1)`, which\nallows that object's destructor ([§§](#destructors)) to run. A similar thing happens\nwith `$b`, as it too is the only handle to its Point.\n\nAlthough the examples above only show with only two instance properties,\nthe same mechanics apply for value assignment of all object types, even\nthough they can have an arbitrarily large number of instance properties\nof arbitrary type. Likewise, the same mechanics apply to value\nassignment of all resource types.\n\n### # ByRef Assignment for Scalar Types with Local Variables\nLet's begin with the same value assignment ([§§](#simple-assignment)) as in the previous\nsubclause, `$a = 123` and `$b = false`:\n\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n\n[VSlot $b *]-->[VStore Bool false]\n</pre>\n\nNow consider the byRef assignment ([§§](#byref-assignment)) `$b =& $a`, which has byRef\nsemantics:\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n                 ^\n                 |\n[VSlot $b *]-----+     [VStore Bool false (dead)]\n</pre>\n\nIn this example, byRef assignment changes `$b`’s VSlot point to the same\nVStore that `$a`’s VSlot points to. The old VStore that `$b`’s VSlot used\nto point to is now unreachable. As stated in [§§](#general), it is not possible for a VSlot to point to another VSlot, so `$b`‘s VSlot cannot point to `$a`‘s VSlot. When multiple variables’ VSlots point to the same VStore,\nthe variables are said to be *aliases* of each other or they are said to\nhave an *alias relationship*. In the example above, after the byRef\nassignment executes the variables `$a` and `$b` will be aliases of each\nother.\n\nNow, let's observe what happens when we change the value of `$b` using\n`++$b`:\n<pre>\n[VSlot $a *]-->[VStore Int 124 (123 was overwritten)]\n                 ^\n                 |\n[VSlot $b *]-----+\n</pre>\n\n`$b`‘s value, which is stored in the VStore that `$b`’s VSlot points, is\nchanged to 124. And as that VStore is also aliased by `$a`’s VSlot, the\nvalue of `$a` is also 124. Indeed, any variable’s VSlot that is aliased\nto that VStore will have the value 124.\n\nNow consider the value assignment `$a = 99`:\n<pre>\n[VSlot $a *]-->[VStore Int 99 (124 was overwritten)]\n                 ^\n                 |\n[VSlot $b *]-----+\n</pre>\n\nThe alias relationship between `$a` and `$b` can be broken explicitly by\nusing `unset` on variable `$a` or variable `$b`. For example, consider\n`unset($a)`:\n<pre>\n[VSlot $a (dead)]      [VStore Int 99]\n                         ^\n                         |\n[VSlot $b *]-------------+\n</pre>\n\nUnsetting `$a` causes variable `$a` to be destroyed and its corresponding\nalias to the VStore to be removed, leaving `$c`’s VSlot as the only\npointer remaining to the VStore.\n\nOther operations can also break an alias relationship between two or\nmore variables. For example, `$a = 123` and `$b =& $a`, and `$c = 'hi'`:\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n                 ^\n                 |\n[VSlot $b *]-----+\n\n[VSlot $c *]-->[VStore Str 'hi']\n</pre>\n\nAfter the byRef assignment, `$a` and `$b` now have an alias relationship.\nNext, let's observe what happens for `$b = &$c`:\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n\n[VSlot $b *]-----+\n                 |\n                 V\n[VSlot $c *]-->[VStore Str 'hi']\n</pre>\n\nAs we can see, the byRef assignment above breaks the alias relationship\nbetween `$a` and `$b`, and now `$b` and `$c` are aliases of each other. When\nbyRef assignment changes a VSlot to point to a different VStore, it\nbreaks any existing alias relationship the left hand side variable had\nbefore the assignment operation.\n\nIt is also possible to use byRef assignment to make three or more VSlots\npoint to the same VStore. Consider the following example:\n\n```\n$b = &$a;\n$c = &$b;\n$a = 123;\n```\n<pre>\n[VSlot $a *]-->[VStore Int 123]\n                 ^   ^\n                 |   |\n[VSlot $b *]-----+   |\n                     |\n[VSlot $c *]---------+\n</pre>\n\nLike value assignment, byRef assignment provides a means for the\nprogrammer to created variables. If the local variables that appear on\nthe left- or right-hand side of byRef assignment do not exist, the\nengine will bring new local variables into existence and create a VSlot\nand initial VStore for storing the local variable’s value.\n\nNote that literals, constants, and other expressions that don’t\ndesignate a modifiable lvalue cannot be used on the left- or right-hand\nside of byRef assignment.\n\n### # Byref Assignment of Non-Scalar Types with Local Variables\nbyRef assignment of non-scalar types works using the same mechanism as\nbyRef assignment for scalar types. Nevertheless, it is worthwhile to\ndescribe a few examples to clarify the semantics of byRef assignment.\nRecall the example from [§§](#value-assignment-of-object-and-resource-types-to-a-local-variable)) using the `Point` class:\n\n`$a = new Point(1, 3);`\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]\n                                                        |            |\n                                                        V            V\n                                               [VStore Int 1]  [VStore Int 3]\n</pre>\n\nNow consider the byRef assignment ([§§](#byref-assignment)) `$b =& $a`, which has byRef\nsemantics:\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *][VSlot $y *]]\n                 ^                                      |           |\n                 |                                      V           V\n[VSlot $b *]-----+                               [VStore Int 1] [VStore Int 3]\n</pre>\n`$a` and `$b` now aliases of each other. Note that byRef assignment\nproduces a different result than `$b = `$a where `$a` and `$b` would point\nto distinct VStores pointing to the same HStore.\n\nLet's modify the value of the `Point` aliased by `$a` using `$a->move(4,\n6)`:\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *] VSlot $y *]]\n                 ^                                      |           |\n                 |                                      V           V\n[VSlot $b *]-----+                           [VStore Int 4] [VStore Int 6]\n                                        (1 was overwritten) (3 was overwritten)\n</pre>\n\nNow, let's change `$a` itself using the value assignment `$a = new\nPoint(2, 1)`:\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Point [VSlot $x *][VSlot $y *]]\n                 ^                                      |           |\n                 |                                      V           V\n[VSlot $b *]-----+                             [VStore Int 2] [VStore Int 1]\n\n                               [HStore Point [VSlot $x *]   [VSlot $y *] (dead)]\n                                                       |              |\n                                                       V              V\n                                     [VStore Int 4 (dead)] [VStore Int 6 (dead)]\n</pre>\n\nAs we can see, `$b` continues to have an alias relationship with `$a`.\nHere's what's involved in that assignment: `$a` and `$b`'s VStore’s handle\npointing to `Point(4,6)` is removed, `Point(2,1)` is created, and `$a` and\n`$b`’s VStore is overwritten to contain a handle pointing to that new\n`Point`. As there are now no VStores pointing to `Point(4,6)`, its\ndestructor ([§§](#destructors)) can run.\n\nWe can remove these aliases using `unset($a, $b)`:\n<pre>\n[VSlot $a (dead)]       [HStore Point [VSlot $x *] [VSlot $y *] (dead)]\n                                                |            |\n                                                V            V\n[VSlot $b (dead)]             [VStore Int 2 (dead)]  [VStore Int 1 (dead)]\n</pre>\n\nOnce all the aliases to the VStores are gone, the VStores can be\ndestroyed, in which case, there are no more pointers to the HStore, and\nits destructor ([§§]estructors](#Destructors)) can be run.\n\n### # Value Assignment of Array Types to Local Variables\nThe semantics of value assignment of array types is different from value\nassignment of other types. Recall the `Point` class from the examples in [§§](#value-assignment-of-object-and-resource-types-to-a-local-variable), and consider the following value assignments ([§§](#simple-assignment)) and their abstract implementation:\n\n`$a = array(10, 'B' => new Point(1, 3));`\n<pre>\n[VSlot $a *]-->[VStore Arr *]-->[HStore Array [VSlot 0 *] [VSlot 'B' *]]\n                                                       |             |\n                                                       V             V\n                                             [VStore Int 10]   [VStore Obj *]\n                                                                           |\n                                [HStore Point [VSlot $x *] [VSlot $y *]]&lt;--+\n                                                        |            |\n                                                        V            V\n                                            [VStore Int 1]  [VStore Int 3]\n</pre>\n\nIn the example above, `$a`‘s VStore is initialized to contain a handle to\nan HStore for an array containing two elements, where one element is an\ninteger and the other is a handle to an HStore for an object.\n\nNow consider the following value assignment `$b = $a`. A conforming\nimplementation must implement value assignment of arrays in one of the\nfollowing ways: (1) eager copying, where the implementation makes a copy\nof `$a`’s array during value assignment and changes `$b`’s VSlot to point\nto the copy; or (2) deferred copying, where the implementation uses a\ndeferred copy mechanism that meets certain requirements. This subclause\ndescribes eager copying, and the subclause that immediately follows ([§§](#deferred-array-copying))\ndescribes deferred copying.\n\nTo describe the semantics of eager copying, let’s begin by considering\nthe value assignment `$b = $a`:\n<pre>\n[VSlot $a *]-->[VStore Arr *]-->[HStore Array [VSlot 0 *] [VSlot 'B' *]]\n                                                       |             |\n[VSlot $b *]-->[VStore Arr *]                          V             V\n                           |                    [VStore Int 10]  [VStore Obj *]\n                           V                                                 |\n[HStore Array [VSlot 0 *] [VSlot 'B' *]]                                     |\n                       |             |                                       |\n             +---------+   +---------+                                       |\n             V             V                                                 |\n[VStore Int 10] [VStore Obj *]-->[HStore Point [VSlot $x *] [VSlot $y *]]&lt;---+\n                                                         |            |\n                                                         V            V\n                                                 [VStore Int 1]  [VStore Int 3]\n</pre>\n\nThe value assignment `$b = $a` made a copy of `$a`’s array. Note how\n`$b`’s VSlot points to a different VStore than `$a`’s VSlot, and `$b`’s\nVStore points to a different HStore than `$b`’s VStore. Each source array\nelement is copied using *member-copy assignment* `=*`, which is defined\nas follows:\n\n```\n   $destination =* $source\n```\n-   If `$source`’s VStore has a refcount equal to 1, the Engine copies the\n    array element using  value assignment (`destination = $source`).\n-   If `$source`’s VStore has a refcount that is greater than 1, the Engine\n    uses an implementation-defined algorithm to decide whether to copy the element\n    using value assignment (`$destination = $source`) or byRef\n    assignment (`$destination = &$source`).\n\nNote the member-copy assignment `=*` is **not** an operator or language\nconstruct in the PHP language, but instead it is used internally to\ndescribe behavior for the engine for array copying and other operations\n\nFor the particular example above, member-copy assignment exhibits the\nsame semantics as value assignment for all conforming implementations\nbecause all of the array elements’ VStores have a refcount equal to 1.\nThe first element VSlots in `$a`’s array and `$b`’s array point\nto distinct VStores, each of which contain a distinct copy of the\ninteger value 10. The second element VSlots in `$a`’s array and `$b`’s\narray point to distinct VStores, each of which contain a handle to the\nsame object HStore.\n\nLet’s consider another example:\n```\n$x = 123;\n$a = array(array(&$x, 'hi'));\n$b = $a;\n```\n\nEager copying can produce two possible outcomes depending on the\nimplementation. Here is the first possible outcome:\n<pre>\n[VSlot $a *]---->[VStore Arr *]---->[HStore Array [VSlot 0 *]]\n                                                           |\n[VSlot $x *]-------------------------+   [VStore Arr *]&lt;---+\n                                     |               |\n[VSlot $b *]-->[VStore Arr *]        |               V\n                           |         |  [HStore Array [VSlot 0 *][VSlot 1 *]]\n                           V         |                          |          |\n         [HStore Array [VSlot 0 *]]  |                          V          |\n                                |    +---------------->[VStore Int 123]    |\n                                V                          ^               V\n                     [VStore Arr *]                        |   [VStore Str 'hi']\n                                 |          +--------------+\n                                 V          |\n                     [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                                                        |\n                                                        V\n                                                     [VStore Str 'hi']\n</pre>\n\nHere is the second possible outcome:\n<pre>\n[VSlot $a *]---->[VStore Arr *]---->[HStore Array [VSlot 0 *]]\n                                                           |\n[VSlot $x *]-------------------------+  [VStore Arr *]&lt;----+\n                                     |               |\n[VSlot $b *]-->[VStore Arr *]        |               V\n                           |         |  [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                           V         |                         |           |\n         [HStore Array [VSlot 0 *]]  |                         V           |\n                                |    +---------------->[VStore Int 123]    |\n                                V                                          V\n                     [VStore Arr *]                            [VStore Str 'hi']\n                                 |\n                                 V\n                    [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                                           |           |\n                                           V           V \n                                  [VStore Int 123]  [VStore Str 'hi']\n</pre>\n\nIn both possible outcomes, value assignment with eager copying makes a\ncopy of `$a`’s array, copying the array’s single element using\nmember-copy assignment (which in this case will exhibit the same\nsemantics of value assignment for all implementations), which in turn\nmakes a copy of the inner array inside `$a`’s array, copying the inner\narray’s elements using member-copy assignment. The inner array’s first\nelement VSlot points to a VStore that has a refcount that is greater than 1,\nso an implementation-defined algorithm is used to decide whether to use value\nassignment or byRef assignment. The first possible outcome shown above\ndemonstrates what happens if the implementation chooses to do byRef\nassignment, and the second possible outcome shown above demonstrates\nwhat happens if the implementation chooses to do value assignment. The\ninner array’s second element VSlot points to a VStore that has a refcount\nequal to 1, so value assignment is used to copy the inner array’s second\nelement for all conforming implementations that use eager copying.\n\nAlthough the examples in this subclause only use arrays with one\nelement or two elements, the model works equally well for all\narrays even though they can have an arbitrarily large number\nof elements. As to how an HStore accommodates all of them, is\nunspecified and unimportant to the abstract model.\n\n### # Deferred Array Copying\nAs mentioned in the previous subclause ([§§](#value-assignment-of-array-types-to-local-variables)), an implementation may\nchoose to use a deferred copy mechanism instead of eagerly making a copy\nfor value assignment of arrays. An implementation may use any deferred\ncopy mechanism desired so long as it conforms to the abstract model’s\ndescription of deferred array copy mechanisms presented in this\nsubclause.\n\nBecause an array’s contents can be arbitrarily large, eagerly copying an\narray’s entire contents for value assignment can be expensive. In\npractice an application written in PHP may rely on value assignment of\narrays being relatively inexpensive for the common case (in order to deliver\nacceptable performance), and as such it is common for an implementation\nto use a deferred array copy mechanism in order to reduce the cost of\nvalue assignment for arrays.\n\nUnlike conforming deferred string copy mechanisms discussed in [§§](#value-assignment-of-scalar-types-to-a-local-variable)\nthat must produce the same observable behavior as eager string copying,\ndeferred array copy mechanisms are allowed in some cases to exhibit\nobservably different behavior than eager array copying. Thus, for\ncompleteness this subclause describes how deferred array copies can be\nmodeled in the abstract memory model and how conforming deferred array\ncopy mechanisms must behave.\n\nConforming deferred array copy mechanisms work by not making an array\ncopy during value assignment, by allowing the destination VStore to\nshare an array HStore with the source VStore, and by making a copy of\nthe array HStore at a later time if or when it is necessary. The\nabstract model represents a deferred array copy relationship by marking\nthe destination VStore with a special “Arr-D” type tag and by sharing\nthe same array HStore between the source and destination VStores. Note\nthat the source VStore’s type tag remains unchanged. For the purposes of\nthis abstract model, the “Arr-D” type tag is considered identical to the\n“Arr” type in all respects except when specified otherwise.\n\nTo illustrate this, let’s see how the previous example would be\nrepresented under the abstract model assuming the implementation defers\nthe copying the array:\n\n```\n$x = 123;\n$a = array(array(&$x, ‘hi’));\n$b = $a;\n```\n<pre>\n[VSlot $a *]--->[VStore Arr *]--->[HStore Array [VSlot 0 *]]\n                                    ^                    |\n                                    |   [VStore Arr *]&lt;--+\n[VSlot $b *]--->[VStore Arr-D *]----+               |\n                                                    V\n                                        [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                                                               |           |\n                                                               V           |\n[VSlot $x *]------------------------------------------>[VStore Int 123]    |\n                                                                           V\n                                                               [VStore Str 'hi']\n</pre>\n\nAs we can see, both `$a`’s VStore (the source VStore) and `$b`’s VStore\n(the destination VStore) point to the same array HStore. Note the\nasymmetric nature of how deferred array copies are represented in the\nabstract model. In the above example the source VStore’s type tag\nremains unchanged after value assignment, whereas the destination\nVStore’s type tag was changed to “Arr-D”.\n\nWhen the engine is about to perform an array-mutating operation on a\nVStore tagged “Arr” that participates in a deferred array copy\nrelationship or on a VStore tagged “Arr-D”, the engine must first take\ncertain actions that involve making a copy of the array (described in\nthe next paragraph) before performing the array-mutating operation. An\narray-mutating operation is any operation can add or remove array\nelements, overwrite existing array elements, change the state of the\narray’s internal cursor, or cause the refcount of one or more of the\narray’s element VStores or subelement VStores to increase from 1 to\na value greater than 1. This requirement to take certain actions before\nperforming an array-mutation operation on a VStore participating in a\ndeferred array copy relationship is commonly referred to as the\ncopy-on-write requirement.\n\nWhen an array-mutating operation is about to be performed on a given\nVStore X with an “Arr” type tag that participates in a deferred array\ncopy relationship, the engine must find all of the VStores tagged\n“Arr-D” that point to the same array HStore that VStore X points to,\nmake a copy of the array (using member-copy assignment to copy the\narray’s elements as described in [§§](#value-assignment-of-array-types-to-local-variables)), and update all of these\nVStores tagged “Arr-D” to point to the newly created copy (note that\nVStore X remains unchanged). When an array-mutation operation is about\nto be performed on a given VStore X with an “Arr-D” type tag, the engine\nmust make a copy of the array (as described in [§§](#value-assignment-of-array-types-to-local-variables)), update VStore\nX to point to the newly created copy, and change VStore X’s type tag to\n“Arr”. These specific actions that the engine must perform on VStore at\ncertain times to satisfy the copy-on-write requirement are collectively\nreferred to as “array-separation” or “array-separating the VStore”. An\narray-mutation operation is said to “trigger” an array-separation.\n\nNote that for any VStore with an “Arr” type tag that participates in a\ndeferred array copy relationship, or for any VStore with an “Arr-D” type\ntag, a conforming implementation may choose to array-separate the VStore\nat any time for any reason as long as the copy-on-write requirement is\nupheld.\n\nContinuing with the previous example, consider the array-mutating\noperation `$b[1]++`. Depending on the implementation, this can produce\none of three possible outcomes. Here is the one of the possible\noutcomes:\n<pre>\n[VSlot $a *]---->[VStore Arr *]---->[HStore Array [VSlot 0 *]]\n                                                           |\n[VSlot $b *]-->[VStore Arr *]            [VStore Arr *]&lt;---+\n                             |                       |\n      +----------------------+              +--------+\n      V                                     V\n  [HStore Array [VSlot 0 *] [VSlot 1 *]]  [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                         |           |       ^                  |          |\n                         |           V       |                  V          |\n                         |   [VStore Int 1]  |            [VStore Int 123] |\n                         V                   |             ^               V\n                       [VStore Arr-D *]-----+              |   [VStore Str 'hi']\n                                                           |\n [VSlot $x *]----------------------------------------------+\n</pre>\n\nAs we can see in the outcome shown above, `$b`’s VStore was\narray-separated and now `$a`’s VStore and `$b`’s VStore point to distinct\narray HStores. Performing array-separation on `$b`’s VStore was necessary\nto satisfy the copy-on-write requirement. `$a`’s array remains unchanged\nand that `$x` and `$a[0][0]` still have an alias relationship with each\nother. For this particular example, conforming implementations are\nrequired to preserve `$a`’s array’s contents and to preserve the alias\nrelationship between `$x` and `$a[0][0]`. Finally, note that `$a[0]` and\n`$b[0]` have a deferred copy relationship with each other in the outcome\nshown above. For this particular example, a conforming implementation is\nnot required to array-separate `$b[0]`’s VStore, and the outcome shown\nabove demonstrates what happens when `$b[0]`’s VStore is not\narray-separated. However, an implementation can choose to array-separate\n`$b[0]`’s VStore at any time if desired. The other two possible outcomes\nshown below demonstrate what can possibly happen if the implementation\nchoose to array-separate `$b[0]`’s VStore as well. Here is the second\npossible outcome:\n<pre>\n[VSlot $a *]---->[VStore Arr *]---->[HStore Array [VSlot 0 *]]\n                                                           |\n[VSlot $b *]-->[VStore Arr *]            [VStore Arr *]&lt;---+\n                          |                          |\n                          V                          V\n  [HStore Array [VSlot 0 *] [VSlot 1 *]]  [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                         |           |                           |           |\n       +-----------------+           V                           |           |\n       |                     [VStore Int 1]                  +---+           |\n       V                                                     |               V\n  [VStore Arr-D *]-->[HStore Array [VSlot 0 *] [VSlot 1 *]] | [VStore Str 'hi']\n                                            |           |   |\n                                    +-------+           |   |\n                                    |                   V   |\n                                    |    [VStore Str ‘hi’]  |\n                                    V                       |\n [VSlot $x *]--------------------->[VStore Int 123]&lt;--------+\n</pre>\n\nHere is the third possible outcome:\n<pre>\n[VSlot $a *]---->[VStore Arr *-]---->[HStore Array [VSlot 0 *]]\n                                                            |\n[VSlot $b *]-->[VStore Arr *]             [VStore Arr *]&lt;---+\n                            |                          |\n                            V                          V\n [HStore Array [VSlot 0 *] [VSlot 1 *]]  [HStore Array [VSlot 0 *] [VSlot 1 *]]\n                         |           |                           |           |\n       +-----------------+           V                           |           |\n       |                     [VStore Int 1]                  +---+           |\n       V                                                     |               V\n   [VStore Arr-D *]-->[HStore Array [VSlot 0 *] [VSlot 1 *]] | [VStore Str 'hi']\n                                             |           |   |\n                     [VStore Int 123]&lt;-------+           |   |\n                                                         V   |\n                                          [VStore Str 'hi']  |\n                                                             |\n [VSlot $x *]--------------------->[VStore Int 123]&lt;--------+\n</pre>\n\nThe second and third possible outcomes show what can possibly happen if\nthe implementation chooses to array-separate `$b[0]`’s VStore. In the\nsecond outcome, `$b[0][0]` has an alias relationship with `$x` and\n`$a[0][0]`. In the third outcome, `$b[0][0]` does not have an alias\nrelationship, though `$x` and `$a[0][0]` still have an alias relationship\nwith each other. The differences between the second and third outcome\nare reflect that different possibilities when the engine uses\nmember-copy assignment to copy `$a[0]`’s arrays’s elements into `$b[0]`’s\narray.\n\nFinally, let’s briefly consider one more example:\n```\n$x = 0;\n$a = array(&$x);\n$b = $a;\n$x = 2;\nunset($x);\n$b[1]++;\n$b[0]++;\necho $a[0], ' ', $b[0];\n```\n\nFor the example above, a conforming implementation could output “2 1”,\n“2 3”, or “3 3” depending on how it implements value assignment for\narrays.\n\nFor portability, it is generally recommended that programs written in\nPHP should avoid performing value assignment with a right-hand side that\nis an array with one or more elements or sub-elements that have an alias\nrelationship.\n\n***Implementation Notes:*** For generality and for simplicity, the\nabstract model represents deferred array copy mechanisms in a manner\nthat is more open-ended and superficially different than the php.net\nimplementation’s model, which uses a symmetric deferred copy mechanism\nwhere a single zval contains the sole pointer to a given Hashtable and\ndeferred array copies are represented as multiple slots pointing to the\nsame single zval that holds the array. Despite this superficial\ndifference, php.net’s implementation produces behavior that is\ncompatible with the abstract model’s definition of deferred array copy\nmechanisms.\n\n### # General Value Assignment\nThe subclauses above thus far have described the mechanics of value assignment\nto a local variable. This subclause describes how value assignment works\nwhen general modifiable lvalue expressions are used on the left hand side.\n\n**[TODO: Add description and examples here involving array elements and object\ninstance properties. Describe how new array elements and object instance\nproperties can be created via value assignment.]**\n\n### # General ByRef Assignment\nThe subclauses above thus far have described the mechanics of byref assignment\nwith local variables. This subclause describes how byref assignment works when\ngeneral modifiable lvalue expressions are used on the left hand side and/or\nthe right hand side.\n\n**[TODO: Add description and examples here involving array elements and\nobject instance properties. Describe how new array elements and object\ninstance properties can be created via byref assignment.]**\n\n## # Argument Passing\nArgument passing is defined in terms of simple assignment ([§§](#value-assignment-of-scalar-types-to-a-local-variable), [§§](#value-assignment-of-object-and-resource-types-to-a-local-variable), [§§](#value-assignment-of-array-types-to-local-variables), and [§§](#simple-assignment)) or byRef assignment ([§§]), [§§](#byref-assignment-of-non-scalar-types-with-local-variables), and [§§](#byref-assignment)), depending on how the parameter is declared. \nThat is, passing an argument to a function having a corresponding\nparameter is like assigning that argument to that parameter. The\nfunction-call situations involving missing arguments or\nundefined-variable arguments are discussed in ([§§](#function-call-operator)).\n\n## # Value Returning\nReturning a value from a function is defined in terms of simple\nassignment ([§§](#value-assignment-of-scalar-types-to-a-local-variable), [§§](#value-assignment-of-object-and-resource-types-to-a-local-variable), [§§](#value-assignment-of-array-types-to-local-variables), and [§§](#simple-assignment)) or byRef assignment ([§§](#byref-assignment-for-scalar-types-with-local-variables), [§§](#byref-assignment-of-non-scalar-types-with-local-variables), and [§§](#byref-assignment)) depending on how the\nfunction is declared.  That is, returning a value from a function to its\ncaller is like assigning that value to the user of the caller's return\nvalue. The function-return situations involving a missing return value\nare discussed in ([§§](#function-call-operator)).\n\n\n## # Cloning objects\nWhen an instance is allocated, operator `new` ([§§](#the-new-operator)) returns a handle\nthat points to that object. As described in [§§](#value-assignment-of-object-and-resource-types-to-a-local-variable)), value assignment of a handle to an object does not copy the object HStore itself. Instead, it creates a copy of the handle. How then to make a copy of the object itself? Our only access to it is\nvia the handle. The PHP language allows us to do this via operator `clone` ([§§](#the-clone-operator)).\n\nTo demonstrate how the `clone` operator works, consider the case in which\nan instance of class `Widget` contains two instance properties: `$p1` has\nthe integer value 10, and `$p2` is a handle to an array of elements of\nsome type(s) or to an instance of some other type.\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Widget [VSlot $p1 *][VSlot $p2 *]]\n                                                          |          |\n                                                          V          V\n                                               [VStore Int 10] [VStore Obj *]\n                                                                         |\n                                                                         V\n                                                                 [HStore ...]\n</pre>\n\nLet us consider the result of `$b = clone $a`:\n<pre>\n[VSlot $a *]-->[VStore Obj *]-->[HStore Widget [VSlot $p1 *][VSlot $p2 *]]\n                                                          |            |\n[VSlot $b *]-->[VStore Obj *]                             V            V\n                             |                  [VStore Int 10] [VStore Obj *]\n     +-----------------------+                                              |\n     V                                                                      V\n   [HStore Widget [VSlot $p1 *] [VSlot $p2 *]]              +--->[HStore ...]\n                             |             |                |\n                             V             V                |\n                 [VStore Int 10] [VStore Obj *]-------------+\n</pre>\n\nThe clone operator will create another object HStore of the same class\nas the original, copy `$a`’s object’s instance properties using\nmember-copy assignment `=*` ([§§](#value-assignment-of-array-types-to-local-variables)). For the example shown above, the\nhandle to the newly created HStore stored into `$b` using value\nassignment. Note that the clone operator will not recursively clone\nobjects held in `$a`’s instance properties; hence the object copying\nperformed by the clone operator is often referred to as a *shallow\ncopy*. If a *deep copy* of an object is desired, the programmer must\nachieve this manually by using the method `__clone` ([§§](#method-__clone)) or by\nother means.\n\n# # Scope\n\nThe same name can designate different things at different places in a\nprogram. For each different thing that a name designates, that name is\nvisible only within a part of the program called that name's *scope*.\nThe following distinct scopes exist:\n\n-   Script, which means from the point of declaration/first\n    initialization through to the end of that script, including any\n    included and required files ([§§](#general-16)).\n-   Function, which means from the point of declaration/first\n    initialization through to the end of that function ([§§](#function-definitions)).\n-   Class, which means the body of that class and any classes derived\n    from it ([§§](#class-declarations)).\n-   Interface, which means the body of that interface, any interfaces\n    derived from it, and any classes that implement it ([§§](#interface-declarations)).\n-   Namespace, which means from the point of declaration/first\n    initialization through to the end of that namespace ([§§](#general-28)).\n\nA variable declared or first initialized inside a function, has function\nscope; otherwise, the variable has script scope. \n\nSuperglobals ([§§](#general-5)) are always in scope; they never need explicit\ndeclaration.\n\nEach function has its own function scope. An anonymous function ([§§](#anonymous-functions))\nhas its own scope separate from that of any function inside which that\nanonymous function is defined.\n\nThe scope of a parameter is the body of the function in which the\nparameter is declared. For the purposes of scope, a catch-block ([§§](#the-try-statement))\nis treated like a function body, in which case, the *variable-name* in\n*parameter-declaration-list* is treated like a parameter.\n\nThe scope of a *named-label* ([§§](#labeled-statements)) is the body of the function in\nwhich the label is defined. \n\nThe scope of a class member m ([§§](#class-members)) declared in, or inherited by, a\nclass type C is the body of C.\n\nThe scope of an interface member m ([§§](#class-members)) declared in, or inherited by,\nan interface type I is the body of I.\n\nWhen a trait ([§§](#general-26)) is used by a class or an interface, the trait's\nmembers ([§§](#trait-members)) take on the scope of a member of that class or\ninterface.\n\n# # Storage Duration\n\nThe lifetime of a variable is the time during program execution that\nstorage for that variable is guaranteed to exist. This lifetime is\nreferred to as the variable's *storage duration*, of which there are\nthree kinds: automatic, static, and allocated.\n\nA variable having *automatic storage duration* comes into being and is\ninitialized at its declaration or on its first use, if it has no\ndeclaration. Its lifetime is delimited by an enclosing scope ([§§](#scope)). The\nautomatic variable's lifetime ends at the end of that scope. Automatic\nvariables lend themselves to being stored on a stack where they can help\nsupport argument passing and recursion. Local variables ([§§](#local-variables)), which\ninclude function parameters ([§§](#function-definitions)), have automatic storage duration.\n\nA variable having *static storage duration* comes into being and is\ninitialized before its first use, and lives until program shutdown. The\nfollowing kinds of variables have static storage duration: constants\n([§§](#constants-1)), function statics ([§§](#function-statics)), global variables ([§§](#global-variables)), static\nproperties ([§§](#static-properties)), and class and interface constants ([§§](#class-and-interface-constants)).\n\nA variable having *allocated storage duration* comes into being based on\nprogram logic by use of the new operator ([§§](#the-new-operator)). Ordinarily, once\nsuch storage is no longer needed, it is reclaimed automatically by the\nEngine via its garbage-collection process ([§§](#)) and the use of\ndestructors ([§§](#destructors)). The following kinds of variables have allocated\nstorage duration: array elements ([§§](#array-elements)) and instance properties\n([§§](#instance-properties)).\n\nAlthough all three storage durations have default ends-of-life, their\nlives can be shortened by calling the intrinsic unset ([§§](#unset)),\nwhich destroys any given set of variables.\n\nThe following example demonstrates the three storage durations:\n\n```\nclass Point { ... }\n\n$av1 = new Point(0, 1);       // auto variable $av1 created and initialized\nstatic $sv1 = ...;          // static variable $sv1 created and initialized\n\nfunction doit($p1)\n{\n  $av2 = ...;           // auto variable $av2 created and initialized\n  static $sv2 = ...;        // static variable $sv2 created and initialized\n  if ($p1)\n  {\n    $av3 = ...;         // auto variable $av3 created and initialized\n    static $sv3 = ...;    // static variable $sv3 created and initialized\n    ...\n  }\n  global $av1;\n  $av1 = new Point(2, 3);   // Point(0,1) is eligible for destruction\n  ...\n}                   // $av2 and $av3 are eligible for destruction\n\ndoit(TRUE);\n\n// At end of script, $av1, $sv1, $sv2, and $sv3 are eligible for destruction\n```\n\nThe comments indicate the beginning and end of lifetimes for each\nvariable. In the case of the initial allocated Point variable whose\nhandle is stored in `$av1`, its life ends when `$av1` is made to point to\na different Point.\n\nIf function `doit` is called multiple times, each time it is called, its\nautomatic variables are created and initialized, whereas its static\nvariables retain their values from previous calls.\n\nConsider the following recursive function: \n\n```\nfunction factorial($i)\n{\n  if ($i > 1) return $i * factorial($i - 1);\n  else if ($i == 1) return $i;\n  else return 0;\n}\n```\n\nWhen `factorial` is first called, the local variable parameter `$i` is\ncreated and initialized with the value of the argument in the call.\nThen, if this function calls itself, the same process is repeated each\ncall. Specifically, each time `factorial` calls itself, a new local\nvariable parameter `$i` is created and initialized with the value of the\nargument in the call.\n\nThe lifetime of any VStore (§[[4.4.1](#general)](#general)) or HStore (§[[4.4.1](#general)](#general)) can be extended by\nthe Engine as long as needed. Conceptually, the lifetime of a VStore ends\nwhen it is no longer pointed to by any VSlots ([§§](#general)). Conceptually, the\nlifetime of an HStore ends when no VStores have a handle to it.\n\n\n\n# Types\n\n# # General\n\nThe meaning of a value is determined by its *type*. PHP's types are\ncategorized as *scalar types* and *composite types*. The scalar types\nare Boolean ([§§](#the-boolean-type)), integer ([§§](#the-integer-type)), floating-point ([§§](#the-floating-point-type)), string\n([§§](#the-string-type)), and null ([§§](#the-null-type)). The composite types are array ([§§](#array-types)),\nobject ([§§](#object-types)), and resource ([§§](#resource-types)).\n\nThe scalar types are *value types*. That is, a variable of scalar type\nbehaves as though it contains its own value. On the\nother hand, the composite types are *handle types*. A variable of\ncomposite type contains information—in a *handle*—that leads to the\nvalue. The differences between value and handle types become apparent\nwhen it comes to understanding the semantics of assignment, and passing\narguments to, and returning values from, functions ([§§](#the-memory-model)). That said,\narray types really are a hybrid; on the one hand, an array may contain\nan arbitrary number of elements separate from the array variable itself,\nyet on the other hand, certain array operations do have value semantics.\n\nVariables are not declared to have a particular type. Instead, a\nvariable's type is determined at runtime by the context in which it is\nused.\n\nUseful library functions for interrogating and using type information\ninclude `gettype` (§xx), `is_type` (§xx), `settype` (§xx), and `var_dump`\n(§xx).\n\n# # Scalar Types\n\n## # General\n\nThe integer and floating-point types are collectively known as\n*arithmetic types*. The library function `is_numeric` (§xx) indicates if\na given value is a number or a numeric string ([§§](#the-string-type)).\n\nThe library function `is_scalar` (§xx) indicates if a given value has a\nscalar type. However, that function does not consider `NULL` to be scalar.\nTo test for `NULL`, use `is_null` (§xx).\n\n## # The Boolean Type\n\nThe Boolean type is `bool`, for which the name boolean is a synonym. This\ntype is capable of storing two distinct values, which correspond to the\nBoolean values `TRUE` and `FALSE` ([§§](#core-predefined-constants)), respectively. The representation of\nthis type and its values is unspecified.\n\nThe library function `is_bool` (§xx) indicates if a given value has type\nbool.\n\n## # The Integer Type\n\nThere is one integer type, `int`, for which the name integer is a synonym.\nThis type is binary, signed, and uses twos-complement representation for\nnegative values. The range of values that can be stored is\nimplementation-defined; however, the range [-2147483648, 2147483647],\nmust be supported.\n\nCertain operations on integer values produce a mathematical result that\ncannot be represented as an integer. Examples include the following:\n\n-   Incrementing the largest value or decrementing the smallest value\n-   Applying the unary minus to the smallest value\n-   Multiplying, adding, or subtracting two values\n\nIn such cases, the resulting type and value is implementation-defined,\nbut must be one of the following:\n\n-   The computation is done as though the types of the values were `float`\n    with the result having that type\n-   The result type is int and the value reflects wrap-around (for\n    example adding 1 to the largest value results in the smallest value)\n-   The computation is done as though the type had some unspecified,\n    arithmetic-like object type with the result being mathematically\n    correct\n\nThe constants `PHP_INT_SIZE` (§[[6.3](#core-predefined-constants)](#core-predefined-constants)) and `PHP_INT_MAX` (§[[6.3](#core-predefined-constants)](#core-predefined-constants)) define certain\ncharacteristics about type `int`.\n\nThe library function `is_int` (§xx) indicates if a given value has type\nint.\n\n## # The Floating-Point Type\n\nThere is one floating-point type, `float`, for which the names `double` and\n`real` are synonyms. The `float` type must support at least the range and\nprecision of IEEE 754 64-bit double-precision representation.\n\nThe library function `is_float` (§xx) indicates if a given value has type\n`float`. The library function `is_finite` (§xx) indicates if a given\nfloating-point value is finite. The library function `is_infinite` (§xx)\nindicates if a given floating-point value is infinite. The library\nfunction `is_nan` (§xx) indicates if a given floating-point value is a\n`NaN`.\n\n## # The String Type\n\nA string is a set of contiguous bytes that represents a sequence of zero\nor more characters.\n\nConceptually, a string can be considered as an array ([§§](#array-types)) of\nbytes—the *elements*—whose keys are the `int` values starting at zero. The\ntype of each element is `string`. However, a string is *not* considered a\ncollection, so it cannot be iterated over.\n\nA string whose length is zero is an *empty string*.\n\nAs to how the bytes in a string translate into characters is\nunspecified.\n\nAlthough a user of a string might choose to ascribe special semantics to\nbytes having the value `U+0000`, from PHP's perspective, such *null bytes*\nare simply just bytes! PHP does not assume strings contain any specific\ndata or assign special values to any bytes or sequences. However, many\nlibrary functions assume the strings they receive as arguments are UTF-8\nencoded, often without explicitly mentioning that fact.\n\nA *numeric string* is a string whose content exactly matches the pattern\ndefined using integer format by the production *integer-literal*\n([§§](#integer-literals)) or using floating-point format by the production\n*floating-literal* ([§§](#floating-point-literals)), where leading whitespace is permitted.\nA *leading-numeric string* is a string whose initial characters follow\nthe requirements of a numeric string, and whose trailing characters are\nnon-numeric. A *non-numeric string* is a string that is not a numeric\nstring.\n\nOnly one mutation operation may be performed on a string, offset\nassignment, which involves the simple assignment operator = ([§§](#simple-assignment)).\n\nThe library function `is_string` (§xx) indicates if a given value has\ntype string.\n\n## # The Null Type\n\nThe null type has only one possible value, `NULL` ([§§](#core-predefined-constants)). The representation\nof this type and its value is unspecified.\n\nThe library function `is_null` (§xx) indicates if a given value is `NULL`.\n\n# # Composite Types\n\n## # Array Types\n\nAn array is a data structure that contains a collection of zero or more\nelements whose values are accessed through keys that are of type `int` or\n`string`. Arrays are described in [§§](#arrays).\n\nThe library function `is_array` (§xx) indicates if a given value is an\narray.\n\n## # Object Types\n\nAn *object* is an instance of a class ([§§](#classes)). Each distinct\n*class-declaration* ([§§](#class-declarations)) defines a new class type, and each class\ntype is an object type. The representation of object types is\nunspecified.\n\nThe library function `is_object` (§xx) indicates if a given value is an\nobject, and the library function\n[`get_class`](http://us2.php.net/manual/en/function.get-class.php)\n(§xx) indicates the name of an object's class.\n\n## # Resource Types\n\nA [*resource*](http://www.php.net/manual/en/language.types.resource.php)\nis a descriptor to some sort of external entity. (Examples include\nfiles, databases, and sockets.)\n\nA resource is an abstract entity whose representation is unspecified.\nResources are only created or consumed by the implementation; they are\nnever created or consumed by PHP code.\n\nEach distinct resource has a unique ID of some unspecified form.\n\nWhen scripts execute in a mode having a command-line interface, the\nfollowing predefined resource constants that correspond to file streams\nare automatically opened at program start-up:\n\n-   STDIN, which maps to standard input (php://stdin)\n-   STDOUT, which maps to standard output (php://stdout)\n-   STDERR, which maps to standard error (php://stderr)\n\nThe library function `is_resource` (§xx) indicates if a given value is a\nresource, and the library function\n[`get_resource_type`](http://us2.php.net/manual/en/function.get-resource-type.php)\n(§xx) indicates the type of a resource.\n\n\n\n# Constants\n\n# # General\n\nA *constant* is a name ([§§](#names)) for a value that once given its\ninitial value, cannot be changed.\n\nA constant can be defined in one of two ways: as a *c-constant* using a\n*const-declaration* ([§§](#constants-2)), or as a *d-constant* by calling the library\nfunction `define` (§xx). However, the two approaches differ slightly.\nSpecifically:\n\n-   The name of a c-constant must comply with the lexical grammar for a\n    name while that for a d-constant can contain any source character.\n-   The name of a c-constant is case-insensitive while that for a\n    d-constant can be case-sensitive or case-insensitive based on the\n    value of the third argument passed to `define`.\n-   If `define` is able to define the given name, it returns `TRUE`;\n    otherwise, it returns `FALSE`.\n\nThe library function `defined` (§xx) reports if a given name (specified as\na string) is defined as a constant. The library function `constant` (§xx)\nreturns the value of a given constant whose name is specified as a\nstring.\n\n**Examples**\n\n```\nconst MAX_HEIGHT = 10.5;              // define two (case-insensitive) c-constants\nconst UPPER_LIMIT = MAX_HEIGHT;\ndefine('COEFFICIENT_1', 2.345, TRUE); // define a case-insensitive d-constant\ndefine('FAILURE', TRUE, FALSE);       // define a case-sensitive d-constant\n```\n\n# # Context-Dependent Constants\n\nThe following constants—sometimes referred to as *magic constants*—are\nautomatically available to all scripts; their values are not fixed:\n\n Constant Name                    | Description                     \n -----------------                | ---------                            \n `__CLASS__`                        | `string`; The name of the current class. From within a trait method, the name of the class in which that trait is used. If the current namespace is other than the default, the namespace name and \"\\\\\" are prepended, in that order. If used outside all classes, the result is the empty string. \n`__DIR__`                            |  `string`; The directory name of the script. A directory separator is only appended for the root directory.\n`__FILE__`                           | `string`; The full name of the script.\n`__FUNCTION__`                       | `string`; Inside a function, the name of the current function exactly as it was declared, with the following prepended: If a named namespace exists, that namespace name followed by \"\\\". If used outside all functions, the result is the empty string. For a method, no parent-class prefix is present. (See `__METHOD__` and [§§](#anonymous-functions).)\n`__LINE__`                           | `int`; the number of the current source line\n`__METHOD__`                         | `string`; Inside a method, the name of the current method exactly as it was declared, with the following prepended, in order: If a named namespace exists, that namespace name followed by \"\\\"; the parent class name or trait name followed by `::`. If used outside all methods, the result is the same as for `__FUNCTION__`.\n`__NAMESPACE__`                      | `string`; The name of the current namespace exactly as it was declared. For the default namespace, the result is the empty string.\n`__TRAIT__`                          | `string`; The name of the current trait. From within a trait method, the name of the current trait. If used outside all traits, the result is the empty string.\n\nConstants beginning with __ are reserved for future use by the Engine.\n\n# # Core Predefined Constants\n\nThe following constants are automatically available to all scripts:\n\nConstant Name | Description\n-------------   | -----------  \n`__COMPILER_HALT_OFFSET__` |  `int`; When the library function `__HALT_COMPILER__` (§xx) is called, this constant contains the location in the source file immediately following the `__HALT_COMPILER__()`; token.\n`DEFAULT_INCLUDE_PATH` |  `string`; the `fopen` library function (§xx) include path is used if it is not overridden by the `php.ini` setting `include_path`.\n`E_ALL` | `int`; All errors and warnings, as supported.\n`E_COMPILE_ERROR` | `int`; Fatal compile-time errors. This is like an `E_ERROR`, except that `E_COMPILE_ERROR` is generated by the scripting engine.\n`E_COMPILE_WARNING` | `int`; Compile-time warnings (non-fatal errors). This is like an `E_WARNING`, except that `E_COMPILE_WARNING` is generated by the scripting engine.\n`E_CORE_ERROR` |  `int`; Fatal errors that occur during PHP's initial start-up. This is like an `E_ERROR`, except that `E_CORE_ERROR` is generated by the core of PHP.\n`E_CORE_WARNING` |  `int`; Warnings (non-fatal errors) that occur during PHP's initial start-up. This is like an `E_WARNING`, except that `E_CORE_WARNING` is generated by the core of PHP.\n`E_DEPRECATED` |  `int`; Run-time notices. Enable this to receive warnings about code that will not work in future versions.\n`E_ERROR` | `int`; Fatal run-time errors. These indicate errors that cannot be recovered from, such as a memory allocation problem. Execution of the script is halted.\n`E_NOTICE` | `int`; Run-time notices. Indicate that the script encountered something that could indicate an error, but could also happen in the normal course of running a script.\n`E_PARSE` | `int`; Compile-time parse errors.\n`E_RECOVERABLE_ERROR` | `int`; Catchable fatal error. It indicates that a probably dangerous error occurred, but did not leave the Engine in an unstable state. If the error is not caught by a user defined handler (see the library function `set_error_handler` (§xx)), the application aborts as it was an `E_ERROR`.\n`E_STRICT` |  `int`; Have PHP suggest changes to the source code to ensure the best interoperability.\n`E_USER_DEPRECATED` | `int`; User-generated error message. This is like an `E_DEPRECATED`, except that `E_USER_DEPRECATED` is generated in PHP code by using the library function `trigger_error` (§xx).\n`E_USER_ERROR` |  `int`; User-generated error message. This is like an `E_ERROR`, except that `E_USER_ERROR` is generated in PHP code by using the library function `trigger_error` (§xx).\n`E_USER_NOTICE` | `int`; User-generated warning message. This is like an `E_NOTICE`, except that `E_USER_NOTICE` is generated in PHP code by using the library function `trigger_error` (§xx).\n`E_USER_WARNING` |  `int`; User-generated warning message. This is like an `E_WARNING`, except that  `E_USER_WARNING` is generated in PHP code by using the library function `trigger_error` (§xx).\n`E_WARNING` | `int`; Run-time warnings (non-fatal errors). Execution of the script is not halted.\n`E_USER_DEPRECATED` | `int`; User-generated warning message. This is like an `E_DEPRECATED`, except that  `E_USER_DEPRECATED` is generated in PHP code by using the library function `trigger_error` (§xx).\n`FALSE` |   `bool`; the case-insensitive Boolean value `FALSE`.\n`INF` | `float`; Infinity\n`M_1_PI` |  `float`; 1/pi\n`M_2_PI` |  `float`; 2/pi\n`M_2_SQRTPI` |  `float`; 2/sqrt(pi)\n`M_E` | `float`; e\n`M_EULER` | `float`; Euler constant\n`M_LN10` |  `float`; log_e 10\n`M_LN2` | `float`; log_e 2\n`M_LNPI` |  `float`; log_e(pi)\n`M_LOG10E` |  `float`; log_10 e\n`M_LOG2E` | `float`; log_2 e\n`M_PI` |  `float`; Pi\n`M_PI_2` |  `floa`t; pi/2\n`M_PI_4` |  `float`; pi/4\n`M_SQRT1_2` | `float`; 1/sqrt(2)\n`M_SQRT2` | `float`; sqrt(2)\n`M_SQRT3` | `float`; sqrt(3)\n`M_SQRTPI` |  `float`; sqrt(pi)\n`NAN` | `float`; Not-a-Number\n`NULL` |  `null`; the case-insensitive value `NULL`.\n`PHP_BINARY` |  `string`; the PHP binary path during script execution.\n`PHP_BINDIR` |  `string`; the installation location of the binaries.\n`PHP_CONFIG_FILE_PATH` |  `string`; location from which php.ini values were parsed\n`PHP_CONFIG_FILE_SCAN_DIR` |  `string`; The directory containing multiple INI files, all of which were parsed on start-up.\n`PHP_DEBUG` | `int`; Indicates whether the engine was built with debugging enabled.\n`PHP_EOL` | `string`; the end-of-line terminator for this platform.\n`PHP_EXTENSION_DIR` | `string`; The directory to be searched by the library function dl (§xx) when looking for runtime extensions.\n`PHP_EXTRA_VERSION` | `string`; the current PHP extra version.\n`PHP_INT_MAX` | `int`; the largest representable value for an integer.\n`PHP_INT_SIZE` |  `int`; the number of bytes used to represent an integer.\n`PHP_MAJOR_VERSION` | `int`; the current PHP major version\n`PHP_MANDIR`  | `string`; the installation location of the manual pages.\n`PHP_MAXPATHLEN` |  `int`; the maximum length of a fully qualified filename supported by this build.\n`PHP_MINOR_VERSION` | `int`; the current PHP minor version\n`PHP_OS` | `string`; the current operating system.\n`PHP_PREFIX`  | `string`; the value to which \"--prefix\" was set when configured.\n`PHP_RELEASE_VERSION` | `int`; the current PHP release version\n`PHP_ROUND_HALF_DOWN` | `int`; Round halves down\n`PHP_ROUND_HALF_EVEN` | `int`; Round halves to even numbers\n`PHP_ROUND_HALF_ODD` |  `int`; Round halves to odd numbers\n`PHP_ROUND_HALF_UP` | `int`; Round halves up\n`PHP_SAPI | `string`; the Server API for this build.\n`PHP_SHLIB_SUFFIX` |  `string`; build-platform's shared library suffix.\n`PHP_SYSCONFDIR` |  `string`; the PHP system configuration directory.xx\n`PHP_VERSION` | `string`; the current PHP version in the form \"major.minor.release[extra]\".\n`PHP_VERSION_ID` |  `int`; the current PHP version\n`PHP_ZTS` | `int`; Indicates whether the compiler was built with thread safety enabled.\n`TRUE` |  `bool`; the case-insensitive Boolean value `TRUE`.\n\nThe members of the `E_\\*` family have values that are powers of 2, so\nthey can be combined meaningfully using bitwise operators.\n\n# # User-Defined Constants\n\nA constant may be defined inside or outside of functions ([§§](#constants-2)), inside\na class ([§§](#constants-2)), or inside an interface ([§§](#constants-3)).\n\n\n\n# Variables\n\n# # General\n\nA *variable* is a named area of data storage that has a type and a\nvalue, both of which can change. A variable is represented by a VSlot\n([§§](#general)). A variable is created by assigning a value to it ([§§](#assignment), [§§](#simple-assignment),\n[§§](#byref-assignment), [§§](#the-new-operator), [§§](#array-creation-operator)).  A variable is destroyed by *unsetting* it, either by an explicit call to the intrinsic unset ([§§](#unset)), or by the Engine. The intrinsic `isset` ([§§](#isset)) tests if a given variable exists and is not set to `NULL`. A variable that somehow becomes defined, but is not initialized starts out with the value `NULL`.\n\nVariables have names as defined in [§§](#names). Distinct variables may have\nthe same name provided they are in different scopes ([§§](#scope)).\n\nA constant ([§§](#general-4)) is a variable that, once initialized, its value cannot\nbe changed. \n\nBased on the context in which it is declared, a variable has a scope\n([§§](#scope)) and a storage duration ([§§](#storage-duration)).\n\nA *superglobal* variable is one that is accessible in all scopes without\nthe need for a *global-declaration* ([§§](#global-variables)).\n\nThe following kinds of variable may exist in a script:\n\n-   Constant ([§§](#constants-1))\n-   Local variable ([§§](#local-variables))\n-   Array element ([§§](#array-elements))\n-   Function static ([§§](#function-statics))\n-   Global variable ([§§](#global-variables))\n-   Instance property ([§§](#instance-properties))\n-   Static property ([§§](#static-properties))\n-   Class and interface constant ([§§](#class-and-interface-constants))\n\n# # Kinds of Variables\n\n## # Constants\n\n**Syntax:**\n\nSee [§§](#general-4).\n\n**Constraints:**\n\nOutside of a class or interface, a c-constant can be defined only at the\ntop level of a script. \n\n**Semantics:**\n\nSee [§§](#general-4) and [§§](#constants-2).\n\nA constant defined outside of a class or interface is a superglobal\n([§§](#general-5)).\n\nA constant defined inside a function has function scope ([§§](#scope)). A\nconstant defined at the top level has script scope. A constant has\nstatic storage duration ([§§](#storage-duration)) and is a non-modifiable lvalue.\n\n**Examples**\n\n```\nconst MAX_HEIGHT = 10.5;        // define two c-constants\nconst UPPER_LIMIT = MAX_HEIGHT;\ndefine('COEFFICIENT_1', 2.345); // define two d-constants\ndefine('FAILURE', TRUE);\n```\n\n## # Local Variables\n\n**Syntax:**\n\nSee Semantics below.\n\nSemantics:\n\nExcept for a parameter, a local variable is never defined explicitly;\ninstead, it is created when it is first assigned a value. A local\nvariable can be assigned to as a parameter in the parameter list of a\nfunction definition ([§§](#function-definitions)) or inside any compound statement ([§§](#compound-statements)). It\nhas function scope ([§§](#scope)) and automatic storage duration ([§§](#storage-duration)). A local\nvariable is a modifiable lvalue.\n\n**Examples**\n\n```\nfunction doit($p1)  // assigned the value TRUE when called\n{\n  $count = 10;\n    ...\n  if ($p1)\n  {\n    $message = \"Can't open master file.\";\n    ...\n  }\n  ...\n}\ndoit(TRUE);\n// -----------------------------------------\nfunction f()\n{\n  $lv = 1;\n  echo \"\\$lv = $lv\\n\";\n  ++$lv;\n}\nfor ($i = 1; $i <= 3; ++$i)\n  f();\n```\n\nUnlike the function static equivalent in [§§](#function-statics), function `f` outputs\n\"`$lv = 1`\" each time.\n\nSee the recursive function example in [§§](#storage-duration).\n\n## # Array Elements\n\n**Syntax:**\n\nArrays ([§§](#arrays)) are created via the array-creation operator ([§§](#array-creation-operator)) or\nthe intrinsic `array` ([§§](#array)). At the same time, one or more elements\nmay be created for that array. New elements are inserted into an\nexisting array via the simple-assignment operator ([§§](#simple-assignment)) in\nconjunction with the subscript operator `[]` ([§§](#subscript-operator)). Elements can be\nremoved by calling the `unset` intrinsic ([§§](#unset)).\n\n**Semantics:**\n\nThe scope ([§§](#scope)) of an array element is the same as the scope of that\narray's name. An array element has allocated storage duration ([§§](#storage-duration)).\n\n**Examples**\n\n```\n$colors = [\"red\", \"white\", \"blue\"]; // create array with 3 elements\n$colors[] = \"green\";                // insert a new element\n```\n\n## # Function Statics\n\n**Syntax:**\n\n<pre>\n  <i>function-static-declaration:</i>\n    static <i>name</i>   <i>function-static-initializer<sub>opt</sub></i> ;\n  <i>function-static-initializer:</i>\n    = <i>const-expression</i>\n</pre>\n\n*name* is defined in ([§§](#names)), and *const-expression* is defined in\n([§§](#constant-expressions)).\n\n**Constraints:**\n\nA function static must be defined inside a function.\n\n**Semantics:**\n\nA function static may be defined inside any compound statement ([§§](#compound-statements)).\nIt is a modifiable lvalue.\n\nA function static has function scope ([§§](#scope)) and static storage duration\n([§§](#storage-duration)).\n\nThe value of a function static is retained across calls to its parent\nfunction. Each time the function containing a function static\ndeclaration is called, that execution is dealing with an alias ([§§](#general))\nto that static variable. If that alias is passed to the `unset` intrinsic\n([§§](#unset)), only that alias is destroyed. The next time that function\nis called, a new alias is created.\n\n**Examples**\n\n```\nfunction f()\n{\n  static $fs = 1;\n  echo \"\\$fs = $fs\\n\";\n  ++$fs;\n}\nfor ($i = 1; $i <= 3; ++$i)\n  f();\n```\n\nUnlike the local variable equivalent in [§§](#local-variables), function `f` outputs \"`$fs\n= 1`\", \"`$fs = 2`\", and \"`$fs = 3`\", as `$fs` retains its value across\ncalls.\n\n## # Global Variables\n\n**Syntax:**\n\n<pre>\n  <i>global-declaration:</i>\n    global <i>variable-name-list</i> ;\n\n  <i>variable-name-list:</i>\n    <i>expression</i>\n    <i>variable-name-list  , expression</i>\n</pre>\n\n*expression* is defined in [§§](#general-16).\n\n**Constraints:**\n\nEach *expression* must designate a variable name.\n\n**Semantics:**\n\nA global variable is never defined explicitly; instead, it is created\nwhen it is first assigned a value. That may be done at the top level of\na script, or from within a block in which that variable has been\ndeclared (*imported*, that is) using the `global` keyword.\n\nAs described in [§§](#predefined-variables),\n[`$GLOBALS`](http://www.php.net/manual/en/reserved.variables.globals.php) is\na superglobal ([§§](#general-5)) array whose elements' key/value pairs contain the\nname and value, respectively, of each global variable currently defined.\nAs such, a global variable `gv` can be initialized with the value `v`,\nand possibly be created, using the following form of assignment:\n\n`$GLOBALS['gv'] = v`\n\nAs `$GLOBALS` is a superglobal, `gv` need not first be the subject of a\n*global-declaration*.\n\nA global variable has script scope ([§§](#scope)) and static storage duration\n([§§](#storage-duration)). A global variable is a modifiable lvalue.\n\nWhen a global value is imported into a function, each time the function\nis called, that execution is dealing with an alias ([§§](#general)) to that\nglobal variable. If that alias is passed to the `unset` intrinsic\n([§§](#unset)), only that alias is destroyed. The next time that function\nis called, a new alias is created with the current value of the global\nvariable.\n\n**Examples**\n\n```\n$colors = array(\"red\", \"white\", \"blue\");\n$GLOBALS['done'] = FALSE;\n// -----------------------------------------\n$min = 10; $max = 100; $average = NULL;\nglobal $min, $max;         // allowed, but serves no purpose\nfunction compute($p)\n{\n  global $min, $max;\n  global $average;\n  $average = ($max + $min)/2;\n\n  if ($p)\n  {\n    global $result;\n    $result = 3.456;  // initializes a global, creating it, if necessary\n  }\n}\ncompute(TRUE);\necho \"\\$average = $average\\n\";  // $average = 55\necho \"\\$result = $result\\n\";  // $result = 3.456\n// -----------------------------------------\n$g = 100;\nfunction f()\n{\n  $v = 'g';\n  global $$v;          // import global $g\n  ...\n}\n```\n\n## # Instance Properties\n\nThese are described in ([§§](#properties)). They have class scope ([§§](#scope)) and\nallocated storage duration ([§§](#storage-duration)).\n\n## # Static Properties\n\nThese are described in ([§§](#properties)). They have class scope ([§§](#scope)) and static\nstorage duration ([§§](#storage-duration)).\n\n## # Class and Interface Constants\n\nThese are described in [§§](#constants-2) and [§§](#constants-3). They have class or interface\nscope ([§§](#scope)) and static storage duration ([§§](#storage-duration)).\n\n# # Predefined Variables\n\nThe following variables are automatically available to all scripts:\n\nVariable Name |   Description\n-------------   |    -----------\n`$argc` | `int`; The number of command-line arguments passed to the script. This is at least 1. (See `$argv` below.)\n`$argv` | `array`; An array of `$argc` elements containing the command-line arguments passed to the script as strings. Each element has an `int` key with the keys being numbered sequentially starting at zero through `$argc-1`. `$argv[0]` is the name of the script. It is implementation-defined as to how white space on command lines is handled, whether letter casing is preserved, which characters constitute quotes, or how `$argv[0]`'s string is formatted. As to how command-line arguments are defined, is unspecified.\n`$_COOKIE` |  `array`; The variables passed to the current script via HTTP Cookies.\n`$_ENV` | `array`; A superglobal ([§§](#general-5)) array in which the environment variable names are element keys, and the environment variable value strings are element values. As to how an environment variable is defined, is unspecified.\n`$_FILES` | `array`; The items uploaded to the current script via the HTTP POST method.\n`$_GET` | `array`; The variables passed to the current script via the URL parameters.\n`$GLOBALS` |  `array`; A superglobal ([§§](#general-5)) array containing the names of all variables that are currently defined in the global scope of the script. The variable names are the element keys, and the variable values are the element values.\n`$_POST` |  `array`; The variables passed to the current script via the HTTP POST method.\n`$_REQUEST` | `array`; By default contains the contents of `$_COOKIE`, `$_GET`, and `$_POST`.\n`$_SERVER` |  `array`; Server and execution environment information, such as headers, paths, and script locations. The entries in this array are created by the web server.\n`$_SESSION` | `array`; The session variables available to the current script.\n\n\n# Conversions\n\n# # General\n\nSome operators implicitly convert automatically the values of operands\nfrom one type to another. Explicit conversion is performed using the\ncast operator ([§§](#cast-operator)).\n\nIf an expression is converted to its own type, the type and value of the\nresult are the same as the type and value of the expression.\n\n# # Converting to Boolean Type\n\nThe [result type] (http://www.php.net/manual/en/language.types.boolean.php#language.types.boolean.casting) is `bool`.\n\nIf the source type is `int` or `float`, then if the source value tests equal\nto 0, the result value is `FALSE`; otherwise, the result value is `TRUE`.\n\nIf the source value is `NULL`, the result value is `FALSE`.\n\nIf the source is an empty string or the string \"0\", the result value is\n`FALSE`; otherwise, the result value is `TRUE`.\n\nIf the source is an array with zero elements, the result value is `FALSE`;\notherwise, the result value is `TRUE`.\n\nIf the source is an object, the result value is `TRUE`.\n\nIf the source is a resource, the result value is `TRUE`.\n\nThe library function `boolval` (§xx) allows values to be converted to\n`bool`.\n\n# # Converting to Integer Type\n\nThe [result type](http://www.php.net/manual/en/language.types.integer.php#language.types.integer.casting)  is `int`.\n\nIf the source type is `bool`, then if the source value is `FALSE`, the\nresult value is 0; otherwise, the result value is 1.\n\nIf the source type is `float`, for the values `INF`, `-INF`, and `NAN`, the\nresult value is implementation-defined. For all other values, if the\nprecision can be preserved, the fractional part is rounded towards zero\nand the result is well defined; otherwise, the result is undefined.\n\nIf the source value is `NULL`, the result value is 0.\n\nIf the source is a numeric string or leading-numeric string ([§§](#the-string-type))\nhaving integer format, if the precision can be preserved the result\nvalue is that string's integer value; otherwise, the result is\nundefined. If the source is a numeric string or leading-numeric string\nhaving floating-point format, the string's floating-point value is\ntreated as described above for a conversion from `float`. The trailing\nnon-numeric characters in leading-numeric strings are ignored.  For any\nother string, the result value is 0.\n\nIf the source is an array with zero elements, the result value is 0;\notherwise, the result value is 1.\n\nIf the source is an object, the conversion is invalid.\n\nIf the source is a resource, the result is the resource's unique ID.\n\nThe library function [`intva`l\n(§xx)](http://www.php.net/manual/en/function.intval.php) allows values\nto be converted to `int`.\n\n# # Converting to Floating-Point Type\n\nThe [result type](http://www.php.net/manual/en/language.types.float.php#language.types.float.casting) is `float`.\n\nIf the source type is `int`, if the precision can be preserved the result\nvalue is the closest approximation to the source value; otherwise, the\nresult is undefined.\n\nIf the source is a numeric string or leading-numeric string ([§§](#the-string-type))\nhaving integer format, the string's integer value is treated as\ndescribed above for a conversion from `int`. If the source is a numeric\nstring or leading-numeric string having floating-point format, the\nresult value is the closest approximation to the string's floating-point\nvalue. The trailing non-numeric characters in leading-numeric strings\nare ignored. For any other string, the result value is 0.\n\nIf the source is an object, the conversion is invalid.\n\nFor sources of all other types, the conversion is performed by first\nconverting the source value to [`int`](http://www.php.net/manual/en/language.types.integer.php)\n([§§](#converting-to-integer-type)) and then to `float`.\n\nIf the source is a resource, the result is the resource's unique ID.\n\nThe library function `floatval` (§xx) allows values to be converted to\nfloat.\n\n# # Converting to String Type\n\nThe [result type](http://www.php.net/manual/en/language.types.string.php#language.types.string.casting) is string.\n\nIf the source type is `bool`, then if the source value is `FALSE`, the\nresult value is the empty string; otherwise, the result value is \"1\".\n\nIf the source type is `int` or `float`, then the result value is a string\ncontaining the textual representation of the source value (as specified\nby the library function `sprintf` (§xx)).\n\nIf the source value is `NULL`, the result value is an empty string.\n\nIf the source is an array, the result value is the string \"Array\".\n\nIf the source is an object, then if that object's class has a\n`__toString` method ([§§](#method-__tostring)), the result value is the string returned\nby that method; otherwise, the conversion is invalid.\n\nIf the source is a resource, the result value is an\nimplementation-defined string.\n\nThe library function `strval` (§xx) allows values to be converted to\nstring.\n\n# # Converting to Array Type\n\nThe [result type](http://www.php.net/manual/en/language.types.array.php#language.types.array.casting) is `array`.\n\nIf the source type is `bool`, `int`, `float`, or `string`, the result value is\nan array of one element whose type and value is that of the source.\n\nIf the source value is `NULL`, the result value is an array of zero\nelements.\n\nIf the source is an object, the result is\nan [array](http://www.php.net/manual/en/language.types.array.php) of\nzero or more elements, where the elements are key/value pairs\ncorresponding to the\n[object](http://www.php.net/manual/en/language.types.object.php)'s\ninstance properties. The order of insertion of the elements into the\narray is the lexical order of the instance properties in the\n*class-member-declarations* ([§§](#class-members)) list. The key for a private instance\nproperty has the form \"\\\\0*name*\\\\0*name*\", where the first *name* is\nthe class name, and the second name is the property name. The key for a\nprotected instance property has the form \"\\\\0\\*\\\\0*name*\", where *name*\nis that of the property. The key for a public instance property has the\nform \"*name*\", where *name* is that of the property. The value for each\nkey is that from the corresponding property's initializer, if one\nexists, else `NULL`.\n\nIf the source is a resource, the result is an array of one element\ncontaining the implementation-defined value of the resource.\n\n# # Converting to Object Type\n\nThe [result type](http://www.php.net/manual/en/language.types.object.php#language.types.object.casting) is `object`.\n\nIf the source has any type other than object, the result is an instance\nof the predefined class `stdClass` ([§§](#class-stdclass)). If the value of the source\nis `NULL`, the instance is empty. If the value of the source has a scalar\ntype and is non-`NULL`, the instance contains a public property called\nscalar whose value is that of the source. If the value of the source is\nan array, the instance contains a set of public properties whose names\nand values are those of the corresponding key/value pairs in the source.\nThe order of the properties is the order of insertion of the source's\nelements.\n\n\n\n# Lexical Structure\n\n# # Scripts\n\nA script ([§§](#program-structure)) is an ordered sequence of characters. Typically, a\nscript has a one-to-one correspondence with a file in a file system, but\nthis correspondence is not required.\n\nConceptually speaking, a script is translated using the following steps:\n\n1.  Transformation, which converts a script from a particular character\n    repertoire and encoding scheme into a sequence of 8-bit characters.\n\n2.  Lexical analysis, which translates a stream of input characters into\n    a stream of tokens. \n\n3.  Syntactic analysis, which translates the stream of tokens into\n    executable code.\n\nConforming implementations must accept scripts encoded with the UTF-8\nencoding form (as defined by the Unicode standard), and transform them\ninto a sequence of characters. Implementations can choose to accept and\ntransform additional character encoding schemes.\n\n# # Grammars\n\nThis specification shows the syntax of the PHP programming language\nusing two grammars. The *lexical grammar* defines how source\ncharacters are combined to form white space, comments, and tokens. The\n*syntactic grammar* defines how the resulting tokens are combined to\nform PHP programs.\n\nThe grammars are presented using *grammar productions*, with each one\ndefining a non-terminal symbol and the possible expansions of that\nnon-terminal symbol into sequences of non-terminal or terminal symbols.\nIn productions, non-terminal symbols are shown in slanted type *like\nthis*, and terminal symbols are shown in a fixed-width font `like this`. \n\nThe first line of a grammar production is the name of the non-terminal\nsymbol being defined, followed by one colon for a syntactic grammar\nproduction, and two colons for a lexical grammar production. Each\nsuccessive indented line contains a possible expansion of the\nnon-terminal given as a sequence of non-terminal or terminal symbols.\nFor example, the production:\n\n<pre>\n  <i>single-line-comment::</i>\n    // input-characters<sub>opt</sub>\n    #  input-characters<sub>opt</sub>\n</pre>\n\ndefines the lexical grammar production *single-line-comment* as being\nthe terminals `//` or `#`, followed by an optional *input-characters*. Each\nexpansion is listed on a separate line.\n\nAlthough alternatives are usually listed on separate lines, when there\nis a large number, the shorthand phrase “one of” may precede a list of\nexpansions given on a single line. For example,\n\n<pre>\n  <i>hexadecimal-digit: one of</i>\n    0   1   2   3   4   5   6   7   8   9\n    a   b   c   d   e   f\n    A   B   C   D   E   F\n</pre>\n\n# # Lexical analysis\n\n# # General\n\nThe production *input-file* is the root of the lexical structure for a\nscript. Each script must conform to this production.\n\n**Syntax:**\n\n<pre>\n  <i>input-file::\n    <i>input-element\n    <i>input-file   input-element\n  <i>input-element::</i>\n    <i>comment</i>\n    <i>white-space</i>\n    <i>token</i>\n</pre>\n\n*comment* is defined in [§§](#comments); *white-space* is defined in [§§](#white-space), and\n*token* is defined in [§§](#tokens).\n\n**Semantics:**\n\nThe basic elements of a script are comments, white space, and tokens.\n\nThe lexical processing of a script involves the reduction of that script\ninto a sequence of tokens ([§§](#tokens)) that becomes the input to the\nsyntactic analysis. Tokens can be separated by white space ([§§](#white-space)) and\ndelimited comments ([§§](#comments)).\n\nLexical processing always results in the creation of the longest\npossible lexical element. (For example, `$a+++++$b` must be parsed as\n`$a++ ++ +$b`, which syntactically is invalid.)\n\n# # Comments\n\nTwo forms of comments are supported: *delimited comments* and\n*single-line comments*. \n\n**Syntax:**\n\n<pre>\n  <i>comment::</i>\n    <i>single-line-comment</i>\n    <i>delimited-comment</i>\n    \n  <i>single-line-comment::</i>\n    //   <i>input-characters<sub>opt</sub></i>\n      #    <i>input-characters<sub>opt</sub></i>\n\n  <i>input-characters::</i>\n    <i>input-character</i>\n    <i>input-characters   input-character</i>\n\n  <i>input-character::</i>\n    Any source character except new-line\n    \n  <i>new-line::</i>\n    Carriage-return character (U+000D)\n    Line-feed character (U+000A)\n    Carriage-return character (U+000D) followed by line-feed character (U+000A)\n\n  <i>delimited-comment::</i>\n    /*   No characters or any source character sequence except /*   */\n</pre>\n\n**Semantics:**\n\nExcept within a string literal or a comment, the characters /\\* start a\ndelimited comment, which ends with the characters \\*/. Except within a\nstring literal or a comment, the characters // or \\# start a single-line\ncomment, which ends with a new line. That new line is not part of the\ncomment. However, if the single-line comment is the last source element\nin an embedded script, the trailing new line can be omitted. (Note: this\nallows for uses like `<?php ... // ... ?>`.)\n\nA delimited comment can occur in any place in a script in which white\nspace ([§§](#white-space)) can occur. (For example;\n`/*...*/$c/*...*/=/*...*/567/*...*/;/*...*/` is parsed as `$c=567;`, and\n`$k = $i+++/*...*/++$j;` is parsed as `$k = $i+++ ++$j;`.)\n\n**Implementation Notes**\n\nDuring tokenizing, an implementation can treat a delimited comment as\nthough it was white space.\n\n## # White Space\n\nWhite space consists of an arbitrary combination of one or more\nnew-line, space, horizontal tab, vertical tab, and form-feed characters.\n\n**Syntax:**\n\n<pre>\n  <i>white-space::</i>\n    <i>white-space-character</i>\n    <i>white-space   white-space-character</i>\n\n  <i>white-space-character::</i>\n    <i>new-line</i>\n    Space character (U+0020)\n    Horizontal-tab character (U+0009)\n</pre>\n\n*new-line* is defined in [§§](#comments).\n\n**Semantics:**\n\nThe space and horizontal tab characters are considered *horizontal\nwhite-space characters*.\n\n## # Tokens\n\n### # General\n\nThere are several kinds of source *token*s:\n\n**Syntax:**\n\n<pre>\n  <i>token::</i>\n    <i>variable-name</i>\n    <i>name</i>\n    <i>keyword</i>\n    <i>literal</i>\n    <i>operator-or-punctuator</i>\n</pre>\n\n*variable-name* and *name* are defined in [§§](#names); *keyword* is defined\nin [§§](#keywords); *literal* is defined in [§§](#general-9); and\n*operator-or-punctuator* is defined in [§§](#operators-and-punctuators).\n\n### # Names\n\n**Syntax:**\n\n<pre>\n  <i>variable-name::</i>\n    $   <i>name</i>\n\n  <i>namespace-name::</i>\n    <i>name </i>\n    <i>namespace-name   \\   name</i>\n    \n  <i>namespace-name-as-a-prefix::</i>\n    \\\n    \\<sub>opt</sub>   <i>namespace-name</i>   \\\n    namespace   \\\n    namespace   \\   <i>namespace-name</i>   \\\n    \n  <i>qualified-name::</i>\n    <i>namespace-name-as-a-prefix<sub>opt</sub>   name</i>\n    \n  <i>name::</i>\n    <i>name-nondigit</i>\n    <i>name   name-nondigit</i>\n    <i>name   digit</i>\n\n  <i>name-nondigit::</i>\n    <i>nondigit</i>\n    one of the characters U+007f–U+00ff\n\n  <i>nondigit::</i> one of\n    _\n    a   b   c   d   e   f   g   h   i   j   k   l   m\n    n   o   p   q   r   s   t   u   v   w   x   y   z\n    A   B   C   D   E   F   G   H   I   J   K   L   M\n    N   O   P   Q   R   S   T   U   V   W   X   Y   Z\n</pre>\n\n*digit* is defined in [§§](#integer-literals)\n\n**Semantics:**\n\nNames are used to identify the following: constants ([§§](#general-4)), variables\n([§§](#general-5)), labels ([§§](#labeled-statements)), functions ([§§](#function-definitions)), classes ([§§](#class-declarations)), class\nmembers ([§§](#class-members)), interfaces ([§§](#interface-declarations)), traits ([§§](#general-26)), namespaces ([§§](#general-28)),\nand names in heredoc ([§§](#heredoc-string-literals)) and nowdoc comments ([§§](#nowdoc-string-literals)).\n\nA *name* begins with an underscore (_), *name-nondigit*, or extended\nname character in the range U+007f– ** U+00ff. Subsequent characters can\nalso include *digit*s. A *variable name* is a name with a leading\ndollar ($).\n\nUnless stated otherwise ([§§](#function-definitions), [§§](#class-declarations), [§§](#methods), [§§](#interface-declarations), [§§](#trait-declarations), [§§](#defining-namespaces)),\nnames are case-sensitive, and every character in a name is significant.\n\nFunction and method names beginning with two underscores (__) are\nreserved by the PHP language.\n\nVariable names and function names (when used in a function-call context)\nneed not be defined as source tokens; they can also be created at\nruntime using the variable name-creation operator ([§§](#variable-name-creation-operator)). (For\nexample, given `$a = \"Total\"; $b = 3; $c = $b + 5;, ${$a.$b.$c} =\nTRUE;` is equivalent to `$Total38 = TRUE;`, and `${$a.$b.$c}()` is\nequivalent to `Total38()`).\n\n**Examples**\n\n```\nconst MAX_VALUE = 100;\nfunction getData() { ... }\nclass Point { ... }\ninterface ICollection { ... }\n```\n\n**Implementation Notes**\n\nAn implementation is discouraged from placing arbitrary restrictions on\nname length or length of significance.\n\n### # Keywords\n\nA *keyword* is a name-like sequence of characters that is reserved, and\ncannot be used as a name.\n\n**Syntax:**\n\n<pre>\n  <i>keyword::</i> one of\n    abstract   and   as   break   callable   case   catch   class   clone   \n    const   continue   declare   default   do   echo   else   elseif   \n    enddeclare   endfor   endforeach   endif   endswitch   endwhile\n    extends   final   finally   for   foreach   function   global\n    goto   if   implements   include   include_once   instanceof\n    insteadof   interface   namespace   new or   print   private\n    protected   public   require   require_once   return static   switch\n    throw   trait   try   use   var   while   xor   yield\n</pre>\n\n**Semantics:**\n\nKeywords are not case-sensitive.\n\n### # Literals\n\n#### # General\n\nThe source code representation of a value is called a *literal*.\n\n**Syntax:**\n\n<pre>\n  <i>literal::\n    <i>boolean-literal</i>\n    <i>integer-literal</i>\n    <i>floating-literal</i>\n    <i>string-literal</i>\n    <i>null-literal</i>\n</pre>\n\n*boolean-literal* is defined in [§§](#boolean-literals); *integer-literal* is defined\nin [§§](#integer-literals); *floating-literal* is defined in [§§](#floating-point-literals);\n*string-literal* is defined in [§§](#string-literals); and *null-literal* is defined\nin [§§](#the-null-literal).\n\n#### # Boolean Literals\n\n**Syntax:**\n\n<pre>\n  <i>boolean-literal::</i>\n    TRUE (written in any case combination)\n    FALSE (written in any case combination)\n</pre>\n\n**Semantics:**\n\nThe type of a *boolean-literal* is bool. The values `TRUE` and `FALSE`\nrepresent the Boolean values True and False, respectively.\n\n**Examples**\n\n```\n$done = FALSE;\ncomputeValues($table, TRUE);\n```\n\n#### # Integer Literals\n\n**Syntax:**\n\n<pre>\n  <i>integer-literal::</i>\n    <i>decimal-literal</i>\n    <i>octal-literal</i>\n    <i>hexadecimal-literal</i>\n    <i>binary-literal</i>\n\n    <i>decimal-literal::</i>\n      <i>nonzero-digit</i>\n      <i>decimal-literal   digit</i>\n\n    <i>octal-literal::</i>\n      0\n      <i>octal-literal   octal-digit</i>\n\n    <i>hexadecimal-literal::</i>\n      <i>hexadecimal-prefix   hexadecimal-digit</i>\n      <i>hexadecimal-literal   hexadecimal-digit</i>\n\n    <i>hexadecimal-prefix:: one of</i>\n      0x  0X\n\n    <i>binary-literal::</i>\n      <i>binary-prefix   binary-digit</i>\n      <i>binary-literal   binary-digit</i>\n\n    <i>binary-prefix:: one of</i>\n      0b  0B\n\n    <i>digit:: one of</i>\n      0  1  2  3  4  5  6  7  8  9\n\n    <i>nonzero-digit:: one of</i>\n      1  2  3  4  5  6  7  8  9\n      \n    <i>octal-digit:: one of</i>\n      0  1  2  3  4  5  6  7\n\n    <i>hexadecimal-digit:: one of</i>\n      0  1  2  3  4  5  6  7  8  9\n            a  b  c  d  e  f\n            A  B  C  D  E  F\n\n    <i>binary-digit:: one of</i>\n        0  1\n</pre>\n\n**Semantics:**\n\nThe value of a decimal integer literal is computed using base 10; that\nof an octal integer literal, base 8; that of a hexadecimal integer\nliteral, base 16; and that of a binary integer literal, base 2.\n\nIf the value of an *integer-literal* can be represented in type int,\nthat is its type; otherwise, its type is float, as described below.\n\nUsing a twos-complement system, can the smallest negative value\n(-2147483648 for 32 bits and -9223372036854775808 for 64 bits) be\nrepresented as a decimal integer literal? No. Consider the\nexpression -5. This is made up of two tokens: a unary minus followed by\nthe integer literal 5. As such, **there is no such thing as a\nnegative-valued decimal integer literal in PHP**. Instead, there is the\nnon-negative value, which is then negated. However, if the non-negative\nvalue is too large to represent as an `int`, it becomes `float`, which is\nthen negated. Literals written using hexadecimal, octal, or binary\nnotations are considered to have non-negative values.\n\n**Examples**\n\n```\n$count = 10      // decimal 10\n\n0b101010 >> 4    // binary 101010 and decimal 4\n\n0XAF << 023      // hexadecimal AF and octal 23\n```\n\nOn an implementation using 32-bit int representation\n\n```\n2147483648 -> 2147483648 (too big for int, so is a float)\n\n-2147483648 -> -2147483648 (too big for int, so is a float, negated)\n\n-2147483647 - 1 -> -2147483648 fits in int\n\n0x80000000 -> 2147483648 (too big for int, so is a float)\n```\n\n#### # Floating-Point Literals\n\n**Syntax:**\n\n<pre>\n  <i>ﬂoating-literal::</i>\n    <i>fractional-literal   exponent-part<sub>opt</sub></i>\n    <i>digit-sequence   exponent-part</i>\n\n  <i>fractional-literal::</i>\n    <i>digit-sequence<sub>opt</sub></i> . <i>digit-sequence</i>\n    <i>digit-sequence</i> .\n\n  <i>exponent-part::</i>\n    e  <i>sign<sub>opt</sub>   digit-sequence</i>\n    E  <i>sign<sub>opt</sub>   digit-sequence</i>\n\n  <i>sign:: one of</i>\n    +  -\n\n  <i>digit-sequence::</i>\n    <i>digit</i>\n    <i>digit-sequence   digit</i>\n</pre>\n\n*digit* is defined in [§§](#integer-literals).\n\n**Constraints**\n\nThe value of a floating-point literal must be representable by its type.\n\n**Semantics:**\n\nThe type of a *floating-literal* is `float`.\n\nThe constants `INF` (§[[6.3](#core-predefined-constants)](#core-predefined-constants)) and `NAN` (§[[6.3](#core-predefined-constants)](#core-predefined-constants)) provide access to the floating-\npoint values for infinity and Not-a-Number, respectively.\n\n**Examples**\n\n```\n$values = array(1.23, 3e12, 543.678E-23);\n```\n\n#### # String Literals\n\n**Syntax:**\n\n<pre>\n  <i>string-literal::</i>\n    <i>single-quoted-string-literal</i>\n    <i>double-quoted-string-literal</i>\n    <i>heredoc-string-literal</i>\n    <i>nowdoc-string-literal</i>\n</pre>\n*single-quoted-string-literal* is defined in [§§](#integer-literals);\n*double-quoted-string-literal* is defined in [§§](#integer-literals);\n*heredoc-string-literal* is defined in [§§](#integer-literals); and\n*nowdoc-string-literal* is defined in [§§](#integer-literals).\n\nNote: By conventional standards, calling *heredoc-string-literal*s (§)\nand *nowdoc-string-literal*s ([§§](#nowdoc-string-literals)) literals is a stretch, as\neach is hardly a single token.\n\n**Semantics:**\n\nA string literal is a sequence of zero or more characters delimited in\nsome fashion. The delimiters are not part of the literal's content.\n\nThe type of a string literal is string.\n\n##### # Single-Quoted String Literals\n\n**Syntax:**\n\n<pre>\n  <i>single-quoted-string-literal::</i>\n    b<i><sub>opt</sub></i>  ' <i>sq-char-sequence<sub>opt</sub></i>  '\n\n  <i>sq-char-sequence::</i>\n    <i>sq-char</i>\n    <i>sq-char-sequence   sq-char</i>\n\n  <i>sq-char::</i>\n    <i>sq-escape-sequence</i>\n    \\<i><sub>opt</sub></i>   any member of the source character set except single-quote (') or backslash (\\)\n\n  <i>sq-escape-sequence:: one of</i>\n    \\'  \\\\\n</pre>\n**Semantics:**\n\nA single-quoted string literal is a string literal delimited by\nsingle-quotes ('). The literal can contain any source character except\nsingle-quote (') and backslash (\\\\), which can only be represented by\ntheir corresponding escape sequence.\n\nThe optional `b` prefix is reserved for future use in dealing with\nso-called *binary strings*. For now, a *single-quoted-string-literal*\nwith a `b` prefix is equivalent to one without.\n\nA single-quoted string literal is a c-constant ([§§](#general-4)).\n\n**Examples**\n\n```\n'This text is taken verbatim'\n\n'Can embed a single quote (\\') and a backslash (\\\\) like this'\n```\n\n##### # Double-Quoted String Literals\n\n**Syntax:**\n\n<pre>\n  <i>double-quoted-string-literal::</i>\n    b<i><sub>opt</sub></i>  \" <i>dq-char-sequence<sub>opt</sub></i>  \"\n\n  <i>dq-char-sequence::</i>\n    <i>dq-char</i>\n    <i>dq-char-sequence   dq-char</i>\n\n  <i>dq-char::</i>\n    <i>dq-escape-sequence</i>\n    any member of the source character set except double-quote (\") or backslash (\\)\n    \\  any member of the source character set except \"\\$efnrtvxX or\noctal-digit\n\n  <i>dq-escape-sequence::</i>\n    <i>dq-simple-escape-sequence</i>\n    <i>dq-octal-escape-sequence</i>\n    <i>dq-hexadecimal-escape-sequence</i>\n\n  <i>dq-simple-escape-sequence:: one of</i>\n    \\\"   \\\\   \\$   \\e   \\f   \\n   \\r   \\t   \\v\n\n  <i>dq-octal-escape-sequence::</i>\n    \\   <i>octal-digit</i>\n    \\   <i>octal-digit   octal-digit</i>\n    \\   <i>octal-digit   octal-digit   octal-digit</i>\n\n  <i>dq-hexadecimal-escape-sequence::</i>\n    \\x  <i>hexadecimal-digit   hexadecimal-digit<sub>opt</sub></i>\n    \\X  <i>hexadecimal-digit   hexadecimal-digit<sub>opt</sub></i>\n</pre>\n\n*octal-digit* and *hexadecimal-digit* are defined in [§§](#integer-literals).\n\n**Semantics:**\n\nA double-quoted string literal is a string literal delimited by\ndouble-quotes (\"). The literal can contain any source character except\ndouble-quote (\") and backslash (\\\\), which can only be represented by\ntheir corresponding escape sequence. Certain other (and sometimes\nnon-printable) characters can also be expressed as escape sequences.\n\nThe optional `b` prefix is reserved for future use in dealing with\nso-called *binary strings*. For now, a *double-quoted-string-literal*\nwith a `b` prefix is equivalent to one without.\n\nAn escape sequence represents a single-character encoding, as described\nin the table below:\n\nEscape sequence | Character name\n--------------- | --------------\n\\$  | Dollar sign\n\\\"  | Double quote\n\\\\  | Backslash\n\\e  | Escape\n\\f  | Form feed\n\\n  | New line\n\\r  | Carriage Return\n\\t  | Horizontal Tab\n\\v  | Vertical Tab\n\\ooo |  1–3-digit octal digit value ooo\n\\xhh or \\Xhh  | 1–2-digit hexadecimal digit value hh\n\nWithin a double-quoted string literal, except when recognized as the\nstart of an escape sequence, a backslash (\\\\) is retained verbatim.\n\nWithin a double-quoted string literal a dollar ($) character not\nescaped by a backslash (\\\\) is handled, as follows:\n\n-   If that dollar ($) character plus the character sequence following\n    spells a longest-possible variable name:\n-   For a scalar type, that variable name is replaced by the string\n    representation of that variable's value, if such a variable exists. \n    This is known as *variable substitution*. If no such variable is\n    currently defined, the value substituted is the empty string. (For\n    the purposes of variable substitution, the string representation is\n    produced as if the library function `sprintf` was used. In the case of\n    a floating-point value, the conversion specifier used is `%.nG`,\n    where the precision `n` is implementation-defined.\n-   For a variable that designates an array, if that variable name is\n    followed by characters of the form \"`[index]`\" without any\n    intervening white space, the variable name and these following\n    characters are presumed to refer to the corresponding element of\n    that array, in which case, the value of that element is substituted.\n    If `index` is itself a variable having scalar type, that variable's\n    value is substituted. If `index` is an integer literal, it must be a\n    decimal-integer literal. `index` must not be a character sequence\n    that itself looks like an array subscript or a class property.\n-   For a variable that designates an array, but no subscript-like\n    character sequence follows that variable name, the value substituted\n    is \"Array\".\n-   For a variable that designates an instance of a class, if that\n    variable name is followed by characters of the form \"`->name`\"\n    without any intervening white space, the variable name and these\n    following characters are presumed to refer to the corresponding\n    property of that instance, in which case, the value of that property\n    is substituted.\n-   Otherwise, the dollar ($) is retained verbatim.\n\nVariable substitution also provides limited support for the evaluation\nof expressions. This is done by enclosing an expression in a pair of\nmatching braces ({...}). The opening brace must be followed immediately by\na dollar ($) without any intervening white space, and that dollar must\nbegin a variable name. If this is not the case, braces are treated\nverbatim. An opening brace ({) cannot be escaped.\n\nA double-quoted string literal is a c-constant ([§§](#general-4)) if it does not\ncontain any variable substitution.\n\n**Examples**\n\n```\n$x = 123;\necho \">\\$x.$x\".\"<\"; // → >$x.123<\n// -----------------------------------------\n$colors = array(\"red\", \"white\", \"blue\");\n$index = 2;\necho \"\\$colors[$index] contains >$colors[$index]<\\n\";\n  // → $colors[2] contains >blue<\n// -----------------------------------------\nclass C {\n    public $p1 = 2;\n}\n$myC = new C();\necho \"\\$myC->p1 = >$myC->p1<\\n\";  // → $myC->p1 = >2<\n```\n\n##### # Heredoc String Literals\n\n**Syntax:**\n\n<pre>\n  <i>heredoc-string-literal::</i>\n    <<<  <i>hd-start-identifier   new-line   hd-char-sequence<sub>opt</sub>  new-line hd-end-identifier</i>  ;<i><sub>opt</sub>   new-line</i>\n\n  <i>hd-start-identifier::</i>\n    <i>name</i>\n\n  <i>hd-end-identifier::</i>\n    <i>name</i>\n\n  <i>hd-char-sequence::</i>\n    <i>hd-char</i>\n    <i>hd-char-sequence   hd-char</i>\n\n  <i>hd-char::</i>\n    <i>hd-escape-sequence</i>\n    any member of the source character set except backslash (\\)\n    \\  any member of the source character set except \\$efnrtvxX or\noctal-digit\n\n  <i>hd-escape-sequence::</i>\n    <i>hd-simple-escape-sequence</i>\n    <i>dq-octal-escape-sequence</i>\n    <i>dq-hexadecimal-escape-sequence</i>\n\n  <i>hd-simple-escape-sequence:: one of</i>\n    \\\\   \\$   \\e   \\f   \\n   \\r   \\t   \\v\n</pre>\n\n*name* is defined in [§§](#names); *new-line* is defined in [§§](#comments); and\n*dq-octal-escape-sequence* and *dq-hexadecimal-escape-sequence* are\ndefined in [§§](#double-quoted-string-literals).\n\n**Constraints**\n\nThe start and end identifier must be the same. Only horizontal white\nspace is permitted between `<<<` and the start identifier. No white\nspace is permitted between the start identifier and the new-line that\nfollows. No white space is permitted between the new-line and the end\nidentifier that follows. Exception for an optional semicolon (`;`), no\ncharacters—not even comments or white space—are permitted between the\nend identifier and the new-line that terminates that source line.\n\n**Semantics:**\n\nA heredoc string literal is a string literal delimited by\n\"`<<< name`\" and \"`name`\". The literal can contain any source\ncharacter. Certain other (and sometimes non-printable) characters can\nalso be expressed as escape sequences.\n\nA heredoc literal supports variable substitution as defined for\ndouble-quoted string literals ([§§](#double-quoted-string-literals)).\n\nA heredoc string literal is a c-constant ([§§](#general-4)) if it does not contain\nany variable substitution.\n\n**Examples**\n\n```\n$v = 123;\n$s = <<<    ID\nS'o'me \"\\\"t e\\txt; \\$v = $v\"\nSome more text\nID;\necho \">$s<\";\n→ >S'o'me \"\\\"t e  xt; $v = 123\"\nSome more text<\n```\n\n##### # Nowdoc String Literals\n\n**Syntax:**\n\n<pre>\n  <i>nowdoc-string-literal::</i>\n    <<<  '  <i>hd-start-identifier</i>  '  <i>new-line  hd-char-sequence<sub>opt</sub>   new-line hd-end-identifier</i>  ;<i><sub>opt</sub>   new-line</i>\n</pre>\n\n*hd-start-identifier*, *hd-char-sequence*, and *hd-end-identifier* are\ndefined in [§§](#heredoc-string-literals); and *new-line* is defined in [§§](#comments).\n\n**Constraints**\n\nNo white space is permitted between the start identifier and its\nenclosing single quotes ('). See also [§§](#heredoc-string-literals).\n\n**Semantics:**\n\nA nowdoc string literal looks like a heredoc string literal\n([§§](#heredoc-string-literals)) except that in the former the start identifier name is\nenclosed in single quotes ('). The two forms of string literal have the\nsame semantics and constraints except that a nowdoc string literal is\nnot subject to variable substitution.\n\nA nowdoc string literal is a c-constant ([§§](#general-4)).\n\n**Examples**\n\n```\n$v = 123;\n$s = <<<    'ID'\nS'o'me \"\\\"t e\\txt; \\$v = $v\"\nSome more text\nID;\necho \">$s<\\n\\n\";\n→ >S'o'me \"\\\"t e\\txt; \\$v = $v\"\nSome more text<\n```\n\n#### # The Null Literal\n\nThere is one null-literal value, `NULL`. Its spelling is case-insensitive.\n(Note: Throughout this specification, the convention is to use all\nuppercase.)\n\n<pre>\n  <i>null-literal::</i>\n    NULL (written in any case combination)\n</pre>\n\nA *null-literal* has the null type.\n\n### # Operators and Punctuators\n\n**Syntax**\n\n<pre>\n  <i>operator-or-punctuator:: one of</i>\n    [   ]    (   )   {    }   .   ->   ++   --   **   *   +   -   ~   !\n    $   /   % <<   >>   <   >   <=   >=   ==   ===   !=   !==   ^   |\n    &   &&   ||   ?   :   ; =   **=   *=   /=   %=   +=   -=   .=   <<=\n    >>=   &=   ^=   |=   ,\n</pre>\n\n**Semantics:**\n\nOperators and punctuators are symbols that have independent syntactic\nand semantic significance. *Operators* are used in expressions to\ndescribe operations involving one or more *operands*, and that yield a\nresulting value, produce a side effect, or some combination thereof.\n*Punctuators* are used for grouping and separating.\n\n\n# Expressions\n\n# # General\n\nAn *expression* involves one or more terms and zero or more operators.\n\nA *full expression* is an expression that is not part of another\nexpression.\n\nA *side effect* is an action that changes the state of the execution\nenvironment. (Examples of such actions are modifying a variable, writing\nto a device or file, or calling a function that performs such\noperations.)\n\nWhen an expression is evaluated, it produces a result. It might also\nproduce a side effect. Only a few operators produce side effects. (For\nexample, given the expression statement ([§§](#expression-statements)) `$v = 10`; the\nexpression 10 is evaluated to the result 10, and there is no side\neffect. Then the assignment operator is executed, which results in the\nside effect of `$v` being modified. The result of the whole expression is\nthe value of `$v` after the assignment has taken place. However, that\nresult is never used. Similarly, given the expression statement `++$v`;\nthe expression is evaluated to the result incremented-value-of-`$v`, and\nthe side effect is that `$v` is actually incremented. Again, the result\nis never used.)\n\nThe occurrence of value computation and side effects is delimited by\n*sequence points*, places in a program's execution at which all the\ncomputations and side effects previously promised are complete, and no\ncomputations or side effects of future operations have yet begun. There\nis a sequence point at the end of each full expression. The logical and\n([§§](#logical-and-operator-form-1)), logical or (§[[10.15](#logical-inclusive-or-operator-form-1)](#logical-inclusive-or-operator-form-1)), conditional (§[[10.15](#logical-inclusive-or-operator-form-1)](#logical-inclusive-or-operator-form-1)), and function-call\n([§§](#function-call-operator)) operators each contain a sequence point. (For example, in the\nfollowing series of expression statements, `$a = 10; ++$a; $b = $a;`,\nthere is sequence point at the end of each full expression, so the\nassignment to $a is completed before `$a` is incremented, and the\nincrement is completed before the assignment to `$b`.)\n\nWhen an expression contains multiple operators, the *precedence* of\nthose operators controls the order in which those operators are applied.\n(For example, the expression `$a - $b / $c` is evaluated as\n`$a - ($b / $c)` because the / operator has higher precedence than the\nbinary - operator.) The precedence of an operator is determined by the\ndefinition of its associated grammar production.\n\nIf an operand occurs between two operators having the same precedence,\nthe order in which the operations are performed is determined by those\noperators' *associativity*. With *left-associative* operators,\noperations are performed left-to-right. (For example, `$a + $b - $c` is\nevaluated as `($a + $b) - $c.`) With *right-associative* operators,\noperations are performed right-to-left. (For example, `$a = $b = $c` is\nevaluated as `$a = ($b = $c)`.)\n\nPrecedence and associativity can be controlled using *grouping\nparentheses*. (For example, in the expression `($a - $b) / $c`, the\nsubtraction is done before the division. Without the grouping\nparentheses, the division would take place first.)\n\nWhile precedence, associativity, and grouping parentheses control the\norder in which operators are applied, they do *not* control the order of\nevaluation of the terms themselves. Unless stated explicitly in this\nspecification, the order in which the operands in an expression are\nevaluated relative to each other is unspecified. See the discussion\nabove about the operators that contain sequence points. (For example, in\nthe full expression `$list1[$i] = $list2[$i++]`, whether the value\nof `$i` on the left-hand side is the old or new `$i`, is unspecified.\nSimilarly, in the full expression `$j = $i + $i++`, whether the value\nof `$i` is the old or new `$i`, is unspecified. Finally, in the full\nexpression `f() + g() \\* h()`, the order in which the three functions are\ncalled, is unspecified.)\n\n**Implementation Notes**\n\nAn expression that contains no side effects and whose resulting value is\nnot used need not be evaluated. For example, the expression statements\n`6;, $i + 6;`, and `$i/$j`; are well formed, but they contain no side\neffects and their results are not used.\n\nA side effect need not be executed if it can be determined that no other\nprogram code relies on its having happened. (For example, in the cases\nof return `$a++`; and return `++$a`;, it is obvious what value must be\nreturned in each case, but if `$a` is a variable local to the enclosing\nfunction, `$a` need not actually be incremented.\n\n# # Primary Expressions\n\n## # General\n\n**Syntax**\n\n<pre>\n  <i>primary-expression:</i>\n    <i>variable-name</i>\n    <i>qualified-name</i>\n    <i>literal</i>\n    <i>const-expression</i>\n    <i>intrinsic</i>\n    <i>anonymous-function-creation-expression</i>\n    (  <i>expression</i>  )\n    $this\n</pre>\n\n*variable-name* and *qualified-name* are defined in [§§](#names); *literal*\nis defined in [§§](#general-9); *const-expression* is defined in [§§](#constant-expressions);\n*intrinsic* is defined in [§§](#general-12);\n*anonymous-function-creation-expression* is defined in [§§](#anonymous-function-creation); and\n*expression* is defined in [§§](#script-inclusion-operators). \n\n**Semantics**\n\nWhen the name of a function is used as an expression without the\nfunction-call operator `()` ([§§](#function-call-operator)), that name is treated as a string\ncontaining that function's name.\n\nThe type and value of parenthesized expression are identical to those of\nthe un-parenthesized expression.\n\nThe variable `$this` is predefined inside any instance method or\nconstructor when that method is called from within an object\ncontext. `$this` is a handle ([§§](#general-2)) that points to the calling object or\nto the object being constructed. The type of `$this` is the type of the\nclass within which the usage of `$this` occurs. However, at run time, the\ntype of the object referred to by `$this` may be the type of the\nenclosing class or any type derived from that class.\n\n## # Intrinsics\n\n### # General\n\n**Syntax**\n<pre>\n  <i>intrinsic:</i>\n    <i>array-intrinsic</i>\n    <i>echo-intrinsic</i>\n    <i>empty-intrinsic</i>\n    <i>eval-intrinsic</i>\n    <i>exit-intrinsic</i>\n    <i>isset-intrinsic</i>\n    <i>list-intrinsic</i>\n    <i>print-intrinsic</i>\n    <i>unset-intrinsic</i>\n</pre>\n\n*array-intrinsic* is defined in [§§](#array); *echo-intrinsic* is defined\nin [§§](#echo); *empty-intrinsic* is defined in [§§](#empty);\n*eval-intrinsic* is defined in [§§](#eval); *exit-intrinsic* is defined in\n[§§](#exitdie); *isset-intrinsic* is defined in [§§](#isset); *list-intrinsic*\nis defined in [§§](#list); *print-intrinsic* is defined in [§§](#print); and\n*unset-intrinsic* is defined in [§§](#unset).\n\n**Semantics**\n\nThe names in this series of subclauses have special meaning and are\ncalled *intrinsics*, but they are not keywords; nor are they functions.\n\n### # array\n\n**Syntax**\n\n<pre>\n  <i>array-intrinsic:</i>\n    array ( <i>array-initializer<sub>opt</sub></i>  )\n</pre>\n\n*array-initializer* is defined in [§§](#array-creation-operator).\n\n**Semantics**\n\nThis intrinsic creates and initializes an array. It is equivalent to the\narray-creation operator `[]` ([§§](#array-creation-operator)).\n\n### # echo\n\n**Syntax**\n\n<pre>\n  <i>echo-intrinsic:</i>\n    echo  <i>expression</i>\n    echo  (  <i>expression</i>  )\n    echo  <i>expression-list-two-or-more</i>\n\n  <i>expression-list-two-or-more:</i>\n    <i>expression</i>  ,  <i>expression</i>\n    <i>expression-list-two-or-more</i>  ,  <i>expression</i>\n</pre>\n\n*expression* is defined in [§§](#general-16).\n\n**Constraints**\n\n*expression* must not designate an array nor an instance of a type not\nhaving a `__toString` method ([§§](#method-__tostring)). \n\n**Semantics**\n\nAfter converting each of its *expression*s' values to strings, if\nnecessary, `echo` concatenates them in lexical order, and writes the\nresulting string to `STDOUT` ([§§](#resource-types)). Unlike `print` ([§§](#print)), it does\nnot produce a result.\n\nFor value substitution in string literals, see [§§](#double-quoted-string-literals) and\n[§§](#heredoc-string-literals). For conversion to string, see [§§](#converting-to-string-type).\n\n**Examples**\n\n```\n$v1 = TRUE;\n$v2 = 123;\necho  '>>' . $v1 . '|' . $v2 . \"<<\\n\";    // outputs \">>1|123<<\"\necho  '>>' , $v1 , '|' , $v2 , \"<<\\n\";    // outputs \">>1|123<<\"\necho ('>>' . $v1 . '|' . $v2 . \"<<\\n\");   // outputs \">>1|123<<\"\n$v3 = \"qqq{$v2}zzz\";\necho \"$v3\\n\"; \n```\n\n### # empty\n\n**Syntax**\n\n<pre>\n  <i>empty-intrinsic:</i>\n    empty ( <i>expression</i>  )\n</pre>\n\n*expression* is defined in [§§](#general-16).\n\n**Semantics**\n\nThis intrinsic returns `TRUE` if the variable or value designated by\n*expression* is empty, where *empty* means that the variable does not\nexist, or it exists and its value compares equal to `FALSE`. Otherwise,\nthe intrinsic returns `FALSE`.\n\nThe following values are considered empty: `FALSE`, `0`, `0.0`, \"\", \"`0`\", `NULL`, `[]`/`array()`, and any uninitialized variable.\n\nIf this intrinsic is used with an expression that designate a dynamic\nproperty ([§§](#dynamic-members)), then if the class of that property has an `__isset`\nmethod ([§§](#method-__isset)), that method is called.\n\n**Examples**\n\n```\nempty(\"0\")  // results in TRUE\nempty(\"00\") // results in FALSE\n$v = [10, 20];\nempty($v)   // results in FALSE\n```\n\n### # eval\n\n**Syntax**\n\n<pre>\n  <i>eval-intrinsic:</i>\n    eval (  <i>expression</i>  )\n</pre>\n\n*expression* is defined in [§§](#general-16).   \n\n**Constraints**\n\n*expression* must designate a string, the contents of which must be\nvalid PHP source code.\n\nThe PHP source code in the string must not be delimited by opening and\nclosing [PHP\ntags](http://us3.php.net/manual/en/language.basic-syntax.phpmode.php).\n\n**Semantics**\n\nThis intrinsic evaluates the contents of the string designated by\n*expression*, as PHP source code.\n\nExecution of a `return` statement ([§§](#the-return-statement)) from within the source code\nterminates the intrinsic, and the value returned becomes the value\nreturned by eval. If the source code is ill formed, eval returns `FALSE`;\notherwise, eval returns `NULL`.\n\nThe source code is executed in the scope of that from which `eval` is\ncalled.\n\n**Examples**\n\n```\n$str = \"Hello\";\neval(\"echo \\$str . \\\"\\\\n\\\";\");  // → echo $str . \"\\n\";\n```\n\n### # exit/die\n\n**Syntax**\n\n<pre>\n  <i>exit-intrinsic:</i>\n    exit  <i>expression<sub>opt</sub></i>\n    exit  (  <i>expression<sub>opt</sub></i>  )\n    die   <i>expression<sub>opt</sub></i>\n    die   (   <i>expression<sub>opt</sub></i> )\n</pre>\n\n*expression* is defined in [§§](#general-16).\n\n**Constraints**\n\nWhen *expression* designates an integer, its value must be in the range\n0–254.\n\n**Semantics**\n\n`exit` and `die` are equivalent.\n\nThis intrinsic terminates the current script. If *expression* designates\na string, that string is written to `STDOUT` ([§§](#resource-types)). If *expression*\ndesignates an integer, that represents the script's *exit status code*.\nCode 255 is reserved by PHP. Code 0 represents \"success\". The exit\nstatus code is made available to the execution environment. If\n*expression* is omitted or is a string, the exit status code is zero.\n`exit` does not have a resulting value.\n\n`exit` performs the following operations, in order:\n\n-   Writes the optional string to `STDOUT` ([§§](#resource-types)).\n-   Calls any functions registered via the library function\n    `register_shutdown_function` (§xx) in their order of registration.\n-   Invokes destructors ([§§](#destructors)) for all remaining instances.\n\n**Examples**\n\n```\nexit (\"Closing down\");\nexit (1);\nexit;\n```\n\n### # isset\n\n**Syntax**\n\n<pre>\n  <i>isset-intrinsic:</i>\n    isset  (  <i>expression-list-one-or-more</i>  )\n\n  <i>expression-list-one-or-more</i>:\n    <i>expression</i>\n    <i>expression-list-one-or-mor</i>  ,  <i>expression</i>\n</pre>\n\n*expression* is defined in [§§](#general-16).   \n\n**Constraints**\n\nEach *expression* must designate a variable.\n\n**Semantics**\n\nThis intrinsic returns `TRUE` if all the variables designated by\n*expression*s are set and their values are not `NULL`. Otherwise, it\nreturns `FALSE`.\n\nIf this intrinsic is used with an expression that designates a dynamic\nproperty ([§§](#dynamic-members)), then if the class of that property has an `__isset`\nmethod ([§§](#method-__isset)), that method is called.\n\n**Examples**\n\n```\n$v = TRUE;\nisset($v)     // results in TRUE\n$v = NULL;\nisset($v)     // results in FALSE\n$v1 = TRUE; $v2 = 12.3; $v1 = NULL;\nisset($v1, $v2, $v3)  // results in FALSE\n```\n\n### # list\n\n**Syntax**\n\n<pre>\n  <i>list-intrinsic:</i>\n    list  (  <i>list-expression-list<sub>opt</sub></i>  )\n\n  <i>list-expression-list:</i>\n  <i>list-or-variable</i>\n  ,\n  <i>list-expression-list</i>  ,  <i>list-or-variable<sub>opt</sub></i>\n\n  <i>list-or-variable:</i>\n    <i>list-intrinsic</i>\n    <i>expression</i>\n</pre>\n\n*expression* is defined in [§§](#general-16).   \n\n**Constraints**\n\n*list-intrinsic* must be used as the left-hand operand in a\n*simple-assignment-expression* ([§§](#simple-assignment)) of which the right-hand\noperand must be an expression that designates an array (the \"source\narray\").\n\nEach *expression* in *expression-list-one-or-more* must designate a\nvariable (the \"target variable\").\n\n**Semantics**\n\nThis intrinsic assigns zero or more elements of the source array to the\ntarget variables. On success, it returns a copy of the source array. If\nthe source array is actually the value `NULL`, this is consider a failure,\nand the return value from `list` is undefined.\n\nAll elements in the source array having keys of type `string` are ignored.\nThe element having an `int` key of 0 is assigned to the first target\nvariable, the element having an `int` key of 1 is assigned to the second\ntarget variable, and so on, until all target variables have been\nassigned. Any elements having an `int` key outside the range 0–(*n*-1),\nwhere *n* is the number of target variables, are ignored. If there are\nfewer element candidates having int keys than there are target\nvariables, the unassigned target variables are unset ([§§](#unset)).\n\nAny target variable may be a list, in which case, the corresponding\nelement is expected to be an array.\n\nIf the source array elements and the target variables overlap in any\nway, the behavior is unspecified.\n\n**Examples**\n\n```\nlist($min, $max, $avg) = array(0, 100, 67);\n  // $min is 0, $max is 100, $avg is 67\nlist($min, $max, $avg) = array(2 => 67, 1 => 100, 0 => 0);\n  // same as example above\nlist($min, , $avg) = array(0, 100, 67);\n  // $min is 0, $avg is 67\nlist($min, $max, $avg) = array(0, 2 => 100, 4 => 67);\n  // $min is 0, $max is unset, $avg is 100\nlist($min, list($max, $avg)) = [0, [1 => 67, 99, 0 => 100], 33];\n  // $min is 0, $max is 100, $avg is 67\n```\n\n### # print\n\n**Syntax**\n\n<pre>\n  <i>print-intrinsic:\n    print  <i>expression</i>\n    print  (  <i>expression</i>  )\n</pre>\n\n*expression* is defined in [§§](#general-16).   \n\n**Constraints**\n\n*expression* must not designate an array or an instance of a type not\nhaving a `__toString` method. \n\n**Semantics**\n\nAfter converting its *expression*'s value to a string, if necessary,\n`print` writes the resulting string to `STDOUT` ([§§](#resource-types)). Unlike `echo`\n([§§](#echo)), `print` can be used in any context allowing an expression. It\nalways returns the value 1.\n\nFor value substitution in string literals, see [§§](#double-quoted-string-literals) and\n[§§](#heredoc-string-literals). For conversion to string, see [§§](#converting-to-string-type).\n\n**Examples**\n\n```\n$v1 = TRUE;\n$v2 = 123;\nprint  '>>' . $v1 . '|' . $v2 . \"<<\\n\";   // outputs \">>1|123<<\"\nprint ('>>' . $v1 . '|' . $v2 . \"<<\\n\");  // outputs \">>1|123<<\"\n$v3 = \"qqq{$v2}zzz\";\nprint \"$v3\\n\";            // outputs \"qqq123zzz\"\n$a > $b ? print \"...\" : print \"...\";\n```\n\n### # unset\n\n**Syntax**\n\n<pre>\n  <i>unset-intrinsic:</i>\n    unset  (  <i>expression-list-one-or-more</i>  )\n</pre>\n\n*expression-list-one-or-more* is defined in [§§](#isset).  \n\n**Constraints**\n\nEach *expression* must designate a variable.\n\n**Semantics**\n\nThis intrinsic unsets ([§§](#general-5)) the variables designated by each\n*expression* in *expression-list-one-or-more*. No value is returned. An\nattempt to unset a non-existent variable (such as a non-existent element\nin an array) is ignored.\n\nWhen called from inside a function, this intrinsic behaves, as follows:\n\n-   For a variable declared `global` in that function, `unset` removes the\n    alias to that variable from the scope of the current call to that\n    function. Once the function returns, the global variable is still\n    set. (To unset the global variable, use unset on the corresponding\n    [`$GLOBALS`](http://us3.php.net/manual/en/reserved.variables.globals.php) array entry ([§§](#predefined-variables)).)\n-   For a variable passed byRef to that function, `unset` removes the\n    alias to that variable from the scope of the current call to that\n    function. Once the function returns, the passed-in argument variable\n    is still set.\n-   For a variable declared static in that function, `unset` removes the\n    alias to that variable from the scope of the current call to that\n    function. In subsequent calls to that function, the static variable\n    is still set and retains its value from call to call.\n\nAny visible instance property may be unset, in which case, the property\nis removed from that instance.\n\nIf this intrinsic is used with an expression that designate a dynamic\nproperty ([§§](#dynamic-members)), then if the class of that property has an `__unset`\nmethod ([§§](#method-__unset)), that method is called.\n\n**Examples**\n\n```\nunset($v);\nunset($v1, $v2, $v3);\nunset($x->m); // if m is a dynamic property, $x's __unset(\"m\") is called\n```\n\n## # Anonymous Function-Creation\n\n**Syntax**\n\n<pre>\n  <i>anonymous-function-creation-expression:</i>\n  function  &<sub>opt</sub> (  <i>parameter-declaration-list<sub>opt<sub></i>  )  <i>anonymous-function-use-clause<sub>opt</sub></i>\n      <i>compound-statement</i>\n\n  <i>anonymous-function-use-clause:</i>\n    use  (  <i>use-variable-name-list</i>  )\n\n  <i>use-variable-name-list:</i>\n    &<sub>opt</sub>   <i>variable-name</i>\n    <i>use-variable-name-list</i>  ,  &<sub>opt</sub>  <i>variable-name</i>\n</pre>\n\n*parameter-declaration-list* is defined in [§§](#function-definitions); *compound-statement*\nis defined in [§§](#compound-statements); *variable-name* is defined in [§§](#names).\n\n**Semantics**\n\nThis operator returns an object of type `Closure` ([§§](#class-closure)), or a derived\ntype thereof, that encapsulates the anonymous function ([§§](#anonymous-functions)) defined\nwithin. An anonymous function is defined like, and behaves like, a named\nfunction ([§§](#function-definitions)) except that the former has no name and has an optional\n*anonymous-function-use-clause*.\n\nAn expression that designates an anonymous function is compatible with\nthe type hint `callable` ([§§](#function-definitions)).\n\nThe *use-variable-name-list* is a list of variables from the enclosing\nscope, which are to be made available by name to the body of the\nanonymous function. Each of these may be passed by value or byRef, as\nneeded. The values used for these variables are those at the time the\n`Closure` object is created, not when it is used to call the function it\nencapsulates.\n\nAn anonymous function defined inside an instance method has access to\nthe variable `$this`.\n\n**Examples**\n\n```\nfunction doit($value, callable $process)  // return type is \"Closure\"\n{\n  return $process($value);\n}\n$result = doit(5, function ($p) { return $p * 2; });  // doubles a value\n$result = doit(5, function ($p) { return $p * $p; }); // squares a value\n// -----------------------------------------\nclass C\n{\n  public function compute(array $values)\n  {\n    $count = 0;\n          $callback1 = function () use (&$count) // called C::{closure}\n    {\n      ++$count;\n      ...\n    };\n    ...\n    $callback2 = function()   // also called C::{closure}\n    {\n      ...\n    };\n    ...\n  }\n  ...\n}\n```\n\n# # Postfix Operators\n\n## # General\n\n**Syntax**\n\n<pre>\n  <i>postfix-expression:</i>\n    <i>primary-expression</i>\n    <i>clone-expression</i>\n    <i>object-creation-expression</i>\n    <i>array-creation-expression</i>\n    <i>subscript-expression</i>\n    <i>function-call-expression</i>\n    <i>member-selection-expression</i>\n    <i>postfix-increment-expression</i>\n    <i>postfix-decrement-expression</i>\n    <i>scope-resolution-expression</i>\n    <i>exponentiation-expression</i>\n</pre>\n\n*primary-expression* is defined in [§§](#general-11); *clone-expression* is\ndefined in [§§](#the-clone-operator); *object-creation-expression* is defined in [§§](#the-new-operator);\n*array-creation-expression* is defined in [§§](#array-creation-operator);\n*subscript-expression* is defined in [§§](#subscript-operator); *function-call-expression* is defined in [§§](#function-call-operator); *member-selection-expression* is defined in [§§](#member-selection-operator);\n*postfix-increment-expression* and *postfix-decrement-expression* are\ndefined in [§§](#postfix-increment-and-decrement-operators); *scope-resolution-expression* is defined in [§§](#scope-resolution-operator);\nand *exponentiation-expression* is defined in [§§](#exponentiation-operator)..\n\n**Semantics**\n\nThese operators associate left-to-right.\n\n## # The `clone` Operator\n\n**Syntax**\n\n<pre>\n  <i>clone-expression:</i>\n    clone  <i>expression</i>\n</pre>\n\n*expression* is defined in [§§](#general-16).\n\n**Constraints**\n\n*expression* must designate an object.\n\n**Semantics**\n\nThe `clone` operator creates a new object that is a shallow copy of the object designated by *expression*. Then, if the class type of *expression* has a method called `__clone` ([§§](#method-__clone)), that is called to perform a deep copy. The result is a handle that points to the new object.\n\n**Examples**\n\nConsider a class `Employee`, from which is derived a class `Manager`. Let us\nassume that both classes contain properties that are objects. clone is\nused to make a copy of a Manager object, and behind the scenes, the\n`Manager` object uses clone to copy the properties for the base class,\n`Employee`.\n\n```\nclass Employee\n{\n  ...\n  public function __clone() \n  {\n    // make a deep copy of Employee object\n  }\n}\nclass Manager extends Employee\n{\n  ...\n  public function __clone() \n  {\n    $v = parent::__clone();\n    // make a deep copy of Manager object\n\n  }\n}\n$obj1 = new Manager(\"Smith\", 23);\n$obj2 = clone $obj1;  // creates a new Manager that is a deep copy\n```\n\n## # The `new` Operator\n\n**Syntax**\n\n<pre>\n  <i>object-creation-expression:</i>\n    new  <i>class-type-designator</i>  (  <i>argument-expression-list<sub>opt</sub></i>  )\n    new  <i>class-type-designator</i>\n\n  <i>class-type-designator:</i>\n    static\n    <i>qualified-name</i>\n    <i>expression</i>\n</pre>\n\n*argument-expression-list* is defined in [§§](#function-call-operator); *qualified-name* is\ndefined in [§§](#names); and *expression* is defined in [§§](#general-16).\n\n**Constraints**\n\n*qualified-name* must name a class.\n\n*expression* must be a value of type `string` (but not be a string\nliteral) that contains the name of a class.\n\n*class-type-designator* must not designate an abstract class ([§§](#general-23)).\n\nThe number of arguments in *argument-expression-list* must be at least\nas many as the number of parameters defined for the class's constructor.\n\n**Semantics**\n\nThe `new` operator allocates memory for an object that is an instance of\nthe class specified by *class-type-designator*.\n\nThe object is initialized by calling the class's constructor ([§§](#constructors))\npassing it the optional *argument-expression-list*. If the class has no\nconstructor, the constructor that class inherits (if any) is used.\nOtherwise, each instance property takes on the value `NULL`.\n\nThe result of an *object-creation-expression* is a handle to an object\nof the type specified by *class-type-designator*.\n\nFrom within a method, the use of `static` corresponds to the class in the\ninheritance context in which the method is called.\n\nBecause a constructor call is a function call, the relevant parts of\n[§§](#function-call-operator) also apply.\n\n**Examples**\n\n```\nclass Point \n{\n  public function __construct($x = 0, $y = 0) \n  {\n    ...\n  }\n  ...\n}\n$p1 = new Point;     // create Point(0, 0)\n$p1 = new Point(12);   // create Point(12, 0)\n$cName = 'Point';\n$p1 = new $cName(-1, 1); // create Point(-1, 1)\n```\n\n## # Array Creation Operator\n\nAn array is created and initialized by one of two equivalent ways: via\nthe array-creation operator `[]`, as described below, or the intrinsic\n`array` ([§§](#array)).\n\n**Syntax**\n\n<pre>\n  <i>array-creation-expression:</i>\n    array  (  <i>array-initializer<sub>opt</sub></i>  )\n    [ <i>array-initializer<sub>opt</sub></i> ]\n\n  <i>array-initializer:</i>\n    <i>array-initializer-list</i>  ,<sub>opt</sub>\n\n  <i>array-initializer-list:</i>\n    <i>array-element-initializer</i>\n    <i>array-element-initializer  ,  array-initializer-list</i>\n\n  <i>array-element-initializer:</i>\n    &<sub>opt</sub>   <i>element-value</i>\n    element-key  =>  &<sub>opt</sub>   <i>element-value</i>\n\n  <i>element-key:</i>\n    <i>expression</i>\n\n  <i>element-value</i>\n    <i>expression</i>\n</pre>\n\n*expression* is defined in [§§](#general-16).\n\n**Constraints**\n\nIf *array-element-initializer* contains &, *element-value's expression*\nmust be a variable name ([§§](#names)).\n\n**Semantics**\n\nIf *array-initializer* is omitted, the array has zero elements. For\nconvenience, an *array-initializer* may have a trailing comma; however,\nthis comma has no purpose. An *array-initializer-list* consists of a\ncomma-separated list of one or more *array-element-initializer*s, each\nof which is used to provide an *element-value* and an optional\n*element-key*.\n\nIf the value of *element-key* is neither `int` nor `string`, keys with `float`\nor `bool` values, or strings whose contents match exactly the pattern of\n*decimal-literal* ([§§](#integer-literals)), are converted to `int` ([§§](#converting-to-integer-type)), and values\nof all other key types are converted to `string` ([§§](#converting-to-string-type)).\n\nIf *element-key* is omitted from an *array-element-initializer*, an\nelement key of type `int` is associated with the corresponding\n*element-value*. The key associated is one more than the previously\nassigned `int` key for this array, regardless of whether that key was\nprovided explicitly or by default. However, if this is the first element\nwith an `int` key, key zero is associated.\n\nOnce the element keys have been converted to `int` or `string`, and omitted\nelement keys have each been associated by default, if two or more\n*array-element-initializer*s in an *array-initializer* contain the same\nkey, the lexically right-most one is the one whose element-value is used\nto initialize that element.\n\nThe result of this operator is a handle to the set of array elements.\n\nIf *array-element-initializer* contains &, *element-value's* value is\nstored using byRef assignment ([§§](#assignment)).\n\n**Examples**\n\n```\n$v = [];      // array has 0 elements\n$v = array(TRUE);   // array has 1 element, the Boolean TRUE\n$v = [123, -56];  // array of two ints, with implicit int keys 0 and 1\n$v = [0 => 123, 1 => -56]; // array of two ints, with explicit int keys 0 and 1\n$i = 10;\n$v = [$i - 10 => 123, $i - 9 => -56]; // key can be a runtime expression\n$v = [NULL, 1 => FALSE, 123, 3 => 34e12, \"Hello\"];  // implicit & explicit keys\n$i = 6; $j = 12;\n$v = [7 => 123, 3 => $i, 6 => ++$j];  // keys are in arbitrary order\n$v[4] = 99;   // extends array with a new element\n$v = [2 => 23, 1 => 10, 2 => 46, 1.9 => 6];\n     // array has 2, with keys 2 and 1, values 46 and 6, respectively\n$v = [\"red\" => 10, \"4\" => 3, 9.2 => 5, \"12.8\" => 111, NULL => 1];\n     // array has 5 elements, with keys “red”, 4, 9, “12.8”, and “”.\n$c = array(\"red\", \"white\", \"blue\");\n$v = array(10, $c, NULL, array(FALSE, NULL, $c));\n$v = array(2 => TRUE, 0 => 123, 1 => 34.5, -1 => \"red\");\nforeach($v as $e) { ... } // iterates over keys 2, 0, 1, -1\nfor ($i = -1; $i <= 2; ++$i) { ... $v[$i] } // retrieves via keys -1, 0, 1, 2\n```\n\n## # Subscript Operator\n\n**Syntax**\n\n<pre>\n  <i>subscript-expression:</i>\n    <i>postfix-expression</i>  [  <i>expression<sub>opt</sub></i>  ]\n    <i>postfix-expression</i>  {  <i>expression<sub>opt</sub></i>  }   <b>[Deprecated form]</b>\n</pre>\n\n*postfix-expression* is defined in [§§](#general-13); and *expression* is defined\nin [§§](#general-16).\n\n**Constraints**\n\nIf *postfix-expression* designates a string, *expression* must not\ndesignate a string.\n\n*expression* can be omitted only if *subscript-expression* is used in a\nmodifiable-lvalue context and *postfix-expression* does not designate a\nstring.\n\nIf *subscript-expression* is used in a non-lvalue context, the element\nbeing designated must exist.\n\n**Semantics**\n\nA *subscript-expression* designates a (possibly non-existent) element of\nan array or string. When *subscript-expression* designates an object of\na type that implements `ArrayAccess` ([§§](#interface-arrayaccess)), the minimal semantics are\ndefined below; however, they can be augmented by that object's methods\n`offsetGet` (§[[15.6.1](#interface-arrayaccess)](#interface-arrayaccess)) and `offsetSet` (§[[15.6.1](#interface-arrayaccess)](#interface-arrayaccess)).\n\nThe element key is designated by *expression*. If the value of\n*element-key* is neither `int` nor `string`, keys with `float` or `bool` values,\nor strings whose contents match exactly the pattern of *decimal-literal*\n([§§](#integer-literals)), are converted to `int` ([§§](#converting-to-integer-type)), and values of all other key\ntypes are converted to `string` ([§§](#converting-to-string-type)).\n\nIf both *postfix-expression* and *expression* designate strings,\n*expression* is treated as if it specified the `int` key zero instead.\n\nA *subscript-expression* designates a modifiable lvalue if and only if\n*postfix-expression* designates a modifiable lvalue.\n\n*postfix-expression designates an array*\n\nIf *expression* is present, if the designated element exists, the type\nand value of the result is the type and value of that element;\notherwise, the result is `NULL`.\n\nIf *expression* is omitted, a new element is inserted. Its key has type\n`int` and is one more than the highest, previously assigned, non-negative\n`int` key for this array. If this is the first element with a non-negative\n`int` key, key zero is used. However, if the highest, previously assigned\n`int` key for this array is `PHP_INT_MAX` ([§§](#)), **no new element is\ninserted**. The type and value of the result is the type and value of\nthe new element.\n\n-   If the usage context is as the left-hand side of a\n    *simple-assignment-expression* ([§§](#simple-assignment)): The value of the new\n    element is the value of the right-hand side of that\n    *simple-assignment-expression*.\n-   If the usage context is as the left-hand side of a\n    *compound-assignment-expression* ([§§](#compound-assignment)): The expression\n    `e1 op= e2` is evaluated as `e1 = NULL op (e2)`.\n-   If the usage context is as the operand of a postfix- or\n    prefix-increment or decrement operator ([§§](#postfix-increment-and-decrement-operators), [§§](#prefix-increment-and-decrement-operators)): The value\n    of the new element is `NULL`.\n\n*postfix-expression designates a string*\n\nIf the designated element exists, the type and value of the result is\nthe type and value of that element; otherwise, the result is an empty\nstring.\n\n*postfix-expression designates an object of a type that implements*\n`ArrayAccess`\n\nIf *expression* is present,\n\n-   If *subscript-expression* is used in a non-lvalue context, the\n    object's method `offsetGet` is called with an argument of\n    *expression*. The type and value of the result is the type and value\n    returned by `offsetGet`.\n-   If the usage context is as the left-hand side of a\n    *simple-assignment-expression*: The object's method `offsetSet` is\n    called with a first argument of *expression* and a second argument\n    that is the value of the right-hand side of that\n    *simple-assignment-expression*. The type and value of the result is\n    the type and value of the right-hand side of that\n    *simple-assignment-expression*.\n-   If the usage context is as the left-hand side of a\n    *compound-assignment-expression*: The expression `e1 op= e2` is\n    evaluated as `e1 = offsetGet(expression) op (e2)`, which is then\n    processed according to the rules for simple assignment immediately\n    above.\n-   If the usage context is as the operand of a postfix- or\n    prefix-increment or decrement operator ([§§](#postfix-increment-and-decrement-operators), [§§](#prefix-increment-and-decrement-operators)): The\n    object's method `offsetGet` is called with an argument of\n    *expression*. However, this method has no way of knowing if an\n    increment or decrement operator was used, or whether it was a prefix\n    or postfix operator. The type and value of the result is the type\n    and value returned by `offsetGet`.\n\nIf *expression* is omitted, \n\n-   If the usage context is as the left-hand side of a\n    *simple-assignment-expression*: The object's method `offsetSet`\n    ([§§](#interface-arrayaccess)) is called with a first argument of `NULL` and a second\n    argument that is the value of the right-hand side of that\n    *simple-assignment-expression*. The type and value of the result is\n    the type and value of the right-hand side of that\n    *simple-assignment-expression*.\n-   If the usage context is as the left-hand side of a\n    *compound-assignment-expression*: The expression `e1 op= e2` is\n    evaluated as `e1 = offsetGet(NULL) op (e2)`, which is then processed\n    according to the rules for simple assignment immediately above.\n-   If the usage context is as the operand of a postfix- or\n    prefix-increment or decrement operator ([§§](#postfix-increment-and-decrement-operators), [§§](#prefix-increment-and-decrement-operators)): The\n    object's method `offsetGet` is called with an argument of `NULL`.\n    However, this method has no way of knowing if an increment or\n    decrement operator was used, or whether it was a prefix or postfix\n    operator. The type and value of the result is the type and value\n    returned by `offsetGet`.\n\nNote: The brace (`{...}`) form of this operator has been deprecated. \n\n**Examples**\n\n```\n$v = array(10, 20, 30);\n$v[1] = 1.234;    // change the value (and type) of element [1]\n$v[-10] = 19;   // insert a new element with int key -10\n$v[\"red\"] = TRUE; // insert a new element with string key \"red\"\n[[2,4,6,8], [5,10], [100,200,300]][0][2]  // designates element with value 6\n[\"black\", \"white\", \"yellow\"][1][2]  // designates substring \"i\" in \"white\"\nfunction f() { return [1000, 2000, 3000]; } \nf()[2]      // designates element with value 3000\n\"red\"[1.9]    // designates [1]\n\"red\"[0][0][0]    // designates [0]\n// -----------------------------------------\nclass MyVector implements ArrayAccess { ... }\n$vect1 = new MyVector(array(10, 'A' => 2.3, \"up\"));\n$vect1[10] = 987; // calls Vector::offsetSet(10, 987)\n$vect1[] = \"xxx\"; // calls Vector::offsetSet(NULL, \"xxx\")\n$x = $vect1[1];   // calls Vector::offsetGet(1)\n```\n\n## # Function Call Operator\n\n**Syntax**\n\n<pre>\n  <i>function-call-expression:</i>\n    <i>postfix-expression</i>  (  <i>argument-expression-list<sub>opt</sub></i>  )\n\n  <i>argument-expression-list:</i>\n    <i>assignment-expression</i>\n    <i>argument-expression-list</i>  ,  <i>assignment-expression</i>\n</pre>\n\n*postfix-expression* is defined in [§§](#general-13); and *assignment-expression*\nis defined in [§§](#general-15).\n\n\n**Constraints**\n\n*postfix-expression* must designate a function, either by being its\n*name*, by being a value of type string (but not a string literal) that\ncontains the function's name, or by being a variable whose type is\n`Closure` ([§§](#class-closure)) or a derived type thereof.\n\nThe number of arguments present in a function call must be at least as\nmany as the number of parameters defined for that function.\n\nNo calls can be made to a conditionally defined function ([§§](#general-22)) until\nthat function exists.\n\nAny argument that matches a parameter passed byRef should (but need not)\ndesignate an lvalue.\n\n**Semantics**\n\nAn expression of the form *function-call-expression* is a *function\ncall*. The postfix expression designates the *called function*, and\n*argument-expression-list* specifies the arguments to be passed to that\nfunction. An argument can have any type. In a function call,\n*postfix-expression* is evaluated first, followed by each\n*assignment-expression* in the order left-to-right. There is a sequence\npoint ([§§](#general-10)) right before the function is called. For details of the\ntype and value of a function call see [§§](#the-return-statement). The value of a function\ncall is a modifiable lvalue only if the function returns a byRef that\naliases a modifiable lvalue.\n\nWhen *postfix-expression* designates an instance method or constructor,\nthe instance used in that designation is used as the value of `$this` in\nthe invoked method or constructor. However, if no instance was used in\nthat designation (for example, in the call `C::instance_method()`) the\ninvoked instance has no `$this` defined.\n\nWhen a function is called, the value of each argument passed to it is\nassigned to the corresponding parameter in that function's definition,\nif such a parameter exists. The assignment of argument values to\nparameters is defined in terms of simple ([§§](#simple-assignment)) or byRef assignment\n([§§](#byref-assignment)), depending on how the parameter was declared.  There may be\nmore arguments than parameters, in which case, the library functions\n[`func_num_args`](http://www.php.net/manual/en/function.func-num-args.php)\n(§xx), [`func_get_arg`](http://www.php.net/manual/en/function.func-get-arg.php)\n(§xx),\nand [`func_get_args`](http://www.php.net/manual/en/function.func-get-args.php)\n(§xx) can be used to get access to the complete argument list that was\npassed. If the number of arguments present in a function call is fewer\nthan the number of parameters defined for that function, any parameter\nnot having a corresponding argument is considered undefined if it has no\ndefault argument value ([§§](#function-definitions)); otherwise, it is considered defined with\nthat default argument value.\n\nIf an undefined variable is passed using byRef, that variable becomes\ndefined, with a default value of `NULL`.\n\nDirect and indirect recursive function calls are permitted.\n\nIf *postfix-expression* is a string, this is a variable function call\n([§§](#variable-functions)).\n\n**Examples**\n\n'''\nfunction square($v) { return $v * $v; } \nsquare(5)     // call square directly; it returns 25\n$funct = square;  // assigns the string \"square\" to $funct\n$funct(-2.3)    // call square indirectly; it returns 5.29\nstrlen($lastName) // returns the # of bytes in the string\n// -----------------------------------------\nfunction f1() { ... }  function f2() { ... }  function f3() { ... }  \nfor ($i = 1; $i <= 2; ++$i) { $f = 'f' . $i;  $f(); }\n// -----------------------------------------\nfunction f($p1, $p2, $p3, $p4, $p5) { ... }\nfunction g($p1, $p2, $p3, $p4, $p5) { ... }\nfunction h($p1, $p2, $p3, $p4, $p5) { ... }\n$funcTable = array(f, g, h);  // list of 3 function designators \n$i = 1;\n$funcTable[$i++]($i, ++$i, $i, $i = 12, --$i); // calls g(2,3,3,12,11)\n// -----------------------------------------\nfunction f4($p1, $p2 = 1.23, $p3 = \"abc\") { ... }\nf4(); // inside f4, $p1 is undefined, $p2 is 1.23, $p3 is \"abc\"\n// -----------------------------------------\nfunction f(&$p) { ... }\n$a = array(10, 20, 30);\nf($a[5]); // non-existent element going in, but element exists afterwards\n// -----------------------------------------\nfunction factorial($int)  // contains a recursive call\n{\n  return ($int > 1) ? $int * factorial($int - 1) : $int;\n}\n// -----------------------------------------\n$anon = function () { ... };  // store a Closure in $anon\n$anon();  // call the anonymous function encapsulated by that object\n'''\n\n## # Member-Selection Operator\n\n**Syntax**\n\n<pre>\n  <i>member-selection-expression:</i>\n    <i>postfix-expression</i>  ->  <i>member-selection-designator</i>\n\n  <i>member-selection-designator:</i>\n    <i>name</i>\n    <i>expression</i>\n</pre>\n\n*postfix-expression* is defined in [§§](#general-13); *name* is defined in\n[§§](#names); and *expression* is defined in [§§](#general-16).\n\n**Constraints**\n\n*postfix-expression* must designate an object or be `NULL`, `FALSE`, or an\nempty string. \n\n*name* must designate an instance property, or an instance or static\nmethod of *postfix-expression*'s class type.\n\n*expression* must be a value of type `string` (but not a string literal)\nthat contains the name of an instance property (**without** the\nleading `$`) or an instance or static method of that instance's class\ntype.\n\n**Semantics**\n\nA *member-selection-expression* designates an instance property or an\ninstance or static method of the object designated by\n*postfix-expression*. For a property, the value is that of the property,\nand is a modifiable lvalue if *postfix-expression* is a modifiable\nlvalue.\n\nWhen the `->` operator is used in a modifiable lvalue context and *name*\nor *expression* designate a property that is not visible, the property\nis treated as a dynamic property ([§§](#dynamic-members)). If *postfix-expression*'s class\ntype defines a `__set` method ([§§](#method-__set)), it is called to store the\nproperty's value. When the `->` operator is used in a non-lvalue context\nand *name* or *expression* designate a property that is not visible, the\nproperty is treated as a dynamic property. If *postfix-expression*'s\nclass type defines a `__get` method ([§§](#method-__get)), it is called to retrieve\nthe property's value.\n\nIf *postfix-expression* is `NULL`, `FALSE`, or an empty string, an expression\nof the form `$p->x = 10` causes an instance of `stdClass` ([§§](#class-stdclass)) to be\ncreated with a dynamic property x having a value of 10. `$p` is then made\nto refer to this instance.\n\n**Examples**\n\n```\nclass Point \n{\n  private $x;\n  private $y;\n  public function move($x, $y) \n  {\n    $this->x = $x;  // sets private property $x\n    $this->y = $y;  // sets private property $x\n  }\n  public function __toString() \n  {\n    return '(' . $this->x . ',' . $this->y . ')';\n  }     // get private properties $x and $y\n    public function __set($name, $value) { ... }\n    public function __get($name) { ... }\n}\n$p1 = new Point;\n$p1->move(3, 9);  // calls public instance method move by name\n$n = \"move\";\n$p1->$n(-2, 4);   // calls public instance method move by variable\n$p1->color = \"red\"; // turned into $p1->__set(\"color\", \"red\");\n$c = $p1->color;  // turned into $c = $p1->__get(\"color\");\n```\n\n## # Postfix Increment and Decrement Operators\n\n**Syntax**\n\n<pre>\n  <i>postfix-increment-expression:</i>\n    <i>unary-expression</i>  ++\n\n  <i>postfix-decrement-expression:</i>\n    <i>unary-expression</i>  --\n</pre>\n\n*unary-expression* is defined in [§§](#general-14).\n\n**Constraints**\n\nThe operand of the postfix ++ and -- operators must be a modifiable\nlvalue that has scalar type.\n\n**Semantics**\n\nThese operators behave like their prefix counterparts ([§§](#prefix-increment-and-decrement-operators)) except\nthat the value of a postfix ++ or -- expression is the value before any\nincrement or decrement takes place.\n\n**Examples**\n\n```\n$i = 10; $j = $i-- + 100;   // old value of $i (10) is added to 100\n$a = array(100, 200); $v = $a[1]++; // old value of $ia[1] (200) is assigned\n```\n\n## # Scope-Resolution Operator\n\n**Syntax**\n\n<pre>\n  <i>scope-resolution-expression:</i>\n    <i>scope-resolution-qualifier</i>  ::  <i>member-selection-designator</i>\n    <i>scope-resolution-qualifier</i>  ::  <i>class</i>\n\n  <i>scope-resolution-qualifier:</i>\n    <i>qualified-name</i>\n    <i>expression</i>\n    self\n    parent\n    static\n</pre>\n\n*member-selection-designator* is defined in [§§](#member-selection-operator).\n\n**Constraints**\n\n*qualified-name* must be the name of a class or interface type.\n\n*expression* must be a value of type string (but not a string literal)\nthat contains the name of a class or interface type.\n\n**Semantics**\n\nFrom inside or outside a class or interface, operator `::` allows the\nselection of a constant. From inside or outside a class, this operator\nallows the selection of a static property, static method, or instance\nmethod. From within a class, it also allows the selection of an\noverridden property or method. For a property, the value is that of the\nproperty, and is a modifiable lvalue if *member-selection-designator* is\na modifiable lvalue.\n\nFrom within a class, `self::m` refers to the member `m` in that class,\nwhereas `parent::m` refers to the closest member `m` in the base-class\nhierarchy, not including the current class. From within a method,\n`static::m` refers to the member `m` in the class that corresponds to the\nclass inheritance context in which the method is called. This allows\n*late static binding*. Consider the following scenario:\n\n```\nclass Base\n{\n  public function b()\n  {\n    static::f();  // calls the most appropriate f()\n  }\n  public function f() { ... }\n}\nclass Derived extends Base\n{\n  public function f() { ... }\n}\n$b1 = new Base;\n$b1->b(); // as $b1 is an instance of Base, Base::b() calls Base::f()\n$d1 = new Derived;\n$d1->b(); // as $d1 is an instance of Derived, Base::b() calls Derived::f()\n```\n\nThe value of the form of *scope-resolution-expression* ending in `::class`\nis a string containing the fully qualified name of the current class,\nwhich for a static qualifier, means the current class context.\n\n**Examples**\n\n```\nfinal class MathLibrary \n{\n  public static function sin() { ... }\n  ...\n}\n$v = MathLibrary::sin(2.34);  // call directly by class name\n$clName = 'MathLibrary';\n$v = $clName::sin(2.34);    // call indirectly via string\n// -----------------------------------------\nclass MyRangeException extends Exception \n{\n  public function __construct($message, ...)\n  {\n    parent::__construct($message);\n    ...\n  }\n  ...\n}\n// -----------------------------------------\nclass Point \n{\n  private static $pointCount = 0;\n  public static function getPointCount() \n  {\n    return self::$pointCount;\n  }\n  ...\n}\n```\n\n## # Exponentiation Operator\n\n**Syntax**\n\n<pre>\n  <i>exponentiation-expression:</i>\n    <i>expression  **  expression</i>\n</pre>\n\n*expression* is defined in [§§](#general-16).\n\n**Semantics**\n\nThe `**` operator produces the result of raising the value of the\nleft-hand operand to the power of the right-hand one. If either or both\noperands have non-numeric types, their values are converted to type `int`\nor `float`, as appropriate. If both operands have non-negative integer\nvalues and the result can be represented as an `int`, the result has type\n`int`; otherwise, the result has type `float`.\n\n**Examples**\n\n```\n2**3;   // int with value 8\n2**3.0;   // float with value 8.0\n\"2.0\"**\"3\"; // float with value 8.0\n```\n\n# # Unary Operators\n\n## # General\n\n**Syntax**\n\n<pre>\n  <i>unary-expression:</i>\n    <i>postfix-expression</i>\n    <i>prefix-increment-expression</i>\n    <i>prefix-decrement-expression</i>\n    <i>unary-op-expression</i>\n    <i>error-control-expression</i>\n    <i>shell-command-expression</i>\n    <i>cast-expression</i>\n    <i>variable-name-creation-expression</i>\n</pre>\n\n*postfix-expression* is defined in [§§](#general-13);\n*prefix-increment-expression* and *prefix-decrement-expression* are\ndefined in [§§](#prefix-increment-and-decrement-operators); *unary-op-expression* is defined in [§§](#unary-arithmetic-operators);\n*error-control-expression* is defined in [§§](#error-control-operator);\n*shell-command-expression* is defined in [§§](#shell-command-operator); *cast-expression* is\ndefined in [§§](#cast-operator) and *variable-name-creation-expression* is defined in\n[§§](#variable-name-creation-operator).\n\n**Semantics**\n\nThese operators associate right-to-left.\n\n## # Prefix Increment and Decrement Operators\n\n**Syntax**\n\n<pre>\n  <i>prefix-increment-expression:</i>\n    ++ <i>unary-expression</i>\n\n  <i>prefix-decrement-expression:</i>\n    -- <i>unary-expression</i>\n</pre>\n\n*unary-expression* is defined in [§§](#general-14).   \n\n**Constraints**\n\nThe operand of the prefix `++` or `--` operator must be a modifiable lvalue\nthat has scalar type.\n\n**Semantics**\n\n*Arithmetic Operands*\n\nFor a prefix `++` operator used with an arithmetic operand, the side\neffect ([§§](#general-10)) of the operator is to increment by 1, as appropriate, the\nvalue of the operand. The result is the value of the operand after it\nhas been incremented. If an int operand's value is the largest\nrepresentable for that type, the type and value of the result is\nimplementation-defined ([§§](#the-integer-type)).\n\nFor a prefix `--` operator used with an arithmetic operand, the side\neffect of the operator is to decrement by 1, as appropriate, the value\nof the operand. The result is the value of the operand after it has been\ndecremented. If an int operand's value is the smallest representable for\nthat type, the type and value of the result is implementation-defined\n([§§](#the-integer-type)).\n\nFor a prefix `++` or `--` operator used with an operand having the value\n`INF`, `-INF`, or `NAN`, there is no side effect, and the result is the\noperand's value.\n\n*Boolean Operands*\n\nFor a prefix `++` or `--` operator used with a Boolean-valued operand, there\nis no side effect, and the result is the operand's value.\n\n*NULL-valued Operands*\n\nFor a prefix -- operator used with a `NULL`-valued operand, there is no\nside effect, and the result is the operand's value. For a prefix `++`\noperator used with a `NULL`-valued operand, the side effect is that the\noperand's type is changed to int, the operand's value is set to zero,\nand that value is incremented by 1. The result is the value of the\noperand after it has been incremented.\n\n*String Operands*\n\nFor a prefix `--` operator used with an operand whose value is an empty\nstring, the side effect is that the operand's type is changed to `int`,\nthe operand's value is set to zero, and that value is decremented by 1.\nThe result is the value of the operand after it has been incremented.\n\nFor a prefix `++` operator used with an operand whose value is an empty\nstring, the side effect is that the operand's value is changed to the\nstring \"1\". The type of the operand is unchanged. The result is the new\nvalue of the operand.\n\nFor a prefix `--` or `++` operator used with a numeric string, the numeric\nstring is treated as the corresponding `int` or `float` value.\n\nFor a prefix `--` operator used with a non-numeric string-valued operand,\nthere is no side effect, and the result is the operand's value.\n\nFor a non-numeric string-valued operand that contains only alphanumeric\ncharacters, for a prefix `++` operator, the operand is considered to be a\npseudo-base-36 number (i.e., with digits 0–9 followed by A–Z or a–z) in\nwhich letter case is ignored for value purposes. The right-most digit is\nincremented by 1. For the digits 0–8, that means going to 1–9. For the\nletters \"A\"–\"Y\" (or \"a\"–\"y\"), that means going to \"B\"–\"Z\" (or \"b\"–\"z\").\nFor the digit 9, the digit becomes 0, and the carry is added to the next\nleft-most digit, and so on. For the digit \"Z\" (or \"z\"), the resulting\nstring has an extra digit \"A\" (or \"a\") appended. For example, when\nincrementing, \"a\" -> \"b\", \"X\" -> \"AA\", \"AA\" -> \"AB\", \"F29\" -> \"F30\", \"FZ9\" -> \"GA0\", and \"ZZ9\" -> \"AAA0\". A digit position containing a number wraps\nmodulo-10, while a digit position containing a letter wraps modulo-26.\n\nFor a non-numeric string-valued operand that contains any\nnon-alphanumeric characters, for a prefix `++` operator, all characters up\nto and including the right-most non-alphanumeric character is passed\nthrough to the resulting string, unchanged. Characters to the right of\nthat right-most non-alphanumeric character are treated like a\nnon-numeric string-valued operand that contains only alphanumeric\ncharacters, except that the resulting string will not be extended.\nInstead, a digit position containing a number wraps modulo-10, while a\ndigit position containing a letter wraps modulo-26.\n\n**Examples**\n\n```\n$i = 10; $j = --$i + 100;   // new value of $i (9) is added to 100\n$a = array(100, 200); $v = ++$a[1]; // new value of $ia[1] (201) is assigned\n```\n\n## # Unary Arithmetic Operators\n\n**Syntax**\n\n<pre>\n  <i>unary-op-expression:</i>\n    <i>unary-operator cast-expression</i>\n\n  <i>unary-operator: one of</i>\n    +  -  !  \\\n</pre>\n\n*cast-expression* is defined in [§§](#cast-operator).   \n\n**Constraints**\n\nThe operand of the unary `+`, unary `-`, and unary `!` operators must have\nscalar type.\n\nThe operand of the unary `~` operator must have arithmetic type.\n\n**Semantics**\n\n*Arithmetic Operands*\n\nFor a unary `+` operator used with an arithmetic operand, the type and\nvalue of the result is the type and value of the operand. \n\nFor a unary `-` operator used with an arithmetic operand, the value of the\nresult is the negated value of the operand. However, if an int operand's\noriginal value is the smallest representable for that type, the type and\nvalue of the result is implementation-defined ([§§](#the-integer-type)).\n\nFor a unary `!` operator used with an arithmetic operand, the type of the\nresult is `bool`. The value of the result is `TRUE` if the value of the\noperand is non-zero; otherwise, the value of the result is `FALSE`. For\nthe purposes of this operator, `NAN` is considered a non-zero value. The\nexpression `!E` is equivalent to `(E == 0)`.\n\nFor a unary `~` operator used with an `int` operand, the type of the result\nis `int`. The value of the result is the bitwise complement of the value\nof the operand (that is, each bit in the result is set if and only if\nthe corresponding bit in the operand is clear). For a unary `~` operator\nused with a `float` operand, the value of the operand is first converted\nto `int` before the bitwise complement is computed.\n\n*Boolean Operands*\n\nFor a unary `+` operator used with a `TRUE`-valued operand, the value of the\nresult is 1 and the type is `int`. When used with a `FALSE`-valued operand,\nthe value of the result is zero and the type is `int`.\n\nFor a unary `-` operator used with a `TRUE`-valued operand, the value of the\nresult is -1 and the type is `int`. When used with a `FALSE`-valued operand,\nthe value of the result is zero and the type is `int`.\n\nFor a unary `!` operator used with a `TRUE`-valued operand, the value of the\nresult is `FALSE` and the type is `bool`. When used with a `FALSE`-valued\noperand, the value of the result is `TRUE` and the type is `bool`.\n\n*NULL-valued Operands*\n\nFor a unary `+` or unary `-` operator used with a `NULL`-valued operand, the\nvalue of the result is zero and the type is `int`.\n\nFor a unary `!` operator used with a `NULL`-valued operand, the value of the\nresult is `TRUE` and the type is `bool`.\n\n*String Operands*\n\nFor a unary `+` or `-` operator used with a numeric string or a\nleading-numeric string, the string is first converted to an `int` or\n`float`, as appropriate, after which it is handled as an arithmetic\noperand. The trailing non-numeric characters in leading-numeric strings\nare ignored. With a non-numeric string, the result has type `int` and\nvalue 0.\n\nFor a unary `!` operator used with a string, the string is first converted\nto `bool`, after which its value is negated.\n\n**Examples**\n\n```\n$v = +10;\nif ($v1 > -5) ...\n$t = TRUE;\nif (!$t) ...\n$v = ~0b1010101;\n```\n\n## # Error Control Operator\n\n**Syntax**\n\n<pre>\n  <i>error-control-expression:</i>\n    @   <i>expression</i>\n</pre>\n\n*expression* is defined in [§§](#general-16).   \n\n**Semantics**\n\nOperator `@` supresses any error messages generated by the evaluation of\n*expression*.\n\nIf a custom error-handler has been established using the library\nfunction [`set_error_handler` (§xx), that\nhandler](http://us3.php.net/manual/en/function.set-error-handler.php)is\nstill called.\n\n**Examples**\n\n```\n$infile = @fopen(\"NoSuchFile.txt\", 'r');\n```\n\nOn open failure, the value returned by `fopen` is `FALSE`, which is\nsufficient to know to handle the error. There is no need to have any\nerror message displayed.\n\n**Implementation Notes**\n\nGiven the following example:\n\n```\nfunction f() {\n  $ret = $y;\n  return $ret;\n}\n\n$x = @f();  // without @, get \"Undefined variable: y\"\n```\n\nThe following code shows how this statement is handled:\n\n```\n$origER = error_reporting();\nerror_reporting(0);\n$tmp = f();\n$curER = error_reporting();\nif ($curER === 0) error_reporting($origER);\n$x = $tmp;\n```\n\n## # Shell Command Operator\n\n**Syntax**\n\n<pre>\n  <i>shell-command-expression:</i>\n    `  <i>dq-char-sequence<sub>opt</sub></i>  `\n</pre>\n\nwhere \\` is the GRAVE ACCENT character U+0060, commonly referred to as a\n*backtick*.\n\n*dq-char-sequence* is described in [§§](#double-quoted-string-literals).\n\n**Semantics**\n\nThis operator passes *dq-char-sequence* to the command shell for\nexecution, as though it was being passed to the library function\n`shell_exec` (§xx). If the output from execution of that command is\nwritten to `STDOUT` ([§§](#resource-types)), that output is the result of this operator\nas a string. If the output is redirected away from `STDOUT`, or\n*dq-char-sequence* is empty or contains only white space, the result of\nthe operator is `NULL`.\n\nIf [`shell_exec`](http://www.php.net/manual/en/function.shell-exec.php)\n(§xx) is disabled, this operator is disabled.\n\n**Examples**\n\n```\n$result = `ls`;           // result is the output of command ls\n$result = `ls >dirlist.txt`;  // result is NULL\n$d = \"dir\"; $f = \"*.*\";\n$result = `$d {$f}`;      // result is the output of command dir *.*\n```\n\n## # Cast Operator\n\n**Syntax**\n\n<pre>\n  <i>cast-expression:</i>\n    <i>unary-expression</i>\n    (  <i>cast-type</i>  ) <i>cast-expression</i>\n\n  <i>cast-type: one of</i>\n    array  binary  bool  boolean  double  int  integer  float  object\n    real  string  unset\n</pre>\n\n*unary-expression* is defined in [§§](#general-14).   \n\n**Constraints**\n\nFor *binary*, *cast-expression* must designate a string.\n\n**Semantics**\n\nWith the exception of the *cast-type*s unset and binary (see below), the\nvalue of the operand *cast-expression* is converted to the type\nspecified by *cast-type*, and that is the type and value of the result.\nThis construct is referred to a *cast,* and is used as the verb, \"to\ncast\". If no conversion is involved, the type and value of the result\nare the same as those of *cast-expression*.\n\nA cast can result in a loss of information.\n\nA *cast-type* of `array` results in a conversion to type array. See [§§](#converting-to-array-type)\nfor details.\n\nA *cast-type* of `binary` is reserved for future use in dealing with\nso-called *binary strings*. Casting a string to binary results in the\nsame string.\n\nA *cast-type* of `bool` or `boolean` results in a conversion to type `bool`.\nSee [§§](#converting-to-boolean-type) for details.\n\nA *cast-type* of `int` or `integer` results in a conversion to type `int`. See [§§](#converting-to-integer-type) for details.\n\nA *cast-type* of `float`, `double`, or `real` results in a conversion to type `float`. See [§§](#converting-to-floating-point-type) for details.\n\nA *cast-type* of `object` results in a conversion to type `object`. See [§§](#converting-to-object-type)\nfor details.\n\nA *cast-type* of `string` results in a conversion to type `string`. See [§§](#converting-to-string-type)\nfor details.\n\nA *cast-type* of `unset` always results in a value of `NULL`. (This use of\n`unset` should not be confused with the `unset` intrinsic ([§§](#unset)).)\n\n**Examples**\n\n```\n(int)(10/3)          // results in the int 3 rather than the float 3.333...\n(array)(16.5)      // results in an array of 1 float; [0] = 16.5\n(int)(float)\"123.87E3\" // results in the int 123870\n```\n\n## # Variable-Name Creation Operator\n\n**Syntax**\n\n<pre>\n  <i>variable-name-creation-expression:</i>\n    $   <i>expression</i>\n    $  {  <i>expression</i>  }\n</pre>\n\n*expression* is defined in [§§](#general-16).\n\n**Constraints**\n\nIn the non-brace form, *expression* must be a\n*variable-name-creation-expression* or a *variable-name* that designates\na scalar value.\n\nIn the brace form, *expression* must be a\n*variable-name-creation-expression* or an expression that designates a\nscalar value.\n\n**Semantics**\n\nThe result of this operator is a variable name spelled using the textual\nrepresentation of the value of *expression* even though such a name\nmight not be permitted as a variable-name ([§§](#names)) source code token.\n\nThis specification documents existing practice rather than ideal\nlanguage design, and **there is one aspect of this operator that behaves\nin a manner that violates the precedence rules**. Consider `o` to be an\nobject of some class that has an instance property called `pr`. How is the\nnon-brace-form expression `$$o->pr` handled with respect to precedence?\nAs the operator `->` has higher precedence, the answer would seem to be,\n\"`->` wins over `$`\"; however, that is not the case. In fact, the\nexpression is treated as `${$o}->pr`.\n\n**Examples**\n\n```\n$color = \"red\";\n$$color = 123;    // equivalent to $red = 123\n// -----------------------------------------\n$x = 'ab'; $ab = 'fg'; $fg = 'xy';\n$$ $ $x = 'Hello';  // equivalent to $xy = Hello\n// -----------------------------------------\n$v1 = 3;\n$$v1 = 22;        // equivalent to ${3} = 22\n$v2 = 9.543;\n$$v2 = TRUE;    // equivalent to ${9.543} = TRUE\n$v3 = NULL;\n$$v3 = \"abc\";   // equivalent to ${NULL} = \"abc\"\n// -----------------------------------------\nfunction f1 () { return 2.5; }\n${1 + f1()} = 1000;   // equivalent to ${3.5} = 1000\n// -----------------------------------------\n$v = array(10, 20); $a = 'v';\n$$a[0] = 5;       // [] has higher precedence than $\n$v = array(10, 20); $a = 'v';\n${$a[0]} = 5;   // equivalent to above\n$v = array(10, 20); $a = 'v';\n${$a}[0] = 5;   // $ gets first shot at $a\n```\n\n# # `instanceof` Operator\n\n**Syntax**\n\n<pre>\n  <i>instanceof-expression:</i>\n    <i>unary-expression</i>\n    <i>instanceof-subject</i>  instanceof   <i>instanceof-type-designator</i>\n\n  <i>instanceof-subject:</i>\n    <i>expression</i>\n\n  <i>instanceof-type-designator:</i>\n    <i>qualified-name</i>\n    <i>expression</i>\n</pre>\n\n*unary-expression* is defined in [§§](#general-14); *expression* is defined in\n[§§](#general-16); and *qualified-name* is defined in [§§](#names). \n\n**Constraints**\n\nThe *expression* in *instanceof-subject* must designate a variable.\n\nThe *expression* in *instanceof-type-designator* must not be any form of\nliteral.\n\n*qualified-name* must be the name of a class or interface type.\n\n**Semantics**\n\nOperator `instanceof` returns `TRUE` if the variable designated by\n*expression* in *instanceof-subject* is an object having type\n*qualified-name*, is an object whose type is derived from type\n*qualified-name*, or is an object whose type implements interface\n*qualified-name*. Otherwise, it returns `FALSE`. When the *expression*\nform of *instanceof-type-designator* is used, *expression* may be a\nstring that contains a class or interface name. Alternatively,\n*expression* can designate an instance variable, in which case, operator\n`instanceof` returns `TRUE` if the variable designated by the left-hand\n*expression* is an instance of the\n[`class`](http://www.php.net/manual/en/language.oop5.basic.php#language.oop5.basic.class)\ntype, or of a derived type, of the right-hand *expression*.\n\nIf either *expression* is not an instance, `FALSE` is returned.\n\nNote: This operator supersedes the library function `is_a` (§xx), which\nhas been deprecated. \n\n**Examples**\n\n```\nclass C1 { ... } $c1 = new C1;\nclass C2 { ... } $c2 = new C2;\nclass D extends C1 { ... } $d = new D;\n$d instanceof C1      // TRUE\n$d instanceof C2      // FALSE\n$d instanceof D       // TRUE\n// -----------------------------------------\ninterface I1 { ... }\ninterface I2 { ... }\nclass E1 implements I1, I2 { ... }\n$e1 = new E1;\n$e1 instanceof I1       // TRUE\n$iName = \"I2\";\n$e1 instanceof $iName     // TRUE\n```\n\n# # Multiplicative Operators\n\n**Syntax**\n\n<pre>\n  <i>multiplicative-expression:</i>\n    <i>instanceof-expression</i>\n    <i>multiplicative-expression</i>  *  <i>multiplicative-expression</i>\n    <i>multiplicative-expression</i>  /  <i>multiplicative-expression</i>\n    <i>multiplicative-expression</i>  %  <i>multiplicative-expression</i>\n</pre>\n\n*instanceof-expression* is defined in [§§](#instanceof-operator). \n\n**Constraints**\n\nThe right-hand operand of operator `/` and operator `%` must not be zero.\n\n**Semantics**\n\nThe binary `*` operator produces the product of its operands. If either\nor both operands have non-numeric types, their values are converted to\ntype `int` or `float`, as appropriate. Then if either operand has type\n`float`, the other is converted to that type, and the result has type\n`float`. Otherwise, both operands have type `int`, in which case, if the\nresulting value can be represented in type `int` that is the result type.\nOtherwise, the type and value of the result is implementation-defined\n([§§](#the-integer-type)).\n\nDivision by zero results in a diagnostic followed by a `bool` result\nhaving value `FALSE`. (The values +/- infinity and NaN cannot be generated\nvia this operator; instead, use the predefined constants `INF` and `NAN`.)\n\nThe binary `/` operator produces the quotient from dividing the left-hand\noperand by the right-hand one. If either or both operands have\nnon-numeric types, their values are converted to type `int` or `float`, as\nappropriate. Then if either operand has type `float`, the other is\nconverted to that type, and the result has type `float`. Otherwise, both\noperands have type `int`, in which case, if the mathematical value of the\ncomputation can be preserved using type `int`, that is the result type;\notherwise, the type of the result is `float`.\n\nThe binary `%` operator produces the remainder from dividing the left-hand\noperand by the right-hand one. If the type of both operands is not `int`,\ntheir values are converted to that type. The result has type `int`.\n\nThese operators associate left-to-right.\n\n**Examples**\n\n```\n-10 * 100;       // int with value -1000\n100 * -3.4e10;   // float with value -3400000000000\n\"123\" * \"2e+5;   // float with value 24600000\n100 / 100;       // int with value 1\n100  / \"123\";    // float with value 0.8130081300813\n\"123\" % 100;     // int with value 23\n```\n\n# # Additive Operators\n\n**Syntax**\n\n<pre>\n  <i>additive-expression:</i>\n    <i>multiplicative-expression</i>\n    <i>additive-expression</i>  +  <i>multiplicative-expression</i>\n    <i>additive-expression</i>  -  <i>multiplicative-expression</i>\n    <i>additive-expression</i>  .  <i>multiplicative-expression</i>\n</pre>\n\n*multiplicative-expression* is defined in [§§](#multiplicative-operators). \n\n**Constraints**\n\nIf either operand has array type, the other operand must also have array\ntype.\n\n**Semantics**\n\nFor non-array operands, the binary `+` operator produces the sum of those\noperands, while the binary `- `operator produces the difference of its\noperands when subtracting the right-hand operand from the left-hand one.\nIf either or both operands have non-array, non-numeric types, their\nvalues are converted to type `int` or `float`, as appropriate. Then if\neither operand has type `float`, the other is converted to that type, and\nthe result has type `float`. Otherwise, both operands have type `int`, in\nwhich case, if the resulting value can be represented in type `int` that\nis the result type. Otherwise, the type and value of the result is\nimplementation-defined ([§§](#the-integer-type)).\n\nIf both operands have array type, the binary `+` operator produces a new\narray that is the union of the two operands. The result is a copy of the\nleft-hand array with elements inserted at its end, in order, for each\nelement in the right-hand array whose key does not already exist in the\nleft-hand array. Any element in the right-hand array whose key exists in\nthe left-hand array is ignored.\n\nThe binary `.` operator creates a string that is the concatenation of the\nleft-hand operand and the right-hand operand, in that order. If either\nor both operands have types other than `string`, their values are\nconverted to type `string`. The result has type `string`.\n\nThese operators associate left-to-right.\n\n**Examples**\n\n```\n-10 + 100;        // int with value 90\n100 + -3.4e10;    // float with value -33999999900\n\"123\" + \"2e+5\";   // float with value 200123\n100 - \"123\";      // int with value 23\n-3.4e10 - \"abc\";  // float with value -34000000000\n// -----------------------------------------\n[1, 5 => FALSE, \"red\"] + [4 => -5, 1.23]; // [1, 5 => FALSE, \"red\", 4 => -5]\n  // dupe key 5 (value 1.23) is ignored\n[NULL] + [1, 5 => FALSE, \"red\"];          // [NULL, 5 => FALSE, \"red\"]\n  // dupe key 0 (value 1) is ignored\n[4 => -5, 1.23] + [NULL];                 // [4 => -5, 1.23, 0 => NULL]\n// -----------------------------------------\n-10 . NAN;        // string with value \"-10NAN\"\nINF . \"2e+5\";     // string with value \"INF2e+5\"\nTRUE . NULL;      // string with value \"1\"\n10 + 5 . 12 . 100 - 50;  // int with value 1512050; ((((10 + 5).12).100)-50)\n```\n\n# # Bitwise Shift Operators\n\n**Syntax**\n\n<pre>\n  <i>shift-expression:</i>\n    <i>additive-expression</i>\n    <i>shift-expression</i>  <<  <i>additive-expression</i>\n    <i>shift-expression</i>  >>  <i>additive-expression</i>\n</pre>\n\n*additive-expression* is defined in [§§](#additive-operators). \n\n**Constraints**\n\nEach of the operands must have scalar type.\n\n**Semantics**\n\nGiven the expression `e1 << e2`, the bits in the value of `e1` are shifted\nleft by `e2` positions. Bits shifted off the left end are discarded, and\nzero bits are shifted on from the right end. Given the expression\n`e1 >> e2`, the bits in the value of `e1` are shifted right by\n`e2` positions. Bits shifted off the right end are discarded, and the sign\nbit is propagated from the left end. \n\nIf either operand does not have type `int`, its value is first converted\nto that type.\n\nThe type of the result is `int`, and the value of the result is that after\nthe shifting is complete. The values of `e1` and `e2` are unchanged.\n\nIf the shift count is negative, the actual shift applied is `n -\n(-shift count % n)`, where `n` is the number of bits per `int`. If the\nshift count is greater than the number of bits in an `int`, the actual\nshift applied is shift count `% n`.\n\nThese operators associate left-to-right.\n\n**Examples**\n\n```\n1000 >> 2   // 3E8 is shifted right 2 places\n-1000 << 2      // FFFFFC18 is shifted left 5 places\n123 >> 128      // adjusted shift count = 0\n123 << 33   // For a 32-bit int, adjusted shift count = 1; otherwise, 33\n```\n\n# # Relational Operators\n\n**Syntax**\n\n<pre>\n  <i>relational-expression:</i>\n    <i>shift-expression</i>\n    <i>relational-expression</i>  <   <i>shift-expression</i>\n    <i>relational-expression</i>  >   <i>shift-expression</i>\n    <i>relational-expression</i>  <=  <i>shift-expression</i>\n    <i>relational-expression</i>  >=  <i>shift-expression</i>\n</pre>\n\n*shift-expression* is defined in [§§](#bitwise-shift-operators). \n\n**Semantics**\n\nOperator `<` represents *less-than*, operator `>` represents\n*greater-than*, operator `<=` represents *less-than-or-equal-to*, and\noperator `>=` represents *greater-than-or-equal-to*.\n\nThe type of the result is `bool`. \n\nThe operands are processed using the following steps, in order:\n\n1.  If either operand has the value `NULL`, then if the other operand has\n    type string, the `NULL` is converted to the empty string (\"\");\n    otherwise, the `NULL` is converted to type `bool`.\n2.  If both operands are non-numeric strings or one is a numeric string\n    and the other a leading-numeric string, the result is the lexical\n    comparison of the two operands. Specifically, the strings are\n    compared byte-by-byte starting with their first byte. If the two\n    bytes compare equal and there are no more bytes in either string,\n    the strings are equal and the comparison ends; otherwise, if this is\n    the final byte in one string, the shorter string compares less-than\n    the longer string and the comparison ends. If the two bytes compare\n    unequal, the string having the lower-valued byte compares less-than\n    the other string, and the comparison ends. If there are more bytes\n    in the strings, the process is repeated for the next pair of bytes.\n3.  If either operand has type `bool`, the other operand is converted to\n    that type. The result is the logical comparison of the two operands\n    after conversion, where `FALSE` is defined to be less than `TRUE`.\n4.  If the operands both have arithmetic type, string type, or are\n    resources, they are converted to the corresponding arithmetic type\n    ([§§](#converting-to-integer-type) and [§§](#converting-to-floating-point-type)). The result is the numerical comparison of the two\n    operands after conversion.\n5.  If both operands have array type, if the arrays have different\n    numbers of elements, the one with the fewer is considered less-than\n    the other one—regardless of the keys and values in each—, and the\n    comparison ends. For arrays having the same numbers of elements, if\n    the next key in the left-hand operand exists in the right-hand\n    operand, the corresponding values are compared. If they are unequal,\n    the array containing the lesser value is considered less-than the\n    other one, and the comparison ends; otherwise, the process is\n    repeated with the next element. If the next key in the left-hand\n    operand does not exist in the right-hand operand, the arrays cannot\n    be compared and `FALSE` is returned. For array comparison, the order\n    of insertion of the elements into those arrays is irrelevant.\n6.  If only one operand has object type, that compares greater-than any\n    other operand type.\n7.  If only one operand has array type, that compares greater-than any\n    other operand type.\n8.  If the operands have different object types, the result is always\n    `FALSE`.\n9.  If the operands have the same object type, the result is determined\n    by comparing the lexically first-declared instance property in each\n    object. If those properties have object type, the comparison is\n    applied recursively.\n\nThese operators associate left-to-right.\n\n**Examples**\n\n```\n\"\" < \"ab\"       // result has value TRUE\n\"a\" > \"A\"       // result has value TRUE\n\"a0\" < \"ab\"     // result has value TRUE\n\"aA <= \"abc\"    // result has value TRUE\n// -----------------------------------------\nNULL < [10,2.3] // result has value TRUE\nTRUE > -3.4     // result has value FALSE\nTRUE < -3.4     // result has value FALSE\nTRUE >= -3.4    // result has value TRUE\nFALSE < \"abc\"   // result has value TRUE\n// -----------------------------------------\n10 <= 0         // result has value FALSE\n10 >= \"-3.4\"    // result has value TRUE\n\"-5.1\" > 0      // result has value FALSE\n// -----------------------------------------\n[100] < [10,20,30] // result has value TRUE (LHS array is shorter)\n[10,20] >= [\"red\"=>0,\"green\"=>0] // result has value FALSE, (key 10 does not exists in RHS)\n[\"red\"=>0,\"green\"=>0] >= [\"green\"=>0,\"red\"=>0] // result has value TRUE (order is irrelevant)\n```\n\n# # Equality Operators\n\n**Syntax**\n\n<pre>\n  <i>equality-expression:</i>\n    <i>relational-expression</i>\n    <i>equality-expression</i>  ==  <i>relational-expression</i>\n    <i>equality-expression</i>  !=  <i>relational-expression</i>\n    <i>equality-expression</i>  <>  <i>relational-expression</i>\n    <i>equality-expression</i>  ===  <i>relational-expression</i>\n    <i>equality-expression</i>  !==  <i>relational-expression</i>\n</pre>\n\n*relational-expression* is defined in [§§](#relational-operators). \n\n**Semantics**\n\nOperator `==` represents *value-equality*, operators `!=` and `<>` are\nequivalent and represent *value-inequality*, operator `===` represents\n*same-type-and-value-equality*, and operator `!==` represents\n*not-same-type-and-value-equality*. However, when comparing two objects,\noperator `===` represents *identity* and operator `!==` represents\n*non-identity*. Specifically, in this context, these operators check to\nsee if the two operands are the exact same object, not two different\nobjects of the same type and value.\n\nThe type of the result is `bool`. \n\nThe operands are processed using the following steps, in order:\n\n1.  For operators `==`, `!=`, and `<>`, if either operand has the value\n    `NULL`, then if the other operand has type string, the `NULL` is\n    converted to the empty string (\"\"); otherwise, the `NULL` is converted\n    to type bool.\n2.  If both operands are non-numeric strings or one is a numeric string\n    and the other a leading-numeric string, the result is the lexical\n    comparison of the two operands. Specifically, the strings are\n    compared byte-by-byte starting with their first byte. If the two\n    bytes compare equal and there are no more bytes in either string,\n    the strings are equal and the comparison ends; otherwise, if this is\n    the final byte in one string, the shorter string compares less-than\n    the longer string and the comparison ends. If the two bytes compare\n    unequal, the string having the lower-valued byte compares less-than\n    the other string, and the comparison ends. If there are more bytes\n    in the strings, the process is repeated for the next pair of bytes.\n3.  If either operand has type bool, for operators `==`, `!=`, and `<>`, the\n    other operand is converted to that type. The result is the logical\n    comparison of the two operands after any conversion, where `FALSE` is\n    defined to be less than `TRUE`.\n4.  If the operands both have arithmetic type, string type, or are\n    resources, for operators `==`, `!=`, and `<>`, they are converted to the\n    corresponding arithmetic type ([§§](#converting-to-integer-type) and [§§](#converting-to-floating-point-type)). The result is the\n    numerical comparison of the two operands after any conversion.\n5.  If both operands have array type, for operators `==`, `!=`, and `<>`,\n    the arrays are equal if they have the same set of key/value pairs,\n    after element type conversion, without regard to the order of\n    insertion of their elements. For operators `===` and `!==` the arrays\n    are equal if they have the same set of key/value pairs, the\n    corresponding values have the same type, and the order of insertion\n    of their elements are the same.\n6.  If only one operand has object type, the two operands are never\n    equal.\n7.  If only one operand has array type, the two operands are never\n    equal.\n8.  If the operands have different object types, the two operands are\n    never equal.\n9.  If the operands have the same object type, the two operands are\n    equal if the instance properties in each object have the same\n    values. Otherwise, the objects are unequal. The instance properties\n    are compared, one at a time, in the lexical order of their\n    declaration. For properties that have object type, the comparison is\n    applied recursively.\n\nThese operators associate left-to-right.\n\n**Examples**\n\n```\n\"a\" <> \"aa\" // result has value TRUE\n// -----------------------------------------\nNULL == 0   // result has value TRUE\nNULL === 0  // result has value FALSE\nTRUE != 100  // result has value FALSE\nTRUE !== 100  // result has value TRUE\n// -----------------------------------------\n\"10\" != 10  // result has value FALSE\n\"10\" !== 10 // result has value TRUE\n// -----------------------------------------\n[10,20] == [10,20.0]  // result has value TRUE\n[10,20] === [10,20.0] // result has value FALSE\n[\"red\"=>0,\"green\"=>0] === [\"red\"=>0,\"green\"=>0] // result has value TRUE\n[\"red\"=>0,\"green\"=>0] === [\"green\"=>0,\"red\"=>0] // result has value FALSE\n```\n\n# # Bitwise AND Operator\n\n**Syntax**\n\n<pre>\n  <i>bitwise-AND-expression:</i>\n    <i>equality-expression</i>\n    <i>bit-wise-AND-expression</i>  &  <i>equality-expression</i>\n</pre>\n\n*equality-expression* is defined in [§§](#equality-operators). \n\n**Constraints**\n\nEach of the operands must have scalar type.\n\n**Semantics**\n\nIf either operand does not have type `int`, its value is first converted\nto that type.\n\nThe result of this operator is the bitwise-AND of the two operands, and\nthe type of that result is `int`.\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```\n0b101111 & 0b101          // 0b101\n$lLetter = 0x73;          // letter 's'\n$uLetter = $lLetter & ~0x20;  // clear the 6th bit to make letter 'S'\n```\n\n# # Bitwise Exclusive OR Operator\n\n**Syntax**\n\n<pre>\n  <i>bitwise-exc-OR-expression:</i>\n    <i>bitwise-AND-expression</i>\n    <i>bitwise-exc-OR-expression</i>  ^   <i>bitwise-AND-expression</i>\n</pre>\n\n*bitwise-AND-expression* is defined in [§§](#bitwise-and-operator). \n\n**Constraints**\n\nEach of the operands must have scalar type.\n\n**Semantics**\n\nIf either operand does not have type `int`, its value is first converted\nto that type.\n\nThe result of this operator is the bitwise exclusive-OR of the two\noperands, and the type of that result is `int`.\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```\n0b101111 | 0b101    // 0b101010\n$v1 = 1234; $v2 = -987; // swap two integers having different values\n$v1 = $v1 ^ $v2;\n$v2 = $v1 ^ $v2;\n$v1 = $v1 ^ $v2;    // $v1 is now -987, and $v2 is now 1234\n```\n\n# # Bitwise Inclusive OR Operator\n\n**Syntax**\n\n<pre>\n  <i>bitwise-inc-OR-expression:</i>\n    <i>bitwise-exc-OR-expression</i>\n    <i>bitwise-inc-OR-expression</i>  |  <i>bitwise-exc-OR-expression</i>\n</pre>\n\n*bitwise-exc-OR-expression* is defined in [§§](#bitwise-exclusive-or-operator). \n\n**Constraints**\n\nEach of the operands must have scalar type.\n\n**Semantics**\n\nIf either operand does not have type `int`, its value is first converted\nto that type.\n\nThe result of this operator is the bitwise inclusive-OR of the two\noperands, and the type of that result is `int`.\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```\n0b101111 | 0b101      // 0b101111\n$uLetter = 0x41;      // letter 'A'\n$lLetter = $upCaseLetter | 0x20;  // set the 6th bit to make letter 'a'\n```\n\n# # Logical AND Operator (form 1)\n\n**Syntax**\n\n<pre>\n  <i>logical-AND-expression-1:</i>\n    <i>bitwise-incl-OR-expression</i>\n    <i>logical-AND-expression-1</i>  &&  <i>bitwise-inc-OR-expression</i>\n</pre>\n\n*bitwise-incl-OR-expression* is defined in [§§](#bitwise-inclusive-or-operator). \n\n**Constraints**\n\nEach of the operands must have scalar type.\n\n**Semantics**\n\nIf either operand does not have type bool, its value is first converted\nto that type.\n\nGiven the expression `e1 && e2, e1` is evaluated first. If `e1` is `FALSE`, `e2` is not evaluated, and the result has type `bool`, value `FALSE`. Otherwise, `e2` is evaluated. If `e2` is `FALSE`, the result has type bool, value `FALSE`; otherwise, it has type `bool`, value `TRUE`. There is a sequence point after the evaluation of `e1`.\n\nThis operator associates left-to-right.\n\nExcept for the difference in precedence, operator `&&` has exactly the\nsame semantics as operator `and` ([§§](#logical-and-operator-form-2)).\n\n**Examples**\n\n```\nif ($month > 1 && $month <= 12) ...\n```\n\n# # Logical Inclusive OR Operator (form 1)\n\n**Syntax**\n\n<pre>\n  <i>logical-inc-OR-expression-1:</i>\n    <i>logical-AND-expression-1</i>\n    <i>logical-inc-OR-expression-1</i>  ||  <i>logical-AND-expression-1</i>\n</pre>\n\n*logical-exc-OR-expression* is defined in [§§](#bitwise-exclusive-or-operator). \n\n**Constraints**\n\nEach of the operands must have scalar type.\n\n**Semantics**\n\nIf either operand does not have type bool, its value is first converted\nto that type.\n\nGiven the expression `e1 || e2`, `e1` is evaluated first. If `e1` is TRUE, `e2` is not evaluated, and the result has type `bool`, value `TRUE`. Otherwise, `e2` is evaluated. If `e2` is `TRUE`, the result has type `bool`, value `TRUE`; otherwise, it has type `bool`, value `FALSE`. There is a sequence point after the evaluation of `e1`.\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```\nif ($month < 1 || $month > 12) ...\n```\n\n# # Conditional Operator\n\n**Syntax**\n\n<pre>\n  <i>conditional-expression:</i>\n    <i>logical-inc-OR-expression-1</i>\n    <i>logical-inc-OR-expression-1</i>  ?  <i>expression<sub>opt</sub></i>  :  <i>conditional-expression</i>\n</pre>\n\n*logical-OR-expression* is defined in [§§](#logical-inclusive-or-operator-form-1); and *expression* is\ndefined in [§§](#general-16).\n\n**Constraints**\n\nThe first operand must have scalar type.\n\n**Semantics**\n\nGiven the expression `e1 ? e2 : e3`, if `e1` is `TRUE`, then and only then is `e2` evaluated, and the result and its type become the result and type of\nthe whole expression. Otherwise, then and only then is `e3` evaluated, and\nthe result and its type become the result and type of the whole\nexpression. There is a sequence point after the evaluation of `e1`. If `e2`\nis omitted, the result and type of the whole expression is the value and\ntype of `e1` when it was tested.\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```\nfor ($i = -5; $i <= 5; ++$i)\n  echo \"$i is \".(($i & 1 == TRUE) ? \"odd\\n\" : \"even\\n\");\n// -----------------------------------------\n$a = 10 ? : \"Hello\";  // result is int with value 10\n$a = 0 ? : \"Hello\";     // result is string with value \"Hello\"\n$i = PHP_INT_MAX;\n$a = $i++ ? : \"red\";  // result is int with value 2147483647 (on a 32-bit \n                // system) even though $i is now the float 2147483648.0\n// -----------------------------------------\n$i++ ? f($i) : f(++$i); // the sequence point makes this well-defined\n// -----------------------------------------\nfunction factorial($int)\n{\n  return ($int > 1) ? $int * factorial($int - 1) : $int;\n}\n```\n\n# # Assignment Operators\n\n## # General\n\n**Syntax**\n\n<pre>\n  <i>assignment-expression:</i>\n    <i>conditional-expression</i>\n    <i>simple-assignment-expression</i>\n    <i>byref-assignment-expression</i>\n    <i>compound-assignment-expression</i>\n</pre>\n\n*conditional-expression* is defined in [§§](#conditional-operator);\n*simple-assignment-expression* is defined in [§§](#simple-assignment);\n*byref-assignment-expression* is defined in [§§](#byref-assignment); and\n*compound-assignment-expression* is defined in [§§](#compound-assignment).\n\n**Constraints**\n\nThe left-hand operand of an assignment operator must be a modifiable\nlvalue.\n\n**Semantics**\n\nThese operators associate right-to-left.\n\n## # Simple Assignment\n\n**Syntax**\n\n<pre>\n  <i>simple-assignment-expression:</i>\n    <i>unary-expression</i>  =  <i>assignment-expression</i>\n</pre>\n\n*unary-expression* is defined in [§§](#general-14); *assignment-expression* is\ndefined in [§§](#general-15).\n\n**Constraints**\n\nIf the location designated by the left-hand operand is a string element,\nthe key must not be a negative-valued `int`, and the right-hand operand\nmust have type `string`.\n\n**Semantics**\n\nIf *assignment-expression* designates an expression having value type,\nsee [§§](#value-assignment-of-object-and-resource-types-to-a-local-variable). If *assignment-expression*\ndesignates an expression having handle type, see [§§](#byref-assignment-for-scalar-types-with-local-variables). If\n*assignment-expression* designates an expression having array type, see\n[§§](#value-assignment-of-array-types-to-local-variables).\n\nThe type and value of the result is the type and value of the left-hand\noperand after the store (if any [see below]) has taken place. The result\nis not an lvalue.\n\nIf the location designated by the left-hand operand is a non-existent\narray element, a new element is inserted with the designated key and\nwith a value being that of the right-hand operand.\n\nIf the location designated by the left-hand operand is a string element,\nthen if the key is a negative-valued `int`, there is no side effect.\nOtherwise, if the key is a non-negative-valued `int`, the left-most single\ncharacter from the right-hand operand is stored at the designated\nlocation; all other characters in the right-hand operand string are\nignored.  If the designated location is beyond the end of the\ndestination string, that string is extended to the new length with\nspaces (U+0020) added as padding beyond the old end and before the newly\nadded character. If the right-hand operand is an empty string, the null\ncharacter \\\\0 (U+0000) is stored.\n\n**Examples**\n\n```\n$a = $b = 10    // equivalent to $a = ($b = 10)\n$v = array(10, 20, 30);\n$v[1] = 1.234;    // change the value (and type) of an existing element\n$v[-10] = 19;   // insert a new element with int key -10\n$v[\"red\"] = TRUE; // insert a new element with string key \"red\"\n$s = \"red\";\n$s[1] = \"X\";    // OK; \"e\" -> \"X\"\n$s[-5] = \"Y\";   // warning; string unchanged\n$s[5] = \"Z\";    // extends string with \"Z\", padding with spaces in [3]-[5]\n$s = \"red\";\n$s[0] = \"DEF\";    // \"r\" -> \"D\"; only 1 char changed; \"EF\" ignored\n$s[0] = \"\";       // \"D\" -> \"\\0\"\n$s[\"zz\"] = \"Q\";   // warning; defaults to [0], and \"Q\" is stored there\n// -----------------------------------------\nclass C { ... }\n$a = new C; // make $a point to the allocated object\n```\n\n## # byRef Assignment\n\n**Syntax**\n\n<pre>\n  <i>byref-assignment-expression:</i>\n    <i>unary-expression</i>  =  &  <i>assignment-expression</i>\n</pre>\n\n*unary-expression* is defined in [§§](#general-14); *assignment-expression* is\ndefined in [§§](#general-15).\n\n**Constraints**\n\n*unary-expression* must be a variable name.\n\n*assignment-expression* must be an lvalue, a call to a function that\nreturns a value byRef, or a *new-expression* (see comment below\nregarding this).\n\n**Semantics**\n\n*unary-expression* becomes an alias for *assignment-expression*. If\n*assignment-expression* designates an expression having value type, see\n[§§](#value-assignment-of-object-and-resource-types-to-a-local-variable). If *assignment-expression* designates an expression having\nhandle type, see [§§](#byref-assignment-of-non-scalar-types-with-local-variables). If *assignment-expression* designates an\nexpression having array type, see [§§](#deferred-array-copying).\n\n**Examples**\n\n```\n$a = 10;\n$b = &$a;   // make $b an alias of $a\n++$a;       // increment $a/$b to 11\n$b = -12;   // sets $a/$b to -12\n$a = \"abc\";     // sets $a/$b to \"abc\"\nunset($b);      // removes $b's alias to $a\n// -----------------------------------------\nfunction &g2() { $t = \"xxx\"; return $t; } // return byRef\n$b = &g2();     // make $b an alias to \"xxx\"\n```\n\n# # Compound Assignment\n\n**Syntax**\n\n<pre>\n  <i>compound-assignment-expression:</i>\n    <i>unary-expression   compound-assignment-operator   assignment-expression</i>\n\n  <i>compound-assignment-operator: one of</i>\n    **=  *=  /=  %=  +=  -=  .=  <<=  >>=  &=  ^=  |=\n</pre>\n\n*unary-expression* is defined in [§§](#general-14); *assignment-expression* is\ndefined in [§§](#general-15).\n\n**Constraints**\n\nAny constraints that apply to the corresponding postfix or binary\noperator apply to the compound-assignment form as well.\n\n**Semantics**\n\nThe expression `e1 op= e2` is equivalent to `e1 = e1 op (e2)`, except\nthat `e1` is evaluated once only.\n\n**Examples**\n\n```\n$v = 10;\n$v += 20;   // $v = 30\n$v -= 5;    // $v = 25\n$v .= 123.45  // $v = \"25123.45\"\n$a = [100, 200, 300];\n$i = 1;\n$a[$i++] += 50; // $a[1] = 250, $i → 2\n```\n\n# # Logical AND Operator (form 2)\n\n**Syntax**\n\n<pre>\n  <i>logical-AND-expression-2:</i>\n    <i>assignment-expression</i>\n    <i>logical-AND-expression-2</i>  and  <i>assignment-expression</i>\n</pre>\n\n*assignment-expression* is defined in [§§](#general-15).\n\n**Constraints**\n\nEach of the operands must have scalar type.\n\n**Semantics**\n\nExcept for the difference in precedence, operator and has exactly the\nsame semantics as operator `&&` ([§§](#logical-and-operator-form-1)).\n\n# # Logical Exclusive OR Operator\n\n**Syntax**\n\n<pre>\n  <i>logical-exc-OR-expression:</i>\n    <i>logical-AND-expression-2</i>\n    <i>logical-exc-OR-expression</i>  xor  <i>logical-AND-expression-2</i>\n</pre>\n\n*logical-AND-expression* is defined in [§§](#logical-and-operator-form-2).\n\n**Constraints**\n\nEach of the operands must have scalar type.\n\n**Semantics**\n\nIf either operand does not have type `bool`, its value is first converted\nto that type.\n\nGiven the expression `e1 xor e2`, `e1` is evaluated first, then `e2`. If\neither `e1` or `e2` is `TRUE`, but not both, the result has type `bool`, value\n`TRUE`. Otherwise, the result has type `bool`, value `FALSE`. There is a\nsequence point after the evaluation of `e1`.\n\nThis operator associates left-to-right.\n\n**Examples**\n\n```\nf($i++) XOR g($i) // the sequence point makes this well-defined\n```\n\n# # Logical Inclusive OR Operator (form 2)\n\n**Syntax**\n\n<pre>\n  <i>logical-inc-OR-expression-2:</i>\n    <i>logical-exc-OR-expression</i>\n    <i>logical-inc-OR-expression-2</i>  or  <i>logical-exc-OR-expression</i>\n</pre>\n\n*logical-exc-OR-expression* is defined in [§§](#logical-exclusive-or-operator).\n\n**Constraints**\n\nEach of the operands must have scalar type.\n\n**Semantics**\n\nExcept for the difference in precedence, operator and has exactly the\nsame semantics as operator `||` ([§§](#logical-inclusive-or-operator-form-1)).\n\n# # `yield` Operator\n\n**Syntax**\n\n<pre>\n  <i>yield-expression:</i>\n    <i>logical-inc-OR-expression-2</i>\n    yield  <i>array-element-initializer</i>\n</pre>\n\n*logical-inc-OR-expression* is defined in [§§](#logical-inclusive-or-operator-form-2);\n*array-element-initializer* is defined in [§§](#array-creation-operator).\n\n**Semantics**\n\nAny function containing a *yield-expression* is a *generator function*.\nA generator function generates a collection of zero or more key/value\npairs where each pair represents the next in some series. For example, a\ngenerator might *yield* random numbers or the series of Fibonacci\nnumbers. When a generator function is called explicitly, it returns an\nobject of type `Generator` ([§§](#class-generator)), which implements the interface\n`Iterator` ([§§](#interface-iterator)). As such, this allows that object to be iterated over\nusing the `foreach` statement ([§§](#the-foreach-statement)). During each iteration, the Engine\ncalls the generator function implicitly to get the next key/value pair.\nThen the Engine saves the state of the generator for subsequent\nkey/value pair requests.\n\nThis operator produces the result `NULL` unless the method\n`Generator->send` ([§§](#class-generator)) was called to provide a result value. This\noperator has the side effect of generating the next value in the\ncollection.\n\nBefore being used, an *element-key* must have, or be converted to, type\n`int` or `string`. Keys with `float` or `bool` values, or strings whose contents\nmatch exactly the pattern of *decimal-literal* ([§§](#integer-literals)), are\nconverted to `int` ([§§](#converting-to-integer-type)). Values of all other key types are converted to\n`string` ([§§](#converting-to-string-type)).\n\nIf *element-key* is omitted from an *array-element-initializer*, an\nelement key of type `int` is associated with the corresponding\n*element-value*. The key associated is one more than the previously\nassigned int key for this collection. However, if this is the first\nelement in this collection with an `int` key, key zero is used. If\n*element-key* is provided, it is associated with the corresponding\n*element-value*. The resulting key/value pair is made available by\n`yield`.\n\nIf *array-element-initializer* is omitted, default int-key assignment is\nused and each value is `NULL`.\n\nIf the generator function definition declares that it returns byRef,\neach value in a key/value pair is yielded byRef.\n\n**Examples**\n\n```\nfunction getTextFileLines($filename)\n{\n  $infile = fopen($filename, 'r');\n  if ($infile == FALSE) { /* deal with the file-open failure */ }\n\n  try\n  {\n    while ($textLine = fgets($infile))  // while not EOF\n    {\n      $textLine = rtrim($textLine, \"\\r\\n\"); // strip off terminator\n      yield $textLine;\n    }\n  }\n  finally\n  {\n    fclose($infile);\n  }\n}\nforeach (getTextFileLines(\"Testfile.txt\") as $line) { /* process each line */ }\n// -----------------------------------------\nfunction series($start, $end, $keyPrefix = \"\")\n{\n  for ($i = $start; $i <= $end; ++$i)\n  {\n    yield $keyPrefix . $i => $i;  // generate a key/value pair\n  }\n}\nforeach (series(1, 5, \"X\") as $key => $val) { /* process each key/val pair */ }\n```\n\n# # Script Inclusion Operators\n\n## # General\n\n**Syntax**\n\n<pre>\n  <i>expression:</i>\n    <i>yield-expression</i>\n    <i>include-expression</i>\n    <i>include-once-expression</i>\n    <i>require-expression</i>\n    <i>require-once-expression</i>\n</pre>\n\n*yield-expression* is described in [§§](#yield-operator); *include-expression* is\ndescribed in [§§](#the-include-operator); *include-once-expression* is described in\n[§§](#the-include_once-operator); *require-expression* is described in [§§](#the-require-operator); and\n*require-once-expression* is described in [§§](#the-require_once-operator).\n\n**Semantics:**\n\nWhen creating large applications or building component libraries, it is\nuseful to be able to break up the source code into small, manageable\npieces each of which performs some specific task, and which can be\nshared somehow, and tested, maintained, and deployed individually. For\nexample, a programmer might define a series of useful constants and use\nthem in numerous and possibly unrelated applications. Likewise, a set of\nclass definitions can be shared among numerous applications needing to\ncreate objects of those types.\n\nAn *include file* is a script that is suitable for *inclusion* by\nanother script. The script doing the including is the *including file*,\nwhile the one being included is the *included file*. A script can be an\nincluding file and an included file, either, or neither.\n\nUsing the series-of-constants example, an include file called\n`Positions.php` might define the constants `TOP`, `BOTTOM`, `LEFT`, and `RIGHT`,\nin their own namespace ([§§](#general-28)), Positions. Using the set-of-classes\nexample, to support two-dimensional geometry applications, an include\nfile called `Point.php` might define the class `Point`. An include file\ncalled `Line.php` might define the class Line (where a `Line` is represented\nas a pair of Points).An include file, called `Circle.php` might define the\nclass `Circle` (where a `Circle` is represented as a `Point` for the origin,\nand a radius).\n\nIf a number of the scripts making up an application each use one or more\nof the Position constants, they can each include the corresponding\ninclude file via the `include` operator ([§§](#the-include-operator)). However, most include\nfiles behave the same way each time they are included, so it is\ngenerally a waste of time including the same include file more than once\ninto the same scope. In the case of the geometry example, any attempt to\ninclude the same include file more than once will result in a fatal\n\"attempted class type redefinition\" error. However, this can be avoided\nby using the `include_once` operator ([§§](#the-include_once-operator)) instead.\n\nThe `require` operator ([§§](#the-require-operator)) is a variant of the `include` operator,\nand the `require_once` operator ([§§](#the-require_once-operator)) is a variant of the\n`include_once` operator.\n\nIt is important to understand that unlike the C/C++ (or similar)\npreprocessor, script inclusion in PHP is not a text substitution\nprocess. That is, the contents of an included file are not treated as if\nthey directly replaced the inclusion operation source in the including\nfile.\n\nAn inclusion expression can be written to look like a function call;\nhowever, that is not the case, even though an included file can return a\nvalue to its including file.\n\nThe name used to specify an include file may contain an absolute or\nrelative path. In the latter case, an implementation may use the\nconfiguration directive\n[`include_path`](http://www.php.net/manual/en/ini.core.php#ini.include-path)\n(§xx) to resolve the include file's location.\n\n## # The `include` Operator\n\n**Syntax**\n\n<pre>\n  <i>include-expression:</i>\n    include  (  <i>include-filename</i>  )\n    include  <i>include-filename</i>\n\n  <i>include-filename:</i>\n    <i>expression</i>\n</pre>\n\n*expression* is defined in [§§](#general-16).   \n\n**Constraints:**\n\n*expression* must be a string that designates a file that exists, is\naccessible, and whose format is suitable for inclusion (that is, starts\nwith a PHP start-tag, and optionally ends with a PHP end-tag). However,\nif the designated file is not accessible, execution may continue.\n\n**Semantics:**\n\nWhen an included file is opened, parsing immediately drops out of PHP\nmode and into HTML mode at the beginning, and switches back again when\nthe end of the included file is reached.\n\nVariables defined in an included file take on scope of the source line\non which the inclusion occurs in the including file. However, functions\nand classes defined in the included file are given global scope.\n\nIf inclusion occurs inside a function definition within the including\nfile, the complete contents of the included file are treated as though\nit were defined inside that function.\n\nOperator `include` has a side effect of including the designated include\nfile. The result produced by this operator is one of the following:\n`FALSE`, which indicates the inclusion attempt failed; the `int` 1, which\nindicates the default value for inclusion attempt succeeded; or some\nother value, as returned from the included file ([§§](#the-return-statement)). \n\nThe library function `get_included_files` (§xx) provides the names of\nall files included or required.\n\n**Examples:**\n\n```\n$fileName = 'limits' . '.php'; include $fileName;\n$inc = include('limits.php');\nIf ((include 'Positions.php') == 1) ...\n```\n\n## # The `include_once` Operator\n\n**Syntax**\n\n<pre>\n  <i>include-once-expression:</i>\n    include_once  (  <i>include-filename</i>  )\n    include_once  <i>include-filename</i>\n</pre>\n\n*include-filename* is defined in [§§](#the-include-operator).   \n\n**Semantics:**\n\nThis operator is identical to operator `include` ([§§](#the-include-operator)) except that in\nthe case of `include_once`, the include file is included once only during\nprogram execution.\n\nOnce an include file has been included, a subsequent use of\n`include_once` on that include file results in a return value of `TRUE`.\n\n**Examples:**\n\nPoint.php:\n\n```\n\\\\ Point.php:\n<?php ...\nclass Point { ... }\n\n\\\\ Circle.php:\n<?php ...\ninclude_once 'Point.php';\nclass Circle { /* uses Point somehow */ }\n\n\\\\ MyApp.php\ninclude_once 'Point.php';   // Point.php included directly\ninclude_once 'Circle.php';    // Point.php now not included indirectly\n$p1 = new Point(10, 20);\n$c1 = new Circle(9, 7, 2.4);\n```\n\n## # The `require` Operator\n\n**Syntax**\n\n<pre>\n  <i>require-expression:</i>\n    require  (  <i>include-filename</i>  )\n    require  <i>include-filename</i>\n</pre>\n\n*include-filename* is defined in [§§](#the-include-operator).   \n\n**Semantics:**\n\nThis operator is identical to operator `include` ([§§](#the-include-operator)) except that in\nthe case of `require`, failure to find/open the designated include file\nterminates program execution.\n\nThe library function `get_included_files` (§xx) provides the names of\nall files included or required.\n\n## # The `require_once` Operator\n\n**Syntax**\n\n<pre>\n  <i>require-once-expression:</i>\n    require_once  (  <i>include-filename</i>  )\n    require_once  <i>include-filename</i>\n</pre>\n\n*include-filename* is defined in [§§](#the-include-operator).   \n\n**Semantics:**\n\nThis operator is identical to operator `require` ([§§](#the-require-operator)) except that in\nthe case of `require_once`, the include file is included once only during\nprogram execution.\n\nOnce an include file has been included, a subsequent use of\n`require_once` on that include file results in a return value of TRUE.\n\n# # Constant Expressions\n\n**Syntax**\n\n<pre>\n  <i>constant-expression:</i>\n    <i>array-creation-expression</i>\n    <i>const-expression</i>\n\n  <i>const-expression:</i>\n    <i>expression</i>\n</pre>\n\n*array-creation-expression* is defined in [§§](#array-creation-operator) and *expression* is\ndefined in [§§](#general-16).   \n\n**Constraints:**\n\nAll of the *element-key* and *element-value* *expression*s in\n*array-creation-expression* ([§§](#array-creation-operator)) must be literals.\n\n*expression* must have a scalar type, and be a literal or the name of an\nexisting c-constant ([§§](#general-4)), that is currently in scope.\n\n**Semantics:**\n\nA *const-expression* is the value of a c-constant. A *const-expression*\nis required in several contexts, such as in initializer values in a\n*const-declaration* ([§§](#constants-2)) and default initial values in a function\ndefinition ([§§](#function-definitions)).\n\nAn initializer in a *property-declaration* ([§§](#properties)) is less restrictive\nthan one in a *const-declaration*.\n\n\n\n# Statements\n\n# # General\n\n**Syntax**\n\n<pre>\n\n  <i>statement:</i>\n    <i>compound-statement</i>\n\t<i>labeled-statement</i>\n    <i>expression-statement</i>\n    <i>selection-statement</i>\n    <i>iteration-statement</i>\n    <i>jump-statement</i>\n    <i>declare-statement</i>\n    <i>const-declaration</i>\n    <i>function-definition</i>\n    <i>class-declaration</i>\n    <i>interface-declaration</i>\n    <i>trait-declaration</i>\n    <i>namespace-definition</i>\n    <i>namespace-use-declaration</i>\n    <i>global-declaration</i>\n    <i>function-static-declaration</i>\n</pre>\n\n*compound-statement* is defined in [§§](#compound-statements); *labeled-statement* is defined\nin [§§](#labeled-statements); *expression-statement* is defined in [§§](#expression-statements);\n*selection-statement* is defined in [§§](#general-18); *iteration-statement* is\ndefined in [§§](#general-19); *jump-statement* is defined in [§§](#general-20);\n*declare-statement* is defined in [§§](#the-declare-statement); *const-declaration* is defined\nin [§§](#constants-2); *function-definition* is defined in [§§](#function-definitions); *class-declaration*\nis defined in [§§](#class-declarations); *interface-declaration* is defined in [§§](#interface-declarations);\n*trait-declaration* is defined in [§§](#trait-declarations); *namespace-definition* is\ndefined in [§§](#defining-namespaces); *namespace-use-declaration* is defined in [§§](#namespace-use-declarations);\n*global-declaration* is defined in [§§](#global-variables); and\n*function-static-declaration* is defined in [§§](#function-statics). \n\n# # Compound Statements\n\n**Syntax**\n\n<pre>\n  <i>compound-statement:</i>\n    {   <i>statement-list<sub>opt</sub></i>  }\n\n  <i>statement-list:</i>\n    <i>statement</i>\n    <i>statement-list   statement</i>\n</pre>\n\n*statement* is defined in [§§](#general-17).\n\n**Semantics**\n\nA *compound statement* allows a group of zero of more statements to be\ntreated syntactically as a single statement. A compound statement is\noften referred to as a *block*.\n\n**Examples**\n\n```\nif (condition)\n{\t// braces are needed as the true path has more than one statement\n\t// statement-1\n\t// statement-2\n}\nelse\n{\t// braces are optional as the false path has only one statement\n\t// statement-3\n}\n// -----------------------------------------\nwhile (condition)\n{\t// the empty block is equivalent to a null statement\n}\n```\n\n# # Labeled Statements\n\n**Syntax**\n\n<pre>\n  <i>labeled-statement:</i>\n    <i>named-label</i>\n    <i>case-label</i>\n    <i>default-label</i>\n\n  <i>named-label:</i>\n    <i>name</i>  :  <i>statement</i>\n\n  <i>case-label:</i>\n    <i>case   expression   case-default-label-terminator   statement</i>\n\n  <i>default-label:</i>\n    <i>default  case-default-label-terminator   statement</i>\n\n  <i>case-default-label-terminator:</i>\n    :\n    ;\n</pre>\n\n*name* is defined in [§§](#names); *statement* is defined in [§§](#general-17); and\n*expression* is defined in [§§](#general-16).\n\n**Constraints**\n\nA named label must only be used as the target of a `goto` statement\n([§§](#the-goto-statement)). \n\nNamed labels must be unique within a function.\n\nA case and default label must only occur inside a `switch` statement\n([§§](#the-switch-statement)).\n\n**Semantics**\n\nAny statement may be preceded by a token sequence that declares a name\nas a label name. The presence of a label does not alter the ﬂow of\nexecution.\n\n# # Expression Statements\n\n**Syntax**\n\n<pre>\n   <i>expression-statement:</i>\n     <i>expression<sub>opt</sub></i>  ;\n</pre>\n\n*expression* is defined in [§§](#general-16).\n\n**Semantics**\n\nIf present, *expression* is evaluated for its side effects, if any, and\nany resulting value is discarded. If *expression* is omitted, the\nstatement is a *null statement*, which has no effect on execution.\n\n**Examples**\n\n```\n$i = 10;\t// $i is assigned the value 10; result (10) is discarded\n++$i;\t// $i is incremented; result (11) is discarded\n$i++;\t// $i is incremented; result (11) is discarded\nDoIt();\t// function DoIt is called; result (return value) is discarded\n// -----------------------------------------\n$i;\t\t// no side effects, result is discarded. Vacuous but permitted\n123;\t// likewise for this one and the two statements following\n34.5 * 12.6 + 11.987;\nTRUE;\n// -----------------------------------------\nfunction findValue($table, $value)  // where $table is 2x3 array\n{\n\tfor ($row = 0; $row <= 1; ++$row)\n\t{\n\t\tfor ($colm = 0; $colm <= 2; ++$colm)\n\t\t{\n\t\t\tif ($table[$row][$colm] == $value)\n\t\t\t{\n\t\t\t\t// ...\n\t\t\t\tgoto done;\n\t\t\t}\n\t\t}\n\t}\n\t// ...\ndone:\n\t;     // null statement needed as a label must precede a statement\n}\n```\n\n# # Selection Statements\n\n## # General\n\n**Syntax**\n\n<pre>\n  <i>selection-statement:</i>\n    <i>if-statement</i>\n    <i>switch-statement</i>\n</pre>\n\n*if-statement* is defined in [§§](#the-if-statement) and *switch-statement* is defined\nin [§§](#the-switch-statement).\n\n**Semantics**\n\nBased on the value of a controlling expression, a selection statement\nselects among a set of statements.\n\n## # The `if` Statement\n\n**Syntax**\n\n<pre>\n  <i>if-statement:</i>\n    if   (   <i>expression</i>   )   <i>statement   elseif-clauses-1opt   else-clause-1opt</i>\n    if   (   <i>expression   )   :   <i>statement-list   elseif-clauses-2opt   else-clause-2opt</i>   endif   ;\n\n  <i>elseif-clauses-1:</i>\n    <i>elseif-clause-1</i>\n    <i>elseif-clauses-1   elseif-clause-1</i>\n\n  <i>elseif-clause-1:</i>\n    elseif   (   <i>expression</i>   )   <i>statement</i>\n \n  <i>else-clause-1:</i>\n    else   <i>statement</i>\n\n  <i>elseif-clauses-2:</i>\n    <i>elseif-clause-2</i>\n    <i>elseif-clauses-2   elseif-clause-2</i>\n\n  <i>elseif-clause-2:</i>\n    elseif   (   <i>expression</i>   )   :   <i>statement-list</i>\n  \n  <i>else-clause-2:</i>\n    else   :   <i>statement-list</i>\n</pre>\n\n*expression* is defined in [§§](#general-16); *statement* is defined in [§§](#general-17);\nand *statement-list* is defined in [§§](#compound-statements).\n\n**Constraints**\n\nThe controlling expression *expression* must have type `bool` or be\nimplicitly convertible to that type.\n\n**Semantics**\n\nThe two forms of the `if` statement are equivalent; they simply provide\nalternate styles.\n\nIf *expression* tests `TRUE`, the *statement* that follows immediately is\nexecuted. Otherwise, if an `elseif` clause is present the *statement*\nimmediately following the `elseif` is executed. Otherwise, any other\n`elseif` *expression*s are evaluated. If none of those tests `TRUE`, if an\n`else` clause is present the *statement* immediately following the `else` is\nexecuted.\n\nAn `else` clause is associated with the lexically nearest preceding `if` or\n`elseif` that is permitted by the syntax.\n\n**Examples**\n```\nif ($count > 0)\n{\n\t...\n\t...\n\t...\n}\n// -----------------------------------------\ngoto label1;\necho \"Unreachable code\\n\";\n\nif ($a)\n{\nlabel1:\n\t...\n}\nelse\n{\n\t...\n}\n// -----------------------------------------\nif (1)\n\t...\n\tif (0)\n\t\t...\nelse \t// this else does NOT go with the outer if\n\t...\n\nif (1)\n{\n\t...\n\tif (0)\n\t\t...\n}\nelse \t// this else does go with the outer if\n\t\t...\n```\n\n## # The `switch` Statement\n\n**Syntax**\n\n<pre>\n  <i>switch-statement:</i>\n    switch  (  <i>expression</i>  )  <i>compound-statement</i>\n    switch  (  <i>expression</i>  )  :   <i>statement-list</i>  endswitch;\n</pre>\n\n*expression* is defined in [§§](#general-16); and *compound-statement* and\n*statement-list* are defined in [§§](#compound-statements).\n\n**Constraints**\n\nThe controlling expression *expression* must have scalar type.\n\nThe *statement-list* must not contain any *compound-statement*s.\n\nThere must be at most one default label.\n\n**Semantics**\n\nThe two forms of the `switch` statement are equivalent; they simply\nprovide alternate styles.\n\nBased on the value of its *expression*, a `switch` statement transfers\ncontrol to a case label (§[[11.3](#labeled-statements)](#labeled-statements)); to a default label (§[[11.3](#labeled-statements)](#labeled-statements)), if one\nexists; or to the statement immediately following the end of the `switch`\nstatement. A case or default label is only reachable directly within its\nclosest enclosing `switch` statement.\n\nOn entry to the `switch` statement, the controlling expression is\nevaluated and then compared with the value of the case-label-expression\nvalues, in lexical order. If one matches, control transfers to the\nstatement following the corresponding case label. If there is no match,\nthen if there is a default label, control transfers to the statement\nfollowing that; otherwise, control transfers to the statement\nimmediately following the end of the `switch` statement. If a `switch`\ncontains more than one case label whose values compare equal to the\ncontrolling expression, the first in lexical order is consider the\nmatch.\n\nAn arbitrary number of statements can be associated with any case or\ndefault label. In the absence of a `break` statement ([§§](#the-break-statement)) at the end\nof a set of such statements, control drops through into any following\ncase or default label. Thus, if all cases and the default end in break\nand there are no duplicate-valued case labels, the order of case and\ndefault labels is insignificant.\n\nCase-label values can be runtime expressions, and the types of sibling\ncase-label values need not be the same.\n\nSwitches may nested, in which case, each `switch` has its own set of\n`switch` clauses.\n\n**Examples**\n\n```\n$v = 10;\nswitch ($v)\n{\ndefault:\n\techo \"default case: \\$v is $v\\n\";\n\tbreak;\t\t// break ends \"group\" of default statements\ncase 20:\n\techo \"case 20\\n\";\n\tbreak; \t\t// break ends \"group\" of case 20 statements\ncase 10:\n\techo \"case 10\\n\";\t// no break, so control drops into next label's \"group\"\ncase 30:\n\techo \"case 30\\n\";\t// no break, but then none is really needed either\n}\n// -----------------------------------------\n$v = 30;\nswitch ($v)\n{\ncase 30.0:\t// <===== this case matches with 30\n\techo \"case 30.0\\n\";\n\tbreak;\ndefault:\n\techo \"default case: \\$v is $v\\n\";\n\tbreak;\ncase 30:\t\t// <===== rather than this case matching with 30\n\techo \"case 30\\n\";\n\tbreak;\n}\n// -----------------------------------------\nswitch ($v)\n{\ncase 10 + $b:\t// non-constant expression\n\t// ...\ncase $v < $a: \t// non-constant expression\n\t// ...\n// ...\n}\n```\n\n# # Iteration Statements\n\n## # General\n\n**Syntax**\n\n<pre>\n  <i>iteration-statement:</i>\n    <i>while-statement</i>\n    <i>do-statement</i>\n    <i>for-statement</i>\n    <i>foreach-statement</i>\n</pre>\n\n*while-statement* is defined in [§§](#the-while-statement); *do-statement* is defined in\n[§§](#the-do-statement); *for-statement* is defined in [§§](#the-for-statement); and *foreach-statement*\nis defined in [§§](#the-foreach-statement).\n\n# # The `while` Statement\n\n**Syntax**\n\n<pre>\n  <i>while-statement:</i>\n    while  (  <i>expression</i>  )  <i>statement</i>\n    while  (  <i>expression</i>  )  :   <i>statement-list</i>  endwhile ;\n</pre>\n\n*expresion* is defined in [§§](#general-16); *statement* is defined in [§§](#general-17); and\n*statement-list* is defined in [§§](#compound-statements).\n\n**Constraints**\n\nThe controlling expression *expression* must have type `bool` or be\nimplicitly convertible to that type.\n\n**Semantics**\n\nThe two forms of the `while` statement are equivalent; they simply provide\nalternate styles.\n\nIf *expression* tests `TRUE`, the *statement* that follows immediately is\nexecuted, and the process is repeated. If *expression* tests `FALSE`,\ncontrol transfers to the point immediately following the end of the\n`while` statement. The loop body, *statement*, is executed zero or more\ntimes.\n\n**Examples**\n\n```\n$i = 1;\nwhile ($i <= 10):\n\techo \"$i\\t\".($i * $i).\"\\n\";\t// output a table of squares\n\t++$i;\nendwhile;\n// -----------------------------------------\nwhile (TRUE)\n{\n\t// ...\n\tif ($done)\n\t\tbreak;\t// break out of the while loop\n\t// ...\n}\n```\n\n# # The `do` Statement\n\n**Syntax**\n\n<pre>\n  <i>do-statement:</i>\n    do  <i>statement</i>  while  (  <i>expression</i>  )  ;\n</pre>\n\n*statement* is defined in [§§](#general-17) and *expresion* is defined in [§§](#general-16).\n\n (Note: There is no `:/enddo` alternate syntax.)\n\n**Constraints**\n\nThe controlling expression *expression* must have type `bool` or be\nimplicitly convertible to that type.\n\n**Semantics**\n\nFirst, *statement* is executed and then *expression* is tested. If its\nvalue is `TRUE`, the process is repeated. If *expression* tests `FALSE`,\ncontrol transfers to the point immediately following the end of the `do`\nstatement. The loop body, *statement*, is executed one or more times.\n\n**Examples**\n\n```\n$i = 1;\ndo\n{\n\techo \"$i\\t\".($i * $i).\"\\n\";\t// output a table of squares\n\t++$i;\n}\nwhile ($i <= 10);\n```\n\n# # The `for` Statement\n\n**Syntax**\n\n<pre>\n  <i>for-statement:</i>\n    for   (   <i>for-initializeropt</i>   ;   <i>for-controlopt</i>   ;   <i>for-end-of-loopopt</i>   )   <i>statement</i>\n    for   (   <i>for-initializeropt</i>   ;   <i>for-controlopt</i>   ;   <i>for-end-of-loopopt</i>   )   :   <i>statement-list</i>   endfor   ;\n\n  <i>for-initializer:</i>\n    <i>for-expression-group</i>\n\n  <i>for-control:</i>\n    <i>for-expression-group</i>\n\n  <i>for-end-of-loop:</i>\n    <i>for-expression-group</i>\n\n  <i>for-expression-group:</i>\n    <i>expression</i>\n    <i>for-expression-group</i>   ,   <i>expression</i>\n</pre>\n\n*statement* is defined in [§§](#general-17); *statement-list* is defined in [§§](#compound-statements);\nand *expression* is defined in [§§](#general-16).\n\nNote: Unlike C/C++, PHP does not support a comma operator, per se.\nHowever, the syntax for the `for` statement has been extended from that of\nC/C++ to achieve the same results in this context.\n\n**Constraints**\n\nThe controlling expression—the right-most *expression* in\n*for-control*—must have type `bool` or be implicitly convertible to that\ntype.\n\n**Semantics**\n\nThe two forms of the `for` statement are equivalent; they simply provide\nalternate styles.\n\nThe group of expressions in *for-initializer* is evaluated once,\nleft-to-right, for their side effects. Then the group of expressions in\n*for-control* is evaluated left-to-right (with all but the right-most\none for their side effects only), with the right-most expression's value\nbeing tested. If that tests `TRUE`, *statement* is executed, and the group\nof expressions in *for-end-of-loop* is evaluated left-to-right, for\ntheir side effects only. Then the process is repeated starting with\n*for-control*. If the right-most expression in *for-control* tests\n`FALSE`, control transfers to the point immediately following the end of\nthe `for` statement. The loop body, *statement*, is executed zero or more\ntimes.\n\nIf *for-initializer* is omitted, no action is taken at the start of the\nloop processing. If *for-control* is omitted, this is treated as if\n*for-control* was an expression with the value `TRUE`. If\n*for-end-of-loop* is omitted, no action is taken at the end of each\niteration.\n\n**Examples**\n\n```\nfor ($i = 1; $i <= 10; ++$i)\n{\n\techo \"$i\\t\".($i * $i).\"\\n\";\t// output a table of squares\n}\n// -----------------------------------------\n// omit 1st and 3rd expressions\n\n$i = 1;\nfor (; $i <= 10;):\n\techo \"$i\\t\".($i * $i).\"\\n\";\t// output a table of squares\n\t++$i;\nendfor;\n// -----------------------------------------\n// omit all 3 expressions\n\n$i = 1;\nfor (;;)\n{\n\tif ($i > 10)\n\t\tbreak;\n\techo \"$i\\t\".($i * $i).\"\\n\";\t// output a table of squares\n\t++$i;\n}\n// -----------------------------------------\n//  use groups of expressions\n\nfor ($a = 100, $i = 1; ++$i, $i <= 10; ++$i, $a -= 10)\n{\n\techo \"$i\\t$a\\n\";\n}\n```\n\n# # The `foreach` Statement\n\n**Syntax**\n\n<pre>\n  <i>foreach-statement:</i>\n    foreach  (  <i>foreach-collection-name</i>  as  <i>foreach-key<sub>opt</sub>  foreach-value</i>  )   statement\n    foreach  (  <i>foreach-collection-name</i>  as  <i>foreach-key<sub>opt</sub>   foreach-value</i>  )  :   <i>statement-list</i>  endforeach  ;\n\n  <i>foreach-collection-name</i>:\n    <i>expression</i>\n\n  <i>foreach-key:</i>\n    <i>expression</i>  =>\n\n  <i>foreach-value:<i>\n    &<sub>opt</sub>   <i>expression</i>\n    <i>list-intrinsic</i>\n</pre>\n\n*statement* is defined in [§§](#general-17); *statement-list* is defined in [§§](#compound-statements);\n*variable-name* is defined in [§§](#names); *list-intrinsic* is defined in\n[§§](#list); and *expression* is defined in [§§](#general-16).\n\n**Constraints**\n\nThe variable designated by *foreach-collection-name* must be a\ncollection.\n\nEach *expression* must designate a variable name.\n\n**Semantics**\n\nThe two forms of the `foreach` statement are equivalent; they simply\nprovide alternate styles.\n\nThe *foreach* statement iterates over the set of elements in the\ncollection designated by *foreach-collection-name*, starting at the\nbeginning, executing *statement* each iteration. On each iteration, if\nthe `&` is present in *foreach-value*, the variable designated by the\ncorresponding *expression* is made an alias to the current element. If\nthe `&` is omitted, the value of the current element is assigned to the\ncorresponding variable. The loop body, *statement*, is executed zero or\nmore times. After the loop terminates, *expression* in *foreach-value*\nhas the same meaning it had after the final iteration, if any.\n\nIf *foreach-key* is present, the variable designated by its *expression*\nis assigned the current element's key value.\n\nIn the *list-intrinsic* case, a value that is an array is split into\nindividual elements.\n\n**Examples**\n\n```\n$colors = array(\"red\", \"white\", \"blue\");\nforeach ($colors as $color):\n    // ...\nendforeach;\n// -----------------------------------------\nforeach ($colors as $key => $color)\n{\n    // ...\n}\n// -----------------------------------------\n// Modify the local copy of an element's value\n\nforeach ($colors as $color)\n{\n\t$color = \"black\";\n}\n// -----------------------------------------\n// Modify the the actual element itself\n\nforeach ($colors as &$color)\t// note the &\n{\n\t$color = \"black\";\n}\n```\n\n# # Jump Statements\n\n## # General\n\n**Syntax**\n\n<pre>\n  <i>jump-statement:</i>\n    <i>goto-statement</i>\n    <i>continue-statement</i>\n    <i>break-statement</i>\n    <i>return-statement</i>\n    <i>throw-statement</i>\n</pre>\n\n*goto-statement* is defined in [§§](#the-goto-statement); *continue-statement* is defined\nin [§§](#the-continue-statement); *break-statement* is defined in [§§](#the-break-statement); *return-statement*\nis defined in [§§](#the-return-statement); and *throw-statement* is defined in [§§](#the-throw-statement).\n\n## # The `goto` Statement\n\n**Syntax**\n\n<pre>\n  <i>goto-statement:</i>\n    goto  <i>name</i>  ;\n</pre>\n\n*name* is defined in [§§](#names). \n\n**Constraints**\n\nThe name in a `goto` statement must be that of a named label located\nsomewhere in the current script. Control must not be transferred into or\nout of a function, or into an iteration statement ([§§](#iteration-statements)) or a `switch`\nstatement ([§§](#the-switch-statement)).\n\nA `goto` statement must not attempt to transfer control out of a\nfinally-block ([§§](#the-try-statement)).\n\n**Semantics**\n\nA `goto` statement transfers control unconditionally to the named label\n([§§](#labeled-statements)).\n\nA `goto` statement may break out of a construct that is fully contained\nwithin a finally-block.\n\n**Examples**\n\n```\nfunction findValue($table, $v)\t// where $table is 2x3 array\n{\n\tfor ($row = 0; $row <= 1; ++$row)\n\t{\n\t\tfor ($colm = 0; $colm <= 2; ++$colm)\n\t\t{\n\t\t\tif ($table[$row][$colm] == $v)\n\t\t\t{\n\t\t\t\techo \"$v was found at row $row, column $colm\\n\";\n\t\t\t\tgoto done; // not quite the same as break 2!\n\t\t\t}\n\t\t}\n\t}\n\techo \"$v was not found\\n\";\ndone:\n\t;\t// note that a label must always precede a statement\n}\n```\n\n## # The `continue` Statement\n\n**Syntax**\n\n<pre>\n  <i>continue-statement:</i>\n    continue   <i>breakout-level<sub>opt</sub></i>  ;\n\n  <i>breakout-level:</i>\n    <i>integer-literal</i>\n</pre>\n\n*integer-literal* is defined in [§§](#integer-literals). \n\n**Constraints**\n\nThe breakout level must not be zero, and it must not exceed the level of\nactual enclosing iteration and/or `switch` statements.\n\nA `continue` statement must not attempt to break out of a finally-block\n([§§](#the-try-statement)).\n\n**Semantics**\n\nA `continue` statement terminates the execution of the innermost enclosing\niteration ([§§](#iteration-statements)) or `switch` ([§§](#the-switch-statement)) statement.\n\nA `continue` statement terminates the execution of one or more enclosing\niteration ([§§](#iteration-statements)) or `switch` ([§§](#the-switch-statement)) statements. If *breakout-level* is\ngreater than one, the next iteration (if any) of the next innermost\nenclosing iteration or switch statement is started; however, if that\nstatement is a `for` statement and it has a *for-end-of-loop*, its\nexpression group for the current iteration is evaluated first. If\n*breakout-level* is 1, the behavior is the same as for `break 1`. If\n*breakout-level* is omitted, a level of 1 is assumed.\n\nA `continue` statement may break out of a construct that is fully\ncontained within a finally-block.\n\n**Examples**\n\n```\nfor ($i = 1; $i <= 5; ++$i)\n{\n\tif (($i % 2) == 0)\n\t\tcontinue;\n\techo \"$i is odd\\n\";\n}\n```\n\n# # The `break` Statement\n\n**Syntax**\n\n<pre>\n  <i>break-statement:</i>\n    break  <i>breakout-level<sub>opt</sub></i>  ;\n</pre>\n\n*breakout-level* is defined in [§§](#the-continue-statement). \n\n**Constraints**\n\nThe breakout level must not be zero, and it must not exceed the level of\nactual enclosing iteration and/or `switch` statements.\n\nA `break` statement must not attempt to break out of a finally-block\n([§§](#the-try-statement)).\n\n**Semantics**\n\nA `break` statement terminates the execution of one or more enclosing\niteration ([§§](#iteration-statements)) or `switch` ([§§](#the-switch-statement)) statements. The number of levels\nbroken out is specified by *breakout-level*. If *breakout-level* is\nomitted, a level of 1 is assumed.\n\nA `break` statement may break out of a construct that is fully contained\nwithin a finally-block.\n\n**Examples**\n\n```\n$i = 1;\nfor (;;)\n{\n\tif ($i > 10)\n\t\tbreak;\n\t// ...\n\t++$i;\n}\n// -----------------------------------------\nfor ($row = 0; $row <= 1; ++$row)\n{\n\tfor ($colm = 0; $colm <= 2; ++$colm)\n\t{\n\t\tif (some-condition-set)\n\t\t{\n\t\t\tbreak 2;\n\t\t}\n\t\t// ...\n\t}\n}\n// -----------------------------------------\nfor ($i = 10; $i <= 40; $i +=10)\n{\n        switch($i)\n        {\n        case 10: /* ... */; break;\t\t// breaks to the end of the switch\n        case 20: /* ... */; break 2;\t// breaks to the end of the for\n        case 30: /* ... */; break; \t\t// breaks to the end of the switch\n        }\n}\n```\n\n## # The `return` Statement\n\n**Syntax**\n\n<pre>\n  <i>return-statement:</i>\n    return  <i>expression<sub>opt</sub></i>  ;\n</pre>\n\n*expression* is defined in [§§](#general-16). \n\n**Constraints**\n\nThe *expression* in a *return-statement* in a generator function\n([§§](#yield-operator)) must be the literal `NULL` or be omitted.\n\n**Semantics**\n\nA `return` statement from within a function terminates the execution of\nthat function normally, and depending on how the function was defined\n([§§](#function-calls)), it returns the value of *expression* to the function's caller\nby value or byRef. If *expression* is omitted the value `NULL` is used. \n\nIf execution flows into the closing brace (`}`) of a function, `return\nNULL;` is implied.\n\nA function may have any number of `return` statements, whose returned\nvalues may have different types.\n\nIf an undefined variable is returned byRef, that variable becomes\ndefined, with a value of `NULL`.\n\nA `return` statement is permitted in a try-block ([§§](#the-try-statement)) and a catch-block\n([§§](#the-try-statement)). However, it is unspecified whether a `return` statement is\npermitted in a finally-block ([§§](#the-try-statement)), and, if so, the semantics of\nthat. \n\nUsing a `return` statement inside a finally-block will override any other\n`return` statement or thrown exception from the try-block and all its\ncatch-blocks.   Code execution in the parent stack will continue as if\nthe exception was never thrown.\n\nIf an uncaught exception exists when a finally-block is executed, if\nthat finally-block executes a `return` statement, the uncaught exception\nis discarded.\n\nIn an included file ([§§](#general-16)) a `return` statement may occur outside any\nfunction. This statement terminates processing of that script and\nreturns control to the including file. If *expression* is present, that\nis the value returned; otherwise, the value `NULL` is returned. If\nexecution flows to the end of the script, `return 1;` is implied. However,\nif execution flows to the end of the top level of a script, `return 0;` is\nimplied. Likewise, if *expression* is omitted at the top level. (See\nexit ([§§](#exitdie)).)\n\nReturning from a constructor or destructor behaves just like returning\nfrom a function.\n\nA `return` statement inside a generator function causes the generator to\nterminate.\n\nReturn statements can also be used in the body of anonymous functions.\n\n`return` terminates the execution of source code given to the intrinsic\n[`eval` ([§§](#eval))](http://www.php.net/manual/en/function.eval.php). \n\n**Examples**\n\n```\nfunction f() { return 100; }\t// f explicitly returns a value\nfunction g() { \treturn; }\t\t// g explicitly returns an implicit NULL\nfunction h() { }\t\t\t// h implicitly returns NULL\n// -----------------------------------------\n// j returns one of three dissimilarly-typed values\nfunction j($x)\n{\n\tif ($x > 0)\n\t{\n\t\treturn \"Positive\";\n\t}\n\telse if ($x < 0)\n\t{\n\t\treturn -1;\n\t}\n\t// for zero, implied return NULL\n}\nfunction &compute() { ...; return $value; } // returns $value byRef\n// -----------------------------------------\nclass Point \n{\n\tprivate static $pointCount = 0;\n\tpublic static function getPointCount() \n\t{\n\t\treturn self::$pointCount;\n\t}\n\t...\n}\n```\n\n**Implementation Notes**\n\nAlthough *expression* is a full expression ([§§](#general-10)), and there is a\nsequence point ([§§](#general-10)) at the end of that expression, as stated in\n[§§](#general-10), a side effect need not be executed if it can be determined that\nno other program code relies on its having happened. (For example, in\nthe cases of `return $a++;` and `return ++$a;`, it is obvious what value\nmust be returned in each case, but if `$a` is a variable local to the\nenclosing function, `$a` need not actually be incremented.\n\n## # The `throw` Statement\n\n**Syntax**\n\n<pre>\n  <i>throw-statement:</i>\n    throw  <i>expression</i>  ;\n</pre>\n\n*expression* is defined in [§§](#general-16). \n\n**Constraints**\n\nThe type of *expression* must be Exception ([§§](#class-exception)) or a subclass of that\nclass.\n\n*expression* must be such that an alias to it can be created. \n\n**Semantics**\n\nA `throw` statement throws an exception immediately and unconditionally.\nControl never reaches the statement immediately following the throw. See\n[§§](#general-27) and [§§](#the-try-statement) for more details of throwing and catching exceptions,\nand how uncaught exceptions are dealt with.\n\nRather than handle an exception, a catch-block may (re-)throw the same\nexception that it caught, or it can throw an exception of a different\ntype.\n\n**Examples**\n\n```\nthrow new Exception;\nthrow new Exception(\"Some message\", 123);\nclass MyException extends Exception { ... }\nthrow new MyException;\n```\n\n# # The `try` Statement\n\n**Syntax**\n\n<pre>\n  <i>try-statement:</i>\n    try  <i>compound-statement   catch-clauses</i>\n    try  <i>compound-statement   finally-clause</i>\n    try  <i>compound-statement   catch-clauses   finally-clause</i>\n\n  <i>catch-clauses:</i>\n    <i>catch-clause</i>\n    <i>catch-clauses   catch-clause</i>\n\n  <i>catch-clause:</i>\n    catch  (  <i>parameter-declaration-list</i>  )  <i>compound-statement</i>\n\n  <i>finally-clause:</i>\n    finally   <i>compound-statement</i>\n</pre>\n\n*compound-statement* is defined in [§§](#compound-statements) and\n*parameter-declaration-list* is defined in [§§](#function-definitions).\n\n**Constraints**\n\nIn a *catch-clause*, *parameter-declaration-list* must contain only one\nparameter, and its type must be `Exception` ([§§](#class-exception)) or a type derived from\nthat class, and that parameter must not be passed byRef.\n\n**Semantics**\n\nIn a *catch-clause*, *identifier* designates an *exception variable*\npassed in by value. This variable corresponds to a local variable with a\nscope that extends over the catch-block. During execution of the\ncatch-block, the exception variable represents the exception currently\nbeing handled.\n\nOnce an exception is thrown, the Engine searches for the nearest\ncatch-block that can handle the exception. The process begins at the\ncurrent function level with a search for a try-block that lexically\nencloses the throw point. All catch-blocks associated with that\ntry-block are considered in lexical order. If no catch-block is found\nthat can handle the run-time type of the exception, the function that\ncalled the current function is searched for a lexically enclosing\ntry-block that encloses the call to the current function. This process\ncontinues until a catch-block is found that can handle the current\nexception. \n\nIf a matching catch-block is located, the Engine prepares to transfer\ncontrol to the first statement of that catch-block. However, before\nexecution of that catch-block can start, the Engine first executes, in\norder, any finally-blocks associated with try-blocks nested more deeply\nthan the one that caught the exception. \n\nIf no matching catch-block is found, the behavior is\nimplementation-defined.\n\n**Examples**\n\n```\nfunction getTextLines($filename)\n{\n\t$infile = fopen($filename, 'r');\n\tif ($infile == FALSE) { /* deal with an file-open failure */ }\n\ttry\n\t{\n\t\twhile ($textLine = fgets($infile)) \t// while not EOF\n\t\t{\n\t\t\tyield $textLine;\t// leave line terminator attached\n\t\t}\n\t}\n\tfinally\n\t{\n\t\tfclose($infile);\n\t}\n}\n// -----------------------------------------\nclass DeviceException extends Exception { ... }\nclass DiskException extends DeviceException { ... }\nclass RemovableDiskException extends DiskException { ... }\nclass FloppyDiskException extends RemovableDiskException { ... }\n\ntry\n{\n\tprocess(); // call a function that might generate a disk-related exception\n}\ncatch (FloppyDiskException $fde) { ... }\ncatch (RemovableDiskException $rde) { ... }\ncatch (DiskException $de) { ... }\ncatch (DeviceException $dve) { ... }\nfinally { ... }\n```\n\n# # The `declare` Statement\n\n**Syntax**\n\n<pre>\n  <i>declare-statement:</i>\n    declare  (  <i>declare-directive</i>  )  <i>statement</i>\n    declare  (  <i>declare-directive</i>  )  :  <i>statement-list</i>  enddeclare  ;\n    declare  (  <i>declare-directive</i>  )  ;\n\n  <i>declare-directive:</i>\n    ticks  =  <i>declare-tick-count</i>\n    encoding  =  <i>declare-character-encoding</i>\n\n  <i>declare-tick-count</i>\n    <i>expression</i>\n\n  <i>declare-character-encoding:</i>\n    <i>expression</i>\n</pre>\n\n*statement* is defined in [§§](#general-17); *statement-list* is defined in [§§](#compound-statements);\nand *expression* is defined in [§§](#the-include-operator).\n\n**Constraints**\n\n*tick-count* must designate a value that is, or can be converted, to an\ninteger having a non-negative value.\n\n*character-encoding* must designate a string whose value names an\n8-bit-[character\nencoding](http://en.wikipedia.org/wiki/Character_encoding).\n\nExcept for white space, a *declare-statement* in a script that specifies\n*character-encoding* must be the first thing in that script.\n\n**Semantics**\n\nThe first two forms of the `declare` statement are equivalent; they simply\nprovide alternate styles.\n\nThe `declare` statement sets an *execution directive* for its *statement*\nbody, or for the `;`-form, for the remainder of the script or until the\nstatement is overridden by another *declare-statement*, whichever comes\nfirst. As the parser is executing, certain statements are considered\n*tickable*. For every *tick-count* ticks, an event occurs, which can be\nserviced by the function previously registered by the library function \n[`register_tick_function`\n(§xx)](http://www.php.net/manual/en/function.register-tick-function.php).\nTick event monitoring can be disabled by calling the library function \n[`unregister_tick_function`\n(§xx)](http://www.php.net/manual/en/function.unregister-tick-function.php).\nThis facility allows a profiling mechanism to be developed.\n\nCharacter encoding can be specified on a script-by-script basis using\nthe encoding directive. The joint ISO and IEC standard ISO/IEC\n8859 standard series (<http://en.wikipedia.org/wiki/ISO/IEC_8859>)\nspecifies a number of 8-bit-[character\nencodings](http://en.wikipedia.org/wiki/Character_encoding) whose names\ncan be used with this directive.\n\n**Examples**\n\n```\ndeclare(ticks = 1) { ... }\ndeclare(encoding = 'ISO-8859-1'); // Latin-1 Western European\ndeclare(encoding = 'ISO-8859-5'); // Latin/Cyrillic\n```\n\n# Arrays\n\n# # General\n\nAn *array* is a data structure that contains a collection of zero or\nmore *elements*. The elements of an array need not have the same type,\nand the type of an array element can change over its lifetime. An array\nelement can have any type (which allows for arrays of arrays). However,\nPHP does not support\nmultidimensional [array](http://www.php.net/manual/en/language.types.array.php)s.\n\nAn [array](http://www.php.net/manual/en/language.types.array.php) is\nrepresented as an ordered map in which each entry is a key/value pair\nthat represents an element. An element key can be an expression of type\n`int` or `string`. Duplicate keys are not permitted. The order of the\nelements in the map is the order in which the elements were *inserted*\ninto the array. An element is said to *exist* once it has been inserted\ninto the array with a corresponding key. An array is *extended* by\ninitializing a previously non-existent element using a new key. Elements\ncan be *removed* from an array via the intrinsic unset ([§§](#unset)).\n\nThe `foreach` statement ([§§](#the-foreach-statement)) can be used to iterate over the\ncollection of elements in an array, in the order in which the elements\nwere inserted. This statement provides a way to access the key and value\nfor each element.\n\nEach array has its own *current element pointer* that designates the\n*current array element*. When an array is created, the current element\nis the first element inserted into the array.\n\nNumerous library functions are available to create and/or manipulate\narrays. See §xx.\n\n(Note: Arrays in PHP are quite different from arrays in numerous\nmainstream languages. Specifically, in PHP, array elements need not have\nthe same type, the subscript index need not be an integer (so there is\nno concept of a base index of zero or 1), and there is no concept of\nconsecutive elements occupying physically adjacent memory locations.)\n\n# # Array Creation and Initialization\n\nAn array is created and initialized by one of two equivalent ways: via\nthe array-creation operator `[]` ([§§](#array-creation-operator)) or the intrinsic array\n([§§](#array)).\n\n# # Element Access and Insertion\n\nThe value (and possibly the type) of an existing element is changed, and\nnew elements are inserted, using the subscript operator `[]` ([§§](#subscript-operator)).\n\n\n# Functions\n\n# # General\n\nWhen a function is called, information may be passed to it by the caller\nvia an *argument list*, which contains one or more *argument\nexpressions*, or more simply, *arguments*. These correspond by position\nto the *parameters* in a *parameter list* in the called function's\ndefinition ([§§](#function-definitions)).\n\nAn *unconditionally defined function* is a function whose definition is\nat the top level of a script. A *conditionally defined function* is a\nfunction whose definition occurs inside a compound statement (which is\ninside a function definition); that is, it is a *nested function*. There\nis no limit on the depth of levels of function nesting. Consider the\ncase of an *outer function*, and an *inner function* defined within it.\nUntil the outer function is called at least once, its inner function\ncannot exist. Even if the outer function is called, if its runtime logic\nbypasses the definition of the inner function, that inner function still\ndoes not exist.\n\nAny function containing `yield` ([§§](#yield-operator)) is a *generator function*.\n\n**Examples**\n\n```\nucf1(); // can call ucf1 before its definition is seen\nfunction ucf1() { ... }\nucf1(); // can call ucf1 after its definition is seen\ncf1(); // Error; call to non-existent function\n$flag = TRUE;\nif ($flag) { function cf1() { ... } } // cf1 now exists\nif ($flag) { cf1(); } // can call cf1 now\n// -----------------------------------------\nfunction ucf2() { function cf2() { ... } }\ncf2(); // Error; call to non-existent function\nucf2(); // now cf2 exists\ncf2(); // so we can call it\n```\n\n# # Function Calls\n\nA function is called via the function-call operator `()` ([§§](#function-call-operator)).\n\n# # Function Definitions\n\n**Syntax**\n\n<pre>\n  <i>function-definition:</i>\n    <i>function-definition-header   compound-statement</i>\n\n  <i>function-definition-header:</i>\n    function  &<sub>opt</sub>   <i>name</i>  (  <i>parameter-declaration-list<sub>opt</sub></i>  )\n\n  <i>parameter-declaration-list:</i>\n    <i>parameter-declaration</i>\n    <i>parameter-declaration-list</i>  ,  <i>parameter-declaration</i>\n\n  <i>parameter-declaration:</i>\n    <i>type-hint<sub>opt</sub></i>  &<sub>opt</sub>   <i>variable-name   default-argument-specifier<sub>opt</sub></i>\n\n  <i>type-hint:</i>\n    array\n    callable\n    <i>qualified-name</i>\n\n  <i>default-argument-specifier:</i>\n    =  <i>const-expression</i>\n</pre>\n\n*const-expression* is defined in [§§](#constant-expressions). *qualified-name* is defined in\n[§§](#names).\n\n**Constraints**\n\nEach parameter name in a *function-definition* must be distinct.\n\nA conditionally defined function ([§§](#general-22)) must exist before any calls are\nmade to that function.\n\n*parameter-declaration* must not contain `&` if *type-hint* is `array` or\n`callable`.\n\n**Semantics**\n\nA *function-definition* defines a function called *name*. Function names\nare **not** case-sensitive. A function can be defined with zero or more\nparameters, each of which is specified in its own\n*parameter-declaration* in a *parameter-declaration-list*. Each\nparameter has a name, *variable-name*, and optionally, a\n*default-argument-specifier*. An `&` in *parameter-declaration* indicates\nthat parameter is passed byRef ([§§](#assignment)) rather than by value. An `&`\nbefore *name* indicates that the value returned from this function is to\nbe returned byRef. Function-value returning is described in [§§](#the-return-statement).\n\nWhen the function is called, if there exists a parameter for which there\nis a corresponding argument, the argument is assigned to the parameter \nvariable using value assignment, while for passing-byRef, the argument is \nassigned to the parameter variable using byRef assignment ([§§](#assignment), [§§](#argument-passing)). If that parameter has no corresponding argument, but the parameter has a \ndefault argument value, for passing-by-value or passing-byRef, the default \nvalue is assigned to the parameter variable using value assignment. \nOtherwise, if the parameter has no corresponding argument and the parameter \ndoes not have a default value, the parameter variable is non-existent and no corresponding VSlot ([§§](#the-memory-model)) exists.  After all possible parameters have been \nassigned initial values or aliased to arguments, the body of the function, \n*compound-statement*, is executed. This execution may terminate normally \n(§[[4.3](#program-termination)](#program-termination), [§§](#the-return-statement)) or abnormally (§[[4.3](#program-termination)](#program-termination)).\n\nEach parameter is a variable local to the parent function, and is a\nmodifiable lvalue.\n\nA *function-definition* may exist at the top level of a script, inside\nany *compound-statement*, in which case, the function is conditionally\ndefined ([§§](#general-22)), or inside a *method-declaration* ([§§](#methods)). \n\nBy default, a parameter will accept an argument of any type. However, by\nspecifying a *type-hint*, the types of argument accepted can be\nrestricted. By specifying `array`, only an argument designating an array\ntype is accepted. By specifying `callable`, only an argument designating a\nfunction is accepted. By specifying *qualified-name*, only an instance\nof a class having that type, or being derived from that type, are\naccepted, or only an instance of a class that implements that interface\ntype directly or indirectly is accepted.    \n\n# # Variable Functions\n\nIf a variable name is followed by the function-call operator `()`\n([§§](#function-call-operator)), and the value of that variable is a string containing the\nname of a function currently defined and visible, that function will be\nexecuted.\n\nThe library function `is_callable` (§xx) reports whether the contents of\na variable can be called as a function.\n\n# # Anonymous Functions\n\nAn *anonymous function*, also known as a *closure*, is a function\ndefined with no name. As such, it must be defined in the context of an\nexpression whose value is used immediately to call that function, or\nthat is saved in a variable for later execution. An anonymous function\nis defined via the anonymous function-creation operator ([§§](#anonymous-function-creation)).\n\nFor both `__FUNCTION__` and `__METHOD__` ([§§](#context-dependent-constants)), an anonymous\nfunction's name is `{closure}`. All anonymous functions created in the\nsame scope have the same name.\n\n\n# Classes\n\n# # General\n\nA class is a type that may contain zero or more explicitly declared\n*members*, which can be any combination of *class constants* ([§§](#constants-2));\ndata members, called *properties* ([§§](#properties)); and function members, called\n*methods* ([§§](#methods)). (The ability to add properties and methods to an\ninstance at runtime is described in [§§](#dynamic-members).) An object (often called an\n*instance*) of a class type is created (i.e., *instantiated*) via the\nnew operator ([§§](#the-new-operator)). \n\nPHP supports inheritance ([§§](#class-declarations)), a means by which a *derived class* can\n*extend* and specialize a single *base class*. However, unlike numerous\nother languages, classes in PHP are **not** all derived from a common\nancestor. An *abstract* class ([§§](#class-declarations)) is a base type intended for\nderivation, but which cannot be instantiated directly. A *concrete*\nclass is a class that is not abstract. A *final* class ([§§](#class-declarations)) is one\nfrom which other classes cannot be derived.\n\nA class may *implement* one or more *interfaces* ([§§](#class-declarations), [§§](#general-25)), each of\nwhich defines a contract.\n\nA class can *use* one or more traits ([§§](#general-26)), which allows a class to\nhave some of the benefits of multiple inheritance.\n\nA *constructor* ([§§](#constructors)) is a special method that is used to initialize\nan instance immediately after it has been created. A *destructor*\n([§§](#destructors)) is a special method that is used to free resources when an\ninstance is no longer needed. Other special methods exist; they are\ndescribed in ([§§](#methods-with-special-semantics)).\n\nThe members of a class each have a default or explicitly declared\n*visibility*, which determines what source code can access them. A\nmember with `private` visibility may be accessed only from within its own\nclass. A member with `protected` visibility may be accessed only from\nwithin its own class and from classes derived from that class. Access to\na member with `public` visibility is unrestricted. \n\nThe *signature* of a method is a combination of the parent class name,\nthat method's name, and its parameter list, including type hints and\nindication for arguments passed using byRef, and whether the resulting\nvalue is returned byRef.\n\nMethods and properties from a base class can be *overridden* in a\nderived class by redeclaring them with the same signature defined in the\nbase class.\n\nWhen an instance is allocated, new returns a handle that points to that\nobject. As such, assignment of a handle does not copy the object itself.\n(See [§§](#cloning-objects) for a discussion of shallow and deep copying.)\n\n# # Class Declarations\n\n**Syntax**\n\n<pre>\n  <i>class-declaration:</i>\n    <i>class-modifier<sub>opt</sub></i>  class  <i>name   class-base   clause<sub>opt</sub>  class-interface-clause<sub>opt</sub></i>   {   <i>trait-use-clauses<sub>opt</sub>   class-member-declarations<sub>opt</sub></i> }\n\n  <i>class-modifier:</i>\n    abstract\n    final\n\n  <i>class-base-clause:</i>\n    extends  <i>qualified-name</i>\n\n  <i>class-interface-clause:</i>\n    implements  <i>qualified-name</i>\n    <i>class-interface-clause</i>  ,  <i>qualified-name</i>\n</pre>\n\n*qualified-name* is defined in [§§](#names). *class-member-declarations* is\ndefined in [§§](#class-members). *trait-use-clauses* ~~ is defined in [§§](#trait-declarations)\n\n**Constraints**\n\nA class must not be derived directly or indirectly from itself.\n\nA *class-declaration* containing any *class-member-declarations* that\nhave the modifier `abstract` must itself have an `abstract`\n*class-modifier*.\n\n*class-base-clause* must not name a final class.\n\n*qualified-name* in *class-base-clause* must name a class type, and must\nnot be `parent`, `self`, or `static`.\n\nA concrete class must implement each of the methods from all the\ninterfaces ([§§](#general-25)) specified in *class-interface-clause*, using the\nexact same signature as defined in each interface.\n\n*qualified-name* in *class-interface-clause* must name an interface\ntype.\n\n**Semantics**\n\nA *class-declaration* defines a class type by the name *name*. Class\nnames are case-insensitive.\n\nThe `abstract` modifier declares a class usable only as a base class; the\nclass cannot be instantiated directly. An abstract class may contain one\nor more abstract members, but it is not required to do so. When a\nconcrete class is derived from an abstract class, the concrete class\nmust include an implementation for each of the abstract members it\ninherits.\n\nThe `final` modifier prevents a class from being used as a base class.\n\nThe optional *class-base-clause* specifies the one base class from which\nthe class being defined is derived. In such a case, the derived class\ninherits all the members from the base class.\n\nThe optional *class-interface-clause* specifies the one or more\ninterfaces that are implemented by the class being defined.\n\nA class can use one or more traits via a *trait-use-clauses*; see [§§](#general-26)\nand [§§](#trait-declarations).\n\n**Examples**\n\n```\nabstract class Vehicle \n{\n\tpublic abstract function getMaxSpeed();\n\t...\n}\nabstract class Aircraft extends Vehicle \n{\n\tpublic abstract function getMaxAltitude();\n\t...\n}\nclass PassengerJet extends Aircraft \n{\n\tpublic function getMaxSpeed()\n\t{\n\t\t// implement method\n\t}\n\tpublic function getMaxAltitude()\n\t{\n\t\t// implement method\n\t}\n\t...\n}\n$pj = new PassengerJet(...);\necho \"\\$pj's maximum speed: \" . $pj->getMaxSpeed() . \"\\n\";\necho \"\\$pj's maximum altitude: \" . $pj->getMaxAltitude() . \"\\n\";\n// -----------------------------------------\nfinal class MathLibrary \n{\n\tprivate function MathLibrary() {}\t// disallows instantiation\n\tpublic static function sin() { ... }\n\t// ...\n}\n$v = MathLibrary::sin(2.34);\n// -----------------------------------------\ninterface MyCollection \n{\n        function put($item);\n        function get();\n}\nclass MyList implements MyCollection \n{\n\tpublic function put($item)\n\t{\n\t\t// implement method\n\t}\n\tpublic function get()\n\t{\n\t\t// implement method\n\t}\n\t...\n}\n```\n\n# # Class Members\n\n**Syntax**\n\n<pre>\n  <i>class-member-declarations:</i>\n    <i>class-member-declaration</i>\n    <i>class-member-declarations   class-member-declaration</i>\n\n   <i>class-member-declaration:</i>\n     <i>const-declaration</i>\n     <i>property-declaration</i>\n     <i>method-declaration</i>\n     <i>constructor-declaration</i>\n     <i>destructor-declaration</i>\n</pre>\n\n*const-declaration* is defined in [§§](#constants-2); *property-declaration* is\ndefined in [§§](#properties); *method-declaration* is defined in [§§](#methods);\n*constructor-declaration* is defined in [§§](#names); and\n*destructor-declaration* is defined in [§§](#destructors).\n\n**Semantics**\n\nThe members of a class are those specified by its\n*class-member-declaration*s, and the members inherited from its base\nclass. (A class may also contain dynamic members, as described in [§§](#dynamic-members).\nHowever, as these have no compile-time names, they can only be accessed\nvia method calls.)\n\nA class may contain the following members:\n\n-   Constants – the constant values associated with the class ([§§](#constants-2)).\n-   Properties – the variables of the class ([§§](#properties)).\n-   Methods – the computations and actions that can be performed by the\n    class ([§§](#methods), [§§](#methods-with-special-semantics)).\n-   Constructor – the actions required to initialize an instance of the\n    class ([§§](#constructors))\n-   Destructor – the actions to be performed when an instance of the\n    class is no longer needed ([§§](#destructors)).\n\nA number of names are reserved for methods with special semantics, which\nuser-defined versions must follow. These are described in ([§§](#methods-with-special-semantics)).\n\nMethods and properties can either be *static* or *instance* members. A\nstatic member is declared using `static`. An instance member is one that\nis not static. The name of a static method or property can never be used\non its own; it must always be used as the right-hand operand of the\nscope resolution operator ([§§](#scope-resolution-operator)). The name of an instance method or\nproperty can never be used on its own; it must always be used as the\nright-hand operand of the member selection operator ([§§](#member-selection-operator)).\n\nEach instance of a class contains its own, unique set of instance\nproperties of that class. An instance member is accessed via the\n`->` operator ([§§](#member-selection-operator)). In contrast, a static property designates\nexactly one VSlot for its class, which does not belong to any instance,\nper se. A static property exists whether or not any instances of that\nclass exist. A static member is accessed via the `::` operator ([§§](#scope-resolution-operator)).\n\nWhen any instance method operates on a given instance of a class, within\nthat method that object can be accessed via `$this` ([§§](#general-11)). As a\nstatic method does not operate on a specific instance, it has no `$this`.\n\n**Examples**\n\n```\nclass Point \n{\n\tprivate static $pointCount = 0;\t\t\t// static property\n\n\tprivate $x;\t\t\t\t\t\t\t// instance property\n\tprivate $y;\t\t\t\t\t\t\t// instance property\n\n\tpublic static function getPointCount()\t\t// static method\n\t{\n\t\treturn self::$pointCount;\t\t\t// access static property\n\t}\n\tpublic function move($x, $y)\t\t\t\t// instance method\n\t{\n\t\t$this->x = $x;\n\t\t$this->y = $y;\n\t}\n\tpublic function __construct($x = 0, $y = 0)\t// instance method\n\t{\n\t\t$this->x = $x; \t\t\t\t\t// access instance property\n\t\t$this->y = $y; \t\t\t\t\t// access instance property\n\t\t++self::$pointCount; \t\t\t\t// access static property\n\t}\n\tpublic function __destruct()\t\t\t\t// instance method\n\t{\n\t\t--self::$pointCount; \t\t\t\t// access static property\n\t\t...\n\t}\n\t...\n}\necho \"Point count = \" . Point::getPointCount() . \"\\n\";\n$cName = 'Point';\necho \"Point count = \" . $cName::getPointCount() . \"\\n\";\n```\n\n# # Dynamic Members\n\nOrdinarily, all of the instance properties and methods of a class are\ndeclared explicitly in that class's definition. However, other\nmembers—*dynamic properties* and, under certain circumstances, *dynamic\nmethods*—can be added to a particular instance of a class or to the\nclass as a whole at runtime. A dynamic property can also be removed from\nan instance at runtime. In the case of dynamic properties, if a class\nmakes provision to do so by defining a series of special methods, it can\ndeal with the allocation and management of storage for those properties,\nby storing them in another object or in a database, for example. (The\ndefault behavior is for the Engine to allocate a VSlot for each one.)\nThis is called *class-specific dynamic allocation*. Otherwise, the\nEngine takes care of the storage in some unspecified manner. Dynamic\nmethod handling is only possible when ** class-specific dynamic\nallocation is used.\n\nConsider the following scenario, which involves dynamic properties:\n\n```\nclass Point { ... } // has no public property \"color\", but has made\n                    // provision to support dynamic properties.\n$p = new Point(10, 15);\n$p->color = \"red\"; // create/set the dynamic property \"color\"\n$v = $p->color;    // get the dynamic property \"color\"\nisset($p->color);  // test if the dynamic property \"color\" exists\nunset($p->color);  // remove the dynamic property \"color\"\n```\n\nFor the ** class-specific dynamic allocation scenario, when a property\nname that is not currently visible (because it is hidden or it does not\nexist) is used in a modifiable lvalue context (as with the assignment of\n\"red\"), the Engine generates a call to the instance method `__set`\n([§§](#method-__set)). This method treats that name as designating a dynamic\nproperty of the instance being operated on, and sets its value to \"red\",\ncreating the property, if necessary. Similarly, in a non-lvalue context,\n(as with the assignment of color to $v), the Engine generates a call to\nthe instance method `__get` ([§§](#method-__get)), which treats that name as\ndesignating a dynamic property of the instance being operated on, and\ngets its value. In the case of the call to the intrinsic `isset`\n([§§](#isset)), this generates a call to the instance method `__isset`\n([§§](#method-__isset)), while a call to the intrinsic `unset` ([§§](#unset)) generates a\ncall to the instance method `__unset` ([§§](#method-__unset)). By defining these\nfour special methods, the implementer of a class can control how dynamic\nproperties are handled. For the non-class-specific dynamic allocation\nscenario, the process is like that above except that no special `__*`\nmethods are called.\n\nIn the case of a dynamic method, no method is really added to the\ninstance or the class. However, the illusion of doing that is achieved\nby allowing a call to an instance or static method, but one which is not\ndeclared in that instance's class, to be accepted, intercepted by a\nmethod called `__call` ([§§](#method-__call)) or `__callStatic` ([§§](#method-__callstatic)), and\ndealt with under program control. \n\nConsider the following code fragment, in which class Widget has neither\nan instance method called `iMethod` nor a static method called `sMethod`,\nbut that class has made provision to deal with dynamic methods:\n\n```\n$obj = new Widget;\n$obj->iMethod(10, TRUE, \"abc\");\nWidget::sMethod(NULL, 1.234);\n```\n\nThe call to `iMethod` is treated as if it were\n\n```\n$obj->__call('iMethod', array(10, TRUE, \"abc\"))\n```\n\nand the call to `sMethod` is treated as if it were\n\n```\nWidget::__callStatic('sMethod', array(NULL, 1.234))\n```\n\n# # Constants\n\n**Syntax**\n\n<pre>\n  <i>const-declaration:</i>\n    const  <i>name</i>  =  <i>const-expression</i>   ;\n</pre>\n\n*name* is defined in ([§§](#names)). *const-expression* is defined in\n([§§](#constant-expressions)).\n\n**Constraints:**\n\nA *const-declaration* must only appear at the top level of a script, be\na *class constant* (inside a *class-definition*; [§§](#class-members)) or be an\n*interface constant* (inside an *interface-definition;* [§§](#interface-members)).\n\nA *const-declaration* must not redefine an existing c-constant ([§§](#general-4)).\n\nA class constant must not have an explicit visibility specifier ([§§](#general-23)).\n\nA class constant must not have an explicit `static` specifier.\n\n**Semantics:**\n\nA *const-declaration* defines a c-constant.\n\nAll class constants have public visibility.\n\nAll constants are implicitly `static`.\n\n**Examples:**\n\n```\nconst MIN_VAL = 20;\nconst LOWER = MIN_VAL;\n// -----------------------------------------\nclass Automobile\n{\n  const DEFAULT_COLOR = \"white\";\n  ...\n}\n$col = Automobile::DEFAULT_COLOR;\n```\n\n# # Properties\n\n**Syntax**\n\n<pre>\n  <i>property-declaration:</i>\n    <i>property-modifier   name   property-initializer<sub>opt</sub></i>  ;\n\n  <i>property-modifier:</i>\n    var\n    <i>visibility-modifier   static-modifier<sub>opt</sub></i>\n    <i>static-modifier   visibility-modifier<sub>opt</sub></i>\n\n  <i>visibility-modifier:</i>\n    public\n    protected\n    private\n\n  <i>static-modifier:</i>\n    static\n\n  <i>property-initializer:</i>\n    =  <i>constant-expression</i>\n</pre>\n\n\n*name* is described in [§§](#names) and *constant-expression* is described\nin [§§](#constant-expressions).\n\n**Semantics**\n\nA *property-declaration* defines an instance or static property.\n\nThe visibility modifiers are described in [§§](#general-23). If\n*visibility-modifier* is omitted, public is assumed. The var modifier\nimplies public visibility. The `static` modifier is described in [§§](#class-members).\n\nThe *property-initializer*s for instance properties are applied prior to\nthe class's constructor being called. \n\nAn instance property that is visible may be unset ([§§](#unset)), in which\ncase, the property is actually removed from that instance.\n\n**Examples**\n\n```\nclass Point \n{\n  private static $pointCount = 0; // static property with initializer\n  \n  private $x; // instance property\n  private $y; // instance property\n  ...\n\n}\n```\n\n# # Methods\n\n**Syntax**\n\n<pre>\n  method-declaration:\n    <i>method-modifiers<sub>opt</sub>   function-definition</i>\n    <i>method-modifiers   function-definition-header</i>  ;\n\n  <i>method-modifiers:</i>\n    <i>method-modifier</i>\n    <i>method-modifiers   method-modifier</i>\n\n  <i>method-modifier:</i>\n    <i>visibility-modifier</i>\n    <i>static-modifier</i>\n    abstract\n    final\n</pre>\n\n*visibility-modifier* is described in [§§](#general-23); *static-modifier* is\ndescribed in [§§](#class-members); and *function-definition* and\n*function-definition-header* are defined in [§§](#function-definitions).\n\n**Constraints**\n\nWhen defining a concrete class that inherits from an abstract class, the\ndefinition of each abstract method inherited by the derived class must\nhave the same or a\nless-restricted [visibility](http://www.php.net/manual/en/language.oop5.visibility.php)\nthan in the corresponding abstract declaration. Furthermore, the\nsignature of a method definition must match that of its abstract\ndeclaration.\n\nThe *method-modifiers* preceding a *function-definition* must not contain\nthe `abstract` modifier.\n\nThe *method-modifiers* preceding a *function-definition-header* must\ncontain the `abstract` modifier.\n\nA method must not have the same modifier specified more than once. A\nmethod must not have more than one *visibility-modifier*. A method must\nnot have both the modifiers `abstract` and `private`, or `abstract` and `final`.\n\n**Semantics**\n\nA *method-declaration* defines an instance or static method. A method is\na function that is defined inside a class. However, the presence of\n`abstract` indicates an abstract method, in which case, no implementation\nis provided. The absence of `abstract` indicates a concrete method, in\nwhich case, an implementation is provided.\n\nMethod names are case-insensitive.\n\nThe presence of `final` indicates the method cannot be overridden in a\nderived class.\n\nIf *visibility-modifier* is omitted, `public` is assumed.\n\n**Examples**\n\nSee [§§](#class-members) for examples of instance and static methods. See [§§](#class-declarations) for\nexamples of abstract methods and their subsequent definitions.\n\n# # Constructors\n\n**Syntax**\n\n<pre>\n  <i>constructor-definition:</i>\n    <i>visibility-modifier</i>  function &<sub>opt</sub>   __construct  (  <i>parameter-declaration-list<sub>opt</sub></i>  )  <i>compound-statement</i>\n    <i>visibility-modifier</i>  function &<sub>opt</sub>    <i>name</i>  (  <i>parameter-declaration-list<sub>opt</sub></i>  )  <i>compound-statement </i>    <b>[Deprecated form]</b>\n\n</pre>\n\n*visibility-modifier* is described in [§§](#general-23);\n*parameter-declaration-list* is described in [§§](#function-definitions); and\n*compound-statement* is described in [§§](#compound-statements). *name* is described in\n[§§](#names).\n\n**Constraints**\n\nAn overriding constructor in a derived class must have the same or a\nless-restricted [visibility](http://www.php.net/manual/en/language.oop5.visibility.php)\nthan that being overridden in the base class.\n\n*name* must be the same as that in the *class-declaration* ([§§](#class-declarations)) that\ncontains this *constructor-definition*.\n\n**Semantics**\n\nA constructor is a specially named instance method ([§§](#methods)) that is used\nto initialize an instance immediately after it has been created. Any\ninstance properties not explicitly initialized by a constructor take on\nthe value `NULL`. Like a method, a constructor can return a result by\nvalue or byRef. (Unlike a method, a constructor cannot be abstract or\nstatic.)\n\nIf *visibility-modifier* is omitted, `public` is assumed. A `private`\nconstructor inhibits the creation of an instance of the class type.\n\nConstructors can be overridden in a derived class by redeclaring them.\nHowever, an overriding constructor need not have the same signature as\ndefined in the base class. \n\nConstructors are called by *object-creation-expression*s ([§§](#the-new-operator))\nand from within other constructors.\n\nIf classes in a derived-class hierarchy have constructors, it is the\nresponsibility of the constructor at each level to call the constructor\nin its base-class explicitly, using the notation\n`parent::__construct(...)`. If a constructor calls its base-class\nconstructor, it should do so as the first statement in\n*compound-statement*, so the object hierarchy is built from the\nbottom-up. A constructor should not call its base-class constructor more\nthan once. A call to a base-class constructor searches for the nearest\nconstructor in the class hierarchy. Not every level of the hierarchy\nneed have a constructor.\n\nPrior to the addition of the `__construct` form of constructor, a\nclass's constructor was called the same as its class name. For example,\nclass `Point`'s constructor was called `Point`. Although this old-style form\nis supported, its use is deprecated. In any event, both\n`parent::__construct(...)` and `parent::name(...)` (where `name` is the name\nof the parent class type) will find an old- or a new-style constructor\nin the base class, if one exists. If both forms exist, the new-style one\nis used. The same is true of an *object-creation-expression* when\nsearching for a base-class constructor.\n\n**Examples**\n\n```\nclass Point \n{\n\tprivate static $pointCount = 0;\n\tprivate $x;\n\tprivate $y;\n\tpublic function __construct($x = 0, $y = 0)\n\t{\n\t\t$this->x = $x;\n\t\t$this->y = $y;\n\t\t++self::$pointCount;\n\t}\n\tpublic function __destruct()\n\t{\n\t\t--self::$pointCount;\n\t\t...\n\t}\n\t...\n}\n// -----------------------------------------\nclass MyRangeException extends Exception \n{\n\tpublic function __construct($message, ...)\n\t{\n\t\tparent::__construct($message);\n\t\t...\n\t}\n\t...\n}\n```\n\n# # Destructors\n\n**Syntax**\n\n<pre>\n  <i>destructor-definition:</i>\n    <i>visibility-modifier</i>  function  &<sub>opt</sub>  __destruct  ( ) <i>compound-statement</i>\n</pre>\n\n*visibility-modifier* is described in [§§](#general-23) and *compound-statement* is\ndescribed in [§§](#compound-statements).\n\n**Constraints**\n\nAn overriding destructor in a derived class must have the same or a\nless-restricted [visibility](http://www.php.net/manual/en/language.oop5.visibility.php)\nthan that being overridden in the base class.\n\n**Semantics**\n\nA destructor is a special-named instance method ([§§](#methods)) that is used to\nfree resources when an instance is no longer needed. The destructors for\ninstances of all classes are called automatically once there are no\nhandles pointing to those instances or in some unspecified order during\nprogram shutdown. Like a method, a destructor can return a result by\nvalue or byRef. (Unlike a method, a destructor cannot be abstract or\nstatic.)\n\nIf *visibility-modifier* is omitted, `public` is assumed. \n\nDestructors can be overridden in a derived class by redeclaring them. \n\nDestructors are called by the Engine or from within other destructors.\n\nIf classes in a derived-class hierarchy have destructors, it is the\nresponsibility of the destructor at each level to call the destructor in\nthe base-class explicitly, using the notation `parent::__destruct()`. If\na destructor calls its base-class destructor, it should do so as the\nlast statement in *compound-statement*, so the object hierarchy is\ndestructed from the top-down. A destructor should not call its\nbase-class destructor more than once. A call to a base-class destructor\nsearches for the nearest destructor in the class hierarchy. Not every\nlevel of the hierarchy need have a destructor. A `private` destructor\ninhibits destructor calls from derived classes.\n\nAny dynamic properties\n([§](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12)14.4,\n[§](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12)14.10.8)\nhaving an object type, and whose parent instances exist when the program\nterminates will have their destructors (if any) called as part of the\ncleanup of the parent instances, even if the parent class type has no\ndestructor defined.\n\n**Examples**\n\nSee [§§](#constructors) for an example of a constructor and destructor.\n\n# # Methods with Special Semantics\n\n## # General\n\nIf a class contains a definition for a method having one of the\nfollowing names, that method must have the prescribed visibility,\nsignature, and semantics:\n\nMethod Name\t| Description | Reference\n------------|-------------|----------\n`__call` | Calls a dynamic method in the context of an instance-method call | [§§](#method-__call)\n`__callStatic` | Calls a dynamic method in the context of a static-method call | [§§](#method-__callstatic)\n__clone |Typically used to make a deep copy ([§§](#)) of an object | [§§](#method-__clone)\n`__construct` | A constructor | \t[§§](#constructors)\n`__destruct` | A destructor |\t[§§](#destructors)\n`__get` | Retrieves the value of a given dynamic property |\t[§§](#method-__get)\n`__invoke` | Called when a script calls an object as a function |\t[§§](#method-__invoke)\n`__isset` | Reports if a given dynamic property exists |\t[§§](#method-__isset)\n`__set` | Sets the value of a given dynamic property |\t[§§](#method-__set) \n`__set_state` | Called when a class is exported by `var_export` (§xx) | [§§](#method-__set_state)\n`__sleep` | Executed before serialization ([§§](#serialization)) of an instance of this class | [§§](#method-__sleep)\n`__toString` | Returns a string representation of the instance on which it is called | \t[§§](#method-__tostring)\n`__unset` | Removes a given dynamic property |\t[§§](#method-__unset)\n`__wakeup` | Executed after unserialization ([§§](#serialization)) of an instance of this class | [§§](#method-__wakeup)\n\n## # Method `__call`\n\n**Syntax**\n\n<pre>\n  public  function  __call  (  <i>$name</i>  ,  <i>$arguments</i>  )  <i>compound-statement</i>\n</pre>\n\n*compound-statement* is described in [§§](#compound-statements).\n\n**Constraints**\n\nThe argument corresponding to `$name` must have type `string`, and that\ncorresponding to `$arguments` must have type `array`.\n\nThe arguments passed to this method must not be passed byRef.\n\n**Semantics**\n\nThis instance method is called to invoke the dynamic method ([§§](#dynamic-members))\ndesignated by `$name` using the arguments specified by the elements of\nthe array designated by `$arguments`. It can return any value deemed\nappropriate.\n\nTypically, `__call` is called implicitly, when the `->` operator\n([§§](#member-selection-operator)) is used to call an instance method that is not visible. Now\nwhile `__call` can be called explicitly, the two scenarios do not\nnecessarily produce the same result. Consider the expression `p->m(...)`,\nwhere `p` is an instance and `m` is an instance-method name. If `m` is the\nname of a visible method, `p->m(...)` does not result in `__call`'s being\ncalled. Instead, the visible method is used. On the other hand, the\nexpression `p->__call('m',array(...))` always calls the named dynamic\nmethod, ignoring the fact that a visible method having the same name\nmight exist. If `m` is not the name of a visible method, the two\nexpressions are equivalent; that is; when handling `p->m(...)`, if no\nvisible method by that name is found, a dynamic method is assumed, and\n`__call` is called. (Note: While it would be unusual to create\ndeliberately a dynamic method with the same name as a visible one, the\nvisible method might be added later. This name \"duplication\" is\nconvenient when adding a dynamic method to a class without having to\nworry about a name clash with any method names that class inherits.)\n\nWhile a method-name source token has a prescribed syntax, there are no\nrestrictions on the spelling of the dynamic method name designated by\n*$name*. Any source character is allowed here.\n\n**Examples**\n\n```\nclass Widget\n{\n\tpublic function __call($name, $arguments)\n\t{\n\t\t// using the method name and argument list, redirect/process\n\t\t// the method call, as desired.\n\t}\n\t...\n}\n$obj = new Widget;\n$obj->iMethod(10, TRUE, \"abc\");\t// $obj->__call('iMethod', array(...))\n```\n\n## # Method `__callStatic`\n\n**Syntax**\n\n<pre>\n  public  static  function  __callStatic  (  <i>$name</i>  ,  <i>$arguments</i>  )   <i>compound-statement</i>\n</pre>\n\n*compound-statement* is described in [§§](#compound-statements).\n\n**Constraints**\n\nThe argument corresponding to `$name` must have type `string`, and that\ncorresponding to `$arguments` must have type `array`.\n\nThe arguments passed to this method must not be passed byRef.\n\n**Semantics**\n\nThis static method is called to invoke the dynamic method ([§§](#dynamic-members))\ndesignated by `$name` using the arguments specified by the elements of\nthe array designated by `$arguments`. It can return any value deemed\nappropriate.\n\nTypically, `__callStatic` is called implicitly, when the `::` operator\n([§§](#scope-resolution-operator)) is used to call a static method that is not visible. Now while\n`__callStatic` can be called explicitly, the two scenarios do not\nnecessarily produce the same result. Consider the expression `C::m(...)`,\nwhere `C` is a class and `m` is a static-method name. If `m` is the name of a\nvisible method, `C::m(...)` does not result in `__callStatic`'s being\ncalled. Instead, the visible method is used. On the other hand, the\nexpression `C::__callStatic('m',array(...))` always calls the named\ndynamic method, ignoring the fact that a static visible method having\nthe same name might exist. If m is not the name of a visible method, the\ntwo expressions are equivalent; that is; when handling `C::m(...)`, if no\nvisible method by that name is found, a dynamic method is assumed, and\n`__callStatic` is called. (Note: While it would be unusual to create\ndeliberately a static dynamic method with the same name as a static\nvisible one, the visible method might be added later. This name\n\"duplication\" is convenient when adding a dynamic method to a class\nwithout having to worry about a name clash with any method names that\nclass inherits.)\n\nWhile a method-name source token has a prescribed syntax, there are no\nrestrictions on the spelling of the dynamic method name designated by\n`$name`. Any source character is allowed here.\n\n**Examples**\n\n```\nclass Widget\n{\n    public static function __callStatic($name, $arguments)\n    {\n      // using the method name and argument list, redirect/process\\\n      // the method call, as desired.\n    }\n    ...\n}\n\nWidget::sMethod(NULL, 1.234); // Widget::__callStatic('sMethod', array(...))\n```\n\n## # Method `__clone`\n\n**Syntax**\n\n<pre>\n  public  function  __clone  (  )  <i>compound-statement</i>\n</pre>\n\n*compound-statement* is described in [§§](#compound-statements).\n\n**Semantics**\n\nThis instance method is called by the `clone` operator ([§§](#the-clone-operator)),\n(typically) to make a deep copy ([§§](#)) of the current class component of the instance on which it is\ncalled. (Method `__clone` cannot be called directly by the program.) \n\nConsider a class `Employee`, from which is derived a class `Manager`. Let us\nassume that both classes contain properties that are objects. To make a\ncopy of a `Manager` object, its `__clone` method is called to do whatever\nis necessary to copy the properties for the `Manager` class. That method\nshould, in turn, call the `__clone` method of its parent class,\n`Employee`, so that the properties of that class can also be copied (and\nso on, up the derived-class hierarchy).\n\nTo clone an object, the `clone` operator makes a shallow copy ([§§](#)) of the object on which it is called.\nThen, if the class of the instance being cloned has a method called\n`__clone`, that method is automatically called to make a deep copy.\nMethod `__clone` cannot be called directly from outside a class; it can\nonly be called by name from within a derived class, using the notation\n`self::__clone()`. This method can return a value; however, if it does\nso and control returns directly to the point of invocation via the `clone`\noperator, that value will be ignored. The value returned to a\n`self::__clone()` call can, however, be retrieved.\n\nWhile cloning creates a new object, it does so without using a\nconstructor, in which case, code may need to be added to the `__clone`\nmethod to emulate what happens in a corresponding constructor. (See the\n`Point` example below.)\n\nAn implementation of `__clone` should factor in the possibility of an\ninstance having dynamic properties ([§§](#dynamic-members)).\n\n**Examples**\n\n```\nclass Employee\n{\n\t...\n\tpublic function __clone() \n\t{\n\t\t// do what it takes here to make a copy of Employee object properties\n\t}\n}\nclass Manager extends Employee\n{\n\t...\n\tpublic function __clone() \n\t{\n\t\tparent::__clone(); // request cloning of the Employee properties\n\n\t\t// do what it takes here to make a copy of Manager object properties\n\t}\n\t...\n}\n// -----------------------------------------\nclass Point \n{\n\tprivate static $pointCount = 0;\n\tpublic function __construct($x = 0, $y = 0) \n\t{\n\t\t...\n\t\t++self::$pointCount;\n\t}\n\tpublic function __clone() \n\t{\n\t\t++self::$pointCount; // emulate the constructor\n\t}\n\t...\n}\n$p1 = new Point;\t// created using the constructor\n$p2 = clone $p1; \t// created by cloning\n```\n\n## # Method `__get`\n\n**Syntax**\n\n<pre>\n  public  function  &<sub>opt</sub>  __get  (  <i>$name</i>  )   <i>compound-statement</i>\n</pre>\n\n*compound-statement* is described in [§§](#compound-statements).\n\n**Constraints**\n\nThe argument passed to this method must have type `string` and be passed\nby value.\n\n**Semantics**\n\nThis instance method gets the value of the dynamic property ([§§](#dynamic-members))\ndesignated by `$name`. If no such dynamic property currently exists,\nNULL is returned.\n\nTypically, `__get` is called implicitly, when the `->` operator ([§§](#member-selection-operator))\nis used in a non-lvalue context and the named property is not visible.\nNow while `__get` can be called explicitly, the two scenarios do not\nnecessarily produce the same result. Consider the expression\n`$v = $p->m`, where `p` is an instance and `m` is a property name. If `m` is\nthe name of a visible property, `p->m` does not result in `__get`'s being\ncalled. Instead, the visible property is used. On the other hand, the\nexpression `p->__get('m')` always gets the value of the named dynamic\nproperty, ignoring the fact that a visible property having the same name\nmight exist. If `m` is not the name of a visible property, the two\nexpressions are equivalent; that is; when handling `p->m` in a non-lvalue\ncontext, if no visible property by that name is found, a dynamic\nproperty is assumed, and `__get` is called.\n\nConsider the expression $`v = $p->m = 5`, where `m` is a dynamic\nproperty. While `__set` ([§§](#method-__set)) is called to assign the value 5 to\nthat property, `__get` is not called to retrieve the result after that\nassignment is complete.\n\nIf the dynamic property is an array, `__get` should return byRef, so\nsubscripting can be done correctly on the result.\n\n**Examples**\n\n```\nclass Point \n{\n    private $dynamicProperties = array();\n    private $x;\n    private $y;\n    public function __get($name)\n    {\n        if (array_key_exists($name, $this->dynamicProperties))\n        {\n            return $this->dynamicProperties[$name];\n        }\n\n        // no-such-property error handling goes here\n        return NULL;\n    }\n\t...\n}\n```\n\n**Implementation Notes**\n\nConsider the following class, which does **not** contain a property\ncalled prop:\n\n```\nclass C\n{\n\tpublic function __get($name)\n\t{\n\t\treturn $this->$name;    // must not recurse\n\t}\n\t...\n}\n$c = new C;\n$x = $c->prop;\n```\n\n\nAs no property (dynamic or otherwise) by the name prop exists in the\nclass and a `__get` method is defined, this looks look a recursive\nsituation. However, the implementation must not allow that. The same\napplies to seemingly self-referential implementations of `__set`\n([§§](#method-__set)), `__isset` ([§§](#method-__isset)), and `__unset` ([§§](#method-__unset)).\n\n## # Method `__invoke`\n\n**Syntax**\n\n<pre>\npublic  function  __invoke  ( <i>parameter-declaration-list<sub>opt</sub></i>  )  <i>compound-statement</i>\n</pre>\n\n*parameter-declaration-list* is defined in [§§](#function-definitions); *compound-statement*\nis described in [§§](#compound-statements).\n\n**Semantics**\n\nThis instance method allows an instance to be used with function-call\nnotation. An instance whose class provides this method will return `TRUE`\nwhen passed to `is_callable` (§xx); otherwise, `FALSE` is returned.\n\nWhen an instance is called as a function, the argument list used is made\navailable to `__invoke`, whose return value becomes the value of the\ninitial function call.\n\n**Examples**\n\n```\nclass C\n{\n\tpublic function __invoke($p)\n\t{\n\t\t...\n\t\treturn ...;\n\t}\n\t...\n}\n$c = new C;\nis_callable($c)\t\t// returns TRUE\n$r = $c(123);\t\t// becomes $r = $c->__invoke(123);\t\n```\n\n## # Method `__isset`\n\n**Syntax**\n\n<pre>\npublic  function  __isset  (  <i>$name</i>  )  <i>compound-statement</i>\n</pre>\n\n*compound-statement* is described in [§§](#compound-statements).\n\n**Constraints**\n\nThe argument passed to this method must have type `string` and be passed\nby value.\n\n**Semantics**\n\nIf the dynamic property ([§§](#dynamic-members)) designated by `$name` exists, this\ninstance method returns `TRUE`; otherwise, `FALSE` is returned.\n\nTypically, `__isset` is called implicitly, when the intrinsic `isset`\n([§§](#isset)) is called with an argument that designates a property that\nis not visible. (It can also be called by the intrinsic empty\n([§§](#empty)).) Now while `__isset` can be called explicitly, the two\nscenarios do not necessarily produce the same result. Consider the\nexpression `isset($p->m)`, where `p` is an instance and `m` is a property\nname. If `m` is the name of a visible property, `__isset` is not called.\nInstead, the visible property is used. On the other hand, the expression\n`p->__isset('m')` always tests for the named dynamic property, ignoring\nthe fact that a visible property having the same name might exist. If `m`\nis not the name of a visible property, the two expressions are\nequivalent; that is; when handling `p->m` in a non-lvalue context, if no\nvisible property by that name is found, a dynamic property is assumed.\n\n**Examples**\n\n```\nclass Point \n{\n    private $dynamicProperties = array();\n    private $x;\n    private $y;\n    public function __isset($name)\n    {\n        return isset($this->dynamicProperties[$name]);\n    }\n\t...\n}\n```\n\n**Implementation Notes**\n\nSee the Implementation Notes for `__get` ([§§](#method-__get)).\n\n## # Method `__set`\n\n**Syntax**\n\n<pre>\npublic  function  __set  (  <i>$name</i>  ,  <i>$value</i>  )  <i>compound-statement</i>\n</pre>\n\n*compound-statement* is described in [§§](#compound-statements).\n\n**Constraints**\n\nThe arguments passed to this method must not be passed byRef.\n\nThe argument corresponding to `$name` must have type `string`.\n\n**Semantics**\n\nThis instance method sets the value of the dynamic property ([§§](#dynamic-members))\ndesignated by `$name` to `$value`. If no such dynamic property\ncurrently exists, it is created. No value is returned.\n\nTypically, `__set` is called implicitly, when the `->` operator ([§§](#member-selection-operator))\nis used in a modifiable lvalue context and the named property is not\nvisible. Now while `__set` can be called explicitly, the two scenarios\ndo not necessarily produce the same result. Consider the expression\n`p->m = 5`, where `p` is an instance and `m` is a property name. If `m` is the\nname of a visible property, `p->m` does not result in `__set`'s being\ncalled. Instead, the visible property is used. On the other hand, the\nexpression `p->__set('m',5)` always sets the value of the named dynamic\nproperty, ignoring the fact that a visible property having the same name\nmight exist. If `m` is not the name of a visible property, the two\nexpressions are equivalent; that is; when handling `p->m`, if no visible\nproperty by that name is found, a dynamic property is assumed, and\n`__set` is called. (Note: While it would be unusual to create\ndeliberately a dynamic property with the same name as a visible one, the\nvisible property might be added later. This name \"duplication\" is\nconvenient when adding a dynamic property to a class without having to\nworry about a name clash with any property names that class inherits.)\n\nThe parameter `$value` can have any type including an object type, and\nthat type could have a destructor. Any dynamic properties of such types,\nwhose parent instances exist when the program terminates will have their\ndestructors called as part of the cleanup of the parent instances, even\nif the parent class type has no destructor defined.\n\nWhile a property-name source token has a prescribed syntax, there are no\nrestrictions on the spelling of the dynamic property name designated by\n`$name`. Any source character is allowed here.\n\n**Examples**\n\n```\nclass Point \n{\n    private $dynamicProperties = array();\n    private $x;\n    private $y;\n    public function __set($name, $value)\n    {\n        $this->dynamicProperties[$name] = $value;\n    }\n\t...\n}\n// -----------------------------------------\nclass X\n{\n    public function __destruct() { ... }\n}\n$p = new Point(5, 9);\n$p->thing = new X;  // set dynamic property \"thing\" to instance with destructor\n...\n// at the end of the program, p->thing's destructor is called\n```\n\n**Implementation Notes**\n\nSee the Implementation Notes for `__get` ([§§](#method-__get)).\n\n## # Method `__set_state`\n\n**Syntax**\n\n<pre>\nstatic public  function  __set_state  ( array  <i>$properties</i>  )  <i>compound-statement</i>\n</pre>\n\n*compound-statement* is described in [§§](#compound-statements).\n\n**Constraints**\n\n`$properties` must contain a key/value pair for each instance property\nin the class and all its direct and indirect base classes, where each\nkey is the name of a property in that class.\n\n**Semantics**\n\nThis function supports the library function `var_export` (§xx) when it is\ngiven an instance of this class type. `var_export` takes a variable and\nproduces a string representation of that variable as valid PHP code\nsuitable for use with the intrinsic `eval` ([§§](#eval)). \n\nFor an object, the string returned by `var_export` has the following\ngeneral format:\n\n`classname::__set_state(array('prop1' => value, ..., 'propN'\n=> value , ))` \n\nwhere the property names `prop1` through `propN` do not include a\nleading dollar (`$`). This string contains a call to the `__set_state`\nmethod even if no such method is defined for this class or in any of its\nbase classes, in which case, a subsequent call to `eval` using this string\nwill fail. To allow the string to be used with eval, the method\n`__set_state` must be defined, and it must create a new instance of the\nclass type, initialize its instance properties using the key/value pairs\nin `$properties`, and it must return that new object. \n\nIf a derived class does not define a `__set_state` method, a call to it\nwill look for such a method in the base class hierarchy, and that method\nwill return an instance of the appropriate base class, not of the class\non which it was invoked. This is probably not what the programmer\nexpected. If a derived class defines a `__set_state` method, but any\nbase class has instance properties that are not visible within that\nmethod, that method must invoke parent's `__set_state` as well, but\nthat can require support from a base class. See the second example\nbelow.\n\n**Examples**\n\n```\nclass Point \n{\n\tprivate $x;\n\tprivate $y;\n\tstatic public function __set_state(array $properties)\n\t{\n\t\t$p = new Point;\n\t\t$p->x = $properties['x'];\n\t\t$p->y = $properties['y'];\n\t\treturn $p;\n\t}\n\t...\n}\n$p = new Point(3, 5);\n$v = var_export($p, TRUE);\t// returns string representation of $p\n```\nThe string produced looks something like the following:\n\n```\n\"Point::__set_state(array(\n   'x' => 3,\n   'y' => 5,\n))\" \neval('$z = ' . $v . \";\");\t// execute the string putting the result in $z\necho \"Point \\$z is $z\\n\";\t// Point $z is (3,5)\n// -----------------------------------------\nclass B\t// base class of D\n{\n\tprivate $bprop;\n\tpublic function __construct($p)\n\t{\n\t\t$this->bprop = $p;\n\t}\n\tstatic public function __set_state(array $properties)\n\t{\n\t\t$b = new static($properties['bprop']);\t// note the static\n\t\treturn $b;\n\t\t// Because of the \"new static\", the return statement\n\t\t//   returns a B when called in a B context, and\n\t\t//   returns a D when called in a D context\n\t}\n}\nclass D extends B\n{\n\tprivate $dprop = 123;\n\tpublic function __construct($bp, $dp = NULL)\n\t{\n\t\t$this->dprop = $dp;\n\t\tparent::__construct($bp);\n\t}\n\tstatic public function __set_state(array $properties)\n\t{\n\t\t$d = parent::__set_state($properties); // expects back a D, NOT a B\n\t\t$d->dprop = $properties['dprop'];\n\t\treturn $d;\n\t}\n}\n$b = new B(10);\n$v = var_export($b, TRUE);\neval('$z = ' . $v . \";\");\n$d = new D(20, 30);\n$v = var_export($d, TRUE);\neval('$z = ' . $v . \";\");\n```\n\n## # Method `__sleep`\n\n**Syntax**\n\n<pre>\npublic  function  __sleep  ( ) <i>compound-statement</i>\n</pre>\n\n*compound-statement* is described in [§§](#compound-statements).\n\n**Semantics**\n\nThe instance methods `__sleep` and `__wakeup` ([§§](#method-__wakeup)) support\nserialization ([§§](#serialization)).\n\nIf a class has a `__sleep` method, the library function `serialize` (§xx)\ncalls that method to find out which visible instance properties it\nshould serialize. (In the absence of a `__sleep` or `serialize` method,\nall such properties are serialized, including any dynamic properties\n([§§](#dynamic-members)).) This information is returned by `__sleep` as an array of zero\nor more elements, where each element's value is distinct and is the name\nof a visible instance property. These properties' values are serialized\nin the order in which the elements are inserted in the array. If\n`__sleep` does not return a value explicitly, `NULL` is returned, and that\nvalue is serialized.\n\nBesides creating the array of property names, `__sleep` can do whatever\nelse might be needed before serialization occurs.\n\nConsider a `Point` class that not only contains x- and y-coordinates, it\nalso has an `id` property; that is, each distinct `Point` created during a\nprogram's execution has a unique numerical id. However, there is no need\nto include this when a `Point` is serialized. It can simply be recreated\nwhen that `Point` is unserialized. This information is transient and need\nnot be preserved across program executions. (The same can be true for\nother transient properties, such as those that contain temporary results\nor run-time caches.)\n\nIn the absence of methods `__sleep` and `__wakeup`, instances of derived\nclasses can be serialized and unserialized. However, it is not possible\nto perform customize serialization using those methods for such\ninstances. For that, a class must implement the interface Serializable\n([§§](#interface--serializable)).\n\n**Examples**\n\n```\nclass Point \n{\n\tprivate static $nextId = 1;\n\tprivate $x;\n\tprivate $y;\n\tprivate $id;\n\tpublic function __construct($x = 0, $y = 0) \n\t{\n\t\t$this->x = $x;\n\t\t$this->y = $y;\n\t\t$this->id = self::$nextId++;\t// assign the next available id\n\t}\n\tpublic function __sleep() \n\t{\n\t\treturn array('y', 'x');\t// serialize only $y and $x, in that order\n\t}\n\tpublic function __wakeup() \n\t{\n\t\t$this->id = self::$nextId++;\t// assign a new id\n\t}\n\t...\n}\n$p = new Point(-1, 0);\n$s = serialize($p);\t\t// serialize Point(-1,0)\n$v = unserialize($s);\t\t// unserialize Point(-1,0)\n```\n\n## # Method `__toString`\n\n**Syntax**\n\n<pre>\npublic  function  __toString  ( )  <i>compound-statement</i>\n</pre>\n\n*compound-statement* is described in [§§](#compound-statements).\n\n**Constraints**\n\nThis function must return a string.\n\nThis function must not throw any exceptions.\n\n**Semantics**\n\nThis instance method is intended to create a string representation of\nthe instance on which it is called. If the instance's class is derived\nfrom a class that has or inherits a `__toString` method, the result of\ncalling that method should be prepended to the returned string.\n\n`__toString` is called by a number of language and library facilities,\nincluding `echo`, when an object-to-string conversion is needed.\n`__toString` can be called directly.\n\nAn implementation of `__toString` should factor in the possibility of an\ninstance having dynamic properties ([§§](#dynamic-members)).\n\n**Examples**\n\n```\nclass Point \n{\n\tprivate $x;\n\tprivate $y;\n\tpublic function __construct($x = 0, $y = 0) \n\t{\n\t\t$this->x = $x;\n\t\t$this->y = $y;\n\t}\n\tpublic function __toString() \n\t{\n\t\treturn '(' . $this->x . ',' . $this->y . ')';\n\t}\n\t...\t\n}\n$p1 = new Point(20, 30);\necho $p1 . \"\\n\";\t// implicit call to __toString() returns \"(20,30)\"\n// -----------------------------------------\nclass MyRangeException extends Exception \n{\n\tpublic function __toString() \n\t{\n\t\treturn parent::__toString()\n\t\t\t. string-representation-of-MyRangeException\n\t}\n\t...\n}\n```\n\n## # Method `__unset`\n\n**Syntax**\n\n<pre>\npublic  function  __unset  (  <i>$name</i>  )  <i>compound-statement</i>\n</pre>\n\n*compound-statement* is described in [§§](#compound-statements).\n\n**Constraints**\n\nThe argument passed to this method must have type `string` and be passed\nby value.\n\n**Semantics**\n\nIf the dynamic property ([§§](#dynamic-members)) designated by `$name` exists, it is\nremoved by this instance method; otherwise, the call has no effect. No\nvalue is returned.\n\nTypically, `__unset` is called implicitly, when the intrinsic `unset`\n([§§](#unset)) is called with an argument that designates a property that\nis not visible. Now while `__unset` can be called explicitly, the two\nscenarios do not necessarily produce the same result. Consider the\nexpression `unset($p->m)`, where `p` is an instance and `m` is a property\nname. If `m` is the name of a visible property, `__unset` is not called.\nInstead, the visible property is used. On the other hand, the expression\n`p->__unset('m'))` always removes the named dynamic property, ignoring\nthe fact that a visible property having the same name might exist. If `m`\nis not the name of a visible property, the two expressions are\nequivalent; that is; when handling `p->m` in a non-lvalue context, if no\nvisible property by that name is found, a dynamic property is assumed.\n\n**Examples**\n\n```\nclass Point \n{\n    private $dynamicProperties = array();\n    private $x;\n    private $y;\n    public function __unset($name)\n    {\n        unset($this->dynamicProperties[$name]);\n    }\n\t...\n}\n```\n\n**Implementation Notes**\n\nSee the Implementation Notes for `__get` ([§§](#method-__get)).\n\n## # Method `__wakeup`\n\n**Syntax**\n\n<pre>\npublic  function  __wakeup  ( )  <i>compound-statement</i>\n</pre>\n\n*compound-statement* is described in [§§](#compound-statements).\n\n**Constraints**\n\nXx\n\n**Semantics**\n\nThe instance methods `__sleep` ([§§](#method-__sleep)) and `__wakeup` support\nserialization ([§§](#serialization)).\n\nWhen the library function `unserialize` (§xx) is called on the string\nrepresentation of an object, as created by the library function\n`serialize` (§xx), `unserialize` creates an instance of that object's type\n**without calling a constructor**, and then calls that class's\n`__wakeup` method, if any, to initialize the instance. In the absence of\na `__wakeup` method, all that is done is that the values of the instance\nproperties encoded in the serialized string are restored.\n\nConsider a `Point` class that not only contains x- and y-coordinates, it\nalso has an `id` property; that is, each distinct `Point` created during a\nprogram's execution has a unique numerical id. However, there is no need\nto include this when a `Point` is serialized. It can simply be recreated\nby `__wakeup` when that `Point` is unserialized. This means that\n`__wakeup` must emulate the constructor, as appropriate.\n\n`__wakeup` does not return a value.\n\n**Examples**\n\nSee [§§](#method-__sleep).\n\n# # Serialization\n\nIn PHP, variables can be converted into some external form suitable for\nuse in file storage or inter-program communication. The process of\nconverting to this form is known as *serialization* while that of\nconverting back again is known as *unserialization*. These facilities\nare provided by the library functions `serialize` (§xx) and `unserialize`\n(§xx), respectively.\n\nIn the case of variables that are objects, on their own, these two\nfunctions serialize and unserialize all the instance properties, which\nmay be sufficient for some applications. However, if the programmer\nwants to customize these processes, they can do so in one of two,\nmutually exclusive ways. The first approach is to define methods called\n`__sleep` and `__awake`, and have them get control before serialization\nand after serialization, respectively. For information on this approach,\nsee [§§](#method-__sleep) and [§§](#method-__wakeup). The second approach involves implementing\nthe interface `Serializable` ([§§](#interface--serializable)) by defining two methods, `serialize`\nand `unserialize`.\n\nConsider a `Point` class that not only contains x- and y-coordinates, it\nalso has an `id` property; that is, each distinct `Point` created during a\nprogram's execution has a unique numerical id. However, there is no need\nto include this when a `Point` is serialized. It can simply be recreated\nwhen that `Point` is unserialized. This information is transient and need\nnot be preserved across program executions. (The same can be true for\nother transient properties, such as those that contain temporary results\nor run-time caches.) Furthermore, consider a class `ColoredPoint` that\nextends `Point` by adding a `color` property. The following code shows how\nthese classes need be defined in order for both `Points` and `ColoredPoints`\nto be serialized and unserialized:\n\n```\nclass Point implements Serializable\t// note the interface\n{\n\tprivate static $nextId = 1;\n\tprivate $x;\n\tprivate $y;\n\tprivate $id;\t// transient property; not serialized\n\tpublic function __construct($x = 0, $y = 0) \n\t{\n\t\t$this->x = $x;\n\t\t$this->y = $y;\n\t\t$this->id = self::$nextId++;\n\t}\n\tpublic function __toString() \n\t{\n\t\treturn 'ID:' . $this->id . '(' . $this->x . ',' . $this->y . ')';\n\t}\t\n\tpublic function serialize() \n\t{\n\t\treturn serialize(array('y' => $this->y, 'x' => $this->x));\n\t}\n```\n\nThe custom method `serialize` calls the library function `serialize` to\ncreate a string version of the array, whose keys are the names of the\ninstance properties to be serialized. The insertion order of the array\nis the order in which the properties are serialized in the resulting\nstring. The array is returned.\n\n```\n\tpublic function unserialize($data)\n\t{\n\t\t$data = unserialize($data);\n\t\t$this->x = $data['x'];\n\t\t$this->y = $data['y'];\n\t\t$this->id = self::$nextId++;\n\t}\n}\n```\n\nThe custom method `unserialize` converts the serialized string passed to\nit back into an array. Because a new object is being created, but\nwithout any constructor being called, the `unserialize` method must\nperform the tasks ordinarily done by a constructor. In this case, that\ninvolves assigning the new object a unique id.\n\n```\n$p = new Point(2, 5);\n$s = serialize($p);\n```\n\nThe call to the library function `serialize` calls the custom `serialize`\nmethod. Afterwards, the variable `$s` contains the serialized version of\nthe `Point(2,5)`, and that can be stored in a database or transmitted to a\ncooperating program. The program that reads or receives that serialized\nstring can convert its contents back into the corresponding variable(s),\nas follows:\n\n```\n$v = unserialize($s);\n```\n\nThe call to the library function `unserialize` calls the custom\n`unserialize` method. Afterwards, the variable `$s` contains a new\n`Point(2,5)`.\n\n\n```\nclass ColoredPoint extends Point implements Serializable\n{\n\tconst RED = 1;\n\tconst BLUE = 2;\n\n\tprivate $color;\t// an instance property\n\n\tpublic function __construct($x = 0, $y = 0, $color = RED) \n\t{\n\t\tparent::__construct($x, $y);\n\t\t$this->color = $color;\n\t}\n\n\tpublic function __toString() \n\t{\n\t\treturn parent::__toString() . $this->color;\n\t}\t\n\n\tpublic function serialize() \n\t{\n\t\treturn serialize(array(\n\t\t\t'color' => $this->color,\n\t\t\t'baseData' => parent::serialize()\n\t\t));\n\t}\n```\n\nAs with class `Point`, this custom method returns an array of the instance\nproperties that are to be serialized. However, in the case of the second\nelement, an arbitrary key name is used, and its value is the serialized\nversion of the base Point within the current `ColoredPoint` object. The\norder of the elements is up to the programmer.\n\n```\n    public function unserialize($data)\n    {\n\t\t$data = unserialize($data);\n\t\t$this->color = $data['color'];\n\t\tparent::unserialize($data['baseData']);\n    }\n}\n```\n\nAs `ColoredPoint` has a base class, it unserializes its own instance\nproperties before calling the base class's custom method, so it can\nunserialize the `Point` properties.\n\n```\n$cp = new ColoredPoint(9, 8, ColoredPoint::BLUE);\n$s = serialize($cp);\n...\n$v = unserialize($s);\n```\n\n# # Predefined Classes\n\n# # # Class `Closure`\n\nThe predefined\nclass [`Closure`](http://www.php.net/manual/en/class.closure.php) is used\nfor representing an [anonymous\nfunction](http://www.php.net/manual/en/functions.anonymous.php). It\ncannot be instantiated except by the Engine, as described below.\n\n```\nclass Closure\n{\n\tpublic static bind(Closure $closure, $newthis [, $newscope = \"static\" ]);\n\tpublic bindTo($newthis [, $newscope = \"static\" ]);\n}\n\n```\n\nThe class members are defined below:\n\nName | Purpose\n-----|--------\n`bind` |\tDuplicates closure `$closure` with a specific bound object `$newthis` and class scope `$newscope`. Make `$newthis` `NULL` if the closure is to be unbound. `$newscope` is the class scope to which the closure is to be associated, or static to keep the current one. If an object is given, the type of the object will be used instead. This determines the visibility of protected and private methods of the bound object. Returns a new `Closure` object or `FALSE` on failure.\n`bindTo` |\tDuplicates the closure designated by the current instance with a new-bound object and class scope. This method is an instance version of bind. \n\nWhen the anonymous function-creation operator ([§§](#anonymous-function-creation)) is evaluated,\nthe result is an object of type `Closure` (or some unspecified class\nderived from that type) created by the Engine. This object is referred\nto here as \"the Closure object\". This instance encapsulates the\nanonymous function defined in the corresponding\n*anonymous-function-creation-expression*.\n\nThe contents of a `Closure` object are determined based on the context in\nwhich an anonymous function is created. Consider the following scenario:\n\n```\nclass C\n{\n\tpublic function compute()\n\t{\n\t\t$count = 0;\n\t\t$values = array(\"red\" => 3, 10);\n\t\t$callback = function ($p1, $p2) use (&$count, $values)\n\t\t{\n\t\t\t...\n\t\t};\n\t\t...\n\t}\n}\n\n```\n\nA `Closure` object may contain the following, optional dynamic properties,\nin order: `static`, `this`, and `parameter`.\n\nIf an *anonymous-function-creation-expression* contains an\n*anonymous-function-use-clause*, a dynamic property called `static` is\npresent. This property is an array having an element for each\n*variable-name* in the *use-variable-name-list*, inserted in lexical\norder of their appearance in the use clause. Each element's key is the\ncorresponding *variable-name*, and each element value is the value of\nthat variable at the time the time the `Closure` object is created (not\nwhen it is used to call the encapsulated function). In the scenario\nabove, this leads to the following, shown as pseudo code:\n\n```\n$this->static = array([\"count\"]=>&0,[\"values\"]=>array([\"red\"]=>3,[0]=>10));\n```\n\nIf an *anonymous-function-creation-expression* is used inside an\ninstance method, a dynamic property called `this` is present. This\nproperty is a handle that points to the current instance. In the\nscenario above, this leads to the following, shown as pseudo code:\n\n```\n$this->this = $this;\n```\n\nIf an *anonymous-function-creation-expression* contains a\n*parameter-declaration-list*, a dynamic property called `parameter` is\npresent. This property is an array of one or more elements, each of\nwhich corresponds to a parameter. The elements are inserted in that\narray in lexical order of their declaration. Each element's key is the\ncorresponding parameter name, and each element value is some unspecified\nvalue. (These values are overridden by the argument values used when the\nanonymous function is called.) In the scenario above, this leads to the\nfollowing, shown as pseudo code:\n\n```\n$property = array(\"$p1\" => ???, \"$p2\" => ???)\n```\n\nIt is possible for all three dynamic properties to be absent, in which\ncase, the `Closure` object is empty.\n\n## # Class `Generator`\n\nThis class supports the `yield` operator ([§§](#yield-operator)). This class cannot be\ninstantiated directly. It is defined, as follows:\n\nclass Generator implements Iterator\n\n```\nclass Generator implements Iterator\n{\n\tpublic function current();\n\tpublic function key();\n\tpublic function next();\n\tpublic function rewind();\n\tpublic function send($value) ;\n\tpublic function throw(Exception $exception) ;\n\tpublic function valid();\n\tpublic function __wakeup();\n}\n```\n\nThe class members are defined below:\n\nName | Purpose\n---- | -------\n`current` | An implementation of the instance method `Iterator::current `([§§](#interface-iterator)).\n`key` | An implementation of the instance method `Iterator::key` ([§§](#interface-iterator)).\nnext | An implementation of the instance method Iterator::next ([§§](#interface-iterator)).\n`rewind` | An implementation of the instance method `Iterator::rewind` ([§§](#interface-iterator)).\n`send` | This instance method sends the value designated by `$value` to the generator as the result of the current [`yield`](http://us2.php.net/manual/en/ language.generators.syntax.php#control-structures.yield) expression, and resumes execution of the generator. `$value` is the return value of the [`yield`](http://us2.php.net/manual/en/language.generators.syntax.php#control-structures.yield) expression the generator is currently at. If the generator is not at a [`yield`](http://us2.php.net/manual/en/language.generators.syntax.php#control-structures.yield) expression when this method is called, it will first be let to advance to the first [`yield`](http://us2.php.net/manual/en/language.generators.syntax.php#control-structures.yield) expression before sending the value. This method returns the yielded value.\n`throw` | This instance method throws an exception into the generator and resumes execution of the generator. The behavior is as if the current [`yield`](http://us2.php.net/manual/en/language.generators.syntax.php#control-structures.yield) expression was replaced with throw `$exception`. If the generator is already closed when this method is invoked, the exception will be thrown in the caller's context instead. This method returns the yielded value.\n`valid` |  An implementation of the instance method `Iterator::valid` ([§§](#interface-iterator)).\n`__wakeup` | An implementation of the special instance method `__wakeup` ([§§](#method-__wakeup)). As a generator can't be serialized, this method throws an exception of an unspecified type. It returns no value.\n\n## # Class `__PHP_Incomplete_Class`\n\nThere are certain circumstances in which a program can generate an\ninstance of this class, which on its own contains no members. One\ninvolves an attempt to unserialize ([§§](#method-__wakeup), [§§](#serialization)) a string that\nencodes an instance of a class for which there is no definition in\nscope. Consider the following class, which supports a two-dimensional\nCartesian point:\n\n```\nclass Point \n{\n\tprivate $x;\n\tprivate $y;\n\t...\n}\n$p = new Point(2, 5);\n$s = serialize($p); // properties $x and $y are serialized, in that order\n```\n\nLet us assume that the serialized string is stored in a database from\nwhere it is retrieved by a separate program. That program contains the\nfollowing code, but does not contain a definition of the class Point:\n\n```\n$v = unserialize($s);\n```\n\nInstead of returning a point, `Point(2, 5`), an instance of\n`__PHP_Incomplete_Class` results, with the following contents:\n\n```\n__PHP_Incomplete_Class\n{\n\t __PHP_Incomplete_Class_Name => \"Point\"\n\tx:Point:private => 2\n\ty:Point:private => 5\n}\n```\n\nThe three dynamic properties ([§§](#dynamic-members)) contain the name of the unknown\nclass, and the name, visibility, and value of each property that was\nserialized, in order of serialization.\n\n## # Class `stdClass`\n\nThis class contains no members. It can be instantiated and used as a\nbase class. An instance of this type is automatically created when a\nnon-object is converted to an object ([§§](#converting-to-object-type)), or the member-selection\noperator ([§§](#member-selection-operator)) is applied to `NULL`, `FALSE`, or an empty string.\n\n\n# Interfaces\n\n# # General\n\nA class can implement a set of capabilities—herein called a\n*contract*—through what is called an interface. An *interface* is a set\nof method declarations and constants.  Note that the methods are only\ndeclared, not defined; that is, an interface defines a type consisting\nof abstract methods, where those methods are implemented by client\nclasses as they see fit. An interface allows unrelated classes to\nimplement the same facilities with the same names and types without\nrequiring those classes to share a common base class.\n\nAn interface can extend one or more other interfaces, in which case, it\ninherits all members from its *base interface(s)*.\n\n# # Interface Declarations\n\n**Syntax**\n\n<pre>\n  <i>interface-declaration:</i>\n    interface   <i>name   interface-base-clause<sub>opt</sub></i> {  <i>interface-member-declarations<sub>opt</sub></i>  }\n\n  <i>interface-base-clause:</i>\n    extends   <i>qualified-name</i>\n    <i>interface-base-clause</i>  ,  <i>qualified-name</i>\n</pre>\n\n*name* and *qualified-name* are defined in [§§](#names).\n*interface-member-declarations* is defined in [§§](#interface-members).\n\n**Constraints**\n\nAn interface must not be derived directly or indirectly from itself.\n\n*qualified-name* must name an interface type.\n\n**Semantics**\n\nAn interface-declaration defines a contract that one or more classes can\nimplement.\n\nInterface names are case-insensitive.\n\nThe optional *interface-base-clause* specifies the base interfaces from\nwhich the interface being defined is derived. In such a case, the\nderived interface inherits all the members from the base interfaces.\n\n**Examples**\n\n```\ninterface MyCollection \n{\n\tconst MAX_NUMBER_ITEMS = 1000;\n\tfunction put($item);\n\tfunction get();\n}\nclass MyList implements MyCollection \n{\n\tpublic function put($item)\t{ /* implement method */ }\n\tpublic function get()\t\t{ /* implement method */ }\n\t...\n}\nclass MyQueue implements MyCollection \n{\n\tpublic function put($item)\t{ /* implement method */ }\n\tpublic function get()\t\t{ /* implement method */ }\n\t...\n}\nfunction processCollection(MyCollection $p1)\n{\n\t... /* can process any object whose class implements MyCollection\n}\nprocessCollection(new MyList(...));\nprocessCollection(new MyQueue(...));\n```\n\n# # Interface Members\n\n**Syntax**\n\n<pre>\n  <i>interface-member-declarations:</i>\n    <i>interface-member-declaration</i>\n    <i>interface-member-declarations   interface-member-declaration</i>\n\n  <i>interface-member-declaration:</i>\n    <i>const-declaration</i>\n    <i>method-declaration</i>\n</pre>\n\n*const-declaration* is defined in [§§](#constants-2) and *method-declaration* is\ndefined in [§§](#methods).\n\n**Semantics**\n\nThe members of an interface are those specified by its\n*interface-member-declaration*s, and the members inherited from its base\ninterfaces.\n\nAn interface may contain the following members:\n\n-   Constants – the constant values associated with the interface\n    ([§§](#constants-3)).\n-   Methods – placeholders for the computations and actions that can be\n    performed by implementers of the interface ([§§](#methods-1)).\n\n# # Constants\n\n**Semantics:**\n\nAn interface constant is just like a class constant ([§§](#constants-2)), except that\nan interface constant cannot be overridden by a class that implements it\nnor by an interface that extends it.\n\n**Examples:**\n\n```\ninterface MyCollection \n{\n\tconst MAX_NUMBER_ITEMS = 1000;\n\tfunction put($item);\n\tfunction get();\n}\n```\n\n# # Methods\n\n**Constraints**\n\nAll methods declared in an interface must be implicitly or explicitly\npublic, and they must not be declared `abstract`.\n\n**Semantics:**\n\nAn interface method is just like an abstract method ([§§](#methods)).\n\n**Examples:**\n\n```\ninterface MyCollection \n{\n\tconst MAX_NUMBER_ITEMS = 1000;\n\tfunction put($item);\n\tfunction get();\n}\n```\n\n# # Predefined Interfaces\n\n## # Interface `ArrayAccess`\n\nThis interface allows an instance of an implementing class to be\naccessed using array-like notation. This interface is defined, as\nfollows:\n\n```\ninterface ArrayAccess\n{\n\tfunction offsetExists($offset);\n\tfunction offsetGet($offset);\n\tfunction offsetSet($offset, $value);\n\tfunction offsetUnset($offset);\n}\n```\n\nThe interface members are defined below:\n\nName\t|   Purpose\n----    |   -------\n`offsetExists`  |\tThis instance method returns `TRUE` if the instance contains an element with key `$offset`, otherwise, `FALSE`.\n`offsetGet`\t|  This instance method gets the value having key `$offset`. It may return by value or byRef. (Ordinarily, this wouldn't be allowed because a class implementing an interface needs to match the interface's method signatures; however, the Engine gives special treatment to `ArrayAccess` and allows this.) This method is called when an instance of a class that implements this interface is subscripted ([§§](#subscript-operator)) in a non-lvalue context.\n`offsetSet`\t| This instance method sets the value having key `$offset` to $value. It returns no value. This method is called when an instance of a class that implements this interface is subscripted ([§§](#subscript-operator)) in a modifiable-lvalue context.\n`offsetUnset`\t| This instance method unsets the value having key `$offset`. It returns no value.\n\n## # Interface `Iterator`\n\nThis interface allows instances of an implementing class to be treated\nas a collection. This interface is defined, as follows:\n\n```\ninterface Iterator extends Traversable\n{\n\tfunction current();\n\tfunction key();\n\tfunction next();\n\tfunction rewind();\n\tfunction valid();\n}\n\n```\n\nThe interface members are defined below:\n\nName | Purpose\n---- | -------\n`current` | This instance method returns the element at the current position.\n`key` |This instance method returns the key of the current element. On failure, it returns `NULL`; otherwise, it returns the scalar value of the key.\n`next` | This instance method moves the current position forward to the next element. It returns no value. From within a `foreach` statement, this method is called after each loop.\n`rewind` |  This instance method resets the current position to the first element. It returns no value. From within a `foreach` statement, this method is called once, at the beginning.\n`valid` | This instance method checks if the current position is valid. It takes no arguments. It returns a bool value of `TRUE` to indicate the current position is valid; `FALSE`, otherwise. This method is called after each call to [`Iterator::rewind()`](http://us2.php.net/manual/en/iterator.rewind.php) and [`Iterator::next()`](http://us2.php.net/manual/en/iterator.next.php).\n\n## # Interface `IteratorAggregate`\n\nThis interface allows the creation of an external iterator. This\ninterface is defined, as follows:\n\n```\nInterface IteratorAggregate extends Traversable\n{\n\tfunction getIterator();\n}\n```\nThe interface members are defined below:\n\n\nName\t|   Purpose\n----    |   -------\n`getIterator` | This instance method retrieves an iterator, which implements `Iterator` or `Traversable`. It throws an `Exception` on failure.\n\n## # Interface `Traversable`\n\nThis interface is intended as the base interface for all traversable\nclasses. This interface is defined, as follows:\n\n```\nTraversable\n{\n}\n```\n\nThis interface has no members.\n\n## # Interface  `Serializable`\n\nThis interface provides support for custom serialization. It is defined,\nas follows:\n\n```\ninterface Serializable\n{\n\tfunction serialize();\n\tfunction unserialize ($serialized);\n\n}\n```\n\nThe interface members are defined below:\n\nName |\tPurpose\n-----|  -------\n`serialize` | This instance method returns a string representation of the current instance. On failure, it returns `NULL`.\n`unserialize` | This instance method constructs an object from its string form designated by `$serialized`. It does not return a value.\n\n\n\n# Traits\n\n# # General\n\nPHP's class model allows single inheritance only ([§§](#general-23)) with contracts\nbeing enforced separately via interfaces ([§§](#general-25)). A *trait* can provide\nboth implementation and contracts. Specifically, a class can inherit\nfrom a base class while getting implementation from one or more traits.\nAt the same time, that class can implement contracts from one or more\ninterfaces as well as from one or more traits. The use of a trait by a\nclass does not involve any inheritance hierarchy, so unrelated classes\ncan use the same trait. In summary, a trait is a set of methods and/or\nstate information that can be reused.\n\nTraits are designed to support classes; a trait cannot be instantiated\ndirectly.\n\nThe members of a trait each have visibility ([§§](#general-23)), which applies once\nthey are used by a given class. The class that uses a trait can change\nthe visibility of any of that trait's members, by either widening or\nnarrowing that visibility. For example, a private trait member can be\nmade public in the using class, and a pubic trait member can be made\nprivate in that class.\n\nOnce implementation comes from both a base class and one or more traits,\nname conflicts can occur. However, trait usage provides a means of\ndisambiguating such conflicts. Names gotten from a trait can also be\ngiven aliases.\n\nA class member with a given name overrides one with the same name in any\ntraits that class uses, which, in turn, overrides any such name from\nbase classes. \n\nTraits can contain both instance and static members, including both\nmethods and properties. In the case of a trait with a static property,\neach class using that trait has its own instance of that property.\n\nMethods in a trait have full access to all members of any class in which\nthat trait is used.\n\n# # Trait Declarations\n\n**Syntax**\n\n<pre>\n  <i>trait-declaration:</i>\n    trait   <i>name</i>   {   <i>trait-use-clauses<sub>opt</sub>   trait-member-declarations<sub>opt</sub></i>   }\n\n  <i>trait-use-clauses:</i>\n    <i>trait-use-clause</i>\n    <i>trait-use-clauses   trait-use-clause</i>\n\n  <i>trait-use-clause:</i>\n    use   <i>trait-name-list   trait-use-terminator</i>\n\n  <i>trait-name-list:</i>\n    <i>qualified-name</i>\n    <i>trait-name-list</i>   ,   <i>qualified-name</i>\n\n  <i>trait-use-terminator:</i>\n    ;\n    {   <i>trait-select-and-alias-clauses<sub>opt</sub></i>   }\n\n  <i>trait-select-and-alias-clauses:</i>\n    <i>trait-select-and-alias-clause</i>\n    <i>trait-select-and-alias-clauses   trait-select-and-alias-clause</i>\n\n  <i>trait-select-and-alias-clause:</i>\n    <i>trait-select-insteadof-clause</i>\n    <i>trait-alias-as-clause</i>\n\n  <i>trait-select-insteadof-clause:</i>\n    <i>name</i>   insteadof   <i>name</i>\n\n  trait-alias-as-clause:\n    <i>name</i>   as   <i>visibility-modifier<sub>opt</sub>   name</i>\n    <i>name</i>   as   <i>visibility-modifier   name<sub>opt</sub></i>\n</pre>\n\n*name* is defined in [§§](#names); *visibility-modifier* is defined in\n[§§](#properties); and *trait-member-declarations* is defined in [§§](#trait-members).\n\n**Constraints**\n\nThe *name*s in *trait-name-list* must designate trait names, excluding\nthe name of the trait being declared.\n\nThe left-hand *name* in *trait-select-insteadof-clause* must\nunambiguously designate a member of a trait made available by\n*trait-use-clauses*. The right-hand *name* in\n*trait-select-insteadof-clause* must unambiguously designate a trait\nmade available by *trait-use-clauses*.\n\nThe left-hand *name* in *trait-alias-as-clause* must unambiguously\ndesignate a member of a trait made available by *trait-use-clauses*.\nThe right-hand *name* in *trait-alias-as-clause* must be a new,\nunqualified name.\n\n**Semantics**\n\nA *trait-declaration* defines a named set of members, which are made\navailable to any class that uses that trait.\n\nTrait names are case-insensitive.\n\nA *trait-declaration* may also use other traits. This is done via one or\nmore *trait-use-clause*s, each of which contains a comma-separated list\nof trait names. A *trait-use-clause* ends in a semicolon or a\nbrace-delimited set of *trait-select-insteadof-clause*s and\n*trait-alias-as-clause*s.\n\nA *trait-select-insteadof-clause* allows name clashes to be avoided.\nSpecifically, the left-hand *name* designates which name to be used from\nof a pair of names. That is, `T1::compute insteadof T2`; indicates that\ncalls to method compute, for example, should be satisfied by a method of\nthat name in trait `T1` rather than `T2`.\n\nA *trait-alias-as-clause* allows a (possibly qualified) name to be\nassigned a simple alias name. Specifically, the left-hand *name* in\n*trait-alias-as-clause* designates a name made available by\n*trait-use-clauses* ~~ that is to be aliased, and the right-hand *name*\nis the alias.\n\nIf *trait-alias-as-clause* contains a visibility-modifier, that controls\nthe visibility of the alias, if a right-hand name is provided;\notherwise, it controls the visibility of the left-hand name.\n\n**Examples**\n\n```\ntrait T1 { public function compute( ... ) { ... } }\ntrait T2 { public function compute( ... ) { ... } }\ntrait T1 { public function sort( ... ) { ... } }\ntrait T4\n{\n\tuse T3;\n\tuse T1, T2\n\t{\n\t\tT1::compute insteadof T2;\t// disambiguate between two computes\n\t\tT3::sort as private sorter;\t// make alias with adjusted visibility\n\t}\n}\n```\n\n# # Trait Members\n\n**Syntax**\n\n<pre>\n  <i>trait-member-declarations:</i>\n    <i>trait-member-declaration</i>\n    <i>trait-member-declarations   trait-member-declaration</i>\n\n  <i>trait-member-declaration:</i>\n    <i>property-declaration</i>\n    <i>method-declaration</i>\n    <i>constructor-declaration</i>\n    <i>destructor-declaration</i>\n</pre>\n\n*property-declaration* is defined in [§§](#properties); *method-declaration* is\ndefined in [§§](#methods); *constructor-declaration* is defined in [§§](#names); and\n*destructor-declaration* is defined in [§§](#destructors).\n\n**Semantics**\n\nThe members of a trait are those specified by its\n*trait-member-declaration*s, and the members from any other traits it\nuses.\n\nA trait may contain the following members:\n\n-   Properties – the variables made available to the class in which the\n    trait is used ([§§](#properties)).\n-   Methods – the computations and actions that can be performed by the\n    class in which the trait is used ([§§](#methods), [§§](#methods-with-special-semantics)).\n-   Constructor – the actions required to initialize an instance of the\n    class in which the trait is used ([§§](#constructors))\n-   Destructor – the actions to be performed when an instance of the\n    class in which the trait is used is no longer needed ([§§](#destructors)).\n\nIf a member has no explicit visibility, `public` is assumed.\n\n**Examples**\n\n```\ntrait T\n{\n\tprivate $prop1 = 1000;\n\tprotected static $prop2;\n\tvar $prop3;\n\tpublic function compute( ... ) { ... }\n\tpublic static function getData( ... ) { ... }\n}\n```\n\n\n# Exception Handling\n\n# # General\n\nAn *exception* is some unusual condition in that it is outside the\nordinary expected behavior. (Examples include dealing with situations in\nwhich a critical resource is needed, but is unavailable, and detecting\nan out-of-range value for some computation.) As such, exceptions require\nspecial handling. This clause describes how exceptions can be created\nand handled.\n\nWhenever some exceptional condition is detected at runtime, an exception\nis *thrown*. A designated exception handler can *catch* the thrown\nexception and service it. Among other things, the handler might recover\nfrom the situation completely (allowing the script to continue\nexecution), it might perform some recovery and then throw an exception\nto get further help, or it might perform some cleanup action and\nterminate the script. Exceptions may be thrown on behalf of the Engine\nor by explicit code source code in the script.\n\nException handling involves the use of the following keywords:\n\n-   `try` ([§§](#the-try-statement)), which allows a *try-block* of code containing one or\n    more possible exception generations, to be tried\n-   `catch` ([§§](#the-try-statement)), which defines a handler for a specific type of\n    exception thrown from the corresponding try-block or from some\n    function it calls\n-   `finally` ([§§](#the-try-statement)), which allows the *finally-block* of a try-block to\n    be executed (to perform some cleanup, for example), whether or not\n    an exception occurred within that try-block\n-   `throw` ([§§](#the-throw-statement)), which generates an exception of a given type, from\n    a place called a *throw point*\n\nWhen an exception is thrown, an *exception object* of type `Exception`\n([§§](#class-exception)), or of a subclass of that type, is created and made available to\nthe first catch-handler that can catch it. Among other things, the\nexception object contains an *exception message* and an *exception\ncode*, both of which can be used by a handler to determine how to handle\nthe situation.\n\nPrior to the addition of exception handling to PHP, exception-like\nconditions were handled using Error Reporting (§xx). Now, errors can be\ntranslated to exceptions via the class\n[`ErrorException`](http://www.php.net/manual/en/class.errorexception.php)\n(which is not part of this specification).\n\n# # Class `Exception`\n\nClass `Exception` is the base class of all exception types. This class is\ndefined, as follows:\n\n```\nClass Exception\n{\n\tprivate   $string;\n\tprivate   $trace;\n\tprivate   $previous;\n\n\tprotected $message = 'Unknown exception';\n\tprotected $code = 0;\n\tprotected $file;\n\tprotected $line;\n\n\tpublic function __construct($message = \"\", $code = 0,\n \t\t\t\t\t\t\t\tException $previous = NULL);\n\n\tfinal private function __clone();\n\n\tfinal public  function getMessage();\n\tfinal public  function getCode();\n\tfinal public  function getFile();\n\tfinal public  function getLine();\n\tfinal public  function getTrace();\n\tfinal public  function getPrevious();\n\tfinal public  function getTraceAsString();\n\tpublic function __toString();\n}\n```\n\nFor information about exception trace-back, see [§§](#tracing-exceptions). For information\nabout nested exceptions, see [§§](#tracing-exceptions). \n\nThe class members are defined below:\n\nName\t| Purpose\n----    | -------\n`$code`\t| `int`; the exception code (as provided by the constructor)\n`$file`\t| `string`; the name of the script where the exception was generated\n`$line`\t| `int`; the source line number in the script where the exception was generated\n`$message`\t| `string`; the exception message (as provided by the constructor)\n`$previous`\t| The previous exception in the chain, if this is a nested exception; otherwise, `NULL`\n`$string`\t| Work area for `__toString`\n`$trace`\t| Work area for function-call tracing\n`__construct`\t| Takes three (optional) arguments – `string`: the exception message (defaults to \"\"), `int`: the exception code (defaults to 0), and `Exception`: the previous exception in the chain (defaults to `NULL`)\n`__clone`\t| Present to inhibit the cloning of exception objects\n`__toString`\t| `string`; retrieves a string representation of the exception in some unspecified format\n`getCode`\t| `mixed`; retrieves the exception code (as set by the constructor). For an exception of type Exception, the returned value has type int; for subclasses of `Exception`, it may have some other type.\n`getFile`\t| `string`; retrieves the name of the script where the exception was generated\n`getLine`\t| `int`; retrieves the source line number in the script where the exception was generated\n`getMessage`\t| `string`; retrieves the exception message\n`getPrevious`\t| `Exception`; retrieves the previous exception (as set by the constructor), if one exists; otherwise, `NULL`\n`getTrace`\t| `array`; retrieves the function stack trace information as an array (see [§§](#tracing-exceptions))\n`getTraceAsString`\t| `string`; retrieves the function stack trace information formatted as a single string in some unspecified format\n\n# # Tracing Exceptions\n\nWhen an exception is caught, the `get*` functions in class `Exception`\nprovide useful information. If one or more nested function calls were\ninvolved to get to the place where the exception was generated, a record\nof those calls is also retained, and made available by getTrace, through\nwhat is referred to as the *function stack trace*, or simply, `*trace*`.\n\nLet's refer to the top level of a script as *function-level* 0.\nFunction-level 1 is inside any function called from function-level 0.\nFunction-level 2 is inside any function called from function-level 1,\nand so on. The library function `getTrace` returns an array. Exceptions\ngenerated at function-level 0 involve no function call, in which case,\nthe array returned by `getTrace` has zero elements.\n\nEach element of the array returned by `getTrace` provides information\nabout a given function level. Let us call this array *trace-array* and\nthe number of elements in this array *call-level*. The key for each of\ntrace-array's elements has type int, and ranges from 0 to\ncall-level - 1. For example, when a top-level script calls function `f1`,\nwhich calls function `f2`, which calls function `f3`, which then generates\nan exception, there are four function levels, 0–3, and there are three\nlots of trace information, one per call level. That is, trace-array\ncontains three elements, and they each correspond to the reverse order\nof the function calls. For example, trace-array[0] is for the call to\nfunction `f3`, trace-array[1] is for the call to function `f2`, and\ntrace-array[2] is for the call to function `f1`.\n\nEach element in trace-array is itself an array that contains elements\nwith the following key/value pairs:\n\nKey\t| Value Type\t| Value\n--- | ----------    | -----\n\"args\"\t| `array`\t| The set of arguments passed to the function\n\"class\"\t| `string` |\tThe name of the function's parent class\n\"file\"\t| `string` |\tThe name of the script where the function was called\n\"function\"\t| `string` |\tThe name of the function or class method\n\"line\"\t| `int` |\tThe line number in the source where the function was called\n\"object\" |\t`object` | The current object\n\"type\"\t| `string` |\tType of call; `->` for an instance method call, `::` for a static method call, ordinary function call, \"\" is returned.\n\nAs to whether extra elements with other keys are provided is\nunspecified.\n\nThe key `args` has a value that is yet another array, which we shall\ncall *argument-array*. That array contains a set of values that\ncorresponds directly to the set of values passed as arguments to the\ncorresponding function. Regarding element order, argument-array[0]\ncorresponds to the left-most argument, argument-array[1] corresponds to\nthe next argument to the right, and so on.\n\nConsider the case in which a function has a default argument value\ndefined for a parameter. If that function is called without an argument\nfor the parameter having the default value, no corresponding argument\nexists in array-argument. Only arguments present at the function-call\nsite have their values recorded in array-argument. \n\nSee also, library functions `debug_backtrace` (§xx) and\n`debug_print_backtrace` (§xx).\n\n# # User-Defined Exception Classes\n\nAn exception class is defined simply by having it extend class `Exception`\n([§§](#class-exception)). However, as that class's `__clone` method is declared `final`\n([§§](#methods)), exception objects cannot be cloned.\n\nWhen an exception class is defined, typically, its constructors call the\nparent class' constructor as their first operation to ensure the\nbase-class part of the new object is initialized appropriately. They\noften also provide an augmented implementation of\n[`__toString()`](http://www.php.net/manual/en/language.oop5.magic.php)\n([§§](#method-__tostring)).\n\n\n# Namespaces\n\n# # General\n\nA problem encountered when managing large projects is that of avoiding\nthe use of the same name in the same scope for different purposes. This\nis especially problematic in a language that supports modular design and\ncomponent libraries.\n\nA *namespace* is a container for a set of (typically related)\ndefinitions of classes, interfaces, traits, functions, and constants.\nNamespaces serve two purposes:\n\n-   They help avoid name collisions.\n-   They allow certain long names to be accessed via shorter, more\n    convenient and readable, names.\n\nA namespace may have *sub-namespaces*, where a sub-namespace name shares\na common prefix with another namespace. For example, the namespace\n`Graphics` might have sub-namespaces `Graphics\\D2` and `Graphics\\D3`, for\ntwo- and three-dimensional facilities, respectively. Apart from their\ncommon prefix, a namespace and its sub-namespaces have no special\nrelationship. The namespace whose prefix is part of a sub-namespace need\nnot actually exist for the sub-namespace to exist. That is, `NS1\\Sub` can\nexist without `NS1`.\n\nIn the absence of any namespace definition, the names of subsequent\nclasses, interfaces, traits, functions, and constants are in the\n*default namespace*, which has no name, per se.\n\nThe namespaces PHP, php, and sub-namespaces beginning with those\nprefixes are reserved for use by PHP.\n\n# # Name Lookup\n\nWhen an existing name is used in source code, the Engine must determine\nhow that name is found with respect to namespace lookup. For this\npurpose, names can have one of the three following forms:\n\n-   Unqualified name: Such names are just simple names without any\n    prefix, as in the class name `Point` in the following expression:\n    `$p = new Point(3,5)`. If the current namespace is `NS1`, the name\n    `Point` resolves to `NS1\\Point`. If the current namespace is the\n    default namespace ([§§](#general-28)), the name `Point` resolves to `Point`. In the\n    case of an unqualified function or constant name, if that name does\n    not exist in the current namespace, a global function or constant by\n    that name is used.\n-   Qualified name: Such names have a prefix consisting of a namespace\n    name and/or one or more levels of sub-namespace names, and,\n    possibly, a class, interface, trait, function, or constant name.\n    Such names are relative. For example, `D2\\Point` could be used to\n    refer to the class Point in the sub-namespace `D2` of the current\n    namespace. One special case of this is when the first component of\n    the name is the keyword `namespace`. This means \"the current\n    namespace\".\n-   Fully qualified name: Such names begin with a backslash (`\\`) and are\n    followed optionally by a namespace name and one or more levels of\n    sub-namespace names, and, finally, a class, interface, trait,\n    function, or constant name. Such names are absolute. For example,\n    `\\Graphics\\D2\\Point` could be used to refer unambiguously to the\n    class `Point` in namespace `Graphics`, sub-namespace `D2`.\n   \nThe names of the standard types (such as `Exception`), constants (such as\n`PHP_INT_MAX`), and library functions (such as `is_null`) are defined outside\nany namespace. To refer unambiguously to such names, one can prefix them\nwith a backslash (`\\`), as in `\\Exception`, `\\PHP_INT_MAX`, and `\\is_null`.\n\n# # Defining Namespaces\n\n**Syntax**\n\n<pre>\n  <i>namespace-definition:</i>\n    namespace  <i>namespace-name</i>  ;\n    namespace  <i>namespace-name<sub>opt</sub>   compound-statement</i>\n</pre>\n\n*namespace-name* is defined in [§§](#names), and *compound-statement* is\ndefined in [§§](#compound-statements).\n\n**Constraints**\n\nExcept for white space and an optional *declare-statement* ([§§](#the-declare-statement)), the\nfirst occurrence of a *namespace-definition* in a script must be the\nfirst thing in that script.\n\nAll occurrence of a *namespace-definition* in a script must have the\n*compound-statement* form or must not have that form; the two forms\ncannot be mixed.\n\nWhen a script contains source code that is not inside a namespace, and\nsource code that is inside one or namespaces, the namespaced code must\nuse the *compound-statement* form of *namespace-definition*.\n\n*compound-statement* must not contain a *namespace-definition*.\n\n**Semantics**\n\nAlthough a namespace may contain any PHP source code, the fact that that\ncode is contained in a namespace affects only the declaration and name\nresolution of classes, interfaces, traits, functions, and constants.\n\nNamespace and sub-namespace names are case-insensitive.\n\nThe pre-defined constant `__NAMESPACE__` ([§§](#context-dependent-constants)) contains the name of\nthe current namespace.\n\nWhen the same namespace is defined in multiple scripts, and those\nscripts are combined into the same program, the namespace is considered\nthe merger of its individual contributions.\n\nThe scope of the non-*compound-statement* form of *namespace-definition*\nruns until the end of the script, or until the lexically next\n*namespace-definition*, whichever comes first. The scope of the\n*compound-statement* form is the *compound-statement*.\n\n**Examples**\n\nScript1.php:\n```\nnamespace NS1;\n...\t\t\t\t// __NAMESPACE__ is \"NS1\"\nnamespace NS3\\Sub1;\n...\t\t\t\t// __NAMESPACE__ is \"NS3\\Sub1\"\n```\n\nScript2.php:\n```\nnamespace NS1\n{\n...\t\t\t\t// __NAMESPACE__ is \"NS1\"\n}\nnamespace\n{\n...\t\t\t\t// __NAMESPACE__ is \"\"\n}\nnamespace NS3\\Sub1;\n{\n...\t\t\t\t// __NAMESPACE__ is \"NS3\\Sub1\"\n}\n```\n\n# # Namespace Use Declarations**\n\n**Syntax**\n\n<pre>\n  <i>namespace-use-declaration:</i>\n    use  <i>namespace-use-clauses</i>  ;\n\n  <i>namespace-use-clauses:</i>\n    <i>namespace-use-clause</i>\n    <i>namespace-use-clauses</i>  ,  <i>namespace-use-clause</i>\n\n  <i>namespace-use-clause:</i>\n    <i>qualified-name   namespace-aliasing-clause<sub>opt</sub></i>\n\n  <i>namespace-aliasing-clause:</i>\n    as  <i>name</i>\n</pre>\n\n*qualified-name* and *name* are defined in [§§](#names).\n\n**Constraints**\n\nA *namespace-use-declaration* must not occur except at the pseudomain\nlevel or directly in the context of a *namespace-definition* (18.3).\n\nIf the same *qualified-name* is imported multiple times in the same\nscope, each occurrence must have a different alias.\n\n**Semantics**\n\n*qualified-name* is always interpreted as referring to a class,\ninterface, or trait by that name. *namespace-use-clauses* can only\ncreate aliases for classes, interfaces, or traits; it is not possible to\nuse them to create aliases to functions or constants.\n\nA *namespace-use-declaration* *imports*—that is, makes available—one or\nmore names into a scope, optionally giving them each an alias. Each of\nthose names may designate a namespace, a sub-namespace, a class, an\ninterface, or a trait. If a namespace-alias-clause is present, its\n*name* is the alias for *qualified-name*. Otherwise, the right-most name\nin *qualified-name* is the implied alias for *qualified-name*.\n\n**Examples**\n\n```\nnamespace NS1\n{\n\tconst CON1 = 100;\n\tfunction f() { ... }\n\tclass C { ... }\n\tinterface I { ... }\n\ttrait T { ... }\n}\n\nnamespace NS2\n{\n\tuse \\NS1\\C, \\NS1\\I, \\NS1\\T;\n\tclass D extends C implements I\n\t{\n\t\tuse T;\n\t}\n\t$v = \\NS1\\CON1;\t// explicit namespace still needed for constants\n\t\\NS1\\f();\t\t// explicit namespace still needed for functions\n\n\tuse \\NS1\\C as C2;\t// C2 is an alias for the class name \\NS1\\C\n\t$c2 = new C2;\n}\n```\n\n# Grammar\n\n# # General\n\nThe grammar notation is described in [§§](#grammars).\n\n# # Lexical Grammar\n\n## # General\n\n<pre>\n  <i>input-file::\n    <i>input-element\n    <i>input-file   input-element\n  <i>input-element::</i>\n    <i>comment</i>\n    <i>white-space</i>\n    <i>token</i>\n</pre>\n\n## # Comments\n\n<pre>\n  <i>comment::</i>\n    <i>single-line-comment</i>\n    <i>delimited-comment</i>\n    \n  <i>single-line-comment::</i>\n    //   <i>input-characters<sub>opt</sub></i>\n      #    <i>input-characters<sub>opt</sub></i>\n\n  <i>input-characters::</i>\n    <i>input-character</i>\n    <i>input-characters   input-character</i>\n\n  <i>input-character::</i>\n    Any source character except new-line\n    \n  <i>new-line::</i>\n    Carriage-return character (U+000D)\n    Line-feed character (U+000A)\n    Carriage-return character (U+000D) followed by line-feed character (U+000A)\n\n  <i>delimited-comment::</i>\n    /*   No characters or any source character sequence except /*   */\n</pre>\n\n## # White Space\n\n<pre>\n  <i>white-space::</i>\n    <i>white-space-character</i>\n    <i>white-space   white-space-character</i>\n\n  <i>white-space-character::</i>\n    <i>new-line</i>\n    Space character (U+0020)\n    Horizontal-tab character (U+0009)\n</pre>\n\n## # Tokens\n\n### # General\n\n<pre>\n  <i>token::</i>\n    <i>variable-name</i>\n    <i>name</i>\n    <i>keyword</i>\n    <i>literal</i>\n    <i>operator-or-punctuator</i>\n</pre>\n\n### # Names\n\n<pre>\n  <i>variable-name::</i>\n    $   <i>name</i>\n\n  <i>namespace-name::</i>\n    <i>name </i>\n    <i>namespace-name   \\   name</i>\n    \n  <i>namespace-name-as-a-prefix::</i>\n    \\\n    \\<sub>opt</sub>   <i>namespace-name</i>   \\\n    namespace   \\\n    namespace   \\   <i>namespace-name</i>   \\\n    \n  <i>qualified-name::</i>\n    <i>namespace-name-as-a-prefix<sub>opt</sub>   name</i>\n    \n  <i>name::</i>\n    <i>name-nondigit</i>\n    <i>name   name-nondigit</i>\n    <i>name   digit</i>\n\n  <i>name-nondigit::</i>\n    <i>nondigit</i>\n    one of the characters U+007f–U+00ff\n\n  <i>nondigit::</i> one of\n    _\n    a   b   c   d   e   f   g   h   i   j   k   l   m\n    n   o   p   q   r   s   t   u   v   w   x   y   z\n    A   B   C   D   E   F   G   H   I   J   K   L   M\n    N   O   P   Q   R   S   T   U   V   W   X   Y   Z\n</pre>\n\n## # Keywords\n\n<pre>\n  <i>keyword::</i> one of\n    abstract   and   as   break   callable   case   catch   class   clone   \n    const   continue   declare   default   do   echo   else   elseif   \n    enddeclare   endfor   endforeach   endif   endswitch   endwhile\n    extends   final   finally   for   foreach   function   global\n    goto   if   implements   include   include_once   instanceof\n    insteadof   interface   namespace   new or   print   private\n    protected   public   require   require_once   return static   switch\n    throw   trait   try   use   var   while   xor   yield\n</pre>\n\n## # Literals\n\n### # General\n\n<pre>\n  <i>literal::\n    <i>boolean-literal</i>\n    <i>integer-literal</i>\n    <i>floating-literal</i>\n    <i>string-literal</i>\n    <i>null-literal</i>\n</pre>\n\n### # Boolean Literals\n\n<pre>\n  <i>boolean-literal::</i>\n    TRUE (written in any case combination)\n    FALSE (written in any case combination)\n</pre>\n\n### # Integer Literals\n\n<pre>\n  <i>integer-literal::</i>\n    <i>decimal-literal</i>\n    <i>octal-literal</i>\n    <i>hexadecimal-literal</i>\n    <i>binary-literal</i>\n\n    <i>decimal-literal::</i>\n      <i>nonzero-digit</i>\n      <i>decimal-literal   digit</i>\n\n    <i>octal-literal::</i>\n      0\n      <i>octal-literal   octal-digit</i>\n\n    <i>hexadecimal-literal::</i>\n      <i>hexadecimal-prefix   hexadecimal-digit</i>\n      <i>hexadecimal-literal   hexadecimal-digit</i>\n\n    <i>hexadecimal-prefix:: one of</i>\n      0x  0X\n\n    <i>binary-literal::</i>\n      <i>binary-prefix   binary-digit</i>\n      <i>binary-literal   binary-digit</i>\n\n    <i>binary-prefix:: one of</i>\n      0b  0B\n\n    <i>digit:: one of</i>\n      0  1  2  3  4  5  6  7  8  9\n\n    <i>nonzero-digit:: one of</i>\n      1  2  3  4  5  6  7  8  9\n      \n    <i>octal-digit:: one of</i>\n      0  1  2  3  4  5  6  7\n\n    <i>hexadecimal-digit:: one of</i>\n      0  1  2  3  4  5  6  7  8  9\n            a  b  c  d  e  f\n            A  B  C  D  E  F\n\n    <i>binary-digit:: one of</i>\n        0  1\n</pre>\n\n### # Floating-Point Literals\n\n<pre>\n  <i>ﬂoating-literal::</i>\n    <i>fractional-literal   exponent-part<sub>opt</sub></i>\n    <i>digit-sequence   exponent-part</i>\n\n  <i>fractional-literal::</i>\n    <i>digit-sequence<sub>opt</sub></i> . <i>digit-sequence</i>\n    <i>digit-sequence</i> .\n\n  <i>exponent-part::</i>\n    e  <i>sign<sub>opt</sub>   digit-sequence</i>\n    E  <i>sign<sub>opt</sub>   digit-sequence</i>\n\n  <i>sign:: one of</i>\n    +  -\n\n  <i>digit-sequence::</i>\n    <i>digit</i>\n    <i>digit-sequence   digit</i>\n</pre>\n\n### # String Literals\n\n<pre>\n  <i>string-literal::</i>\n    <i>single-quoted-string-literal</i>\n    <i>double-quoted-string-literal</i>\n    <i>heredoc-string-literal</i>\n    <i>nowdoc-string-literal</i>\n\n  <i>single-quoted-string-literal::</i>\n    b<i><sub>opt</sub></i>  ' <i>sq-char-sequence<sub>opt</sub></i>  '\n\n  <i>sq-char-sequence::</i>\n    <i>sq-char</i>\n    <i>sq-char-sequence   sq-char</i>\n\n  <i>sq-char::</i>\n    <i>sq-escape-sequence</i>\n    \\<i><sub>opt</sub></i>   any member of the source character set except single-quote (') or backslash (\\)\n\n  <i>sq-escape-sequence:: one of</i>\n    \\'  \\\\\n\n  <i>double-quoted-string-literal::</i>\n    b<i><sub>opt</sub></i>  \" <i>dq-char-sequence<sub>opt</sub></i>  \"\n\n  <i>dq-char-sequence::</i>\n    <i>dq-char</i>\n    <i>dq-char-sequence   dq-char</i>\n\n  <i>dq-char::</i>\n    <i>dq-escape-sequence</i>\n    any member of the source character set except double-quote (\") or backslash (\\)\n    \\  any member of the source character set except \"\\$efnrtvxX or\noctal-digit\n\n  <i>dq-escape-sequence::</i>\n    <i>dq-simple-escape-sequence</i>\n    <i>dq-octal-escape-sequence</i>\n    <i>dq-hexadecimal-escape-sequence</i>\n\n  <i>dq-simple-escape-sequence:: one of</i>\n    \\\"   \\\\   \\$   \\e   \\f   \\n   \\r   \\t   \\v\n\n  <i>dq-octal-escape-sequence::</i>\n    \\   <i>octal-digit</i>\n    \\   <i>octal-digit   octal-digit</i>\n    \\   <i>octal-digit   octal-digit   octal-digit</i>\n\n  <i>dq-hexadecimal-escape-sequence::</i>\n    \\x  <i>hexadecimal-digit   hexadecimal-digit<sub>opt</sub></i>\n    \\X  <i>hexadecimal-digit   hexadecimal-digit<sub>opt</sub></i>\n\n  <i>heredoc-string-literal::</i>\n    <<<  <i>hd-start-identifier   new-line   hd-char-sequence<sub>opt</sub>  new-line hd-end-identifier</i>  ;<i><sub>opt</sub>   new-line</i>\n\n  <i>hd-start-identifier::</i>\n    <i>name</i>\n\n  <i>hd-end-identifier::</i>\n    <i>name</i>\n\n  <i>hd-char-sequence::</i>\n    <i>hd-char</i>\n    <i>hd-char-sequence   hd-char</i>\n\n  <i>hd-char::</i>\n    <i>hd-escape-sequence</i>\n    any member of the source character set except backslash (\\)\n    \\  any member of the source character set except \\$efnrtvxX or\noctal-digit\n\n  <i>hd-escape-sequence::</i>\n    <i>hd-simple-escape-sequence</i>\n    <i>dq-octal-escape-sequence</i>\n    <i>dq-hexadecimal-escape-sequence</i>\n\n  <i>hd-simple-escape-sequence:: one of</i>\n    \\\\   \\$   \\e   \\f   \\n   \\r   \\t   \\v\n\n\n  <i>nowdoc-string-literal::</i>\n    <<<  '  <i>hd-start-identifier</i>  '  <i>new-line  hd-char-sequence<sub>opt</sub>   new-line hd-end-identifier</i>  ;<i><sub>opt</sub>   new-line</i>     \n</pre>\n\n### # The Null Literal\n\n<pre>\n  <i>null-literal::</i>\n    NULL (written in any case combination)\n</pre>\n\n## # Operators and Punctuators\n\n<pre>\n  <i>operator-or-punctuator:: one of</i>\n    [   ]    (   )   {    }   .   ->   ++   --   **   *   +   -   ~   !\n    $   /   % <<   >>   <   >   <=   >=   ==   ===   !=   !==   ^   |\n    &   &&   ||   ?   :   ; =   **=   *=   /=   %=   +=   -=   .=   <<=\n    >>=   &=   ^=   |=   ,\n</pre>\n\n# # Syntactic Grammar\n\n## # Program Structure\n\n<pre>\n<i>script:</i>\n<i> script-section</i>\n<i> script   script-section</i>\n\n<i>script-section:</i>\n  <i> text<sub>opt</sub></i> &lt;?php <i>statement-list<sub>opt</sub></i> ?&gt;<sub>opt</sub> <i>text<sub>opt</sub></i>\n\n<i>text:</i>\n  arbitrary text not containing the sequence &lt;?php\n</pre>\n\n## # Variables\n\n<pre>\n  <i>function-static-declaration:</i>\n    static <i>name</i>   <i>function-static-initializer<sub>opt</sub></i> ;\n  \n  <i>function-static-initializer:</i>\n    = <i>const-expression</i>\n    \n  <i>global-declaration:</i>\n    global <i>variable-name-list</i> ;\n\n  <i>variable-name-list:</i>\n    <i>expression</i>\n    <i>variable-name-list  , expression</i>\n</pre>\n    \n## # Expressions\n\n### # Primary Expressions\n\n<pre>\n  <i>primary-expression:</i>\n    <i>variable-name</i>\n    <i>qualified-name</i>\n    <i>literal</i>\n    <i>const-expression</i>\n    <i>intrinsic</i>\n    <i>anonymous-function-creation-expression</i>\n    (  <i>expression</i>  )\n    $this\n\n  <i>intrinsic:</i>\n    <i>array-intrinsic</i>\n    <i>echo-intrinsic</i>\n    <i>empty-intrinsic</i>\n    <i>eval-intrinsic</i>\n    <i>exit-intrinsic</i>\n    <i>isset-intrinsic</i>\n    <i>list-intrinsic</i>\n    <i>print-intrinsic</i>\n    <i>unset-intrinsic</i>\n\n  <i>array-intrinsic:</i>\n    array ( <i>array-initializer<sub>opt</sub></i>  )\n\n  <i>echo-intrinsic:</i>\n    echo  <i>expression</i>\n    echo  (  <i>expression</i>  )\n    echo  <i>expression-list-two-or-more</i>\n\n  <i>expression-list-two-or-more:</i>\n    <i>expression</i>  ,  <i>expression</i>\n    <i>expression-list-two-or-more</i>  ,  <i>expression</i>\n\n  <i>empty-intrinsic:</i>\n    empty ( <i>expression</i>  )\n    \n  <i>eval-intrinsic:</i>\n    eval (  <i>expression</i>  )\n\n  <i>exit-intrinsic:</i>\n    exit  <i>expression<sub>opt</sub></i>\n    exit  (  <i>expression<sub>opt</sub></i>  )\n    die   <i>expression<sub>opt</sub></i>\n    die   (   <i>expression<sub>opt</sub></i> )\n\n  <i>isset-intrinsic:</i>\n    isset  (  <i>expression-list-one-or-more</i>  )\n\n  <i>expression-list-one-or-more</i>:\n    <i>expression</i>\n    <i>expression-list-one-or-mor</i>  ,  <i>expression</i>\n\n  <i>list-intrinsic:</i>\n    list  (  <i>list-expression-list<sub>opt</sub></i>  )\n\n  <i>list-expression-list:</i>\n  <i>list-or-variable</i>\n  ,\n  <i>list-expression-list</i>  ,  <i>list-or-variable<sub>opt</sub></i>\n\n  <i>list-or-variable:</i>\n    <i>list-intrinsic</i>\n    <i>expression</i>\n\n  <i>print-intrinsic:\n    print  <i>expression</i>\n    print  (  <i>expression</i>  )\n\n  <i>unset-intrinsic:</i>\n    unset  (  <i>expression-list-one-or-more</i>  )\n    \n  <i>anonymous-function-creation-expression:</i>\n  function  &<sub>opt</sub> (  <i>parameter-declaration-list<sub>opt<sub></i>  )  <i>anonymous-function-use-clause<sub>opt</sub></i>\n      <i>compound-statement</i>\n\n  <i>anonymous-function-use-clause:</i>\n    use  (  <i>use-variable-name-list</i>  )\n\n  <i>use-variable-name-list:</i>\n    &<sub>opt</sub>   <i>variable-name</i>\n    <i>use-variable-name-list</i>  ,  &<sub>opt</sub>  <i>variable-name</i>\n                \n</pre>\n\n### # Postfix Operators\n\n<pre>\n  <i>postfix-expression:</i>\n    <i>primary-expression</i>\n    <i>clone-expression</i>\n    <i>object-creation-expression</i>\n    <i>array-creation-expression</i>\n    <i>subscript-expression</i>\n    <i>function-call-expression</i>\n    <i>member-selection-expression</i>\n    <i>postfix-increment-expression</i>\n    <i>postfix-decrement-expression</i>\n    <i>scope-resolution-expression</i>\n    <i>exponentiation-expression</i>\n\n\n  <i>clone-expression:</i>\n    clone  <i>expression</i>\n\n  <i>object-creation-expression:</i>\n    new  <i>class-type-designator</i>  (  <i>argument-expression-list<sub>opt</sub></i>  )\n    new  <i>class-type-designator</i>\n\n  <i>class-type-designator:</i>\n    static\n    <i>qualified-name</i>\n    <i>expression</i>\n\n  <i>array-creation-expression:</i>\n    array  (  <i>array-initializer<sub>opt</sub></i>  )\n    [ <i>array-initializer<sub>opt</sub></i> ]\n\n  <i>array-initializer:</i>\n    <i>array-initializer-list</i>  ,<sub>opt</sub>\n\n  <i>array-initializer-list:</i>\n    <i>array-element-initializer</i>\n    <i>array-element-initializer  ,  array-initializer-list</i>\n\n  <i>array-element-initializer:</i>\n    &<sub>opt</sub>   <i>element-value</i>\n    element-key  =>  &<sub>opt</sub>   <i>element-value</i>\n\n  <i>element-key:</i>\n    <i>expression</i>\n\n  <i>element-value</i>\n    <i>expression</i>\n\n  <i>subscript-expression:</i>\n    <i>postfix-expression</i>  [  <i>expression<sub>opt</sub></i>  ]\n    <i>postfix-expression</i>  {  <i>expression<sub>opt</sub></i>  }   <b>[Deprecated form]</b>\n\n  <i>function-call-expression:</i>\n    <i>postfix-expression</i>  (  <i>argument-expression-list<sub>opt</sub></i>  )\n\n  <i>argument-expression-list:</i>\n    <i>assignment-expression</i>\n    <i>argument-expression-list</i>  ,  <i>assignment-expression</i>\n\n  <i>member-selection-expression:</i>\n    <i>postfix-expression</i>  ->  <i>member-selection-designator</i>\n\n  <i>member-selection-designator:</i>\n    <i>name</i>\n    <i>expression</i>\n\n  <i>postfix-increment-expression:</i>\n    <i>unary-expression</i>  ++\n\n  <i>postfix-decrement-expression:</i>\n    <i>unary-expression</i>  --\n\n  <i>scope-resolution-expression:</i>\n    <i>scope-resolution-qualifier</i>  ::  <i>member-selection-designator</i>\n    <i>scope-resolution-qualifier</i>  ::  <i>class</i>\n\n  <i>scope-resolution-qualifier:</i>\n    <i>qualified-name</i>\n    <i>expression</i>\n    self\n    parent\n    static\n   \n  <i>exponentiation-expression:</i>\n    <i>expression  **  expression</i>                    \n</pre>\n\n### # Unary Operators\n\n<pre>\n  <i>unary-expression:</i>\n    <i>postfix-expression</i>\n    <i>prefix-increment-expression</i>\n    <i>prefix-decrement-expression</i>\n    <i>unary-op-expression</i>\n    <i>error-control-expression</i>\n    <i>shell-command-expression</i>\n    <i>cast-expression</i>\n    <i>variable-name-creation-expression</i>\n\n  <i>prefix-increment-expression:</i>\n    ++ <i>unary-expression</i>\n\n  <i>prefix-decrement-expression:</i>\n    -- <i>unary-expression</i>\n\n  <i>unary-op-expression:</i>\n    <i>unary-operator cast-expression</i>\n\n  <i>unary-operator: one of</i>\n    +  -  !  \\\n\n  <i>error-control-expression:</i>\n    @   <i>expression</i>\n\n  <i>shell-command-expression:</i>\n    `  <i>dq-char-sequence<sub>opt</sub></i>  `\n\n  <i>cast-expression:</i>\n    <i>unary-expression</i>\n    (  <i>cast-type</i>  ) <i>cast-expression</i>\n\n  <i>cast-type: one of</i>\n    array  binary  bool  boolean  double  int  integer  float  object\n    real  string  unset\n\n  <i>variable-name-creation-expression:</i>\n    $   <i>expression</i>\n    $  {  <i>expression</i>  }\n                        \n</pre>\n\n### # instanceof Operator\n\n<pre>\n  <i>instanceof-expression:</i>\n    <i>unary-expression</i>\n    <i>instanceof-subject</i>  instanceof   <i>instanceof-type-designator</i>\n\n  <i>instanceof-subject:</i>\n    <i>expression</i>\n\n  <i>instanceof-type-designator:</i>\n    <i>qualified-name</i>\n    <i>expression</i>\n</pre>\n\n### # Multiplicative Operators\n\n<pre>\n  <i>multiplicative-expression:</i>\n    <i>instanceof-expression</i>\n    <i>multiplicative-expression</i>  *  <i>multiplicative-expression</i>\n    <i>multiplicative-expression</i>  /  <i>multiplicative-expression</i>\n    <i>multiplicative-expression</i>  %  <i>multiplicative-expression</i>\n</pre>\n\n### # Additive Operators\n\n<pre>\n  <i>additive-expression:</i>\n    <i>multiplicative-expression</i>\n    <i>additive-expression</i>  +  <i>multiplicative-expression</i>\n    <i>additive-expression</i>  -  <i>multiplicative-expression</i>\n    <i>additive-expression</i>  .  <i>multiplicative-expression</i>\n</pre>\n\n### # Bitwise Shift Operators\n\n<pre>\n  <i>shift-expression:</i>\n    <i>additive-expression</i>\n    <i>shift-expression</i>  <<  <i>additive-expression</i>\n    <i>shift-expression</i>  >>  <i>additive-expression</i>\n</pre>\n\n### # Relational Operators\n\n<pre>\n  <i>relational-expression:</i>\n    <i>shift-expression</i>\n    <i>relational-expression</i>  <   <i>shift-expression</i>\n    <i>relational-expression</i>  >   <i>shift-expression</i>\n    <i>relational-expression</i>  <=  <i>shift-expression</i>\n    <i>relational-expression</i>  >=  <i>shift-expression</i>\n</pre>\n\n### # Equality Operators\n\n<pre>\n  <i>equality-expression:</i>\n    <i>relational-expression</i>\n    <i>equality-expression</i>  ==  <i>relational-expression</i>\n    <i>equality-expression</i>  !=  <i>relational-expression</i>\n    <i>equality-expression</i>  <>  <i>relational-expression</i>\n    <i>equality-expression</i>  ===  <i>relational-expression</i>\n    <i>equality-expression</i>  !==  <i>relational-expression</i>\n</pre>\n\n### # Bitwise Logical Operators\n\n<pre>\n  <i>bitwise-AND-expression:</i>\n    <i>equality-expression</i>\n    <i>bit-wise-AND-expression</i>  &  <i>equality-expression</i>\n\n  <i>bitwise-exc-OR-expression:</i>\n    <i>bitwise-AND-expression</i>\n    <i>bitwise-exc-OR-expression</i>  ^   <i>bitwise-AND-expression</i>\n    \n  <i>bitwise-inc-OR-expression:</i>\n    <i>bitwise-exc-OR-expression</i>\n    <i>bitwise-inc-OR-expression</i>  |  <i>bitwise-exc-OR-expression</i>\n</pre>\n\n### # Logical Operators (form 1)\n\n<pre>\n  <i>logical-AND-expression-1:</i>\n    <i>bitwise-incl-OR-expression</i>\n    <i>logical-AND-expression-1</i>  &&  <i>bitwise-inc-OR-expression</i>\n\n  <i>logical-inc-OR-expression-1:</i>\n    <i>logical-AND-expression-1</i>\n    <i>logical-inc-OR-expression-1</i>  ||  <i>logical-AND-expression-1</i>\n</pre>\n\n### # Conditional Operator\n\n<pre>\n  <i>conditional-expression:</i>\n    <i>logical-inc-OR-expression-1</i>\n    <i>logical-inc-OR-expression-1</i>  ?  <i>expression<sub>opt</sub></i>  :  <i>conditional-expression</i>\n</pre>\n\n### # Assignment Operators\n\n<pre>\n  <i>assignment-expression:</i>\n    <i>conditional-expression</i>\n    <i>simple-assignment-expression</i>\n    <i>byref-assignment-expression</i>\n    <i>compound-assignment-expression</i>\n\n  <i>simple-assignment-expression:</i>\n    <i>unary-expression</i>  =  <i>assignment-expression</i>\n    \n  <i>byref-assignment-expression:</i>\n    <i>unary-expression</i>  =  &  <i>assignment-expression</i>\n    \n  <i>compound-assignment-expression:</i>\n    <i>unary-expression   compound-assignment-operator   assignment-expression</i>\n\n  <i>compound-assignment-operator: one of</i>\n    **=  *=  /=  %=  +=  -=  .=  <<=  >>=  &=  ^=  |=    \n</pre>\n\n### # Logical Operators (form 2)\n\n<pre>\n  <i>logical-AND-expression-2:</i>\n    <i>assignment-expression</i>\n    <i>logical-AND-expression-2</i>  and  <i>assignment-expression</i>\n\n  <i>logical-exc-OR-expression:</i>\n    <i>logical-AND-expression-2</i>\n    <i>logical-exc-OR-expression</i>  xor  <i>logical-AND-expression-2</i>\n\n  <i>logical-inc-OR-expression-2:</i>\n    <i>logical-exc-OR-expression</i>\n    <i>logical-inc-OR-expression-2</i>  or  <i>logical-exc-OR-expression</i>\n    \n</pre>\n\n\n### # yield Operator\n\n<pre>\n  <i>yield-expression:</i>\n    <i>logical-inc-OR-expression-2</i>\n    yield  <i>array-element-initializer</i>\n</pre>\n\n### # Script Inclusion Operators\n\n<pre>\n  <i>expression:</i>\n    <i>yield-expression</i>\n    <i>include-expression</i>\n    <i>include-once-expression</i>\n    <i>require-expression</i>\n    <i>require-once-expression</i>\n\n  <i>include-expression:</i>\n    include  (  <i>include-filename</i>  )\n    include  <i>include-filename</i>\n\n  <i>include-filename:</i>\n    <i>expression</i>\n    \n  <i>include-once-expression:</i>\n    include_once  (  <i>include-filename</i>  )\n    include_once  <i>include-filename</i>\n    \n  <i>require-expression:</i>\n    require  (  <i>include-filename</i>  )\n    require  <i>include-filename</i>\n    \n  <i>require-once-expression:</i>\n    require_once  (  <i>include-filename</i>  )\n    require_once  <i>include-filename</i>\n</pre>\n\n### # Constant Expressions\n\n<pre>\n  <i>constant-expression:</i>\n    <i>array-creation-expression</i>\n    <i>const-expression</i>\n\n  <i>const-expression:</i>\n    <i>expression</i>\n</pre>\n  \n## # Statements\n\n### # General\n\n<pre>\n\n  <i>statement:</i>\n    <i>compound-statement</i>\n\t<i>labeled-statement</i>\n    <i>expression-statement</i>\n    <i>selection-statement</i>\n    <i>iteration-statement</i>\n    <i>jump-statement</i>\n    <i>declare-statement</i>\n    <i>const-declaration</i>\n    <i>function-definition</i>\n    <i>class-declaration</i>\n    <i>interface-declaration</i>\n    <i>trait-declaration</i>\n    <i>namespace-definition</i>\n    <i>namespace-use-declaration</i>\n    <i>global-declaration</i>\n    <i>function-static-declaration</i>\n</pre>\n\n### # Compound Statements\n\n<pre>\n  <i>compound-statement:</i>\n    {   <i>statement-list<sub>opt</sub></i>  }\n\n  <i>statement-list:</i>\n    <i>statement</i>\n    <i>statement-list   statement</i>\n</pre>\n\n### # Labeled Statements\n\n<pre>\n  <i>labeled-statement:</i>\n    <i>named-label</i>\n    <i>case-label</i>\n    <i>default-label</i>\n\n  <i>named-label:</i>\n    <i>name</i>  :  <i>statement</i>\n\n  <i>case-label:</i>\n    <i>case   expression   case-default-label-terminator   statement</i>\n\n  <i>default-label:</i>\n    <i>default  case-default-label-terminator   statement</i>\n\n  <i>case-default-label-terminator:</i>\n    :\n    ;\n</pre>\n\n### # Expression Statements\n\n<pre>\n   <i>expression-statement:</i>\n     <i>expression<sub>opt</sub></i>  ;\n\n  <i>selection-statement:</i>\n    <i>if-statement</i>\n    <i>switch-statement</i>\n    \n  <i>if-statement:</i>\n    if   (   <i>expression</i>   )   <i>statement   elseif-clauses-1opt   else-clause-1opt</i>\n    if   (   <i>expression   )   :   <i>statement-list   elseif-clauses-2opt   else-clause-2opt</i>   endif   ;\n\n  <i>elseif-clauses-1:</i>\n    <i>elseif-clause-1</i>\n    <i>elseif-clauses-1   elseif-clause-1</i>\n\n  <i>elseif-clause-1:</i>\n    elseif   (   <i>expression</i>   )   <i>statement</i>\n \n  <i>else-clause-1:</i>\n    else   <i>statement</i>\n\n  <i>elseif-clauses-2:</i>\n    <i>elseif-clause-2</i>\n    <i>elseif-clauses-2   elseif-clause-2</i>\n\n  <i>elseif-clause-2:</i>\n    elseif   (   <i>expression</i>   )   :   <i>statement-list</i>\n  \n  <i>else-clause-2:</i>\n    else   :   <i>statement-list</i>\n\n  <i>switch-statement:</i>\n    switch  (  <i>expression</i>  )  <i>compound-statement</i>\n    switch  (  <i>expression</i>  )  :   <i>statement-list</i>  endswitch;\n        \n</pre>\n\n### # Iteration Statements\n\n<pre>\n  <i>iteration-statement:</i>\n    <i>while-statement</i>\n    <i>do-statement</i>\n    <i>for-statement</i>\n    <i>foreach-statement</i>\n\n  <i>while-statement:</i>\n    while  (  <i>expression</i>  )  <i>statement</i>\n    while  (  <i>expression</i>  )  :   <i>statement-list</i>  endwhile ;\n    \n  <i>do-statement:</i>\n    do  <i>statement</i>  while  (  <i>expression</i>  )  ;\n\n\n  <i>for-statement:</i>\n    for   (   <i>for-initializeropt</i>   ;   <i>for-controlopt</i>   ;   <i>for-end-of-loopopt</i>   )   <i>statement</i>\n    for   (   <i>for-initializeropt</i>   ;   <i>for-controlopt</i>   ;   <i>for-end-of-loopopt</i>   )   :   <i>statement-list</i>   endfor   ;\n\n  <i>for-initializer:</i>\n    <i>for-expression-group</i>\n\n  <i>for-control:</i>\n    <i>for-expression-group</i>\n\n  <i>for-end-of-loop:</i>\n    <i>for-expression-group</i>\n\n  <i>for-expression-group:</i>\n    <i>expression</i>\n    <i>for-expression-group</i>   ,   <i>expression</i>\n\n  <i>foreach-statement:</i>\n    foreach  (  <i>foreach-collection-name</i>  as  <i>foreach-key<sub>opt</sub>  foreach-value</i>  )   statement\n    foreach  (  <i>foreach-collection-name</i>  as  <i>foreach-key<sub>opt</sub>   foreach-value</i>  )  :   <i>statement-list</i>  endforeach  ;\n\n  <i>foreach-collection-name</i>:\n    <i>expression</i>\n\n  <i>foreach-key:</i>\n    <i>expression</i>  =>\n\n  <i>foreach-value:<i>\n    &<sub>opt</sub>   <i>expression</i>\n    <i>list-intrinsic</i>\n            \n</pre>\n\n### # Jump Statements\n\n<pre>\n  <i>jump-statement:</i>\n    <i>goto-statement</i>\n    <i>continue-statement</i>\n    <i>break-statement</i>\n    <i>return-statement</i>\n    <i>throw-statement</i>\n\n  <i>goto-statement:</i>\n    goto  <i>name</i>  ;\n    \n  <i>continue-statement:</i>\n    continue   <i>breakout-level<sub>opt</sub></i>  ;\n\n  <i>breakout-level:</i>\n    <i>integer-literal</i>\n    \n  <i>break-statement:</i>\n    break  <i>breakout-level<sub>opt</sub></i>  ;\n    \n  <i>return-statement:</i>\n    return  <i>expression<sub>opt</sub></i>  ;\n    \n  <i>throw-statement:</i>\n    throw  <i>expression</i>  ;\n</pre>\n\n### # The try Statement\n\n<pre>\n  <i>try-statement:</i>\n    try  <i>compound-statement   catch-clauses</i>\n    try  <i>compound-statement   finally-clause</i>\n    try  <i>compound-statement   catch-clauses   finally-clause</i>\n\n  <i>catch-clauses:</i>\n    <i>catch-clause</i>\n    <i>catch-clauses   catch-clause</i>\n\n  <i>catch-clause:</i>\n    catch  (  <i>parameter-declaration-list</i>  )  <i>compound-statement</i>\n\n  <i>finally-clause:</i>\n    finally   <i>compound-statement</i>\n</pre>\n\n### # The declare Statement\n\n<pre>\n  <i>declare-statement:</i>\n    declare  (  <i>declare-directive</i>  )  <i>statement</i>\n    declare  (  <i>declare-directive</i>  )  :  <i>statement-list</i>  enddeclare  ;\n    declare  (  <i>declare-directive</i>  )  ;\n\n  <i>declare-directive:</i>\n    ticks  =  <i>declare-tick-count</i>\n    encoding  =  <i>declare-character-encoding</i>\n\n  <i>declare-tick-count</i>\n    <i>expression</i>\n\n  <i>declare-character-encoding:</i>\n    <i>expression</i>\n</pre>\n\n## # Functions\n\n<pre>\n  <i>function-definition:</i>\n    <i>function-definition-header   compound-statement</i>\n\n  <i>function-definition-header:</i>\n    function  &<sub>opt</sub>   <i>name</i>  (  <i>parameter-declaration-list<sub>opt</sub></i>  )\n\n  <i>parameter-declaration-list:</i>\n    <i>parameter-declaration</i>\n    <i>parameter-declaration-list</i>  ,  <i>parameter-declaration</i>\n\n  <i>parameter-declaration:</i>\n    <i>type-hint<sub>opt</sub></i>  &<sub>opt</sub>   <i>variable-name   default-argument-specifier<sub>opt</sub></i>\n\n  <i>type-hint:</i>\n    array\n    callable\n    <i>qualified-name</i>\n\n  <i>default-argument-specifier:</i>\n    =  <i>const-expression</i>\n</pre>\n\n## # Classes\n\n<pre>\n  <i>class-declaration:</i>\n    <i>class-modifier<sub>opt</sub></i>  class  <i>name   class-base   clause<sub>opt</sub>  class-interface-clause<sub>opt</sub></i>   {   <i>trait-use-clauses<sub>opt</sub>   class-member-declarations<sub>opt</sub></i> }\n\n  <i>class-modifier:</i>\n    abstract\n    final\n\n  <i>class-base-clause:</i>\n    extends  <i>qualified-name</i>\n\n  <i>class-interface-clause:</i>\n    implements  <i>qualified-name</i>\n    <i>class-interface-clause</i>  ,  <i>qualified-name</i>\n\n  <i>class-member-declarations:</i>\n    <i>class-member-declaration</i>\n    <i>class-member-declarations   class-member-declaration</i>\n\n   <i>class-member-declaration:</i>\n     <i>const-declaration</i>\n     <i>property-declaration</i>\n     <i>method-declaration</i>\n     <i>constructor-declaration</i>\n     <i>destructor-declaration</i>\n     \n  <i>const-declaration:</i>\n    const  <i>name</i>  =  <i>const-expression</i>   ;\n    \n  <i>property-declaration:</i>\n    <i>property-modifier   name   property-initializer<sub>opt</sub></i>  ;\n\n  <i>property-modifier:</i>\n    var\n    <i>visibility-modifier   static-modifier<sub>opt</sub></i>\n    <i>static-modifier   visibility-modifier<sub>opt</sub></i>\n\n  <i>visibility-modifier:</i>\n    public\n    protected\n    private\n\n  <i>static-modifier:</i>\n    static\n\n  <i>property-initializer:</i>\n    =  <i>constant-expression</i>\n    \n  method-declaration:\n    <i>method-modifiers<sub>opt</sub>   function-definition</i>\n    <i>method-modifiers   function-definition-header</i>  ;\n\n  <i>method-modifiers:</i>\n    <i>method-modifier</i>\n    <i>method-modifiers   method-modifier</i>\n\n  <i>method-modifier:</i>\n    <i>visibility-modifier</i>\n    <i>static-modifier</i>\n    abstract\n    final\n\n  <i>constructor-definition:</i>\n    <i>visibility-modifier</i>  function &<sub>opt</sub>   __construct  (  <i>parameter-declaration-list<sub>opt</sub></i>  )  <i>compound-statement</i>\n    <i>visibility-modifier</i>  function &<sub>opt</sub>    <i>name</i>  (  <i>parameter-declaration-list<sub>opt</sub></i>  )  <i>compound-statement </i>    <b>[Deprecated form]</b>\n\n  <i>destructor-definition:</i>\n    <i>visibility-modifier</i>  function  &<sub>opt</sub>  __destruct  ( ) <i>compound-statement</i>\n    \n</pre>\n\n## # Interfaces\n\n<pre>\n  <i>interface-declaration:</i>\n    interface   <i>name   interface-base-clause<sub>opt</sub></i> {  <i>interface-member-declarations<sub>opt</sub></i>  }\n\n  <i>interface-base-clause:</i>\n    extends   <i>qualified-name</i>\n    <i>interface-base-clause</i>  ,  <i>qualified-name</i>\n\n  <i>interface-member-declarations:</i>\n    <i>interface-member-declaration</i>\n    <i>interface-member-declarations   interface-member-declaration</i>\n\n  <i>interface-member-declaration:</i>\n    <i>const-declaration</i>\n    <i>method-declaration</i>\n</pre>\n\n## # Traits\n\n<pre>\n  <i>trait-declaration:</i>\n    trait   <i>name</i>   {   <i>trait-use-clauses<sub>opt</sub>   trait-member-declarations<sub>opt</sub></i>   }\n\n  <i>trait-use-clauses:</i>\n    <i>trait-use-clause</i>\n    <i>trait-use-clauses   trait-use-clause</i>\n\n  <i>trait-use-clause:</i>\n    use   <i>trait-name-list   trait-use-terminator</i>\n\n  <i>trait-name-list:</i>\n    <i>qualified-name</i>\n    <i>trait-name-list</i>   ,   <i>qualified-name</i>\n\n  <i>trait-use-terminator:</i>\n    ;\n    {   <i>trait-select-and-alias-clauses<sub>opt</sub></i>   }\n\n  <i>trait-select-and-alias-clauses:</i>\n    <i>trait-select-and-alias-clause</i>\n    <i>trait-select-and-alias-clauses   trait-select-and-alias-clause</i>\n\n  <i>trait-select-and-alias-clause:</i>\n    <i>trait-select-insteadof-clause</i>\n    <i>trait-alias-as-clause</i>\n\n  <i>trait-select-insteadof-clause:</i>\n    <i>name</i>   insteadof   <i>name</i>\n\n  trait-alias-as-clause:\n    <i>name</i>   as   <i>visibility-modifier<sub>opt</sub>   name</i>\n    <i>name</i>   as   <i>visibility-modifier   name<sub>opt</sub></i>\n\n  <i>trait-member-declarations:</i>\n    <i>trait-member-declaration</i>\n    <i>trait-member-declarations   trait-member-declaration</i>\n\n  <i>trait-member-declaration:</i>\n    <i>property-declaration</i>\n    <i>method-declaration</i>\n    <i>constructor-declaration</i>\n    <i>destructor-declaration</i>\n    \n</pre>    \n\n## # Namespaces\n\n<pre>\n  <i>namespace-definition:</i>\n    namespace  <i>namespace-name</i>  ;\n    namespace  <i>namespace-name<sub>opt</sub>   compound-statement</i>\n\n  <i>namespace-use-declaration:</i>\n    use  <i>namespace-use-clauses</i>  ;\n\n  <i>namespace-use-clauses:</i>\n    <i>namespace-use-clause</i>\n    <i>namespace-use-clauses</i>  ,  <i>namespace-use-clause</i>\n\n  <i>namespace-use-clause:</i>\n    <i>qualified-name   namespace-aliasing-clause<sub>opt</sub></i>\n\n  <i>namespace-aliasing-clause:</i>\n    as  <i>name</i>\n</pre>\n\n# Bibliography\n\nThe following documents are useful references for implementers and users\nof this specification:\n\nIEC 60559:1989, *Binary floating-point arithmetic for microprocessor\nsystems* (previously designated IEC 559:1989). (This standard is widely\nknown by its U.S. national designation, ANSI/IEEE Standard 754-1985,\nIEEE Standard for Binary Floating-Point Arithmetic.)\n\nThe Unicode Consortium. *The Unicode Standard, Version 5.0*,\n[www.Unicode.org](http://www.Unicode.org)).\n\n"
  },
  {
    "path": "tests/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Attributes/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Attributes/__ConsistentConstruct.php",
    "content": "<?hh // strict\n\nnamespace NS_ConsistentConstruct;\n\n// --------------------------------------------------------\n// test with constructors having no arguments, but override being variadic\n\n<<__ConsistentConstruct>>\nclass Base {\n  public function __construct() {\n    echo \"In \" . __METHOD__ . \"\\n\";\n  }\n\n  public static function make(): this {\n    echo \"making a new object\\n\";\n    return new static();\n  }\n}\n\nclass Derived extends Base {\n  public function __construct(...) {\n    echo \"In \" . __METHOD__ . \"\\n\";\n    parent::__construct();\n  }\n}\n\n// --------------------------------------------------------\n// test with constructors having no 2 arguments, and override being variadic\n\n<<__ConsistentConstruct>>\nclass C1 {\n  public function __construct(int $p1, float $p2) {\n    echo \"In \" . __METHOD__ . \"\\n\";\n  }\n\n  public static function make(): this {\n    echo \"making a new object\\n\";\n    return new static(123, 6.5);\n  }\n}\n\n<<__ConsistentConstruct>>\nclass C2 extends C1 {\n  public function __construct(int $p1, float $p2, ...) {\n    echo \"In \" . __METHOD__ . \"\\n\";\n    parent::__construct($p1, $p2);\n  }\n}\n\n/*\n// --------------------------------------------------------\n// use UNSAFE_Construct attribute\n\n<<__ConsistentConstruct>>\nclass Base2 {\n  public function __construct() {\n    echo \"In \" . __METHOD__ . \"\\n\";\n  }\n\n  public static function make(): this {\n    echo \"making a new object\\n\";\n    return new static();\n  }\n}\n\nclass Derived2 extends Base2 {\n  <<UNSAFE_Construct>>\n  public function __construct(int $p1) {\n    echo \"In \" . __METHOD__ . \"\\n\";\n    parent::__construct();\n  }\n}\n*/\n// --------------------------------------------------------\n\n//<<__ConsistentConstruct, Attr2(3, true)>>\t// hmmm! accepted\n<<__ConsistentConstruct(3), Attr2(3, true)>>\t// hmmm! accepted with a value\nfunction f1(): void { echo \"Inside \" . __FUNCTION__ . \"\\n\"; }\n\n// --------------------------------------------------------\n\nfunction main(): void {\necho \"\\n============== on constructor =====================\\n\\n\";\n\n  $v1 = Base::make();\n  var_dump($v1);\n\n  $v2 = Derived::make();\n  var_dump($v2);\n\n  $v1 = C1::make();\n  var_dump($v1);\n\n  $v2 = C2::make();\n  var_dump($v2);\n\necho \"\\n============== top-level function f1 =====================\\n\\n\";\n\n  f1();\n  $rf = new \\ReflectionFunction('\\NS_ConsistentConstruct\\f1');\n  $attr1 = $rf->getAttribute('__ConsistentConstruct');\t// hmmm!\n  var_dump($attr1);\n  $attr2 = $rf->getAttribute('Attr2');\n  var_dump($attr2);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Attributes/__ConsistentConstruct.php.expect",
    "content": "\n============== on constructor =====================\n\nmaking a new object\nIn NS_ConsistentConstruct\\Base::__construct\nobject(NS_ConsistentConstruct\\Base)#1 (0) {\n}\nmaking a new object\nIn NS_ConsistentConstruct\\Derived::__construct\nIn NS_ConsistentConstruct\\Base::__construct\nobject(NS_ConsistentConstruct\\Derived)#2 (0) {\n}\nmaking a new object\nIn NS_ConsistentConstruct\\C1::__construct\nobject(NS_ConsistentConstruct\\C1)#3 (0) {\n}\nmaking a new object\nIn NS_ConsistentConstruct\\C2::__construct\nIn NS_ConsistentConstruct\\C1::__construct\nobject(NS_ConsistentConstruct\\C2)#4 (0) {\n}\n\n============== top-level function f1 =====================\n\nInside NS_ConsistentConstruct\\f1\narray(1) {\n  [0]=>\n  int(3)\n}\narray(2) {\n  [0]=>\n  int(3)\n  [1]=>\n  bool(true)\n}"
  },
  {
    "path": "tests/Attributes/__Memoize.php",
    "content": "<?hh // strict\n\nnamespace NS_Memoize;\n\n// --------------------------------------------------------\n\nclass Item {\n  <<__Memoize>>\n  public static function getNameFromProductCode(int $productCode): string {\n    /* ... */\n    return Item::getNameFromStorage($productCode);\n  }\n\n  private static function getNameFromStorage(int $productCode): string {\n    $names = array('??', 'door', 'window', 'cabinet');\n    echo \"Inside \" . __FUNCTION__ . \"\\n\";\n    return $names[$productCode];\n  }\n}\n\n// --------------------------------------------------------\n\ntrait T {\n  <<__Memoize>>\n  public function getNameFromProductCode(int $productCode): string {\n    /* ... */\n    return $this->getNameFromStorage($productCode);\n  }\n\n  private function getNameFromStorage(int $productCode): string {\n    $names = array('??', 'door', 'window', 'cabinet');\n    echo \"Inside \" . __FUNCTION__ . \"\\n\";\n    return $names[$productCode];\n  }\n}\n\nclass C1 {\n  use T;\n}\n\n// --------------------------------------------------------\n\n// hhvm - <<__Memoize>> cannot be used in interfaces\n\ninterface I {\n//  <<__Memoize>>\n  public function getNameFromProductCode(int $productCode): string;\n}\n\nclass C2 implements I {\n  public function getNameFromProductCode(int $productCode): string {\n    /* ... */\n    return $this->getNameFromStorage($productCode);\n  }\n\n  private function getNameFromStorage(int $productCode): string {\n    $names = array('??', 'door', 'window', 'cabinet');\n    echo \"Inside \" . __FUNCTION__ . \"\\n\";\n    return $names[$productCode];\n  }\n}\n\n// --------------------------------------------------------\n\n<<__Memoize>>\nfunction getNameFromProductCode(int $productCode): string {\n  /* ... */\n  return getNameFromStorage($productCode);\n}\n\nfunction getNameFromStorage(int $productCode): string {\n  $names = array('??', 'door', 'window', 'cabinet');\n  echo \"Inside \" . __FUNCTION__ . \"\\n\";\n  return $names[$productCode];\n}\n\n// --------------------------------------------------------\n\n//<<__Memoize, Attr2(3, true)>>\t// hmmm! accepted even though function has a void return type\n<<__Memoize(3), Attr2(3, true)>>\t// hmmm! accepted with a value\nfunction f1(): void { echo \"Inside \" . __FUNCTION__ . \"\\n\"; }\n\n// --------------------------------------------------------\n\nenum ControlStatus: int {\n  Stopped = 0;\n  Stopping = 1;\n  Starting = 2;\n  Started = 3;\n}\n\ntype Point = shape('x' => int, 'y' => int);\n\nclass C3 implements IMemoizeParam {\n  public function getInstanceKey(): string {\n    return \"xxxx\";\n  }\n}\n\nclass C4 {} // does NOT implement IMemoizeParam\n\n// checkout the permitted parameter types on the function\n\n<<__Memoize>>\nfunction getNameFromProductCode2(\n\tbool $p1\n\t, int $productCode\n\t, float $p3\n\t, string $p4\n\t, ?int $p5\n//\t, resource $p6\t\t// invalid type\n\t, array<int> $p7\n\t, array<string, int> $p8\n\t, ControlStatus $p9\t// permitted, but no in docs list\n\t, (int, float) $p10\t// permitted, but no in docs list\n\t, Point $p11\t\t// permitted, but no in docs list\n\t, Vector<int> $p12\t// permitted, presumably this type implements IMemoizeParam\n\t, C3 $p13\n//\t, C4 $p14\t\t// invalid type\n): string {\n  /* ... */\n  return getNameFromStorage2($productCode);\n}\n\nfunction getNameFromStorage2(int $productCode): string {\n  $names = array('??', 'door', 'window', 'cabinet');\n  echo \"Inside \" . __FUNCTION__ . \"\\n\";\n  return $names[$productCode];\n}\n\n// --------------------------------------------------------\n\n// try a variadic function\n\n<<__Memoize>>\nfunction getNameFromProductCode3(int $productCode, ...): string {\n  /* ... */\n  return getNameFromStorage3($productCode);\n}\n\nfunction getNameFromStorage3(int $productCode): string {\n  $names = array('??', 'door', 'window', 'cabinet');\n  echo \"Inside \" . __FUNCTION__ . \"\\n\";\n  return $names[$productCode];\n}\n\n// --------------------------------------------------------\n\nfunction main(): void {\n  echo \"\\n============== in class =====================\\n\\n\";\n\n  var_dump(Item::getNameFromProductCode(3));\n  var_dump(Item::getNameFromProductCode(1));\n  var_dump(Item::getNameFromProductCode(2));\n  var_dump(Item::getNameFromProductCode(1));\n  var_dump(Item::getNameFromProductCode(2));\n  var_dump(Item::getNameFromProductCode(3));\n\n  echo \"\\n============== in trait =====================\\n\\n\";\n\n  $c1 = new C1();\n  var_dump($c1->getNameFromProductCode(3));\n  var_dump($c1->getNameFromProductCode(1));\n  var_dump($c1->getNameFromProductCode(2));\n  var_dump($c1->getNameFromProductCode(1));\n  var_dump($c1->getNameFromProductCode(2));\n  var_dump($c1->getNameFromProductCode(3));\n\n  echo \"\\n============== in interface =====================\\n\\n\";\n\n  $c2 = new C2();\n  var_dump($c2->getNameFromProductCode(3));\n  var_dump($c2->getNameFromProductCode(1));\n  var_dump($c2->getNameFromProductCode(2));\n  var_dump($c2->getNameFromProductCode(1));\n  var_dump($c2->getNameFromProductCode(2));\n  var_dump($c2->getNameFromProductCode(3));\n\n  echo \"\\n============== top-level function getNameFromProductCode =====================\\n\\n\";\n\n  var_dump(getNameFromProductCode(3));\n  var_dump(getNameFromProductCode(1));\n  var_dump(getNameFromProductCode(2));\n  var_dump(getNameFromProductCode(1));\n  var_dump(getNameFromProductCode(2));\n  var_dump(getNameFromProductCode(3));\n\n  echo \"\\n============== top-level function getNameFromProductCode2 =====================\\n\\n\";\n\n  var_dump(getNameFromProductCode2(true, 3, 1.2, \"z\", null\n//\t\t, STDERR\t\t\t// invalid type\n\t\t, array(10,20)\n\t\t, array('q' => 10, 'a' => 12)\n\t\t, ControlStatus::Stopped\t// permitted, but no in docs list\n\t\t, tuple(10, 1.2)\t\t// permitted, but no in docs list\n\t\t, shape('x' => 1, 'y' => 3)\t// permitted, but no in docs list\n\t\t, Vector {10,20,30}\t\t// permitted, but no in docs list\n\t\t, new C3()\t\t\t// permitted, presumably this type implements IMemoizeParam\n//\t\t, new C4()\t\t\t// invalid type\n  ));\n  var_dump(getNameFromProductCode2(true, 3, 1.2, \"z\", null\n//\t\t, STDERR\t\t\t// invalid type\n\t\t, array(10,20)\n\t\t, array('q' => 10, 'a' => 12)\n\t\t, ControlStatus::Stopped\t// permitted, but no in docs list\n\t\t, tuple(10, 1.2)\t\t// permitted, but no in docs list\n\t\t, shape('x' => 1, 'y' => 3)\t// permitted, but no in docs list\n\t\t, Vector {10,20,30}\t\t// permitted, but no in docs list\n\t\t, new C3()\t\t\t// permitted, presumably this type implements IMemoizeParam\n//\t\t, new C4()\t\t\t// invalid type\n  ));\n\n  echo \"\\n============== top-level function getNameFromProductCode3 =====================\\n\\n\";\n\n  var_dump(getNameFromProductCode3(3));\n  var_dump(getNameFromProductCode3(1));\n  var_dump(getNameFromProductCode3(2));\n  var_dump(getNameFromProductCode3(1));\n  var_dump(getNameFromProductCode3(2));\n  var_dump(getNameFromProductCode3(3));\n\n  echo \"\\n============== top-level function f1 =====================\\n\\n\";\n\n  f1();\n  $rf = new \\ReflectionFunction('\\NS_Memoize\\f1');\n  $attr1 = $rf->getAttribute('__Memoize');\t// hmmm!\n  var_dump($attr1);\n  $attr2 = $rf->getAttribute('Attr2');\n  var_dump($attr2);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Attributes/__Memoize.php.expect",
    "content": "\n============== in class =====================\n\nInside getNameFromStorage\nstring(7) \"cabinet\"\nInside getNameFromStorage\nstring(4) \"door\"\nInside getNameFromStorage\nstring(6) \"window\"\nstring(4) \"door\"\nstring(6) \"window\"\nstring(7) \"cabinet\"\n\n============== in trait =====================\n\nInside getNameFromStorage\nstring(7) \"cabinet\"\nInside getNameFromStorage\nstring(4) \"door\"\nInside getNameFromStorage\nstring(6) \"window\"\nstring(4) \"door\"\nstring(6) \"window\"\nstring(7) \"cabinet\"\n\n============== in interface =====================\n\nInside getNameFromStorage\nstring(7) \"cabinet\"\nInside getNameFromStorage\nstring(4) \"door\"\nInside getNameFromStorage\nstring(6) \"window\"\nInside getNameFromStorage\nstring(4) \"door\"\nInside getNameFromStorage\nstring(6) \"window\"\nInside getNameFromStorage\nstring(7) \"cabinet\"\n\n============== top-level function getNameFromProductCode =====================\n\nInside NS_Memoize\\getNameFromStorage\nstring(7) \"cabinet\"\nInside NS_Memoize\\getNameFromStorage\nstring(4) \"door\"\nInside NS_Memoize\\getNameFromStorage\nstring(6) \"window\"\nstring(4) \"door\"\nstring(6) \"window\"\nstring(7) \"cabinet\"\n\n============== top-level function getNameFromProductCode2 =====================\n\nInside NS_Memoize\\getNameFromStorage2\nstring(7) \"cabinet\"\nstring(7) \"cabinet\"\n\n============== top-level function getNameFromProductCode3 =====================\n\nInside NS_Memoize\\getNameFromStorage3\nstring(7) \"cabinet\"\nInside NS_Memoize\\getNameFromStorage3\nstring(4) \"door\"\nInside NS_Memoize\\getNameFromStorage3\nstring(6) \"window\"\nstring(4) \"door\"\nstring(6) \"window\"\nstring(7) \"cabinet\"\n\n============== top-level function f1 =====================\n\nInside NS_Memoize\\f1\narray(1) {\n  [0]=>\n  int(3)\n}\narray(2) {\n  [0]=>\n  int(3)\n  [1]=>\n  bool(true)\n}"
  },
  {
    "path": "tests/Attributes/__Override.php",
    "content": "<?hh // strict\n\nnamespace NS_Override;\n\n// --------------------------------------------------------\n\nclass Button {\n  public function draw(): void { /* ... */ }\n  public static function sf(): void { /* ... */ }\n}\n\n// If parent class has no function to be overridden (or extends clause omitted), get\n// NS_Override\\CustomButton::draw() is marked as override; no non-private parent definition \n// found or overridden parent is defined in non-<?hh code \n\nclass CustomButton extends Button {\n  <<__Override>>\n  public function draw(): void { /* ... */ }\n  <<__Override>>\n  public static function sf(): void { /* ... */ }\n}\n\n// --------------------------------------------------------\n\ntrait T1 {\n  <<__Override>> // checked on use classes\n  public function foo(): void {}\n}\n\nclass C1 {\n//  use T1; // error! foo is not an override\n}\n\nclass C2 {\n  public function foo(): void {}\n}\n\nclass C3 extends C2 {\n  use T1; // OK! C2's implementation is being overridden\n}\n\n// --------------------------------------------------------\n\ninterface I1 {\n  public function f(): void;\n}\n\n// Without I1, I2 causes\n// NS_Override\\I2::f() is marked as override; no non-private parent definition found or overridden\n// parent is defined in non-<?hh code\n\ninterface I2 extends I1 {\n  <<__Override>>\n  public function f(): void;\n}\n\nclass C implements I2 {\n  public function f(): void {}\n}\n\n// --------------------------------------------------------\n\n//<<__Override, Attr2(3, true)>>\t// hmmm! accepted\n<<__Override(3), Attr2(3, true)>>\t// hmmm! accepted\nfunction f1(): void { echo \"Inside \" . __FUNCTION__ . \"\\n\"; }\n\nfunction main(): void {\n  echo \"\\n============== top-level function =====================\\n\\n\";\n\n  f1();\n  $rf = new \\ReflectionFunction('\\NS_Override\\f1');\n  $attr1 = $rf->getAttribute('__Override');\t// hmmm!\n  var_dump($attr1);\n  $attr2 = $rf->getAttribute('Attr2');\n  var_dump($attr2);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Attributes/__Override.php.expect",
    "content": "\n============== top-level function =====================\n\nInside NS_Override\\f1\narray(1) {\n  [0]=>\n  int(3)\n}\narray(2) {\n  [0]=>\n  int(3)\n  [1]=>\n  bool(true)\n}"
  },
  {
    "path": "tests/Attributes/attributes.php",
    "content": "<?hh // strict\n\nnamespace NS_attrib1;\n\n// --------------------------------------------------------\n\n// example for spec\n\n<<Help(\"http://www.MyOnlineDocs.com/Widget.html\")>>\nclass Widget {\n  // ...\n}\n\n// --------------------------------------------------------\n\n<<Attr1, Attr2(3, true, 3.4, 'top-level function')>>\nfunction f1(): void { echo \"Inside \" . __FUNCTION__ . \"\\n\"; }\n\n// --------------------------------------------------------\n\n// attributes accepted, but don't seem to serve a purpose\n\n<<Attr1b, Attr2b(3, true, 3.4, 'trait')>>\ntrait T {\n  <<Attr1, Attr2(3, true, 3.4, 'trait instance method')>>\n  public function compute(): void { }\n\n  <<Attr1, Attr2(3, true, 3.4, 'trait static method')>>\n  public static function getData(): void { }\n}\n\n// --------------------------------------------------------\n\n// attributes accepted, but don't seem to serve a purpose\n\n<<Attr1c, Attr2c(3, true, 3.4, 'interface')>>\ninterface I {\n  // attributes accepted, but don't seem to serve a purpose\n\n  <<Attr1, Attr2(3, true, 3.4, 'interface instance method')>>\n  public function f(): void;\n}\n\n// --------------------------------------------------------\n\n// Check that token and whitespace handling is regular. It is\n// Also note that an empty value list is equivalent to no value list\n\n<<  Attr1()   , Attr2  (  3  , true  , 3.4  ,\n\t 'class C1'  )  >>\n\nclass C1 implements I {\n  use T;\n\n// hh_client - Expected modifier (Parsing[1002]); The class member _ is not always properly initialized\n//\n//  <<Attr1, Attr2(3, true, 3.4, 'const')>>\n  const int CON = 100;\n\n// hhvm - Fatal error: syntax error, unexpected T_STRING, expecting T_FUNCTION \n//\n//  <<Attr1, Attr2(3, true, 3.4, 'static int property')>>\n  private static int $pr1 = 0;\n\n// hhvm - Fatal error: syntax error, unexpected T_STRING, expecting T_FUNCTION\n//\n//  <<Attr1, Attr2(3, true, 3.4, 'int property')>>\n  private int $pr2 = 0;\n\n  <<Attr1, Attr2(3, true, 3.4, 'constructor')>>\n  public function __construct() { }\n\n  <<Attr1, Attr2(3, true, 3.4, 'destructor')>>\n  public function __destruct() { }\n\n  <<Attr1, Attr2(3, true, 3.4, 'instance method')>>\n  public function f(): void { }\n\n// attributes on parameter accepted, but don't seem to serve a purpose\n\n  public function f2(<<X>> int $p1): void { echo \"Inside \" . __FUNCTION__ . \"\\n\"; }\n\n  <<Attr1, Attr2(3, true, 3.4, 'static method')>>\n  public static function sf(): void { }\n}\n\n// --------------------------------------------------------\n\n// can't have duplicate attributes, with or without arguments\n// Accepted by hh_client, but rejected by hhvm; Redeclared attribute Attr3\n\n//<<Attr3, Attr3(3.4, 'class C2')>> \n//<<Attr3, Attr3>>\n//<<Attr3(3.4, 'class C2'), Attr3(3.4, 'class C2')>>\nclass C2 {}\n\n// --------------------------------------------------------\n\n// Can a target have multiple attribute specifications? No\n\n<<Attr4>>\n//<<Attr5>>\t// hh_client: rejected; Expected expression\nclass C3 {}\n\n// --------------------------------------------------------\n\n// What types can an attribute value have?\n\nenum ControlStatus: int {\n  Stopped = 0;\n  Stopping = 1;\n  Starting = 2;\n  Started = 3;\n}\n\n// no errors from hh_client, but from hhvm, \n// User-defined constants are not allowed in user attribute expressions\n\nclass X {\n  const int MAX = 100;\n}\n\n<<Attr6(true, 123, 3.4, 'class C4', null\n//\t, X::MAX\t\t\t// disallowed\n//\t, STDERR\t\t\t// disallowed\n\t, array(10, 20, 30)\n\t, array('x' => 3, 'y' => 5)\n//\t, ControlStatus::Stopping\t// disallowed\n\t, tuple (12, 5.9)\n\t, shape('x' => -3, 'y' => 6)\n//\t, Vector {22, 33}\t\t// disallowed\n)>> \nclass C4 {\n  <<Attr6(true, 123, 3.4, 'method C4->f', null\n//\t\t, X::MAX\t\t\t// disallowed\n//\t\t, STDERR\t\t\t// disallowed\n\t\t, array(10, 20, 30)\n\t\t, array('x' => 3, 'y' => 5)\n//\t\t, ControlStatus::Stopping\t// disallowed\n\t\t, tuple (12, 5.9)\n\t\t, shape('x' => -3, 'y' => 6)\n//\t\t, Vector {22, 33}\t\t// disallowed\n  )>> \n  public function f(): void { }\n}\n\n// --------------------------------------------------------\n\n// attributes cannot go in a closure type nor on an anonymous function\n\n/*\nclass C5 {\n  private (<<XX>> function (): void) $prop;\t// rejected by hh_client\n  public function __construct() {\n    $this->prop = <<XX>> function (): void { echo \"Hi there!\\n\"; };\t// rejected by hh_client\n  }\n}\n*/\n\n// --------------------------------------------------------\n\nfunction main(): void {\n  echo \"\\n============== top-level function =====================\\n\\n\";\n\n  f1();\n  $rf = new \\ReflectionFunction('\\NS_attrib1\\f1');\n  $attr1 = $rf->getAttribute('Attr1');\n  var_dump($attr1);\n  $attr2 = $rf->getAttribute('Attr2');\n  var_dump($attr2);\n\n// The method getAttributes is undefined in an object of type ReflectionFunction\n\n//  $attrs = $rf->getAttributes();\n//  var_dump($attrs);\n\n// --------------------------------------------------------\n\n  $rc = new \\ReflectionClass('\\NS_attrib1\\Widget');\n\n  echo \"\\n============== class Widget =====================\\n\\n\";\n\n  $attrHelp = $rc->getAttribute('Help');\n  var_dump($attrHelp);\n//  $attrHelp = $rc->getAttributes();\t// method not defined\n\n  echo \"\\n============== class C1->f2 =====================\\n\\n\";\n\n  $c1 = new C1();\n  $c1->f2(10);\n\n  $rc1 = new \\ReflectionClass('\\NS_attrib1\\C1');\n\n  echo \"\\n============== class =====================\\n\\n\";\n\n  $attr1 = $rc1->getAttribute('Attr1');\n  var_dump($attr1);\n  $attr2 = $rc1->getAttribute('Attr2');\n  var_dump($attr2);\n\n  echo \"\\n============== constructor =====================\\n\\n\";\n\n  $attr1 = $rc1->getMethod('__construct')->getAttribute('Attr1');\n  var_dump($attr1);\n  $attr2 = $rc1->getMethod('__construct')->getAttribute('Attr2');\n  var_dump($attr2);\n\n  echo \"\\n============== destructor =====================\\n\\n\";\n\n  $attr1 = $rc1->getMethod('__destruct')->getAttribute('Attr1');\n  var_dump($attr1);\n  $attr2 = $rc1->getMethod('__destruct')->getAttribute('Attr2');\n  var_dump($attr2);\n\n  echo \"\\n============== instance method =====================\\n\\n\";\n\n  $attr1 = $rc1->getMethod('f')->getAttribute('Attr1');\n  var_dump($attr1);\n  $attr2 = $rc1->getMethod('f')->getAttribute('Attr2');\n  var_dump($attr2);\n\n  echo \"\\n============== static method =====================\\n\\n\";\n\n  $attr1 = $rc1->getMethod('sf')->getAttribute('Attr1');\n  var_dump($attr1);\n  $attr2 = $rc1->getMethod('sf')->getAttribute('Attr2');\n  var_dump($attr2);\n\n  echo \"\\n============== trait instance method =====================\\n\\n\";\n\n  $attr1 = $rc1->getMethod('compute')->getAttribute('Attr1');\n  var_dump($attr1);\n  $attr2 = $rc1->getMethod('compute')->getAttribute('Attr2');\n  var_dump($attr2);\n\n  echo \"\\n============== trait static method =====================\\n\\n\";\n\n  $attr1 = $rc1->getMethod('getData')->getAttribute('Attr1');\n  var_dump($attr1);\n  $attr2 = $rc1->getMethod('getData')->getAttribute('Attr2');\n  var_dump($attr2);\n\n  echo \"\\n============== class C4 =====================\\n\\n\";\n\n  $rc4 = new \\ReflectionClass('\\NS_attrib1\\C4');\n  $attr6 = $rc4->getAttribute('Attr6');\n  var_dump($attr6);\n  $attr6 = $rc4->getMethod('f')->getAttribute('Attr6');\n  var_dump($attr6);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Attributes/attributes.php.expect",
    "content": "\n============== top-level function =====================\n\nInside NS_attrib1\\f1\narray(0) {\n}\narray(4) {\n  [0]=>\n  int(3)\n  [1]=>\n  bool(true)\n  [2]=>\n  float(3.4)\n  [3]=>\n  string(18) \"top-level function\"\n}\n\n============== class Widget =====================\n\narray(1) {\n  [0]=>\n  string(39) \"http://www.MyOnlineDocs.com/Widget.html\"\n}\n\n============== class C1->f2 =====================\n\nInside f2\n\n============== class =====================\n\narray(0) {\n}\narray(4) {\n  [0]=>\n  int(3)\n  [1]=>\n  bool(true)\n  [2]=>\n  float(3.4)\n  [3]=>\n  string(8) \"class C1\"\n}\n\n============== constructor =====================\n\narray(0) {\n}\narray(4) {\n  [0]=>\n  int(3)\n  [1]=>\n  bool(true)\n  [2]=>\n  float(3.4)\n  [3]=>\n  string(11) \"constructor\"\n}\n\n============== destructor =====================\n\narray(0) {\n}\narray(4) {\n  [0]=>\n  int(3)\n  [1]=>\n  bool(true)\n  [2]=>\n  float(3.4)\n  [3]=>\n  string(10) \"destructor\"\n}\n\n============== instance method =====================\n\narray(0) {\n}\narray(4) {\n  [0]=>\n  int(3)\n  [1]=>\n  bool(true)\n  [2]=>\n  float(3.4)\n  [3]=>\n  string(15) \"instance method\"\n}\n\n============== static method =====================\n\narray(0) {\n}\narray(4) {\n  [0]=>\n  int(3)\n  [1]=>\n  bool(true)\n  [2]=>\n  float(3.4)\n  [3]=>\n  string(13) \"static method\"\n}\n\n============== trait instance method =====================\n\narray(0) {\n}\narray(4) {\n  [0]=>\n  int(3)\n  [1]=>\n  bool(true)\n  [2]=>\n  float(3.4)\n  [3]=>\n  string(21) \"trait instance method\"\n}\n\n============== trait static method =====================\n\narray(0) {\n}\narray(4) {\n  [0]=>\n  int(3)\n  [1]=>\n  bool(true)\n  [2]=>\n  float(3.4)\n  [3]=>\n  string(19) \"trait static method\"\n}\n\n============== class C4 =====================\n\narray(9) {\n  [0]=>\n  bool(true)\n  [1]=>\n  int(123)\n  [2]=>\n  float(3.4)\n  [3]=>\n  string(8) \"class C4\"\n  [4]=>\n  NULL\n  [5]=>\n  array(3) {\n    [0]=>\n    int(10)\n    [1]=>\n    int(20)\n    [2]=>\n    int(30)\n  }\n  [6]=>\n  array(2) {\n    [\"x\"]=>\n    int(3)\n    [\"y\"]=>\n    int(5)\n  }\n  [7]=>\n  array(2) {\n    [0]=>\n    int(12)\n    [1]=>\n    float(5.9)\n  }\n  [8]=>\n  array(2) {\n    [\"x\"]=>\n    int(-3)\n    [\"y\"]=>\n    int(6)\n  }\n}\narray(9) {\n  [0]=>\n  bool(true)\n  [1]=>\n  int(123)\n  [2]=>\n  float(3.4)\n  [3]=>\n  string(12) \"method C4->f\"\n  [4]=>\n  NULL\n  [5]=>\n  array(3) {\n    [0]=>\n    int(10)\n    [1]=>\n    int(20)\n    [2]=>\n    int(30)\n  }\n  [6]=>\n  array(2) {\n    [\"x\"]=>\n    int(3)\n    [\"y\"]=>\n    int(5)\n  }\n  [7]=>\n  array(2) {\n    [0]=>\n    int(12)\n    [1]=>\n    float(5.9)\n  }\n  [8]=>\n  array(2) {\n    [\"x\"]=>\n    int(-3)\n    [\"y\"]=>\n    int(6)\n  }\n}"
  },
  {
    "path": "tests/Basic_Concepts/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Basic_Concepts/program_structure.php",
    "content": "<?hh // strict\n\n// ?> closing tag not allowed\n"
  },
  {
    "path": "tests/Basic_Concepts/program_structure.php.expectf",
    "content": "\nFatal error: HH mode: ?> not allowed (Line: 3, Char: 30)\nsyntax error, unexpected T_HH_ERROR, expecting $end in %s/tests/Basic_Concepts/program_structure.php on line 3"
  },
  {
    "path": "tests/Basic_Concepts/top_level_stuff.php",
    "content": "<?hh // strict\n\nnamespace NS_top_level_stuff;\nuse NS2\\X;\nclass C {}\ninterface I {}\ntrait T {}\nfunction f1(): void {}\n\n//{ }\n//f1();\n//if (5 < 10) echo \"True\\n\"; else echo \"False\\n\";\n//for ($i = 1; $i <= 5; ++$i) echo \"$i = $i\\n\";\n//return;\n//declare(encoding = 'ISO-8859-1');\n//const MAXIMUM_LENGTH = 1000;\n//static $s = 100;\n"
  },
  {
    "path": "tests/Basic_Concepts/top_level_stuff.php.expect",
    "content": ""
  },
  {
    "path": "tests/Classes/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Classes/Aircraft.php",
    "content": "<?hh // strict\n\nnamespace NS_Vehicles;\n\nrequire_once 'Vehicle.php';\n\nabstract class Aircraft extends Vehicle {\n  public abstract function getMaxAltitude(): int;\n  // ...\n}\n"
  },
  {
    "path": "tests/Classes/Aircraft.php.expect",
    "content": ""
  },
  {
    "path": "tests/Classes/Closure_call.php",
    "content": "// NOT YET IMPLEMENTED IN CHECKER OR ENGINE <?hh // strict\n\nnamespace NS_Closure_call;\n\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2014-2016 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\nclass Value {\n  protected int $value;\n\n  public function __construct(int $value) {\n    $this->value = $value;\n  }\n\n  public function getValue(): int {\n    return $this->value;\n  }\n}\n\nfunction main(): void {\n\n  $three = new Value(3);\n  $four = new Value(4);\n\n  $closure = function ($delta) { var_dump($this->getValue() + $delta); };\n  $closure->call($three, 4);\n  $closure->call($four, 4);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/Closure_call.php.expectf",
    "content": "\nFatal error: HH mode: content before <?hh (Line: 1, Char: 44)\nsyntax error, unexpected T_HH_ERROR, expecting $end in %s/tests/Classes/Closure_call.php on line 1"
  },
  {
    "path": "tests/Classes/Generator_getReturn.php",
    "content": "// NOT YET IMPLEMENTED   <?hh // strict\n\nnamespace NS_Generator_getReturn;\n\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2015-2016 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\nfunction foo(): \\Generator<int, int, void> {\n    yield 1;\n    yield 2;\n    return 42;\n}\n\nfunction main(): void { \n  $bar = foo();\n\n  try {\n    var_dump($bar->getReturn());\n    echo \"Call to getReturn succeded\\n\";\n  }\n  catch (\\Exception $e) {\n    echo \"Call to getReturn failed\\n\";\n    echo $e . \"\\n\";\n  }\n\n  foreach ($bar as $element) {\n    echo $element, \"\\n\";\n  }\n \n  var_dump($bar->getReturn());\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/Generator_getReturn.php.expectf",
    "content": "\nFatal error: HH mode: content before <?hh (Line: 1, Char: 25)\nsyntax error, unexpected T_HH_ERROR, expecting $end in %s/tests/Classes/Generator_getReturn.php on line 1"
  },
  {
    "path": "tests/Classes/MathLibrary.php",
    "content": "<?hh // strict\n\nnamespace NS_MathLibrary;\n\nfinal class MathLibrary {\n  private function __construct(): void {}\t// disallows instantiation\n\n  public static function sin(float $p): float { return 0.0; /* ... */ }\n  public static function cos(float $p): float { return 0.0; /* ... */ }\n  public static function tan(float $p): float { return 0.0; /* ... */ }\n  // ...\n}\n"
  },
  {
    "path": "tests/Classes/MathLibrary.php.expect",
    "content": ""
  },
  {
    "path": "tests/Classes/MathLibrary_test1.php",
    "content": "<?hh // strict\n\nnamespace NS_MathLibrary_test1;\n\nrequire_once 'MathLibrary.php';\n\nfunction main(): void {\n//  $m = new \\NS_MathLibrary\\MathLibrary();\t// can't instantiate a final class\n\n  \\NS_MathLibrary\\MathLibrary::sin(2.34);\n  \\NS_MathLibrary\\MathLibrary::cos(2.34);\n  \\NS_MathLibrary\\MathLibrary::tan(2.34);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/MathLibrary_test1.php.expect",
    "content": ""
  },
  {
    "path": "tests/Classes/MyCollection.php",
    "content": "<?hh // strict\n\nnamespace NS_MyCollections;\n\ninterface MyCollection {\n  public function put(int $item): void;\n  public function get(): int;\n}\n"
  },
  {
    "path": "tests/Classes/MyCollection.php.expect",
    "content": ""
  },
  {
    "path": "tests/Classes/MyList.php",
    "content": "<?hh // strict\n\nnamespace NS_MyList;\n\nrequire_once 'MyCollection.php';\n\nclass MyList implements \\NS_MyCollections\\MyCollection {\n  public function put(int $item): void {\n    // ...\n  }\n\n  public function get(): int {\n    // ...\n    return 100;\n  }\n\t\n  // ...\n}\n\n"
  },
  {
    "path": "tests/Classes/MyList.php.expect",
    "content": ""
  },
  {
    "path": "tests/Classes/PassengerJet.php",
    "content": "<?hh // strict\n\nnamespace NS_Vehicles;\n\nrequire_once 'Aircraft.php';\n\nclass PassengerJet extends Aircraft {\n  public function __construct(...) {}\n\n  public function getMaxSpeed(): int {\n    // implement method\n    return 550;\n  }\n\n  public function getMaxAltitude(): int {\n    // implement method\n    return 30000;\n  }\n\n  // ...\n}\n"
  },
  {
    "path": "tests/Classes/PassengerJet.php.expect",
    "content": ""
  },
  {
    "path": "tests/Classes/Point.php",
    "content": "<?hh // strict\n\nnamespace NS_Point;\n\nclass Point {\n  private static int $nextId = 1;\n  private array<string,mixed> $dynamicProperties = array();\n  private static int $pointCount = 0;\n  private int $id;\n\n  private float $x;\t\t// Cartesian x-coordinate\n  private float $y;\t\t// Cartesian y-coordinate\n\n  public function getX(): float  { return $this->x; }\n  public function setX(num $x):void \t{ $this->x = (float)$x;   }\n  public function getY(): float  { return $this->y; }\n  public function setY(num $y): void   { $this->y = (float)$y;   }\n\n  public static function getPointCount(): int {\n    return self::$pointCount;\n  }\n\n  public function __construct(num $x = 0, num $y = 0) {\n    $this->x = (float)$x;\n    $this->y = (float)$y;\n    ++self::$pointCount;\n    $this->id = self::$nextId++;\t// assign the next available id\n    echo \"Inside \" . __METHOD__ . \", point count = \" . self::$pointCount . \"\\n\";\n  }\n\n  public function __destruct() {\n    --self::$pointCount;\n    echo \"Inside \" . __METHOD__ . \", point count = \" . self::$pointCount . \"\\n\";\n  }\n\n  public function move(num $x, num $y): void {\n    $this->x = (float)$x;\n    $this->y = (float)$y;\n  }\t\n\n  public function translate(num $x, num $y): void {\n    $this->x += $x;\n    $this->y += $y;\n  }\n\n  public function __toString(): string {\n    return '(' . $this->x . ',' . $this->y . ')';\n  }\t\n\n  public function __clone(): void {\n    ++self::$pointCount;\n    echo \"Inside \" . __METHOD__ . \", point count = \" . self::$pointCount . \"\\n\";\n  }\n\n  public function __call(string $name, array<mixed> $arguments) : mixed\t{\n    echo \"Inside \" . __METHOD__ . \", \\$name = $name\\n\";\n    var_dump($arguments); echo \"\\n\";\n  }\n\n  public static function __callStatic(string $name, array<mixed> $arguments) : mixed {\n    echo \"Inside \" . __METHOD__ . \", \\$name = $name\\n\";\n    var_dump($arguments); echo \"\\n\";\n  }\n\n  public function __get(string $name): mixed {\n    echo \"Inside \" . __METHOD__ . \", \\$name = $name\\n\";\n\n    if (array_key_exists($name, $this->dynamicProperties)) {\n      return $this->dynamicProperties[$name];\n    }\n\n    // no-such-property error handling goes here\n    return null;\n  }\n\n  public function __set(string $name, mixed $value): void {\n    echo \"Inside \" . __METHOD__ . \", \\$name = $name\\n\";\n    var_dump($value); echo \"\\n\";\n\n    $this->dynamicProperties[$name] = $value;\n  }\n\n  public function __isset(string $name): bool {\n    echo \"Inside \" . __METHOD__ . \", \\$name = $name\\n\";\n\n    return true; //isset($this->dynamicProperties[$name]);\n  }\n\n  public function __unset(string $name): void {\n    echo \"Inside \" . __METHOD__ . \", \\$name = $name\\n\";\n\n//  unset($this->dynamicProperties[$name]);\n  }\n\n  public function __invoke(...): mixed {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n//  var_dump($p); echo \"\\n\";\n\n    return true;\n  }\n\n  static public function __set_state(array<string,mixed> $properties): Point {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    var_dump($properties); echo \"\\n\";\n\n    $p = new Point();\n    $p->x = (float)$properties['x'];\n    $p->y = (float)$properties['y'];\n    return $p;\n  }\n\n  public function __sleep(): array<string> {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n\n    return array('y', 'x');\t// serialize only $y and $x, in that order\n  }\n\n  public function __wakeup(): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n\n    $this->id = self::$nextId++;\t// assign a new id\n  }\n}\n"
  },
  {
    "path": "tests/Classes/Point.php.expect",
    "content": ""
  },
  {
    "path": "tests/Classes/Point2.php",
    "content": "<?hh // strict\n\nnamespace NS_Point2;\n\nclass Point2 {\n  private static int $pointCount = 0;\n\n  public float $x;\t\t// Cartesian x-coordinate\n  public float $y;\t\t// Cartesian y-coordinate\n\n  public static function getPointCount(): int {\n    return self::$pointCount;\n  }\n\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    $this->x = $x;\n    $this->y = $y;\n    ++self::$pointCount;\n  }\n\n  public function __destruct() {\n    --self::$pointCount;\n  }\n///*\n  public function __clone(): void {\n    ++self::$pointCount;\n\n    echo \"Inside \" . __METHOD__ . \", point count = \" . self::$pointCount . \"\\n\";\n  }\n//*/\n\n  public function __toString(): string {\n    return '(' . $this->x . ',' . $this->y . ')';\n  }\t\n}\n"
  },
  {
    "path": "tests/Classes/Point2.php.expect",
    "content": ""
  },
  {
    "path": "tests/Classes/Point_test1.php",
    "content": "<?hh // strict\n\nrequire_once 'Point.php';\nuse NS_Point\\Point;\n\nfunction main(): void {\n  error_reporting(-1);\n\n  echo \"\\n==================== new Point ===================\\n\\n\";\n\n  $p1 = new Point();\n  echo \"\\$p1 = $p1\\n\";\n//  unset($p1);\n\n  echo \"\\n==================== new Point() ===================\\n\\n\";\n\n  $p1 = new Point();\n  var_dump($p1);\n//  unset($p1);\n\n  echo \"\\n==================== new Point(100) ===================\\n\\n\";\n\n  $p1 = new Point(100);\t\t// let y default\n  var_dump($p1);\n//  unset($p1);\n\n//  echo \"\\n==================== new 'Point'(-1, 1) ===================\\n\\n\";\n//\n//  $cName = 'Point';\n//  $p1 = new $cName(-1, 1);\t// use string form\n//  var_dump($p1);\n//  unset($p1);\n\n  echo \"\\n==================== new Point(20,30) ===================\\n\\n\";\n\n  $p1 = new Point(20,30.0);\n  echo \"\\$p1 = $p1\\n\";\n\n  echo \"\\n==================== \\$p1->getX(), \\$p1->getY() ===================\\n\\n\";\n\n  var_dump($p1->getX());\n  var_dump($p1->getY());\n\n  echo \"\\n==================== \\$p1->setX(), \\$p1->setY() ===================\\n\\n\";\n\n  $p1->setX(-3);\n  $p1->setY(10);\n  echo $p1 . \"\\n\";\t\t\t\t\t// implicit call to __toString()\n  echo $p1->__toString() . \"\\n\";\t\t// explicit call to __toString()\n\n  echo \"\\n==================== \\$p1->move(-5, 7) ===================\\n\\n\";\n\n  $p1->move(-5, 7);\n  echo $p1 . \"\\n\";\n\n  echo \"\\n==================== \\$p1->translate(1, 1) ===================\\n\\n\";\n\n  $p1->translate(1, 1);\n  echo $p1 . \"\\n\";\n//  unset($p1);\n\n  echo \"\\n==================== create 3 Points then call getPointCount() ===================\\n\\n\";\n\n  $p1 = new Point();\n  $p2 = new Point(-4,3);\n  $p3 = new Point(20,30);\n\n  echo \"Point count = \" . Point::getPointCount() . \"\\n\";\n//  $cName = 'Point';\n//  echo \"Point count = \" . $cName::getPointCount() . \"\\n\";\n//  unset($p1, $p2, $p3);\n\n  echo \"\\n==================== \\$p1->iMethod(...) ===================\\n\\n\";\n\n  $p1 = new Point();\n  $p1->iMethod(10, true, \"abc\");\t// $p1->__call('iMethod', array(…))\n//  unset($p1);\n\n  echo \"\\n==================== Point::sMethod(NULL, 1.234) ===================\\n\\n\";\n\n  Point::sMethod(null, 1.234);\t// Point::__callStatic('sMethod', array(…))\n\n  echo \"\\n==================== \\$p1 = new Point(3.123, 6.2) ===================\\n\\n\";\n\n  $p1 = new Point(3.123, 6.2);\n  $p2 = clone $p1;\n  echo \"\\$p1 = $p1\\n\";\n  echo \"\\$p2 = $p2\\n\";\n//  unset($p1, $p2);\n\n//  echo \"\\n==================== set/get dynamic property ===================\\n\\n\";\n\n//\n//  $p1 = new Point(2, 1);\n//  $p1->dummy = \"abc\";            // set dynamic property\n//  var_dump($p1);\n//  $v = $p1->dummy;             // get dynamic property\n//  echo \"dummy = $v\\n\";\n\n//  echo \"\\n==================== isset ===================\\n\\n\";\n\n//\n//  var_dump(isset($p1->dummy));     // test if dummy exists and is accessible, or is dynamic\n\n  echo \"\\n==================== unset ===================\\n\\n\";\n\n//  unset($p1->dummy);\n//  unset($p1);\n\n//  echo \"\\n==================== __invoke() ===================\\n\\n\";\n\n//\n//  $p1 = new Point(2.3, 4.5);\n//  $r = $p1(123);\t\t// becomes $r = $p1->__invoke(123);\t\n//  echo \"\\$r = $r\\n\";\n//  unset($p1);\n\n  echo \"\\n==================== __set_state/var_export ===================\\n\\n\";\n\n  $p1 = new Point(3, 5);\n  $v = var_export($p1, true);\t// returns string representation of $p1\n  var_dump($v);\n//  unset($p1);\n\n  echo \"\\n==================== __sleep/__wakeup ===================\\n\\n\";\n\n  $p1 = new Point(-1, 0);\n  $s = serialize($p1);\t\t// serialize Point(-1,0)\n//  echo \"\\$s = >$s<\\n\";\n  var_dump($s);\n  $v = unserialize($s);\t\t// unserialize Point(-1,0)\n//  echo \"\\$v = >$v<\\n\";\n  var_dump($v);\n//  unset($p1);\n\n  echo \"\\n==================== end ===================\\n\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/Serializable.php",
    "content": "<?hh // strict\n\nnamespace NS_Serializable;\n\nclass Point implements \\Serializable {\n  private static int $nextId = 1;\n\n  private float $x;\n  private float $y;\n  private int $id;\n\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    $this->x = $x;\n    $this->y = $y;\n    $this->id = self::$nextId++;\n\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n  }\n\n  public function __toString(): string {\n    return 'ID:' . $this->id . '(' . $this->x . ',' . $this->y . ')';\n  }\t\n\n  public function serialize(): string {\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n\t\t\n    return serialize(array('y' => $this->y, 'x' => $this->x));\n  }\n    \n  public function unserialize(string $data): void {\n    $data = unserialize($data);\n    $this->x = $data['x'];\n    $this->y = $data['y'];\n    $this->id = self::$nextId++;\n\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n  }\n}\n\nclass ColoredPoint extends Point implements \\Serializable {\n  const int RED = 1;\n  const int BLUE = 2;\n\n  private int $color;\n\n  public function __construct(float $x = 0.0, float $y = 0.0, int $color = ColoredPoint::RED) {\n    parent::__construct($x, $y);\n    $this->color = $color;\n\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n  }\n\n  public function __toString(): string {\n    return parent::__toString() . $this->color;\n  }\t\n\n  public function serialize(): string {\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n\t\t\n    return serialize(array(\n      'color' => $this->color,\n      'baseData' => parent::serialize()\n    ));\n  }\n    \n  public function unserialize(string $data): void {\n    $data = unserialize($data);\n    $this->color = $data['color'];\n    parent::unserialize($data['baseData']);\n\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n  }\n}\n\nfunction main(): void {\n  echo \"---------------- create, serialize, and unserialize a Point -------------------\\n\";\n\n  $p = new Point(2.0, 5.0);\n  echo \"Point \\$p = $p\\n\";\n\n  $s = serialize($p);\n  var_dump($s);\n\n  echo \"------\\n\";\n\n  $v = unserialize($s);\n  var_dump($v);\n\n  echo \"---------------- Serialize ColoredPoint -------------------\\n\";\n\n  $cp = new ColoredPoint(9.0, 8.0, ColoredPoint::BLUE);\n  echo \"ColoredPoint \\$cp = $cp\\n\";\n\n  $s = serialize($cp);\n  var_dump($s);\n\n  $v = unserialize($s);\n  var_dump($v);\n\n  echo \"---------------- end -------------------\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/Serializable.php.expectf",
    "content": "\nFatal error: Declaration of NS_Serializable\\Point::unserialize() must be compatible with that of Serializable::unserialize() in %s/tests/Classes/Serializable.php on line 5"
  },
  {
    "path": "tests/Classes/Serializable_with_untrusted_data.php",
    "content": "// NOT YET IMPLEMENTED IN CHECKER OR ENGINE <?hh // strict\n\nnamespace NS_Serializable_with_untrusted_data;\n\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2014-2016, 2015 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\nclass Point implements \\Serializable {\n  private static int $nextId = 1;\n\n  private int $x;\n  private int $y;\n  private int $id;\n\n  public function __construct(int $x = 0, int $y = 0) {\n    $this->x = $x;\n    $this->y = $y;\n    $this->id = self::$nextId++;\n\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n  }\n\n  public function __toString(): string {\n    return 'ID:' . $this->id . '(' . $this->x . ',' . $this->y . ')';\n  }\t\n\n  public function serialize(): string {\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n\t\t\n    return serialize(array('y' => $this->y, 'x' => $this->x));\n  }\n    \n  public function unserialize(string $data): void {\n    $data = unserialize($data);\n    $this->x = $data['x'];\n    $this->y = $data['y'];\n    $this->id = self::$nextId++;\n\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n  }\n}\n\nclass ColoredPoint extends Point implements \\Serializable {\n  const int RED = 1;\n  const int BLUE = 2;\n\n  private int $color;\n\n  public function __construct(int $x = 0, int $y = 0, int $color = ColoredPoint::RED) {\n    parent::__construct($x, $y);\n    $this->color = $color;\n\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n  }\n\n  public function __toString(): string {\n    return parent::__toString() . $this->color;\n  }\t\n\n  public function serialize(): string {\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n\t\t\n    return serialize(array(\n      'color' => $this->color,\n      'baseData' => parent::serialize()\n    ));\n  }\n    \n  public function unserialize(string $data): void {\n    $data = unserialize($data);\n    $this->color = $data['color'];\n    parent::unserialize($data['baseData']);\n\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n  }\n}\n\nfunction main(): void {\n\n  echo \"---------------- create, serialize, and unserialize a Point -------------------\\n\";\n\n  $p = new Point(2, 5);\n  echo \"Point \\$p = $p\\n\";\n\n  $s = serialize($p);\n  var_dump($s);\n\n  echo \"------\\n\";\n\n//  $v = unserialize($s, [\"allowed_classes\" => true]);\t// OK\n  $v = unserialize($s, [\"allowed_classes\" => false]);\t\t// converts Point to __PHP_Incomplete_Class\n  var_dump($v);\n\n  echo \"---------------- Serialize ColoredPoint -------------------\\n\";\n\n  $cp = new ColoredPoint(9, 8, ColoredPoint::BLUE);\n  echo \"ColoredPoint \\$cp = $cp\\n\";\n\n  $s = serialize($cp);\n  var_dump($s);\n\n//  $v = unserialize($s, [\"allowed_classes\" => true]);\t// OK\n  $v = unserialize($s, [\"allowed_classes\" => false]);\t\t// converts ColoredPoint to __PHP_Incomplete_Class\n  var_dump($v);\n\n  echo \"---------------- end -------------------\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/Serializable_with_untrusted_data.php.expectf",
    "content": "\nFatal error: HH mode: content before <?hh (Line: 1, Char: 44)\nsyntax error, unexpected T_HH_ERROR, expecting $end in %s/tests/Classes/Serializable_with_untrusted_data.php on line 1"
  },
  {
    "path": "tests/Classes/Vehicle.php",
    "content": "<?hh // strict\n\nnamespace NS_Vehicles;\n\nabstract class Vehicle {\n  public abstract function getMaxSpeed(): int;\n\n  // ...\n}\n"
  },
  {
    "path": "tests/Classes/Vehicle.php.expect",
    "content": ""
  },
  {
    "path": "tests/Classes/Vehicle_test1.php",
    "content": "<?hh // strict\n\nnamespace NS_Vehicle_test1;\n\nrequire_once 'PassengerJet.php';\n\nfunction main(): void {\n  $pj = new \\NS_Vehicles\\PassengerJet(\"Horizon\", 1993, 33000, 235);\n  echo \"\\$pj's maximum speed: \" . $pj->getMaxSpeed() . \"\\n\";\n  echo \"\\$pj's maximum altitude: \" . $pj->getMaxAltitude() . \"\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/Vehicle_test1.php.expect",
    "content": "$pj's maximum speed: 550\n$pj's maximum altitude: 30000"
  },
  {
    "path": "tests/Classes/__PHP_Incomplete_Class.php",
    "content": "<?hh // strict\n\nnamespace NS___PHP_Incomplete_Class;\n\nclass Point {\n  private float $x;\n  private float $y;\n\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    $this->x = $x;\n    $this->y = $y;\n\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n  }\n\n  public function __toString(): string {\n    return '(' . $this->x . ',' . $this->y . ')';\n  }\t\n}\n\nfunction main(): void {\n  echo \"--- create a Point ---\\n\\n\";\n\n  $p = new Point(2.0, 5.0);\n  echo \"Point \\$p = $p\\n\";\n\n  echo \"\\n--- serialize that Point ---\\n\\n\";\n\n  $s = serialize($p);\t\t// all instance properties get serialized\n  var_dump($s);\n\n  echo \"\\n--- unserialize that Point ---\\n\\n\";\n\n  $v = unserialize($s);\n  var_dump($v);\n\n  echo \"\\n--- fake string value ---\\n\\n\";\n\n  $s[32] = 'J';\t\t// change class name, so an unserialize failure occurs\n  var_dump($s);\n\n  echo \"\\n--- unserialize that Point to non-existant class type ---\\n\\n\";\n\n  $v = unserialize($s);\n  var_dump($v);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/abstract_constants.php",
    "content": "<?hh // strict\n\nnamespace NS_abstract_constants;\n\ninterface I1 {\n  abstract const int CI;\n  abstract const int CI2;\n}\n\ninterface I2 extends I1 {\n  abstract const int CI;\n  const int CI2 = 50;\n}\n\nabstract class C1 implements I2 {\n  const int CI = 10;\n  abstract const int C3;\n}\n\nclass C2 implements I2 {\n  const int CI = 20;\n  const int C3 = 55;\n}\n\nclass C3 extends C1 {\n  const int CI = 99;\n  const int C3 = 66;\n}\n\nfunction main(): void {\n  var_dump(new C2());\n  var_dump(new C3());\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/abstract_constants.php.expect",
    "content": "object(NS_abstract_constants\\C2)#1 (0) {\n}\nobject(NS_abstract_constants\\C3)#1 (0) {\n}"
  },
  {
    "path": "tests/Classes/cc.php",
    "content": "<?php\n\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2014, 2015 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\nerror_reporting(-1);\n\nclass Value {\n    protected $value;\n\n    public function __construct($value) {\n        $this->value = $value;\n    }\n\n    public function getValue() {\n        return $this->value;\n    }\n}\n\n$three = new Value(3);\n$four = new Value(4);\n\n$closure = function ($delta) { var_dump($this->getValue() + $delta); };\n$closure->call($three, 4);\n$closure->call($four, 4);"
  },
  {
    "path": "tests/Classes/cc.php.expectf",
    "content": "int(7)\nint(8)\n"
  },
  {
    "path": "tests/Classes/classes.php",
    "content": "<?hh // strict\n\nnamespace NS_classes;\n\ninterface I1 {}\ninterface I2 {}\nclass C1 {}\nclass C2 extends C1 implements I1, I2 {}\n\nfunction main(): void {\n  $c = new C2();\n  var_dump($c);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n\n"
  },
  {
    "path": "tests/Classes/classes.php.expect",
    "content": "object(NS_classes\\C2)#1 (0) {\n}"
  },
  {
    "path": "tests/Classes/cloning.php",
    "content": "<?hh // strict\n\nnamespace NS_cloning;\n\nrequire_once 'Point2.php';\nuse NS_Point2\\Point2;\n\nclass C {\n  private int $m;\n  public function __construct(int $p1) {\n    $this->m = $p1;\n  }\n\n///*\n  public function __clone(): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n//*/\n}\n\nclass Employee {\n  private string $name;\n\n  public function __construct(string $name) {\n    $this->name = $name;\n  }\n\n  public function __clone(): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n\n    // make a copy of Employee object\n  }\n}\n\nclass Manager extends Employee {\n  private int $level;\n\n  public function __construct(string $name, int $level) {\n    parent::__construct($name);\n    $this->level = $level;\n  }\n\n  public function __clone(): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n\n    parent::__clone();\n\n    // make a copy of Manager object\n  }\n}\n\nfunction main(): void {\n  $obj1 = new C(10);\n  var_dump($obj1);\n\n  $obj2 = clone $obj1;\t// default action is to make a shallow copy\n  var_dump($obj2);\n\n  echo \"================= Use cloning in Point class =================\\n\";\n\n  echo \"Point count = \" . Point2::getPointCount() . \"\\n\";\n  $p1 = new Point2(-3.5, 1.4);\n  var_dump($p1);\n  echo \"Point count = \" . Point2::getPointCount() . \"\\n\";\n  $p2 = clone $p1;\n  var_dump($p2);\n  echo \"Point count = \" . Point2::getPointCount() . \"\\n\";\n\n  var_dump($p3 = clone $p1);\n  echo \"Point count = \" . Point2::getPointCount() . \"\\n\";\n\n  var_dump($p4 = clone $p1);\n  echo \"Point count = \" . Point2::getPointCount() . \"\\n\";\n\n  echo \"================= use chained cloning in a class heirarchy =================\\n\";\n\n  $obj3 = new Manager(\"Smith\", 23);\n  var_dump($obj3);\n\n  $obj4 = clone $obj3;\n  var_dump($obj4);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/cloning.php.expect",
    "content": "object(NS_cloning\\C)#1 (1) {\n  [\"m\":\"NS_cloning\\C\":private]=>\n  int(10)\n}\nInside NS_cloning\\C::__clone\nobject(NS_cloning\\C)#2 (1) {\n  [\"m\":\"NS_cloning\\C\":private]=>\n  int(10)\n}\n================= Use cloning in Point class =================\nPoint count = 0\nobject(NS_Point2\\Point2)#3 (2) {\n  [\"x\"]=>\n  float(-3.5)\n  [\"y\"]=>\n  float(1.4)\n}\nPoint count = 1\nInside NS_Point2\\Point2::__clone, point count = 2\nobject(NS_Point2\\Point2)#4 (2) {\n  [\"x\"]=>\n  float(-3.5)\n  [\"y\"]=>\n  float(1.4)\n}\nPoint count = 2\nInside NS_Point2\\Point2::__clone, point count = 3\nobject(NS_Point2\\Point2)#5 (2) {\n  [\"x\"]=>\n  float(-3.5)\n  [\"y\"]=>\n  float(1.4)\n}\nPoint count = 3\nInside NS_Point2\\Point2::__clone, point count = 4\nobject(NS_Point2\\Point2)#6 (2) {\n  [\"x\"]=>\n  float(-3.5)\n  [\"y\"]=>\n  float(1.4)\n}\nPoint count = 4\n================= use chained cloning in a class heirarchy =================\nobject(NS_cloning\\Manager)#7 (2) {\n  [\"level\":\"NS_cloning\\Manager\":private]=>\n  int(23)\n  [\"name\":\"NS_cloning\\Employee\":private]=>\n  string(5) \"Smith\"\n}\nInside NS_cloning\\Manager::__clone\nInside NS_cloning\\Employee::__clone\nobject(NS_cloning\\Manager)#8 (2) {\n  [\"level\":\"NS_cloning\\Manager\":private]=>\n  int(23)\n  [\"name\":\"NS_cloning\\Employee\":private]=>\n  string(5) \"Smith\"\n}"
  },
  {
    "path": "tests/Classes/constructors.php",
    "content": "<?hh // strict\n\nnamespace NS_constructors;\n\nclass D1 {\n  public function __construct(int $p1) {\n    echo \"In D1 constructor, $p1\\n\";\n  }\n}\n\nclass D2 extends D1 {\n  public function __construct(int $p1, int $p2) {\n    parent::__construct($p1);\n    echo \"In D2 constructor, $p1, $p2\\n\";\n  }\n}\n\nclass D3 extends D2 {\n  public function __construct(int $p1, int $p2, int $p3) {\n    parent::__construct($p1, $p2);\n    echo \"In D3 constructor, $p1, $p2, $p3\\n\";\n  }\n}\n\nclass D4 extends D3 {\n  public function __construct() {\n    parent::__construct(1, 2, 3);\n    echo \"In D4 constructor\\n\";\n  }\n}\n\n// ---------------------------------------------------------\n\n// Play with private parameters\n// starting with supposedly unintended uses\n\n// *** private is accepted in a regular function; that doesn't sound right. Note also public/protected\n// However, hhvm gags with Fatal error: syntax error, unexpected T_PRIVATE\n\n//function f1(private int $p1, public int $p2, protected int $p3): void {}\n\n// ---------------------------------------------------------\n\n// can't have private in a closure's parameter list; okay\n\n//function f2((function (private int, int, int): void) $p1): void {}\n\n// ---------------------------------------------------------\n\nfunction f3(int $iValue, (function (int): int) $process): int {\n  return $process($iValue);\n}\n\n// *** private is accepted in an anonymous function; that doesn't sound right\n// However, hhvm gags with Fatal error: syntax error, unexpected T_PRIVATE\n\nfunction f4(): void {\n//  $result = f3(5, function (private int $p) { return $p * 2; });\t// doubles 5\n}\n\n// ---------------------------------------------------------\n\n// *** private is accepted in an abstract method in an interface; that doesn't sound right\n// However, hhvm gags with Fatal error: Parameters modifiers not allowed on methods\n\ninterface I1 {\n//  public function f(private int $p1): void;\n}\n\n// ---------------------------------------------------------\n\n// *** private is accepted in a method in a trait; that doesn't sound right\n// However, hhvm gags with Fatal error: Parameters modifiers not allowed on methods\n\ntrait T1 {\n//  public function f(private int $p1): void {}\n}\n\n// ---------------------------------------------------------\n\n// *** private is accepted in a method in a class; that doesn't sound right\n// However, hhvm gags with Fatal error: Parameters modifiers not allowed on methods\n\nclass C1 {\n//  public function f(private int $p1): void {}\n}\n\n// ---------------------------------------------------------\n\n// OK; auto generates 3 properties, $p2, $p4, and $p6, with the given type and visibility\n\nclass C2 {\n  private int $pr1;\n  protected int $pr3;\n  public int $pr5;\n\n  public function __construct(int $p1, private int $p2, int $p3, protected float $p4, int $p5,\n    public string $p6 = \"xxx\") {\n    $this->pr1 = $p1;\n    $this->pr3 = $p3;\n    $this->pr5 = $p5;\n  }\n}\n\n// ---------------------------------------------------------\n\n// If have explicit property name same as implicit one, get \"Name already bound: px\"; good\nclass C3 {\n//  private ?int $p1;\n//  private ?int $p2;\n//  private ?int $p3;\n\n  public function __construct(private int $p1, protected float $p2, public string $p3) {\n  }\n}\n\nfunction main(): void {\n//  $d1 = new D1(10);\n//  $d2 = new D2(10, 20);\n//  $d3 = new D3(10, 20, 30);\n  $d4 = new D4();\n\n  $c2 = new C2(10, 20, 30, 40.0, 50);\n  var_dump($c2);\n//  echo $c2->pr1 . \"\\n\";\t// can't access private member; good\n//  echo $c2->p2 . \"\\n\";\t// can't access private member; good\n//  echo $c2->pr3 . \"\\n\";\t// can't access protected member; good\n//  echo $c2->p4 . \"\\n\";\t// can't access protected member; good\n  echo $c2->pr5 . \"\\n\";\t// can access public member; good\n  echo $c2->p6 . \"\\n\";\t// can access public member; good\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/constructors.php.expect",
    "content": "In D1 constructor, 1\nIn D2 constructor, 1, 2\nIn D3 constructor, 1, 2, 3\nIn D4 constructor\nobject(NS_constructors\\C2)#2 (6) {\n  [\"pr1\":\"NS_constructors\\C2\":private]=>\n  int(10)\n  [\"pr3\":protected]=>\n  int(30)\n  [\"pr5\"]=>\n  int(50)\n  [\"p2\":\"NS_constructors\\C2\":private]=>\n  int(20)\n  [\"p4\":protected]=>\n  float(40)\n  [\"p6\"]=>\n  string(3) \"xxx\"\n}\n50\nxxx"
  },
  {
    "path": "tests/Classes/destructors.php",
    "content": "<?hh // strict\n\nnamespace NS_destructors;\n\nclass D1 {\n  private function __destruct() {\n    echo \"In D1 destructor\\n\";\n  }\n}\n\nclass D2 extends D1 {\n  public function __destruct() {\n    echo \"In D2 destructor\\n\";\n//  parent::__destruct();\t\t// can't access private destructor\n  }\n}\n\nclass D3 extends D2 {\n  public function __destruct() {\n    echo \"In D3 destructor\\n\";\n    parent::__destruct();\n  }\n}\n\nclass D4 extends D3 {\n  public function __destruct() {\n    echo \"In D4 destructor\\n\";\n    parent::__destruct();\n  }\n}\n\nfunction main(): void {\n//  $d1 = new D1();\n//  $d2 = new D2();\n//  $d3 = new D3();\n  $d4 = new D4();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/destructors.php.expect",
    "content": "In D4 destructor\nIn D3 destructor\nIn D2 destructor"
  },
  {
    "path": "tests/Classes/dynamic_methods.php",
    "content": "<?hh // strict\n\nnamespace NS_dynamic_methods;\n\nclass Widget {\n  public function __call(string $name, array<mixed> $arguments): int {\n    echo \"Calling instance method >$name<\\n\";\n    var_dump($arguments);\n\n    return 987;\n  }\n\n  public static function __callStatic(string $name, array<mixed> $arguments): string {\n    echo \"Calling static method >$name<\\n\";\n    var_dump($arguments);\n\n    return \"hello\";\n  }\n}\n\nfunction main(): void {\n  $obj = new Widget();\n\n  $obj->iMethod(10, true, \"abc\");\n//  $obj->__call('iMethod', array(10, true, \"abc\"));\n//  $obj->__call('123#$%', []);\n\n  Widget::sMethod(null, 1.234);\n  Widget::__callStatic('sMethod', array(null, 1.234));\n  Widget::__callStatic('[]{}', []);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/dynamic_methods.php.expect",
    "content": "Calling instance method >iMethod<\narray(3) {\n  [0]=>\n  int(10)\n  [1]=>\n  bool(true)\n  [2]=>\n  string(3) \"abc\"\n}\nCalling static method >sMethod<\narray(2) {\n  [0]=>\n  NULL\n  [1]=>\n  float(1.234)\n}\nCalling static method >sMethod<\narray(2) {\n  [0]=>\n  NULL\n  [1]=>\n  float(1.234)\n}\nCalling static method >[]{}<\narray(0) {\n}"
  },
  {
    "path": "tests/Classes/invoke.php",
    "content": "<?hh // strict\n\nnamespace NS_invoke;\n\nclass C {\n  public function __invoke(): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n}\n\nfunction main(): void {\n  $c = new C();\n  var_dump(is_callable($c)); // returns true if __invoke exists; otherwise, false\n//  $c();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/invoke.php.expect",
    "content": "bool(true)"
  },
  {
    "path": "tests/Classes/property_initializer.php",
    "content": "<?hh // strict\n\nnamespace NS_property_initializer;\n\nclass Point {\n  public float $x = -10.0;\t// gets applied before constructor runs\n  public float $y = 10.0;\t\t// gets applied before constructor runs\n\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    $this->x = $x;\n    $this->y = $y;\n  }\n\n  public function __toString(): string {\n    return '(' . $this->x . ',' . $this->y . ')';\n  }\t\n}\n\nfunction main(): void {\n  $p = new Point();\n  echo $p . \"\\n\";\n\n  $p = new Point(100.0);\n  echo $p . \"\\n\";\n\n  $p = new Point(1000.0, 2000.0);\n  echo $p . \"\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/property_initializer.php.expect",
    "content": "(0,0)\n(100,0)\n(1000,2000)"
  },
  {
    "path": "tests/Classes/require_extends_implements.php",
    "content": "<?hh // strict\n\nnamespace NS_require_extends_implements;\n\nclass B {\n}\n\nclass C extends B {\n}\n\n/* While multiple class types can be require extends, given the single-\ninheritance model, all such class types have to be related via inheritance\nfor the implementing class tobe able to extend them all. */\n\ninterface I {\n  const int COUNT1 = 100;\n  require extends B;\n  const int COUNT2 = 1000;\n  require extends C;\n  const int COUNT3 = 10000;\n}\n\n// As D extends C, which in turn extends B, D satisfies I's requirement\n\nclass D extends C implements I {\n}\n\ninterface J {\n}\n\ninterface K {\n}\n\ntrait T {\n  const int COUNT1 = 1;\n  require extends B;\n  const int COUNT2 = 10;\n  require implements J;\n  const int COUNT3 = 100;\n  require extends C;\n  const int COUNT4 = 1000;\n  require implements K;\n  const int COUNT5 = 10000;\n}\n\n// As E extends C, which in turn extends B, E satisfies T's requirement\n// re base classes\n\nclass E extends C implements J, K {\n  use T;\n}\n\nfunction main (): void\n{\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/require_extends_implements.php.expectf",
    "content": "\nFatal error: Traits cannot have constants in %s/tests/Classes/require_extends_implements.php on line 35"
  },
  {
    "path": "tests/Classes/sleep_and_wakeup.php",
    "content": "<?hh // strict\n\nnamespace NS_sleep_and_wakeup;\n\nclass Point {\n  private static int $pointCount = 0;\n  private static int $nextId = 1;\n\n  private float $x;\n  private float $y;\n  private int $id;\n\n  public static function getPointCount(): int {\n    return self::$pointCount;\n  }\n\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    $this->x = $x;\n    $this->y = $y;\n    ++self::$pointCount;\n    $this->id = self::$nextId++;\n\n    echo \"\\nInside \" . __METHOD__ . \", $this, point count = \" . self::$pointCount . \"\\n\\n\";\n  }\n\n  public function move(float $x, float $y): void {\n    $this->x = $x;\n    $this->y = $y;\n  }\t\n\n  public function translate(float $x, float $y): void {\n    $this->x += $x;\n    $this->y += $y;\n  }\n\n  public function __destruct() {\n    --self::$pointCount;\n\n    echo \"\\nInside \" . __METHOD__ . \", $this, point count = \" . self::$pointCount . \"\\n\\n\";\n  }\n\n  public function __toString(): string {\n    return 'ID:' . $this->id . '(' . $this->x . ',' . $this->y . ')';\n  }\t\n\n  public function __sleep(): array<string> {\n    echo \"\\nInside \" . __METHOD__ . \", $this, point count = \" . self::$pointCount . \"\\n\\n\";\n\t\t\n    return array('y', 'x');\t// get serialized in array insertion order\n  }\n\n  public function __wakeup(): void {\n    echo \"\\nInside \" . __METHOD__ . \", $this, \\$nextId, = \" . self::$nextId . \"\\n\\n\";\n\t\t\n    ++self::$pointCount;\n    $this->id = self::$nextId++;\n  }\n}\n\nclass ColoredPoint extends Point {\n  const int RED = 1;\n  const int BLUE = 2;\n\n  private int $color;\n\n  public function __construct(float $x = 0.0, float $y = 0.0, int $color = ColoredPoint::RED) {\n    parent::__construct($x, $y);\n    $this->color = $color;\n\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n  }\n\n  public function __toString(): string {\n    return parent::__toString() . $this->color;\n  }\t\n\n// while this method returns an array containing the names of the two inherited, private \n// properties and adds to that the one private property from the current class,\n// serialize runs in the context of the type of the object given it. If that type is\n// ColoredPoint, serialize doesn't know what to do when it comes across the names of the \n// inherited, private properties.\n\n  public function __sleep(): array<string> {\n    echo \"\\nInside \" . __METHOD__ . \", $this\\n\\n\";\n\t\t\n    $a = parent::__sleep();\n    var_dump($a);\n    $a[] = 'color';\n    var_dump($a);\n    return $a;\n  }\n}\n\nfunction main(): void {\n  echo \"---------------- create and destroy a Point to boost id -------------------\\n\";\n\n  $a = new Point(1.0, 1.0);\n\n  echo \"---------------- create, serialize, and unserialize a Point -------------------\\n\";\n\n  $p = new Point(-1.0, 0.0);\n  echo \"Point \\$p = $p\\n\";\n\n  $s = serialize($p);\t\t// all instance properties get serialized\n  var_dump($s);\n\n  echo \"------\\n\";\n\n  $v = unserialize($s);\t// without a __wakeup method, any instance property present \n\t\t\t\t\t\t// in the string takes on its default value.\n  var_dump($v);\n\n  echo \"---------------- Serialize and unserialize null -------------------\\n\";\n\n  $s = serialize(null);\t// simulate __sleep not having a return statement or returning nothing\n  var_dump($s);\n\n  $v = unserialize($s);\n  var_dump($v);\n\n  echo \"---------------- Serialize ColoredPoint -------------------\\n\";\n\n  $cp = new ColoredPoint(9.0, 8.0, ColoredPoint::BLUE);\n  echo \"ColoredPoint \\$cp = $cp\\n\";\n\n  $s = serialize($cp);\n  var_dump($s);\n\n  $v = unserialize($s);\n  var_dump($v);\n\n  echo \"---------------- end -------------------\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/test_for_new_types.php",
    "content": "<?hh // strict\n\nnamespace NS_test_for_new_types;\n\nfunction main(): void {\n//  new \\ArithmeticError();\n//  new \\AssertionError();\n  new \\Closure();\n//  new \\DivisionByZeroError();\n//  new \\Error();\n  new \\Generator();\n//  new \\ParseError();\n//  new \\TypeError();\n//  new \\Throwable();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain($2);"
  },
  {
    "path": "tests/Classes/test_for_new_types.php.expectf",
    "content": "\nFatal error: syntax error, unexpected T_LNUMBER, expecting T_VARIABLE or T_PIPE_VAR or '$' in %s/tests/Classes/test_for_new_types.php on line 18"
  },
  {
    "path": "tests/Classes/type_constants.php",
    "content": "<?hh // strict\n\nnamespace NS_type_constants;\n\n// ---------------------------------------------------------------------\n\n// A \"getting-acquainted\" example\n\nabstract class User {\n  abstract const type T as arraykey;\n  public function __construct(private this::T $id) {}\n  public function getID(): this::T {\n    return $this->id;\n  }\n}\n\ntrait UserTrait {\n  require extends User;\n}\n\ninterface IUser {\n  require extends User;\n}\n\nclass AppUser extends User implements IUser {\n  const type T = int;\n  use UserTrait;\n}\n\nclass WebUser extends User implements IUser {\n  const type T = string;\n  use UserTrait;\n}\n\nclass OtherUser extends User implements IUser {\n  const type T = arraykey;\n  use UserTrait;\n}\n\n/*\nfunction main(): void {\n  $au = new AppUser(-1);\n  var_dump($au->getID());\n  $wu = new WebUser('-1');\n  var_dump($wu->getID());\n  $ou1 = new OtherUser(-1);\n  var_dump($ou1->getID());\n  $ou2 = new OtherUser('-1');\n  var_dump($ou2->getID());\n}\n\nmain();\n*/\n\n// ---------------------------------------------------------------------\n\n// type constants are implicitly public, but can't be explicitly declared as such\n\nabstract class Ctc1 {\n  abstract const type T;\n//  abstract public const type T;\n//  private abstract const type T;\n//  protected abstract const type T;\n}\n\n// use public name Ctc1::T\n\nfunction ftc1(Ctc1::T $p): Ctc1::T { return $p; }\n\n// ---------------------------------------------------------------------\n\n// Can have multiple type constants in a class, they can be interspersed with other members, and\n// can have forward references to them (see T3 in __construct below).\n\nabstract class Ctc2 {\n  abstract const type T1;\n  public function __construct(private this::T3 $id) {}\n  abstract const type T2;\n  public function getID(): this::T3 {\n    return $this->id;\n  }\n  abstract const type T3;\n}\n\n// ---------------------------------------------------------------------\n\n// Check the permitted orderings of the keywords\n\nabstract class Ctc3a {\n  abstract const type T1;\t// OK\n//  abstract type const T2;\t// ill-formed\n//  const abstract type T3;\t// ill-formed\n//  type abstract const T4;\t// ill-formed\n//  const type abstract T5;\t// ill-formed\n//  type const abstract T6;\t// ill-formed\n}\n\nclass Ctc3b {\n  const type T1 = int;\t\t\t// OK\n  const type T2 as arraykey = int;\t// OK\n//  type const T3 = int;\t\t// ill-formed\n//  type const T4 as arraykey = int;\t// ill-formed\n}\n\n// ---------------------------------------------------------------------\n\n// an abstract class\n\nabstract class Ctc4 {\n  abstract const type T1;\t\t\t// constraint omitted; OK\n  abstract const type T2 as arraykey;\t\t// constraint present; OK\n//  abstract const type T3 = int;\t\t// Declared as abstract, so cannot have a concrete type\n//  abstract const type T4 as arraykey = int;\t// Declared as abstract, so cannot have a concrete type\n\n//  const type T5;\t\t\t\t// Not declared as abstract, so must have a concrete type\n//  const type T6 as arraykey;\t\t\t// Not declared as abstract, so must have a concrete type\n  const type T7 = int;\t\t\t\t// Not declared as abstract, has a concrete type; OK\n  const type T8 as arraykey = int;\t\t// Not declared as abstract, has a concrete type; OK\n\n//  abstract const type T9, T10 as arraykey;\t// A list is not permitted\n}\n\n// ---------------------------------------------------------------------\n\n// a concrete class\n\nclass Ctc5 {\n//  abstract const type T1;\t\t\t// Can't have abstract type constant in a concrete class\n//  abstract const type T2 as arraykey;\t\t// Can't have abstract type constant in a concrete class\n//  abstract const type T3 = int;\t\t// Can't have abstract type constant in a concrete class\n//  abstract const type T4 as arraykey = int;\t// Can't have abstract type constant in a concrete class\n\n//  const type T5;\t\t\t\t// Not declared as abstract, so must have a concrete type\n//  const type T6 as arraykey;\t\t\t// Not declared as abstract, so must have a concrete type\n  const type T7 = int;\t\t\t\t// Not declared as abstract, has a concrete type; OK\n  const type T8 as arraykey = int;\t\t// Not declared as abstract, has a concrete type; OK\n}\n\n// ---------------------------------------------------------------------\n\n// interfaces\n\n// can have multiple type constants, in any order, just like classes\n// but can't have a constraint on a concrete type constant\n\ninterface Itc1a {\n  abstract const type T1 as arraykey;\n  public function getID1(): this::T1;\n  const type T4a = int;\n//  const type T4b as arraykey = int; // Disallowed: An interface cannot contain a partially abstract type constant\n}\n\ninterface Itc1b {\n  abstract const type T2;\n  public function getID2(this::T2 $p): void;\n  abstract const type T3;\n  const type T4c = string;\n}\n\n// an interface can refer to a type constant from one of its base interfaces\n\ninterface Itc1c extends Itc1b {\n  public function f(this::T2 $p): void;\n}\n\n// can implement multiple interfaces getting abstract and/or concrete type constants from each\n\nclass Ctc6 implements Itc1a, Itc1b {\n  const type T1 = int;\n  public function __construct(private this::T1 $id) {}\n  public function getID1(): this::T1 {\n    return $this->id;\n  }\n\n  const type T2 = string;\n  public function getID2(this::T2 $p): void {}\n\n  const type T3 = float;\n\n  public function f(this::T4a $p1, this::T4c $p2): void {}\n}\n\n// ---------------------------------------------------------------------\n\n// traits; type constants are not permitted!\n\ntrait Ttc1 {\n//  abstract const type T1;\t\t\t// Cannot declare a constant in a trait\n//  const type T2 = int;\t\t\t// Cannot declare a constant in a trait\n}\n\n// ---------------------------------------------------------------------\n\n// redeclaring a type constant\n\nabstract class Ctc7a {\n  abstract const type T1;\n//  abstract const type T1;\t\t\t// cannot redeclare in same class\n  const type T7 = int;\n//  const type T7 = int;\t\t\t// cannot redeclare in same class\n}\n\nabstract class Ctc7b extends Ctc7a {\n  abstract const type T1;\t\t\t// redeclared exactly as was; OK\n  const type T7 = int;\t\t\t\t// redeclared exactly as was; OK\n  const type T8 = num;\n}\n\nclass Ctc7c extends Ctc7b {\n  const type T1 = float;\t\t\t// finally gets a concrete type; OK\n//  const type T7 = num;\t\t\t// num is inconsistent with int; error\n//  const type T8 = int;\t\t\t// int is inconsistent with num; error\n}\n\ninterface Itc2a {\n  abstract const type T1;\n//  abstract const type T1;\t\t\t// cannot redeclare in same interface\n//***  const type T7 = int;\n//  const type T7 = int;\t\t\t// cannot redeclare in same interface\n}\n\ninterface Itc2b extends Itc2a {\n  abstract const type T1;\t\t\t// redeclared exactly as was; OK\n//****  const type T7 = int;\t\t\t\t// redeclared exactly as was; OK\n  const type T8 = num;\n}\n\ninterface Itc2c extends Itc2b {\n  const type T1 = float;\t\t\t// finally gets a concrete type; OK\n//  const type T7 = num;\t\t\t// num is inconsistent with int; error\n//  const type T8 = int;\t\t\t// int is inconsistent with num; error\n}\n\nclass Ctc7d extends Ctc7c implements Itc2a {\n  const type T7 = int;\t\t\t\t// redeclared exactly as was; OK\n}\n\n// ---------------------------------------------------------------------\n\n// multiple aliases for the same type constant\n\ninterface Itc8 {\n  const type T = int;\n}\n\nclass Ctc8a implements Itc8 {}\nclass Ctc8b extends Ctc8a {}\n\nfunction ftc8a(Itc8::T $p): void {}\nfunction ftc8b(Ctc8a::T $p): void {}\nfunction ftc8c(Ctc8b::T $p): void {}\n\nfunction ftcx(Itc8::T $p1, Ctc8a::T $p2, Ctc8b::T $p3): void {\n  ftc8a($p1); ftc8a($p2); ftc8a($p3);\n  ftc8b($p1); ftc8b($p2); ftc8b($p3);\n  ftc8c($p1); ftc8c($p2); ftc8c($p3);\n}\n\n//ftcx(5, 10, 15);\n\n// ---------------------------------------------------------------------\n\n// Issue #105\n\ninterface Ix {\n  const type T7 = int;\n}\n\ninterface Iy extends Ix {\n//  const type T7 = int;\t// HHVM error: Cannot override previously defined type constant Ix::T7\n}\n\nclass Cw {\n  const type T7 = int;\n}\n\nclass Cx extends Cw {\n  const type T7 = int;\n}\n\n/*\n// HHVM Error: cannot inherit the type constant T7 from Ix,\n// because it was previously inherited from Cx\n\nclass Cy extends Cx implements Ix {\n}\n*/\n\ninterface I1 {\n  abstract const type T1;\n}\n\ninterface I2 extends I1 {\n  abstract const type T1;\n}\n\nabstract class AC1 {\n  abstract const type T1;\n}\n\nabstract class AC2 extends AC1 implements I1, I2 {\n  abstract const type T1;\n}\n\n// ---------------------------------------------------------------------\n\n// use :: in type contexts rather than in expression contexts\n\ninterface Itc9a {\n  abstract const type T0;\n}\n\ninterface Itc9b extends Itc9a {\n  abstract const type T1;\n}\n\nabstract class Ctc9 implements Itc9b {\n  const type T2 = int;\n  abstract public function ftc9(\n\tItc9b::T1 $p1,\n\tthis::T2 $p2): void;\n  public static Ctc9::T2 $count = 0;\n}\n\nfunction f9a(array<Ctc9::T2, bool> $p): void {}\n\nfunction f9b(array<Ctc9::T1> $p1, array<Itc9b::T0> $p2): void {}\n\n\n// can chain (with multiple ::) and use \"keywords\" in identifier contexts\n\ninterface I10 {\n  const type this = int;\t// this is an identifier, NOT a keyword\n}\n\nclass C10 {\n  const type self = I10;\t// self is an identifier, NOT a keyword\n}\n\nfunction test10(C10::self::this $x): void {}\n\n\n// ---------------------------------------------------------------------\n\n// Example of using this::T\n\nabstract class CBase {\n  abstract const type T;\n  public function __construct(protected this::T $value) {}\n}\n\nclass Cstring extends CBase {\n  const type T = string;\n  public function getString(): string {\n    return $this->value;\t// gets the string\n  }\n}\n\nclass Cint extends CBase {\n  const type T = int;\n  public function getInt(): int {\n    return $this->value;\t// gets the int\n  }\n}\n\nfunction main(): void {\n  var_dump((new Cstring('abc'))->getString());\n  var_dump((new Cint(123))->getInt());\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/type_constants.php.expect",
    "content": "string(3) \"abc\"\nint(123)"
  },
  {
    "path": "tests/Classes/visibility.php",
    "content": "<?hh // strict\n\nnamespace NS_visibility;\n\nclass C {\n// constants\n\n  const int CON1 = 123;\t\t// implicitly static, and can't say so explicitly\n//  public const int CON2 = 123;\t// class constants are implicitly public; can't say explicitly\n//  protected const int CON3 = 123;\t// class constants are implicitly public\n//  private const int CON4 = 123;\t// class constants are implicitly public\n\n// properties\n\n//  $prop1a;\t\t\t// rejected; must have a modifier of some sort\n//  $prop1b = 123;\t\t\t// rejected; must have a modifier of some sort\n  public int $prop2 = 0;\n  protected int $prop3 = 0;\n  private int $prop4 = 0;\n\n//  public var $vprop1a;\t\t// var not supported, with or without an explicit type\n//  var $vprop1b = 123;\t\t// \n//  public var $vprop2;\t\t// can't combine var with visibility modifiers\n//  var public  $vprop2;\n//  protected var $vprop3;\n//  var protected  $vprop3;\n//  var private $vprop4;\n\n  static int $sprop1 = 0;\n  public static int $sprop2 = 0;\n  static protected int $sprop3 = 0;\t// visibility and static ordering unimportant\n  private static int $sprop4 = 0;\n\n//  static var $vsprop1;\t// can't combine var with static modifier\n//  var static $vsprop1;\n//  var public static $vsprop2;\n//  protected var static $vsprop3;\n//  private static var $vsprop4;\n\n// methods\n\t\n  public function f1(): void {}\n  public function f2(): void {}\n  protected function f3(): void {}\n  private function f4(): void {}\n\n  static function sf1(): void {}\n  public static function sf2(): void {}\n  static protected function sf3(): void {}\t// visibility and static ordering unimportant\n  private static function sf4(): void {}\n\n// constructors\n\t\n  public function __construct() {}\n//  protected function __construct() {}\t\t// OK on its own\n//  private function __construct() {}\t\t// OK on its own\n\n//  static function __construct() {}\t\t\t// constructors can't be static\n//  public static function __construct() {}\n//  protected static function __construct() {}\n//  private static function __construct() {}\n\n// destructors\n\t\n  public function __destruct() {}\n//  protected function __destruct() {}\t\t// OK on its own\n//  private function __destruct() {}\t\t// OK on its own\n\n//  static function __destruct() {}\t\t\t// destructors can't be static\n//  public static function __destruct() {}\n//  protected static function __destruct() {}\n//  private static function __destruct() {}\n}\n\nabstract class D1 {\n  public abstract function paf1(int $p1): void;\n  abstract protected  function paf2(): void;\n//  private abstract function paf3(): void;\t\t// can't ever provide an implementation\n  public static abstract  function pasf1(): void;\n  protected abstract static function pasf2(int $p1): void;\n}\n\nclass D2 extends D1 {\n//  public function paf1(): void {}\t\t\t// Declaration of D2::paf1() must be compatible with D1::paf1($p1)\n  public function paf1(int $q1): void {}\t\t// OK; has same visibility as abstract decl, and same signature\n//  public function paf1(int $q1, int $q2): void {}\t// Declaration of D2::paf1() must be compatible with D1::paf1($p1)\n//  protected function paf1(int $q1): void {}\t\t// Access level to D2::paf1() must be public\n//  private function paf1(int $q1): void {}\t\t// Access level to D2::paf1() must be public\n\n//  public function paf2(): void {}\t\t\t// OK; has wider visibility than abstract decl\n  protected function paf2(): void {}\t\t// OK; has same visibility as abstract decl\n//  private function paf2(): void {}\t\t\t// Access level to D2::paf2() must be protected\n\n  public static function pasf1(): void {}\t// OK; has same visibility as abstract decl\n//  protected static function pasf1(): void {}// Access level to D2::pasf1() must be public\n//  private static function pasf1(): void {}\t// Access level to D2::pasf1() must be public\n\n//  static public function pasf2(int $q1): void {}\t// OK; has wider visibility than abstract decl\n//  static protected function pasf2(): void {}\t// Declaration of D2::pasf2() must be compatible with D1::pasf2($p1)\n  static protected function pasf2(int $q1): void {}\t// OK; has same visibility as abstract decl, and same signature\n//  static protected function pasf2(int $q1, int $q2): void {}\t// Declaration of D2::pasf2() must be compatible with D1::pasf2($p1)\n//  static private function pasf2(int $q1): void {}\t// Access level to D2::pasf2() must be protected\n}\n\nfunction main(): void {\n  echo \"CON1: \" . C::CON1 . \"\\n\";\t// use :: notation, as a const is implicitly static\n\n  $c = new C();\t// calls public constructor\n  var_dump($c->prop2);\t// accesses public instance method\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Classes/visibility.php.expect",
    "content": "CON1: 123\nint(0)"
  },
  {
    "path": "tests/Collections/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Collections/collections_intrinsics_list.php",
    "content": "<?hh // strict\n\nnamespace NS_intrinsics;\n\nfunction main(): void {\n  echo \"--------- test with full and omitted LHS vars -------------\\n\";\n\n  $v = list($min, $max, $avg) = Vector {0, 100, 67};\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n\n//  list($min, , $avg) = array(0, 100, 67);\t\t// missing arguments not allowed\n//  list($min, , $avg) = Vector {0, 100, 67};\t// missing arguments not allowed\n//  echo \"\\$min: $min, , \\$avg: $avg\\n\";\n\n  list($min, $max, ) = Vector {0, 100, 67};\n  echo \"\\$min: $min, \\$max: $max,\\n\";\n\n  list($min, $max) = Vector {0, 100, 67};\n  echo \"\\$min: $min, \\$max: $max\\n\";\n\n  list($min) = Vector {0, 100, 67};\n  echo \"\\$min: $min\\n\";\n\n  $v = list($first, $second) = Pair {-5, 7};\n  echo \"\\$first: $first, \\$second: $second\\n\";\n  print_r($v);\n\n//  $v = list($first) = Pair {-15, 17};\t\t// must extract both elements\n\n  echo \"--------- test with more elements than variables -------------\\n\";\n\n  $v = list($min, $max, $avg) = Vector {0, 100, 67, 22, 33};\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n\n//  $v = list($first, $second, $third) = Pair {-5, 7}; // must extract both elements only\n\n//  echo \"--------- test with fewer elements than variables -------------\\n\";\n//\n//  $v = list($min, $max, $avg) = Vector {100, 500};\t// Undefined offset: 2\n\n  echo \"--------- test with element being an array -------------\\n\";\n\n  $v = list($min, $max, $avg) = Vector {0, Vector {1, 7}, Vector {3, 6}};\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n\n  $v = list($first, $second) = Pair {Vector {1, 7}, Vector {3, 6}};\n  echo \"\\$first: $first, \\$second: $second\\n\";\n  print_r($v);\n\n  echo \"--------- test with target vars being array elements -------------\\n\";\n\n  $a = array();\t\t// Hack needs $a to exist, whereas PHP doesn't\n  $v = list($a[0], $a[2], $a[4]) = Vector {0, 100, 67};\n  print_r($a);\n  print_r($v);\n\n  $a = array();\n  // UNSAFE (type check error - diff D3113087 out to fix)\n  $v = list($a[0], $a[2]) = Pair {12, 24};\n  print_r($a);\n  print_r($v);\n\n  echo \"--------- test with no variables -------------\\n\";\n\n  $v = list() = Vector {0, 100, 67};\n  print_r($v);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Collections/collections_intrinsics_list.php.expect",
    "content": "--------- test with full and omitted LHS vars -------------\n$min: 0, $max: 100, $avg: 67\nHH\\Vector Object\n(\n    [0] => 0\n    [1] => 100\n    [2] => 67\n)\n$min: 0, $max: 100,\n$min: 0, $max: 100\n$min: 0\n$first: -5, $second: 7\nHH\\Pair Object\n(\n    [0] => -5\n    [1] => 7\n)\n--------- test with more elements than variables -------------\n$min: 0, $max: 100, $avg: 67\nHH\\Vector Object\n(\n    [0] => 0\n    [1] => 100\n    [2] => 67\n    [3] => 22\n    [4] => 33\n)\n--------- test with element being an array -------------\n$min: 0, $max: Vector, $avg: Vector\nHH\\Vector Object\n(\n    [0] => 0\n    [1] => HH\\Vector Object\n        (\n            [0] => 1\n            [1] => 7\n        )\n\n    [2] => HH\\Vector Object\n        (\n            [0] => 3\n            [1] => 6\n        )\n\n)\n$first: Vector, $second: Vector\nHH\\Pair Object\n(\n    [0] => HH\\Vector Object\n        (\n            [0] => 1\n            [1] => 7\n        )\n\n    [1] => HH\\Vector Object\n        (\n            [0] => 3\n            [1] => 6\n        )\n\n)\n--------- test with target vars being array elements -------------\nArray\n(\n    [4] => 67\n    [2] => 100\n    [0] => 0\n)\nHH\\Vector Object\n(\n    [0] => 0\n    [1] => 100\n    [2] => 67\n)\nArray\n(\n    [2] => 24\n    [0] => 12\n)\nHH\\Pair Object\n(\n    [0] => 12\n    [1] => 24\n)\n--------- test with no variables -------------\nHH\\Vector Object\n(\n    [0] => 0\n    [1] => 100\n    [2] => 67\n)"
  },
  {
    "path": "tests/Collections/collections_operations.php",
    "content": "<?hh // strict\n\nnamespace NS_collections_operations;\n\nclass C {}\n\nfunction main(int $idx): void {\n//  $str = \"Hello\";\n//  eval(\"echo \\$str . \\\"\\\\n\\\";\");\t\t\t// intrinsic eval not recognized\n\n//  exit (\"bye bye!\\n\");\n//  die (\"bye bye!\\n\");\t\t\t\t// intrinsic die not recognized\n\n  echo \"========================== Vector =======================\\n\";\n\n//  $v1 = Vector {5, $idx, $idx * 3};\n//  $v1 = Vector {0 = 5, 1 = $idx, 2 = $idx * 3};\t// no explicit keys allowed\n  $v1 = (Vector {})->addAll(array(5, 10, 15));\t// grouping parens needed\n  $v1[] = 20;\n  $v1[0] = -5;\n\n//  $v1[] += 17;\t// throws InvalidOperationException;\n\t\t\t// Cannot use [] with collections for reading in an lvalue context\n//  $v1[]++;\t// ditto\n//  ++$v1[];\t// ditto\n//  $v1[]--;\t// ditto\n//  --$v1[];\t// ditto\n\n  echo \"\\$v1[1] = \" . $v1[1] . \"\\n\";\n//  echo \"\\$v1[100] = \" . $v1[100] . \"\\n\";\t\t// throws OutOfBoundsException\n  var_dump($v1);\n\n//  var_dump(Vector {2, 4, 6}[1]);\t\t\t// unexpected '[', expecting ')'\n  var_dump((Vector {2, 4, 6})[1]);\t\t// grouping parens needed\n\n  echo \"Vector \\$v1 = >$v1<\\n\";\n//  $res = print \"Vector \\$v1 = >$v1<\\n\";\t\t// intrinsic print not recognized\n\n//  echo \"empty(Vector {}) = >\" . empty(Vector {}) . \"<\\n\";\t// intrinsic empty not recognized\n\n//  echo \"isset(\\$v1) is \" . (isset($v1) ? \"True\" : \"False\") . \"\\n\"; // told not to use isset\n//  unset($v1);\t\t\t\t\t// intrinsic unset not recognized\n\n  $v = list($min, $max, $avg) = Vector {0, 100, 67};\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n\n  $v1 = Vector {Vector {true, false}, Pair {10, 20}};\n  $v2 = clone $v1;\n  var_dump($v1);\n  var_dump($v2);\n\n  $v1 = Vector {5, 10};\n  $v2 = Vector {5, 10};\n  $v3 = Vector {10, 5};\n  $v4 = Vector {5, 10, 15};\n\n  echo \"Vector ==  #1: \" . ($v1 == $v1 ? 'T' : 'F') . \"\\n\";\n  echo \"Vector ==  #2: \" . ($v1 == $v2 ? 'T' : 'F') . \"\\n\";\n  echo \"Vector ==  #3: \" . ($v1 == $v3 ? 'T' : 'F') . \"\\n\";\n  echo \"Vector ==  #4: \" . ($v1 == $v4 ? 'T' : 'F') . \"\\n\";\n\n  echo \"Vector === #1: \" . ($v1 === $v1 ? 'T' : 'F') . \"\\n\";\n  echo \"Vector === #2: \" . ($v1 === $v2 ? 'T' : 'F') . \"\\n\";\n  echo \"Vector === #3: \" . ($v1 === $v3 ? 'T' : 'F') . \"\\n\";\n  echo \"Vector === #4: \" . ($v1 === $v4 ? 'T' : 'F') . \"\\n\";\n\n  echo \"========================== Conversions from Vector =======================\\n\";\n\n  $v1 = Vector {};\n  $v2 = Vector {5.2, 10.1, 15.3};\n\n  $b1 = (bool)$v1;\n  $b2 = (bool)$v2;\n  var_dump($b1, $b2);\n\n//  $i1 = (int)$v1;\t\t// conversion not permitted\n//  $i2 = (int)$v2;\t\t// conversion not permitted\n//  var_dump($i1, $i2);\n\n//  $f1 = (float)$v1;\t// conversion not permitted\n//  $f2 = (float)$v2;\t// conversion not permitted\n//  var_dump($f1, $f2);\n\n  $s1 = (string)$v1;\t// uses __tostring\n  $s2 = (string)$v2;\t// uses __tostring\n  var_dump($s1, $s2);\n\n//  $a1 = (array)$v1;\t// (array) cast forbidden in strict mode; arrays with\n//\t\t\t\t// unspecified key and value types are not allowed\n//  $a2 = (array)$v2;\n//  $a1 = (array<float>)$v1;\t// can't cast to typed arrays either\n//  $a2 = (array<float>)$v2;\n\n//  $o1 = (object)$v1;\t\t// object not supported\n//  $o2 = (object)$v2;\n//  var_dump($o1, $o2);\n\n  echo \"========================== ImmVector =======================\\n\";\n\n  $iv1 = ImmVector {5, 10, 15};\n//  $iv1[] = 20;\t\t\t\t\t// mutation not allowed\n//  $iv1[0] = -5;\t\t\t\t\t// mutation not allowed\n  echo \"\\$iv1[1] = \" . $iv1[1] . \"\\n\";\n//  echo \"\\$iv1[100] = \" . $iv1[100] . \"\\n\";\t// throws OutOfBoundsException\n  var_dump($iv1);\n\n  $v = list($min, $max, $avg) = ImmVector {0, 100, 67};\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  var_dump($v);\n\n  $iv1 = ImmVector{5, 10};\n  $iv2 = ImmVector{5, 10};\n  $iv3 = ImmVector{10, 5};\n  $iv4 = ImmVector{5, 10, 15};\n\n  echo \"ImmVector ==  #1: \" . ($iv1 == $iv1 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmVector ==  #2: \" . ($iv1 == $iv2 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmVector ==  #3: \" . ($iv1 == $iv3 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmVector ==  #4: \" . ($iv1 == $iv4 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmVector == Vector: \" . (ImmVector {5, 10} == Vector {5, 10} ? 'T' : 'F') . \"\\n\";\n\n  echo \"ImmVector === #1: \" . ($iv1 === $iv1 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmVector === #2: \" . ($iv1 === $iv2 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmVector === #3: \" . ($iv1 === $iv3 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmVector === #4: \" . ($iv1 === $iv4 ? 'T' : 'F') . \"\\n\";\n\n  echo \"========================== Conversions from ImmVector =======================\\n\";\n\n  $iv1 = ImmVector {};\n  $iv2 = ImmVector {5.2, 10.1, 15.3};\n\n  $b1 = (bool)$iv1;\n  $b2 = (bool)$iv2;\n  var_dump($b1, $b2);\n\n  $s1 = (string)$iv1;\t// uses __tostring\n  $s2 = (string)$iv2;\t// uses __tostring\n  var_dump($s1, $s2);\n\n  echo \"========================== Map =======================\\n\";\n\n  $m1 = Map {'red' => -1, 'green' => -4, 'red' => 5, 'green' => 12};\n  var_dump($m1);\n  $m1['blue'] = 35;\t\t\t\t// add an element with a new key\n  $m1['red'] = 6;\t\t\t\t\t// change the value of an existing element\n//  $m1[] = 20;\t\t\t\t\t// can only append a value of type Pair\n  $m1[] = Pair {'black', 43};\t\t\t// append value 43 with key 'black'\n  $m1[] = Pair {'red', 123};\t\t\t// replaces existing element's value with 123\n//  $m1[true] = 99;\t\t\t\t\t// throws InvalidArgumentException\n  echo \"\\$m1['red'] = \" . $m1['red'] . \"\\n\";\n//  echo \"\\$m1['white'] = \" . $m1['white'] . \"\\n\";\t// throws OutOfBoundsException\n  var_dump($m1);\n\n  echo \"Map \\$m1 = >$m1<\\n\";\n\n//  $m1 = Map {0 => 0, 1 => 100, 2 => 67};\n//  \t$v = list($min, $max, $avg) = $m1;\t\t// can't use a Map here\n\n  $m1 = Map{2 => 5.2, 'a' => 10.1};\n  $m2 = Map{2 => 5.2, 'a' => 10.1};\n  $m3 = Map{'a' => 10.1, 2 => 5.2};\n  $m4 = Map{2 => 5.2, 'a' => 10.1, 1 => 12};\n\n  echo \"Map ==  #1: \" . ($m1 == $m1 ? 'T' : 'F') . \"\\n\";\n  echo \"Map ==  #2: \" . ($m1 == $m2 ? 'T' : 'F') . \"\\n\";\n  echo \"Map ==  #3: \" . ($m1 == $m3 ? 'T' : 'F') . \"\\n\";\n  echo \"Map ==  #4: \" . ($m1 == $m4 ? 'T' : 'F') . \"\\n\";\n\n  echo \"Map === #1: \" . ($m1 === $m1 ? 'T' : 'F') . \"\\n\";\n  echo \"Map === #2: \" . ($m1 === $m2 ? 'T' : 'F') . \"\\n\";\n  echo \"Map === #3: \" . ($m1 === $m3 ? 'T' : 'F') . \"\\n\";\n  echo \"Map === #4: \" . ($m1 === $m4 ? 'T' : 'F') . \"\\n\";\n\n  echo \"========================== Conversions from Map =======================\\n\";\n\n  $m1 = Map {};\n  $m2 = Map {2 => 5.2, 'a' => 10.1, 'x' => 15.3};\n\n  $b1 = (bool)$m1;\n  $b2 = (bool)$m2;\n  var_dump($b1, $b2);\n\n  $s1 = (string)$m1;\t// uses __tostring\n  $s2 = (string)$m2;\t// uses __tostring\n  var_dump($s1, $s2);\n\n  echo \"========================== ImmMap =======================\\n\";\n\n  $im1 = ImmMap {'red' => 5, 'green' => 12};\n//  $im1['blue'] = 35;\t\t\t\t// mutation not allowed\n//  $im1['red'] = 6;\t\t\t\t// mutation not allowed\n//  $im1[] = Pair {'black', 43};\t\t\t// mutation not allowed\n  echo \"\\$im1['red'] = \" . $im1['red'] . \"\\n\";\n//  echo \"\\$im1['white'] = \" . $im1['white'] . \"\\n\";// throws OutOfBoundsException\n  var_dump($im1);\n\n  $im1 = ImmMap{2 => 5.2, 'a' => 10.1};\n  $im2 = ImmMap{2 => 5.2, 'a' => 10.1};\n  $im3 = ImmMap{'a' => 10.1, 2 => 5.2, };\n  $im4 = ImmMap{2 => 5.2, 'a' => 10.1, 1 => 12};\n\n  echo \"ImmMap ==  #1: \" . ($im1 == $im1 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmMap ==  #2: \" . ($im1 == $im2 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmMap ==  #3: \" . ($im1 == $im3 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmMap ==  #4: \" . ($im1 == $im4 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmMap == Map: \" . (ImmMap{2 => 5.2, 'a' => 10.1} == Map{2 => 5.2, 'a' => 10.1} ? 'T' : 'F') . \"\\n\";\n\n  echo \"ImmMap === #1: \" . ($im1 === $im1 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmMap === #2: \" . ($im1 === $im2 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmMap === #3: \" . ($im1 === $im3 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmMap === #4: \" . ($im1 === $im4 ? 'T' : 'F') . \"\\n\";\n\n  echo \"========================== Conversions from ImmMap =======================\\n\";\n\n  $im1 = ImmMap {};\n  $im2 = ImmMap {2 => 5.2, 'a' => 10.1, 'x' => 15.3};\n\n  $b1 = (bool)$im1;\n  $b2 = (bool)$im2;\n  var_dump($b1, $b2);\n\n  $s1 = (string)$im1;\t// uses __tostring\n  $s2 = (string)$im2;\t// uses __tostring\n  var_dump($s1, $s2);\n\n  echo \"========================== Set =======================\\n\";\n\n  $s1 = Set {1, 1, 1, 5, 10, 1, 15, 1};\t\t// duplicates are allowed, but are ignored\n  $s1[] = 'red';\n  $s1[] = 20;\n  $s1[] = 5;\t\t\t\t\t// attempt to add a duplicate is ignored\n  $s1->add(10);\t\t\t\t\t// attempt to add a duplicate is ignored\n//  $s1[] = true;\t\t\t\t\t// throws InvalidArgumentException\n//  $s1[0] = -5;\t\t\t\t\t// [index] not permitted\n//  echo \"\\$s1[1] = \" . $s1[1] . \"\\n\";\t\t// [index] not permitted\n  var_dump($s1);\n\n  echo \"Set \\$s1 = >$s1<\\n\";\n\n//  $v = list($min, $max, $avg) = $s1;\t\t// can't use a Map here\n\n  $s1 = Set{10, 'red'};\n  $s2 = Set{10, 'red'};\n  $s3 = Set{'red', 10};\n  $s4 = Set{10, 'red', 12};\n\n  echo \"Set ==  #1: \" . ($s1 == $s1 ? 'T' : 'F') . \"\\n\";\n  echo \"Set ==  #2: \" . ($s1 == $s2 ? 'T' : 'F') . \"\\n\";\n  echo \"Set ==  #3: \" . ($s1 == $s3 ? 'T' : 'F') . \"\\n\";\n  echo \"Set ==  #4: \" . ($s1 == $s4 ? 'T' : 'F') . \"\\n\";\n\n  echo \"Set === #1: \" . ($s1 === $s1 ? 'T' : 'F') . \"\\n\";\n  echo \"Set === #2: \" . ($s1 === $s2 ? 'T' : 'F') . \"\\n\";\n  echo \"Set === #3: \" . ($s1 === $s3 ? 'T' : 'F') . \"\\n\";\n  echo \"Set === #4: \" . ($s1 === $s4 ? 'T' : 'F') . \"\\n\";\n\n  echo \"========================== Conversions from Set =======================\\n\";\n\n  $s1 = Set {};\n  $s2 = Set {10, 'red'};\n\n  $b1 = (bool)$s1;\n  $b2 = (bool)$s2;\n  var_dump($b1, $b2);\n\n  $s1 = (string)$s1;\t// uses __tostring\n  $s2 = (string)$s2;\t// uses __tostring\n  var_dump($s1, $s2);\n\n  echo \"========================== ImmSet =======================\\n\";\n\n  $is1 = ImmSet {1, 1, 1, 5, 10, 1, 'red', 1};\t// duplicates are allowed, but are ignored\n// $is1[] = 'red';\t\t\t\t\t// [index] not permitted\n//  echo \"\\$is1[1] = \" . $is1[1] . \"\\n\";\t\t// [index] not permitted\n  var_dump($is1);\n\n  $is1 = ImmSet{10, 'red'};\n  $is2 = ImmSet{10, 'red'};\n  $is3 = ImmSet{'red', 10};\n  $is4 = ImmSet{10, 'red', 12};\n\n  echo \"ImmSet ==  #1: \" . ($is1 == $is1 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmSet ==  #2: \" . ($is1 == $is2 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmSet ==  #3: \" . ($is1 == $is3 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmSet ==  #4: \" . ($is1 == $is4 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmSet == Set: \" . (ImmSet{10, 'red'} == Set{10, 'red'} ? 'T' : 'F') . \"\\n\";\n\n  echo \"ImmSet === #1: \" . ($is1 === $is1 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmSet === #2: \" . ($is1 === $is2 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmSet === #3: \" . ($is1 === $is3 ? 'T' : 'F') . \"\\n\";\n  echo \"ImmSet === #4: \" . ($is1 === $is4 ? 'T' : 'F') . \"\\n\";\n\n  echo \"========================== Conversions from ImmSet =======================\\n\";\n\n  $is1 = ImmSet {};\n  $is2 = ImmSet {10, 'red'};\n\n  $b1 = (bool)$is1;\n  $b2 = (bool)$is2;\n  var_dump($b1, $b2);\n\n  $is1 = (string)$is1;\t// uses __tostring\n  $is2 = (string)$is2;\t// uses __tostring\n  var_dump($is1, $is2);\n\n  echo \"========================== Pair =======================\\n\";\n\n//  $p1 = new Pair();\t\t\t\t// throws InvalidOperationException\n//  $p1 = Pair {0 = 55, 1 = 'abc'};\t\t\t// no explicit keys allowed\n  $p1 = Pair {55, new C()};\n\n//  $p1[0] = 14;\t\t\t\t\t// throws InvalidOperationException\n//  $p1[0]++;\t\t\t\t\t// ditto\n//  --$p1[0];\t\t\t\t\t// ditto\n//  $p1[0] *= 3;\t\t\t\t\t// ditto\n\n//  $p1[] = 20;\t\t\t\t\t// mutation not allowed\n  echo \"\\$p1[0] = \" . $p1[0] . \"\\n\";\n//  echo \"\\$p1[true] = \" . $p1[true] . \"\\n\";\t// Pair elements can only be accessed with an integer literal\n//  echo \"\\$p1[100] = \" . $p1[100] . \"\\n\";\t\t// Invalid index for this pair\n//  echo \"\\$p1[$idx] = \" . $p1[$idx] . \"\\n\";\t// Pair elements can only be accessed with an integer literal\n  var_dump($p1);\n\n  echo \"Pair \\$p1 = >$p1<\\n\";\n\n  $p2 = Pair {15, 75};\n  \n  // UNSAFE (type check error - diff D3113087 out to fix)\n  $v = list($min, $max) = $p2;\n  echo \"\\$min: $min, \\$max: $max\\n\";\n  var_dump($v);\n\n  $p1 = Pair{10, 'red'};\n  $p2 = Pair{10, 'red'};\n  $p3 = Pair{'red', 10};\n\n  echo \"Pair ==  #1: \" . ($p1 == $p1 ? 'T' : 'F') . \"\\n\";\n  echo \"Pair ==  #2: \" . ($p1 == $p2 ? 'T' : 'F') . \"\\n\";\n  echo \"Pair ==  #3: \" . ($p1 == $p3 ? 'T' : 'F') . \"\\n\";\n\n  echo \"Pair === #1: \" . ($p1 === $p1 ? 'T' : 'F') . \"\\n\";\n  echo \"Pair === #2: \" . ($p1 === $p2 ? 'T' : 'F') . \"\\n\";\n  echo \"Pair === #3: \" . ($p1 === $p3 ? 'T' : 'F') . \"\\n\";\n\n  echo \"========================== Conversions from Pair =======================\\n\";\n\n  $v2 = Pair {5.2, 'red'};\n\n  $b2 = (bool)$v2;\n  var_dump($b2);\n\n  $s2 = (string)$v2;\t// uses __tostring\n  var_dump($s2);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain(100);\n"
  },
  {
    "path": "tests/Collections/collections_operations.php.expect",
    "content": "========================== Vector =======================\n$v1[1] = 10\nobject(HH\\Vector)#1 (4) {\n  [0]=>\n  int(-5)\n  [1]=>\n  int(10)\n  [2]=>\n  int(15)\n  [3]=>\n  int(20)\n}\nint(4)\nVector $v1 = >Vector<\n$min: 0, $max: 100, $avg: 67\nHH\\Vector Object\n(\n    [0] => 0\n    [1] => 100\n    [2] => 67\n)\nobject(HH\\Vector)#5 (2) {\n  [0]=>\n  object(HH\\Vector)#3 (2) {\n    [0]=>\n    bool(true)\n    [1]=>\n    bool(false)\n  }\n  [1]=>\n  object(HH\\Pair)#4 (2) {\n    [0]=>\n    int(10)\n    [1]=>\n    int(20)\n  }\n}\nobject(HH\\Vector)#6 (2) {\n  [0]=>\n  object(HH\\Vector)#3 (2) {\n    [0]=>\n    bool(true)\n    [1]=>\n    bool(false)\n  }\n  [1]=>\n  object(HH\\Pair)#4 (2) {\n    [0]=>\n    int(10)\n    [1]=>\n    int(20)\n  }\n}\nVector ==  #1: T\nVector ==  #2: T\nVector ==  #3: F\nVector ==  #4: F\nVector === #1: T\nVector === #2: F\nVector === #3: F\nVector === #4: F\n========================== Conversions from Vector =======================\nbool(false)\nbool(true)\nstring(6) \"Vector\"\nstring(6) \"Vector\"\n========================== ImmVector =======================\n$iv1[1] = 10\nobject(HH\\ImmVector)#13 (3) {\n  [0]=>\n  int(5)\n  [1]=>\n  int(10)\n  [2]=>\n  int(15)\n}\n$min: 0, $max: 100, $avg: 67\nobject(HH\\ImmVector)#14 (3) {\n  [0]=>\n  int(0)\n  [1]=>\n  int(100)\n  [2]=>\n  int(67)\n}\nImmVector ==  #1: T\nImmVector ==  #2: T\nImmVector ==  #3: F\nImmVector ==  #4: F\nImmVector == Vector: T\nImmVector === #1: T\nImmVector === #2: F\nImmVector === #3: F\nImmVector === #4: F\n========================== Conversions from ImmVector =======================\nbool(false)\nbool(true)\nstring(9) \"ImmVector\"\nstring(9) \"ImmVector\"\n========================== Map =======================\nobject(HH\\Map)#22 (2) {\n  [\"red\"]=>\n  int(5)\n  [\"green\"]=>\n  int(12)\n}\n$m1['red'] = 123\nobject(HH\\Map)#22 (4) {\n  [\"red\"]=>\n  int(123)\n  [\"green\"]=>\n  int(12)\n  [\"blue\"]=>\n  int(35)\n  [\"black\"]=>\n  int(43)\n}\nMap $m1 = >Map<\nMap ==  #1: T\nMap ==  #2: T\nMap ==  #3: T\nMap ==  #4: F\nMap === #1: T\nMap === #2: F\nMap === #3: F\nMap === #4: F\n========================== Conversions from Map =======================\nbool(false)\nbool(true)\nstring(3) \"Map\"\nstring(3) \"Map\"\n========================== ImmMap =======================\n$im1['red'] = 5\nobject(HH\\ImmMap)#29 (2) {\n  [\"red\"]=>\n  int(5)\n  [\"green\"]=>\n  int(12)\n}\nImmMap ==  #1: T\nImmMap ==  #2: T\nImmMap ==  #3: T\nImmMap ==  #4: F\nImmMap == Map: T\nImmMap === #1: T\nImmMap === #2: F\nImmMap === #3: F\nImmMap === #4: F\n========================== Conversions from ImmMap =======================\nbool(false)\nbool(true)\nstring(6) \"ImmMap\"\nstring(6) \"ImmMap\"\n========================== Set =======================\nobject(HH\\Set)#37 (6) {\n  int(1)\n  int(5)\n  int(10)\n  int(15)\n  string(3) \"red\"\n  int(20)\n}\nSet $s1 = >Set<\nSet ==  #1: T\nSet ==  #2: T\nSet ==  #3: T\nSet ==  #4: F\nSet === #1: T\nSet === #2: F\nSet === #3: F\nSet === #4: F\n========================== Conversions from Set =======================\nbool(false)\nbool(true)\nstring(3) \"Set\"\nstring(3) \"Set\"\n========================== ImmSet =======================\nobject(HH\\ImmSet)#43 (4) {\n  int(1)\n  int(5)\n  int(10)\n  string(3) \"red\"\n}\nImmSet ==  #1: T\nImmSet ==  #2: T\nImmSet ==  #3: T\nImmSet ==  #4: F\nImmSet == Set: T\nImmSet === #1: T\nImmSet === #2: F\nImmSet === #3: F\nImmSet === #4: F\n========================== Conversions from ImmSet =======================\nbool(false)\nbool(true)\nstring(6) \"ImmSet\"\nstring(6) \"ImmSet\"\n========================== Pair =======================\n$p1[0] = 55\nobject(HH\\Pair)#50 (2) {\n  [0]=>\n  int(55)\n  [1]=>\n  object(NS_collections_operations\\C)#51 (0) {\n  }\n}\nPair $p1 = >Pair<\n$min: 15, $max: 75\nobject(HH\\Pair)#52 (2) {\n  [0]=>\n  int(15)\n  [1]=>\n  int(75)\n}\nPair ==  #1: T\nPair ==  #2: T\nPair ==  #3: F\nPair === #1: T\nPair === #2: F\nPair === #3: F\n========================== Conversions from Pair =======================\nbool(true)\nstring(4) \"Pair\""
  },
  {
    "path": "tests/Collections/vector.php",
    "content": "<?hh // strict\n\nnamespace NS_vector;\n\nclass C {\n  public array<int> $pr1;\n  public function __construct() {\n    $this->pr1 = array(22, 33, 44);\n  }\n}\n\nfunction displayVector<T>(Vector<T> $v): void {\n  var_dump($v);\n/*\n  foreach ($v as $item) {\n//    var_dump($item);\n      echo (string)$item . \"\\n\";\n  }\n*/\n}\n\nfunction main(): void {\n  $v1 = new Vector(null);\t\t// vector of zero items\n  displayVector($v1);\n  echo \"\\$v1 = \" . ($v1->isEmpty() ? \"is\" : \"is not\") . \" empty\\n\";\n\n  $v1 = new Vector(array());\t// vector of zero items\n  displayVector($v1);\n\n  $v1 = Vector {};\t\t// vector of zero items\n  echo \"\\$v1's element count = \" . $v1->count() . \"\\n\";\n  displayVector($v1);\n\n  $v1->add(12);\t\t\t// add item 0\n  $v1[] = 99;\t\t\t// add item 1\n//  $v1[2] = 2001;\t\t\t// add item 2 ==> OutOfBoundsException\n  $v1[] = 199;\t\t\t// add item 2\n  displayVector($v1);\n  echo \"\\$v1's element count = \" . $v1->count() . \"\\n\";\n  echo \"\\$v1 = \" . ($v1->isEmpty() ? \"is\" : \"is not\") . \" empty\\n\";\n\n  if ($v1->containsKey(1)) {\n    echo \"\\$v1[1] = \" . $v1->at(1) . \"\\n\";\n  }\n//  echo \"\\$v1[-1] = \" . $v1->at(-1) . \"\\n\";\t// OutOfBoundsException\n//  echo \"\\$v1[100] = \" . $v1->at(100) . \"\\n\";\t// OutOfBoundsException\n\n  $v2 = Vector::fromItems(array(2, 8));\n  displayVector($v2);\n\n  $v2 = $v1->filter(function (int $value): bool {\n    return $value > 50;\n  });\n  displayVector($v2);\n\n  $v1->clear();\n\n  $v1->addAll(null);\t\t\t// add no new items\n\n  $c1 = new C();\n  var_dump($c1);\n\n  $v1->addAll($c1->pr1);\t\t// add 3 new items\n  displayVector($v1);\n\n  $c1->pr1[-5] = 17;\n  $c1->pr1[200] = 18;\n  var_dump($c1->pr1);\n  $v1 = new Vector($c1->pr1);\n  displayVector($v1);\n  $v1->addAll($c1->pr1);\n  displayVector($v1);\n  echo \"\\$v1 contains >$v1<\\n\";\n\n  $v2 = Vector::fromItems($c1->pr1);\n  displayVector($v2);\n\n  $v2 = Vector {-100, -50, 0, 50, 100};\n  $v2->removeKey(1);\n  $v2->removeKey(3);\n  displayVector($v2);\n\n  $v2->reverse();\n  displayVector($v2);\n\n  $str = serialize($v2);\n  echo \"\\$str contains >$str<\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Collections/vector.php.expect",
    "content": "object(HH\\Vector)#1 (0) {\n}\n$v1 = is empty\nobject(HH\\Vector)#2 (0) {\n}\n$v1's element count = 0\nobject(HH\\Vector)#3 (0) {\n}\nobject(HH\\Vector)#3 (3) {\n  [0]=>\n  int(12)\n  [1]=>\n  int(99)\n  [2]=>\n  int(199)\n}\n$v1's element count = 3\n$v1 = is not empty\n$v1[1] = 99\nobject(HH\\Vector)#4 (2) {\n  [0]=>\n  int(2)\n  [1]=>\n  int(8)\n}\nobject(HH\\Vector)#6 (2) {\n  [0]=>\n  int(99)\n  [1]=>\n  int(199)\n}\nobject(NS_vector\\C)#7 (1) {\n  [\"pr1\"]=>\n  array(3) {\n    [0]=>\n    int(22)\n    [1]=>\n    int(33)\n    [2]=>\n    int(44)\n  }\n}\nobject(HH\\Vector)#3 (3) {\n  [0]=>\n  int(22)\n  [1]=>\n  int(33)\n  [2]=>\n  int(44)\n}\narray(5) {\n  [0]=>\n  int(22)\n  [1]=>\n  int(33)\n  [2]=>\n  int(44)\n  [-5]=>\n  int(17)\n  [200]=>\n  int(18)\n}\nobject(HH\\Vector)#8 (5) {\n  [0]=>\n  int(22)\n  [1]=>\n  int(33)\n  [2]=>\n  int(44)\n  [3]=>\n  int(17)\n  [4]=>\n  int(18)\n}\nobject(HH\\Vector)#8 (10) {\n  [0]=>\n  int(22)\n  [1]=>\n  int(33)\n  [2]=>\n  int(44)\n  [3]=>\n  int(17)\n  [4]=>\n  int(18)\n  [5]=>\n  int(22)\n  [6]=>\n  int(33)\n  [7]=>\n  int(44)\n  [8]=>\n  int(17)\n  [9]=>\n  int(18)\n}\n$v1 contains >Vector<\nobject(HH\\Vector)#9 (5) {\n  [0]=>\n  int(22)\n  [1]=>\n  int(33)\n  [2]=>\n  int(44)\n  [3]=>\n  int(17)\n  [4]=>\n  int(18)\n}\nobject(HH\\Vector)#10 (3) {\n  [0]=>\n  int(-100)\n  [1]=>\n  int(0)\n  [2]=>\n  int(50)\n}\nobject(HH\\Vector)#10 (3) {\n  [0]=>\n  int(50)\n  [1]=>\n  int(0)\n  [2]=>\n  int(-100)\n}\n$str contains >V:9:\"HH\\Vector\":3:{i:50;i:0;i:-100;}<"
  },
  {
    "path": "tests/Constants/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Constants/Testfile.txt",
    "content": "Once upon a time,\nin a land\nfar,   \nfar away,  \nthere lived an ogre called Big Bad Bruce.\n"
  },
  {
    "path": "tests/Constants/constants.php",
    "content": "<?hh // strict\n\nnamespace NS_constants;\n\nfunction trace(string $name, mixed $value, bool $b = false): void {\n  $r = define($name, $value, $b);\n  echo \"define $name \" . ($r ? \"succeeded\" : \"failed\");\n  if (defined($name))\n    echo \"; value is >\" . constant($name)  . \"<\\n\";\n  else\n    echo \"; not defined\\n\";\n}\n\nfunction getValue(): int { return 250; }\n\nclass C {}\n\nclass MyClass {\n//  define(\"DEFINE_INSIDE_CLASS\", 10);\t\t// not permitted inside a class; OK\n\n//  const int CON30;\t\t// not permitted; OK\n  const float CON31 = 5 + 10.1 * 3;\n//  const int CON34 = array(10, 20)[0];\t// failed; Arrays are not allowed in class constants\n//  const float CON37 = (float)10;// failed; unexpected '(float)'\n//  const C CON40 = new C();\t// failed; unexpected 'new'\n  const int CON38 = 99;\t\t// succeeded\n  const int CON39 = MyClass::CON38;\t// succeeded\n}\n\nclass C3 {\n  const CON1 = 123;\t\t// implicitly static, and can't say so explicitly\n//  public const CON2 = 123;\t// all class constants are implicitly public; can't say explicitly\n//  protected const CON3 = 123;\t// all class constants are implicitly public\n//  private const CON4 = 123;\t// all class constants are implicitly public\n}\n\nfunction main(): void {\n/*\n// define some constants with simple (single-token) scalar initial values \n\n  trace(\"STATUS1\", true);\n  trace(\"MIN\", 10);\n  trace(\"MAX\", 20, true);\t\t// HHVM Warning: Case insensitive constant names are not supported in HipHop\n  trace(\"MY_PI\", 3.1415926);\n  trace(\"MY_COLOR\", \"red\");\n  trace(\"C1\", null);\n*/\n\n///*\n// try to define some constants with multiple-token scalar initial values \n\n// involving literals only\n\n  trace(\"CON1\", 5 + 10.1 * 3);// succeeded;\n\n// involving variables and other non-basic operators\n\n  $v1 = 10;\n  trace(\"CON2\", 5 + $v1);\t\t\t// succeeded\n  $v2 = array(10, 20);\n  trace(\"CON3\", 5 + $v2[0]);\t\t// succeeded\n  trace(\"CON4\", 5 + array(10, 20)[0]);\t// succeeded\n  trace(\"CON5\", 5 + ++$v2[0]);\t\t// succeeded\n  trace(\"CON6\", 5 + $v2[0]--);\t\t// succeeded\n  trace(\"CON7\", 5 + (float)$v1);\t\t// succeeded\n  trace(\"CON8\", 1 << $v1);\t\t// succeeded\n  trace(\"CON9\", $v2[0] == $v2[1]);\t// succeeded\n  trace(\"CON10\", $v2[0] = 123);\t\t// succeeded\n  trace(\"CON11\", getValue() - 100);\t// succeeded\n\n// involving constants\n\n  trace(\"CON21\", 1 + constant(\"CON1\"));\t\t// succeeded;\n  trace(\"CON22\", 2 * constant(\"CON2\") + constant(\"CON1\"));\t// succeeded;\n\n//  define('X1', 10, false);\n//  define('X2', 5 * X1, false);\t\t// Unbound name: NS_constants\\X1\n//  define('X2', 5 * constant('X1'), false);\n//  var_dump(constant('X1'), constant('X2'));\n\n//*/\n\n/*\n// try to define some constants with names not permitted as tokens\n\n  trace(\"36ABC\", 100) . \"\\n\";\t\t// ill-formed name, but no error. Seems to work\n  trace(\"#%&\", 200) . \"\\n\";\t\t// ill-formed name, but no error. Seems to work\n*/\n\n/*\n// try to redefine a user-defined constant\n\n  trace(\"MY_COLOR\", \"green\");\t\t// Warning, and doesn't change the value\n\n// try to redefine a pre-defined constant\n\n  trace(\"true\", 999) . \"\\n\";\t\t// HHVM:  Constant true already defined ...\n  echo \"    true's value:\" . true . \"\\n\";\t// however, this shows the old value, 1\n*/\n\n/*\n// try to define some constants with non-scalar initial values \n\n  trace(\"COLORS\", [10, 20]);\t// Constants may only evaluate to scalar values\n\n  trace(\"MY_OBJECT\", new C());\t// Constants may only evaluate to scalar values\n\n  $infile = fopen(\"Testfile.txt\", 'r');\n  if ($infile == false) {\n    echo \"Can't open file\\n\";\n  }\n  trace(\"MY_RESOURCE\", $infile);\t// HHVM: Constants may only evaluate to scalar values\n*/\n\n//  print_r(get_defined_constants());\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Constants/constants.php.expect",
    "content": "define CON1 succeeded; value is >35.3<\ndefine CON2 succeeded; value is >15<\ndefine CON3 succeeded; value is >15<\ndefine CON4 succeeded; value is >15<\ndefine CON5 succeeded; value is >16<\ndefine CON6 succeeded; value is >16<\ndefine CON7 succeeded; value is >15<\ndefine CON8 succeeded; value is >1024<\ndefine CON9 succeeded; value is ><\ndefine CON10 succeeded; value is >123<\ndefine CON11 succeeded; value is >150<\ndefine CON21 succeeded; value is >36.3<\ndefine CON22 succeeded; value is >65.3<"
  },
  {
    "path": "tests/Constants/context_dependent_constants.php",
    "content": "<?hh // strict\n\nnamespace NS_context_dependent_constants;\n\nfunction ComputeResult(): void {\n  echo \"Inside ComputeResult\\n\";\n  echo \"__FUNCTION__: \"; var_dump(__FUNCTION__);\n  echo \"__METHOD__: \"; var_dump(__METHOD__);\n//  echo \"__CLASS__: \"; var_dump(__CLASS__);\n//  echo \"__TRAIT__: \"; var_dump(__TRAIT__);\n  echo \"__NAMESPACE__: \"; var_dump(__NAMESPACE__);\n}\n\nclass Date {\n  private string $name1 = __FUNCTION__;\n  private string $name2 = __METHOD__;\t// takes on \"__construct\" rather than \"\"\n\n  public function __construct() {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    echo \"__CLASS__: \"; var_dump(__CLASS__);\n    echo \"__FUNCTION__: \"; var_dump(__FUNCTION__);\n//    echo \"__TRAIT__: \"; var_dump(__TRAIT__);\n    echo \"__NAMESPACE__: \"; var_dump(__NAMESPACE__);\n\n    echo \"\\$name1: \"; var_dump($this->name1);\n    echo \"\\$name2: \"; var_dump($this->name2);\n\n    // ...\n  }\n\n  public function __destruct() {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    echo \"__FUNCTION__: \"; var_dump(__FUNCTION__);\n\n    // ...\n  }\n\n  public function setDay(int $day): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    echo \"__FUNCTION__: \"; var_dump(__FUNCTION__);\n    echo \"__LINE__: \"; var_dump(__LINE__);\n\n    $this->priv1();\n    Date::spf1();\n  }\n\n// public vs. private doesn't matter\n\n  private function priv1(): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    echo \"__FUNCTION__: \"; var_dump(__FUNCTION__);\n  }\n\n  static public function spf1(): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    echo \"__FUNCTION__: \"; var_dump(__FUNCTION__);\n  }\n\n}\n\nclass DatePlus extends Date {\n  public function xx(): void {\n    echo \"__CLASS__: \"; var_dump(__CLASS__);\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    echo \"__FUNCTION__: \"; var_dump(__FUNCTION__);\n  }\n}\n\nfunction main(): void {\n  echo \"__LINE__: \"; var_dump(__LINE__);\n\n  echo \"__FILE__: \"; var_dump(__FILE__);\n\n  echo \"__DIR__: \"; var_dump(__DIR__);\n  var_dump(dirname(__FILE__));\n\n  echo \"__LINE__: \"; var_dump(__LINE__);\n\n  echo \"__NAMESPACE__: \"; var_dump(__NAMESPACE__);\n\n  echo \"-----------------------------------------\\n\";\n\n  echo \"Outside all classes\\n\";\n//  echo \"__CLASS__: \"; var_dump(__CLASS__);\n\n  echo \"-----------------------------------------\\n\";\n\n  echo \"Outside all classes\\n\";\n//  echo \"__TRAIT__: \"; var_dump(__TRAIT__);\n\n  echo \"-----------------------------------------\\n\";\n\n  ComputeResult();\n\n  echo \"-----------------------------------------\\n\";\n\n  $date1 = new Date();\n  $date1->setDay(22);\n\n  echo \"-----------------------------------------\\n\";\n\n  $datePlus1 = new DatePlus();\n  $datePlus1->xx();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Constants/context_dependent_constants.php.expectf",
    "content": "__LINE__: int(70)\n__FILE__: string(%d) \"%s/tests/Constants/context_dependent_constants.php\"\n__DIR__: string(%d) \"%s/tests/Constants\"\nstring(%d) \"%s/tests/Constants\"\n__LINE__: int(77)\n__NAMESPACE__: string(30) \"NS_context_dependent_constants\"\n-----------------------------------------\nOutside all classes\n-----------------------------------------\nOutside all classes\n-----------------------------------------\nInside ComputeResult\n__FUNCTION__: string(44) \"NS_context_dependent_constants\\ComputeResult\"\n__METHOD__: string(44) \"NS_context_dependent_constants\\ComputeResult\"\n__NAMESPACE__: string(30) \"NS_context_dependent_constants\"\n-----------------------------------------\nInside NS_context_dependent_constants\\Date::__construct\n__CLASS__: string(35) \"NS_context_dependent_constants\\Date\"\n__FUNCTION__: string(11) \"__construct\"\n__NAMESPACE__: string(30) \"NS_context_dependent_constants\"\n$name1: string(0) \"\"\n$name2: string(35) \"NS_context_dependent_constants\\Date\"\nInside NS_context_dependent_constants\\Date::setDay\n__FUNCTION__: string(6) \"setDay\"\n__LINE__: int(41)\nInside NS_context_dependent_constants\\Date::priv1\n__FUNCTION__: string(5) \"priv1\"\nInside NS_context_dependent_constants\\Date::spf1\n__FUNCTION__: string(4) \"spf1\"\n-----------------------------------------\nInside NS_context_dependent_constants\\Date::__construct\n__CLASS__: string(35) \"NS_context_dependent_constants\\Date\"\n__FUNCTION__: string(11) \"__construct\"\n__NAMESPACE__: string(30) \"NS_context_dependent_constants\"\n$name1: string(0) \"\"\n$name2: string(35) \"NS_context_dependent_constants\\Date\"\n__CLASS__: string(39) \"NS_context_dependent_constants\\DatePlus\"\nInside NS_context_dependent_constants\\DatePlus::xx\n__FUNCTION__: string(2) \"xx\"\nInside NS_context_dependent_constants\\Date::__destruct\n__FUNCTION__: string(10) \"__destruct\"\nInside NS_context_dependent_constants\\Date::__destruct\n__FUNCTION__: string(10) \"__destruct\"\n"
  },
  {
    "path": "tests/Constants/core_predefined_constants.php",
    "content": "<?hh // strict\n\nnamespace NS_core_predefined_constants;\n\nfunction main(): void {\n//  $v = __COMPILER_HALT_OFFSET__;\n//  $v = DEFAULT_INCLUDE_PATH;\n  $v = E_ALL;\n  $v = E_COMPILE_ERROR;\n  $v = E_COMPILE_WARNING;\n  $v = E_CORE_ERROR;\n  $v = E_CORE_WARNING;\n  $v = E_DEPRECATED;\n  $v = E_ERROR;\n  $v = E_NOTICE;\n  $v = E_PARSE;\n  $v = E_RECOVERABLE_ERROR;\n  $v = E_STRICT;\n  $v = E_USER_DEPRECATED;\n  $v = E_USER_ERROR;\n  $v = E_USER_NOTICE;\n  $v = E_USER_WARNING;\n  $v = E_WARNING;\n  $v = E_USER_DEPRECATED;\n//  $v = M_1_PI;\n//  $v = M_2_PI;\n//  $v = M_2_SQRTPI;\n  $v = M_E;\n//  $v = M_EULER;\n//  $v = M_LN10;\n//  $v = M_LN2;\n//  $v = M_LNPI;\n//  $v = M_LOG10E;\n//  $v = M_LOG2E;\n  $v = M_PI;\n//  $v = M_PI_2;\n//  $v = M_PI_4;\n//  $v = M_SQRT1_2;\n//  $v = M_SQRT2;\n//  $v = M_SQRT3;\n//  $v = M_SQRTPI;\n//  $v = PEAR_EXTENSION_DIR;\n//  $v = PEAR_INSTALL_DIR;\n//  $v = PHP_BINARY;\n//  $v = PHP_BINDIR;\n//  $v = PHP_CONFIG_FILE_PATH;\n//  $v = PHP_CONFIG_FILE_SCAN_DIR;\n//  $v = PHP_DATADIR;\n//  $v = PHP_DEBUG;\n  $v = PHP_EOL;\n//  $v = PHP_EXTENSION_DIR;\n//  $v = PHP_EXTRA_VERSION;\n  $v = PHP_INT_MAX;\n  $v = PHP_INT_SIZE;\n//  $v = PHP_LIBDIR;\n//  $v = PHP_LOCALSTATEDIR;\n//  $v = PHP_MAJOR_VERSION;\n//  $v = PHP_MANDIR;\n//  $v = PHP_MAXPATHLEN;\n//  $v = PHP_MINOR_VERSION;\n//  $v = PHP_OS;\n//  $v = PHP_PREFIX;\n//  $v = PHP_RELEASE_VERSION;\n//  $v = PHP_ROUND_HALF_DOWN;\n//  $v = PHP_ROUND_HALF_EVEN;\n//  $v = PHP_ROUND_HALF_ODD;\n//  $v = PHP_ROUND_HALF_UP;\n//  $v = PHP_SAPI;\n//  $v = PHP_SHLIB_SUFFIX;\n//  $v = PHP_SYSCONFDIR;\n//  $v = PHP_VERSION;\n//  $v = PHP_VERSION_ID;\n//  $v = PHP_ZTS;\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Constants/core_predefined_constants.php.expect",
    "content": ""
  },
  {
    "path": "tests/Enums/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Enums/enum_constraints.php",
    "content": "<?hh // strict\n\nnamespace NS_enum_constraints;\n\nenum E2: int { Z = 12; }\nenum E3: string { X = 'aa'; }\n\n//enum E: int as bool {\t\t// types are incompatible\n//enum E: int as int {\t\t// Okay\n//enum E: int as float {\t// types are incompatible\n//enum E: int as num {\t\t// Okay\n//enum E: int as arraykey {\t// Okay\n//enum E: int as ?int {\t\t// Okay\n//enum E: int as string {\t// types are incompatible\n//enum E: int as void {\t\t// types are incompatible\n//enum E: int as string {\t// types are incompatible\n//enum E: int as E2 {\t\t// types are incompatible\n//enum E: int as E3 {\t\t// types are incompatible\nenum E: int as mixed {\t\t// Okay\n  A = 1;\n  B = 2;\n}\n\nenum F2: int { Z = 12; }\nenum F3: string { X = 'aa'; }\n\n//enum F: string as bool {\t// types are incompatible\n//enum F: string as int {\t// types are incompatible\n//enum F: string as float {\t// types are incompatible\n//enum F: string as num\t{\t// types are incompatible\n//enum F: string as arraykey {\t// Okay\n//enum F: string as string {\t// Okay\n//enum F: string as ?string {\t// Okay\n//enum F: string as void {\t// types are incompatible\n//enum F: string as F2 {\t// types are incompatible\n//enum F: string as F3 {\t// types are incompatible\nenum F: string as mixed {\t// Okay\n  A = 'zz';\n  B = 'xx';\n}\n\nfunction main(): void {\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n\n"
  },
  {
    "path": "tests/Enums/enum_constraints.php.expect",
    "content": ""
  },
  {
    "path": "tests/Enums/enums.php",
    "content": "<?hh // strict\n\nnamespace NS_enum;\n\nenum BitFlags: int as int {\n  F2 = BitFlags::F1 << 1;\n  F3 = BitFlags::F2 << 1;\n  F1 = 1;\n}\n\nenum ControlStatus: int {\n  Stopped = 0;\n  Stopping = 1;\n  Starting = 2;\n  Started = 2 + 1;\t\t// use an a non-trivial expression\n}\n\nenum ControlStatus2    : int as int {\n  Stopped = 0;\n  Stopping = 1;\n  Starting = 2;\n  Started = 4 - 1;\t\t// use an a non-trivial expression\n}\n\n/*\n// an enum must have an explicit underlying type\n\nenum E1 {\n}\n*/\n\n// an enum can be empty\n\nenum E2a: int {\n}\n\nenum E2b: string {\n}\n\n/* mixed enums no longer allowed\n\nenum E2c: mixed {\n}\n*/\n\n/*\n// an enum must have an explicit underlying type of int, string, or mixed\n\nenum E2d: bool {\n}\n\nenum E2e: float {\n}\n\nenum E2f: num {\n}\n*/\n\n/*\n// an enum constant must be initialized explicitly; no default values are assigned\n\nenum E3: int {\n\tX;\t// need an = and initial value\n}\n*/\n\nenum E4a: string {\n  Ready = 'READY';\n  Set = 'SET';\n  Go = 'GO';\n}\n\nenum E4b: string as string {\n  Ready = 'READY';\n  Set = 'SET';\n  Go = 'GO';\n}\n\n/* mixed enums no longer allowed\n\nenum E5: mixed {\n  Ready = 'R';\n  Set = 'S';\n  Stopped = 10;\n  Started = 20;\n\n//  Status = false;\t// Enum constants must be an int or string\n//  Value = 1.234;\t// Enum constants must be an int or string\n//  X = null;\t// Enum constants must be an int or string\n}\n*/\n\n// an int enum can have negative constants, duplicate values, and gaps in the sequence\n\nenum E6a: int {\n  val1 = 10;\n  val2 = 20;\n  val3 = -5;\t\t// negative value okay\n  val4 = 20;\t\t// duplicate okay\n//  val5 = val1;\t\t// unbound name val1\n//  val6 = E6a::val1;\t// Constant of type int conflicts with type E6a\n//  val7 = self::val1;\t// Constant of type int conflicts with type E6a\n}\n\nenum E6c: int as int {\n  val1 = 10;\n  val2 = 20;\n  val3 = -5;\t\t// negative value okay\n  val4 = 20;\t\t// duplicate okay\n}\n\n// a string enum can have duplicate values\n\nenum E6b: string {\n  v1 = 'xx';\n  v2 = 'xx';\n}\n\n/*\n// a string enum with as int clause\n\nenum E7a: string as int {\t// Invalid constraint on enum\n}\n\n// an int enum with as string clause\n\nenum E7b: int as string {\t// Invalid constraint on enum\n}\n\n// a mixed enum with as string clause\n\nenum E7c: mixed as string {\t// Invalid constraint on enum\n}\n\n// a mixed enum with as int clause\n\nenum E7d: mixed as int {\t// Invalid constraint on enum\n}\n*/\n\n// a mixed enum with as mixed clause\n\n/* mixed enums no longer allowed\n\nenum E7e: mixed as mixed {\t// Allowed, but not obvious what the value of that might be\n  con1 = 123;\n}\n*/\n\nenum E8a: int {\n con1 = 0;\n}\n\nenum E8b: string {\n  con1 = \"\";\n}\n\nenum Permission: string {\n  Read = 'R';\n  Write = 'W';\n  Execute = 'E';\n  Delete = 'D';\n}\n\nenum Months: int as int {\n  January = 0;\n  February = 1;\n  March = 2;\n  April = 3;\n  May = 4;\n  June = 5;\n  July = 6;\n  August = 7;\n  September = 8;\n  October = 9;\n  November = 10;\n  December = 11;\n}\n\n//function main(ControlStatus $p1, ControlStatus2 $p2, E4a $p3, E5 $p4, E6a $p5): void {\nfunction main(ControlStatus $p1, ControlStatus2 $p2, E4a $p3, E6a $p5): void {\n  var_dump(ControlStatus::Started);\t// int\n\n  echo \"====== use an enum value to control a switch ======\\n\\n\";\n\n  switch ($p1) {\n  case ControlStatus::Stopped:\n    echo \"Stopped: $p1\\n\";\n    break;\n  case ControlStatus::Stopping:\n    echo \"Stopping: $p1\\n\";\n    break;\n  case ControlStatus::Starting:\n    echo \"Starting: $p1\\n\";\t// ***\n    break;\n  case ControlStatus::Started:\n    echo \"Started: $p1\\n\";\n    break;\n  }\n\n  switch ($p3) {\n  case E4a::Ready:\n    echo \"Ready: $p3\\n\";\t// ***\n    break;\n  case E4a::Set:\n    echo \"Set: $p3\\n\";\n    break;\n  case E4a::Go:\n    echo \"Go: $p3\\n\";\n    break;\n  }\n\n/*\n// The following debug code was used to figure what was going wrong when E5::Ready was initialized\n// with the value 0. Doing that caused $p4 (= 'R') to match the case label E5::Started, as 'R' == 0 \n// tests True in PHP and so in hhvm. That is, switch/case matching appears to use == rather than ===.\n\n  echo \"++++++\\n\";\n  var_dump($p4);\t// 'R'\n  echo $p4 . \" == \" . E5::Set . \" is \" . (($p4 == E5::Set) ? \"True\\n\" : \"False\\n\");\t\t// False\n  echo $p4 . \" == \" . E5::Started . \" is \" . (($p4 == E5::Started) ? \"True\\n\" : \"False\\n\");\t// True **\n  echo $p4 . \" === \" . E5::Started . \" is \" . (($p4 === E5::Started) ? \"True\\n\" : \"False\\n\");\t// False\n  echo $p4 . \" == \" . E5::Stopped . \" is \" . (($p4 == E5::Stopped) ? \"True\\n\" : \"False\\n\");\t// False\n  echo $p4 . \" == \" . E5::Ready . \" is \" . (($p4 == E5::Ready) ? \"True\\n\" : \"False\\n\");\t\t// True\n  echo $p4 . \" === \" . E5::Ready . \" is \" . (($p4 === E5::Ready) ? \"True\\n\" : \"False\\n\");\t// True\n  echo \"++++++\\n\";\n\n  switch ($p4) {\n  case E5::Set:\n    echo \"Set: $p4\\n\";\n    break;\n  case E5::Started:\n    echo \"Started: $p4\\n\";\n    break;\n  case E5::Stopped:\n    echo \"Stopped: $p4\\n\";\n    break;\n  case E5::Ready:\n    echo \"Ready: $p4\\n\";\n    break;\n  }\n*/\n  echo \"\\n====== does an int enum behave like an int? Ordinarily, no. ======\\n\\n\";\n\n  if (ControlStatus::Started == 3) ;\n\n//  if (ControlStatus::Started < 3) ;\t// This is an object of type NS_enum\\ControlStatus\n\t\t\t\t\t// It is incompatible with an int\n\n//  $r = ControlStatus::Stopping << 3;\t// This is an int because this is used in a bitwise\n\t\t\t\t\t// operation. It is incompatible with an object of type\n\t\t\t\t\t// NS_enum\\ControlStatus\n\n//  $r = ControlStatus::Stopping * 10;\t// This is a num (int/float) because this is used in\n\t\t\t\t\t// an arithmetic operation. It is incompatible with\n\t\t\t\t\t// an object of type NS_enum\\ControlStatus\n\n  echo \"\\n====== does an int enum behave like an int? Can do if an \\\"as int\\\" clause is present in the definition. ======\\n\\n\";\n\n  if (ControlStatus2::Started == 3) ;\n  if ($p2 < 3) ;\n  $r = ControlStatus2::Stopping << 3;\n  $r = $p2 * 10;\n\n// Clearly, I can use the enum constant as an int, so why does the checker gag on the two \n// subscript attempts?\n\n  Months::March < 6;\n  Months::March << 3;\n  Months::March * 10;\n\n  $monthTotals = array(100, 200, 300, 100, 200, 300, 100, 200, 300, 100, 200, 300);\n//  echo \"Total for March is \" . $monthTotals[Months::March] . \"\\n\"; \n\n  $monthTotals = Vector {100, 200, 300, 100, 200, 300, 100, 200, 300, 100, 200, 300};\n//  echo \"Total for March is \" . $monthTotals[Months::March] . \"\\n\"; \n\n  echo \"\\n====== use enum having duplicate enum constant values ======\\n\\n\";\n\n  if ($p5 == E6a::val1) echo \"\\$p5 == E6a::val1\\n\";\n  if ($p5 == E6a::val2) echo \"\\$p5 == E6a::val2\\n\";\t// gets here\n  if ($p5 == E6a::val3) echo \"\\$p5 == E6a::val3\\n\";\n  if ($p5 == E6a::val4) echo \"\\$p5 == E6a::val4\\n\";\t// and here too\n\n  echo \"\\n====== use Enum static methods ======\\n\\n\";\n\n//  $e = new \\Enum();\t// Unbound name: Enum; hmm. I was expecting to get something like\n\t\t\t\t// \"Can't instantiate an abstract class\"\n\n  $names = ControlStatus::getNames();\n  echo \"ControlStatus::getNames() ---\\n\";\n  foreach ($names as $key => $value) {\n    echo \"\\tkey >$key< has value >$value<\\n\";\n  }\n\n  $values = ControlStatus::getValues();\n  echo \"ControlStatus::getValues() ---\\n\";\n  foreach ($values as $key => $value) {\n    echo \"\\tkey >$key< has value >$value<\\n\";\n  }\n/*\n  $names = E5::getNames();\n  echo \"E5::getNames() ---\\n\";\n  foreach ($names as $key => $value) {\n    echo \"\\tkey >$key< has value >$value<\\n\";\n  }\n\n  $values = E5::getValues();\n  echo \"E5::getValues() ---\\n\";\n  foreach ($values as $key => $value) {\n    echo \"\\tkey >$key< has value >$value<\\n\";\n  }\n*/\n/*\n// Due to duplicate enum constant values, the call to getNames results in\n// Fatal error: Uncaught exception 'HH\\InvariantException' with message 'Enum has overlapping values' ...\n\n  $names = E6a::getNames();\n  echo \"E6a::getNames() ---\\n\";\n  foreach ($names as $key => $value) {\n    echo \"\\tkey >$key< has value >$value<\\n\";\n  }\n*/\n\n// However, getValues works okay with dupe values\n\n  $values = E6a::getValues();\n  echo \"E6a::getValues() ---\\n\";\n  foreach ($values as $key => $value) {\n    echo \"\\tkey >$key< has value >$value<\\n\";\n  }\n/*\n  echo \"\\nValue 'R'         \" . (E5::isValid('R') ? 'is' : 'is not') . \" a value in the enum\\n\";\n  echo \"Value E5::Ready   \" . (E5::isValid(E5::Ready) ? 'is' : 'is not') . \" a value in the enum\\n\";\n  echo \"Value 1           \" . (E5::isValid(1) ? 'is' : 'is not') . \" a value in the enum\\n\";\n  echo \"Value E5::Stopped \" . (E5::isValid(E5::Stopped) ? 'is' : 'is not') . \" a value in the enum\\n\";\n  echo \"Value 7           \" . (E5::isValid(7) ? 'is' : 'is not') . \" a value in the enum\\n\";\n  echo \"Value 'X'         \" . (E5::isValid('X') ? 'is' : 'is not') . \" a value in the enum\\n\";\n*/\n\n  echo \"\\n====== string operations on a string enum constant  ======\\n\\n\";\n\n  var_dump('READY'[1]);\t// outputs string(1) \"E\"\n\n//  var_dump(E4a::Ready[1]);\t\t// rejected, as expected\n  echo \"E4a:Ready is \" . E4a::Ready . \"\\n\";\t// concat works for enum (special case, apparently)\n//  takes_string(E4a::Ready);\t\t// rejected, as expected\n\n//  var_dump(E4b::Ready[1]);\t\t// rejected, hmm; I expected this to work (Issue #60)\n  echo \"E4b:Ready is \" . E4b::Ready . \"\\n\";\t// concat works for enum\n  takes_string(E4b::Ready);\t\t// acepted; enum behaves as string\n\n  echo \"\\n====== int operations on an int enum constant  ======\\n\\n\";\n\n//  takes_int(ControlStatus::Starting);\t// rejected, as expected\n  takes_int(ControlStatus2::Starting);\n\n/*\n  echo \"\\n====== mixed operations on an mixed enum constant  ======\\n\\n\";\n\n  takes_mixed(E5::Stopped);\t\t// acepted; but then mixed accepts any kind of argument\n\t\t\t\t\t// including one of enum type, so the mixed enum is NOT\n\t\t\t\t\t// being treated like a mixed\n  takes_mixed(E7e::con1);\t\t// acepted; enum behaves as string\n*/\n}\n\nfunction takes_int(int $x): void { var_dump($x); }\nfunction takes_string(string $x): void { var_dump($x); }\nfunction takes_mixed(mixed $x): void { var_dump($x); }\n\n//main(ControlStatus::Started, ControlStatus2::Started, E4a::Ready, E6a::val2);\n"
  },
  {
    "path": "tests/Enums/enums.php.expect",
    "content": ""
  },
  {
    "path": "tests/Enums/enums_ops.php",
    "content": "<?hh // strict\n\nnamespace NS_enum_ops;\n\nenum Status: int {\n  Stopped = 0;\n  Stopping = 1;\n  Starting = 2;\n  Started = 3;\n}\n\nenum State: string {\n  Ready = 'READY';\n  Set = 'SET';\n  Go = 'GO';\n  MT = '';\n}\n\nfunction main(): void {\n  opsOnEnums(Status::Stopping, Status::Stopping, Status::Starting, Status::Stopped,\n    State::Set, State::Set, State::Go, State::MT);\n}\n\nfunction opsOnEnums(\n    Status $enumI1, Status $enumI2, Status $enumI3, Status $enumI4,\n    State $enumS1, State $enumS2, State $enumS3, State $enumS4\n  ): void {\n\n  echo \"\\n====== various operations on int and string enums  ======\\n\\n\";\n/*\n  echo \"______ \\$enumI1\\n\"; var_dump($enumI1);\n  echo \"______ \\$enumI3\\n\"; var_dump($enumI3);\n  echo \"______ \\$enumS1\\n\"; var_dump($enumS1);\n  echo \"______ \\$enumS3\\n\"; var_dump($enumS3);\n*/\n\n//  $enumI1++;\n\n//  --$enumI1;\n/*\n  echo \"\\n______ !\\n\"; var_dump(!$enumI1);\t// bool(false)\t!1\n  echo \"______ !\\n\"; var_dump(!$enumI3);\t// bool(false)\t!2\n  echo \"______ !\\n\"; var_dump(!$enumS1);\t// bool(false)\t!'SET'\n  echo \"______ !\\n\"; var_dump(!$enumS3);\t// bool(false)\t!'GO'\n  echo \"______ !\\n\"; var_dump(!$enumI4);\t// bool(true)\t!0\n  echo \"______ !\\n\"; var_dump(!$enumS4);\t// bool(true)\t!''\n*/\n\n//  +$enumI1;\n//  -$enumI1;\n//  ~$enumI1;\n\n//  $enumI1 * 1;\n//  $enumI1 / 2;\n//  $enumI1 % 2;\n\n//  $enumI1 + 1;\n//  $enumI1 - 1;\n\n/*\n  echo \"\\n______ .\\n\"; var_dump($enumI1 . 1);\t// string(2) \"11\"\n  echo \"______ .\\n\"; var_dump($enumI3 . 1);\t// string(2) \"21\"\n  echo \"______ .\\n\"; var_dump($enumS1 . 1);\t// string(4) \"SET1\"\n  echo \"______ .\\n\"; var_dump($enumS3 . 1);\t// string(3) \"GO1\"\n\n//  $enumI1 << 2;\n//  2000 >> $enumI1;\n*/\n\n///*\n  echo \"\\n______ <\\n\"; var_dump($enumI1 < $enumI3);\t// bool(true)\t1 < 2\n  echo \"______ >=\\n\"; var_dump($enumI1 >= $enumI3);\t// bool(false)\t1 >= 2\n\n  echo \"\\n______ <\\n\"; var_dump($enumS1 < $enumS3);\t// bool(false)\t'SET' < 'GO'\n  echo \"______ >=\\n\"; var_dump($enumS1 >= $enumS3);\t// bool(true)\t'SET' >= 'GO'\n\n  echo \"\\n______ ==\\n\"; var_dump($enumI1 == $enumI3);\t// bool(false)\n  echo \"______ !==\\n\"; var_dump($enumI1 !== $enumI3);\t// bool(true)\n\n  echo \"\\n______ ==\\n\"; var_dump($enumS1 == $enumS3);\t// bool(false)\n  echo \"______ !==\\n\"; var_dump($enumS1 !== $enumS3);\t// bool(true)\n//*/\n\n/*\n//  $enumI1 & 8;\n*/\n\n/*\n  echo \"\\n______ &&\\n\"; var_dump($enumI1 && $enumI3);\t// 1 && 2 => bool(true)\n  echo \"______ &&\\n\"; var_dump($enumI4 && $enumI1);\t// 0 && 1 => bool(false)\n  echo \"______ ||\\n\"; var_dump($enumI4 || $enumI1);\t// 0 || 1 => bool(true)\n\n  echo \"\\n______ && mixed\\n\"; var_dump($enumI1 && $enumS3);\t// 1 && 'Go' => bool(true)\n\n  echo \"\\n______ &&\\n\"; var_dump($enumS1 && $enumS3);\t// 'Ready' && 'Go' => bool(true)\n  echo \"______ &&\\n\"; var_dump($enumS4 && $enumS1);\t// '' && 'Ready' => bool(false)\n  echo \"______ ||\\n\"; var_dump($enumS4 || $enumS1);\t// '' || 'Ready' => bool(true)\n\n  echo \"\\n______ ?:\\n\"; var_dump($v = $enumI1 ? $enumI1 : $enumI3);\t// int(1)\n  echo \"______ ?:\\n\"; var_dump($v = $enumI4 ? $enumI1 : $enumI3);\t// int(2)\n  echo \"______ ?:\\n\"; var_dump($v = $enumS1 ? $enumS1 : $enumS3);\t// string(3) 'SET'\n  echo \"______ ?:\\n\"; var_dump($v = $enumS4 ? $enumS1 : $enumS3);\t// string(2) 'Go'\n*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Enums/enums_ops.php.expect",
    "content": "\n====== various operations on int and string enums  ======\n\n\n______ <\nbool(true)\n______ >=\nbool(false)\n\n______ <\nbool(false)\n______ >=\nbool(true)\n\n______ ==\nbool(false)\n______ !==\nbool(true)\n\n______ ==\nbool(false)\n______ !==\nbool(true)"
  },
  {
    "path": "tests/Enums/string_int_equality_problem.php",
    "content": "<?hh // strict\n\nnamespace NS_string_int_equality_problem;\n\n/* *** mixed enums no longer allowed\n\nenum E5: mixed {\n  Ready = 'R';\n  Started = 0;\n}\n\nfunction main(E5 $p4): void {\n//  var_dump('R' == 0);\t// Surprise, this is True!\n//  var_dump('R' === 0);\t// This is False\n\n// Apparently, this is a PHP \"feature\". The engine tries to convert the 'R' to int and fails, but continues\n// by substituting zero instead!\n\n  echo \"++++++\\n\";\n  var_dump($p4);\t// 'R'\n  echo $p4 . \" == \" . E5::Started . \" is \" . (($p4 == E5::Started) ? \"True\\n\" : \"False\\n\");\t// True **\n  echo $p4 . \" === \" . E5::Started . \" is \" . (($p4 === E5::Started) ? \"True\\n\" : \"False\\n\");\t// False\n  echo $p4 . \" == \" . E5::Ready . \" is \" . (($p4 == E5::Ready) ? \"True\\n\" : \"False\\n\");\t\t// True\n  echo $p4 . \" === \" . E5::Ready . \" is \" . (($p4 === E5::Ready) ? \"True\\n\" : \"False\\n\");\t// True\n  echo \"++++++\\n\";\n\n  switch ($p4) {\n  case E5::Started:\n    echo \"Started: $p4\\n\";\t// ??? comes here, but displays $p4 => 'R' (Ready)\n    break;\n  case E5::Ready:\n    echo \"Ready: $p4\\n\";\n    break;\n  }\n}\n*/\n\n/* HH_FIXME[1002] call to main in strict*/\nmain(E5::Ready);\n/* HH_FIXME[1002] call to main in strict*/\nmain(E5::Started);\n\n"
  },
  {
    "path": "tests/Enums/string_int_equality_problem.php.expectf",
    "content": "\nFatal error: Call to undefined function NS_string_int_equality_problem\\main() in %s/tests/Enums/string_int_equality_problem.php on line 39"
  },
  {
    "path": "tests/Exception_Handling/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Exception_Handling/Exception_class.php",
    "content": "<?hh // strict\n\nnamespace NS_Exception_class;\n\nfunction displayExceptionObject(\\Exception $e): void {\n  echo \"\\$e = >$e<\\n\";\t\t// calls __toString\n  echo \"getMessage:       >\".$e->getMessage().\"<\\n\";\n  echo \"getCode:          >\".$e->getCode().\"<\\n\";\n  echo \"getPrevious:      >\".$e->getPrevious().\"<\\n\";\n  echo \"getFile:          >\".$e->getFile().\"<\\n\";\n  echo \"getLine:          >\".$e->getLine().\"<\\n\";\n  echo \"getTraceAsString: >\".$e->getTraceAsString().\"<\\n\";\n\n  $traceInfo = $e->getTrace();\n  var_dump($traceInfo);\n  echo \"Trace Info:\".((count($traceInfo) == 0) ? \" none\\n\" : \"\\n\");\n\n  foreach ($traceInfo as $traceInfoKey => $traceLevel) {\t// process all traceback levels\n    echo \"Key[$traceInfoKey]:\\n\";\n    foreach ($traceLevel as $levelKey => $levelVal) {\t\t// process one traceback level\n      if ($levelKey != \"args\") {\n        echo \"  Key[$levelKey] => >$levelVal<\\n\";\n      } else {\n        echo \"  Key[$levelKey]:\\n\";\n        foreach ($levelVal as $argKey => $argVal) {\t// process all args for that level\n          echo \"    Key[$argKey] => >$argVal<\\n\";\n        }\n      }\n    }\n  }\n}\n\nfunction fL1(int $p1 = -10): void {\n  try {\n    echo \"fL1: In try-block\\n\";\n\n//  throw new \\Exception();\n    throw new \\Exception(\"fL1 Message\", 123);\n  }\n  catch (\\Exception $e) {\n    echo \"fL1: In catch-block\\n\";\n\n    displayExceptionObject($e);\n  }\n  finally {\n    echo \"fL1: In finally-block\\n\";\n  }\n\n  echo \"fL1: Beyond try/catch/finally blocks\\n==========\\n\";\n  echo \"fL1: Calling fL2\\n\";\n  $a = -4.5;\n  fL2(2.3, $a);\t// pass 2nd arg as a non-literal to see how traceback handles it\n//  fL2(2.3);\t// see what happens when a default argument value is used\n}\n\nfunction fL2(float $p1, float $p2 = -100.0): void {\n  try {\n    echo \"fL2: In try-block\\n\";\n\n//    throw new \\Exception();\n    throw new \\Exception(\"fL2 Message\", 234);\n  }\n  catch (\\Exception $e) {\n    echo \"fL2: In catch-block\\n\";\n\n    displayExceptionObject($e);\n  }\n  finally {\n    echo \"fL2: In finally-block\\n\";\n  }\n\n  echo \"fL2: Beyond try/catch/finally blocks\\n==========\\n\";\n  echo \"fL2: Calling fL3\\n\";\n  $a = \"xyz\"; $b = null; $c = true;\n  fL3($a, $b, $c); // pass args as non-literals to see how traceback handles them\n//  fL3($a, $b);\t// see what happens when a default argument value is used\n}\n\nfunction fL3(string $p1, ?int $p2, bool $p3 = false): void {\n  try {\n    echo \"fL3: In try-block\\n\";\n\n//   throw new \\Exception();\n    throw new \\Exception(\"fL3 Message\", 345);\n  }\n  catch (\\Exception $e) {\n    echo \"fL3: In catch-block\\n\";\n\n    displayExceptionObject($e);\n  }\n  finally {\n    echo \"fL3: In finally-block\\n\";\n  }\n\n  echo \"fL3: Beyond try/catch/finally blocks\\n==========\\n\";\n}\n\nfunction main(): void {\n  try {\n    echo \"L0: In try-block\\n\";\n\n//    throw new \\Exception();\n    throw new \\Exception(\"L0 Message\", -1);\n  }\n  catch (\\Exception $e) {\n    echo \"L0: In catch-block\\n\";\n\n    displayExceptionObject($e);\n  }\n  finally {\n    echo \"L0: In finally-block\\n\";\n  }\n\n  echo \"L0: Beyond try/catch/finally blocks\\n==========\\n\";\n  echo \"L0: Calling fL1\\n\";\n  fL1(10);\n//  fL1();\t// see what happens when a default argument value is used\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Exception_Handling/Exception_class.php.expectf",
    "content": "L0: In try-block\nL0: In catch-block\n$e = >exception 'Exception' with message 'L0 Message' in %s/tests/Exception_Handling/Exception_class.php:103\nStack trace:\n#0 %s/tests/Exception_Handling/Exception_class.php(121): NS_Exception_class\\main()\n#1 {main}<\ngetMessage:       >L0 Message<\ngetCode:          >-1<\ngetPrevious:      ><\ngetFile:          >%s/tests/Exception_Handling/Exception_class.php<\ngetLine:          >103<\ngetTraceAsString: >#0 %s/tests/Exception_Handling/Exception_class.php(121): NS_Exception_class\\main()\n#1 {main}<\narray(1) {\n  [0]=>\n  array(4) {\n    [\"file\"]=>\n    string(%d) \"%s/tests/Exception_Handling/Exception_class.php\"\n    [\"line\"]=>\n    int(121)\n    [\"function\"]=>\n    string(23) \"NS_Exception_class\\main\"\n    [\"args\"]=>\n    array(0) {\n    }\n  }\n}\nTrace Info:\nKey[0]:\n  Key[file] => >%s/tests/Exception_Handling/Exception_class.php<\n  Key[line] => >121<\n  Key[function] => >NS_Exception_class\\main<\n  Key[args]:\nL0: In finally-block\nL0: Beyond try/catch/finally blocks\n==========\nL0: Calling fL1\nfL1: In try-block\nfL1: In catch-block\n$e = >exception 'Exception' with message 'fL1 Message' in %s/tests/Exception_Handling/Exception_class.php:38\nStack trace:\n#0 %s/tests/Exception_Handling/Exception_class.php(116): NS_Exception_class\\fL1()\n#1 %s/tests/Exception_Handling/Exception_class.php(121): NS_Exception_class\\main()\n#2 {main}<\ngetMessage:       >fL1 Message<\ngetCode:          >123<\ngetPrevious:      ><\ngetFile:          >%s/tests/Exception_Handling/Exception_class.php<\ngetLine:          >38<\ngetTraceAsString: >#0 %s/tests/Exception_Handling/Exception_class.php(116): NS_Exception_class\\fL1()\n#1 %s/tests/Exception_Handling/Exception_class.php(121): NS_Exception_class\\main()\n#2 {main}<\narray(2) {\n  [0]=>\n  array(4) {\n    [\"file\"]=>\n    string(%d) \"%s/tests/Exception_Handling/Exception_class.php\"\n    [\"line\"]=>\n    int(116)\n    [\"function\"]=>\n    string(22) \"NS_Exception_class\\fL1\"\n    [\"args\"]=>\n    array(1) {\n      [0]=>\n      int(10)\n    }\n  }\n  [1]=>\n  array(4) {\n    [\"file\"]=>\n    string(%d) \"%s/tests/Exception_Handling/Exception_class.php\"\n    [\"line\"]=>\n    int(121)\n    [\"function\"]=>\n    string(23) \"NS_Exception_class\\main\"\n    [\"args\"]=>\n    array(0) {\n    }\n  }\n}\nTrace Info:\nKey[0]:\n  Key[file] => >%s/tests/Exception_Handling/Exception_class.php<\n  Key[line] => >116<\n  Key[function] => >NS_Exception_class\\fL1<\n  Key[args]:\n    Key[0] => >10<\nKey[1]:\n  Key[file] => >%s/tests/Exception_Handling/Exception_class.php<\n  Key[line] => >121<\n  Key[function] => >NS_Exception_class\\main<\n  Key[args]:\nfL1: In finally-block\nfL1: Beyond try/catch/finally blocks\n==========\nfL1: Calling fL2\nfL2: In try-block\nfL2: In catch-block\n$e = >exception 'Exception' with message 'fL2 Message' in %s/tests/Exception_Handling/Exception_class.php:61\nStack trace:\n#0 %s/tests/Exception_Handling/Exception_class.php(52): NS_Exception_class\\fL2()\n#1 %s/tests/Exception_Handling/Exception_class.php(116): NS_Exception_class\\fL1()\n#2 %s/tests/Exception_Handling/Exception_class.php(121): NS_Exception_class\\main()\n#3 {main}<\ngetMessage:       >fL2 Message<\ngetCode:          >234<\ngetPrevious:      ><\ngetFile:          >%s/tests/Exception_Handling/Exception_class.php<\ngetLine:          >61<\ngetTraceAsString: >#0 %s/tests/Exception_Handling/Exception_class.php(52): NS_Exception_class\\fL2()\n#1 %s/tests/Exception_Handling/Exception_class.php(116): NS_Exception_class\\fL1()\n#2 %s/tests/Exception_Handling/Exception_class.php(121): NS_Exception_class\\main()\n#3 {main}<\narray(3) {\n  [0]=>\n  array(4) {\n    [\"file\"]=>\n    string(%d) \"%s/tests/Exception_Handling/Exception_class.php\"\n    [\"line\"]=>\n    int(52)\n    [\"function\"]=>\n    string(22) \"NS_Exception_class\\fL2\"\n    [\"args\"]=>\n    array(2) {\n      [0]=>\n      float(2.3)\n      [1]=>\n      float(-4.5)\n    }\n  }\n  [1]=>\n  array(4) {\n    [\"file\"]=>\n    string(%d) \"%s/tests/Exception_Handling/Exception_class.php\"\n    [\"line\"]=>\n    int(116)\n    [\"function\"]=>\n    string(22) \"NS_Exception_class\\fL1\"\n    [\"args\"]=>\n    array(1) {\n      [0]=>\n      int(10)\n    }\n  }\n  [2]=>\n  array(4) {\n    [\"file\"]=>\n    string(%d) \"%s/tests/Exception_Handling/Exception_class.php\"\n    [\"line\"]=>\n    int(121)\n    [\"function\"]=>\n    string(23) \"NS_Exception_class\\main\"\n    [\"args\"]=>\n    array(0) {\n    }\n  }\n}\nTrace Info:\nKey[0]:\n  Key[file] => >%s/tests/Exception_Handling/Exception_class.php<\n  Key[line] => >52<\n  Key[function] => >NS_Exception_class\\fL2<\n  Key[args]:\n    Key[0] => >2.3<\n    Key[1] => >-4.5<\nKey[1]:\n  Key[file] => >%s/tests/Exception_Handling/Exception_class.php<\n  Key[line] => >116<\n  Key[function] => >NS_Exception_class\\fL1<\n  Key[args]:\n    Key[0] => >10<\nKey[2]:\n  Key[file] => >%s/tests/Exception_Handling/Exception_class.php<\n  Key[line] => >121<\n  Key[function] => >NS_Exception_class\\main<\n  Key[args]:\nfL2: In finally-block\nfL2: Beyond try/catch/finally blocks\n==========\nfL2: Calling fL3\nfL3: In try-block\nfL3: In catch-block\n$e = >exception 'Exception' with message 'fL3 Message' in %s/tests/Exception_Handling/Exception_class.php:84\nStack trace:\n#0 %s/tests/Exception_Handling/Exception_class.php(75): NS_Exception_class\\fL3()\n#1 %s/tests/Exception_Handling/Exception_class.php(52): NS_Exception_class\\fL2()\n#2 %s/tests/Exception_Handling/Exception_class.php(116): NS_Exception_class\\fL1()\n#3 %s/tests/Exception_Handling/Exception_class.php(121): NS_Exception_class\\main()\n#4 {main}<\ngetMessage:       >fL3 Message<\ngetCode:          >345<\ngetPrevious:      ><\ngetFile:          >%s/tests/Exception_Handling/Exception_class.php<\ngetLine:          >84<\ngetTraceAsString: >#0 %s/tests/Exception_Handling/Exception_class.php(75): NS_Exception_class\\fL3()\n#1 %s/tests/Exception_Handling/Exception_class.php(52): NS_Exception_class\\fL2()\n#2 %s/tests/Exception_Handling/Exception_class.php(116): NS_Exception_class\\fL1()\n#3 %s/tests/Exception_Handling/Exception_class.php(121): NS_Exception_class\\main()\n#4 {main}<\narray(4) {\n  [0]=>\n  array(4) {\n    [\"file\"]=>\n    string(%d) \"%s/tests/Exception_Handling/Exception_class.php\"\n    [\"line\"]=>\n    int(75)\n    [\"function\"]=>\n    string(22) \"NS_Exception_class\\fL3\"\n    [\"args\"]=>\n    array(3) {\n      [0]=>\n      string(3) \"xyz\"\n      [1]=>\n      NULL\n      [2]=>\n      bool(true)\n    }\n  }\n  [1]=>\n  array(4) {\n    [\"file\"]=>\n    string(%d) \"%s/tests/Exception_Handling/Exception_class.php\"\n    [\"line\"]=>\n    int(52)\n    [\"function\"]=>\n    string(22) \"NS_Exception_class\\fL2\"\n    [\"args\"]=>\n    array(2) {\n      [0]=>\n      float(2.3)\n      [1]=>\n      float(-4.5)\n    }\n  }\n  [2]=>\n  array(4) {\n    [\"file\"]=>\n    string(%d) \"%s/tests/Exception_Handling/Exception_class.php\"\n    [\"line\"]=>\n    int(116)\n    [\"function\"]=>\n    string(22) \"NS_Exception_class\\fL1\"\n    [\"args\"]=>\n    array(1) {\n      [0]=>\n      int(10)\n    }\n  }\n  [3]=>\n  array(4) {\n    [\"file\"]=>\n    string(%d) \"%s/tests/Exception_Handling/Exception_class.php\"\n    [\"line\"]=>\n    int(121)\n    [\"function\"]=>\n    string(23) \"NS_Exception_class\\main\"\n    [\"args\"]=>\n    array(0) {\n    }\n  }\n}\nTrace Info:\nKey[0]:\n  Key[file] => >%s/tests/Exception_Handling/Exception_class.php<\n  Key[line] => >75<\n  Key[function] => >NS_Exception_class\\fL3<\n  Key[args]:\n    Key[0] => >xyz<\n    Key[1] => ><\n    Key[2] => >1<\nKey[1]:\n  Key[file] => >%s/tests/Exception_Handling/Exception_class.php<\n  Key[line] => >52<\n  Key[function] => >NS_Exception_class\\fL2<\n  Key[args]:\n    Key[0] => >2.3<\n    Key[1] => >-4.5<\nKey[2]:\n  Key[file] => >%s/tests/Exception_Handling/Exception_class.php<\n  Key[line] => >116<\n  Key[function] => >NS_Exception_class\\fL1<\n  Key[args]:\n    Key[0] => >10<\nKey[3]:\n  Key[file] => >%s/tests/Exception_Handling/Exception_class.php<\n  Key[line] => >121<\n  Key[function] => >NS_Exception_class\\main<\n  Key[args]:\nfL3: In finally-block\nfL3: Beyond try/catch/finally blocks\n==========\n"
  },
  {
    "path": "tests/Exception_Handling/MyRangeException.php",
    "content": "<?hh // strict\n\nnamespace NS_MyRangeException;\n\nclass MyRangeException extends \\Exception {\n  private int $badValue;\n  private int $lowerValue;\n  private int $upperValue;\n\n  public function __construct(string $message, int $badValue, int $lowerValue, int $upperValue) {\n    parent::__construct($message);\n\n    $this->badValue = $badValue;\n    $this->lowerValue = $lowerValue;\n    $this->upperValue = $upperValue;\n  }\n\n  public function getBadValue(): int   { return $this->badValue; }\n  public function getLowerValue(): int { return $this->lowerValue; }\n  public function getUpperValue(): int { return $this->upperValue; }\n\n  public function __toString(): string {\n    return parent::__toString()\n      . \", badValue: \" . $this->badValue\n      . \", lowerValue: \" . $this->lowerValue\n      . \", upperValue: \" . $this->upperValue;\n  }\n}\n"
  },
  {
    "path": "tests/Exception_Handling/MyRangeException.php.expect",
    "content": ""
  },
  {
    "path": "tests/Exception_Handling/MyRangeException_test1.php",
    "content": "<?hh // strict\n\nnamespace NS_MyRangeException_test1;\n\nrequire_once 'MyRangeException.php';\n\nfunction main(): void {\n  $re = new \\NS_MyRangeException\\MyRangeException(\"xxx\", 5, 20, 30);\n  var_dump($re);\n\n  echo \"=======\\n\";\n\n  echo \"\\$re = >$re<\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Exception_Handling/MyRangeException_test1.php.expectf",
    "content": "object(NS_MyRangeException\\MyRangeException)#1 (10) {\n  [\"badValue\":\"NS_MyRangeException\\MyRangeException\":private]=>\n  int(5)\n  [\"lowerValue\":\"NS_MyRangeException\\MyRangeException\":private]=>\n  int(20)\n  [\"upperValue\":\"NS_MyRangeException\\MyRangeException\":private]=>\n  int(30)\n  [\"message\":protected]=>\n  string(3) \"xxx\"\n  [\"string\":\"Exception\":private]=>\n  string(0) \"\"\n  [\"code\":protected]=>\n  int(0)\n  [\"file\":protected]=>\n  string(%d) \"%s/tests/Exception_Handling/MyRangeException_test1.php\"\n  [\"line\":protected]=>\n  int(8)\n  [\"trace\":\"Exception\":private]=>\n  array(1) {\n    [0]=>\n    array(4) {\n      [\"file\"]=>\n      string(%d) \"%s/tests/Exception_Handling/MyRangeException_test1.php\"\n      [\"line\"]=>\n      int(17)\n      [\"function\"]=>\n      string(30) \"NS_MyRangeException_test1\\main\"\n      [\"args\"]=>\n      array(0) {\n      }\n    }\n  }\n  [\"previous\":\"Exception\":private]=>\n  NULL\n}\n=======\n$re = >exception 'NS_MyRangeException\\MyRangeException' with message 'xxx' in %s/tests/Exception_Handling/MyRangeException_test1.php:8\nStack trace:\n#0 %s/tests/Exception_Handling/MyRangeException_test1.php(17): NS_MyRangeException_test1\\main()\n#1 {main}, badValue: 5, lowerValue: 20, upperValue: 30<\n"
  },
  {
    "path": "tests/Exception_Handling/hierarchy_of_exception_classes.php",
    "content": "<?hh // strict\n\nnamespace NS_hierarchy_of_exception_classes;\n\nclass DeviceException extends \\Exception { /*...*/ }\nclass DiskException extends DeviceException { /*...*/ }\nclass RemovableDiskException extends DiskException { /*...*/ }\nclass FloppyDiskException extends RemovableDiskException { /*...*/ }\n\nfunction process(): void {\n  throw new DeviceException();\n//  throw new \\Exception();\n}\n\nfunction main(): void {\n  try {\n    process(); // call a function that might generate a disk-related exception\n  }\n/*\n// see if compiler complains (ala C#) if there are unreachable catch clauses by putting\n// the ultimate base exception class first. It does not.\n\n  catch (\\Exception $e) {\n    echo \"In handler for Exception\\n\";\n    // ...\n  }\n*/\n  catch (FloppyDiskException $fde) {\n    echo \"In handler for FloppyDiskException\\n\";\n    // ...\n  }\n  catch (RemovableDiskException $rde) {\n    echo \"In handler for RemovableDiskException\\n\";\n    // ...\n  }\n  catch (DiskException $de) {\n    echo \"In handler for DiskException\\n\";\n    // ...\n  }\n  catch (DeviceException $dve) {\n    echo \"In handler for DeviceException\\n\";\n    // ...\n  }\n/*\n  catch (\\Exception $e) {\n    echo \"In handler for Exception\\n\";\n    // ...\n  }\n*/\n  finally {\n    echo \"In finally block\\n\";\n    // perform some cleanup\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Exception_Handling/hierarchy_of_exception_classes.php.expect",
    "content": "In handler for DeviceException\nIn finally block"
  },
  {
    "path": "tests/Exception_Handling/jump_from_catch_or_finally_clause.php",
    "content": "<?hh // strict\n\nnamespace NS_jump_from_catch_or_finally_clause;\n\nfunction msg(): int {\n  echo \"In msg\\n\";\n  return 999;\n}\n\nfunction f(): int {\n  for ($i = 1; $i < 3; ++$i) {\n    try {\n      throw new \\Exception();\n    }\n///*\n    catch (\\Exception $e) {\n      echo \"In handler for Exception\\n\";\n//\tbreak;\t\t\t// allowed\n//\tcontinue;\t\t// allowed\n//\treturn msg();\t\t// expression is evaluated, but value actually returned\n\t\t\t\t// when both returns exist is 20, from finally block, \n    }\n//*/\n    finally {\n      echo \"In finally block\\n\";\n//\tbreak;\t\t\t// not allowed\n//\tcontinue;\t\t// not allowed\n//\treturn 20;\t\t// not allowed\n    }\n  }\n  return 1;\n}\n\nfunction main(): void {\n  $r = f();\n  var_dump($r);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Exception_Handling/jump_from_catch_or_finally_clause.php.expect",
    "content": "In handler for Exception\nIn finally block\nIn handler for Exception\nIn finally block\nint(1)"
  },
  {
    "path": "tests/Exception_Handling/odds_and_ends.php",
    "content": "<?hh // strict\n\nnamespace NS_odds_and_ends;\n\nclass X {}\t// not derived from \\Exception\n\nclass Except extends \\Exception {\n  public int $prop = 100;\n}\n\nfunction main(): void {\n  try {\n    echo \"L0: In try-block\\n\";\n\n//    throw 10;\t\t// Diagnosed; good\n//    throw new X();\t\t// Diagnosed; good\n      throw new \\Exception();\n  }\n/*\n  catch (int $e) {\t\t// diagnosed; good (Unbound name: int)\n    echo \"L0: In catch-block int\\n\";\n  }\n*/\n/*\n  catch (X $e) {\t\t// diagnosed; good\n    echo \"L0: In catch-block int\\n\";\n  }\n*/\n///*\n  catch (\\Exception $e) {\n    echo \"L0: In catch-block Exception\\n\";\n\n//    throw $e;\n//    throw new \\Exception();\n//    throw;\t\t\t// can't re-throw current exception ala C#, C++\n  }\n//*/\n///*\n  finally {\n    echo \"L0: In finally-block\\n\";\n  }\n//*/\n\n  $o = new Except();\n  echo \"\\$o->prop = \" . $o->prop . \"\\n\";\n\n  try {\n    echo \"In try-block\\n\";\n    throw $o;\n    echo \"End of try-block\\n\";\n  }\n  catch (Except $e) {\n    echo \"In catch-block Except\\n\";\n    echo \"\\$e->prop = \" . $e->prop . \"\\n\";\n    $e->prop = 999;\n    echo \"\\$e->prop = \" . $e->prop . \"\\n\";\n  }\n\n  echo \"\\$o->prop = \" . $o->prop . \"\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Exception_Handling/odds_and_ends.php.expect",
    "content": "L0: In try-block\nL0: In catch-block Exception\nL0: In finally-block\n$o->prop = 100\nIn try-block\nIn catch-block Except\n$e->prop = 100\n$e->prop = 999\n$o->prop = 999"
  },
  {
    "path": "tests/Exception_Handling/set_exception_handler.php",
    "content": "<?hh // strict\n\nnamespace NS_set_exception_handler;\n\nfunction displayExceptionObject(\\Exception $e): void {\n  echo \"\\$e = >$e<\\n\";\t// calls __toString\n  echo \"getMessage:       >\".$e->getMessage().\"<\\n\";\n  echo \"getCode:          >\".$e->getCode().\"<\\n\";\n  echo \"getPrevious:      >\".$e->getPrevious().\"<\\n\";\n  echo \"getFile:          >\".$e->getFile().\"<\\n\";\n  echo \"getLine:          >\".$e->getLine().\"<\\n\";\n  echo \"getTraceAsString: >\".$e->getTraceAsString().\"<\\n\";\n\n  $traceInfo = $e->getTrace();\n  var_dump($traceInfo);\n  echo \"Trace Info:\".((count($traceInfo) == 0) ? \" none\\n\" : \"\\n\");\n  foreach ($traceInfo as $traceInfoKey => $traceLevel) { // process all traceback levels\n    echo \"Key[$traceInfoKey]:\\n\";\n    foreach ($traceLevel as $levelKey => $levelVal) {\t// process one traceback level\n      if ($levelKey != \"args\") {\n        echo \"  Key[$levelKey] => >$levelVal<\\n\";\n      } else {\n        echo \"  Key[$levelKey]:\\n\";\n        foreach ($levelVal as $argKey => $argVal) {\t// process all args for that level\n          echo \"    Key[$argKey] => >$argVal<\\n\";\n        }\n      }\n    }\n  }\n}\n\nfunction MyDefExHandler(\\Exception $e): void {\n  echo \"In MyDefExHandler\\n\";\n  displayExceptionObject($e);\n  echo \"Leaving MyDefExHandler\\n\";\n}\n\nfunction f(int $p1, bool $p2): void {\n  try {\n    echo \"In f's try-block\\n\";\n\n    throw new \\Exception(\"Watson, come here!\", 1234);\n  }\n\n// no catch block(s)\n\n  finally {\n    echo \"In f's finally-block\\n\";\n  }\n\n  echo \"Beyond try/catch/finally blocks\\n==========\\n\";\n}\n\nfunction main(): void {\n// define a default un-caught exception handler\n\n  $prev = set_exception_handler(null);\t// set to default handler\n  var_dump($prev);\n\n// establish a new un-caught exception handler\n\n  $prev = set_exception_handler('\\NS_set_exception_handler\\MyDefExHandler');\t// use my handler\n  var_dump($prev);\n\n//  restore_exception_handler();\n\n  echo \"About to call f\\n\";\n  f(10, true);\n  echo \"Beyond the call to f()\\n\";\t// never gets here; script terminates after my handler ends\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Exception_Handling/set_exception_handler.php.expectf",
    "content": "NULL\nNULL\nAbout to call f\nIn f's try-block\nIn f's finally-block\nIn MyDefExHandler\n$e = >exception 'Exception' with message 'Watson, come here!' in %s/tests/Exception_Handling/set_exception_handler.php:42\nStack trace:\n#0 %s/tests/Exception_Handling/set_exception_handler.php(68): NS_set_exception_handler\\f()\n#1 %s/tests/Exception_Handling/set_exception_handler.php(73): NS_set_exception_handler\\main()\n#2 {main}<\ngetMessage:       >Watson, come here!<\ngetCode:          >1234<\ngetPrevious:      ><\ngetFile:          >%s/tests/Exception_Handling/set_exception_handler.php<\ngetLine:          >42<\ngetTraceAsString: >#0 %s/tests/Exception_Handling/set_exception_handler.php(68): NS_set_exception_handler\\f()\n#1 %s/tests/Exception_Handling/set_exception_handler.php(73): NS_set_exception_handler\\main()\n#2 {main}<\narray(2) {\n  [0]=>\n  array(4) {\n    [\"file\"]=>\n    string(%d) \"%s/tests/Exception_Handling/set_exception_handler.php\"\n    [\"line\"]=>\n    int(68)\n    [\"function\"]=>\n    string(26) \"NS_set_exception_handler\\f\"\n    [\"args\"]=>\n    array(2) {\n      [0]=>\n      int(10)\n      [1]=>\n      bool(true)\n    }\n  }\n  [1]=>\n  array(4) {\n    [\"file\"]=>\n    string(%d) \"%s/tests/Exception_Handling/set_exception_handler.php\"\n    [\"line\"]=>\n    int(73)\n    [\"function\"]=>\n    string(29) \"NS_set_exception_handler\\main\"\n    [\"args\"]=>\n    array(0) {\n    }\n  }\n}\nTrace Info:\nKey[0]:\n  Key[file] => >%s/tests/Exception_Handling/set_exception_handler.php<\n  Key[line] => >68<\n  Key[function] => >NS_set_exception_handler\\f<\n  Key[args]:\n    Key[0] => >10<\n    Key[1] => >1<\nKey[1]:\n  Key[file] => >%s/tests/Exception_Handling/set_exception_handler.php<\n  Key[line] => >73<\n  Key[function] => >NS_set_exception_handler\\main<\n  Key[args]:\nLeaving MyDefExHandler\n"
  },
  {
    "path": "tests/Expressions/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Additive_Operators/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Additive_Operators/addition_subtraction_concatenation.php",
    "content": "<?hh // strict\n\nnamespace NS_addition_subtraction_concatenation;\n\nfunction doit(num $p1_num): void {\n  $oper = array(100, -3.4, $p1_num);\n///*\n  foreach ($oper as $e1) {\n    foreach ($oper as $e2) {\n      echo \">$e1< + >$e2<, result: \"; var_dump($e1 + $e2);\n    }\n    echo \"-------------------------------------\\n\";\n  }\n//*/\n///*\n  foreach ($oper as $e1) {\n    foreach ($oper as $e2) {\n      echo \">$e1< - >$e2<, result: \"; var_dump($e1 - $e2);\n    }\n    echo \"-------------------------------------\\n\";\n  }\n//*/\n///*\n  $oper = array(100, -3.4, true, null, \"123\", \"2e+5\", \"\", \"abc\");\n  foreach ($oper as $e1) {\n    foreach ($oper as $e2) {\n      echo \">$e1< . >$e2<, result: \"; var_dump($e1 . $e2);\n    }\n    echo \"-------------------------------------\\n\";\n  }\n//*/\n}\n\nfunction main(): void {\n  doit(11);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Additive_Operators/addition_subtraction_concatenation.php.expect",
    "content": ">100< + >100<, result: int(200)\n>100< + >-3.4<, result: float(96.6)\n>100< + >11<, result: int(111)\n-------------------------------------\n>-3.4< + >100<, result: float(96.6)\n>-3.4< + >-3.4<, result: float(-6.8)\n>-3.4< + >11<, result: float(7.6)\n-------------------------------------\n>11< + >100<, result: int(111)\n>11< + >-3.4<, result: float(7.6)\n>11< + >11<, result: int(22)\n-------------------------------------\n>100< - >100<, result: int(0)\n>100< - >-3.4<, result: float(103.4)\n>100< - >11<, result: int(89)\n-------------------------------------\n>-3.4< - >100<, result: float(-103.4)\n>-3.4< - >-3.4<, result: float(0)\n>-3.4< - >11<, result: float(-14.4)\n-------------------------------------\n>11< - >100<, result: int(-89)\n>11< - >-3.4<, result: float(14.4)\n>11< - >11<, result: int(0)\n-------------------------------------\n>100< . >100<, result: string(6) \"100100\"\n>100< . >-3.4<, result: string(7) \"100-3.4\"\n>100< . >1<, result: string(4) \"1001\"\n>100< . ><, result: string(3) \"100\"\n>100< . >123<, result: string(6) \"100123\"\n>100< . >2e+5<, result: string(7) \"1002e+5\"\n>100< . ><, result: string(3) \"100\"\n>100< . >abc<, result: string(6) \"100abc\"\n-------------------------------------\n>-3.4< . >100<, result: string(7) \"-3.4100\"\n>-3.4< . >-3.4<, result: string(8) \"-3.4-3.4\"\n>-3.4< . >1<, result: string(5) \"-3.41\"\n>-3.4< . ><, result: string(4) \"-3.4\"\n>-3.4< . >123<, result: string(7) \"-3.4123\"\n>-3.4< . >2e+5<, result: string(8) \"-3.42e+5\"\n>-3.4< . ><, result: string(4) \"-3.4\"\n>-3.4< . >abc<, result: string(7) \"-3.4abc\"\n-------------------------------------\n>1< . >100<, result: string(4) \"1100\"\n>1< . >-3.4<, result: string(5) \"1-3.4\"\n>1< . >1<, result: string(2) \"11\"\n>1< . ><, result: string(1) \"1\"\n>1< . >123<, result: string(4) \"1123\"\n>1< . >2e+5<, result: string(5) \"12e+5\"\n>1< . ><, result: string(1) \"1\"\n>1< . >abc<, result: string(4) \"1abc\"\n-------------------------------------\n>< . >100<, result: string(3) \"100\"\n>< . >-3.4<, result: string(4) \"-3.4\"\n>< . >1<, result: string(1) \"1\"\n>< . ><, result: string(0) \"\"\n>< . >123<, result: string(3) \"123\"\n>< . >2e+5<, result: string(4) \"2e+5\"\n>< . ><, result: string(0) \"\"\n>< . >abc<, result: string(3) \"abc\"\n-------------------------------------\n>123< . >100<, result: string(6) \"123100\"\n>123< . >-3.4<, result: string(7) \"123-3.4\"\n>123< . >1<, result: string(4) \"1231\"\n>123< . ><, result: string(3) \"123\"\n>123< . >123<, result: string(6) \"123123\"\n>123< . >2e+5<, result: string(7) \"1232e+5\"\n>123< . ><, result: string(3) \"123\"\n>123< . >abc<, result: string(6) \"123abc\"\n-------------------------------------\n>2e+5< . >100<, result: string(7) \"2e+5100\"\n>2e+5< . >-3.4<, result: string(8) \"2e+5-3.4\"\n>2e+5< . >1<, result: string(5) \"2e+51\"\n>2e+5< . ><, result: string(4) \"2e+5\"\n>2e+5< . >123<, result: string(7) \"2e+5123\"\n>2e+5< . >2e+5<, result: string(8) \"2e+52e+5\"\n>2e+5< . ><, result: string(4) \"2e+5\"\n>2e+5< . >abc<, result: string(7) \"2e+5abc\"\n-------------------------------------\n>< . >100<, result: string(3) \"100\"\n>< . >-3.4<, result: string(4) \"-3.4\"\n>< . >1<, result: string(1) \"1\"\n>< . ><, result: string(0) \"\"\n>< . >123<, result: string(3) \"123\"\n>< . >2e+5<, result: string(4) \"2e+5\"\n>< . ><, result: string(0) \"\"\n>< . >abc<, result: string(3) \"abc\"\n-------------------------------------\n>abc< . >100<, result: string(6) \"abc100\"\n>abc< . >-3.4<, result: string(7) \"abc-3.4\"\n>abc< . >1<, result: string(4) \"abc1\"\n>abc< . ><, result: string(3) \"abc\"\n>abc< . >123<, result: string(6) \"abc123\"\n>abc< . >2e+5<, result: string(7) \"abc2e+5\"\n>abc< . ><, result: string(3) \"abc\"\n>abc< . >abc<, result: string(6) \"abcabc\"\n-------------------------------------"
  },
  {
    "path": "tests/Expressions/Additive_Operators/array_concatenation.php",
    "content": "<?hh // strict\n\nnamespace NS_array_concatenation;\n\nclass Button {}\nclass CustomButton extends Button {}\n\nfunction array_proc(\n  array<int> $p1, array<int> $p2,\n  array<float> $p3, array<num> $p4,\n  array<Button> $p5, array<CustomButton> $p6,\n  array<int, int> $p7,\n  array<int, string> $p8, array<int, string> $p9,\n  array<int, bool> $p10,\n  array<string, int> $p11, array<string, int> $p12\n  ): void {\n  echo \"============= vector-like arrays ================\\n\";\n\n  $v = $p1 + $p2;\t\t// array<int> + array<int> okay\n  echo \"result of p1 + p2 = \"; var_dump($v);\n\n  $v = $p2 + $p1;\t\t// okay, but of course, is not commutative\n  echo \"result of p2 + p1 = \"; var_dump($v);\n\n//  $v = $p1 + $p3;\t\t// array<int> + array<float> disallowed\n//  $v = $p4 + $p1;\t\t// array<num> + array<int> disallowed\n//  $v = $p4 + $p3;\t\t// array<num> + array<float> disallowed\n//  $v = $p5 + $p6;\t\t// array<Button> + array<CustomButton> disallowed\n\n  echo \"============= map-like arrays ================\\n\";\n\n//  $v = $p1 + $p7;\t\t// array<int> + array<int, int> disallowed;\n\t\t\t\t// can't mix vector-like and map-like arrays even with same key/value types\n\n  $v = $p8 + $p9;\t\t// array<int, string> + array<int, string> okay\n  echo \"result of p8 + p9 = \"; var_dump($v);\n\n//  $v = $p7 + $p10;\t// array<int, int> + array<int, bool> disallowed;\n\n  $v = $p11 + $p12;\t// array<string, int> + array<string, int> okay\n  echo \"result of p11 + p12 = \"; var_dump($v);\n\n  echo \"============= concating to an empty/untyped array ================\\n\";\n\n  $p2 = $p1 + array();\t// array<int> + array() allowed;\n  echo \"result of p1 + array() = \"; var_dump($p2);\n  $p2 = array() + $p2;\t// array<int> + array() allowed;\n  echo \"result of array() + p1 = \"; var_dump($p2);\n\n  $v = $p10 + array();\t// array<int, bool> + array() allowed;\n  echo \"result of p10 + array() = \"; var_dump($v);\n\n  $v = $p11 + array();\t// array<string, int> + array() allowed\n  echo \"result of p11 + array() = \"; var_dump($v);\n\n  $p2 = array() + array();\t// array() + array() allowed;\n  echo \"result of array() + array() = \"; var_dump($p2);\n}\n\nfunction main(): void {\n  array_proc(\n    array(66),\n    array(100, 200),\n    array(1.1, 2.2, 3.3),\n    array(1, 2.5),\n    array(new Button()), array(new CustomButton()),\n    array(6 => 66, 12 => 22),\n    array(2 => 'aa', 12 => 'bb'), array(-4 => 'cc', 6 => 'dd'), \n    array(-3 => true),\n    array('red' => 12, 'green' => 7), array('blue' => 3), \n  );\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Additive_Operators/array_concatenation.php.expect",
    "content": "============= vector-like arrays ================\nresult of p1 + p2 = array(2) {\n  [0]=>\n  int(66)\n  [1]=>\n  int(200)\n}\nresult of p2 + p1 = array(2) {\n  [0]=>\n  int(100)\n  [1]=>\n  int(200)\n}\n============= map-like arrays ================\nresult of p8 + p9 = array(4) {\n  [2]=>\n  string(2) \"aa\"\n  [12]=>\n  string(2) \"bb\"\n  [-4]=>\n  string(2) \"cc\"\n  [6]=>\n  string(2) \"dd\"\n}\nresult of p11 + p12 = array(3) {\n  [\"red\"]=>\n  int(12)\n  [\"green\"]=>\n  int(7)\n  [\"blue\"]=>\n  int(3)\n}\n============= concating to an empty/untyped array ================\nresult of p1 + array() = array(1) {\n  [0]=>\n  int(66)\n}\nresult of array() + p1 = array(1) {\n  [0]=>\n  int(66)\n}\nresult of p10 + array() = array(1) {\n  [-3]=>\n  bool(true)\n}\nresult of p11 + array() = array(2) {\n  [\"red\"]=>\n  int(12)\n  [\"green\"]=>\n  int(7)\n}\nresult of array() + array() = array(0) {\n}"
  },
  {
    "path": "tests/Expressions/Binary_Logical_Operators/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Binary_Logical_Operators/binary_logical_operators.php",
    "content": "<?hh // strict\n\nnamespace NS_binary_logical_operators;\n\nfunction f(int $a): int { echo \"inside f(int $a)\\n\"; return 10;}\nfunction g(int $a): int { echo \"inside g(int $a)\\n\"; return 0;}\n\nfunction main(): void {\n  $month = 6;\n  if ($month > 1 && $month <= 12)\n    echo \"\\$month $month is in-bounds\\n\";\n  else\n    echo \"\\$month $month is out-of-bounds\\n\";\n\n  $month = 14;\n  if ($month > 1 && $month <= 12)\n    echo \"\\$month $month is in-bounds\\n\";\n  else\n    echo \"\\$month $month is out-of-bounds\\n\";\n\n  $month = 6;\n  if ($month < 1 || $month > 12)\n    echo \"\\$month $month is out-of-bounds\\n\";\n  else\n    echo \"\\$month $month is in-bounds\\n\";\n\n  $month = 14;\n  if ($month < 1 || $month > 12)\n    echo \"\\$month $month is out-of-bounds\\n\";\n  else\n    echo \"\\$month $month is in-bounds\\n\";\n\n// sequence point\n\n  $i = 5;\n  $v = (f($i++) && g($i));\n  var_dump($v);\n  $i = 0;\n  $v = (g($i++) || f($i));\n  var_dump($v);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Binary_Logical_Operators/binary_logical_operators.php.expect",
    "content": "$month 6 is in-bounds\n$month 14 is out-of-bounds\n$month 6 is in-bounds\n$month 14 is out-of-bounds\ninside f(int 5)\ninside g(int 6)\nbool(false)\ninside g(int 0)\ninside f(int 1)\nbool(true)"
  },
  {
    "path": "tests/Expressions/Bitwise_Shift_Operators/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Bitwise_Shift_Operators/bitwise_shift.php",
    "content": "<?hh // strict\n\nnamespace NS_bitwise_shift;\n\nfunction main(): void {\n  $i32 = 1 << 31;\t// if this is negative, we have a 32-bit int\n  $NumBitsPerInt = ($i32 < 0) ? 32 : 64;\n\n// Shift a positive value right and left using both in- and out-of-range counts\n\n  $v = 1000;\n  for ($i = -$NumBitsPerInt - 1; $i <= $NumBitsPerInt + 1; ++$i) {\n    printf(\"%d(%08X): >> %2d = %08X\\t<< %2d = %08X\\n\", $v, $v, $i, $v >> $i, $i, $v << $i);\n  }\n\n// Shift a negative value right and left using both in- and out-of-range counts\n\n  $v = -1000;\n  for ($i = -$NumBitsPerInt - 1; $i <= $NumBitsPerInt + 1; ++$i) {\n    printf(\"%d(%08X): >> %2d = %08X\\t<< %2d = %08X\\n\", $v, $v, $i, $v >> $i, $i, $v << $i);\n  }\n\n// Figure out the algorithm the implementations use for negative and too-large shift counts\n\n  for ($i = -129; $i <= 129; ++$i) {\n    $rem = $i % $NumBitsPerInt;\n    if ($rem == 0 || $i > 0) {\n      echo \"$i, \".$rem.\"\\n\";\n    } else {  \t// have a negative shift\n      $r = $NumBitsPerInt - (-$i % $NumBitsPerInt);\n      echo \"$i, \".$r.\"\\n\";\n    }\n  }\n\n// Shift all kinds of scalar values\n\n  $v = 10 << 2;\n//  $v = 1.234 << 2;\t// non-numeric operand not allowed\n//  $v = true << 2;\t// ...\n//  $v = null << 2;\t// ...\n//  $v = \"123\" << 2;\t// ...\n//  $v = 10 << 2.0;\t// non-numeric operand not allowed\n\n  $v = 10 >> 2;\n//  $v = 1.234 >> 2;\t// non-numeric operand not allowed\n//  $v = true >> 2;\t// ...\n//  $v = null >> 2;\t// ...\n//  $v = \"123\" >> 2;\t// ...\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Bitwise_Shift_Operators/bitwise_shift.php.expect",
    "content": "1000(000003E8): >> -65 = 00000000\t<< -65 = 00000000\n1000(000003E8): >> -64 = 000003E8\t<< -64 = 000003E8\n1000(000003E8): >> -63 = 000001F4\t<< -63 = 000007D0\n1000(000003E8): >> -62 = 000000FA\t<< -62 = 00000FA0\n1000(000003E8): >> -61 = 0000007D\t<< -61 = 00001F40\n1000(000003E8): >> -60 = 0000003E\t<< -60 = 00003E80\n1000(000003E8): >> -59 = 0000001F\t<< -59 = 00007D00\n1000(000003E8): >> -58 = 0000000F\t<< -58 = 0000FA00\n1000(000003E8): >> -57 = 00000007\t<< -57 = 0001F400\n1000(000003E8): >> -56 = 00000003\t<< -56 = 0003E800\n1000(000003E8): >> -55 = 00000001\t<< -55 = 0007D000\n1000(000003E8): >> -54 = 00000000\t<< -54 = 000FA000\n1000(000003E8): >> -53 = 00000000\t<< -53 = 001F4000\n1000(000003E8): >> -52 = 00000000\t<< -52 = 003E8000\n1000(000003E8): >> -51 = 00000000\t<< -51 = 007D0000\n1000(000003E8): >> -50 = 00000000\t<< -50 = 00FA0000\n1000(000003E8): >> -49 = 00000000\t<< -49 = 01F40000\n1000(000003E8): >> -48 = 00000000\t<< -48 = 03E80000\n1000(000003E8): >> -47 = 00000000\t<< -47 = 07D00000\n1000(000003E8): >> -46 = 00000000\t<< -46 = 0FA00000\n1000(000003E8): >> -45 = 00000000\t<< -45 = 1F400000\n1000(000003E8): >> -44 = 00000000\t<< -44 = 3E800000\n1000(000003E8): >> -43 = 00000000\t<< -43 = 7D000000\n1000(000003E8): >> -42 = 00000000\t<< -42 = FA000000\n1000(000003E8): >> -41 = 00000000\t<< -41 = 1F4000000\n1000(000003E8): >> -40 = 00000000\t<< -40 = 3E8000000\n1000(000003E8): >> -39 = 00000000\t<< -39 = 7D0000000\n1000(000003E8): >> -38 = 00000000\t<< -38 = FA0000000\n1000(000003E8): >> -37 = 00000000\t<< -37 = 1F40000000\n1000(000003E8): >> -36 = 00000000\t<< -36 = 3E80000000\n1000(000003E8): >> -35 = 00000000\t<< -35 = 7D00000000\n1000(000003E8): >> -34 = 00000000\t<< -34 = FA00000000\n1000(000003E8): >> -33 = 00000000\t<< -33 = 1F400000000\n1000(000003E8): >> -32 = 00000000\t<< -32 = 3E800000000\n1000(000003E8): >> -31 = 00000000\t<< -31 = 7D000000000\n1000(000003E8): >> -30 = 00000000\t<< -30 = FA000000000\n1000(000003E8): >> -29 = 00000000\t<< -29 = 1F4000000000\n1000(000003E8): >> -28 = 00000000\t<< -28 = 3E8000000000\n1000(000003E8): >> -27 = 00000000\t<< -27 = 7D0000000000\n1000(000003E8): >> -26 = 00000000\t<< -26 = FA0000000000\n1000(000003E8): >> -25 = 00000000\t<< -25 = 1F40000000000\n1000(000003E8): >> -24 = 00000000\t<< -24 = 3E80000000000\n1000(000003E8): >> -23 = 00000000\t<< -23 = 7D00000000000\n1000(000003E8): >> -22 = 00000000\t<< -22 = FA00000000000\n1000(000003E8): >> -21 = 00000000\t<< -21 = 1F400000000000\n1000(000003E8): >> -20 = 00000000\t<< -20 = 3E800000000000\n1000(000003E8): >> -19 = 00000000\t<< -19 = 7D000000000000\n1000(000003E8): >> -18 = 00000000\t<< -18 = FA000000000000\n1000(000003E8): >> -17 = 00000000\t<< -17 = 1F4000000000000\n1000(000003E8): >> -16 = 00000000\t<< -16 = 3E8000000000000\n1000(000003E8): >> -15 = 00000000\t<< -15 = 7D0000000000000\n1000(000003E8): >> -14 = 00000000\t<< -14 = FA0000000000000\n1000(000003E8): >> -13 = 00000000\t<< -13 = 1F40000000000000\n1000(000003E8): >> -12 = 00000000\t<< -12 = 3E80000000000000\n1000(000003E8): >> -11 = 00000000\t<< -11 = 7D00000000000000\n1000(000003E8): >> -10 = 00000000\t<< -10 = FA00000000000000\n1000(000003E8): >> -9 = 00000000\t<< -9 = F400000000000000\n1000(000003E8): >> -8 = 00000000\t<< -8 = E800000000000000\n1000(000003E8): >> -7 = 00000000\t<< -7 = D000000000000000\n1000(000003E8): >> -6 = 00000000\t<< -6 = A000000000000000\n1000(000003E8): >> -5 = 00000000\t<< -5 = 4000000000000000\n1000(000003E8): >> -4 = 00000000\t<< -4 = 8000000000000000\n1000(000003E8): >> -3 = 00000000\t<< -3 = 00000000\n1000(000003E8): >> -2 = 00000000\t<< -2 = 00000000\n1000(000003E8): >> -1 = 00000000\t<< -1 = 00000000\n1000(000003E8): >>  0 = 000003E8\t<<  0 = 000003E8\n1000(000003E8): >>  1 = 000001F4\t<<  1 = 000007D0\n1000(000003E8): >>  2 = 000000FA\t<<  2 = 00000FA0\n1000(000003E8): >>  3 = 0000007D\t<<  3 = 00001F40\n1000(000003E8): >>  4 = 0000003E\t<<  4 = 00003E80\n1000(000003E8): >>  5 = 0000001F\t<<  5 = 00007D00\n1000(000003E8): >>  6 = 0000000F\t<<  6 = 0000FA00\n1000(000003E8): >>  7 = 00000007\t<<  7 = 0001F400\n1000(000003E8): >>  8 = 00000003\t<<  8 = 0003E800\n1000(000003E8): >>  9 = 00000001\t<<  9 = 0007D000\n1000(000003E8): >> 10 = 00000000\t<< 10 = 000FA000\n1000(000003E8): >> 11 = 00000000\t<< 11 = 001F4000\n1000(000003E8): >> 12 = 00000000\t<< 12 = 003E8000\n1000(000003E8): >> 13 = 00000000\t<< 13 = 007D0000\n1000(000003E8): >> 14 = 00000000\t<< 14 = 00FA0000\n1000(000003E8): >> 15 = 00000000\t<< 15 = 01F40000\n1000(000003E8): >> 16 = 00000000\t<< 16 = 03E80000\n1000(000003E8): >> 17 = 00000000\t<< 17 = 07D00000\n1000(000003E8): >> 18 = 00000000\t<< 18 = 0FA00000\n1000(000003E8): >> 19 = 00000000\t<< 19 = 1F400000\n1000(000003E8): >> 20 = 00000000\t<< 20 = 3E800000\n1000(000003E8): >> 21 = 00000000\t<< 21 = 7D000000\n1000(000003E8): >> 22 = 00000000\t<< 22 = FA000000\n1000(000003E8): >> 23 = 00000000\t<< 23 = 1F4000000\n1000(000003E8): >> 24 = 00000000\t<< 24 = 3E8000000\n1000(000003E8): >> 25 = 00000000\t<< 25 = 7D0000000\n1000(000003E8): >> 26 = 00000000\t<< 26 = FA0000000\n1000(000003E8): >> 27 = 00000000\t<< 27 = 1F40000000\n1000(000003E8): >> 28 = 00000000\t<< 28 = 3E80000000\n1000(000003E8): >> 29 = 00000000\t<< 29 = 7D00000000\n1000(000003E8): >> 30 = 00000000\t<< 30 = FA00000000\n1000(000003E8): >> 31 = 00000000\t<< 31 = 1F400000000\n1000(000003E8): >> 32 = 00000000\t<< 32 = 3E800000000\n1000(000003E8): >> 33 = 00000000\t<< 33 = 7D000000000\n1000(000003E8): >> 34 = 00000000\t<< 34 = FA000000000\n1000(000003E8): >> 35 = 00000000\t<< 35 = 1F4000000000\n1000(000003E8): >> 36 = 00000000\t<< 36 = 3E8000000000\n1000(000003E8): >> 37 = 00000000\t<< 37 = 7D0000000000\n1000(000003E8): >> 38 = 00000000\t<< 38 = FA0000000000\n1000(000003E8): >> 39 = 00000000\t<< 39 = 1F40000000000\n1000(000003E8): >> 40 = 00000000\t<< 40 = 3E80000000000\n1000(000003E8): >> 41 = 00000000\t<< 41 = 7D00000000000\n1000(000003E8): >> 42 = 00000000\t<< 42 = FA00000000000\n1000(000003E8): >> 43 = 00000000\t<< 43 = 1F400000000000\n1000(000003E8): >> 44 = 00000000\t<< 44 = 3E800000000000\n1000(000003E8): >> 45 = 00000000\t<< 45 = 7D000000000000\n1000(000003E8): >> 46 = 00000000\t<< 46 = FA000000000000\n1000(000003E8): >> 47 = 00000000\t<< 47 = 1F4000000000000\n1000(000003E8): >> 48 = 00000000\t<< 48 = 3E8000000000000\n1000(000003E8): >> 49 = 00000000\t<< 49 = 7D0000000000000\n1000(000003E8): >> 50 = 00000000\t<< 50 = FA0000000000000\n1000(000003E8): >> 51 = 00000000\t<< 51 = 1F40000000000000\n1000(000003E8): >> 52 = 00000000\t<< 52 = 3E80000000000000\n1000(000003E8): >> 53 = 00000000\t<< 53 = 7D00000000000000\n1000(000003E8): >> 54 = 00000000\t<< 54 = FA00000000000000\n1000(000003E8): >> 55 = 00000000\t<< 55 = F400000000000000\n1000(000003E8): >> 56 = 00000000\t<< 56 = E800000000000000\n1000(000003E8): >> 57 = 00000000\t<< 57 = D000000000000000\n1000(000003E8): >> 58 = 00000000\t<< 58 = A000000000000000\n1000(000003E8): >> 59 = 00000000\t<< 59 = 4000000000000000\n1000(000003E8): >> 60 = 00000000\t<< 60 = 8000000000000000\n1000(000003E8): >> 61 = 00000000\t<< 61 = 00000000\n1000(000003E8): >> 62 = 00000000\t<< 62 = 00000000\n1000(000003E8): >> 63 = 00000000\t<< 63 = 00000000\n1000(000003E8): >> 64 = 000003E8\t<< 64 = 000003E8\n1000(000003E8): >> 65 = 000001F4\t<< 65 = 000007D0\n-1000(FFFFFFFFFFFFFC18): >> -65 = FFFFFFFFFFFFFFFF\t<< -65 = 00000000\n-1000(FFFFFFFFFFFFFC18): >> -64 = FFFFFFFFFFFFFC18\t<< -64 = FFFFFFFFFFFFFC18\n-1000(FFFFFFFFFFFFFC18): >> -63 = FFFFFFFFFFFFFE0C\t<< -63 = FFFFFFFFFFFFF830\n-1000(FFFFFFFFFFFFFC18): >> -62 = FFFFFFFFFFFFFF06\t<< -62 = FFFFFFFFFFFFF060\n-1000(FFFFFFFFFFFFFC18): >> -61 = FFFFFFFFFFFFFF83\t<< -61 = FFFFFFFFFFFFE0C0\n-1000(FFFFFFFFFFFFFC18): >> -60 = FFFFFFFFFFFFFFC1\t<< -60 = FFFFFFFFFFFFC180\n-1000(FFFFFFFFFFFFFC18): >> -59 = FFFFFFFFFFFFFFE0\t<< -59 = FFFFFFFFFFFF8300\n-1000(FFFFFFFFFFFFFC18): >> -58 = FFFFFFFFFFFFFFF0\t<< -58 = FFFFFFFFFFFF0600\n-1000(FFFFFFFFFFFFFC18): >> -57 = FFFFFFFFFFFFFFF8\t<< -57 = FFFFFFFFFFFE0C00\n-1000(FFFFFFFFFFFFFC18): >> -56 = FFFFFFFFFFFFFFFC\t<< -56 = FFFFFFFFFFFC1800\n-1000(FFFFFFFFFFFFFC18): >> -55 = FFFFFFFFFFFFFFFE\t<< -55 = FFFFFFFFFFF83000\n-1000(FFFFFFFFFFFFFC18): >> -54 = FFFFFFFFFFFFFFFF\t<< -54 = FFFFFFFFFFF06000\n-1000(FFFFFFFFFFFFFC18): >> -53 = FFFFFFFFFFFFFFFF\t<< -53 = FFFFFFFFFFE0C000\n-1000(FFFFFFFFFFFFFC18): >> -52 = FFFFFFFFFFFFFFFF\t<< -52 = FFFFFFFFFFC18000\n-1000(FFFFFFFFFFFFFC18): >> -51 = FFFFFFFFFFFFFFFF\t<< -51 = FFFFFFFFFF830000\n-1000(FFFFFFFFFFFFFC18): >> -50 = FFFFFFFFFFFFFFFF\t<< -50 = FFFFFFFFFF060000\n-1000(FFFFFFFFFFFFFC18): >> -49 = FFFFFFFFFFFFFFFF\t<< -49 = FFFFFFFFFE0C0000\n-1000(FFFFFFFFFFFFFC18): >> -48 = FFFFFFFFFFFFFFFF\t<< -48 = FFFFFFFFFC180000\n-1000(FFFFFFFFFFFFFC18): >> -47 = FFFFFFFFFFFFFFFF\t<< -47 = FFFFFFFFF8300000\n-1000(FFFFFFFFFFFFFC18): >> -46 = FFFFFFFFFFFFFFFF\t<< -46 = FFFFFFFFF0600000\n-1000(FFFFFFFFFFFFFC18): >> -45 = FFFFFFFFFFFFFFFF\t<< -45 = FFFFFFFFE0C00000\n-1000(FFFFFFFFFFFFFC18): >> -44 = FFFFFFFFFFFFFFFF\t<< -44 = FFFFFFFFC1800000\n-1000(FFFFFFFFFFFFFC18): >> -43 = FFFFFFFFFFFFFFFF\t<< -43 = FFFFFFFF83000000\n-1000(FFFFFFFFFFFFFC18): >> -42 = FFFFFFFFFFFFFFFF\t<< -42 = FFFFFFFF06000000\n-1000(FFFFFFFFFFFFFC18): >> -41 = FFFFFFFFFFFFFFFF\t<< -41 = FFFFFFFE0C000000\n-1000(FFFFFFFFFFFFFC18): >> -40 = FFFFFFFFFFFFFFFF\t<< -40 = FFFFFFFC18000000\n-1000(FFFFFFFFFFFFFC18): >> -39 = FFFFFFFFFFFFFFFF\t<< -39 = FFFFFFF830000000\n-1000(FFFFFFFFFFFFFC18): >> -38 = FFFFFFFFFFFFFFFF\t<< -38 = FFFFFFF060000000\n-1000(FFFFFFFFFFFFFC18): >> -37 = FFFFFFFFFFFFFFFF\t<< -37 = FFFFFFE0C0000000\n-1000(FFFFFFFFFFFFFC18): >> -36 = FFFFFFFFFFFFFFFF\t<< -36 = FFFFFFC180000000\n-1000(FFFFFFFFFFFFFC18): >> -35 = FFFFFFFFFFFFFFFF\t<< -35 = FFFFFF8300000000\n-1000(FFFFFFFFFFFFFC18): >> -34 = FFFFFFFFFFFFFFFF\t<< -34 = FFFFFF0600000000\n-1000(FFFFFFFFFFFFFC18): >> -33 = FFFFFFFFFFFFFFFF\t<< -33 = FFFFFE0C00000000\n-1000(FFFFFFFFFFFFFC18): >> -32 = FFFFFFFFFFFFFFFF\t<< -32 = FFFFFC1800000000\n-1000(FFFFFFFFFFFFFC18): >> -31 = FFFFFFFFFFFFFFFF\t<< -31 = FFFFF83000000000\n-1000(FFFFFFFFFFFFFC18): >> -30 = FFFFFFFFFFFFFFFF\t<< -30 = FFFFF06000000000\n-1000(FFFFFFFFFFFFFC18): >> -29 = FFFFFFFFFFFFFFFF\t<< -29 = FFFFE0C000000000\n-1000(FFFFFFFFFFFFFC18): >> -28 = FFFFFFFFFFFFFFFF\t<< -28 = FFFFC18000000000\n-1000(FFFFFFFFFFFFFC18): >> -27 = FFFFFFFFFFFFFFFF\t<< -27 = FFFF830000000000\n-1000(FFFFFFFFFFFFFC18): >> -26 = FFFFFFFFFFFFFFFF\t<< -26 = FFFF060000000000\n-1000(FFFFFFFFFFFFFC18): >> -25 = FFFFFFFFFFFFFFFF\t<< -25 = FFFE0C0000000000\n-1000(FFFFFFFFFFFFFC18): >> -24 = FFFFFFFFFFFFFFFF\t<< -24 = FFFC180000000000\n-1000(FFFFFFFFFFFFFC18): >> -23 = FFFFFFFFFFFFFFFF\t<< -23 = FFF8300000000000\n-1000(FFFFFFFFFFFFFC18): >> -22 = FFFFFFFFFFFFFFFF\t<< -22 = FFF0600000000000\n-1000(FFFFFFFFFFFFFC18): >> -21 = FFFFFFFFFFFFFFFF\t<< -21 = FFE0C00000000000\n-1000(FFFFFFFFFFFFFC18): >> -20 = FFFFFFFFFFFFFFFF\t<< -20 = FFC1800000000000\n-1000(FFFFFFFFFFFFFC18): >> -19 = FFFFFFFFFFFFFFFF\t<< -19 = FF83000000000000\n-1000(FFFFFFFFFFFFFC18): >> -18 = FFFFFFFFFFFFFFFF\t<< -18 = FF06000000000000\n-1000(FFFFFFFFFFFFFC18): >> -17 = FFFFFFFFFFFFFFFF\t<< -17 = FE0C000000000000\n-1000(FFFFFFFFFFFFFC18): >> -16 = FFFFFFFFFFFFFFFF\t<< -16 = FC18000000000000\n-1000(FFFFFFFFFFFFFC18): >> -15 = FFFFFFFFFFFFFFFF\t<< -15 = F830000000000000\n-1000(FFFFFFFFFFFFFC18): >> -14 = FFFFFFFFFFFFFFFF\t<< -14 = F060000000000000\n-1000(FFFFFFFFFFFFFC18): >> -13 = FFFFFFFFFFFFFFFF\t<< -13 = E0C0000000000000\n-1000(FFFFFFFFFFFFFC18): >> -12 = FFFFFFFFFFFFFFFF\t<< -12 = C180000000000000\n-1000(FFFFFFFFFFFFFC18): >> -11 = FFFFFFFFFFFFFFFF\t<< -11 = 8300000000000000\n-1000(FFFFFFFFFFFFFC18): >> -10 = FFFFFFFFFFFFFFFF\t<< -10 = 600000000000000\n-1000(FFFFFFFFFFFFFC18): >> -9 = FFFFFFFFFFFFFFFF\t<< -9 = C00000000000000\n-1000(FFFFFFFFFFFFFC18): >> -8 = FFFFFFFFFFFFFFFF\t<< -8 = 1800000000000000\n-1000(FFFFFFFFFFFFFC18): >> -7 = FFFFFFFFFFFFFFFF\t<< -7 = 3000000000000000\n-1000(FFFFFFFFFFFFFC18): >> -6 = FFFFFFFFFFFFFFFF\t<< -6 = 6000000000000000\n-1000(FFFFFFFFFFFFFC18): >> -5 = FFFFFFFFFFFFFFFF\t<< -5 = C000000000000000\n-1000(FFFFFFFFFFFFFC18): >> -4 = FFFFFFFFFFFFFFFF\t<< -4 = 8000000000000000\n-1000(FFFFFFFFFFFFFC18): >> -3 = FFFFFFFFFFFFFFFF\t<< -3 = 00000000\n-1000(FFFFFFFFFFFFFC18): >> -2 = FFFFFFFFFFFFFFFF\t<< -2 = 00000000\n-1000(FFFFFFFFFFFFFC18): >> -1 = FFFFFFFFFFFFFFFF\t<< -1 = 00000000\n-1000(FFFFFFFFFFFFFC18): >>  0 = FFFFFFFFFFFFFC18\t<<  0 = FFFFFFFFFFFFFC18\n-1000(FFFFFFFFFFFFFC18): >>  1 = FFFFFFFFFFFFFE0C\t<<  1 = FFFFFFFFFFFFF830\n-1000(FFFFFFFFFFFFFC18): >>  2 = FFFFFFFFFFFFFF06\t<<  2 = FFFFFFFFFFFFF060\n-1000(FFFFFFFFFFFFFC18): >>  3 = FFFFFFFFFFFFFF83\t<<  3 = FFFFFFFFFFFFE0C0\n-1000(FFFFFFFFFFFFFC18): >>  4 = FFFFFFFFFFFFFFC1\t<<  4 = FFFFFFFFFFFFC180\n-1000(FFFFFFFFFFFFFC18): >>  5 = FFFFFFFFFFFFFFE0\t<<  5 = FFFFFFFFFFFF8300\n-1000(FFFFFFFFFFFFFC18): >>  6 = FFFFFFFFFFFFFFF0\t<<  6 = FFFFFFFFFFFF0600\n-1000(FFFFFFFFFFFFFC18): >>  7 = FFFFFFFFFFFFFFF8\t<<  7 = FFFFFFFFFFFE0C00\n-1000(FFFFFFFFFFFFFC18): >>  8 = FFFFFFFFFFFFFFFC\t<<  8 = FFFFFFFFFFFC1800\n-1000(FFFFFFFFFFFFFC18): >>  9 = FFFFFFFFFFFFFFFE\t<<  9 = FFFFFFFFFFF83000\n-1000(FFFFFFFFFFFFFC18): >> 10 = FFFFFFFFFFFFFFFF\t<< 10 = FFFFFFFFFFF06000\n-1000(FFFFFFFFFFFFFC18): >> 11 = FFFFFFFFFFFFFFFF\t<< 11 = FFFFFFFFFFE0C000\n-1000(FFFFFFFFFFFFFC18): >> 12 = FFFFFFFFFFFFFFFF\t<< 12 = FFFFFFFFFFC18000\n-1000(FFFFFFFFFFFFFC18): >> 13 = FFFFFFFFFFFFFFFF\t<< 13 = FFFFFFFFFF830000\n-1000(FFFFFFFFFFFFFC18): >> 14 = FFFFFFFFFFFFFFFF\t<< 14 = FFFFFFFFFF060000\n-1000(FFFFFFFFFFFFFC18): >> 15 = FFFFFFFFFFFFFFFF\t<< 15 = FFFFFFFFFE0C0000\n-1000(FFFFFFFFFFFFFC18): >> 16 = FFFFFFFFFFFFFFFF\t<< 16 = FFFFFFFFFC180000\n-1000(FFFFFFFFFFFFFC18): >> 17 = FFFFFFFFFFFFFFFF\t<< 17 = FFFFFFFFF8300000\n-1000(FFFFFFFFFFFFFC18): >> 18 = FFFFFFFFFFFFFFFF\t<< 18 = FFFFFFFFF0600000\n-1000(FFFFFFFFFFFFFC18): >> 19 = FFFFFFFFFFFFFFFF\t<< 19 = FFFFFFFFE0C00000\n-1000(FFFFFFFFFFFFFC18): >> 20 = FFFFFFFFFFFFFFFF\t<< 20 = FFFFFFFFC1800000\n-1000(FFFFFFFFFFFFFC18): >> 21 = FFFFFFFFFFFFFFFF\t<< 21 = FFFFFFFF83000000\n-1000(FFFFFFFFFFFFFC18): >> 22 = FFFFFFFFFFFFFFFF\t<< 22 = FFFFFFFF06000000\n-1000(FFFFFFFFFFFFFC18): >> 23 = FFFFFFFFFFFFFFFF\t<< 23 = FFFFFFFE0C000000\n-1000(FFFFFFFFFFFFFC18): >> 24 = FFFFFFFFFFFFFFFF\t<< 24 = FFFFFFFC18000000\n-1000(FFFFFFFFFFFFFC18): >> 25 = FFFFFFFFFFFFFFFF\t<< 25 = FFFFFFF830000000\n-1000(FFFFFFFFFFFFFC18): >> 26 = FFFFFFFFFFFFFFFF\t<< 26 = FFFFFFF060000000\n-1000(FFFFFFFFFFFFFC18): >> 27 = FFFFFFFFFFFFFFFF\t<< 27 = FFFFFFE0C0000000\n-1000(FFFFFFFFFFFFFC18): >> 28 = FFFFFFFFFFFFFFFF\t<< 28 = FFFFFFC180000000\n-1000(FFFFFFFFFFFFFC18): >> 29 = FFFFFFFFFFFFFFFF\t<< 29 = FFFFFF8300000000\n-1000(FFFFFFFFFFFFFC18): >> 30 = FFFFFFFFFFFFFFFF\t<< 30 = FFFFFF0600000000\n-1000(FFFFFFFFFFFFFC18): >> 31 = FFFFFFFFFFFFFFFF\t<< 31 = FFFFFE0C00000000\n-1000(FFFFFFFFFFFFFC18): >> 32 = FFFFFFFFFFFFFFFF\t<< 32 = FFFFFC1800000000\n-1000(FFFFFFFFFFFFFC18): >> 33 = FFFFFFFFFFFFFFFF\t<< 33 = FFFFF83000000000\n-1000(FFFFFFFFFFFFFC18): >> 34 = FFFFFFFFFFFFFFFF\t<< 34 = FFFFF06000000000\n-1000(FFFFFFFFFFFFFC18): >> 35 = FFFFFFFFFFFFFFFF\t<< 35 = FFFFE0C000000000\n-1000(FFFFFFFFFFFFFC18): >> 36 = FFFFFFFFFFFFFFFF\t<< 36 = FFFFC18000000000\n-1000(FFFFFFFFFFFFFC18): >> 37 = FFFFFFFFFFFFFFFF\t<< 37 = FFFF830000000000\n-1000(FFFFFFFFFFFFFC18): >> 38 = FFFFFFFFFFFFFFFF\t<< 38 = FFFF060000000000\n-1000(FFFFFFFFFFFFFC18): >> 39 = FFFFFFFFFFFFFFFF\t<< 39 = FFFE0C0000000000\n-1000(FFFFFFFFFFFFFC18): >> 40 = FFFFFFFFFFFFFFFF\t<< 40 = FFFC180000000000\n-1000(FFFFFFFFFFFFFC18): >> 41 = FFFFFFFFFFFFFFFF\t<< 41 = FFF8300000000000\n-1000(FFFFFFFFFFFFFC18): >> 42 = FFFFFFFFFFFFFFFF\t<< 42 = FFF0600000000000\n-1000(FFFFFFFFFFFFFC18): >> 43 = FFFFFFFFFFFFFFFF\t<< 43 = FFE0C00000000000\n-1000(FFFFFFFFFFFFFC18): >> 44 = FFFFFFFFFFFFFFFF\t<< 44 = FFC1800000000000\n-1000(FFFFFFFFFFFFFC18): >> 45 = FFFFFFFFFFFFFFFF\t<< 45 = FF83000000000000\n-1000(FFFFFFFFFFFFFC18): >> 46 = FFFFFFFFFFFFFFFF\t<< 46 = FF06000000000000\n-1000(FFFFFFFFFFFFFC18): >> 47 = FFFFFFFFFFFFFFFF\t<< 47 = FE0C000000000000\n-1000(FFFFFFFFFFFFFC18): >> 48 = FFFFFFFFFFFFFFFF\t<< 48 = FC18000000000000\n-1000(FFFFFFFFFFFFFC18): >> 49 = FFFFFFFFFFFFFFFF\t<< 49 = F830000000000000\n-1000(FFFFFFFFFFFFFC18): >> 50 = FFFFFFFFFFFFFFFF\t<< 50 = F060000000000000\n-1000(FFFFFFFFFFFFFC18): >> 51 = FFFFFFFFFFFFFFFF\t<< 51 = E0C0000000000000\n-1000(FFFFFFFFFFFFFC18): >> 52 = FFFFFFFFFFFFFFFF\t<< 52 = C180000000000000\n-1000(FFFFFFFFFFFFFC18): >> 53 = FFFFFFFFFFFFFFFF\t<< 53 = 8300000000000000\n-1000(FFFFFFFFFFFFFC18): >> 54 = FFFFFFFFFFFFFFFF\t<< 54 = 600000000000000\n-1000(FFFFFFFFFFFFFC18): >> 55 = FFFFFFFFFFFFFFFF\t<< 55 = C00000000000000\n-1000(FFFFFFFFFFFFFC18): >> 56 = FFFFFFFFFFFFFFFF\t<< 56 = 1800000000000000\n-1000(FFFFFFFFFFFFFC18): >> 57 = FFFFFFFFFFFFFFFF\t<< 57 = 3000000000000000\n-1000(FFFFFFFFFFFFFC18): >> 58 = FFFFFFFFFFFFFFFF\t<< 58 = 6000000000000000\n-1000(FFFFFFFFFFFFFC18): >> 59 = FFFFFFFFFFFFFFFF\t<< 59 = C000000000000000\n-1000(FFFFFFFFFFFFFC18): >> 60 = FFFFFFFFFFFFFFFF\t<< 60 = 8000000000000000\n-1000(FFFFFFFFFFFFFC18): >> 61 = FFFFFFFFFFFFFFFF\t<< 61 = 00000000\n-1000(FFFFFFFFFFFFFC18): >> 62 = FFFFFFFFFFFFFFFF\t<< 62 = 00000000\n-1000(FFFFFFFFFFFFFC18): >> 63 = FFFFFFFFFFFFFFFF\t<< 63 = 00000000\n-1000(FFFFFFFFFFFFFC18): >> 64 = FFFFFFFFFFFFFC18\t<< 64 = FFFFFFFFFFFFFC18\n-1000(FFFFFFFFFFFFFC18): >> 65 = FFFFFFFFFFFFFE0C\t<< 65 = FFFFFFFFFFFFF830\n-129, 63\n-128, 0\n-127, 1\n-126, 2\n-125, 3\n-124, 4\n-123, 5\n-122, 6\n-121, 7\n-120, 8\n-119, 9\n-118, 10\n-117, 11\n-116, 12\n-115, 13\n-114, 14\n-113, 15\n-112, 16\n-111, 17\n-110, 18\n-109, 19\n-108, 20\n-107, 21\n-106, 22\n-105, 23\n-104, 24\n-103, 25\n-102, 26\n-101, 27\n-100, 28\n-99, 29\n-98, 30\n-97, 31\n-96, 32\n-95, 33\n-94, 34\n-93, 35\n-92, 36\n-91, 37\n-90, 38\n-89, 39\n-88, 40\n-87, 41\n-86, 42\n-85, 43\n-84, 44\n-83, 45\n-82, 46\n-81, 47\n-80, 48\n-79, 49\n-78, 50\n-77, 51\n-76, 52\n-75, 53\n-74, 54\n-73, 55\n-72, 56\n-71, 57\n-70, 58\n-69, 59\n-68, 60\n-67, 61\n-66, 62\n-65, 63\n-64, 0\n-63, 1\n-62, 2\n-61, 3\n-60, 4\n-59, 5\n-58, 6\n-57, 7\n-56, 8\n-55, 9\n-54, 10\n-53, 11\n-52, 12\n-51, 13\n-50, 14\n-49, 15\n-48, 16\n-47, 17\n-46, 18\n-45, 19\n-44, 20\n-43, 21\n-42, 22\n-41, 23\n-40, 24\n-39, 25\n-38, 26\n-37, 27\n-36, 28\n-35, 29\n-34, 30\n-33, 31\n-32, 32\n-31, 33\n-30, 34\n-29, 35\n-28, 36\n-27, 37\n-26, 38\n-25, 39\n-24, 40\n-23, 41\n-22, 42\n-21, 43\n-20, 44\n-19, 45\n-18, 46\n-17, 47\n-16, 48\n-15, 49\n-14, 50\n-13, 51\n-12, 52\n-11, 53\n-10, 54\n-9, 55\n-8, 56\n-7, 57\n-6, 58\n-5, 59\n-4, 60\n-3, 61\n-2, 62\n-1, 63\n0, 0\n1, 1\n2, 2\n3, 3\n4, 4\n5, 5\n6, 6\n7, 7\n8, 8\n9, 9\n10, 10\n11, 11\n12, 12\n13, 13\n14, 14\n15, 15\n16, 16\n17, 17\n18, 18\n19, 19\n20, 20\n21, 21\n22, 22\n23, 23\n24, 24\n25, 25\n26, 26\n27, 27\n28, 28\n29, 29\n30, 30\n31, 31\n32, 32\n33, 33\n34, 34\n35, 35\n36, 36\n37, 37\n38, 38\n39, 39\n40, 40\n41, 41\n42, 42\n43, 43\n44, 44\n45, 45\n46, 46\n47, 47\n48, 48\n49, 49\n50, 50\n51, 51\n52, 52\n53, 53\n54, 54\n55, 55\n56, 56\n57, 57\n58, 58\n59, 59\n60, 60\n61, 61\n62, 62\n63, 63\n64, 0\n65, 1\n66, 2\n67, 3\n68, 4\n69, 5\n70, 6\n71, 7\n72, 8\n73, 9\n74, 10\n75, 11\n76, 12\n77, 13\n78, 14\n79, 15\n80, 16\n81, 17\n82, 18\n83, 19\n84, 20\n85, 21\n86, 22\n87, 23\n88, 24\n89, 25\n90, 26\n91, 27\n92, 28\n93, 29\n94, 30\n95, 31\n96, 32\n97, 33\n98, 34\n99, 35\n100, 36\n101, 37\n102, 38\n103, 39\n104, 40\n105, 41\n106, 42\n107, 43\n108, 44\n109, 45\n110, 46\n111, 47\n112, 48\n113, 49\n114, 50\n115, 51\n116, 52\n117, 53\n118, 54\n119, 55\n120, 56\n121, 57\n122, 58\n123, 59\n124, 60\n125, 61\n126, 62\n127, 63\n128, 0\n129, 1"
  },
  {
    "path": "tests/Expressions/Bitwise_and_or_xor_Operators/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Bitwise_and_or_xor_Operators/bitwise_and_or_xor.php",
    "content": "<?hh // strict\n\nnamespace NS_bitwise_and_or_xor;\n\nfunction main(): void {\n///*\n  echo \"======= check for even/odd integer values by inspecting the low-order bit ========\\n\";\n\n  for ($i = -5; $i <= 5; ++$i) {\n    echo \"$i is \".((($i & 1) == 1) ? \"odd\\n\" : \"even\\n\");\n  }\n\n  $upCaseLetter = 0x41;\t// letter 'A'\n  $lowCaseLetter = $upCaseLetter | 0x20;\t// set the 6th bit\n  printf(\"Lowercase equivalent of '%c' is '%c'\\n\", $upCaseLetter, $lowCaseLetter);\n\n  $lowCaseLetter = 0x73;\t// letter 's'\n  $upCaseLetter = $lowCaseLetter & ~0x20;\t// clear the 6th bit\n  printf(\"Uppercase equivalent of '%c' is '%c'\\n\", $lowCaseLetter, $upCaseLetter);\n//*/\n///*\n  echo \"======= swap two integers ========\\n\";\n\n  $v1 = 1234; $v2 = -987;\n  printf(\"\\$v1 = %d, \\$v2 = %d\\n\", $v1, $v2);\n  $v1 = $v1 ^ $v2;\n  $v2 = $v1 ^ $v2;\n  $v1 = $v1 ^ $v2;\n  printf(\"\\$v1 = %d, \\$v2 = %d\\n\", $v1, $v2);\n\n  echo \"======= misc stuff ========\\n\";\n\n  printf(\"0b101101 & 0b111 = 0b%b\\n\", 0b101111 & 0b101);\n  printf(\"0b101101 | 0b111 = 0b%b\\n\", 0b101111 | 0b101);\n  printf(\"0b101101 ^ 0b111 = 0b%b\\n\", 0b101111 ^ 0b101);\n//*/\n///*\n  echo \"======= Test all kinds of scalar values to see which are ints or can be implicitly converted ========\\n\";\n\n// those elements comments out are rejected; only int operands are accepted\n\n  $scalarValueList = array(-3, 0, 1000 /*, 1.234, 0.0, true, false, null, \"123\", 'xx', \"\"*/);\n  foreach ($scalarValueList as $v) {\n    echo \"$v & 123 = \"; var_dump($v & 123);\n    echo \"$v | 123 = \"; var_dump($v | 123);\n    echo \"$v ^ 123 = \"; var_dump($v ^ 123);\n  }\n//*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Bitwise_and_or_xor_Operators/bitwise_and_or_xor.php.expect",
    "content": "======= check for even/odd integer values by inspecting the low-order bit ========\n-5 is odd\n-4 is even\n-3 is odd\n-2 is even\n-1 is odd\n0 is even\n1 is odd\n2 is even\n3 is odd\n4 is even\n5 is odd\nLowercase equivalent of 'A' is 'a'\nUppercase equivalent of 's' is 'S'\n======= swap two integers ========\n$v1 = 1234, $v2 = -987\n$v1 = -987, $v2 = 1234\n======= misc stuff ========\n0b101101 & 0b111 = 0b101\n0b101101 | 0b111 = 0b101111\n0b101101 ^ 0b111 = 0b101010\n======= Test all kinds of scalar values to see which are ints or can be implicitly converted ========\n-3 & 123 = int(121)\n-3 | 123 = int(-1)\n-3 ^ 123 = int(-122)\n0 & 123 = int(0)\n0 | 123 = int(123)\n0 ^ 123 = int(123)\n1000 & 123 = int(104)\n1000 | 123 = int(1019)\n1000 ^ 123 = int(915)"
  },
  {
    "path": "tests/Expressions/Coalesce Operator/coalesce.php",
    "content": "<?hh // strict\n\nnamespace NS_coalesce;\n\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2015-2016 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\nfunction foo(): void {\n  echo \"executed!\", PHP_EOL;\n}\n\nfunction main(): void {\n  $arr = [\"foo\" => \"bar\", \"qux\" => null];\n  $obj = (object)$arr;\n\n  $a = $arr[\"foo\"] ?? \"bang\"; // \"bar\" as $arr[\"foo\"] is set and not null\n  $a = $arr[\"qux\"] ?? \"bang\"; // \"bang\" as $arr[\"qux\"] is null\n  $a = $arr[\"bing\"] ?? \"bang\"; // \"bang\" as $arr[\"bing\"] is not set\n\n  $a = $obj->foo ?? \"bang\"; // \"bar\" as $obj->foo is set and not null\n  $a = $obj->qux ?? \"bang\"; // \"bang\" as $obj->qux is null\n  $a = $obj->bing ?? \"bang\"; // \"bang\" as $obj->bing is not set\n\n  $a = null ?? $arr[\"bing\"] ?? 2; // 2 as null is null, and $arr[\"bing\"] is not set\n  var_dump(true ?? foo()); // outputs bool(true), \"executed!\" does not appear as it short-circuits\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Coalesce Operator/coalesce.php.expect",
    "content": "bool(true)\n"
  },
  {
    "path": "tests/Expressions/Conditional_Operator/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Conditional_Operator/conditional.php",
    "content": "<?hh // strict\n\nnamespace NS_conditional;\n\nfunction f(int $a): int { echo \"inside f(int $a)\\n\"; return 0;}\n\nfunction main(): void {\n/*\n  echo \"======= check for even integer values by inspecting the low-order bit =======\\n\";\n\n  for ($i = -5; $i <= 5; ++$i) {\n    echo \"$i is \".((($i & 1) == 1) ? \"odd\\n\" : \"even\\n\");\n  }\n\n*/\n/*\n  echo \"======= some simple examples =======\\n\";\n\n  $a = 10 ? 100 : \"Hello\";\n  var_dump($a);\n  $a = 0 ? 100 : \"Hello\";\n  var_dump($a);\n\n*/\n/*\n  echo \"======= omit 2nd operand =======\\n\";\n\n  $a = 10 ? : \"Hello\";\n  var_dump($a);\n  $a = 0 ? : \"Hello\";\n  var_dump($a);\n\n*/\n/*\n  echo \"======= put a side effect in the 1st operand =======\\n\";\n\n  $i = 5;\n  $a = $i++ ? : \"red\";\n  var_dump($a);\n  $i = 5;\n  $a = ++$i ? : \"red\";\n  var_dump($a);\n\n*/\n/*\n  echo \"======= sequence point =======\\n\";\n\n  $i = 5;\n  $i++ ? f($i) : f(++$i);\n  $i = 0;\n  $i++ ? f($i) : f(++$i);\n\n*/\n/*\n  echo \"======= check associativity -- NOT the same as C/C++ =======\\n\";\n\n  $a = true ? -1 : 1 ? 10 : 20;\n  $a = (true ? -1 : 1) ? 10 : 20;\n  var_dump($a);\n  $a = true ? -1 : (1 ? 10 : 20);\n*/\n/*\n  echo \"======= Test all kinds of scalar values to see which are ints or can be implicitly converted =======\\n\";\n\n  $scalarValueList = array(10, -100, 0, 1.234, 0.0, true, false, null, \"123\", 'xx', \"\");\n  foreach ($scalarValueList as $v) {\n    echo \"\\$v = $v, \";\n    $a = $v ? 100 : \"Hello\";\n    var_dump($a);\n  }\n\n*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Conditional_Operator/conditional.php.expect",
    "content": ""
  },
  {
    "path": "tests/Expressions/Equality_Operators/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Equality_Operators/Testfile1.txt",
    "content": "Once upon a time,\nin a land\nfar,   \nfar away,  \nthere lived an ogre called Big Bad Bruce.\n"
  },
  {
    "path": "tests/Expressions/Equality_Operators/Testfile2.txt",
    "content": "Once upon a time,\nin a land\nfar,   \nfar away,  \nthere lived an ogre called Big Bad Bruce.\n"
  },
  {
    "path": "tests/Expressions/Equality_Operators/comparisons.php",
    "content": "<?hh // strict\n\nnamespace NS_equality_comparisons;\n\nfunction doit1(num $p1_num, ?int $p2_nint): void {\n/*\n  echo \"====== checkout the type and value of the result ======\\n\\n\";\n\n  $a = 10 < 20;\n  var_dump($a);\t// bool(true)\n  $a = 10 >= 20;\n  var_dump($a);\t// bool(false)\t\n  $a = \"zz\" > \"xx\";\n  var_dump($a);\t// bool(true)\n*/\n\n/*\n  echo \"====== mix-n-match operand types ======\\n\\n\";\n\n  var_dump(null == false);\t// bool(true)\n  var_dump(null === false);\t// bool(false)\n\n  var_dump(null == true);\t\t// bool(false)\n  var_dump(null === true);\t// bool(false)\n\n  var_dump(false == 0);\t\t// bool(true)\n//  var_dump(false === 0);\t\t// always false\n\n  var_dump(true == 1);\t\t// bool(true)\n//  var_dump(true === 1);\t\t// always false\n\n  var_dump(true == 100);\t\t// bool(true)\n//  var_dump(true === 100);\t\t// always false\n\n  var_dump(null != 1.23);\t\t// bool(true)\n  var_dump(null !== 1.23);\t// bool(true)\n\n  var_dump(false != \"\");\t\t// bool(false)\n//  var_dump(false !== \"\");\t\t// always true\n\n  var_dump(false != \"0\");\t\t// bool(false)\n//  var_dump(false !== \"0\");\t// always true\n\n  var_dump(false != \"123\");\t// bool(true)\n//  var_dump(false !== \"123\");\t// always true\n\n  var_dump(false != \"X\");\t\t// bool(true)\n//  var_dump(false !== \"X\");\t// always true\n\n  var_dump($p1_num == $p2_nint);\t// bool(false)\n  var_dump($p1_num === $p2_nint);\t// bool(false)\n\n  var_dump($p1_num != $p2_nint);\t// bool(true)\n  var_dump($p1_num !== $p2_nint);\t// bool(true)\n*/\n\n/*\n  echo \"\\n====== compare arithmetic ops ======\\n\\n\";\n\n  var_dump(100 == 12.3);\t\t// false\n  var_dump(100 != $p1_num);\t// true\n  var_dump($p1_num === 5.6);\t// false when $p1_num == 11\n*/\n\n/*\n  echo \"\\n====== compare Boolean ops ======\\n\\n\";\n\n  var_dump(true == false);\t// false\n  var_dump(true != false);\t// true\n  var_dump(false === true);\t// false\n*/\n\n/*\n  echo \"\\n====== compare null ops ======\\n\\n\";\n\n  var_dump(null === null);\t// true\n  var_dump(null != null);\t\t// false\n*/\n\n/*\n  echo \"\\n====== compare null with nullable ======\\n\\n\";\n\n// when $p2_nint == null\n\n  var_dump($p2_nint);\t\t// null\n  var_dump(null == $p2_nint);\t// true\n  var_dump(null !== $p2_nint);\t// false\n  var_dump(null != $p2_nint);\t// false\n  var_dump(null === $p2_nint);\t// true\n\n// when $p2_nint != null and non-zero, get false, true, true, false, so is doing numeric comparison\n\n// when $p2_nint != null and is zero, get true, true, false, false, so can't distinguish between null and zero\n*/\n\n/*\n  echo \"\\n====== compare numeric-string ops ======\\n\\n\";\n\n  var_dump('123' == '4');\t\t// false\n  var_dump('123' == 4);\t\t// false\n  var_dump(123 != '4');\t\t// true\n  var_dump('123' == 123);\t\t// true; is doing a numeric comparison\n*/\n\n/*\n  echo \"\\n====== compare non-numeric-string ops ======\\n\\n\";\n\n  $oper1 = array(\"\", \"a\", \"aa\", \"a0\", \"aA\");\n  $oper2 = array(\"\", \"ab\", \"abc\", \"A\", \"AB\");\n\n  foreach ($oper1 as $e1) {\n    foreach ($oper2 as $e2) {\n      echo \"{$e1} ==  {$e2}  result: \"; var_dump($e1 == $e2);\n      echo \"{$e2} !=  {$e1}  result: \"; var_dump($e2 != $e1);\n      echo \"{$e1} === {$e2}  result: \"; var_dump($e1 === $e2);\n      echo \"{$e2} !== {$e1}  result: \"; var_dump($e2 !== $e1);\n    }\n    echo \"-------------------------------------\\n\";\n  }\n*/\n\n/*\n  echo \"\\n====== compare resource ops ======\\n\\n\";\n\n  $infile1 = fopen(\"Testfile1.txt\", 'r');\n  $infile2 = fopen(\"Testfile2.txt\", 'r');\n  var_dump($infile1, $infile2);\n\n  var_dump($infile1 == $infile2);\t\t// false (4 == 5)\n  var_dump($infile1 !== $infile2);\t// true (4 !== 5)\n*/\n}\n\nclass Button {}\nclass CustomButton extends Button {}\n\nfunction array_proc(\n  array<int> $p1, array<int> $p2,\n  array<float> $p3, array<num> $p4,\n  array<Button> $p5, array<CustomButton> $p6,\n  array<int, int> $p7,\n  array<int, string> $p8, array<int, string> $p9,\n  array<int, bool> $p10,\n  array<string, int> $p11, array<string, int> $p12,\n  array<bool> $p13\n): void {\n/*\n  echo \"============= vector-like arrays ================\\n\";\n\n  echo \"result of p1 == p1 = \"; var_dump($p1 == $p1);\t// true\n  echo \"result of p1 === p1 = \"; var_dump($p1 === $p1);\t// true\n\n  echo \"result of p1 == p2 = \"; var_dump($p1 == $p2);\t// false\n  echo \"result of p1 == p3 = \"; var_dump($p1 == $p3);\t// true, 66 -> 66.0\n  echo \"result of p4 != p1 = \"; var_dump($p4 != $p1);\t// true\n  echo \"result of p4 === p3 = \"; var_dump($p4 === $p3);\t// false\n  echo \"result of p5 !== p6 = \"; var_dump($p5 !== $p6);\t// true\n\n  echo \"result of p1 == p13 = \"; var_dump($p1 == $p13);\t// false\n//  echo \"result of p1 == p5 = \"; var_dump($p1 == $p5);\t// tries to convert object to int & fails\n*/\n\n///*\n  echo \"qq============= map-like arrays ================\\n\";\n\n  $v = $p1 == $p7;\t// array<int> == array<int, int> is allowed !!!\n\t\t\t\t// can't mix vector-like and map-like arrays even with same key/value types\n  echo \"result of p1 == p7 = \"; var_dump($v);\n\n  $v = $p8 == $p9;\t// array<int, string> == array<int, string> okay\n  echo \"result of p8 == p9 = \"; var_dump($v);\n\n  $v = $p7 == $p10;\t// array<int, int> == array<int, bool> is allowed !!!\n  echo \"result of p7 == p10 = \"; var_dump($v);\n\n  $v = $p11 == $p12;\t// array<string, int> == array<string, int> okay\n  echo \"result of p11 == p12 = \"; var_dump($v);\n//*/\n\n///*\n  echo \"============= concating to an empty/untyped array ================\\n\";\n\n  $p = $p1 == array();\t// array<int> == array() allowed;\n  echo \"result of p1 == array() = \"; var_dump($p);\n  $p = array() == $p2;\t// array<int> == array() allowed;\n  echo \"result of array() == p1 = \"; var_dump($p);\n\n  $v = $p10 == array();\t// array<int, bool> == array() allowed;\n  echo \"result of p10 == array() = \"; var_dump($v);\n\n  $v = $p11 == array();\t// array<string, int> == array() allowed\n  echo \"result of p11 == array() = \"; var_dump($v);\n\n  $p = array() == array();// array() == array() allowed;\n  echo \"result of array() == array() = \"; var_dump($p);\n//*/\n}\n\nfunction main(): void {\n  doit1(11, null);\n\n  array_proc(\n    array(66),\n    array(66, 200),\n    array(66.0),\n    array(66, 2.5),\n    array(new Button()), array(new CustomButton()),\n    array(6 => 66, 12 => 22),\n    array(2 => 'aa', 12 => 'bb'), array(-4 => 'cc', 6 => 'dd'), \n    array(-3 => true),\n    array('red' => 12, 'green' => 7), array('blue' => 3),\n    array(true, false) \n  );\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Equality_Operators/comparisons.php.expect",
    "content": "qq============= map-like arrays ================\nresult of p1 == p7 = bool(false)\nresult of p8 == p9 = bool(false)\nresult of p7 == p10 = bool(false)\nresult of p11 == p12 = bool(false)\n============= concating to an empty/untyped array ================\nresult of p1 == array() = bool(false)\nresult of array() == p1 = bool(false)\nresult of p10 == array() = bool(false)\nresult of p11 == array() = bool(false)\nresult of array() == array() = bool(true)"
  },
  {
    "path": "tests/Expressions/Equality_Operators/equality_comparison_of_objects.php",
    "content": "<?hh // strict\n\nnamespace NS_equality_comparison_of_objects;\n\nclass C1 {}\nclass C2 {}\nclass C3 { public int $x = -1; }\nclass C4 { public int $y = -10; public int $x = -11; }\n\nfunction main(): void {\n  $c1a = new C1(); // var_dump($c1a);\n  $c1b = new C1(); // var_dump($c1b);\n  $c2 = new C2();  // var_dump($c2);\n///*\n  echo \"\\n===== compare instances of different object types =====\\n\\n\";\n\n  var_dump($c1a == $c2);\t// false\n  var_dump($c1a === $c2);\t// false\n  var_dump($c1a != $c2);\t// true\n  var_dump($c1a !== $c2);\t// true\n//*/\n\n///*\n  echo \"\\n===== compare instances of the same (empty) object type =====\\n\\n\";\n\n  var_dump($c1a == $c1b);\t// true\n  var_dump($c1a === $c1b);// false\n  var_dump($c1a === $c1a);// true; same instance\n  var_dump($c1a != $c1b);\t// false\n  var_dump($c1a !== $c1b);// true\n//*/\n\n  $c3a = new C3(); $c3a->x = 5; // var_dump($c3a);\n  $c3b = new C3(); $c3b->x = 5; // var_dump($c3b);\n\n///*\n  echo \"\\n===== compare instances of the same object type with same values =====\\n\\n\";\n\n  var_dump($c3a == $c3b);\t// true)\n  var_dump($c3a === $c3b);// false\n  var_dump($c3a === $c3a);// true; same instance\n  var_dump($c3a != $c3b);\t// false\n  var_dump($c3a !== $c3b);// true\n//*/\n\n///*\n  echo \"\\n===== compare instances of the same object type with diff values =====\\n\\n\";\n\n  $c3b->x = 7; // var_dump($c3a); var_dump($c3b);\n\n  var_dump($c3a == $c3b);\t// false\n  var_dump($c3a === $c3b);// false\n  var_dump($c3a === $c3a);// true; same instance\n  var_dump($c3a != $c3b);\t// true\n  var_dump($c3a !== $c3b);// true\n//*/\n\n///*\n  echo \"\\n===== compare instances of the same object type with a pair of diff values =====\\n\\n\";\n\n  $c4a = new C4(); $c4a->x = 3; $c4a->y = 6; // var_dump($c4a);\n  $c4b = new C4(); $c4b->x = 5; $c4b->y = 2; // var_dump($c4b);\n\n  var_dump($c4a == $c4b);\t// false\n  var_dump($c4a === $c4b);// false\n  var_dump($c4a === $c4a);// true; same instance\n  var_dump($c4a != $c4b);\t// true\n  var_dump($c4a !== $c4b);// true\n//*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Equality_Operators/equality_comparison_of_objects.php.expect",
    "content": "\n===== compare instances of different object types =====\n\nbool(false)\nbool(false)\nbool(true)\nbool(true)\n\n===== compare instances of the same (empty) object type =====\n\nbool(true)\nbool(false)\nbool(true)\nbool(false)\nbool(true)\n\n===== compare instances of the same object type with same values =====\n\nbool(true)\nbool(false)\nbool(true)\nbool(false)\nbool(true)\n\n===== compare instances of the same object type with diff values =====\n\nbool(false)\nbool(false)\nbool(true)\nbool(true)\nbool(true)\n\n===== compare instances of the same object type with a pair of diff values =====\n\nbool(false)\nbool(false)\nbool(true)\nbool(true)\nbool(true)"
  },
  {
    "path": "tests/Expressions/Instanceof_Operator/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Instanceof_Operator/instanceof.php",
    "content": "<?hh // strict\n\nnamespace NS_instanceof;\n\nclass C1 {}\nclass C2 {}\nclass D extends C1 {}\n\nfunction f1(): D { return new D(); }\n\ninterface I1 {}\ninterface I2 {}\nclass E1 implements I1, I2 {}\n\nclass C11 {}\nclass C21 {}\nclass D1 extends C11 {}\n\ninterface I11 {}\ninterface I21 {}\nclass E11 implements I11, I21 {}\n\nfunction main(): void {\n///*\n// test using a series of classes, some derived\n\n  $c1 = new C1();\n  $c2 = new C2();\n  $c2b = new C2();\n  $d = new D();\n\n  var_dump($c1 instanceof C1);\n  var_dump($c1 instanceof C2);\n  var_dump($c1 instanceof D);\n\n//  var_dump($c1 instanceof \"C1\");\t// can't be a string literal\n//  var_dump($c1 instanceof \"c1\");\t// can't be a string literal\n  $clName = \"C1\";\n//  var_dump($c1 instanceof $clName);\t// TRUE; can be a string\n  $clName = \"C2\";\n//  var_dump($c1 instanceof $clName);\t// FALSE; can be a string\n\n  var_dump($c2 instanceof $c2b); \n  var_dump($d instanceof $c1); \n  var_dump($c1 instanceof $d); \n\n  echo \"--------------------\\n\";\n\n  var_dump(f1() instanceof C1);\n  var_dump(f1() instanceof C2);\n  var_dump(f1() instanceof D);\n\n  echo \"--------------------\\n\";\n\n  var_dump($c2 instanceof C1);\n  var_dump($c2 instanceof C2);\n  var_dump($c2 instanceof D);\n\n  echo \"--------------------\\n\";\n\n  var_dump($d instanceof C1);\n  var_dump($d instanceof C2);\n  var_dump($d instanceof D);\n\n  echo \"------- Interfaces -------------\\n\";\n\n// test using a series of interfaces\n\n  $e1 = new E1();\n\n  var_dump($e1 instanceof E1);\n  var_dump($e1 instanceof I1);\t// Yes\n  var_dump($e1 instanceof I2);\t// Yes\n  $iName = \"I2\";\n//  var_dump($e1 instanceof $iName);\n//  var_dump($e1 instanceof \"I2\");\t// No string literal allowed\n\n  echo \"------- Non-Instances -------------\\n\";\n\n// test using variables that are not instances\n\n  var_dump($d instanceof I1);\t\t// of course not!\n  $v = 10;\n  var_dump($v instanceof C1);\t\t// of course not!\n  $v = 1.234;\n  var_dump($v instanceof C1);\t\t// of course not!\n  $v = null;\n  var_dump($v instanceof C1);\t\t// of course not!\n\n  echo \"------- Non-class/Non-interface types -------------\\n\";\n\n/*\n// test against non-class/non-interface \"types\" and even non-types\n\n  $v = true;\n  var_dump($v instanceof bool);\t\t// false!\n  var_dump($v instanceof int);\t\t// false!\n  var_dump($v instanceof float);\t// false!\n  var_dump($v instanceof string);\t// false!\n*/\n//*/\n  $c11 = new C11();\n  $c21 = new C21();\n  $d = new D1();\n  var_dump($d instanceof C11);\n  var_dump($d instanceof C21);\n  var_dump($d instanceof D1);\n\n// -----------------------------------------\n\n  $e11 = new E11();\n  var_dump($e11 instanceof I11);\t// Yes\n  var_dump($e11 instanceof I21);\t// Yes\n  $iName = \"I21\";\n//  var_dump($e11 instanceof $iName);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Instanceof_Operator/instanceof.php.expect",
    "content": "bool(true)\nbool(false)\nbool(false)\nbool(true)\nbool(true)\nbool(false)\n--------------------\nbool(true)\nbool(false)\nbool(true)\n--------------------\nbool(false)\nbool(true)\nbool(false)\n--------------------\nbool(true)\nbool(false)\nbool(true)\n------- Interfaces -------------\nbool(true)\nbool(true)\nbool(true)\n------- Non-Instances -------------\nbool(false)\nbool(false)\nbool(false)\nbool(false)\n------- Non-class/Non-interface types -------------\nbool(true)\nbool(false)\nbool(true)\nbool(true)\nbool(true)"
  },
  {
    "path": "tests/Expressions/Lambda_Expressions/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Lambda_Expressions/lambdas.php",
    "content": "<?hh // strict\n\nnamespace NS_lambdas;\n\nfunction concatStr(): (function (string): string) {\n  $x = 'XX:';\n  return function (string $y): string use ($x) {\n    return $x . $y;\n  };\n}\n\nfunction lam1(int $b): int {\n// $b is captured from the parameter in this function body\n\n// ==> has the same precedence as =, and associates right-to-left\n\n// function body is an expression\n\n//  $fn = $a ==> $a + $b;\n//  $fn = $a ==> ($a + $b);\n//  $fn = ($a ==> ($a + $b));\n\n// function body is a compound statement ending with a return statement whose value becomes resulting expression\n// compound statement can be empty, which is just like a non-empty one not having a return; implicit void return\n\n  $fn = $a ==> { return $a + $b; };\n\n  return $fn(10);\n}\n\nfunction main(): void {\n  echo \"-------------- anonymous function concatStr ----------------\\n\\n\";\n\n  $fn = concatStr();\n  echo $fn('blue') . \"\\n\";\n  echo $fn('green') . \"\\n\";\n\n  echo \"\\n-------------- lam1 ----------------\\n\\n\";\n\n  var_dump(lam1(42)); // return 52\n\n  echo \"\\n-------------- misc ----------------\\n\\n\";\n\n  $fn = $a ==> $a << 3;\n  var_dump($fn(10));\n//  var_dump($fn(5.6));\t// float is incompatible with <<\n\n  echo \"\\n-------------- empty compound statement ----------------\\n\\n\";\n\n  $fn = $a ==> {};\n//  var_dump($fn(123));\t\t// can't use the resturn value form a void function\n\n  echo \"\\n-------------- single parameter, type inferred ----------------\\n\\n\";\n\n  $fn = $a ==> $a * 2;\n  var_dump($fn(10));\n  var_dump($fn(5.6));\n\n  echo \"\\n-------------- single parameter in parens, type inferred ----------------\\n\\n\";\n\n  $fn = ($a) ==> $a * 2;\n  var_dump($fn(10));\n  var_dump($fn(5.6));\n\n/*\n  echo \"\\n-------------- single parameter in parens with attribute, type inferred ----------------\\n\\n\";\n\n  $fn = (<<XX>> $a) ==> $a * 2;\t// hhvm gags on attribute; reports \"unexpected T_SL\"\n  var_dump($fn(10));\n  var_dump($fn(5.6));\n*/\n  echo \"\\n-------------- single parameter in parens, but with ...; type inferred ----------------\\n\\n\";\n\n  $fn = ($a, ...) ==> $a * 2;\n  var_dump($fn(10));\n  var_dump($fn(5.6));\n  var_dump($fn(3, 4, 5));\t// okay; 2nd and 3rd args are ignored\n\n  echo \"\\n-------------- single parameter in parens, type set by default value ----------------\\n\\n\";\n\n  $fn = ($a = -90) ==> $a * 2;\n  var_dump($fn(10));\n//  var_dump($fn(5.6));\t// float is incompatible with int\n  var_dump($fn());\n\n  echo \"\\n-------------- single parameter in parens, explicit type ----------------\\n\\n\";\n\n// need parens of have explicit type\n\n  $fn = (int $a) ==> $a * 2;\n  var_dump($fn(10));\n//  var_dump($fn(5.6));\t// float is incompatible with int\n\n  echo \"\\n-------------- no parameters, but parens necessary ----------------\\n\\n\";\n\n  $fn = () ==> 100;\n  var_dump($fn());\n\n  echo \"\\n-------------- multiple parameters, types inferred ----------------\\n\\n\";\n\n  $fn = ($a, $b, $c) ==> $a + $b + $c;\n  var_dump($fn(10, 5, 9));\n  var_dump($fn(10.0, 5.0, 9.0));\n\n  echo \"\\n-------------- multiple parameters, types partially/fully specified ----------------\\n\\n\";\n\n  $fn = (int $a, $b, $c) ==> $a + $b + $c;\n  var_dump($fn(10, 5, 9));\n//  var_dump($fn(10.0, 5.0, 9.0));\t// float is incompatible with int\n\n  $fn = (int $a, int $b, $c) ==> $a + $b + $c;\n  var_dump($fn(10, 5, 9));\n\n  $fn = (int $a, int $b, int $c) ==> $a + $b + $c;\n  var_dump($fn(10, 5, 9));\n\n  $fn = ($a, $b, int $c) ==> $a + $b + $c;\n  var_dump($fn(10, 5, 9));\n\n  echo \"\\n-------------- lambdas can be async ----------------\\n\\n\";\n\n  $fn = async $a ==> $a * 2;\n  var_dump($fn(10));\n  var_dump($fn(5.6));\n\n  echo \"\\n-------------- specifying a return type ----------------\\n\\n\";\n\n  $fn = ($a): int ==> $a * 2;\n  var_dump($fn(10));\n//  var_dump($fn(5.6));\t// float is incompatible with int (type of $a * 2)\n\n  $fn = ($a): float ==> $a * 2.0;\n  var_dump($fn(10));\n  var_dump($fn(5.6));\n\n  echo \"\\n-------------- chaining lambdas ----------------\\n\\n\";\n\n  $fn1 = $x ==> $y ==> $x + $y;\n  $fn2 = $fn1(10);\n  $res = $fn2(7);\t\t// result is 17\n  echo \"Result is \" . $res . \"\\n\";\n\n  echo \"\\n-------------- comparing brief lambdas with equivalent anonymous functions ----------------\\n\\n\";\n\n  $doublerl = ($p) ==> $p * 2;\n  var_dump($doublerl);\n  var_dump($doublerl(10));\n  var_dump($doublerl(5.6));\n\n  $doubler2 = function ($p) { return $p * 2; };\n  var_dump($doubler2);\n  var_dump($doubler2(10));\n  var_dump($doubler2(5.6));\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Lambda_Expressions/lambdas.php.expectf",
    "content": "-------------- anonymous function concatStr ----------------\n\nXX:blue\nXX:green\n\n-------------- lam1 ----------------\n\nint(52)\n\n-------------- misc ----------------\n\nint(80)\n\n-------------- empty compound statement ----------------\n\n\n-------------- single parameter, type inferred ----------------\n\nint(20)\nfloat(11.2)\n\n-------------- single parameter in parens, type inferred ----------------\n\nint(20)\nfloat(11.2)\n\n-------------- single parameter in parens, but with ...; type inferred ----------------\n\nint(20)\nfloat(11.2)\nint(6)\n\n-------------- single parameter in parens, type set by default value ----------------\n\nint(20)\nint(-180)\n\n-------------- single parameter in parens, explicit type ----------------\n\nint(20)\n\n-------------- no parameters, but parens necessary ----------------\n\nint(100)\n\n-------------- multiple parameters, types inferred ----------------\n\nint(24)\nfloat(24)\n\n-------------- multiple parameters, types partially/fully specified ----------------\n\nint(24)\nint(24)\nint(24)\nint(24)\n\n-------------- lambdas can be async ----------------\n\nobject(HH\\StaticWaitHandle)#17 (0) {\n}\nobject(HH\\StaticWaitHandle)#17 (0) {\n}\n\n-------------- specifying a return type ----------------\n\nint(20)\nfloat(20)\nfloat(11.2)\n\n-------------- chaining lambdas ----------------\n\nResult is 17\n\n-------------- comparing brief lambdas with equivalent anonymous functions ----------------\n\nobject(Closure$NS_lambdas\\NS_lambdas\\main#%d;%d)#%d (1) {\n  [\"parameter\"]=>\n  array(1) {\n    [\"$p\"]=>\n    string(10) \"<required>\"\n  }\n}\nint(20)\nfloat(11.2)\nobject(Closure$NS_lambdas\\NS_lambdas\\main#%d;%d)#%d (1) {\n  [\"parameter\"]=>\n  array(1) {\n    [\"$p\"]=>\n    string(10) \"<required>\"\n  }\n}\nint(20)\nfloat(11.2)\n"
  },
  {
    "path": "tests/Expressions/Multiplicative_Operators/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Multiplicative_Operators/multiplication_division_modulus.php",
    "content": "<?hh // strict\n\nnamespace NS_multiplication_division_modulus;\n\nfunction doit(num $p1_num): void {\n  $oper = array(100, -3.4, $p1_num);\n/*\n  foreach ($oper as $e1) {\n    foreach ($oper as $e2) {\n      echo \">$e1< * >$e2<, result: \"; var_dump($e1 * $e2);\n    }\n    echo \"-------------------------------------\\n\";\n  }\n*/\n\n/*\n  foreach ($oper as $e1) {\n    foreach ($oper as $e2) {\n      if (($e2) == 0) continue;\t// skip divide-by-zeros\n\n      echo \">$e1< / >$e2<, result: \"; var_dump($e1 / $e2);\n    }\n    echo \"-------------------------------------\\n\";\n  }\n*/\n\n///*\n  $oper = array(100, -3);\n  foreach ($oper as $e1) {\n    foreach ($oper as $e2) {\n      if (((int)$e2) == 0) continue;\t// skip divide-by-zeros\n\n        echo \">$e1< % >$e2<, result: \"; var_dump($e1 % $e2);\n      }\n      echo \"-------------------------------------\\n\";\n    }\n\n//  var_dump(10 % 3.0);\t\t// % requires int operands\n//  var_dump(10.0 % 3);\t\t// % requires int operands\n//  var_dump(10 % $p1_num);\t\t// % requires int operands\n//  var_dump($p1_num % 3);\t\t// % requires int operands\n\n  if (is_int($p1_num)) {\n    echo \">$p1_num< % >3<, result: \"; var_dump($p1_num % 3); // OK; num contains an int\n  }\n//*/\n}\n\nfunction main(): void {\n  doit(11);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Multiplicative_Operators/multiplication_division_modulus.php.expect",
    "content": ">100< % >100<, result: int(0)\n>100< % >-3<, result: int(1)\n-------------------------------------\n>-3< % >100<, result: int(-3)\n>-3< % >-3<, result: int(0)\n-------------------------------------\n>11< % >3<, result: int(2)"
  },
  {
    "path": "tests/Expressions/Null_safe_method_call/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Null_safe_method_call/null_safe_calls.php",
    "content": "<?hh // strict\n\nnamespace NS_null_safe_calls;\n\nclass D {}\n\nclass C {\n  public function f1(int $m, int $n): D {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    return new D();\n  }\n\n  public function f2(int $m, int $n): ?D {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    return null;\n  }\n\n  public function f3(int $m, int $n): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n}\n\n/*\nRemoving the ? from the return type, as in\n\nfunction test(?C $x): D\n\nresults in\n\nInvalid return type in return statement\n  Return statement: This is an object of type NS_null_safe_method_call\\D\n  It is incompatible with a nullable type, [as inferred by the ?-> operator]\n*/\n\nfunction hello(int $j): int {\n  echo \"Inside \" . __METHOD__ . \"; \\$j = $j\\n\";\n  return $j;\n}\n\nfunction test(?C $x): void {\n  $i = 5;\n\n  echo \"------------ \\$x?->f1(++\\$i, hello(\\$i))\\n\";\n\n  $res1 = $x?->f1(++$i, hello($i));\n  var_dump($res1);\n\n  echo \"------------ \\$x?->f2(++\\$i, hello(\\$i))\\n\";\n\n  $res2 = $x?->f2(++$i, hello($i));\n  var_dump($res2);\n\n  echo \"------------ \\$x?->f3(++\\$i, hello(\\$i))\\n\";\n\n  $res3 = $x?->f3(++$i, hello($i));\t// allows >-> to call a void function thus producing a ?void result\n  var_dump($res3);\n}\n\nfunction main(): void {\n  echo \"------------ test(new C())\\n\";\n\n  test(new C());\n\n  echo \"------------ test(null)\\n\";\n\n  test(null);\t// the expressions in the method argument list DO GET CALLED ANYWAY\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Null_safe_method_call/null_safe_calls.php.expect",
    "content": "------------ test(new C())\n------------ $x?->f1(++$i, hello($i))\nInside NS_null_safe_calls\\hello; $j = 6\nInside NS_null_safe_calls\\C::f1\nobject(NS_null_safe_calls\\D)#2 (0) {\n}\n------------ $x?->f2(++$i, hello($i))\nInside NS_null_safe_calls\\hello; $j = 7\nInside NS_null_safe_calls\\C::f2\nNULL\n------------ $x?->f3(++$i, hello($i))\nInside NS_null_safe_calls\\hello; $j = 8\nInside NS_null_safe_calls\\C::f3\nNULL\n------------ test(null)\n------------ $x?->f1(++$i, hello($i))\nInside NS_null_safe_calls\\hello; $j = 6\nNULL\n------------ $x?->f2(++$i, hello($i))\nInside NS_null_safe_calls\\hello; $j = 7\nNULL\n------------ $x?->f3(++$i, hello($i))\nInside NS_null_safe_calls\\hello; $j = 8\nNULL"
  },
  {
    "path": "tests/Expressions/Pipe_Operator/pipe.php",
    "content": "<?hh // strict\n\nnamespace NS_pipe;\n\nfunction fint(int $p): int {\n  echo \"Inside \" . __FUNCTION__ . \"; returning \" . ($p + 3) . \"\\n\";\n  return $p + 3;\n}\n\nfunction gint(int $p): int {\n  echo \"Inside \" . __FUNCTION__ . \"; returning \" . ($p * 2) . \"\\n\";\n  return $p * 2;\n}\n\nfunction hint(int $p): int {\n  echo \"Inside \" . __FUNCTION__ . \"; returning \" . (-$p) . \"\\n\";\n  return -$p;\n}\n\nfunction fvoid(): void {\n  echo \"Inside \" . __FUNCTION__ . \"; returning nothing\\n\";\n}\n\nclass Widget {\n  public function getNumber(): int { return -1; }\n}\n\nfunction pipe_operator_example(array<Widget> $arr): int {\n  return $arr\n    |> array_map($x ==> $x->getNumber(), $$)\n    |> array_filter($$, $x ==> $x % 2 == 0)\n    |> count($$);\n}\n\nfunction main(): void {\n\n// check where $$ is allowed (only in the RHS operand of |>)\n\n//  $$ |> $$;\t// Undefined variable: $$ (on LHS)\n\n  20 |> $$;\t// OK; on RHS of |>\n\n//  $x = $$;\t// Undefined variable: $$\n\n//  $$ = 10;\t// Undefined variable: $$; Invalid lvalue \n\n  echo \"\\n\\n========================= Simple Use =========================\\n\\n\";\n\n  $v = (20 |> $$ |> $$);\n  var_dump($v);\n\n  20 |> var_dump($$);\n  1.23 |> var_dump($$);\n  \"abc\" |> var_dump($$);\n\n//  20 |> $x = $$;\t// Error: Feature not implemented: Assignment within pipe expressions\n//  20 |> ($x = $$);\t// Error: Feature not implemented: Assignment within pipe expressions\n\n// The RH operand must use the result of the LH operand\n\n//  echo \"Result is: \" . (fint(4) |> gint(9)) . \"\\n\";\t// Error: This expression does not contain a usage of the\n\t\t\t\t\t\t// special pipe variable. Did you forget to use the ($$)\n\t\t\t\t\t\t// variable? (Naming[2069]\n\n//  fvoid() |> gint($$);\t// You are using the return value of a void function\n//  fvoid() |> 10 + $$;\t\t// This is a num ... It is incompatible with void\n  fvoid() |> $$ |> $$;\t\t// Permitted because the result (which has type void) is not used\n\n  echo \"\\n\\n========================= Check Associativity =========================\\n\\n\";\n\n// associativity is left-to-right\n\n  echo \"Result is: \" . (fint(4) |> gint($$) |> hint($$)) . \"\\n\";\n  echo \"Result is: \" . (fint(-5) |> gint($$) |> hint($$)) . \"\\n\";\n\n// precedence\n\n// lower than additive operator ., as need grouping parens above\n\n  echo \"\\n\\n========================= Check Precedence against << =========================\\n\\n\";\n\n  2 << fint(1) |> gint($$);\t// lower than <<, as g is passed (2 << fint(1))\n\n/*\n  2 <  fint(1) |> gint($$);\t// lower than <, as g is passed a bool\n  2 == fint(1) |> gint($$);\t// lower than ==, as g is passed a bool\n*/\n\n  echo \"\\n\\n========================= Check Precedence against &, |, and ^ =========================\\n\\n\";\n\n  7 & fint(1) |> gint($$);\t// lower than &, as g is passed (7 & fint(1))\n  7 | fint(1) |> gint($$);\t// lower than |, as g is passed (7 | fint(1))\n  7 ^ fint(1) |> gint($$);\t// lower than ^, as g is passed (7 ^ fint(1))\n\n/*\n  1 && fint(1) |> gint($$);\t// lower than &, as g is passed a bool\n  0 && fint(1) |> gint($$);\t// lower than &, as g is passed a bool\n*/\n\n  echo \"\\n\\n========================= Check Precedence against ?: =========================\\n\\n\";\n\n  0 ? fint(1) |> gint($$) : fint(2) |> gint($$);\n  1 ? fint(1) |> gint($$) : fint(2) |> gint($$);\t// 3rd operand of ?: does NOT include gint($$)\n  1 ? fint(1) |> gint($$) : (fint(2) |> gint($$));\n\n  echo \"\\n\\n========================= Check Precedence against ?? =========================\\n\\n\";\n\n  fint(1) |> gint($$) ?? fint(2) |> gint($$);\t// lower than ??\n  fint(1) |> gint($$) ?? (fint(2) |> gint($$));\n\n  echo \"\\n\\n========================= Check Precedence against a lambda =========================\\n\\n\";\n\n  $doit1 = ($p) ==> fint($p) |> gint($$);\t// higher than ==>\n  var_dump($doit1(2));\n  $doit2 = ($p) ==> (fint($p) |> gint($$));\t// parens are redundant\n  var_dump($doit2(2));\n\n  echo \"\\n\\n========================= Check Precedence against = =========================\\n\\n\";\n\n  $x = fint(2) |> gint($$);\t// higher than =\n  $x = (fint(2) |> gint($$));\t// parens are redundant\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Pipe_Operator/pipe.php.expect",
    "content": "\n\n========================= Simple Use =========================\n\nint(20)\nint(20)\nfloat(1.23)\nstring(3) \"abc\"\nInside NS_pipe\\fvoid; returning nothing\n\n\n========================= Check Associativity =========================\n\nInside NS_pipe\\fint; returning 7\nInside NS_pipe\\gint; returning 14\nInside NS_pipe\\hint; returning -14\nResult is: -14\nInside NS_pipe\\fint; returning -2\nInside NS_pipe\\gint; returning -4\nInside NS_pipe\\hint; returning 4\nResult is: 4\n\n\n========================= Check Precedence against << =========================\n\nInside NS_pipe\\fint; returning 4\nInside NS_pipe\\gint; returning 64\n\n\n========================= Check Precedence against &, |, and ^ =========================\n\nInside NS_pipe\\fint; returning 4\nInside NS_pipe\\gint; returning 8\nInside NS_pipe\\fint; returning 4\nInside NS_pipe\\gint; returning 14\nInside NS_pipe\\fint; returning 4\nInside NS_pipe\\gint; returning 6\n\n\n========================= Check Precedence against ?: =========================\n\nInside NS_pipe\\fint; returning 5\nInside NS_pipe\\gint; returning 10\nInside NS_pipe\\fint; returning 4\nInside NS_pipe\\gint; returning 8\nInside NS_pipe\\gint; returning 16\nInside NS_pipe\\fint; returning 4\nInside NS_pipe\\gint; returning 8\n\n\n========================= Check Precedence against ?? =========================\n\nInside NS_pipe\\fint; returning 4\nInside NS_pipe\\gint; returning 8\nInside NS_pipe\\gint; returning 16\nInside NS_pipe\\fint; returning 4\nInside NS_pipe\\gint; returning 8\n\n\n========================= Check Precedence against a lambda =========================\n\nInside NS_pipe\\fint; returning 5\nInside NS_pipe\\gint; returning 10\nint(10)\nInside NS_pipe\\fint; returning 5\nInside NS_pipe\\gint; returning 10\nint(10)\n\n\n========================= Check Precedence against = =========================\n\nInside NS_pipe\\fint; returning 5\nInside NS_pipe\\gint; returning 10\nInside NS_pipe\\fint; returning 5\nInside NS_pipe\\gint; returning 10"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Postfix_Operators/array_creation.php",
    "content": "<?hh // strict\n\nnamespace NS_array_creation;\n\nfunction main(): void {\n  $a = [1 => 10, 'xx' => 20, 4.5 => 30, false => 40, '-10' => 50];\n  var_dump($a);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/array_creation.php.expect",
    "content": "array(5) {\n  [1]=>\n  int(10)\n  [\"xx\"]=>\n  int(20)\n  [4]=>\n  int(30)\n  [0]=>\n  int(40)\n  [-10]=>\n  int(50)\n}"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/exponentiation.php",
    "content": "<?hh // strict\n\nnamespace NS_exponentiation;\n\nclass C {\n  public float $prop = 12.0;\n}\n\nfunction f(): int { return 3; }\n\nfunction main(): void {\n  echo \"=========== some basic tests ===========\\n\";\n\n/*\n  var_dump(2**3);\n  var_dump(2**3.0);\n  var_dump(2.0**3.0);\n  var_dump(2.111**3.111);\n  var_dump(2**\"3\");\n  var_dump(\"2\"**3.0);\n  var_dump(\"2.0\"**\"3.0\");\n  var_dump(\"2.111\"**\"3.111\");\n\n  echo \"=========== compound-assignment version ===========\\n\";\n\n  $v = 5;\n  $v **= 3;\n  var_dump($v);\n\n  $v = 5;\n  $v **= 3.0;\n  var_dump($v);\n\n  echo \"=========== checking precedence against * and / ===========\\n\";\n\n  $r = 4 / 2 * 3 ** 2; // ** has higher precedence than * and /\n  var_dump($r);\n  $r = 4 / 2 * (3 ** 2);\n  var_dump($r);\n  $r = (4 / 2) * 3 ** 2;\n  var_dump($r);\n  $r = (4 / 2) * (3 ** 2);\n  var_dump($r);\n  $r = (((4 / 2) * 3) ** 2);\n  var_dump($r);\n\n  echo \"=========== checking precedence against unary - ===========\\n\";\n\n  var_dump(-3 ** 2);\n  var_dump((-3) ** 2);\n  var_dump(-(3 ** 2)); // ** has higher precedence than unary -\n\n  echo \"=========== checking precedence against [], (), and -> ===========\\n\";\n\n  $a = array(10, 20);\n  var_dump($a[0] ** 2);\n  var_dump(f() ** 2);\n  $c = new C;\n  var_dump($c->prop ** 2);\n*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/exponentiation.php.expect",
    "content": "=========== some basic tests ==========="
  },
  {
    "path": "tests/Expressions/Postfix_Operators/function_call.php",
    "content": "<?hh // strict\n\nnamespace NS_function_call;\n\nfunction f(): void {\n  echo \"Inside function \" . __FUNCTION__ . \"\\n\";\n}\n\nfunction f2(int $p1, int $p2 = -100): void {}\n\nfunction f3(int $p2 = -100, ...): void {}\n\nfunction fx(int $p1, int $p2, int $p3, int $p4, int $p5): void { }\nfunction fy(int $p1, int $p2, int $p3, int $p4, int $p5): void {\n  echo \"$p1, $p2, $p3, $p4, $p5\\n\";\n}\nfunction fz(int $p1, int $p2, int $p3, int $p4, int $p5): void { }\n\nfunction main(): void {\n//  $x = '\\NS_function_call\\f';\n// $x();\t// unlike PHP, Hack does not allow a function to be called using its raw string name\n  $x = fun('\\NS_function_call\\f');\t// must \"wrap\" using fun instead\n  $x();\n\n//  f2();\t\t\t// too few argumemts\n  f2(24);\n//  f2(2.3);\t\t// incompatible types\n  f2(5, 10);\n//  f2(9, true);\t\t// incompatible types\n//  f2(12, 123, 222);\t// too many arguments\n\n\n  f3();\t\t\t// default value used\n  f3(24);\n//  f3(2.3);\t\t// incompatible types\n  f3(5, 10);\t\t// excess of any number and type okay\n  f3(9, true);\t\t// excess of any number and type okay\n  f3(12, 123, 222);\t// excess of any number and type okay\n\n  $funcTable = array(fun('\\NS_function_call\\fx'), fun('\\NS_function_call\\fy'),\n    fun('\\NS_function_call\\fz'));\t// list of 3 function designators \n  $i = 1;\n  $funcTable[$i++]($i, ++$i, $i, $i = 12, --$i); // calls fy(2,3,3,12,11)\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/function_call.php.expect",
    "content": "Inside function NS_function_call\\f\n2, 3, 3, 12, 11"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/function_call_with_strict_checking.php",
    "content": "<?php\n\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2015-2016 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\ndeclare(strict_types = 1);\n\nfunction doubler(int $p) : int\n{\n    return $p * 2;\n}\n\nfunction main(): void {\n//  var_dump(doubler(10.3)); // Throws a TypeError\n  var_dump(doubler(10));\n\n  echo \"\\n================ End of script ===================\\n\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/function_call_with_strict_checking.php.expectf",
    "content": "\nFatal error: strict_types can only be used when hhvm.php7.scalar_types = true in %s/tests/Expressions/Postfix_Operators/function_call_with_strict_checking.php on line 9"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/member_selection_operator.php",
    "content": "<?hh // strict\n\nnamespace NS_member_selection_operator;\n\nclass Point {\n  private float $x;\n  private float $y;\n\n  public function getX(): float \t{ return $this->x; }\n  public function setX(float $x): void\t{ $this->x = $x;   }\n  public function getY(): float\t\t{ return $this->y; }\n  public function setY(float $y): void\t{ $this->y = $y;   }\n\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n//  $name = 'x';\n//  $this->$name = $x;\t// Unlike PHP, Hack does not permit this\n    $this->x = $x;\n    $this->y = $y;\n  }\n\n  public function move(float $x, float $y): void {\n    $this->x = $x;\n    $this->y = $y;\n  }\t\n\n  public function translate(float $x, float $y): void {\n    $this->x += $x;\n    $this->y += $y;\n  }\n\n  public function __toString(): string {\n    return '(' . $this->x . ',' . $this->y . ')';\n  }\n\n  public int $piProp = 555;\n  public static function psf(): int { return 123; }\n  public static int $psProp = 999;\n  const float MYPI = 3.14159;\n}\n\nclass K {\n  public L $prop;\n  public function __construct(L $p1) {\n    $this->prop = $p1;\n  }\n}\n\nclass L {\n  public function f(): void { echo \"Hello from f\\n\"; }\n}\n\nfunction main(): void {\n  $p1 = new Point();\n  echo \"\\$p1 is >$p1<\\n\";\n\n  $p1->move(3.0, 9.0);\n  echo \"\\$p1 is >$p1<\\n\";\n\n//  $n = \"move\";\n//  $p1->$n(-2.0, 4.0);\t// Unlike PHP, Hack does not permit this\n//  echo \"\\$p1 is >$p1<\\n\";\n\n  var_dump($p1->piProp);\t// okay to access instance property via instance\n//  var_dump($p1->psf());\t// Unlike PHP, Hack doesn't allow access to a static method via instance\n\n  var_dump(Point::psf());\t// okay to access static method via class\n  var_dump(Point::$psProp);// okay to access static property via class, but leading $ needed!!\n  var_dump(Point::MYPI);\t// okay to access const via class\n\n// use multiple ->s\n\n  $k = new K(new L());\n  $k->prop->f();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/member_selection_operator.php.expect",
    "content": "$p1 is >(0,0)<\n$p1 is >(3,9)<\nint(555)\nint(123)\nint(999)\nfloat(3.14159)\nHello from f"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/new.php",
    "content": "<?hh // strict\n\nnamespace NS_new;\n\nclass C {}\n\nfunction main(): void {\n\t$c1 = new C();\n//\t$c1 = new 'C'();\n//\t$name = 'C';\n//\t$c1 = new $name();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/new.php.expect",
    "content": ""
  },
  {
    "path": "tests/Expressions/Postfix_Operators/new_anonymous_classes.php",
    "content": "// NOT YET IMPLEMENTED IN THE CHECKER <?hh // strict\n\nnamespace NS_new_anonymous_classes;\n\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2015 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\nclass C1 {}\ninterface I1 {\n\tpublic function f(): void;\n\tpublic function g(): void;\n}\ninterface I2 {}\n\nfunction main(): void {\n\n  echo \"================ Create some objects of anonymous classes type ===================\\n\\n\";\n\n  $v1a = new class() {\n    public function __construct() {\n      echo \"Inside class \" . __CLASS__ . \"\\n\";\n    }\n  };\n\n  var_dump($v1a);\n\n  $v1b = new class () {\n    public function __construct() {\n      echo \"Inside class \" . __CLASS__ . \"\\n\";\n    }\n  };\n\n  var_dump($v1b);\n\n  $v2 = new class (100) extends C1 implements I1, I2 {\n    public function __construct($p) {\n      echo \"Inside class \" . __CLASS__ . \" constructor with parameter $p\\n\";\n    }\n    public function f(): void {\n      echo \"Inside ??::f()\\n\";\n    }\n    public function g(): void {\n      echo \"Inside ??::g()\\n\";\n    }\n  };\n\n  var_dump($v2);\n\n  $v2->f();\n  $v2->g();\n\n  echo \"\\n================ Comparing anonymous classes ===================\\n\\n\";\n\n/*\nMultiple anonymous classes created in the same position (say, a loop) can be compared with `==`,\nbut those created elsewhere will not match as they will have a different name. */\n\n  $identicalAnonClasses = [];\n \n  for ($i = 0; $i < 2; $i++) {\n    $identicalAnonClasses[$i] = new class(99) {\n      public $i;\n      public function __construct($i) {\n        $this->i = $i;\n      }\n    };\n  }\n \n  var_dump($identicalAnonClasses[0] == $identicalAnonClasses[1]); // true\n \n  $identicalAnonClasses[2] = new class(99) {\n    public $i;\n    public function __construct($i) {\n      $this->i = $i;\n    }\n  };\n \n  var_dump($identicalAnonClasses[0] == $identicalAnonClasses[2]); // false\n\n  echo \"\\n================ End of script ===================\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/new_anonymous_classes.php.expectf",
    "content": "\nFatal error: HH mode: content before <?hh (Line: 1, Char: 38)\nsyntax error, unexpected T_HH_ERROR, expecting $end in %s/tests/Expressions/Postfix_Operators/new_anonymous_classes.php on line 1"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/nullable_and_arithmetic.php",
    "content": "<?hh // strict\n\nnamespace NS_nullable_and_arithmetic;\n\nclass C {\n  public ?int $nint = 5;\n}\n\nfunction f(?int $p1, C $p2): void {\n/*\n  $p1++;\t\t// flagged\n  $p1--;\t\t// flagged\n  ++$p1;\t\t// flagged\n  --$p1;\t\t// flagged\n*/\n/*\n  $p2->nint++;\t// not flagged\n  $p2->nint--;\t// not flagged\n  ++$p2->nint;\t// flagged\n  --$p2->nint;\t// flagged\n*/\n}\n\nfunction main(): void {\n  $v = null;\n//  $v++;\t\t\t// flagged\n//  $q = $v + 3;\t\t// flagged\n//  $q = $v * 1.2;\t\t// flagged\n//  $q = $v >> 3;\t\t// flagged\n\n/*\n// Typing error: This is a num (int/float) because this is used in an arithmetic operation\n// It is incompatible with a nullable type\n//\n  $v = null;\n  $v++;\n  $v--;\n  ++$v;\n  --$v;\n*/\n  $c = new C();\n/*\nTyping error: This is a num (int/float) because this is used in an arithmetic operation\nIt is incompatible with a nullable type\n\n  $v = $c->nint;\n  $v++;\n  $v--;\n  ++$v;\n  --$v;\n/*\n/*\n  $v = $c->nint;\n  if (!is_null($v)) {\t// all OK!\n    $v++;\n    $v--;\n    ++$v;\n    --$v;\n  } else {\n//  $v++;\t\t// flagged, as outside true path\n  }\n\n  if (is_int($v)) {\t// all OK!\n    $v++;\n    $v--;\n    ++$v;\n    --$v;\n  }\n\n  if (is_float($v)) {\t// all OK, but tests false for an ?int\n    $v++;\n    $v--;\n    ++$v;\n    --$v;\n  }\n\n// doesn't work, 'cos is_numeric includes numeric strings, and Hack doesn't allow arithmetic on strings\n//\n//  if (is_numeric($v)) {\n//    $v++;\n//    $v--;\n//    ++$v;\n//    --$v;\n//  }\n*/\n///*\n  $c->nint = 5;\t// if not omitted, all 4 ops \"pass the checker\"\n  $c->nint++;\t// not flagged\n  $c->nint--;\t// not flagged\n  ++$c->nint;\t// flagged if assignment is omitted\n  --$c->nint;\t// flagged if assignment is omitted\n//  var_dump($c);\n\n  if (!is_null($c->nint)) {\t// all OK!\n    $c->nint++;\n    $c->nint--;\n    ++$c->nint;\n    --$c->nint;\n  }\n//*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/nullable_and_arithmetic.php.expect",
    "content": ""
  },
  {
    "path": "tests/Expressions/Postfix_Operators/nullsafe_member_selection.php",
    "content": "<?hh // strict\n\nnamespace NS_nullsafe_member_selection;\n\n// =================== use ?-> with an instance method =====================\n\nclass Bar1 {\n  public function baz1(): int {\n     return 5;\n  }\n  public static function sbaz1(): int {\n    return 55;\n  }\n}\n\nfunction get_Bar1(): ?Bar1 {\n  if (rand(0, 10) === 5) {\n    return null;\n  }\n  return new Bar1();\n}\n\nfunction foo1(): ?int {\n  $b = get_Bar1();\n  // Use the null-safe operator to access a method of class.\n\n//  return $b?->sbaz1();\t// error: method can't be static\n\n  return $b?->baz1();\n}\n\n// =================== use ?-> with a property =====================\n\nclass Bar2 {\n  public function __construct(public string $str = \"\") {}\n  public static string $sstr = \"xx\";\n}\n\nfunction get_Bar2(): ?Bar2 {\n  if (rand(0, 10) < 5) {\n    return null;\n  }\n  return new Bar2(\"Hello\");\n}\n\nfunction foo2(): ?string {\n  $b = get_Bar2();\n  // Use the null-safe operator to access a proprety of a class.\n\n//  $b?->str = 'abc';\t// error: ?-> syntax is not supported for lvalues\n\n//  return $b?->sstr;\t// error: property can't be static\n\n  return $b?->str;\n}\n\nfunction main(): void {\n  var_dump(foo1());\n  var_dump(foo2());\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/nullsafe_member_selection.php.expect",
    "content": "int(5)\nstring(5) \"Hello\""
  },
  {
    "path": "tests/Expressions/Postfix_Operators/post-increment_and_decrement_integer_edge_cases.php",
    "content": "<?hh // strict\n\nnamespace NS_post_inc_and_dec_integer_edge_cases;\n\nfunction incdec(int $x): void {\n  echo \"--- start incdec ---\\n\";\n  $y = $x;\n\n  var_dump($x);\n  --$x;\n  var_dump($x);\n  --$x;\n  var_dump($x);\n  ++$x;\n  var_dump($x);\n  ++$x;\n  var_dump($x);\n\n// equivalent code using -=/+= instead of --/++.\n\n  var_dump($y);\n  $y -= 1;\n  var_dump($y);\n  $y -= 1;\n  var_dump($y);\n  $y += 1;\n  var_dump($y);\n  $y += 1;\n  var_dump($y);\n  echo \"--- end incdec ---\\n\";\n}\n\nfunction incdecrev(int $x): void {\n  echo \"--- start incdecrev ---\\n\";\n  $y = $x;\n\n  var_dump($x);\n  ++$x;\n  var_dump($x);\n  ++$x;\n  var_dump($x);\n  --$x;\n  var_dump($x);\n  --$x;\n  var_dump($x);\n\n// equivalent code using -=/+= instead of --/++.\n\n  var_dump($y);\n  $y += 1;\n  var_dump($y);\n  $y += 1;\n  var_dump($y);\n  $y -= 1;\n  var_dump($y);\n  $y -= 1;\n  var_dump($y);\n  echo \"--- end incdecrev ---\\n\";\n}\n\nfunction main(): void {\n  $i32 = 1 << 31;\t// if this is negative, we have a 32-bit int\n  $i64 = 1 << 63; // same as $i32 for 32-bit int; otherwise, is 64-bit\n  $IntMin = ($i32 < 0) ? $i32 : $i64;\n  $IntMax = ~$IntMin;\n\n  incdec($IntMin);\n  incdecrev($IntMax);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/post-increment_and_decrement_integer_edge_cases.php.expect",
    "content": "--- start incdec ---\nint(-9223372036854775808)\nint(9223372036854775807)\nint(9223372036854775806)\nint(9223372036854775807)\nint(-9223372036854775808)\nint(-9223372036854775808)\nint(9223372036854775807)\nint(9223372036854775806)\nint(9223372036854775807)\nint(-9223372036854775808)\n--- end incdec ---\n--- start incdecrev ---\nint(9223372036854775807)\nint(-9223372036854775808)\nint(-9223372036854775807)\nint(-9223372036854775808)\nint(9223372036854775807)\nint(9223372036854775807)\nint(-9223372036854775808)\nint(-9223372036854775807)\nint(-9223372036854775808)\nint(9223372036854775807)\n--- end incdecrev ---"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/post_increment_and_decrement.php",
    "content": "<?hh // strict\n\nnamespace NS_post_increment_and_decrement;\n\nclass C {\n  public ?int $prop1 = null;\n}\n\nfunction main(): void {\n  echo \"=== int 5 ===\\n\";\n\n  $v = 5; var_dump($v++); var_dump($v--);\n\n  echo \"\\n=== int 0x7fffffffffffffff ===\\n\";\n\n  $v = 0x7fffffffffffffff; var_dump($v++); var_dump($v--);\n\n  echo \"\\n=== int 0x80000000 ===\\n\";\n\n  $v = 0x8000000000000000; var_dump($v++); var_dump($v--);\n\n  echo \"\\n=== float 12.345 ===\\n\";\n\n  $v = 12.345; var_dump($v++); var_dump($v--);\n\n  echo \"\\n=== float INF ===\\n\";\n\n  $v = INF; var_dump($v++); var_dump($v--);\n\n  echo \"\\n=== float -INF ===\\n\";\n\n  $v = -INF; var_dump($v++); var_dump($v--);\n\n  echo \"\\n=== float NAN ===\\n\";\n\n  $v = NAN; var_dump($v++); var_dump($v--);\n/*\n// Hack does not permit null to be the object of a postfix ++/--\n\n  echo \"\\n=== null ===\\n\";\n\n  $v = null; var_dump($v++); var_dump($v--);\n*/\n/*\n// Hack does not permit Boolean values to be the object of a postfix ++/--\n\n  echo \"\\n=== true ===\\n\";\n\n  $v = true; var_dump($v++); var_dump($v--);\n\n  echo \"\\n=== false ===\\n\";\n\n  $v = false; var_dump($v++); var_dump($v--);\n*/\n/*\n// Hack does not permit string values to be the object of a postfix ++/--\n  echo \"\\n=== string \\\"\\\" ===\\n\";\n\n  echo \"---> ++/--/--\\n\";\n  $v = \"\"; var_dump($v++); var_dump($v--); var_dump($v--);\n  echo \"\\n---> --/++/++\\n\";\n  $v = \"\"; var_dump($v--); var_dump($v++); var_dump($v++);\n\n  echo \"\\n=== string \\\"0\\\" ===\\n\";\n\n  echo \"---> ++/--/--\\n\";\n  $v = \"0\"; var_dump($v++); var_dump($v--); var_dump($v--);\n  echo \"\\n---> --/++/++\\n\";\n  $v = \"0\"; var_dump($v--); var_dump($v++); var_dump($v++);\n\n  echo \"\\n=== string \\\"-26\\\" ===\\n\";\n\n  echo \"---> ++/--/--\\n\";\n  $v = \"-26\"; var_dump($v++); var_dump($v--); var_dump($v--);\n  echo \"\\n---> --/++/++\\n\";\n  $v = \"-26\"; var_dump($v--); var_dump($v++); var_dump($v++);\n\n  echo \"\\n=== string \\\"a\\\" ===\\n\";\n\n  echo \"---> ++/--/--\\n\";\n  $v = \"a\"; var_dump($v++); var_dump($v--); var_dump($v--);\n  echo \"\\n---> --/++/++\\n\";\n  $v = \"a\"; var_dump($v--); var_dump($v++); var_dump($v++);\n*/\n/*\n  echo \"=== ?int ===\\n\";\n\n  $c = new C();\n\n  echo \"---> ++/--/--\\n\";\n  $c->prop1 = 5; var_dump($c->prop1++); var_dump($c->prop1--); var_dump($c->prop1--);\n\n  echo \"---> ++/--/--\\n\";\n  $c->prop1 = null; var_dump($c->prop1++); var_dump($c->prop1--); var_dump($c->prop1--);\n*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/post_increment_and_decrement.php.expect",
    "content": "=== int 5 ===\nint(5)\nint(6)\n\n=== int 0x7fffffffffffffff ===\nint(9223372036854775807)\nint(-9223372036854775808)\n\n=== int 0x80000000 ===\nint(9223372036854775807)\nint(-9223372036854775808)\n\n=== float 12.345 ===\nfloat(12.345)\nfloat(13.345)\n\n=== float INF ===\nfloat(INF)\nfloat(INF)\n\n=== float -INF ===\nfloat(-INF)\nfloat(-INF)\n\n=== float NAN ===\nfloat(NAN)\nfloat(NAN)"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/scope_resolution_operator.php",
    "content": "//<?hh // strict\n\nnamespace NS_scope_resolution;\n\nclass M {\n// The following members are overridden in class P\n\n  public static function psf(): string { return \"red\"; }\n  public static int $psProp = -333;\n  const float MYPI = 3.14;\n  const int CON1 = -222;\n\n// method b1 demostrates self vs. static\n\n  public function b1(): void {\n    echo \"  self::\\$psf returns \" . self::psf() . \"\\n\";\n    echo \"static::\\$psf returns \" . static::psf() . \"\\n\";\n    echo \"  self::\\$psProp is   \" . self::$psProp . \"\\n\";\n    echo \"static::\\$psProp is   \" . static::$psProp . \"\\n\";\n    echo \"  self::\\$MYPI is     \" . self::MYPI . \"\\n\";\n    echo \"static::\\$MYPI is     \" . static::MYPI . \"\\n\";\n\n    echo \"  self::\\$b2 --- \"; self::b2();\n    echo \"static::\\$b2 --- \"; static::b2();\n  }\n\n  public function b2(): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n\n  public function __construct() { }\n}\n\nclass N extends M {\n  public function b2(): void\t// overrides base::b2() {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n}\n\nclass P extends N {\n  private int $prop;\n  const int CON1 = 543;\n  private int $prop2 = self::CON1;\n  private int $prop3 = parent::CON1;\n//  private $prop4 = static::CON1; // \"static::\" is not allowed in compile-time constants\n\n  public function __construct(int $p1) {\n    $this->prop = $p1;\n\n    echo \"Inside instance \" . __METHOD__ . \"\\n\";\n    parent::__construct();\n    M::__construct();\t\t// allowed\n    N::__construct();\t\t// allowed\n    $clName = \"M\";\n    $clName::__construct();\t// allowed\n//    \"M\"::__construct();\t\t// not allowed\n\n// can call instance and static methods using both -> and ::\n\n    $this->gi();\t// $this explicitly used (and passed)\n    P::gi();\t\t// $this implicitly used (and passed)\n    self::gi();\t\t// $this implicitly used (and passed)\n\n    $this->gs();\t// call to static method, so no $this passed\n    P::gs();\t\t// call to static method, so no $this passed\n    self::gs();\t\t// call to static method, so no $this passed\n  }\n\n  public function gi(): void {\n    echo \"Inside instance \" . __METHOD__ . \"\\n\";\n    \\var_dump($this);\n  }\n\n  public static function gs(): void {\n    echo \"Inside static \" . __METHOD__ . \"\\n\";\n  }\n\n// method f1 demostrates self and parent\n\n  public static function f1(): void {\n    echo \"Accessing self:\\n\";\n    echo \"psf returns \" . self::psf() . \"\\n\";\n    echo \"psProp = \" . self::$psProp . \"\\n\";\n    echo \"MYPI   = \" . self::MYPI . \"\\n\";\n\n    echo \"Accessing parent(s)\\n\";\n    echo \"psf returns \" . parent::psf() . \"\\n\";\n    echo \"psProp = \" . parent::$psProp . \"\\n\";\n    echo \"MYPI   = \" . parent::MYPI . \"\\n\";\n  }\n\n  public function b2(): void\t// overrides base::b2() {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n\n// The following 3 members override those in class M\n\n  public static function psf(): int { return 123; }\n  public static int $psProp = 999;\n  const MYPI = 3.14159;\n}\n\n// simplified version of static\n\nclass Base {\n  public function b(): void {\n//    echo \"Inside \" . __METHOD__ . \"\\n\";\n    static::f();\n    echo \"The static context here is \" . static::class . \"\\n\";\n  }\n\n  public function f(): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n}\n\nclass Derived extends Base {\n  public function f(): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n}\n\ninterface I1 {\n  const int CON1 = 123;\n  const int CON2 = I1::CON1;\n  const int CON3 = self::CON1;\n  public function f(): void;\n}\n\ninterface I2 extends I1 {\n  const int CON4 = parent::CON1;\t// Cannot access parent:: when current class scope has no parent\n}\n\nclass X implements I2 { public function f(): void {} }\n\nclass W1 {}\n\nclass W2 extends W1 {\n  private int $prop1 = 123;\n\n  public function M(): void {\n    echo \"inside \" . __METHOD__ . \"\\n\";\n    \\var_dump($this);\n\n    \\var_dump(self::class);\n    \\var_dump(parent::class);\n    \\var_dump(static::class);\n  }\n}\n\nfunction main(): void {\n  \\var_dump(M::psf());\t\t// okay to access static method via class\n  $memName = 'psf';\n  \\var_dump(M::$memName());// string form allowed\n//  var_dump(M::'psf'());\t// but not string literal\n\n  \\var_dump(M::$psProp);\t// okay to access static property via class, but leading $ needed!!\n  $memName = '$psProp';\n//  var_dump(M::$memName);// Access to undeclared static property: M::$memName\n//  var_dump(M::memName);// Undefined class constant 'memName'\n\n  \\var_dump(M::MYPI);\t\t// okay to access const via class\n  $memName = 'MYPI';\n//  var_dump(M::$memName);\t// Access to undeclared static property: M::$memName\n\n  $clName = \"M\";\n  \\var_dump($clName::MYPI);\t// okay to use a string containing class name\n//  var_dump(\"M\"::MYPI);\t\t// but not the literal form\n\n  echo \"-----------------------------\\n\";\n\n  \\var_dump(P::psf());\t\t// okay to access static method via class\n  \\var_dump(P::$psProp);\t// okay to access static property via class, but leading $ needed!!\n  \\var_dump(P::MYPI);\t\t// okay to access const via class\n\n  $clName = \"P\";\n  \\var_dump($clName::MYPI);\t// okay to use a string containing class name\n\n  echo \"-----------------------------\\n\";\n\n  P::f1();\n\n  echo \"-----------------------------\\n\";\n\n  $m = new M();\n  $n = new N();\n  $p = new P(1000);\n\n  echo \"-----------------------------\\n\";\n\n  $m->b1();\n\n  echo \"-----------------------------\\n\";\n\n  $n->b1();\n\n  echo \"-----------------------------\\n\";\n\n  $p->b1();\n\n  echo \"-----------------------------\\n\";\n\n  $b1 = new Base();\n  $b1->b();\n  $d1 = new Derived();\n  $d1->b();\n\n  echo \"-----------------------------\\n\";\n\n// see about :: in interfaces\n\n  \\var_dump(I1::CON1);\n  $intName = 'I1';\n  \\var_dump($intName::CON1);\n  \\var_dump(I1::CON2);\n  \\var_dump(I1::CON3);\n\n//  var_dump(I2::CON4);\n\n//  $x = new X();\n\n  echo \"-----------------------------\\n\";\n\n// see about ...::class\n\n  $w2 = new W2();\n  \\var_dump($w2);\n\n  $w2->M();\n\n  \\var_dump(W2::class);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/scope_resolution_operator.php.expectf",
    "content": "\nFatal error: HH mode: content before <?hh (Line: 1, Char: 2)\nsyntax error, unexpected T_HH_ERROR, expecting $end in %s/tests/Expressions/Postfix_Operators/scope_resolution_operator.php on line 1"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/subscripting.php",
    "content": "<?hh // strict\n\nnamespace NS_subscripting;\n\nfunction f(): array<int> {\n  return [1000, 2000, 3000];\n}\n\n// See arrays.php for array creation and initialization\n// This set of tests deals only with array-element access\n\nfunction main(): void {\n/*\n// vector-like array\n\n  $v1 = array(10, 20, 30);\n  var_dump($v1);\n  echo $v1[0] . \"\\n\";\n//  echo $v1[1.2] . \"\\n\";\t\t// index must have type int\n//  echo $v1[\"1\"] . \"\\n\";\t\t// index must have type int\n\n  foreach ($v1 as $k => $e) {\n    echo \"key: \" . $k . \", value: \" . $e . \"\\n\";\n  }\n\n// map-like array\n\n  $v2 = array('x' => 40, 1 => 50, 'y' => 60);\n  var_dump($v2);\n  echo $v2[0] . \"\\n\";\n  echo $v2[1.2] . \"\\n\";\t\t// like PHP index need not have type int\n  echo $v2[\"x\"] . \"\\n\";\t\t// like PHP index need not have type int\n\n  foreach ($v2 as $k => $e) {\n    echo \"key: \" . $k . \", value: \" . $e . \"\\n\";\n  }\n*/\n/*\n// try to access non-existant elements\n\n  $v = array(10, 20, 30);\n  echo \"[7] contains >\".($v[7] == null ? \"null\" : \"??\")\n    .\"<, [12] contains >\".($v[12] == null ? \"null\" : \"??\").\"<\\n\";\n\n  $v[1] = 1.234;\t\t// change the value (and type) of an existing element\n  $v[-10] = 19;\t\t// insert a new element with int key -10\n  $v[5] = 54;\t\t\t// insert a new element with int key 5\n  var_dump($v);\n\n  foreach ($v as $k => $e) {\n    echo \"key: \".$k.\", value: \".$e.\"\\n\";\n  }\n*/\n/*\n  $v = array('x' => 10, 1 => 20, 'y' => 30);\n  $v[\"red\"] = true;\t// insert a new element with string key \"red\"\n  $v[null] = 232;\t\t// insert a new element with string key \"\"\n  var_dump($v);\n\n  foreach ($v as $k => $e) {\n    echo \"key: \".$k.\", value: \".$e.\"\\n\";\n  }\n\n  echo $v[\"red\"].\" \".$v[null].\" \".$v[\"\"].\"\\n\"; // access individual elements by string key\n*/\n/*\n  $v = array(array(2,4,6,8), array(5,10), array(100,200,300));\n  var_dump($v);\n\n  foreach ($v as $k => $e) {\n    echo \"outer key: \" . $k . \"\\n\";\n    foreach ($e as $k2 => $e2) {\n      echo \"inner key: \".$k2.\", inner value: \".$e2.\"\\n\";\n    }\n  }\n\n  var_dump($v[0]); \n  echo \"[0][2]: \".$v[0][2].\"\\n\"; // 6\n  echo \"[1][1]: \".$v[1][1].\"\\n\"; // 10\n*/\n/*\n// show that associativity of () and [] is left-to-right\n\n  $z = array(array(2,4,6,8), array(5,10), array(100,200,300))[0][2];\n  var_dump($z);\n\n  $z = [array(2,4,6,8), array(5,10), array(100,200,300)][0][2];\n  var_dump($z);\n\n  $z = [[2,4,6,8], [5,10], [100,200,300]][0][2];\t// acceses element with value 6\n  var_dump($z);\n\n  var_dump([\"black\", \"white\", \"yellow\"][1]);\t\t// white\n  var_dump([\"black\", \"white\", \"yellow\"][1][2]);\t// 1st [] is for array, 2nd for string\n*/\n/*\n  var_dump(f()[2]);\t// acceses element with value 3000\n*/\n\n/*\n// checkout order of evaluation\n\n  $z = [[2,4,6,8], [5,10], [100,200,300]];\n  $i = 0;\n  var_dump($z[$i++][$i]);\t\t// accesses [0][1] L->R int(4)\n  $i = 0;\n  var_dump($z[$i][$i++]);\t\t// accesses [1][0] R->L int(5)\n  $i = 0;\n  var_dump($z[++$i][$i]);\t\t// accesses [1][1] L->R int(10)\n  $i = 0;\n  var_dump($z[$i][++$i]);\t\t// accesses [1][1] R->L int(10)\n*/\n\n/*\n// unlike PHP, can't subscript scalars\n//\n//  $z = 10;\n//  var_dump($z);\n//  $v = $z[12];\t\t// results in null\n//  var_dump($v);\n//  $v = $z[\"red\"];\t\t// results in null\n//  var_dump($v);\n\n  $z = [[2,4,6,8], [5,10], [100,200,300]];\n  var_dump($z[0][2]);\t// results in 6\n//  var_dump($z[0][2][3]);\t// results in null\n\n  var_dump(f()[2]);\t// results in 3000\n//  var_dump(f()[2][1]);\t// results in null\n\n  $v = 10;\n//  var_dump($v[1]);\t// OK, results in null\n\n  $v = 1.23;\n//  var_dump($v[1]);\t// OK, results in null\n\n  $v = true;\n//  var_dump($v[1]);\t// OK, results in null\n\n  $v = null;\n//  var_dump($v[1]);\t// OK, results in null\n*/\n/*\n// subscript some strings\n\n  var_dump(\"red\"[1]);\t// OK, results in \"e\"\n  var_dump(\"red\"[-1]);\t// OK, results in \"\"\n  var_dump(\"red\"[10]);\t// OK, results in \"\"\n\n// as string[xxx] results in a string, can keep applying more [], indefinitely\n\n  var_dump(\"red\"[0]);\t\t// OK, results in \"r\"\n  var_dump(\"red\"[0][0]);\t\t// OK, results in \"r\"\n  var_dump(\"red\"[0][0][0]);\t// OK, results in \"r\"\n  var_dump(\"red\"[0][0][0][0]);\t// OK, results in \"r\"\n*/\n/*\n// change a string\n\n  $s = \"red\";\n  var_dump($s);\n  $s[1] = \"X\";\t\t// OK; \"e\" -> \"X\"\n  var_dump($s);\n  $s[-5] = \"Y\";\t\t// warning; string unchanged\n  var_dump($s);\n  $s[5] = \"Z\";\t\t// extends string, padding with spaces\n  var_dump($s);\n\n  echo \">\".$s[2].\"<\\n\";\n  echo ($s[2] == \" \") ? \"[2] is a space\\n\" : \"[2] is not a space\\n\";\n  echo \">\".$s[3].\"<\\n\";\n  echo ($s[3] == \" \") ? \"[3] is a space\\n\" : \"[3] is not a space\\n\";\n  echo \">\".$s[4].\"<\\n\";\n  echo ($s[4] == \" \") ? \"[4] is a space\\n\" : \"[4] is not a space\\n\";\n  echo \">\".$s[5].\"<\\n\";\n  echo ($s[5] == \" \") ? \"[5] is a space\\n\" : \"[5] is not a space\\n\";\n\n  $s[0] = \"DEF\";\t\t// \"r\" -> \"D\"; only 1 char changed\n  var_dump($s);\n  $s[0] = \"MN\";\t\t// \"D\" -> \"M\"; only 1 char changed\n  var_dump($s);\n  $s[0] = \"\";\t\t\t// \"M\" -> \"\\0\"\n  var_dump($s);\n*/\n/*\n  echo \"--------------------\\n\";\n\n  $v = array();\n  $v[] = 10;\t\t\t\t// inserts using a key of the next available int value\n  $v[\"XX\"] = 3;\n  $v[5] = 99;\n  $v[] = -2.3;\n  $v[\"AA\"] = 234;\n  $v[12] = 100;\n  $v[] = 'red';\n  var_dump($v);\n*/\n/*\n// Hack does not support deprecated {}\n\n  $colors = array(\"red\", \"white\");\n  var_dump($colors);\n\n  var_dump($colors[0]);\n  var_dump($colors { 0 } );\n\n  $colors { 1 } = 123;\n  var_dump($colors);\n\n  ++$colors{1};\n  var_dump($colors);\n\n  $strs = [[10, 20], [\"abc\", \"xyz\"]];\n  var_dump($strs);\n  $strs[0][0] = 1.1;\n  $strs[0]{1} = 2.2;\n  $strs{1}[0] = 3.3;\n  $strs{1}{1} = 4.4;\n  var_dump($strs);\n*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/subscripting.php.expect",
    "content": ""
  },
  {
    "path": "tests/Expressions/Postfix_Operators/subscripting_2.php",
    "content": "<?hh // strict\n\nnamespace NS_subscripting_2;\n\nfunction main(): void {\n  echo \"====== vector-like array without index; simple assignment =========\\n\";\n\n  $a = array(33, -11);\n  var_dump($a[] = 991);\t\t// creates $a[2]\n  var_dump($a);\n  echo \"------\\n\";\n\n  echo \"====== array without index; compound assignment =========\\n\";\n\n  $a = array(33, -11);\n  var_dump($a[] += 991);\t\t// creates $a[2]\n  var_dump($a);\n  echo \"------\\n\";\n\n  $a = array(33, -11);\n  var_dump($a[] -= 991);\t\t// creates $a[2]\n  var_dump($a);\n  echo \"------\\n\";\n\n  $a = array(33, -11);\n  var_dump($a[] *= 991);\t\t// creates $a[2]\n  var_dump($a);\n\n  echo \"====== array without index; ++/-- =========\\n\";\n\n  $a = array(33, -11);\n  var_dump($a[]++);\n  var_dump($a);\n  echo \"------\\n\";\n\n  var_dump(++$a[]);\n  var_dump($a);\n  echo \"------\\n\";\n\n  var_dump(--$a[]);\n  var_dump($a);\n\n// Hack does not permit a map-like array to have an element appended using an empty []\n//\n//  echo \"====== map-like array without index; simple assignment =========\\n\";\n//\n//  $a = array(3 => 33, -1 => -11);\n//  var_dump($a[] = 991);\t\t// creates $a[4]\n//  var_dump($a);\n//  echo \"------\\n\";\n\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/subscripting_2.php.expect",
    "content": "====== vector-like array without index; simple assignment =========\nint(991)\narray(3) {\n  [0]=>\n  int(33)\n  [1]=>\n  int(-11)\n  [2]=>\n  int(991)\n}\n------\n====== array without index; compound assignment =========\nint(991)\narray(3) {\n  [0]=>\n  int(33)\n  [1]=>\n  int(-11)\n  [2]=>\n  int(991)\n}\n------\nint(-991)\narray(3) {\n  [0]=>\n  int(33)\n  [1]=>\n  int(-11)\n  [2]=>\n  int(-991)\n}\n------\nint(0)\narray(3) {\n  [0]=>\n  int(33)\n  [1]=>\n  int(-11)\n  [2]=>\n  int(0)\n}\n====== array without index; ++/-- =========\nNULL\narray(3) {\n  [0]=>\n  int(33)\n  [1]=>\n  int(-11)\n  [2]=>\n  int(1)\n}\n------\nint(1)\narray(4) {\n  [0]=>\n  int(33)\n  [1]=>\n  int(-11)\n  [2]=>\n  int(1)\n  [3]=>\n  int(1)\n}\n------\nNULL\narray(5) {\n  [0]=>\n  int(33)\n  [1]=>\n  int(-11)\n  [2]=>\n  int(1)\n  [3]=>\n  int(1)\n  [4]=>\n  NULL\n}"
  },
  {
    "path": "tests/Expressions/Postfix_Operators/subscripting_2.php.expectf",
    "content": "\nFatal error: HH mode: content before <?hh (Line: 1, Char: 2)\nsyntax error, unexpected T_HH_ERROR, expecting $end in %s/tests/Expressions/Postfix_Operators/subscripting_2.php on line 1"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Primary_Expressions/Point.php",
    "content": "<?hh // strict\n\nnamespace NS_intrinsics_echo;\n\nclass Point {\n  private float $x;\t\t// Cartesian x-coordinate\n  private float $y;\t\t// Cartesian y-coordinate\n\n  public function getX(): float \t{ return $this->x; }\n  public function setX(float $x): void\t{ $this->x = $x;   }\n  public function getY(): float\t\t{ return $this->y; }\n  public function setY(float $y): void\t{ $this->y = $y;   }\n\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    $this->x = $x;\n    $this->y = $y;\n  }\n\n  public function move(float $x, float $y): void {\n    $this->x = $x;\n    $this->y = $y;\n  }\t\n\n  public function translate(float $x, float $y): void {\n    $this->x += $x;\n    $this->y += $y;\n  }\n\n  public function __toString(): string {\n    return '(' . $this->x . ',' . $this->y . ')';\n  }\t\n}\n"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/Point.php.expect",
    "content": ""
  },
  {
    "path": "tests/Expressions/Primary_Expressions/Point2.php",
    "content": "<?hh // strict\n\nnamespace NS_intrinsics_exit;\n\nclass Point2 {\n  private static int $pointCount = 0;\n\n  public float $x;\t\t// Cartesian x-coordinate\n  public float $y;\t\t// Cartesian y-coordinate\n\n  public static function getPointCount(): int {\n    return self::$pointCount;\n  }\n\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    $this->x = $x;\n    $this->y = $y;\n    ++self::$pointCount;\n  }\n\n  public function __destruct() {\n    --self::$pointCount;\n  }\n\n  public function __toString(): string {\n    return '(' . $this->x . ',' . $this->y . ')';\n  }\t\n}\n"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/Point2.php.expect",
    "content": ""
  },
  {
    "path": "tests/Expressions/Primary_Expressions/intrinsics_echo.php",
    "content": "<?hh // strict\n\nnamespace NS_intrinsics_echo;\n\nrequire_once 'Point.php';\n\nfunction main(): void {\n  $v1 = true;\n  $v2 = 123;\n  $v3 = 20.3E2;\n  $v4 = null;\n  $v5 = \"Hello\";\n  $v6 = new \\NS_intrinsics_echo\\Point(3.0, 5.0);\n\n  echo '>>' . $v1 . '|' . $v2 . \"<<\\n\";\n  echo '>>' , $v1 , '|' , $v2 , \"<<\\n\";\n  echo ('>>' . $v1 . '|' . $v2 . \"<<\\n\");\n  echo (('>>') . ($v1) . ('|') . ($v2) . (\"<<\\n\"));// outer parens are part of optional syntax\n\t\t\t\t\t\t\t// inner ones are redundant grouping parens\n//  echo ('>>' , $v1 , '|' , $v2 , \"<<\\n\");\t// parens no allowed with commas\n\n  echo '>>' . $v3 . '|' . $v4 . '|' . $v5 . '|' . $v6 . \"<<\\n\";\n  echo '>>' , $v3 , '|' , $v4 , '|' , $v5 , '|' , $v6 , \"<<\\n\";\n\n  $v3 = \"qqq{$v2}zzz\";\n  var_dump($v3);\n  echo \"$v3\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/intrinsics_echo.php.expect",
    "content": ">>1|123<<\n>>1|123<<\n>>1|123<<\n>>1|123<<\n>>2030||Hello|(3,5)<<\n>>2030||Hello|(3,5)<<\nstring(9) \"qqq123zzz\"\nqqq123zzz"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/intrinsics_exit.php",
    "content": "<?hh // strict\n\nnamespace NS_intrinsics_exit;\n\nrequire_once('Point2.php');\n\nfunction cleanup1(): void {\n  echo \"Inside \" . __METHOD__ . \"\\n\";\n}\n\nfunction cleanup2(): void {\n  echo \"Inside \" . __METHOD__ . \"\\n\";\n}\n\nfunction main(): void {\n  register_shutdown_function('cleanup2');\n  register_shutdown_function('cleanup1');\n\n  echo \"--------- test with/without string -------------\\n\";\n\n  $p1 = new Point2(5.0, 3.0);\n  $p2 = new Point2();\n  $p3 = new Point2();\n\n  exit(\"goodbye\\n\");\t// writes \"goodbye\", then destructors are called.\n//  exit(99);\t\t// writes nothing\n//  exit();\t\t\t// writes nothing\n//  exit;\t\t\t// writes nothing\n\n  echo \"end of script\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/intrinsics_exit.php.expect",
    "content": "--------- test with/without string -------------\ngoodbye\n\nWarning: Invalid argument: function: method 'cleanup2' not found\n\nWarning: Invalid argument: function: method 'cleanup1' not found"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/intrinsics_invariant.php",
    "content": "<?hh // strict\n\nnamespace NS_intrinsics_invariant;\n\ninterface I {\n  public function foo(): void;\n}\n\nclass A implements I {\n  public function foo(): void {\n    echo \"A\";\n  }\n}\n\nclass B implements I {\n  public function foo(): void {\n    echo \"B\";\n  }\n\n  public function yay(): void {\n    echo \"B->yay!\";\n  }\n}\n\nfunction baz(int $a): I {\n  return $a === 1 ? new A() : new B();\n}\n\nfunction bar(): B {\n  $iface = baz(2);\n  invariant($iface instanceof B, \"Object must have type B\");\n  $iface->yay();\n  return $iface;\n}\n\nfunction main(?int $p): void {\n  bar();\n\n  invariant(!is_null($p), \"Value can't be null\");\n  $v = $p << 2;\n\n  $max = 100;\n  invariant(!is_null($p) && $p <= $max, \"Value %d must be <= %d\", $p, $max);\n}\n\n//main(123);\n//main(null);\n"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/intrinsics_invariant.php.expect",
    "content": ""
  },
  {
    "path": "tests/Expressions/Primary_Expressions/intrinsics_list.php",
    "content": "<?hh // strict\n\nnamespace NS_intrinsics_list;\n\nfunction main(): void {\n  $min = -99;\n  $max = -99;\n  $avg = -99;\n\n///*\n  echo \"--------- test with full and omitted LHS vars -------------\\n\";\n\n  $v = list($min, $max, $avg) = array(0, 100, 67);\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n//*/\n\n/*\n// cannot assign a map-like array to a list\n\n  $v = list($min, $max, $avg) = array(2 => 67, 1 => 100, 0 => 0);\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n*/\n\n/*\n// Can't omit arguments in a list, EXCEPT for the final one\n\n  list($min, , $avg) = array(0, 100, 67);\n  echo \"\\$min: $min, , \\$avg: $avg\\n\";\n\n  list(, $max, $avg) = array(0, 100, 67);\n  echo \", \\$max: $max, \\$avg: $avg\\n\";\n\n  list(, , $avg) = array(0, 100, 67);\n  echo \", , \\$avg: $avg\\n\";\n*/\n\n///*\n  // UNSAFE (type error here - seems to work for collection like Vector but not array, maybe?)\n  list($min, $max,) = array(10, 1100, 167);\n  echo \"\\$min: $min, \\$max: $max,\\n\";\n\n  // UNSAFE (type error here - seems to work for collection like Vector but not array, maybe?)\n  list($min, $max) = array(20, 2100, 267);\n  echo \"\\$min: $min, \\$max: $max\\n\";\n\n//  list($min, , ) = array(0, 100, 67);\n//  echo \"\\$min: $min, ,\\n\";\n\n  list($min) = array(30, 3100, 367);\n  echo \"\\$min: $min\\n\";\n//*/\n\n///*\n  echo \"--------- test with more array elements than variables -------------\\n\";\n\n  $v = list($min, $max, $avg) = array(40, 4100, 467, 22, 33);\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n//*/\n\n/*\n  echo \"--------- test with fewer array elements than variables -------------\\n\";\n\n  $v = list($min, $max, $avg) = array(-100, -500);\t// Undefined offset: 2\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n*/\n\n/*\n// can't use nested lists\n\n  echo \"--------- test with nested lists -------------\\n\";\n\n  $v = list($min, list($max, $avg)) = [0, [67, 99, 100], 33];\n//  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n*/\n\n///*\n  echo \"--------- test with target vars being array elements -------------\\n\";\n\n  $a = array();\n  $v = list($a[0], $a[2], $a[4]) = array(50, 5100, 567);\n  print_r($a);\n  print_r($v);\n//*/\n\n///*\n  echo \"--------- test with no variables -------------\\n\";\n\n  $v = list() = array(0, 100, 67);\n  print_r($v);\n//*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/intrinsics_list.php.expect",
    "content": "--------- test with full and omitted LHS vars -------------\n$min: 0, $max: 100, $avg: 67\nArray\n(\n    [0] => 0\n    [1] => 100\n    [2] => 67\n)\n$min: 10, $max: 1100,\n$min: 20, $max: 2100\n$min: 30\n--------- test with more array elements than variables -------------\n$min: 40, $max: 4100, $avg: 467\nArray\n(\n    [0] => 40\n    [1] => 4100\n    [2] => 467\n    [3] => 22\n    [4] => 33\n)\n--------- test with target vars being array elements -------------\nArray\n(\n    [4] => 567\n    [2] => 5100\n    [0] => 50\n)\nArray\n(\n    [0] => 50\n    [1] => 5100\n    [2] => 567\n)\n--------- test with no variables -------------\nArray\n(\n    [0] => 0\n    [1] => 100\n    [2] => 67\n)"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/listPHP.php",
    "content": "<?php\n\nnamespace NS_intrinsics_listXX;\n\nfunction main(): void {\n  $min = -99;\n  $max = -99;\n  $avg = -99;\n\n///*\n  echo \"--------- test with full and omitted LHS vars -------------\\n\";\n\n  $v = list($min, $max, $avg) = array(0, 100, 67);\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n//*/\n\n/*\n// cannot assign a map-like array to a list\n\n  $v = list($min, $max, $avg) = array(2 => 67, 1 => 100, 0 => 0);\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n*/\n\n/*\n// Can't omit arguments in a list, EXCEPT for the final one\n\n  list($min, , $avg) = array(0, 100, 67);\n  echo \"\\$min: $min, , \\$avg: $avg\\n\";\n\n  list(, $max, $avg) = array(0, 100, 67);\n  echo \", \\$max: $max, \\$avg: $avg\\n\";\n\n  list(, , $avg) = array(0, 100, 67);\n  echo \", , \\$avg: $avg\\n\";\n*/\n\n///*\n  list($min, $max, ) = array(10, 1100, 167);\n  echo \"\\$min: $min, \\$max: $max,\\n\";\n\n  list($min, $max) = array(20, 2100, 267);\n  echo \"\\$min: $min, \\$max: $max\\n\";\n\n//  list($min, , ) = array(0, 100, 67);\n//  echo \"\\$min: $min, ,\\n\";\n\n  list($min) = array(30, 3100, 367);\n  echo \"\\$min: $min\\n\";\n//*/\n\n///*\n  echo \"--------- test with more array elements than variables -------------\\n\";\n\n  $v = list($min, $max, $avg) = array(40, 4100, 467, 22, 33);\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n//*/\n\n/*\n  echo \"--------- test with fewer array elements than variables -------------\\n\";\n\n  $v = list($min, $max, $avg) = array(-100, -500);\t// Undefined offset: 2\n  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n*/\n\n/*\n// can't use nested lists\n\n  echo \"--------- test with nested lists -------------\\n\";\n\n  $v = list($min, list($max, $avg)) = [0, [67, 99, 100], 33];\n//  echo \"\\$min: $min, \\$max: $max, \\$avg: $avg\\n\";\n  print_r($v);\n*/\n\n///*\n  echo \"--------- test with target vars being array elements -------------\\n\";\n\n  $a = array();\n  $v = list($a[0], $a[2], $a[4]) = array(50, 5100, 567);\n  print_r($a);\n  print_r($v);\n//*/\n\n///*\n  echo \"--------- test with no variables -------------\\n\";\n\n  $v = list() = array(0, 100, 67);\n  print_r($v);\n//*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/listPHP.php.expect",
    "content": "--------- test with full and omitted LHS vars -------------\n$min: 0, $max: 100, $avg: 67\nArray\n(\n    [0] => 0\n    [1] => 100\n    [2] => 67\n)\n$min: 10, $max: 1100,\n$min: 20, $max: 2100\n$min: 30\n--------- test with more array elements than variables -------------\n$min: 40, $max: 4100, $avg: 467\nArray\n(\n    [0] => 40\n    [1] => 4100\n    [2] => 467\n    [3] => 22\n    [4] => 33\n)\n--------- test with target vars being array elements -------------\nArray\n(\n    [4] => 567\n    [2] => 5100\n    [0] => 50\n)\nArray\n(\n    [0] => 50\n    [1] => 5100\n    [2] => 567\n)\n--------- test with no variables -------------\nArray\n(\n    [0] => 0\n    [1] => 100\n    [2] => 67\n)"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/primary.php",
    "content": "<?hh // strict\n\nnamespace NS_primary;\n\nfunction main(): void {\n//  ($i) = 100;\t\n  $i = 100;\n  var_dump(((($i) + (10))));\n\n  $a = [100, 200];\n  var_dump($a[0]);\n  var_dump(($a[0]));\t\t// redundant grouping parens\n  var_dump(($a)[0]);\t\t// redundant grouping parens\n\n  $z = [[2,4,6,8], [5,10], [100,200,300]];\n  var_dump($z[0][2]);\n  var_dump(($z[0])[2]);\t\t// redundant grouping parens\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Primary_Expressions/primary.php.expect",
    "content": "int(110)\nint(100)\nint(100)\nint(100)\nint(6)\nint(6)"
  },
  {
    "path": "tests/Expressions/Relational_Operators/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Relational_Operators/Testfile1.txt",
    "content": "Once upon a time,\nin a land\nfar,   \nfar away,  \nthere lived an ogre called Big Bad Bruce.\n"
  },
  {
    "path": "tests/Expressions/Relational_Operators/Testfile2.txt",
    "content": "Once upon a time,\nin a land\nfar,   \nfar away,  \nthere lived an ogre called Big Bad Bruce.\n"
  },
  {
    "path": "tests/Expressions/Relational_Operators/combined_comparison.php",
    "content": "// NOT YET IMPLEMENTED IN THE CHECKER <?hh // strict\n\nnamespace NS_combined_comparison;\n\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2015 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\nfunction main(): void {\n\n// Integers\n\n  echo (1 <=> 1) . \"\\n\"; // 0\n  echo (1 <=> 2) . \"\\n\"; // -1\n  echo (2 <=> 1) . \"\\n\"; // 1\n\n// Floats\n\n  echo (1.5 <=> 1.5) . \"\\n\"; // 0\n  echo (1.5 <=> 2.5) . \"\\n\"; // -1\n  echo (2.5 <=> 1.5) . \"\\n\"; // 1\n \n// Strings\n\n  echo (\"a\" <=> \"a\") . \"\\n\"; // 0\n  echo (\"a\" <=> \"b\") . \"\\n\"; // -1\n  echo (\"b\" <=> \"a\") . \"\\n\"; // 1\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Relational_Operators/combined_comparison.php.expectf",
    "content": "\nFatal error: HH mode: content before <?hh (Line: 1, Char: 38)\nsyntax error, unexpected T_HH_ERROR, expecting $end in %s/tests/Expressions/Relational_Operators/combined_comparison.php on line 1"
  },
  {
    "path": "tests/Expressions/Relational_Operators/comparisons.php",
    "content": "<?hh // strict\n\nnamespace NS_comparisons;\n\nfunction doit1(num $p1_num, ?int $p2_nint): void {\n/*\n  echo \"====== checkout the type and value of the result ======\\n\\n\";\n\n  $a = 10 < 20;\n  var_dump($a);\t// bool(true)\n  $a = 10 >= 20;\n  var_dump($a);\t// bool(false)\t\n  $a = \"zz\" > \"xx\";\n  var_dump($a);\t// bool(true)\n*/\n\n/*\n// all incompatible pairs of types\n\n  var_dump(null > true);\n  var_dump(true >= 100);\n  var_dump(null < 1.23);\n  var_dump(false <= \"123\");\n\n  var_dump($p1_num > $p2_nint);\n  var_dump($p1_num >= $p2_nint);\n  var_dump($p1_num < $p2_nint);\n  var_dump($p1_num <= $p2_nint);\n*/\n\n/*\n  echo \"\\n====== compare arithmetic ops ======\\n\\n\";\n\n  var_dump(100 > 12.3);\t\t// true\n  var_dump(100 >= $p1_num);\t// true\n  var_dump($p1_num < 5.6);\t// false when $p1_num == 11\n*/\n\n/*\n  echo \"\\n====== compare Boolean ops ======\\n\\n\";\n\n// surprise; Boolean comparisons are ordered!\n\n  var_dump(true > false);\t\t// true\n  var_dump(true < false);\t\t// false\n  var_dump(false <= true);\t// true\n*/\n\n/*\n  echo \"\\n====== compare null ops ======\\n\\n\";\n\n// surprise; this compiles!\n\n  var_dump(null < null);\t\t// false\n  var_dump(null > null);\t\t// false\n*/\n\n/*\n  echo \"\\n====== compare null with nullable ======\\n\\n\";\n\n// hmmm\n// when $p2_nint == null\n\n  var_dump($p2_nint);\t\t// null\n  var_dump(null > $p2_nint);\t// false\n  var_dump(null >= $p2_nint);\t// true\n  var_dump(null < $p2_nint);\t// false\n  var_dump(null <= $p2_nint);\t// true\n\n// when $p2_nint != null and non-zero, get false, false, true, true, so is doing numeric comparison\n\n// when $p2_nint != null and is zero, get false, true, false, true, so can't distinguish between null and zero\n*/\n\n/*\n  echo \"\\n====== compare numeric-string ops ======\\n\\n\";\n\n  var_dump('123' <= '4');\t\t// false; is doing a numeric comparison\n  var_dump('X123' <= 'X4');\t// true; is doing a string comparison\n  var_dump(123 <= 4);\t\t// false; numeric comparison\n// var_dump('123' <= 4);\t\t// incompatible types\n//  var_dump(123 <= '4');\t\t// incompatible types\n*/\n\n/*\n  echo \"\\n====== compare non-numeric-string ops ======\\n\\n\";\n\n  $oper1 = array(\"\", \"a\", \"aa\", \"a0\", \"aA\");\n  $oper2 = array(\"\", \"ab\", \"abc\", \"A\", \"AB\");\n\n  foreach ($oper1 as $e1) {\n    foreach ($oper2 as $e2) {\n      echo \"{$e1} >  {$e2}  result: \"; var_dump($e1 > $e2);\n      echo \"{$e2} <= {$e1}  result: \"; var_dump($e2 <= $e1);\n      echo \"---\\n\";\n      echo \"{$e1} >= {$e2}  result: \"; var_dump($e1 >= $e2);\n      echo \"{$e2} <  {$e1}  result: \"; var_dump($e2 < $e1);\n      echo \"---\\n\";\n      echo \"{$e1} <  {$e2}  result: \"; var_dump($e1 < $e2);\n      echo \"{$e2} >= {$e1}  result: \"; var_dump($e2 >= $e1);\n      echo \"---\\n\";\n      echo \"{$e1} <= {$e2}  result: \"; var_dump($e1 <= $e2);\n      echo \"{$e2} >  {$e1}  result: \"; var_dump($e2 > $e1);\n      echo \"=======\\n\";\n    }\n    echo \"-------------------------------------\\n\";\n  }\n*/\n\n/*\n  echo \"\\n====== compare resource ops ======\\n\\n\";\n\n  $infile1 = fopen(\"Testfile1.txt\", 'r');\n  $infile2 = fopen(\"Testfile2.txt\", 'r');\n  var_dump($infile1, $infile2);\n\n// surprise; this compiles!\n\n  var_dump($infile1 > $infile2);\t// false (4 > 5)\n  var_dump($infile1 < $infile2);\t// true (4 < 5)\n*/\n}\n\nfunction doit2(array<int> $p1, array<int> $p2, array<float> $p3): void {\n  var_dump($p1, $p2);\n  echo \"{\\$p1} >  {\\$p2}  result: \"; var_dump($p1 > $p2);\n  echo \"{\\$p2} <= {\\$p1}  result: \"; var_dump($p2 <= $p1);\n  echo \"---\\n\";\n  echo \"{\\$p1} >= {\\$p2}  result: \"; var_dump($p1 >= $p2);\n  echo \"{\\$p2} <  {\\$p1}  result: \"; var_dump($p2 < $p1);\n  echo \"---\\n\";\n  echo \"{\\$p1} <  {\\$p2}  result: \"; var_dump($p1 < $p2);\n  echo \"{\\$p2} >= {\\$p1}  result: \"; var_dump($p2 >= $p1);\n  echo \"---\\n\";\n  echo \"{\\$p1} <= {\\$p2}  result: \"; var_dump($p1 <= $p2);\n  echo \"{\\$p2} >  {\\$p1}  result: \"; var_dump($p2 > $p1);\n  echo \"---\\n\";\n  echo \"{\\$p1} == {\\$p2}  result: \"; var_dump($p1 == $p2);\n  echo \"{\\$p1} != {\\$p2}  result: \"; var_dump($p1 != $p2);\n  echo \"=======\\n\";\n//  var_dump($p3);\n//  echo \"{\\$p3} >  {\\$p2}  result: \"; var_dump($p3 > $p2);\t// correctly rejected\n}\n\nfunction doit3(array<string, int> $p1, array<string, int> $p2): void {\n  var_dump($p1, $p2);\n  echo \"{\\$p1} >  {\\$p2}  result: \"; var_dump($p1 > $p2);\n  echo \"{\\$p2} <= {\\$p1}  result: \"; var_dump($p2 <= $p1);\n  echo \"---\\n\";\n  echo \"{\\$p1} >= {\\$p2}  result: \"; var_dump($p1 >= $p2);\n  echo \"{\\$p2} <  {\\$p1}  result: \"; var_dump($p2 < $p1);\n  echo \"---\\n\";\n  echo \"{\\$p1} <  {\\$p2}  result: \"; var_dump($p1 < $p2);\n  echo \"{\\$p2} >= {\\$p1}  result: \"; var_dump($p2 >= $p1);\n  echo \"---\\n\";\n  echo \"{\\$p1} <= {\\$p2}  result: \"; var_dump($p1 <= $p2);\n  echo \"{\\$p2} >  {\\$p1}  result: \"; var_dump($p2 > $p1);\n  echo \"---\\n\";\n  echo \"{\\$p1} == {\\$p2}  result: \"; var_dump($p1 == $p2);\n  echo \"{\\$p1} != {\\$p2}  result: \"; var_dump($p1 != $p2);\n  echo \"=======\\n\";\n}\n\nfunction main(): void {\n  doit1(11, 0);\n\n/*\n  $oper1 = array([], [10,20]);\n  $oper2 = array([], [10,20], [10,20,30], [10,30]);\n\n  foreach ($oper1 as $e1) {\n    foreach ($oper2 as $e2) {\n      doit2($e1, $e2, array(2.5, 6.7));\n    }\n  }\n*/\n\n///*\n  doit3(array(\"red\" => 0,\"green\" => 0), array(\"red\" => 0,\"green\" => 0));\n  doit3(array(\"red\" => 0,\"green\" => 0), array(\"green\" => 0,\"red\" => 0));\n  doit3(array(\"red\" => 0,\"green\" => 0), array(\"green\" => 0,\"red\" => 5));\n  doit3(array(\"red\" => 0,\"green\" => 0), array(\"green\" => -5,\"red\" => 5));\n  doit3(array(\"red\" => 0,\"green\" => 0), array(\"green\" => -5,\"red\" => 0));\n\n  doit3(array(\"red\" => 0), array(\"green\" => 0));\n  doit3(array(\"green\" => 0), array(\"red\" => 0));\n//*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Relational_Operators/comparisons.php.expect",
    "content": "array(2) {\n  [\"red\"]=>\n  int(0)\n  [\"green\"]=>\n  int(0)\n}\narray(2) {\n  [\"red\"]=>\n  int(0)\n  [\"green\"]=>\n  int(0)\n}\n{$p1} >  {$p2}  result: bool(false)\n{$p2} <= {$p1}  result: bool(true)\n---\n{$p1} >= {$p2}  result: bool(true)\n{$p2} <  {$p1}  result: bool(false)\n---\n{$p1} <  {$p2}  result: bool(false)\n{$p2} >= {$p1}  result: bool(true)\n---\n{$p1} <= {$p2}  result: bool(true)\n{$p2} >  {$p1}  result: bool(false)\n---\n{$p1} == {$p2}  result: bool(true)\n{$p1} != {$p2}  result: bool(false)\n=======\narray(2) {\n  [\"red\"]=>\n  int(0)\n  [\"green\"]=>\n  int(0)\n}\narray(2) {\n  [\"green\"]=>\n  int(0)\n  [\"red\"]=>\n  int(0)\n}\n{$p1} >  {$p2}  result: bool(false)\n{$p2} <= {$p1}  result: bool(true)\n---\n{$p1} >= {$p2}  result: bool(true)\n{$p2} <  {$p1}  result: bool(false)\n---\n{$p1} <  {$p2}  result: bool(false)\n{$p2} >= {$p1}  result: bool(true)\n---\n{$p1} <= {$p2}  result: bool(true)\n{$p2} >  {$p1}  result: bool(false)\n---\n{$p1} == {$p2}  result: bool(true)\n{$p1} != {$p2}  result: bool(false)\n=======\narray(2) {\n  [\"red\"]=>\n  int(0)\n  [\"green\"]=>\n  int(0)\n}\narray(2) {\n  [\"green\"]=>\n  int(0)\n  [\"red\"]=>\n  int(5)\n}\n{$p1} >  {$p2}  result: bool(false)\n{$p2} <= {$p1}  result: bool(false)\n---\n{$p1} >= {$p2}  result: bool(false)\n{$p2} <  {$p1}  result: bool(false)\n---\n{$p1} <  {$p2}  result: bool(true)\n{$p2} >= {$p1}  result: bool(true)\n---\n{$p1} <= {$p2}  result: bool(true)\n{$p2} >  {$p1}  result: bool(true)\n---\n{$p1} == {$p2}  result: bool(false)\n{$p1} != {$p2}  result: bool(true)\n=======\narray(2) {\n  [\"red\"]=>\n  int(0)\n  [\"green\"]=>\n  int(0)\n}\narray(2) {\n  [\"green\"]=>\n  int(-5)\n  [\"red\"]=>\n  int(5)\n}\n{$p1} >  {$p2}  result: bool(true)\n{$p2} <= {$p1}  result: bool(true)\n---\n{$p1} >= {$p2}  result: bool(true)\n{$p2} <  {$p1}  result: bool(true)\n---\n{$p1} <  {$p2}  result: bool(true)\n{$p2} >= {$p1}  result: bool(true)\n---\n{$p1} <= {$p2}  result: bool(true)\n{$p2} >  {$p1}  result: bool(true)\n---\n{$p1} == {$p2}  result: bool(false)\n{$p1} != {$p2}  result: bool(true)\n=======\narray(2) {\n  [\"red\"]=>\n  int(0)\n  [\"green\"]=>\n  int(0)\n}\narray(2) {\n  [\"green\"]=>\n  int(-5)\n  [\"red\"]=>\n  int(0)\n}\n{$p1} >  {$p2}  result: bool(true)\n{$p2} <= {$p1}  result: bool(true)\n---\n{$p1} >= {$p2}  result: bool(true)\n{$p2} <  {$p1}  result: bool(true)\n---\n{$p1} <  {$p2}  result: bool(false)\n{$p2} >= {$p1}  result: bool(false)\n---\n{$p1} <= {$p2}  result: bool(false)\n{$p2} >  {$p1}  result: bool(false)\n---\n{$p1} == {$p2}  result: bool(false)\n{$p1} != {$p2}  result: bool(true)\n=======\narray(1) {\n  [\"red\"]=>\n  int(0)\n}\narray(1) {\n  [\"green\"]=>\n  int(0)\n}\n{$p1} >  {$p2}  result: bool(false)\n{$p2} <= {$p1}  result: bool(false)\n---\n{$p1} >= {$p2}  result: bool(false)\n{$p2} <  {$p1}  result: bool(false)\n---\n{$p1} <  {$p2}  result: bool(false)\n{$p2} >= {$p1}  result: bool(false)\n---\n{$p1} <= {$p2}  result: bool(false)\n{$p2} >  {$p1}  result: bool(false)\n---\n{$p1} == {$p2}  result: bool(false)\n{$p1} != {$p2}  result: bool(true)\n=======\narray(1) {\n  [\"green\"]=>\n  int(0)\n}\narray(1) {\n  [\"red\"]=>\n  int(0)\n}\n{$p1} >  {$p2}  result: bool(false)\n{$p2} <= {$p1}  result: bool(false)\n---\n{$p1} >= {$p2}  result: bool(false)\n{$p2} <  {$p1}  result: bool(false)\n---\n{$p1} <  {$p2}  result: bool(false)\n{$p2} >= {$p1}  result: bool(false)\n---\n{$p1} <= {$p2}  result: bool(false)\n{$p2} >  {$p1}  result: bool(false)\n---\n{$p1} == {$p2}  result: bool(false)\n{$p1} != {$p2}  result: bool(true)\n======="
  },
  {
    "path": "tests/Expressions/Relational_Operators/relational_comparison_of_objects.php",
    "content": "<?hh // strict\n\nnamespace NS_relational_comparison_of_objects;\n\nclass C1 {}\nclass C2 {}\nclass C3 { public int $x = -1; }\nclass C4 { public int $y = -10; public int $x = -11; }\n\nfunction main(): void {\n  $c1a = new C1(); // var_dump($c1a);\n  $c1b = new C1(); // var_dump($c1b);\n  $c2 = new C2();  // var_dump($c2);\n\n/*\n  var_dump($c1a >= 10);\t// different types; incompatible\n  var_dump($c1a < 10.5);\t// different types; incompatible\n  var_dump($c1a > '12');\t// different types; incompatible\n  var_dump($c1a <= true);\t// different types; incompatible\n*/\n\n//  echo \"\\n===== compare instances of different object types =====\\n\\n\";\n\n//  var_dump($c1a >= $c2);\t// different types; incompatible\n\t\n//  var_dump($c1a <= $c2);\t// different types; incompatible\n//  var_dump($c1a <  $c2);\t// different types; incompatible\n\n  echo \"\\n===== compare instances of the same (empty) object type =====\\n\\n\";\n\n  var_dump($c1a >= $c1b);\t// bool(true)\n  var_dump($c1a >  $c1b);\t// bool(false)\n  var_dump($c1a <= $c1b);\t// bool(true)\n  var_dump($c1a <  $c1b);\t// bool(false)\n\n  echo \"\\n===== compare instances of the same object type with same values =====\\n\\n\";\n\n  $c3a = new C3(); $c3a->x = 5; // var_dump($c3a);\n  $c3b = new C3(); $c3b->x = 5; // var_dump($c3b);\n\n  var_dump($c3a >= $c3b);\t// bool(true)\n  var_dump($c3a >  $c3b);\t// bool(false)\n  var_dump($c3a <= $c3b);\t// bool(true)\n  var_dump($c3a <  $c3b);\t// bool(false)\n\n  echo \"\\n===== compare instances of the same object type with diff values =====\\n\\n\";\n\n  $c3b->x = 7; // var_dump($c3a); var_dump($c3b);\n\n  var_dump($c3a >= $c3b);\t// bool(false)\n  var_dump($c3a >  $c3b);\t// bool(false)\n  var_dump($c3a <= $c3b);\t// bool(true)\n  var_dump($c3a <  $c3b);\t// bool(true)\n\n  echo \"\\n===== compare instances of the same object type with a pair of diff values =====\\n\\n\";\n\n// comparison seems to be done in lexical order of property definition; swapping\n// the order of y and x gives different relational op results\n\n  $c4a = new C4(); $c4a->x = 3; $c4a->y = 6; // var_dump($c4a);\n  $c4b = new C4(); $c4b->x = 5; $c4b->y = 2; // var_dump($c4b);\n\n  var_dump($c4a >= $c4b);\t// bool(true)\n  var_dump($c4a >  $c4b);\t// bool(true)\n  var_dump($c4a <= $c4b);\t// bool(false)\n  var_dump($c4a <  $c4b);\t// bool(false)\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Relational_Operators/relational_comparison_of_objects.php.expect",
    "content": "\n===== compare instances of the same (empty) object type =====\n\nbool(true)\nbool(false)\nbool(true)\nbool(false)\n\n===== compare instances of the same object type with same values =====\n\nbool(true)\nbool(false)\nbool(true)\nbool(false)\n\n===== compare instances of the same object type with diff values =====\n\nbool(false)\nbool(false)\nbool(true)\nbool(true)\n\n===== compare instances of the same object type with a pair of diff values =====\n\nbool(true)\nbool(true)\nbool(false)\nbool(false)"
  },
  {
    "path": "tests/Expressions/Testfile.txt",
    "content": "Once upon a time,\nin a land\nfar,   \nfar away,  \nthere lived an ogre called Big Bad Bruce.\n"
  },
  {
    "path": "tests/Expressions/Unary_Operators/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Unary_Operators/cast.php",
    "content": "<?hh // strict\n\nnamespace NS_cast;\n\nfunction main(): void {\n  $v = 0;\n  var_dump((bool)$v);\n//  var_dump((boolean)$v);\t// not permitted\n  var_dump((int)$v);\n//  var_dump((integer)$v);\t// not permitted\n  var_dump((float)$v);\n//  var_dump((double)$v);\t// not permitted\n//  var_dump((real)$v);\n  var_dump((string)$v);\n//  var_dump((array)$v);\t// not permitted\n//  var_dump((object)$v);\t// not permitted\n\n//  var_dump((binary)$v);\t// not permitted\n//  var_dump((binary)\"\");\t// not permitted\n//  var_dump((binary)\"abcdef\");// not permitted\n\n  var_dump($v);\n//  var_dump((unset)$v);\t// currently accepted, but does nothing. Support will be removed\n//  var_dump($v);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Unary_Operators/cast.php.expect",
    "content": "bool(false)\nint(0)\nfloat(0)\nstring(1) \"0\"\nint(0)"
  },
  {
    "path": "tests/Expressions/Unary_Operators/error_control.php",
    "content": "<?hh // strict\n\nnamespace NS_error_control;\n\nfunction main(): void {\n  $infile = fopen(\"NoSuchFile.txt\", 'r');\n  $infile = @fopen(\"NoSuchFile.txt\", 'r');\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Unary_Operators/error_control.php.expectf",
    "content": "\nWarning: No such file or directory in %s/tests/Expressions/Unary_Operators/error_control.php on line 6"
  },
  {
    "path": "tests/Expressions/Unary_Operators/pre-increment_and_decrement.php",
    "content": "<?hh // strict\n\nnamespace NS_pre_increment_and_decrement;\n\nclass C {\n  public int $prop1 = 0;\n}\n\nfunction main(): void {\n  echo \"=== int 5 ===\\n\";\n\n  $v = 5; var_dump(++$v); var_dump(--$v);\n\n  echo \"\\n=== int 0x7fffffffffffffff ===\\n\";\n\n  $v = 0x7fffffffffffffff; var_dump(++$v); var_dump(--$v);\n\n  echo \"\\n=== int 0x80000000 ===\\n\";\n\n  $v = 0x8000000000000000; var_dump(++$v); var_dump(--$v);\n\n  echo \"\\n=== float 12.345 ===\\n\";\n\n  $v = 12.345; var_dump(++$v); var_dump(--$v);\n\n  echo \"\\n=== float INF ===\\n\";\n\n  $v = INF; var_dump(++$v); var_dump(--$v);\n\n  echo \"\\n=== float -INF ===\\n\";\n\n  $v = -INF; var_dump(++$v); var_dump(--$v);\n\n  echo \"\\n=== float NAN ===\\n\";\n\n  $v = NAN; var_dump(++$v); var_dump(--$v);\n/*\n// Hack does not permit null to be the object of a prefix ++/--\n\n  echo \"\\n=== null ===\\n\";\n\n  $v = null; var_dump(++$v); var_dump(--$v);\n*/\n/*\n// Hack does not permit Boolean values to be the object of a prefix ++/--\n\n  echo \"\\n=== true ===\\n\";\n\n  $v = true; var_dump(++$v); var_dump(--$v);\n\n  echo \"\\n=== false ===\\n\";\n\n  $v = false; var_dump(++$v); var_dump(--$v);\n*/\n/*\n// Hack does not permit string values to be the object of a prefix ++/--\n  echo \"\\n=== string \\\"\\\" ===\\n\";\n\n  echo \"---> ++/--/--\\n\";\n  $v = \"\"; var_dump(++$v); var_dump($v--); var_dump(--$v);\n  echo \"\\n---> --/++/++\\n\";\n  $v = \"\"; var_dump(--$v); var_dump(++$v); var_dump(++$v);\n\n  echo \"\\n=== string \\\"0\\\" ===\\n\";\n\n  echo \"---> ++/--/--\\n\";\n  $v = \"0\"; var_dump(++$v); var_dump(--$v); var_dump(--$v);\n  echo \"\\n---> --/++/++\\n\";\n  $v = \"0\"; var_dump(--$v); var_dump($v++); var_dump($v++);\n\n  echo \"\\n=== string \\\"-26\\\" ===\\n\";\n\n  echo \"---> ++/--/--\\n\";\n  $v = \"-26\"; var_dump(++$v); var_dump($v--); var_dump(--$v);\n  echo \"\\n---> --/++/++\\n\";\n  $v = \"-26\"; var_dump(--$v); var_dump($v++); var_dump(++$v);\n\n  echo \"\\n=== string \\\"a\\\" ===\\n\";\n\n  echo \"---> ++/--/--\\n\";\n  $v = \"a\"; var_dump(++$v); var_dump($v--); var_dump(--$v);\n  echo \"\\n---> --/++/++\\n\";\n  $v = \"a\"; var_dump(--$v); var_dump($v++); var_dump(++$v);\n*/\n echo \"=== ?int ===\\n\";\n\n  $c = new C();\n\n  echo \"---> ++/--/--\\n\";\n  $c->prop1 = 5; var_dump(++$c->prop1); var_dump(--$c->prop1); var_dump(--$c->prop1);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Unary_Operators/pre-increment_and_decrement.php.expect",
    "content": "=== int 5 ===\nint(6)\nint(5)\n\n=== int 0x7fffffffffffffff ===\nint(-9223372036854775808)\nint(9223372036854775807)\n\n=== int 0x80000000 ===\nint(-9223372036854775808)\nint(9223372036854775807)\n\n=== float 12.345 ===\nfloat(13.345)\nfloat(12.345)\n\n=== float INF ===\nfloat(INF)\nfloat(INF)\n\n=== float -INF ===\nfloat(-INF)\nfloat(-INF)\n\n=== float NAN ===\nfloat(NAN)\nfloat(NAN)\n=== ?int ===\n---> ++/--/--\nint(6)\nint(5)\nint(4)"
  },
  {
    "path": "tests/Expressions/Unary_Operators/pre-increment_and_decrement_integer_edge_cases.php",
    "content": "<?hh // strict\n\nnamespace NS_pre_increment_and_decrement_integer_edge_cases;\n\nfunction incdec(int $x): void {\n  echo \"--- start incdec ---\\n\";\n  $y = $x;\n\n  var_dump($x);\n  --$x;\n  var_dump($x);\n  --$x;\n  var_dump($x);\n  ++$x;\n  var_dump($x);\n  ++$x;\n  var_dump($x);\n\n// equivalent code using -=/+= instead of --/++.\n\n  var_dump($y);\n  $y -= 1;\n  var_dump($y);\n  $y -= 1;\n  var_dump($y);\n  $y += 1;\n  var_dump($y);\n  $y += 1;\n  var_dump($y);\n  echo \"--- end incdec ---\\n\";\n}\n\nfunction incdecrev(int $x): void {\n  echo \"--- start incdecrev ---\\n\";\n  $y = $x;\n\n  var_dump($x);\n  ++$x;\n  var_dump($x);\n  ++$x;\n  var_dump($x);\n  --$x;\n  var_dump($x);\n  --$x;\n  var_dump($x);\n\n// equivalent code using -=/+= instead of --/++.\n\n  var_dump($y);\n  $y += 1;\n  var_dump($y);\n  $y += 1;\n  var_dump($y);\n  $y -= 1;\n  var_dump($y);\n  $y -= 1;\n  var_dump($y);\n  echo \"--- end incdecrev ---\\n\";\n}\n\nfunction main(): void {\n  $i32 = 1 << 31;\t// if this is negative, we have a 32-bit int\n  $i64 = 1 << 63; // same as $i32 for 32-bit int; otherwise, is 64-bit\n  $IntMin = ($i32 < 0) ? $i32 : $i64;\n  $IntMax = ~$IntMin;\n\n  incdec($IntMin);\n  incdecrev($IntMax);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Unary_Operators/pre-increment_and_decrement_integer_edge_cases.php.expect",
    "content": "--- start incdec ---\nint(-9223372036854775808)\nint(9223372036854775807)\nint(9223372036854775806)\nint(9223372036854775807)\nint(-9223372036854775808)\nint(-9223372036854775808)\nint(9223372036854775807)\nint(9223372036854775806)\nint(9223372036854775807)\nint(-9223372036854775808)\n--- end incdec ---\n--- start incdecrev ---\nint(9223372036854775807)\nint(-9223372036854775808)\nint(-9223372036854775807)\nint(-9223372036854775808)\nint(9223372036854775807)\nint(9223372036854775807)\nint(-9223372036854775808)\nint(-9223372036854775807)\nint(-9223372036854775808)\nint(9223372036854775807)\n--- end incdecrev ---"
  },
  {
    "path": "tests/Expressions/Unary_Operators/unary_arithmetic_operators.php",
    "content": "<?hh // strict\n\nnamespace NS_unary_arithmetic_operators;\n\nfunction DoItInt(int $a): void {\n  echo \"--- start DoItInt -------------------------\\n\\n\";\n  echo \"     original: \"; var_dump($a);\n  $b = +$a;\n  $c = -$a;\n  $d = !$a;\n\n  $f = ~$a;\n  echo \"after unary ~: \"; var_dump($f);\n  printf(\" before Hex: %08X\\n\", $a);\n  printf(\" after  Hex: %08X\\n\", $f);\n\n  echo \" before (int): \".(int)$a;\n  printf(\"; before (int) Hex: %08X\\n\", $a);\n\n  echo \"\\n--- end DoItInt -------------------------\\n\\n\";\n}\n\nfunction DoItFloat(float $a): void {\n  echo \"--- start DoItFloat -------------------------\\n\\n\";\n  echo \"     original: \"; var_dump($a);\n  $b = +$a;\n  $c = -$a;\n  $d = !$a;\n\n  echo \"\\n--- end DoItFloat -------------------------\\n\\n\";\n}\n\nfunction DoItBool(bool $a): void {\n  echo \"--- start DoItBool -------------------------\\n\\n\";\n  echo \"     original: \"; var_dump($a);\n//  $b = +$a;\t\t// a bool is not numeric, so can't be used here\n//  $c = -$a;\t\t// a bool is not numeric, so can't be used here\n  $d = !$a;\n  var_dump($d);\n//  $f = ~$a;\t\t// a bool is not numeric, so can't be used here\n\n  echo \"\\n--- end DoItBool -------------------------\\n\\n\";\n}\n\nfunction DoItString(string $a): void {\n  echo \"--- start DoItString -------------------------\\n\\n\";\n  echo \"     original: \"; var_dump($a);\n//  $b = +$a;\t\t// a string is not numeric, so can't be used here\n//  $c = -$a;\t\t// a string is not numeric, so can't be used here\n  $d = !$a;\n  var_dump($d);\n//  $f = ~$a;\t\t// a string is not numeric, so can't be used here\n\n  echo \"\\n--- end DoItString -------------------------\\n\\n\";\n}\n\nfunction main(): void {\n///*\n// arithmetic operands\n\n  DoItInt(0);\n  DoItInt(5);\n  DoItInt(-10);\n//  DoItInt(PHP_INT_MAX);\t\t// Hack restriction; not yet supporting top-level constants\n//  DoItInt(-PHP_INT_MAX - 1);\t// Hack restriction; not yet supporting top-level constants\n\n  DoItFloat(0.0);\n  DoItFloat(0.0000001e-100);\n  DoItFloat(12.7345);\n  DoItFloat(-9.34E26);\n//  DoItFloat(PHP_INT_MAX + 10);\t// Hack restriction; not yet supporting top-level constants\n  DoItFloat(1234567E50);\n  DoItFloat(1234567E100);\n  DoItFloat(INF);\n  DoItFloat(-INF);\n  DoItFloat(NAN);\n  DoItFloat(-NAN);\n//*/\n\n///*\n// null operand\n\n//  $b = +null;\t\t// null is not numeric, so can't be used here\n//  $c = -null;\t\t// null is not numeric, so can't be used here\n  $d = !null;\n  var_dump($d);\n//  $f = ~null;\t\t// null is not numeric, so can't be used here\n//*/\n\n//*\n// Boolean operands\n\n  DoItBool(true);\n  DoItBool(false);\n//*/\n\n///*\n// string operands\n\n  DoItString(\"0\");\n  DoItString(\"-43\");\n  DoItString(\"123\");\n  DoItString(\"0.0\");\n  DoItString(\"-25.5e-10\");\n  DoItString(\"\");\n  DoItString(\"ABC\");\n//*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Unary_Operators/unary_arithmetic_operators.php.expect",
    "content": "--- start DoItInt -------------------------\n\n     original: int(0)\nafter unary ~: int(-1)\n before Hex: 00000000\n after  Hex: FFFFFFFFFFFFFFFF\n before (int): 0; before (int) Hex: 00000000\n\n--- end DoItInt -------------------------\n\n--- start DoItInt -------------------------\n\n     original: int(5)\nafter unary ~: int(-6)\n before Hex: 00000005\n after  Hex: FFFFFFFFFFFFFFFA\n before (int): 5; before (int) Hex: 00000005\n\n--- end DoItInt -------------------------\n\n--- start DoItInt -------------------------\n\n     original: int(-10)\nafter unary ~: int(9)\n before Hex: FFFFFFFFFFFFFFF6\n after  Hex: 00000009\n before (int): -10; before (int) Hex: FFFFFFFFFFFFFFF6\n\n--- end DoItInt -------------------------\n\n--- start DoItFloat -------------------------\n\n     original: float(0)\n\n--- end DoItFloat -------------------------\n\n--- start DoItFloat -------------------------\n\n     original: float(1.0E-107)\n\n--- end DoItFloat -------------------------\n\n--- start DoItFloat -------------------------\n\n     original: float(12.7345)\n\n--- end DoItFloat -------------------------\n\n--- start DoItFloat -------------------------\n\n     original: float(-9.34E+26)\n\n--- end DoItFloat -------------------------\n\n--- start DoItFloat -------------------------\n\n     original: float(1.234567E+56)\n\n--- end DoItFloat -------------------------\n\n--- start DoItFloat -------------------------\n\n     original: float(1.234567E+106)\n\n--- end DoItFloat -------------------------\n\n--- start DoItFloat -------------------------\n\n     original: float(INF)\n\n--- end DoItFloat -------------------------\n\n--- start DoItFloat -------------------------\n\n     original: float(-INF)\n\n--- end DoItFloat -------------------------\n\n--- start DoItFloat -------------------------\n\n     original: float(NAN)\n\n--- end DoItFloat -------------------------\n\n--- start DoItFloat -------------------------\n\n     original: float(NAN)\n\n--- end DoItFloat -------------------------\n\nbool(true)\n--- start DoItBool -------------------------\n\n     original: bool(true)\nbool(false)\n\n--- end DoItBool -------------------------\n\n--- start DoItBool -------------------------\n\n     original: bool(false)\nbool(true)\n\n--- end DoItBool -------------------------\n\n--- start DoItString -------------------------\n\n     original: string(1) \"0\"\nbool(true)\n\n--- end DoItString -------------------------\n\n--- start DoItString -------------------------\n\n     original: string(3) \"-43\"\nbool(false)\n\n--- end DoItString -------------------------\n\n--- start DoItString -------------------------\n\n     original: string(3) \"123\"\nbool(false)\n\n--- end DoItString -------------------------\n\n--- start DoItString -------------------------\n\n     original: string(3) \"0.0\"\nbool(false)\n\n--- end DoItString -------------------------\n\n--- start DoItString -------------------------\n\n     original: string(9) \"-25.5e-10\"\nbool(false)\n\n--- end DoItString -------------------------\n\n--- start DoItString -------------------------\n\n     original: string(0) \"\"\nbool(true)\n\n--- end DoItString -------------------------\n\n--- start DoItString -------------------------\n\n     original: string(3) \"ABC\"\nbool(false)\n\n--- end DoItString -------------------------\n"
  },
  {
    "path": "tests/Expressions/Yield_Operator/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Expressions/Yield_Operator/yield.php",
    "content": "// Continuation type is not supported  <?hh // strict\n\nnamespace NS_yield;\n\n// define a simple generator that returns a series of consecutive values\n\n//function series(int $start, int $end): Generator<int, int, void> {\nfunction series(int $start, int $end): Continuation<int> {\n  for ($i = $start; $i <= $end; ++$i) {\n    yield $i;\n  }\n}\n\n// define a simple generator that returns key/value pairs\n\nfunction series2(int $start, int $end, string $keyPrefix = \"\"): Generator<string, int, void> {\n  for ($i = $start; $i <= $end; ++$i) {\n    yield $keyPrefix . $i => $i;\t// specify a key/value pair\n  }\n}\n\n// define a generator that returns sucessive lines from a file of text\n\n//function getTextFileLines(string $filename): Generator<int, string, void> {\nfunction getTextFileLines(string $filename): Continuation<string> {\n  $infile = fopen($filename, 'r');\n  if ($infile == false) {\n    // handle file-open failure\n  }\n\n  try {\n    while ($textLine = fgets($infile)) { // while not EOF\n//    echo \"len before rtrim: \" . + strlen($textLine) . \"\\n\";\n      $textLine = rtrim($textLine, \"\\r\\n\");\t// strip off line terminator\n//    echo \"len after rtrim:  \" . + strlen($textLine) . \"\\n\";\n      yield $textLine;\n    }\n  }\n  finally {\n    fclose($infile);\n  }\n}\n\nfunction main(): void {\n  foreach (series(1, 5) as $key => $val) {\n    echo \"key: $key, value: $val\\n\";\n  }\n\n  echo \"===========================\\n\";\n\n  foreach (series2(1, 5, \"X\") as $key => $val) {\n    echo \"key: $key, value: $val\\n\";\n  }\n\n  echo \"===========================\\n\";\n\n  foreach (getTextFileLines(\"Testfile.txt\") as $line) {\n    echo \">$line<\\n\";\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Yield_Operator/yield.php.expectf",
    "content": "\nFatal error: HH mode: content before <?hh (Line: 1, Char: 39)\nsyntax error, unexpected T_HH_ERROR, expecting $end in %s/tests/Expressions/Yield_Operator/yield.php on line 1"
  },
  {
    "path": "tests/Expressions/Yield_Operator/yield_from.php",
    "content": "// SUPPORT IS NOT YET IMPLEMENTED <?hh // strict\n\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2015-2016 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\nfunction gen(): Generator<int, int, void> {\n    yield 1;\n    yield from gen2();\n    yield 4;\n}\n\nfunction gen2(): Generator<int, int, void> {\n    yield 2;\n    yield 3;\n}\n\nfunction g(): Generator<int, int, void> {\n  yield 1;\n  yield from [2, 3];\n  yield 4;\n}\n\nfunction main(): void {\n  echo \"====== yielding from another generator =========\\n\\n\";\n\n  foreach (gen() as $val)\n  {\n    echo $val . \"\\n\";\n  }\n\n  echo \"\\n====== yielding from an array =========\\n\\n\";\n \n  $g = g();\n  foreach ($g as $yielded) {\n    echo $yielded . \"\\n\";\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/Yield_Operator/yield_from.php.expectf",
    "content": "\nFatal error: HH mode: content before <?hh (Line: 1, Char: 34)\nsyntax error, unexpected T_HH_ERROR, expecting $end in %s/tests/Expressions/Yield_Operator/yield_from.php on line 1"
  },
  {
    "path": "tests/Expressions/conversions.php",
    "content": "<?hh // strict\n\nnamespace NS_conversions;\n\nclass Button {\n  private string $label;\n  public function __construct(string $label = '??') {\n    $this->label = $label;\n  }\n  public function __toString(): string {\n    return '[[Button: ' . $this->label . ']]';\n  }\n}\n\nclass CustomButton extends Button {\n  public function __construct(string $label = '??') {\n    parent::__construct($label);\n  }\n  public function __toString(): string {\n    return parent::__toString() . '[[CustomButton]]';\n  }\n}\n\ninterface MyCollection {}\n\nclass MyList implements MyCollection {\n  public function __toString(): string {\n    return '[[MyList]]';\n  }\n}\n\nclass MyQueue implements MyCollection {\n  public function __toString(): string {\n    return '[[MyQueue]]';\n  }\n}\n\nfunction get_resource(): resource {\n  return STDOUT;\n}\n\nclass C1 {\n  private bool $pr_bool;\n  private int $pr_int;\n  private float $pr_float;\n  private num $pr_num;\n  private string $pr_string;\n  private arraykey $pr_arraykey;\n  private resource $pr_resource;\n  private Button $pr_Button;\n  private CustomButton $pr_CustomButton;\n  private MyCollection $pr_MyCollection;\n\n  private ?bool $pr_nbool = null;\n  private ?int $pr_nint = null;\n  private ?float $pr_nfloat = null;\n  private ?num $pr_nnum = null;\n  private ?string $pr_nstring = null;\n  private ?resource $pr_nresource = null;\n  private ?Button $pr_nButton = null;\n  private ?CustomButton $pr_nCustomButton = null;\n  private ?MyCollection $pr_nMyCollection = null;\n\n  private mixed $pr_mixed = null;\n\n  public function __construct() {\n//  echo \"================ Testing (unset) Cast ===================\\n\\n\";\n//\n//  $this->pr_bool = (unset)false;\n//  echo \"(unset)false: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n//  $this->pr_float = (unset)456.78;\n//  echo \"(unset)456.78: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n    echo \"\\n================ setting pr_bool ===================\\n\\n\";\n\n    $this->pr_bool = false;\t\t// false\n    $this->pr_bool = (bool)false;\t// false\n    echo \"(bool)false: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n    $this->pr_bool = true;\t\t// true\n    $this->pr_bool = (bool)true;\t// true\n    echo \"(bool)true: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = 0;\t\t// int is incompatible with bool\n    $this->pr_bool = (bool)0;\t// false\n    echo \"(bool)0: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = 100;\t\t// int is incompatible with bool\n    $this->pr_bool = (bool)100;\t// true\n    echo \"(bool)100: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = 0.0;\t\t// float is incompatible with bool\n    $this->pr_bool = (bool)0.0;\t// false\n    echo \"(bool)0.0: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = 123.45;\t// float is incompatible with bool\n    $this->pr_bool = (bool)123.45;\t// true\n    echo \"(bool)123.45: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = \"\";\t\t// string is incompatible with bool\n    $this->pr_bool = (bool)\"\";\t// false\n    echo \"(bool)\\\"\\\": pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = \"0\";\t\t// string is incompatible with bool\n    $this->pr_bool = (bool)\"0\";\t// false\n    echo \"(bool)\\\"0\\\": pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = \"123ABC\";\t// string is incompatible with bool\n    $this->pr_bool = (bool)\"123ABC\";\t// true\n    echo \"(bool)\\\"123ABC\\\": pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = \"456.78ABC\";\t// string is incompatible with bool\n    $this->pr_bool = (bool)\"456.78ABC\";\t// true\n    echo \"(bool)\\\"456.78ABC\\\": pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = null;\t\t// null is incompatible with bool\n    $this->pr_bool = (bool)null;\t// false\n    echo \"(bool)null: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = array();\t// array() is incompatible with bool\n    $this->pr_bool = (bool)array();\t// false\n    echo \"(bool)array(): pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//   $this->pr_bool = array(10,20,30);\t// array(...) is incompatible with bool\n    $this->pr_bool = (bool)array(10,20,30);\t// true\n    echo \"(bool)array(10,20,30): pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = new Button();\t\t// Button is incompatible with bool\n    $this->pr_bool = (bool)new Button();\t// true\n    echo \"(bool)new Button(): pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//   $this->pr_bool = get_resource();\t// resource is not compatible with bool\n    $this->pr_bool = (bool)get_resource();\t// true\n    echo \"(bool)resource: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n    $this->pr_arraykey = 0;\n//    $this->pr_bool = $this->pr_arraykey;\t// arraykey is incompatible with bool\n    $this->pr_bool = (bool)$this->pr_arraykey;\t// \n    echo \"(bool)arraykey: pr_arraykey = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n    $this->pr_arraykey = 10;\n    $this->pr_bool = (bool)$this->pr_arraykey;\t// \n    echo \"(bool)arraykey: pr_arraykey = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n    $this->pr_arraykey = \"\";\n//    $this->pr_bool = $this->pr_arraykey;\t// arraykey is incompatible with bool\n    $this->pr_bool = (bool)$this->pr_arraykey;\t// \n    echo \"(bool)arraykey: pr_arraykey = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n    $this->pr_arraykey = \"ABC\";\n    $this->pr_bool = (bool)$this->pr_arraykey;\t// \n    echo \"(bool)arraykey: pr_arraykey = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n\n    echo \"\\n================ setting pr_int ===================\\n\\n\";\n\n//    $this->pr_int = false;\t\t// bool is incompatible with int\n    $this->pr_int = (int)false;\t// 0\n    echo \"(int)false: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = true;\t\t// bool is incompatible with int\n    $this->pr_int = (int)true;\t// 1\n    echo \"(int)true: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n    $this->pr_int = 0;\t\t// 0\n    $this->pr_int = (int)0;\t\t// 0\n    echo \"(int)0: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n    $this->pr_int = 100;\t\t// 100\n    $this->pr_int = (int)100;\t// 100\n    echo \"(int)100: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = 0.0;\t\t// float is incompatible with int\n    $this->pr_int = (int)0.0;\t// 0\n    echo \"(int)0.0: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = 123.45;\t\t// float is incompatible with int\n    $this->pr_int = (int)123.45;\t// 123\n    echo \"(int)123.45: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = \"\";\t\t// string is incompatible with int\n    $this->pr_int = (int)\"\";\t// 0\n    echo \"(int)\\\"\\\": pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = \"0\";\t\t// string is incompatible with int\n    $this->pr_int = (int)\"0\";\t// 0\n    echo \"(int)\\\"0\\\": pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = \"123ABC\";\t// string is incompatible with int\n    $this->pr_int = (int)\"123ABC\";\t// 123\n    echo \"(int)\\\"123ABC\\\": pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = \"456.78ABC\";\t// string is incompatible with bool\n    $this->pr_int = (int)\"456.78ABC\";\t// 456\n    echo \"(int)\\\"456.78ABC\\\": pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = null;\t\t// null is incompatible with int\n    $this->pr_int = (int)null;\t// 0\n    echo \"(int)null: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = array();\t// array() is incompatible with int\n    $this->pr_int = (int)array();\t// 0\n echo \"(int)array(): pr_int = >\" . $this->pr_int . \"<\\n\";\n\n// $this->pr_int = array(10,20,30);\t// array(...) is incompatible with int\n    $this->pr_int = (int)array(10,20,30);\t// 1\n    echo \"(int)array(10,20,30): pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = new Button();\t\t// Button is incompatible with int\n//    $this->pr_int = (int)new Button();\n    echo \"(int)new Button(): pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = get_resource();\t\t// resource is not compatible with\n    $this->pr_int = (int)get_resource();\n    echo \"(int)resource: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n    echo \"\\n================ setting pr_float ===================\\n\\n\";\n\n//    $this->pr_float = false;\t// bool is incompatible with float\n    $this->pr_float = (float)false;\t// 0.0\n    echo \"(float)false: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = true;\t\t// bool is incompatible with float\n    $this->pr_float = (float)true;\t// 1.0\n    echo \"(float)true: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = 0;\t\t// int is incompatible with float\n    $this->pr_float = (float)0;\t// 0.0\n    echo \"(float)0: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = 100;\t\t// int is incompatible with float\n    $this->pr_float = (float)100;\t// 100.0\n    echo \"(float)100: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n    $this->pr_float = 0.0;\t\t// 0.0\n    $this->pr_float = (float)0.0;\t// 0.0\n    echo \"(float)0.0: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n    $this->pr_float = 123.45;\t// 123.45\n    $this->pr_float = (float)123.45;\t// 123.45\n    echo \"(float)123.45: pr_float = >\" . $this->pr_float . \"<\\n\";\n    \n    $this->pr_float = INF;\n    $this->pr_float = (float)INF;\n    echo \"(float)INF: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n    $this->pr_float = NAN;\n    $this->pr_float = (float)NAN;\n    echo \"(float)NAN: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = \"\";\t\t// string is incompatible with float\n    $this->pr_float = (float)\"\";\t// 0.0\n    echo \"(float)\\\"\\\": pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = \"0\";\t\t// string is incompatible with float\n    $this->pr_float = (float)\"0\";\t// 0.0\n    echo \"(float)\\\"0\\\": pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = \"123ABC\";\t// string is incompatible with float\n    $this->pr_float = (float)\"123ABC\";\t// 123.0\n    echo \"(float)\\\"123ABC\\\": pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = \"456.78ABC\";\t// string is incompatible with bool\n    $this->pr_float = (float)\"456.78ABC\";\t// 456.78\n    echo \"(float)\\\"456.78ABC\\\": pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = null;\t\t// null is incompatible with float\n    $this->pr_float = (float)null;\t// 0.0\n    echo \"(float)null: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = array();\t// array() is incompatible with float\n    $this->pr_float = (float)array();\t// 0.0\n    echo \"(float)array(): pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = array(10,20,30);\t// array(...) is incompatible with float\n    $this->pr_float = (float)array(10,20,30);\t// 1.0\n    echo \"(float)array(10,20,30): pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = new Button();\t\t// Button is incompatible with float\n//    $this->pr_float = (float)new Button();\n    echo \"(float)new Button(): pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = get_resource();\t\t// resource is not compatible with float\n    $this->pr_float = (float)get_resource();\t// 2.0\n    echo \"(float)resource: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n    echo \"\\n================ setting pr_num ===================\\n\\n\";\n\n//    $this->pr_num = false;\t\t// bool is incompatible with num\n//    $this->pr_num = true;\t\t// bool is incompatible with num\n\n    $this->pr_num = 0;\n    echo \"0: pr_num = >\" . $this->pr_num . \"<\\n\";\n\n    $this->pr_num = 100;\n    echo \"100: pr_num = >\" . $this->pr_num . \"<\\n\";\n\n    $this->pr_num = 0.0;\n    echo \"0.0: pr_num = >\" . $this->pr_num . \"<\\n\";\n\n    $this->pr_num = 123.45;\n    echo \"123.45: pr_num = >\" . $this->pr_num . \"<\\n\";\n\n//    $this->pr_num = \"\";\t\t// string is incompatible with num\n\n//    $this->pr_num = \"0\";\t\t// string is incompatible with num\n\n//    $this->pr_num = \"123ABC\";\t// string is incompatible with num\n\n//    $this->pr_num = \"456.78ABC\";\t// string is incompatible with bool\n\n//    $this->pr_num = null;\t\t// null is incompatible with num\n\n//    $this->pr_num = array();\t// array() is incompatible with num\n\n//    $this->pr_num = array(10,20,30);\t// array(...) is incompatible with num\n\n//    $this->pr_num = new Button();\t\t// Button is incompatible with num\n\n//    $this->pr_num = get_resource();\t\t// resource is not compatible with num\n\n    echo \"\\n================ setting pr_string ===================\\n\\n\";\n\n//    $this->pr_string = (binary)false;\t// cast to binary is not permitted\n\n//    $this->pr_string = false;\t\t// bool is incompatible with string\n    $this->pr_string = (string)false;\t// \"\"\n    echo \"(string)false: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = true;\t\t// bool is incompatible with string\n    $this->pr_string = (string)true;\t// \"1\"\n    echo \"(string)true: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = 0;\n    $this->pr_string = (string)0;\t// \"0\"\n    echo \"(string)0: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = 100;\n    $this->pr_string = (string)100;\t// \"100\"\n    echo \"(string)100: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = 0.0;\t\t// float is incompatible with string\n    $this->pr_string = (string)0.0;\t// \"0\"\n    echo \"(string)0.0: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = 123.45;\t\t// float is incompatible with string\n    $this->pr_string = (string)123.45;\t// \"123.45\"\n    echo \"(string)123.45: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = \"\";\t\t// string is incompatible with string\n    $this->pr_string = (string)\"\";\t// \"\"\n    echo \"(string)\\\"\\\": pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = \"0\";\t\t// string is incompatible with string\n    $this->pr_string = (string)\"0\";\t// \"0\"\n    echo \"(string)\\\"0\\\": pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = \"123ABC\";\t// string is incompatible with string\n    $this->pr_string = (string)\"123ABC\";\t// \"123ABC\"\n    echo \"(string)\\\"123ABC\\\": pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = \"456.78ABC\";\t// string is incompatible with bool\n    $this->pr_string = (string)\"456.78ABC\";\t// \"456.78ABC\"\n    echo \"(string)\\\"456.78ABC\\\": pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = null;\t\t// null is incompatible with string\n    $this->pr_string = (string)null;\t// \"\"\n    echo \"(string)null: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = array();\t// array() is incompatible with string\n//    $this->pr_string = (string)array();\n//    echo \"(string)array(): pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = array(10,20,30);\t// array(...) is incompatible with string\n//    $this->pr_string = (string)array(10,20,30);\n//    echo \"(string)array(10,20,30): pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = new Button();\t\t// Button is incompatible with string\n//    $this->pr_string = (string)new Button();\n//    echo \"(string)new Button(): pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = get_resource();\t\t// resource is not compatible with string\n    $this->pr_string = (string)get_resource();\t// \"Resource id #n\"\n    echo \"(string)resource: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n    echo \"\\n================ setting pr_arraykey ===================\\n\\n\";\n\n//    $this->pr_arraykey = false;\t// bool is incompatible with arraykey\n//    $this->pr_arraykey = true;\t// bool is incompatible with arraykey\n\n    $this->pr_arraykey = 0;\t\t// 0\n    echo \"(arraykey)int: pr_arraykey = >\" . $this->pr_arraykey . \"<\\n\";\n\n    $this->pr_arraykey = 100;\t// 100\n    echo \"(arraykey)int: pr_arraykey = >\" . $this->pr_arraykey . \"<\\n\";\n\n//    $this->pr_arraykey = 0.0;\t// float is incompatible with arraykey\n\n//    $this->pr_arraykey = 123.45;\t// float is incompatible with arraykey\n\n    $this->pr_arraykey = \"\";\t// \"\"\n    echo \"(arraykey)string: pr_arraykey = >\" . $this->pr_arraykey . \"<\\n\";\n\n    $this->pr_arraykey = \"0\";\t// \"0\"\n    echo \"(arraykey)string: pr_arraykey = >\" . $this->pr_arraykey . \"<\\n\";\n\n    $this->pr_arraykey = \"123ABC\";\t// \"123ABC\"\n    echo \"(arraykey)string: pr_arraykey = >\" . $this->pr_arraykey . \"<\\n\";\n\n    $this->pr_arraykey = \"456.78ABC\";\t// \"456.78ABC\"\n    echo \"(arraykey)string: pr_arraykey = >\" . $this->pr_arraykey . \"<\\n\";\n\n//    $this->pr_arraykey = null;\t\t// null is incompatible with arraykey\n\n//    $this->pr_arraykey = array();\t\t// array() is incompatible with arraykey\n\n//    $this->pr_arraykey = array(10,20,30);\t// array(...) is incompatible with arraykey\n\n//    $this->pr_arraykey = new Button();\t// Button is incompatible with arraykey\n\n//    $this->pr_arraykey = get_resource();\t// resource is not compatible with\n\n    echo \"\\n================ setting pr_resource ===================\\n\\n\";\n\n//    $this->pr_resource = false;\t\t// bool is incompatible with resource \n//    $this->pr_resource = (resource)false;\t// cast to resource is not permitted\n\n//    $this->pr_resource = 0;\t\t// int is incompatible with resource\n//    $this->pr_resource = 100;\t// int is incompatible with resource\n//    $this->pr_resource = 0.0;\t// float is incompatible with resource\n//    $this->pr_resource = 123.45;\t// float is incompatible with resource\n//    $this->pr_resource = \"\";\t// string is incompatible with resource\n//    $this->pr_resource = \"0\";\t// string is incompatible with resource\n//    $this->pr_resource = \"123ABC\";\t// string is incompatible with resource\n//    $this->pr_resource = \"456.78ABC\";\t// string is incompatible with resource\n//    $this->pr_resource = null;\t// null is incompatible with resource\n//    $this->pr_resource = array();\t// array() is incompatible with resource\n//    $this->pr_resource = array(10,20,30);// array(...) is incompatible with resource\n\n    $this->pr_resource = get_resource();\n    echo \"resource: pr_resource = >\" . $this->pr_resource . \"<\\n\";\n\n    echo \"\\n================ setting pr_Button ===================\\n\\n\";\n\n//    $this->pr_Button = false;\t\t// bool is incompatible with Button \n//    $this->pr_Button = (Button)false;\t// cast to Button is not permitted\n//    $this->pr_Button = (object)false;\t// cast to object is not permitted\n\n//    $this->pr_Button = 0;\t\t// int is incompatible with Button\n//    $this->pr_Button = 100;\t\t// int is incompatible with Button\n//    $this->pr_Button = 0.0;\t\t// float is incompatible with Button\n//    $this->pr_Button = 123.45;\t// float is incompatible with Button\n//    $this->pr_Button = \"\";\t\t// string is incompatible with Button\n//    $this->pr_Button = \"0\";\t\t// string is incompatible with Button\n//    $this->pr_Button = \"123ABC\";\t// string is incompatible with Button\n//    $this->pr_Button = \"456.78ABC\";\t// string is incompatible with Button\n//    $this->pr_Button = null;\t// null is incompatible with Button\n//    $this->pr_Button = array();\t// array() is incompatible with Button\n//    $this->pr_Button = array(10,20,30);// array(...) is incompatible with Button\n\n    $this->pr_Button = new Button(\"STOP\"); \n    echo \"new Button(\\\"STOP\\\"): pr_Button = >\" . $this->pr_Button . \"<\\n\";\n\n    $this->pr_Button = new CustomButton(\"RAISE\"); \n    echo \"new CustomButton(\\\"RAISE\\\"): pr_Button = >\" . $this->pr_Button . \"<\\n\";\n\n//    $this->pr_Button = get_resource();\t\t// resource is not compatible with Button\n    echo \"resource: pr_Button = >\" . $this->pr_Button . \"<\\n\";\n\n    echo \"\\n================ setting pr_CustomButton===================\\n\\n\";\n\n    $this->pr_CustomButton = new CustomButton(\"LOWER\"); \n    echo \"new CustomButton(\\\"LOWER\\\"): pr_CustomButton= >\" . $this->pr_CustomButton. \"<\\n\";\n\n//    $this->pr_CustomButton = get_resource();\t// resource is not compatible with CustomButton \n    echo \"resource: pr_CustomButton = >\" . $this->pr_CustomButton . \"<\\n\";\n\n    echo \"\\n================ setting pr_MyCollection ===================\\n\\n\";\n\n//    $this->pr_MyCollection = false;\t\t// bool is incompatible with MyCollection \n//    $this->pr_MyCollection = (MyCollection)false;\t// cast to MyCollection is not permitted\n\n    $this->pr_MyCollection = new MyList(); \n    echo \"new MyList(): pr_MyCollection = >\" . $this->pr_MyCollection . \"<\\n\";\n\n    $this->pr_MyCollection = new MyQueue(); \n    echo \"new MyQueue(): pr_MyCollection = >\" . $this->pr_MyCollection . \"<\\n\";\n\n//    $this->pr_MyCollection = get_resource();\t// resource is not compatible with MyCollection \n//    echo \"resource: pr_MyCollection = >\" . $this->pr_MyCollection . \"<\\n\";\n\n    echo \"\\n================ converting non-nullable to corresponding nullable ===================\\n\\n\";\n\n    echo \"bool: pr_nbool = >\" . $this->pr_nbool . \"<\\n\";\n//    $this->pr_nbool = (?bool)true;\t\t// can't cast to any nullable type\n    $this->pr_nbool = true;\n    echo \"bool: pr_nbool = >\" . $this->pr_nbool . \"<\\n\";\n    $this->pr_nbool = false;\n    echo \"bool: pr_nbool = >\" . $this->pr_nbool . \"<\\n\";\n    $this->pr_nbool = $this->pr_bool;\n    echo \"bool: pr_nbool = >\" . $this->pr_nbool . \"<\\n\";\n\n    echo \"int: pr_nint = >\" . $this->pr_nint . \"<\\n\";\n    $this->pr_nint = 100;\n    echo \"int: pr_nint = >\" . $this->pr_nint . \"<\\n\";\n    $this->pr_nint = $this->pr_int;\n    echo \"int: pr_nint = >\" . $this->pr_nint . \"<\\n\";\n\n    echo \"float: pr_nfloat = >\" . $this->pr_nfloat . \"<\\n\";\n    $this->pr_nfloat = 123.45;\n    echo \"float: pr_nfloat = >\" . $this->pr_nfloat . \"<\\n\";\n    $this->pr_nfloat = $this->pr_float;\n    echo \"float: pr_nfloat = >\" . $this->pr_nfloat . \"<\\n\";\n\n    echo \"num: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n    $this->pr_nnum = 100;\n    echo \"num: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n    $this->pr_nnum = 123.45;\n    echo \"num: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n    $this->pr_nnum = $this->pr_num;\n    echo \"num: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n\n    echo \"string: pr_nstring = >\" . $this->pr_nstring . \"<\\n\";\n    $this->pr_nstring = \"123ABC\";\n    echo \"string: pr_nstring = >\" . $this->pr_nstring . \"<\\n\";\n    $this->pr_nstring = $this->pr_string;\n    echo \"string: pr_nstring = >\" . $this->pr_nstring . \"<\\n\";\n\n    echo \"resource: pr_nresource = >\" . $this->pr_nresource . \"<\\n\";\n    $this->pr_nresource = get_resource();\n    echo \"resource: pr_nresource = >\" . $this->pr_nresource . \"<\\n\";\n    $this->pr_nresource = $this->pr_resource;\n    echo \"resource: pr_nresource = >\" . $this->pr_nresource . \"<\\n\";\n\n    echo \"Button: pr_nButton = >\" . $this->pr_nButton . \"<\\n\";\n    $this->pr_nButton = new Button(\"HOT\");\n    echo \"Button: pr_nButton = >\" . $this->pr_nButton . \"<\\n\";\n    $this->pr_nButton = new CustomButton(\"COLD\");\n    echo \"CustomButton: pr_nButton = >\" . $this->pr_nButton . \"<\\n\";\n    $this->pr_nButton = $this->pr_Button;\n    echo \"Button: pr_nButton = >\" . $this->pr_nButton . \"<\\n\";\n\n    echo \"CustomButton: pr_nCustomButton = >\" . $this->pr_nCustomButton . \"<\\n\";\n    $this->pr_nCustomButton = new CustomButton(\"ALARM\");\n    echo \"CustomButton: pr_nCustomButton = >\" . $this->pr_nCustomButton . \"<\\n\";\n    $this->pr_nCustomButton = $this->pr_CustomButton;\n    echo \"CustomButton: pr_nCustomButton = >\" . $this->pr_nCustomButton . \"<\\n\";\n\n//    echo \"MyCollection: pr_nMyCollection = >\" . $this->pr_nMyCollection . \"<\\n\";\n    $this->pr_nMyCollection = new MyList();\n    echo \"MyCollection: pr_nMyCollection = >\" . $this->pr_nMyCollection . \"<\\n\";\n    $this->pr_nMyCollection = new MyQueue();\n    echo \"MyCollection: pr_nMyCollection = >\" . $this->pr_nMyCollection . \"<\\n\";\n    $this->pr_nMyCollection = $this->pr_MyCollection;\n\n// next line disabaled 'cos of probably bug in that property currently contains a resource when that\n// assignment shouldn't have been allowed.\n//    echo \"MyCollection: pr_nMyCollection = >\" . $this->pr_nMyCollection . \"<\\n\";\n\n    echo \"\\n================ converting one nullable to a different nullable (excluding mixed) ===================\\n\\n\";\n\n    $this->pr_nnum = $this->pr_nint;\n    echo \"nint: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n    $this->pr_nnum = $this->pr_nfloat;\n    echo \"nfloat: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n    $this->pr_nButton = $this->pr_nCustomButton;\n    echo \"nCustomButton: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n//???\t$this->pr_nCustomButton = $this->pr_nButton;\n\n    echo \"\\n================ converting nullable to corresponding non-nullable ===================\\n\\n\";\n\n    $this->pr_nbool = null;\n    $this->pr_bool = (bool)$this->pr_nbool;\n    echo \"pr->bool = >\" . $this->pr_bool . \"<\\n\";\n    $this->pr_nbool = true;\n    $this->pr_bool = (bool)$this->pr_nbool;\n    echo \"pr->bool = >\" . $this->pr_bool . \"<\\n\";\n\n    $this->pr_nint = null;\n    $this->pr_int = (int)$this->pr_nint;\n    echo \"pr->int = >\" . $this->pr_int . \"<\\n\";\n    $this->pr_nint = 100;\n    $this->pr_int = (int)$this->pr_nint;\n    echo \"pr->int = >\" . $this->pr_int . \"<\\n\";\n\n    $this->pr_nfloat = null;\n    $this->pr_float = (float)$this->pr_nfloat;\n    echo \"pr->float = >\" . $this->pr_float . \"<\\n\";\n    $this->pr_nfloat = 123.45;\n    $this->pr_float = (float)$this->pr_nfloat;\n    echo \"pr->float = >\" . $this->pr_float . \"<\\n\";\n\n    $this->pr_nstring = null;\n    $this->pr_string = (string)$this->pr_nstring;\n    echo \"pr->string = >\" . $this->pr_string . \"<\\n\";\n    $this->pr_nstring = \"123ABC\";\n    $this->pr_string = (string)$this->pr_nstring;\n    echo \"pr->string = >\" . $this->pr_string . \"<\\n\";\n\n    echo \"\\n================ setting pr_mixed ===================\\n\\n\";\n\n    $this->pr_mixed = false; \n//    $this->pr_mixed = (mixed)false;\t// cast to mixed is not permitted\n    echo \"false: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_bool; \n    echo \"pr_bool: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nbool; \n    echo \"pr_nbool: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = true;\n    echo \"true: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = 0;\n    echo \"0: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_int; \n    echo \"pr_int: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nint; \n    echo \"pr_nint: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = 100;\n    echo \"100: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = 0.0;\n    echo \"0.0: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_float; \n    echo \"pr_float: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nfloat; \n    echo \"pr_nfloat: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = 123.45;\n    echo \"123.45: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = \"\";\n    echo \"\\\"\\\": pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_string; \n    echo \"pr_string: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nstring; \n    echo \"pr_nstring: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = \"0\";\n    echo \"\\\"0\\\": pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = \"123ABC\";\n    echo \"\\\"123ABC\\\": pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = \"456.78ABC\";\n    echo \"\\\"456.78ABC\\\": pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = null;\n    echo \"null: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = array();\n    echo \"array(): pr_mixed = >\" . ((string)$this->pr_mixed) . \"<\\n\";\n\n    $this->pr_mixed = array(10,20,30);\n    echo \"array(10,20,30): pr_mixed = >\" . ((string)$this->pr_mixed) . \"<\\n\";\n\n    $this->pr_mixed = new Button();\n    echo \"new Button(): pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_Button; \n    echo \"pr_Button: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nButton; \n    echo \"pr_nButton: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = new CustomButton();\n    echo \"new CustomButton(): pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_CustomButton; \n    echo \"pr_CustomButton: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nCustomButton; \n    echo \"pr_nCustomButton: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = new MyList();\n    echo \"new MyList(): pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = new MyQueue();\n    echo \"new MyQueue(): pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_MyCollection; \n\n// next line disabled 'cos of probably bug in that property currently contains a resource when that\n// assignment shouldn't have been allowed.\n//    echo \"pr_MyCollection: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = $this->pr_nMyCollection; \n\n// next line disabled 'cos of probably bug in that property currently contains a resource when that\n// assignment shouldn't have been allowed.\n//    echo \"pr_nMyCollection: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = get_resource();\n    echo \"resource: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_resource; \n    echo \"pr_resource: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nresource; \n    echo \"pr_nresource: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n  }\n}\n\nfunction main(): void {\n    $c1 = new C1();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/conversions.php.expectf",
    "content": "\n================ setting pr_bool ===================\n\n(bool)false: pr_bool = >false<\n(bool)true: pr_bool = >true<\n(bool)0: pr_bool = >false<\n(bool)100: pr_bool = >true<\n(bool)0.0: pr_bool = >false<\n(bool)123.45: pr_bool = >true<\n(bool)\"\": pr_bool = >false<\n(bool)\"0\": pr_bool = >false<\n(bool)\"123ABC\": pr_bool = >true<\n(bool)\"456.78ABC\": pr_bool = >true<\n(bool)null: pr_bool = >false<\n(bool)array(): pr_bool = >false<\n(bool)array(10,20,30): pr_bool = >true<\n(bool)new Button(): pr_bool = >true<\n(bool)resource: pr_bool = >true<\n(bool)arraykey: pr_arraykey = >false<\n(bool)arraykey: pr_arraykey = >true<\n(bool)arraykey: pr_arraykey = >false<\n(bool)arraykey: pr_arraykey = >true<\n\n================ setting pr_int ===================\n\n(int)false: pr_int = >0<\n(int)true: pr_int = >1<\n(int)0: pr_int = >0<\n(int)100: pr_int = >100<\n(int)0.0: pr_int = >0<\n(int)123.45: pr_int = >123<\n(int)\"\": pr_int = >0<\n(int)\"0\": pr_int = >0<\n(int)\"123ABC\": pr_int = >123<\n(int)\"456.78ABC\": pr_int = >456<\n(int)null: pr_int = >0<\n(int)array(): pr_int = >0<\n(int)array(10,20,30): pr_int = >1<\n(int)new Button(): pr_int = >1<\n(int)resource: pr_int = >2<\n\n================ setting pr_float ===================\n\n(float)false: pr_float = >0<\n(float)true: pr_float = >1<\n(float)0: pr_float = >0<\n(float)100: pr_float = >100<\n(float)0.0: pr_float = >0<\n(float)123.45: pr_float = >123.45<\n(float)INF: pr_float = >INF<\n(float)NAN: pr_float = >NAN<\n(float)\"\": pr_float = >0<\n(float)\"0\": pr_float = >0<\n(float)\"123ABC\": pr_float = >123<\n(float)\"456.78ABC\": pr_float = >456.78<\n(float)null: pr_float = >0<\n(float)array(): pr_float = >0<\n(float)array(10,20,30): pr_float = >1<\n(float)new Button(): pr_float = >1<\n(float)resource: pr_float = >2<\n\n================ setting pr_num ===================\n\n0: pr_num = >0<\n100: pr_num = >100<\n0.0: pr_num = >0<\n123.45: pr_num = >123.45<\n\n================ setting pr_string ===================\n\n(string)false: pr_string = ><\n(string)true: pr_string = >1<\n(string)0: pr_string = >0<\n(string)100: pr_string = >100<\n(string)0.0: pr_string = >0<\n(string)123.45: pr_string = >123.45<\n(string)\"\": pr_string = ><\n(string)\"0\": pr_string = >0<\n(string)\"123ABC\": pr_string = >123ABC<\n(string)\"456.78ABC\": pr_string = >456.78ABC<\n(string)null: pr_string = ><\n(string)resource: pr_string = >Resource id #2<\n\n================ setting pr_arraykey ===================\n\n(arraykey)int: pr_arraykey = >0<\n(arraykey)int: pr_arraykey = >100<\n(arraykey)string: pr_arraykey = ><\n(arraykey)string: pr_arraykey = >0<\n(arraykey)string: pr_arraykey = >123ABC<\n(arraykey)string: pr_arraykey = >456.78ABC<\n\n================ setting pr_resource ===================\n\nresource: pr_resource = >Resource id #2<\n\n================ setting pr_Button ===================\n\nnew Button(\"STOP\"): pr_Button = >[[Button: STOP]]<\nnew CustomButton(\"RAISE\"): pr_Button = >[[Button: RAISE]][[CustomButton]]<\nresource: pr_Button = >[[Button: RAISE]][[CustomButton]]<\n\n================ setting pr_CustomButton===================\n\nnew CustomButton(\"LOWER\"): pr_CustomButton= >[[Button: LOWER]][[CustomButton]]<\nresource: pr_CustomButton = >[[Button: LOWER]][[CustomButton]]<\n\n================ setting pr_MyCollection ===================\n\nnew MyList(): pr_MyCollection = >[[MyList]]<\nnew MyQueue(): pr_MyCollection = >[[MyQueue]]<\n\n================ converting non-nullable to corresponding nullable ===================\n\nbool: pr_nbool = ><\nbool: pr_nbool = >1<\nbool: pr_nbool = ><\nbool: pr_nbool = >1<\nint: pr_nint = ><\nint: pr_nint = >100<\nint: pr_nint = >2<\nfloat: pr_nfloat = ><\nfloat: pr_nfloat = >123.45<\nfloat: pr_nfloat = >2<\nnum: pr_nnum = ><\nnum: pr_nnum = >100<\nnum: pr_nnum = >123.45<\nnum: pr_nnum = >123.45<\nstring: pr_nstring = ><\nstring: pr_nstring = >123ABC<\nstring: pr_nstring = >Resource id #2<\nresource: pr_nresource = ><\nresource: pr_nresource = >Resource id #2<\nresource: pr_nresource = >Resource id #2<\nButton: pr_nButton = ><\nButton: pr_nButton = >[[Button: HOT]]<\nCustomButton: pr_nButton = >[[Button: COLD]][[CustomButton]]<\nButton: pr_nButton = >[[Button: RAISE]][[CustomButton]]<\nCustomButton: pr_nCustomButton = ><\nCustomButton: pr_nCustomButton = >[[Button: ALARM]][[CustomButton]]<\nCustomButton: pr_nCustomButton = >[[Button: LOWER]][[CustomButton]]<\nMyCollection: pr_nMyCollection = >[[MyList]]<\nMyCollection: pr_nMyCollection = >[[MyQueue]]<\n\n================ converting one nullable to a different nullable (excluding mixed) ===================\n\nnint: pr_nnum = >2<\nnfloat: pr_nnum = >2<\nnCustomButton: pr_nnum = >2<\n\n================ converting nullable to corresponding non-nullable ===================\n\npr->bool = ><\npr->bool = >1<\npr->int = >0<\npr->int = >100<\npr->float = >0<\npr->float = >123.45<\npr->string = ><\npr->string = >123ABC<\n\n================ setting pr_mixed ===================\n\nfalse: pr_mixed = ><\npr_bool: pr_mixed = >1<\npr_nbool: pr_mixed = >1<\ntrue: pr_mixed = >1<\n0: pr_mixed = >0<\npr_int: pr_mixed = >100<\npr_nint: pr_mixed = >100<\n100: pr_mixed = >100<\n0.0: pr_mixed = >0<\npr_float: pr_mixed = >123.45<\npr_nfloat: pr_mixed = >123.45<\n123.45: pr_mixed = >123.45<\n\"\": pr_mixed = ><\npr_string: pr_mixed = >123ABC<\npr_nstring: pr_mixed = >123ABC<\n\"0\": pr_mixed = >0<\n\"123ABC\": pr_mixed = >123ABC<\n\"456.78ABC\": pr_mixed = >456.78ABC<\nnull: pr_mixed = ><\n\nNotice: Array to string conversion in %s/tests/Expressions/conversions.php on line 653\narray(): pr_mixed = >Array<\n\nNotice: Array to string conversion in %s/tests/Expressions/conversions.php on line 656\narray(10,20,30): pr_mixed = >Array<\nnew Button(): pr_mixed = >[[Button: ??]]<\npr_Button: pr_mixed = >[[Button: RAISE]][[CustomButton]]<\npr_nButton: pr_mixed = >[[Button: LOWER]][[CustomButton]]<\nnew CustomButton(): pr_mixed = >[[Button: ??]][[CustomButton]]<\npr_CustomButton: pr_mixed = >[[Button: LOWER]][[CustomButton]]<\npr_nCustomButton: pr_mixed = >[[Button: LOWER]][[CustomButton]]<\nnew MyList(): pr_mixed = >[[MyList]]<\nnew MyQueue(): pr_mixed = >[[MyQueue]]<\nresource: pr_mixed = >Resource id #2<\npr_resource: pr_mixed = >Resource id #2<\npr_nresource: pr_mixed = >Resource id #2<"
  },
  {
    "path": "tests/Expressions/limits_on_types_in_arithmetic.php",
    "content": "<?hh // strict\n\nnamespace NS_limits_on_types_in_arithmetic;\n\nfunction doit(num $p1_num, ?int $p2_nint, ?float $p3_nfloat, ?num $p4_nnum): void {\n//  var_dump(true + 1);\t\t// can't do arithmetic on a bool\n  var_dump(123 + 1);\t\t// Okay\n  var_dump(2.4 + 1);\t\t// Okay\n  var_dump($p1_num + 1);\t// Okay\n//  var_dump(\"123\" + 1);\t// can't do arithmetic on a string, not even a numeric string\n//  var_dump(\"abc\" + 1);\t// can't do arithmetic on a string\n//  var_dump(null + 1);\t\t// can't do arithmetic on a nullable type\n\n//  var_dump($p2_nint + 1);\t// can't do arithmetic on a nullable type\n//  var_dump($p3_nfloat + 1);\t// can't do arithmetic on a nullable type\n//  var_dump($p4_nnum + 1);\t// can't do arithmetic on a nullable type\n}\n\nfunction main(): void {\n  doit(10, 20, 3.45, null);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/limits_on_types_in_arithmetic.php.expect",
    "content": "int(124)\nfloat(3.4)\nint(11)"
  },
  {
    "path": "tests/Expressions/yield.php",
    "content": "\n\n\n\n//<?hh // strict\n\nnamespace NS_yield;\n\n// define a simple generator that returns a series of consecutive values\n\n//function series(int $start, int $end): Generator<int, int, void> {\nfunction series(int $start, int $end): Continuation<int> {\n  for ($i = $start; $i <= $end; ++$i) {\n    yield $i;\n  }\n}\n\n// define a simple generator that returns key/value pairs\n\nfunction series2(int $start, int $end, string $keyPrefix = \"\"): Generator<string, int, void> {\n  for ($i = $start; $i <= $end; ++$i) {\n    yield $keyPrefix . $i => $i;\t// specify a key/value pair\n  }\n}\n\n// define a generator that returns sucessive lines from a file of text\n\n//function getTextFileLines(string $filename): Generator<int, string, void> {\nfunction getTextFileLines(string $filename): Continuation<string> {\n  $infile = fopen($filename, 'r');\n  if ($infile == false) {\n    // handle file-open failure\n  }\n\n  try {\n    while ($textLine = fgets($infile)) { // while not EOF\n//    echo \"len before rtrim: \" . + strlen($textLine) . \"\\n\";\n      $textLine = rtrim($textLine, \"\\r\\n\");\t// strip off line terminator\n//    echo \"len after rtrim:  \" . + strlen($textLine) . \"\\n\";\n      yield $textLine;\n    }\n  }\n  finally {\n    fclose($infile);\n  }\n}\n\nfunction main(): void {\n  foreach (series(1, 5) as $key => $val) {\n    echo \"key: $key, value: $val\\n\";\n  }\n\n  echo \"===========================\\n\";\n\n  foreach (series2(1, 5, \"X\") as $key => $val) {\n    echo \"key: $key, value: $val\\n\";\n  }\n\n  echo \"===========================\\n\";\n\n  foreach (getTextFileLines(\"Testfile.txt\") as $line) {\n    echo \">$line<\\n\";\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Expressions/yield.php.expectf",
    "content": "\nFatal error: HH mode: content before <?hh (Line: 5, Char: 2)\nsyntax error, unexpected T_HH_ERROR, expecting $end in %s/tests/Expressions/yield.php on line 1"
  },
  {
    "path": "tests/Functions/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Functions/TestInc.php",
    "content": "<?hh // strict\n\nnamespace NS_TestInc;\n\nfunction f2(): void {\n  echo \"Inside function \" . __FUNCTION__ . \"\\n\";\n}\n"
  },
  {
    "path": "tests/Functions/TestInc.php.expect",
    "content": ""
  },
  {
    "path": "tests/Functions/anonymous_function_name.php",
    "content": "<?hh // strict\n\nnamespace NS_anonymous_function_name;\n\nclass C {\n  public function f(): void {\n    echo \"__FUNCTION__ = \" . __FUNCTION__ . \"\\n\";\n    echo \"__METHOD__ = \" . __METHOD__ . \"\\n\";\n\n    $res = (function (): void {\t\t\n      echo \"__FUNCTION__ = \" . __FUNCTION__ . \"\\n\";\n      echo \"__METHOD__ = \" . __METHOD__ . \"\\n\";\n    });\n\n    $res();\n  }\n}\n\nfunction main(): void {\n  echo \"__FUNCTION__ = \" . __FUNCTION__ . \"\\n\";\n  echo \"__METHOD__ = \" . __METHOD__ . \"\\n\";\n\n  $res = (function (): void {\n    echo \"__FUNCTION__ = \" . __FUNCTION__ . \"\\n\";\n    echo \"__METHOD__ = \" . __METHOD__ . \"\\n\";\n  });\n\n  $res();\n\n  $c = new C();\n  $c->f();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Functions/anonymous_function_name.php.expect",
    "content": "__FUNCTION__ = NS_anonymous_function_name\\main\n__METHOD__ = NS_anonymous_function_name\\main\n__FUNCTION__ = {closure}\n__METHOD__ = {closure}\n__FUNCTION__ = f\n__METHOD__ = NS_anonymous_function_name\\C::f\n__FUNCTION__ = {closure}\n__METHOD__ = NS_anonymous_function_name\\C::{closure}"
  },
  {
    "path": "tests/Functions/anonymous_functions.php",
    "content": "<?hh // strict\n\nnamespace NS_anonymous_functions;\n\nclass Cz {\n  private ?(function (int): int) $pr1;\n  private array<(function (int): int)> $pr2;\n  private ?array<(function (int): int)> $pr3;\n  private ?array<?(function (int): int)> $pr4;\n\n/*\nIf the initialization of pr2 is omitted from the constructor below, get the following message:\n\nThe class member pr2 is not always properly initialized\nMake sure you systematically set $this->pr2 when the method __construct is called\nAlternatively, you can define the type as optional (?...)\n*/\n  public function __construct() {\n    $this->pr2 = array(\n      function (int $p): int { return $p * 2; }, \n      function (int $p): int { return $p * $p; }\n    );\n  }\n}\n\n\ninterface I {}\nclass C implements I {}\n\nfunction double(int $p): int {\n  return $p * 2;\n}\n\nfunction square(int $p): int {\n  return $p * $p;\n}\n\nfunction doit(int $value, (function (int): int) $process): int {\n  var_dump($process);\n\n  return $process($value);\n}\n\nfunction compute(array<int> $values): void {\n  $count = 0;\n        \n//  $callback = function () use (&$count)\n  $callback = function () use ($count) {\n    echo \"Inside method >>\" . __METHOD__ . \"<<\\n\";\t// called {closure}\n    ++$count;\n  };\n\n  $callback();\n  echo \"\\$count = $count\\n\";\n  $callback();\n  echo \"\\$count = $count\\n\";\n}\n\nclass D {\n  private function f(): void {\n    echo \"Inside method >>\" . __METHOD__ . \"<<\\n\";\n  }\n\n  public function compute(array<string, int> $values): void {\n    $count = 0;\n        \n//  $callback = function (int $p1, int $p2): void use (&$count, $values)\n    $callback = function (int $p1, int $p2): void use ($count, $values) {\n      echo \"Inside method >>\" . __METHOD__ . \"<<\\n\";\t// called D::{closure}\n      ++$count;\n\n      $this->f();\t// $this is available automatically; can't put it in use clause anyway\n    };\n\n    echo \"--\\n\";\n    var_dump(gettype($callback));\n    echo \"--\\n\";\n    var_dump($callback);\n    echo \"--\\n\";\n    var_dump($callback instanceof \\Closure);\n    echo \"--\\n\";\n\n    $callback(1, 2);\n    echo \"\\$count = $count\\n\";\n    $callback(5, 6);\n    echo \"\\$count = $count\\n\";\n        \n    $callback2 = function(): void {\n      echo \"Inside method >>\" . __METHOD__ . \"<<\\n\";\t// ALSO called D::{closure}\n    };\n\n    echo \"--\\n\";\n    var_dump(gettype($callback2));\n    echo \"--\\n\";\n    var_dump($callback2);\n    echo \"--\\n\";\n    var_dump($callback2 instanceof \\Closure);\n    echo \"--\\n\";\n\n    $callback2();\n  }\n\n  public static function stcompute(array<string, int> $values): void {\n    $count = 0;\n        \n//    $callback = function ($p1, $p2) use (&$count, $values)\n    $callback = function (int $p1, int $p2): void use ($count, $values) {\n      echo \"Inside method >>\" . __METHOD__ . \"<<\\n\";\t// called D::{closure}\n      ++$count;\n    };\n\n    echo \"--\\n\";\n    var_dump(gettype($callback));\n    echo \"--\\n\";\n    var_dump($callback);\n    echo \"--\\n\";\n    var_dump($callback instanceof \\Closure);\n    echo \"--\\n\";\n\n    $callback(1, 2);\n    echo \"\\$count = $count\\n\";\n    $callback(5, 6);\n    echo \"\\$count = $count\\n\";\n  }\n}\n\n// (corrected) example from the Hack doc site\n\nfunction foo_closure(string $adder_str): (function (string): int) {\n  return function($to_str) use ($adder_str) {\n    return strlen($to_str) + strlen($adder_str);\n  };\n}\n\nfunction main_closure_example(): void {\n  $hello = foo_closure(\"Hello\");\n  $facebook = foo_closure(\"Facebook\");\n  $fox = foo_closure(\"Fox\");\n\n  echo $hello(\"World\") . \"\\n\";\n  echo $facebook(\"World\") . \"\\n\";\n  echo $fox(\"World\") . \"\\n\";\n}\n\n// example from the Hack doc site\n// Completely contrived\n\nfunction f1((function(int, int): string) $x): string {\n  return $x(2,3);\n}\n\nfunction f2(): string {\n//  $c = function($n, int $m) {\n//  $c = function($n, $m) {\n  $c = function(int $n, int $m): string {\n    $r = '';\n    for ($i=0; $i<$n+$m; $i++) {\n      $r .= \"hi\";\n    }\n    return $r;\n  };\n  return f1($c);\n}\n\nfunction main(): void {\n  echo \"----------------- main_closure_example from Hack doc site ----------------------\\n\";\n\n  main_closure_example();\n\n  echo \"Calling f2 =>\" . f2() . \"<\\n\";\n\n  echo \"----------------- closure with no parameters ----------------------\\n\";\n\n//  $cl1 = function ()\n//  $cl1 = function (): int\n  $cl1 = function (): void {\n    echo \"Inside function >>\" . __FUNCTION__ . \"<<\\n\";\n    echo \"Inside method >>\" . __METHOD__ . \"<<\\n\";\n    // ...\n//  return 123;\t// test\n  };\n\n  echo \"--\\n\";\n  var_dump(gettype($cl1));\n  echo \"--\\n\";\n  var_dump($cl1);\n  echo \"--\\n\";\n  var_dump($cl1 instanceof \\Closure);\n  echo \"--\\n\";\n\n  $cl1();\n//  $x = $cl1();\t\t// test\n//  echo \"\\$x = $x\\n\";\t// test\n\n  // Closure object is empty\n\n  echo \"----------------- closure with 5 parameters ----------------------\\n\";\n\n//  $cl2 = function ($p1, $p2, $p3, $p4, $p5)\n  $cl2 = function (int $p1, int $p2, array<int> $p3, C $p4, I $p5): void {\n    echo \"Inside function >>\" . __FUNCTION__ . \"<<\\n\";\n    echo \"Inside method >>\" . __METHOD__ . \"<<\\n\";\n    // ...\n  };\n\n  echo \"--\\n\";\n  var_dump(gettype($cl2));\n  echo \"--\\n\";\n  var_dump($cl2);\n  echo \"--\\n\";\n  var_dump($cl2 instanceof \\Closure);\n  echo \"--\\n\";\n\n  $cl2(10, 20, array(1, 2), new C(), new C());\n\n  echo \"----------------- passing a callable to a function ----------------------\\n\";\n\n  $res = doit(10, fun('\\NS_anonymous_functions\\double'));\n  echo \"Result of calling doit using function double = $res\\n-------\\n\";\n\n  $res = doit(10, fun('\\NS_anonymous_functions\\square'));\n  echo \"Result of calling doit using function square = $res\\n-------\\n\";\n\n  $doubleFun = function (int $p): int { return $p * 2; };\n  $squareFun = function (int $p): int { return $p * $p; };\n\t\n  $res = doit(5, $doubleFun);\n  echo \"Result of calling doit using double closure = $res\\n-------\\n\";\n\n  $res = doit(5, $squareFun);\n  echo \"Result of calling doit using square closure = $res\\n-------\\n\";\n\n  $functionList = array($doubleFun, $squareFun);\n  echo \"\\$functionList[0] returns \" . $functionList[0](12) . \"\\n\";\n  echo \"\\$functionList[1] returns \" . $functionList[1](15) . \"\\n\";\n  var_dump($functionList);\n\n  echo \"----------------- using a use clause, #1 ----------------------\\n\";\n\n  compute(array(1,2,3));\n\n  echo \"----------------- using a use clause, #2 (instance method) ----------------------\\n\";\n\n  $d1 = new D();\n  $d1->compute(array(\"red\" => 3, \"green\" => 10));\n\n  echo \"----------------- using a use clause, #3 (static method) ----------------------\\n\";\n\n  D::stcompute(array(\"red\" => 3, \"green\" => 10));\n\n  echo \"----------------- Misc. Stuff ----------------------\\n\";\n\n//  (function (): void { echo \"Hi\\n\"; })();\t\t// can't use an anon function directly with ()\n  $v = (function (): void { echo \"Hi\\n\"; });\n  $v();\n\n// can have attributes, default values, and ...\n\n  $v = (function (<<XX>> int $p = 123, ...): void { echo \"\\$p = $p\\n\"; });\n  $v(6, 7, 8);\n  $v(-5);\n  $v();\n//  $v(10.5);\t// float is incompatible with int\n\n// parameter type can be omitted and implied from default value\n\n  $v = (function ($p = 123): void { echo \"\\$p = $p\\n\"; });\n  $v(-5);\n  $v();\n//  $v(10.5);\t// float is incompatible with int\n\n// parameter type can be omitted\n\n  $v = (function ($p): void { echo \"\\$p = $p\\n\"; });\n  $v(-5);\n  $v(10.5);\n\n// return type can be omitted and inferred\n\n  $v = (function ($p) { echo \"\\$p = $p\\n\"; });\n  $v(-5);\n  $v(10.5);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Functions/anonymous_functions.php.expectf",
    "content": "----------------- main_closure_example from Hack doc site ----------------------\n10\n13\n8\nCalling f2 =>hihihihihi<\n----------------- closure with no parameters ----------------------\n--\nstring(6) \"object\"\n--\nobject(Closure$NS_anonymous_functions\\I::NS_anonymous_functions\\main;%d)#%d (0) {\n}\n--\nbool(true)\n--\nInside function >>{closure}<<\nInside method >>{closure}<<\n----------------- closure with 5 parameters ----------------------\n--\nstring(6) \"object\"\n--\nobject(Closure$NS_anonymous_functions\\I::NS_anonymous_functions\\main#%d;%d)#%d (1) {\n  [\"parameter\"]=>\n  array(5) {\n    [\"$p1\"]=>\n    string(10) \"<required>\"\n    [\"$p2\"]=>\n    string(10) \"<required>\"\n    [\"$p3\"]=>\n    string(10) \"<required>\"\n    [\"$p4\"]=>\n    string(10) \"<required>\"\n    [\"$p5\"]=>\n    string(10) \"<required>\"\n  }\n}\n--\nbool(true)\n--\nInside function >>{closure}<<\nInside method >>{closure}<<\n----------------- passing a callable to a function ----------------------\nstring(30) \"\\NS_anonymous_functions\\double\"\nResult of calling doit using function double = 20\n-------\nstring(30) \"\\NS_anonymous_functions\\square\"\nResult of calling doit using function square = 100\n-------\nobject(Closure$NS_anonymous_functions\\I::NS_anonymous_functions\\main#%d;%d)#%d (1) {\n  [\"parameter\"]=>\n  array(1) {\n    [\"$p\"]=>\n    string(10) \"<required>\"\n  }\n}\nResult of calling doit using double closure = 10\n-------\nobject(Closure$NS_anonymous_functions\\I::NS_anonymous_functions\\main#%d;%d)#%d (1) {\n  [\"parameter\"]=>\n  array(1) {\n    [\"$p\"]=>\n    string(10) \"<required>\"\n  }\n}\nResult of calling doit using square closure = 25\n-------\n$functionList[0] returns 24\n$functionList[1] returns 225\narray(2) {\n  [0]=>\n  object(Closure$NS_anonymous_functions\\I::NS_anonymous_functions\\main#%d;%d)#%d (1) {\n    [\"parameter\"]=>\n    array(1) {\n      [\"$p\"]=>\n      string(10) \"<required>\"\n    }\n  }\n  [1]=>\n  object(Closure$NS_anonymous_functions\\I::NS_anonymous_functions\\main#%d;%d)#%d (1) {\n    [\"parameter\"]=>\n    array(1) {\n      [\"$p\"]=>\n      string(10) \"<required>\"\n    }\n  }\n}\n----------------- using a use clause, #1 ----------------------\nInside method >>{closure}<<\n$count = 0\nInside method >>{closure}<<\n$count = 0\n----------------- using a use clause, #2 (instance method) ----------------------\n--\nstring(6) \"object\"\n--\nobject(Closure$NS_anonymous_functions\\D::compute;%d)#%d (3) {\n  [\"static\"]=>\n  array(2) {\n    [\"count\"]=>\n    int(0)\n    [\"values\"]=>\n    array(2) {\n      [\"red\"]=>\n      int(3)\n      [\"green\"]=>\n      int(10)\n    }\n  }\n  [\"parameter\"]=>\n  array(2) {\n    [\"$p1\"]=>\n    string(10) \"<required>\"\n    [\"$p2\"]=>\n    string(10) \"<required>\"\n  }\n  [\"this\"]=>\n  object(NS_anonymous_functions\\D)#10 (0) {\n  }\n}\n--\nbool(true)\n--\nInside method >>NS_anonymous_functions\\D::{closure}<<\nInside method >>NS_anonymous_functions\\D::f<<\n$count = 0\nInside method >>NS_anonymous_functions\\D::{closure}<<\nInside method >>NS_anonymous_functions\\D::f<<\n$count = 0\n--\nstring(6) \"object\"\n--\nobject(Closure$NS_anonymous_functions\\D::compute#%d;%d)#%d (1) {\n  [\"this\"]=>\n  object(NS_anonymous_functions\\D)#10 (0) {\n  }\n}\n--\nbool(true)\n--\nInside method >>NS_anonymous_functions\\D::{closure}<<\n----------------- using a use clause, #3 (static method) ----------------------\n--\nstring(6) \"object\"\n--\nobject(Closure$NS_anonymous_functions\\D::stcompute;%d)#%d (2) {\n  [\"static\"]=>\n  array(2) {\n    [\"count\"]=>\n    int(0)\n    [\"values\"]=>\n    array(2) {\n      [\"red\"]=>\n      int(3)\n      [\"green\"]=>\n      int(10)\n    }\n  }\n  [\"parameter\"]=>\n  array(2) {\n    [\"$p1\"]=>\n    string(10) \"<required>\"\n    [\"$p2\"]=>\n    string(10) \"<required>\"\n  }\n}\n--\nbool(true)\n--\nInside method >>NS_anonymous_functions\\D::{closure}<<\n$count = 0\nInside method >>NS_anonymous_functions\\D::{closure}<<\n$count = 0\n----------------- Misc. Stuff ----------------------\nHi\n$p = 6\n$p = -5\n$p = 123\n$p = -5\n$p = 123\n$p = -5\n$p = 10.5\n$p = -5\n$p = 10.5\n"
  },
  {
    "path": "tests/Functions/anonymous_functions2.php",
    "content": "<?hh // strict\n\nnamespace NS_qq;\n\nfunction main(num $p1): void\n{\n  echo \"=========== \\$doubler1 ===============\\n\\n\";\n\n  $doubler1 = (function ($p) { var_dump($p); return $p * 2; });\n  var_dump($doubler1(3));\n  var_dump($doubler1(4.2));\n  var_dump($doubler1($p1));\n\n  echo \"\\n=========== \\$doubler2 ===============\\n\\n\";\n\n  $doubler2 = (function ($p) { var_dump($p); return $p * 2.0; });\n  var_dump($doubler2(3));\n  var_dump($doubler2(4.2));\n  var_dump($doubler2($p1));\n\n  echo \"\\n=========== \\$doubler3 ===============\\n\\n\";\n\n//  $doubler3 = (function (int $p) { var_dump($p); return $p * 2; });\n//  $doubler3 = (function ($p = 0) { var_dump($p); return $p * 2; });\n  $doubler3 = (function ($p): int { var_dump($p); return $p * 2; });\n  var_dump($doubler3(3));\n//  var_dump($doubler3(4.2));\t// rejected; int/float not compatible\n//  var_dump($doubler3($p1));\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain(10);\n/* HH_FIXME[1002] call to main in strict*/\nmain(1.3);\n"
  },
  {
    "path": "tests/Functions/anonymous_functions2.php.expect",
    "content": "=========== $doubler1 ===============\n\nint(3)\nint(6)\nfloat(4.2)\nfloat(8.4)\nint(10)\nint(20)\n\n=========== $doubler2 ===============\n\nint(3)\nfloat(6)\nfloat(4.2)\nfloat(8.4)\nint(10)\nfloat(20)\n\n=========== $doubler3 ===============\n\nint(3)\nint(6)\n=========== $doubler1 ===============\n\nint(3)\nint(6)\nfloat(4.2)\nfloat(8.4)\nfloat(1.3)\nfloat(2.6)\n\n=========== $doubler2 ===============\n\nint(3)\nfloat(6)\nfloat(4.2)\nfloat(8.4)\nfloat(1.3)\nfloat(2.6)\n\n=========== $doubler3 ===============\n\nint(3)\nint(6)"
  },
  {
    "path": "tests/Functions/async_functions.php",
    "content": "<?hh // strict\n\nnamespace NS_as1;\n\n// async and abstract methods ---------------------------------\n\ninterface I1 {\n  public function f1(): Awaitable<string>;\t// async not allowed here\n}\n\nclass C1 implements I1 {\n  public async function f1(): Awaitable<string> { return \"abc\"; }\n}\n\n// test basic async functions ---------------------------------\n\nasync function calc(): Awaitable<int> {\n  await \\HH\\Asio\\usleep(2000000);\n  return 100;\n}\n\nasync function control(): Awaitable<void> {\n  $awaitable = calc();\n  $result = await $awaitable;\n//  $result = await calc();\t// short version of the 2 assignments above\n\n  await calc();\n\n  echo \"\\$result = $result\\n\";\n}\n\n// define a pair of functions to be awaited on -----------------\n\nasync function dbq1(): Awaitable<int> {\n  await \\HH\\Asio\\usleep(3000000);\n  return 3000;\n}\n\nasync function dbq2(): Awaitable<int> {\n  $v = \\HH\\Asio\\usleep(1000000);\n  return 4000;\n}\n\n// some async iterators\n\nasync function countdown1(int $start): AsyncIterator<int> {\n  for ($i = $start; $i >= 0; --$i) {\n    await \\HH\\Asio\\usleep(1000000); // Sleep for 1 second\n    yield $i;\n  }\n}\n\nasync function use_countdown1(): Awaitable<void> {\n  $async_gen = countdown1(3);\n  foreach ($async_gen await as $value) {\n    // $value is of type int here\n    var_dump($value);\n  }\n}\n\nasync function countdown2(int $start): AsyncKeyedIterator<int, string> {\n  for ($i = $start; $i >= 0; --$i) {\n    await \\HH\\Asio\\usleep(1000000);\n    yield $i => (string)$i;\n  }\n}\n\nasync function use_countdown2(): Awaitable<void> {\n  foreach (countdown2(3) await as $num => $str) {\n    // $num is of type int\n    // $str is of type string\n    var_dump($num, $str);\n  }\n}\n\n// async blocks ------------------------\n\nasync function doit(): Awaitable<void> {\n\n  await async {\t\t// block result has type awaitable<void>\n  };\t\t\t// implicit return nothing\n  var_dump(async {});\n  echo \"-----------------\\n\";\n\n  await async {\t\t// block result has type awaitable<void>\n    return;\t\t// explicit return nothing\n  };\n  var_dump(async { return; });\n  echo \"-----------------\\n\";\n\n  await async {\t\t// block result has type awaitable<int>\n    return 123;\n  };\n\n  $v = await async {\t\t// block result has type awaitable<int>\n    return 123;\n  };\n  var_dump($v, async { return 123; });\n  echo \"-----------------\\n\";\n\n  $v = await async {\t\t// block result has type awaitable<float>\n    return 1.23;\n  };\n  var_dump($v, async { return 1.23; });\n  echo \"-----------------\\n\";\n\n  $v = await \\HH\\Asio\\v(array(async { return 10; }, async { return 1.2; }));\n// first block result has type awaitable<int>, the second, awaitable<float>\n\n  var_dump($v);\n  echo \"-----------------\\n\";\n\n  $v = await \\HH\\Asio\\v(array(async { return 1.2; }, async { return 10; }));\n// first block result has type awaitable<float>, the second, awaitable<int>\n  var_dump($v);\n}\n\n// return type is a composite of all possible types returned ---------------\n\nasync function threeWay(int $p): Awaitable<?arraykey> {\n  if ($p == 0) return null;\n  elseif ($p < 0) return 10;\n  else return \"abc\";\n}\n\n// In what constexts can we use await directly? -----------------------\n\nasync function fDirect(): Awaitable<int> {\n//**  takesAnInt(await calc());\t// runtime Fatal error: syntax error, unexpected T_AWAIT, expecting ')'\n//  $a = array(await calc());\t// runtime Fatal error: syntax error, unexpected T_AWAIT, expecting ')'\n//  $vect = Vector {await calc()};\t// runtime Fatal error: syntax error, unexpected T_AWAIT\n//  $t2 = tuple(await calc());\t// runtime Fatal error: syntax error, unexpected T_AWAIT, expecting ')'\n//  $s = shape('x' => await calc());\t// runtime Fatal error: syntax error, unexpected T_AWAIT\n//  $cl = clone await calc();\t// runtime Fatal error: syntax error, unexpected T_AWAIT\n//  $v = (await calc()) instanceof C1;\t// runtime Fatal error: syntax error, unexpected T_AWAIT\n//  $v = async { return 10; } == await calc();\t// runtime Fatal error: syntax error, unexpected T_AWAIT\n//  $v = true ? (await calc()) : (async { return 5; });\t// runtime Fatal error: syntax error, unexpected T_AWAIT\n\n  await calc();\t\t\t// in an expression statement\n  $v = await calc();\t\t// RHS of a simple assignment\n//  return (await calc());\t// runtime Fatal error: syntax error, unexpected T_AWAIT\n  return await calc();\t\t// OK as the full expression in a return\n}\n\nfunction takesAnInt(int $p): void {\n}\n\n// the main program ------------------------\n\nasync function main(): Awaitable<void> {\n  echo \"\\nTest some basics ======================\\n\\n\";\n\n///*\n  await control();\n\n  echo \"\\nWait on multiple async operations ======================\\n\\n\";\n\n  $awaitables = array(dbq1(), dbq2());\n  $groupAwaitables = \\HH\\Asio\\v($awaitables);\n  await $groupAwaitables;\n  await \\HH\\Asio\\v(array(dbq1(), dbq2()));\t// short version of the 3 statements above\n\n  echo \"\\nUse async iterators ======================\\n\\n\";\n\n  await use_countdown1();\n  await use_countdown2();\n//*/\n  echo \"\\nTest async blocks ======================\\n\\n\";\n\n  await doit();\n\n  echo \"\\nCheck usage contexts for await ======================\\n\\n\";\n\n  await fDirect();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\n\\HH\\Asio\\join(main());\n"
  },
  {
    "path": "tests/Functions/async_functions.php.expectf",
    "content": "\nTest some basics ======================\n\n$result = 100\n\nWait on multiple async operations ======================\n\n\nUse async iterators ======================\n\nint(3)\nint(2)\nint(1)\nint(0)\nint(3)\nstring(1) \"3\"\nint(2)\nstring(1) \"2\"\nint(1)\nstring(1) \"1\"\nint(0)\nstring(1) \"0\"\n\nTest async blocks ======================\n\nobject(HH\\StaticWaitHandle)#%d (0) {\n}\n-----------------\nobject(HH\\StaticWaitHandle)#%d (0) {\n}\n-----------------\nint(123)\nobject(HH\\StaticWaitHandle)#%d (0) {\n}\n-----------------\nfloat(1.23)\nobject(HH\\StaticWaitHandle)#%d (0) {\n}\n-----------------\nobject(HH\\Vector)#%d (2) {\n  [0]=>\n  int(10)\n  [1]=>\n  float(1.2)\n}\n-----------------\nobject(HH\\Vector)#%d (2) {\n  [0]=>\n  float(1.2)\n  [1]=>\n  int(10)\n}\n\nCheck usage contexts for await ======================\n"
  },
  {
    "path": "tests/Functions/async_functions2.php",
    "content": "<?hh // strict\n\nnamespace NS_async_functions2;\n\nasync function f(): Awaitable<int> {\n\n  echo 'Inside ' . __FUNCTION__ . \"\\n\";\n\n  // ...\n\n  echo \"Enter await\\n\";\n  $r1 = await g();\t// $r1 = int($r1); that is, the int is unwrapped from the Awaitable object\n  echo \"Exit await; \\$r1 = \";\n  var_dump($r1);\n\n  return $r1;\t\t// int($r1) is wrapped by an Awaitable object, which is returned\n}\n\nasync function g(): Awaitable<int> {\n\n  echo 'Inside ' . __FUNCTION__ . \"\\n\";\n\n  // ...\n  $r2 = 10;\n\n  return $r2;\t\t// int($r2) is wrapped by an Awaitable object, which is returned\n}\n\nfunction main (): void {\n  $v = f();\t\t// $v = object(HH\\StaticWaitHandle)#1 (0)\n  echo \"\\$v = \";\n  var_dump($v);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Functions/async_functions2.php.expect",
    "content": "Inside NS_async_functions2\\f\nEnter await\nInside NS_async_functions2\\g\nExit await; $r1 = int(10)\n$v = object(HH\\StaticWaitHandle)#1 (0) {\n}"
  },
  {
    "path": "tests/Functions/basics.php",
    "content": "<?hh // strict\n\nnamespace NS_functions_basics;\n\n// Function names are not case-sensitive\n\nfunction f(): void { echo \"f\\n\"; }\n//function F(): void { echo \"F\\n\"; }\t// F is equivalent to f\n\n// function having no declared parameters\n\nfunction f1(...): void {\n  $argList = func_get_args();\n  echo \"f1: # arguments passed is \".count($argList).\"\\n\";\n\n  foreach ($argList as $k => $e) {\n    echo \"\\targ[$k] = >$e<\\n\";\n  }\n}\n\n// function having 2 declared parameters\n\nfunction f2(int $p1, int $p2): void {\n  // A null value doesn't prove the argument wasn't passed; find a better test\n\n  echo \"f2: \\$p1 = \".($p1 == null ? \"null\" : $p1).\n    \", \\$p2 = \".($p2 == null ? \"null\" : $p2).\"\\n\"; \n}\n\nfunction square(num $v): num {\n  return $v * $v;\n}\n\nfunction addVector(Vector<int> $v1, Vector<int> $v2): Vector<int> {\n  $result = Vector{};\n\n  // ...\n\n  return $result;\n}\n\nfunction main(): void {\n//  var_dump(f1());\t// call f1, default return value is null\n//  $f = f1;\t// PHP: assign this string to a variable; Hack disallows\n//  $f();\t\t// PHP: call f1 indirectly via $f; Hack disallows\n\n  f1();\n  f1(10);\n  f1(true, \"green\");\n  f1(23.45, null, array(1,2,3));\n\n  f2(10, 20);\n\n// some simple examples of function calls\n\n  echo \"5 squared = \" . square(5) . \"\\n\";\n  echo strlen(\"abcedfg\").\"\\n\";\n\n  $v = addVector(Vector {10, 20}, Vector {60, 30, 10});\n  var_dump($v);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Functions/basics.php.expectf",
    "content": "f1: # arguments passed is 0\nf1: # arguments passed is 1\n\targ[0] = >10<\nf1: # arguments passed is 2\n\targ[0] = >1<\n\targ[1] = >green<\nf1: # arguments passed is 3\n\targ[0] = >23.45<\n\targ[1] = ><\n\nNotice: Array to string conversion in %s/tests/Functions/basics.php on line 17\n\targ[2] = >Array<\nf2: $p1 = 10, $p2 = 20\n5 squared = 25\n7\nobject(HH\\Vector)#3 (0) {\n}"
  },
  {
    "path": "tests/Functions/callable_typehint.php",
    "content": "<?hh // strict\n\nnamespace NS_callable_typehint;\n\nfunction hello(): void {\n  echo \"Hello!\\n\";\n}\n\n//function f5(callable $p1): void {\t// callable type hint not permitted\nfunction f5((function (): void) $p1): void {\n  echo \"Inside \" . __FUNCTION__ . \"\\n\";\n\n  var_dump($p1);\n  $p1();\n}\n\nfunction main(): void {\n  f5(fun('\\NS_callable_typehint\\hello'));\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Functions/callable_typehint.php.expect",
    "content": "Inside NS_callable_typehint\\f5\nstring(27) \"\\NS_callable_typehint\\hello\"\nHello!"
  },
  {
    "path": "tests/Functions/conditionally_defined_function.php",
    "content": "<?hh // strict\n\nnamespace NS_functions_conditionally-defined;\n\n// Unconditionally defined function\n\nfunction ucf1(): void {\n  echo \"Inside unconditionally defined function ucf1\\n\";\n}\n\n// Conditionally defined function\n\n/*\n// nested function definitions are not supported\n\nfunction ucf2(): void {\n  function cf2(): void {\n    echo \"Inside conditionally defined function cf2\\n\";\n  }\n}\n*/\n\nfunction main(): void {\n  ucf1();\t\t// can call ucf1 before its definition is seen\n\n  ucf1();\t\t// can call ucf1 after its definition is seen\n\n  $flag = true;\n/*\n  cf1();\t// Error; call to undefined function\n\n  if ($flag) {\n// nested/conditional function definitions are not supported\n    function cf1(): void {\n      echo \"Inside conditionally defined function cf1\\n\";\n    }\n  }\n\n  if ($flag) {\n    cf1();\t// can call cf1 now, as it's been defined\n  } else {\n    cf1();\t// Error; call to undefined function\n  }\n*/\n//  cf2();\t\t// Error; call to undefined function\n//  ucf2();\t\t// cf2 now exists\n//  cf2();\t\t// Ok\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Functions/conditionally_defined_function.php.expectf",
    "content": "\nFatal error: syntax error, unexpected '-', expecting T_NS_SEPARATOR or ';' or '{' in %s/tests/Functions/conditionally_defined_function.php on line 3"
  },
  {
    "path": "tests/Functions/default_arguments.php",
    "content": "<?hh // strict\n\nnamespace NS_default_arguments;\n\nfunction f1(int $p1 = 10, float $p2 = 1.23, bool $p3 = true, mixed $p4 = null, string $p5 = \"abc\",\n  ?array<mixed> $p6 = [1,array()]): void {\n  $argList = func_get_args();\n  echo \"f1: # arguments passed is \".count($argList).\"\\n\";\n\n  foreach ($argList as $k => $e) {\n    echo \"\\targ[$k] = >$e<\\n\";\n  }\n  var_dump($p1, $p2, $p3, $p4, $p5, $p6);\n}\n\n/*\n// if any leading parameter has a default argument then all those following must have one too.\n\n// 2 default followed by one non-default; unusual, but permitted\n\nfunction f2(int $p1 = 100, int $p2 = 1.23, int $p3): void {\n}\n*/\n\n// 1 non-default followed by two default\n\nfunction f4(int $p1, int $p2 = -100, int $p3 = -200): void {\n  $argList = func_get_args();\n  echo \"f4: # arguments passed is \".count($argList).\"\\n\";\n\n  foreach ($argList as $k => $e) {\n    echo \"\\targ[$k] = >$e<\\n\";\n  }\n  var_dump($p1, $p2, $p3);\n}\n\nfunction f3(int $p1 = -1, float $p2 = 99.99, string $p3 = '??'): void {\n  echo \"\\$p1 is $p1, \\$p2 is $p2, \\$p3 is $p3\\n\";\n}\n\nfunction main(): void {\n  f1();\n  f1(12);\n//  f1(10.5);\t// mismatch; rejected\n  f1(12, 10.5);\n  f1(12, 10.5, false);\n  f1(12, 10.5, false, 100);\n  f1(12, 10.5, false, 'aaa', 'xxx');\n  f1(12, 10.5, false, 'aaa', 'xxx', null);\n\n//  f4();\t\t// too few arguments\n  f4(10);\n  f4(10, 20);\n  f4(10, 20, 30);\n\n  f3();\t\t\t\t// $p1 is -1, $p2 is 99.99, $p3 is ??\n  f3(123);\t\t\t// $p1 is 123, $p2 is 99.99, $p3 is ??\n  f3(123, 3.14);\t\t// $p1 is 123, $p2 is 3.14, $p3 is ??\n  f3(123, 3.14, 'Hello');\t// $p1 is 123, $p2 is 3.14, $p3 is Hello\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Functions/default_arguments.php.expect",
    "content": "f1: # arguments passed is 0\nint(10)\nfloat(1.23)\nbool(true)\nNULL\nstring(3) \"abc\"\narray(2) {\n  [0]=>\n  int(1)\n  [1]=>\n  array(0) {\n  }\n}\nf1: # arguments passed is 1\n\targ[0] = >12<\nint(12)\nfloat(1.23)\nbool(true)\nNULL\nstring(3) \"abc\"\narray(2) {\n  [0]=>\n  int(1)\n  [1]=>\n  array(0) {\n  }\n}\nf1: # arguments passed is 2\n\targ[0] = >12<\n\targ[1] = >10.5<\nint(12)\nfloat(10.5)\nbool(true)\nNULL\nstring(3) \"abc\"\narray(2) {\n  [0]=>\n  int(1)\n  [1]=>\n  array(0) {\n  }\n}\nf1: # arguments passed is 3\n\targ[0] = >12<\n\targ[1] = >10.5<\n\targ[2] = ><\nint(12)\nfloat(10.5)\nbool(false)\nNULL\nstring(3) \"abc\"\narray(2) {\n  [0]=>\n  int(1)\n  [1]=>\n  array(0) {\n  }\n}\nf1: # arguments passed is 4\n\targ[0] = >12<\n\targ[1] = >10.5<\n\targ[2] = ><\n\targ[3] = >100<\nint(12)\nfloat(10.5)\nbool(false)\nint(100)\nstring(3) \"abc\"\narray(2) {\n  [0]=>\n  int(1)\n  [1]=>\n  array(0) {\n  }\n}\nf1: # arguments passed is 5\n\targ[0] = >12<\n\targ[1] = >10.5<\n\targ[2] = ><\n\targ[3] = >aaa<\n\targ[4] = >xxx<\nint(12)\nfloat(10.5)\nbool(false)\nstring(3) \"aaa\"\nstring(3) \"xxx\"\narray(2) {\n  [0]=>\n  int(1)\n  [1]=>\n  array(0) {\n  }\n}\nf1: # arguments passed is 6\n\targ[0] = >12<\n\targ[1] = >10.5<\n\targ[2] = ><\n\targ[3] = >aaa<\n\targ[4] = >xxx<\n\targ[5] = ><\nint(12)\nfloat(10.5)\nbool(false)\nstring(3) \"aaa\"\nstring(3) \"xxx\"\nNULL\nf4: # arguments passed is 1\n\targ[0] = >10<\nint(10)\nint(-100)\nint(-200)\nf4: # arguments passed is 2\n\targ[0] = >10<\n\targ[1] = >20<\nint(10)\nint(20)\nint(-200)\nf4: # arguments passed is 3\n\targ[0] = >10<\n\targ[1] = >20<\n\targ[2] = >30<\nint(10)\nint(20)\nint(30)\n$p1 is -1, $p2 is 99.99, $p3 is ??\n$p1 is 123, $p2 is 99.99, $p3 is ??\n$p1 is 123, $p2 is 3.14, $p3 is ??\n$p1 is 123, $p2 is 3.14, $p3 is Hello"
  },
  {
    "path": "tests/Functions/noreturn.php",
    "content": "<?hh // strict\n\nnamespace NS_noreturn;\n\nclass ExceptionA extends \\Exception {}\nclass ExceptionB extends \\Exception {}\n\n// ============================== test functions ==============================\n\n/*\nfunction f1(): noreturn { }\t\t// implicit return nothing is disallowed\nfunction f2(): noreturn { return; }\t// explicit return nothing is disallowed\nfunction f3(): noreturn { return 10; }\t// explicit return anything is disallowed\n\nfunction f4(bool $p): noreturn { \n  if ($p) exit(10);\n}\t\t\t\t\t// implicit return nothing on false is disallowed\n\nfunction f5(bool $p): noreturn { \n  if ($p) ; else exit(10);\n}\t\t\t\t\t// implicit return nothing on true is disallowed\n*/\n\nfunction f6(int $p): noreturn { \n  if ($p < 0) throw new ExceptionA();\n  else if ($p > 0) throw new ExceptionB();\n  else exit(10);\n}\t\t\t\t\t// Okay; no path returns\n\n//function caller1(): void { $p = f6(123); }\t// disallowed, as function does not return at all let along a value\n\n\n// What about nested noreturn-function calls?\n\n/*\nThis is disallowed on 2 fronts:\n  Invalid return type (Typing[4110])\n    This is noreturn (throws or exits)\n    It is incompatible with void because this function implicitly returns void\n    You are using the return value of a noreturn function (Typing[4133])\n    A noreturn function always throws or exits\n*/\n\n/*\nfunction f7a(int $p): noreturn { \n  var_dump(f6($p));\t\t\t// disallowed; can't use non-existent value as arg to var_dump\n}\n*/\n\nfunction f7b(int $p): noreturn { \n  return f6($p);\t\t\t\t// Currently allowed; bug??\n}\n\nfunction f7c(int $p): noreturn { \n  f6($p);\n}\t\t\t\t\t\t// implicit return nothing is allowed\n\nfunction f7d(int $p): noreturn { \n  f6($p);\n//  return;\t\t\t\t\t// explicit return nothing is disallowed\n}\n\n// ============================== test instance methods ==============================\n\nclass C1 {\n/*\n  public function f1(): noreturn { }\t\t// implicit return nothing is disallowed\n  public function f2(): noreturn { return; }\t// explicit return nothing is disallowed\n  public function f3(): noreturn { return 10; }\t// explicit return anything is disallowed\n\n  public function f4(bool $p): noreturn { \n    if ($p) exit(10);\n  }\t\t\t\t\t\t// implicit return nothing on false is disallowed\n\n  public function f5(bool $p): noreturn { \n    if ($p) ; else exit(10);\n  }\t\t\t\t\t\t// implicit return nothing on true is disallowed\n*/\n\n  public function f6(int $p): noreturn { \n    if ($p < 0) throw new ExceptionA();\n    else if ($p > 0) throw new ExceptionB();\n    else exit(10);\n  }\t\t\t\t\t\t// Okay; no path returns but surpising. Not supposed to work here \n}\n\n// ============================== test instance methods ==============================\n\nclass C2 {\n/*\n  public static function f1(): noreturn { }\t\t// implicit return nothing is disallowed\n  public static function f2(): noreturn { return; }\t// explicit return nothing is disallowed\n  public static function f3(): noreturn { return 10; }\t// explicit return anything is disallowed\n\n  public static function f4(bool $p): noreturn { \n    if ($p) exit(10);\n  }\t\t\t\t\t\t\t// implicit return nothing on false is disallowed\n\n  public static function f5(bool $p): noreturn { \n    if ($p) ; else exit(10);\n  }\t\t\t\t\t\t\t// implicit return nothing on true is disallowed\n*/\n\n  public static function f6(int $p): noreturn { \n    if ($p < 0) throw new ExceptionA();\n    else if ($p > 0) throw new ExceptionB();\n    else exit(10);\n  }\t\t\t\t\t\t\t// Okay; no path returns\n}\n\n// ============================== end of script ==============================\n"
  },
  {
    "path": "tests/Functions/noreturn.php.expect",
    "content": ""
  },
  {
    "path": "tests/Functions/override_on_return_type.php",
    "content": "<?hh // strict\n\nnamespace NS_override_on_return_type;\n\nclass C1 {};\nclass C2 extends C1 {};\n\ninterface I {}\nclass C3 implements I {}\nclass C4 implements I {}\n\nclass B {\n  public function f1(): int { return 0; }\n  public function f2(): int { return 0; }\n  public function f3(): num { return 0; }\n  public function f4(): num { return 0; }\n  public function f5(): arraykey { return 0; }\n  public function f6(): arraykey { return 0; }\n  public function f7(): ?int { return 0; }\n  public function f8(): ?int { return 0; }\n  public function f9(): C1 { return new C1(); }\n  public function f10(): C1 { return new C1(); }\n  public function f11(): I { return new C3(); }\n  public function f12(): I { return new C3(); }\n}\n\nclass D extends B {\n  public function f1(): int { return 100; }\n//  public function f2(): float { return 100.2; }\t// float return type incompatible with int\n  public function f3(): int { return 0; }\t\t// OK; int is compatible with num\n  public function f4(): float { return 1.2; }\t// OK; float is compatible with num\n  public function f5(): int { return 0; }\t\t// OK; int is compatible with arraykey\n  public function f6(): string { return 'xxx'; }\t// OK; string is compatible with arraykey\n  public function f7(): ?int { return null; }\n  public function f8(): int { return 0; }\t\t// OK; int is compatible with ?int\n  public function f9(): C1 { return new C1(); }\n  public function f10(): C2 { return new C2(); }\t// OK; C2 is compatible with C1\n  public function f11(): I { return new C3(); }\t// OK; C3 is compatible with I\n  public function f12(): I { return new C4(); }\t// OK; C4 is compatible with I\n}\n\n\nclass GB<T> {\n// Invalid return type: This is a value of generic type T. It is incompatible with an int\n\n//  public function f13(): Vector<T> { return Vector {10, 20}; }\n}\n\nfunction main(): void {\n  $b = new B();\n  $b->f1();\n  $b->f2();\n  $b->f3();\n  $b->f4();\n  $b->f5();\n  $b->f6();\n  $b->f7();\n  $b->f8();\n  $b->f9();\n  $b->f10();\n\n  $d = new D();\n  $d->f1();\n  $d->f3();\n  $d->f4();\n  $d->f5();\n  $d->f6();\n  $d->f7();\n  $d->f8();\n  $d->f9();\n  $d->f10();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Functions/override_on_return_type.php.expect",
    "content": ""
  },
  {
    "path": "tests/Functions/recursion.php",
    "content": "<?hh // strict\n\nnamespace NS_functions_recursion;\n\nfunction main(): void {\n  for ($i = 0; $i <= 10; ++$i) {\n    printf(\"%2d! = %d\\n\", $i, factorial($i));\n  }\n}\n\n// use recursion to implement a factorial function\n// Note: can call a function prior to its definition\n\nfunction factorial(int $int): int {\n  return ($int > 1) ? $int * factorial($int - 1) : $int;\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Functions/recursion.php.expect",
    "content": " 0! = 0\n 1! = 1\n 2! = 2\n 3! = 6\n 4! = 24\n 5! = 120\n 6! = 720\n 7! = 5040\n 8! = 40320\n 9! = 362880\n10! = 3628800"
  },
  {
    "path": "tests/Functions/this_play.php",
    "content": "<?hh // strict\n\nnamespace NS_this_play;\n\nclass Base {\n\n// The type \"this\" can only be used as a return type, to instantiate a covariant type variable,\n// or as a private non-static member variable\n\n  private ?this $pr1;\n/*\n  public function f1(this): void {\n  }\n*/\n  public function f2(): this {\n    return $this;\n  }\n\n//  public function __construct() {\n//    $this->pr1 = $this;\n//  }\n\n  private int $x = 0;\n\n//  public function setX(int $new_x): Base {\n  public function setX(int $new_x): this {\n    $this->x = $new_x;\n    // $this has type \"this\"\nvar_dump($this);\n    return $this;\n  }\n\n/*\n//  public static function newInstance(): Base {\n  public static function newInstance(): this {\n    // new static() has type \"this\"\n    return new static();\n  }\n*/\n\n/*\n//  public function newCopy(): Base {\n  public function newCopy(): this {\n    // This would not type check with self::, but static:: is ok\n    return static::newInstance();\n  }\n*/\n/*\n  // You can also say Awaitable<this>;\n  public async function genThis(): \\Awaitable<this> {\n    return $this;\n  }\n*/\n}\n\nclass Derived extends Base {}\n\nfinal class Child {\n  public function newChild(): this {\n    // This is OK because Child is final.\n    // However, if Grandchild extends Child, then this would be wrong, since\n    // $grandchild->newChild() should returns a Child instead of a Grandchild\n    return new Child();\n  }\n}\n\nfunction main(): void {\n  $b1 = new Base();\n  $obj = $b1->setX(10);\n  var_dump($obj);\n\n  $d1 = new Derived();\n  $obj = $d1->setX(20);\n  var_dump($obj);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Functions/this_play.php.expect",
    "content": "object(NS_this_play\\Base)#1 (2) {\n  [\"pr1\":\"NS_this_play\\Base\":private]=>\n  NULL\n  [\"x\":\"NS_this_play\\Base\":private]=>\n  int(10)\n}\nobject(NS_this_play\\Base)#1 (2) {\n  [\"pr1\":\"NS_this_play\\Base\":private]=>\n  NULL\n  [\"x\":\"NS_this_play\\Base\":private]=>\n  int(10)\n}\nobject(NS_this_play\\Derived)#2 (2) {\n  [\"pr1\":\"NS_this_play\\Base\":private]=>\n  NULL\n  [\"x\":\"NS_this_play\\Base\":private]=>\n  int(20)\n}\nobject(NS_this_play\\Derived)#2 (2) {\n  [\"pr1\":\"NS_this_play\\Base\":private]=>\n  NULL\n  [\"x\":\"NS_this_play\\Base\":private]=>\n  int(20)\n}"
  },
  {
    "path": "tests/Functions/variable_functions.php",
    "content": "<?hh // strict\n\nnamespace NS_variable_functions;\n\nrequire_once('TestInc.php');\t// get access to \\NS\\TestInc\\f2()\n\nfunction f1(): void {\n  echo \"Inside function \" . __FUNCTION__ . \"\\n\";\n}\n\nfunction main(): void {\n  f1();\n//  namespace\\f1();\t\t// PHP allows this; Hack does not\n\n  $v = fun('\\NS_variable_functions\\f1');\n  $v();\n\n  $v = fun('\\NS_TestInc\\f2');\n  $v();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Functions/variable_functions.php.expect",
    "content": "Inside function NS_variable_functions\\f1\nInside function NS_variable_functions\\f1\nInside function NS_TestInc\\f2"
  },
  {
    "path": "tests/Generics/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Generics/Complex.php",
    "content": "<?hh // strict\n\nnamespace NS_Complex;\n\nclass Complex<T as num> {\n  private T $real;\n  private T $imag;\n\n  public function __construct(T $real, T $imag) {\n    $this->real = $real;\n    $this->imag = $imag;\n  }\n\n  public function getReal(): T {\n    return $this->real;\n  }\n\n  public function setReal(T $real): void {\n    $this->real = $real;\n  }\n\n  public function getImag(): T {\n    return $this->imag;\n  }\n\n  public function setImag(T $imag): void {\n    $this->imag = $imag;\n  }\n\n  public static function add(Complex<T> $z1, Complex<T> $z2): Complex<T> {\n    return new Complex($z1->real + $z2->real, $z1->imag + $z2->imag);\n  }\n\n  public static function subtract(Complex<T> $z1, Complex<T> $z2): Complex<T> {\n    return new Complex($z1->real - $z2->real, $z1->imag - $z2->imag);\n  }\n\n  public function __toString(): string {\n    if ($this->imag < 0.0) {                                                       \n      return \"(\" . $this->real . \" - \" . (-$this->imag) . \"i)\";\n    } else if (1.0/$this->imag == -INF) {\n      return \"(\" . $this->real . \" + \" . 0.0 . \"i)\";\n    } else {\n      return \"(\" . $this->real . \" + \" . (+$this->imag) . \"i)\";\n    }\n  }\n}\n"
  },
  {
    "path": "tests/Generics/Complex.php.expect",
    "content": ""
  },
  {
    "path": "tests/Generics/Complex_test.php",
    "content": "<?hh // strict\n\nnamespace NS_Complex_test;\n\nrequire_once 'Complex.php';\n\nfunction main(): void {\n  echo \"================== Complex<float> ===================\\n\\n\";\n\n  $c1 = new \\NS_Complex\\Complex(10.5, 5.67);\n  echo \"\\$c1 = \" . $c1 . \"\\n\";\n\n  $c2 = new \\NS_Complex\\Complex(-10.98, -123.45);\n  echo \"\\$c2 = \" . $c2 . \"\\n\";\n\n  echo \"\\$c1 + \\$c2 = \" . \\NS_Complex\\Complex::add($c1, $c2) . \"\\n\";\n  echo \"\\$c1 - \\$c2 = \" . \\NS_Complex\\Complex::subtract($c1, $c2) . \"\\n\";\n\n  echo \"\\n================== Complex<int> ===================\\n\\n\";\n\n  $c3 = new \\NS_Complex\\Complex(5, 6);\n  echo \"\\$c3 = \" . $c3 . \"\\n\";\n\n  $c4 = new \\NS_Complex\\Complex(-10, -12);\n  echo \"\\$c4 = \" . $c4 . \"\\n\";\n\n  echo \"\\$c3 + \\$c4 = \" . \\NS_Complex\\Complex::add($c3, $c4) . \"\\n\";\n  echo \"\\$c3 - \\$c4 = \" . \\NS_Complex\\Complex::subtract($c3, $c4) . \"\\n\";\n\n  echo \"\\n================== Complex<num> ===================\\n\\n\";\n\n  $c5 = new \\NS_Complex\\Complex(9, 5.4);\n  echo \"\\$c5 = \" . $c5 . \"\\n\";\n\n  $c6 = new \\NS_Complex\\Complex(12.2, -20);\n  echo \"\\$c6 = \" . $c6 . \"\\n\";\n\n  echo \"\\$c5 + \\$c6 = \" . \\NS_Complex\\Complex::add($c5, $c6) . \"\\n\";\n  echo \"\\$c5 - \\$c6 = \" . \\NS_Complex\\Complex::subtract($c5, $c6) . \"\\n\";\n\n  var_dump($c5, $c6, \\NS_Complex\\Complex::add($c5, $c6), \\NS_Complex\\Complex::subtract($c5, $c6));\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();"
  },
  {
    "path": "tests/Generics/Complex_test.php.expect",
    "content": "================== Complex<float> ===================\n\n$c1 = (10.5 + 5.67i)\n$c2 = (-10.98 - 123.45i)\n$c1 + $c2 = (-0.48 - 117.78i)\n$c1 - $c2 = (21.48 + 129.12i)\n\n================== Complex<int> ===================\n\n$c3 = (5 + 6i)\n$c4 = (-10 - 12i)\n$c3 + $c4 = (-5 - 6i)\n$c3 - $c4 = (15 + 18i)\n\n================== Complex<num> ===================\n\n$c5 = (9 + 5.4i)\n$c6 = (12.2 - 20i)\n$c5 + $c6 = (21.2 - 14.6i)\n$c5 - $c6 = (-3.2 + 25.4i)\nobject(NS_Complex\\Complex)#5 (2) {\n  [\"real\":\"NS_Complex\\Complex\":private]=>\n  int(9)\n  [\"imag\":\"NS_Complex\\Complex\":private]=>\n  float(5.4)\n}\nobject(NS_Complex\\Complex)#6 (2) {\n  [\"real\":\"NS_Complex\\Complex\":private]=>\n  float(12.2)\n  [\"imag\":\"NS_Complex\\Complex\":private]=>\n  int(-20)\n}\nobject(NS_Complex\\Complex)#7 (2) {\n  [\"real\":\"NS_Complex\\Complex\":private]=>\n  float(21.2)\n  [\"imag\":\"NS_Complex\\Complex\":private]=>\n  float(-14.6)\n}\nobject(NS_Complex\\Complex)#8 (2) {\n  [\"real\":\"NS_Complex\\Complex\":private]=>\n  float(-3.2)\n  [\"imag\":\"NS_Complex\\Complex\":private]=>\n  float(25.4)\n}"
  },
  {
    "path": "tests/Generics/Interface_Support.php",
    "content": "<?hh // strict\n\nnamespace NS_test;\n\nfunction main (): void\n{\n  echo \"------- Container -------\\n\\n\";\n\n  echo (Vector {1, 2} instanceof Container ?\n    \"V is\" : \"V is not\") . \" a Container\\n\";\n  echo (ImmVector {1, 2} instanceof Container ?\n    \"IV is\" : \"IV is not\") . \" a Container\\n\";\n  echo (Map {'x' => -1, 'a' => -4} instanceof Container ?\n    \"M is\" : \"M is **NOT**\") . \" a Container\\n\";\n  echo (ImmMap {'x' => -1, 'a' => -4} instanceof Container ?\n    \"IM is\" : \"IM is **NOT**\") . \" a Container\\n\";\n  echo (Set {1, 3, 5} instanceof Container ?\n    \"S is\" : \"S is **NOT**\") . \" a Container\\n\";\n  echo (ImmSet {1, 3, 5} instanceof Container ?\n    \"IS is\" : \"IS is **NOT**\") . \" a Container\\n\";\n  echo (Pair {1, 'abc'} instanceof Container ?\n    \"P is\" : \"P is **NOT**\") . \" a Container\\n\";\n  echo (array(1,3) instanceof Container ?\n    \"A is\" : \"A is **NOT**\") . \" a Container\\n\";\n\n  echo \"\\n------- KeyedContainer -------\\n\\n\";\n\n  echo (Vector {1, 2} instanceof KeyedContainer ?\n    \"V is\" : \"V is **NOT**\") . \" a KeyedContainer\\n\";\n  echo (ImmVector {1, 2} instanceof KeyedContainer ?\n    \"IV is\" : \"IV is **NOT**\") . \" a KeyedContainer\\n\";\n  echo (Map {'x' => -1, 'a' => -4} instanceof KeyedContainer ?\n    \"M is\" : \"M is **NOT**\") . \" a KeyedContainer\\n\";\n  echo (ImmMap {'x' => -1, 'a' => -4} instanceof KeyedContainer ?\n    \"IM is\" : \"IM is **NOT**\") . \" a KeyedContainer\\n\";\n  echo (Set {1, 3, 5} instanceof KeyedContainer ?\n    \"S is\" : \"S is **NOT**\") . \" a KeyedContainer\\n\";\n  echo (ImmSet {1, 3, 5} instanceof KeyedContainer ?\n    \"IS is\" : \"IS is **NOT**\") . \" a KeyedContainer\\n\";\n  echo (Pair {1, 'abc'} instanceof KeyedContainer ?\n    \"P is\" : \"P is **NOT**\") . \" a KeyedContainer\\n\";\n  echo (array(1,3) instanceof KeyedContainer ?\n    \"A is\" : \"A is **NOT**\") . \" a KeyedContainer\\n\";\n\n  echo \"------- Traversable -------\\n\\n\";\n\n  echo (Vector {1, 2} instanceof Traversable ?\n    \"V is\" : \"V is not\") . \" a Traversable\\n\";\n  echo (ImmVector {1, 2} instanceof Traversable ?\n    \"IV is\" : \"IV is not\") . \" a Traversable\\n\";\n  echo (Map {'x' => -1, 'a' => -4} instanceof Traversable ?\n    \"M is\" : \"M is **NOT**\") . \" a Traversable\\n\";\n  echo (ImmMap {'x' => -1, 'a' => -4} instanceof Traversable ?\n    \"IM is\" : \"IM is **NOT**\") . \" a Traversable\\n\";\n  echo (Set {1, 3, 5} instanceof Traversable ?\n    \"S is\" : \"S is **NOT**\") . \" a Traversable\\n\";\n  echo (ImmSet {1, 3, 5} instanceof Traversable ?\n    \"IS is\" : \"IS is **NOT**\") . \" a Traversable\\n\";\n  echo (Pair {1, 'abc'} instanceof Traversable ?\n    \"P is\" : \"P is **NOT**\") . \" a Traversable\\n\";\n  echo (array(1,3) instanceof Traversable ?\n    \"A is\" : \"A is **NOT**\") . \" a Traversable\\n\";\n\n  echo \"\\n------- KeyedTraversable -------\\n\\n\";\n\n  echo (Vector {1, 2} instanceof KeyedTraversable ?\n     \"V is\" : \"V is **NOT**\") . \" a KeyedTraversable\\n\";\n  echo (ImmVector {1, 2} instanceof KeyedTraversable ?\n     \"IV is\" : \"IV is **NOT**\") . \" a KeyedTraversable\\n\";\n  echo (Map {'x' => -1, 'a' => -4} instanceof KeyedTraversable ?\n     \"M is\" : \"M is **NOT**\") . \" a KeyedTraversable\\n\";\n  echo (ImmMap {'x' => -1, 'a' => -4} instanceof KeyedTraversable ?\n     \"IM is\" : \"IM is **NOT**\") . \" a KeyedTraversable\\n\";\n  echo (Set {1, 3, 5} instanceof KeyedTraversable ?\n     \"S is\" : \"S is **NOT**\") . \" a KeyedTraversable\\n\";\n  echo (ImmSet {1, 3, 5} instanceof KeyedTraversable ?\n     \"IS is\" : \"IS is **NOT**\") . \" a KeyedTraversable\\n\";\n  echo (Pair {1, 'abc'} instanceof KeyedTraversable ?\n     \"P is\" : \"P is **NOT**\") . \" a KeyedTraversable\\n\";\n  echo (array(1,3) instanceof KeyedTraversable ?\n     \"A is\" : \"A is **NOT**\") . \" a KeyedTraversable\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Generics/Interface_Support.php.expect",
    "content": "------- Container -------\n\nV is a Container\nIV is a Container\nM is a Container\nIM is a Container\nS is a Container\nIS is a Container\nP is a Container\nA is a Container\n\n------- KeyedContainer -------\n\nV is a KeyedContainer\nIV is a KeyedContainer\nM is a KeyedContainer\nIM is a KeyedContainer\nS is **NOT** a KeyedContainer\nIS is **NOT** a KeyedContainer\nP is a KeyedContainer\nA is a KeyedContainer\n------- Traversable -------\n\nV is a Traversable\nIV is a Traversable\nM is a Traversable\nIM is a Traversable\nS is a Traversable\nIS is a Traversable\nP is a Traversable\nA is a Traversable\n\n------- KeyedTraversable -------\n\nV is a KeyedTraversable\nIV is a KeyedTraversable\nM is a KeyedTraversable\nIM is a KeyedTraversable\nS is a KeyedTraversable\nIS is a KeyedTraversable\nP is a KeyedTraversable\nA is a KeyedTraversable"
  },
  {
    "path": "tests/Generics/MyVector.php",
    "content": "<?hh // strict\n\nnamespace NS_MyVector;\n\nclass MyVector<T> {\n  private int $length;\n  private array<T> $vector;\n\n  public function getLength(): int {\n    return $this->length;\n  }\n\n  private function setLength(int $newLength): void {\n    $this->length = $newLength;\n  }\n\n  public function getElement(int $index): T {\n    // bounds checking omitted\n    return $this->vector[$index];\n  }\n\n  public function setElement(int $index, T $newValue): void {\n    // bounds checking omitted\n\n    $this->vector[$index] = $newValue;\n  }\n\n  public function __construct(int $vectorLength, T $initValue) {\n    $this->length = $vectorLength;\n    $this->vector = array();\n    for ($i = 0; $i < $this->length; ++$i) {\n      $this->vector[] = $initValue;\n    }\n  }\n\n  public function __toString(): string {\n    $s = '[';\n    for ($i = 0; $i < $this->length - 1; ++$i) {\n      $s .= (string)$this->vector[$i] . ':';\n    }\n    $s .= (string)$this->vector[$i] . ']';\n    return $s;\n  }\n}\n"
  },
  {
    "path": "tests/Generics/MyVector.php.expect",
    "content": ""
  },
  {
    "path": "tests/Generics/MyVector_test.php",
    "content": "<?hh // strict\n\nnamespace NS_MyVector_test;\n\nrequire_once ('MyVector.php');\n\nfunction main(): void {\n  $iv1 = new \\NS_MyVector\\MyVector(7, 2);\n  echo \"\\$iv1: >>$iv1<<\\n\";\n\n  $iv1->setElement(1, 55);\n  $iv1->setElement(3, $iv1->getElement(3) - 17);\n  $iv1->setElement(5, $iv1->getElement(5) * 3);\n  echo \"\\$iv1: >>$iv1<<\\n\";\n\n  $sv1 = new \\NS_MyVector\\MyVector(5, 'X');\n  echo \"\\$sv1: >>$sv1<<\\n\";\n\n  $sv1->setElement(1, 'AB');\n  $sv1->setElement(3, $sv1->getElement(4) . 'ZZ');\n  echo \"\\$sv1: >>$sv1<<\\n\";\n\n  $viv = new \\NS_MyVector\\MyVector(3, new \\NS_MyVector\\MyVector(2, -1));\n  echo \"\\$viv: >>$viv<<\\n\";\n  $viv->setElement(0, new \\NS_MyVector\\MyVector(2, 1));\n  $viv->setElement(1, new \\NS_MyVector\\MyVector(4, 2));\n  $viv->setElement(2, new \\NS_MyVector\\MyVector(3, 5));\n  echo \"\\$viv: >>$viv<<\\n\";\n\n  $res = f($iv1, $sv1, $viv);\n  echo \"\\$res: >>$res<<\\n\";\n  echo \"\\$viv: >>$viv<<\\n\";\n}\n\nfunction f(\\NS_MyVector\\MyVector<int> $p1, \\NS_MyVector\\MyVector<string> $p2,\n  \\NS_MyVector\\MyVector<\\NS_MyVector\\MyVector<int>> $p3)\n  : \\NS_MyVector\\MyVector<\\NS_MyVector\\MyVector<int>> {\n  $p3->setElement(1, $p1);\n  return $p3;\n}\n\nclass Cx {\n  private ?\\NS_MyVector\\MyVector<int> $pr1;\n  private \\NS_MyVector\\MyVector<string> $pr2;\n  private \\NS_MyVector\\MyVector<\\NS_MyVector\\MyVector<int>> $pr3;\n  private \\NS_MyVector\\MyVector<?int> $pr4;\n  private ?\\NS_MyVector\\MyVector<?int> $pr5;\n\n  public function __construct() {\n    $this->pr2 = new \\NS_MyVector\\MyVector(3, '??');\n    $this->pr3 = new \\NS_MyVector\\MyVector(5, new \\NS_MyVector\\MyVector(3, 99));\n    $this->pr4 = new \\NS_MyVector\\MyVector(2, null);\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Generics/MyVector_test.php.expect",
    "content": "$iv1: >>[2:2:2:2:2:2:2]<<\n$iv1: >>[2:55:2:-15:2:6:2]<<\n$sv1: >>[X:X:X:X:X]<<\n$sv1: >>[X:AB:X:XZZ:X]<<\n$viv: >>[[-1:-1]:[-1:-1]:[-1:-1]]<<\n$viv: >>[[1:1]:[2:2:2:2]:[5:5:5]]<<\n$res: >>[[1:1]:[2:55:2:-15:2:6:2]:[5:5:5]]<<\n$viv: >>[[1:1]:[2:55:2:-15:2:6:2]:[5:5:5]]<<"
  },
  {
    "path": "tests/Generics/Stack.php",
    "content": "<?hh // strict\n\nnamespace NS_Stack;\n\nclass StackUnderflowException extends \\Exception {}\n\nclass Stack<T> {\n  private array<T> $stack;\n  private int $stackPtr;\n\n  public function __construct() {\n    $this->stackPtr = 0;\n    $this->stack = array();\n\n    echo \"Inside \" . __METHOD__ . \": stackPtr = \" . $this->stackPtr . \"\\n\";\n  }\n\n  public function __destruct() {\n    $this->stack = array();\n  }\n\n  public function push(T $value): void {\n    echo \"Inside \" . __METHOD__ . \": stackPtr = \" . $this->stackPtr . \"\\n\";\n\n    $this->stack[$this->stackPtr++] = $value;\n  }\n\n  public function pop(): T {\n    echo \"Inside \" . __METHOD__ . \": stackPtr = \" . $this->stackPtr . \"\\n\";\n\n    if ($this->stackPtr > 0) {\n      return $this->stack[--$this->stackPtr];\n    } else {\n      throw new StackUnderflowException();\n    }\n  }\n\n  public function getStackDepth(): int {\n    return $this->stackPtr;\n  }\n}\n"
  },
  {
    "path": "tests/Generics/Stack.php.expect",
    "content": ""
  },
  {
    "path": "tests/Generics/Stack_test.php",
    "content": "<?hh // strict\n\nnamespace NS_Stack_test;\n\nrequire_once ('Stack.php');\n\nfunction main2(\\NS_Stack\\Stack<int> $stInt, \\NS_Stack\\Stack<float> $stFloat): void {\n  $stInt->push(10);\n  $stInt->push(20);\n  $stInt->push(30);\n  echo 'pop => ' . $stInt->pop() . \"\\n\";\n//  $stInt->push(10.5);\t// type argument float is incompatible with type parameter int\n\n  $stFloat->push(10.12);\n  $stFloat->push(-4320.6);\n  echo 'pop => ' . $stFloat->pop() . \"\\n\";\n//  $stFloat->push(100);\t// type argument int is incompatible with type parameter float\n  echo 'pop => ' . $stFloat->pop() . \"\\n\";\n\n  echo 'pop => ' . $stInt->pop() . \"\\n\";\n  echo 'pop => ' . $stInt->pop() . \"\\n\";\n}\n\nfunction process(\\NS_Stack\\Stack<int> $p1): void {}\n//function process(\\NS_Stack\\Stack<float> $p1): void {}\n//function process(\\NS_Stack\\Stack<num> $p1): void {}\n//function process(\\NS_Stack\\Stack<mixed> $p1): void {}\n\nfunction main(): \\NS_Stack\\Stack<num> {\n  $stInt = new \\NS_Stack\\Stack();\n  $stInt->push(100);\n  echo 'pop => ' . $stInt->pop() . \"\\n\";\n\n  echo 'stack depth = ' . $stInt->getStackDepth() . \"\\n\";\n//  process($stInt);\t\t\t// fixes the type as Stack<int>\n\n// With the line above commented out\n// Pushing a float or string on an intended int stack is allowed; need to discuss this under \"type inferencing\"\n// It seems like, ultimately, the stack type really is Stack<Mixed>\n// With the call to processInt enabled, push(float) and push(string) are rejected as being incompatible\n\n  $stInt->push(10.5);\t\t// rejected once stack type is fixed\n  var_dump($stInt);\n  echo 'pop => ' . $stInt->pop() . \"\\n\";\n\n//  process($stInt);\t\t\t// locks in the type as Stack<num>\n\n  $stInt->push('abc');\t\t// rejected once stack type is fixed\n  var_dump($stInt);\n  echo 'pop => ' . $stInt->pop() . \"\\n\";\n\n//  process($stInt);\t\t\t// fixes the type as Stack<mixed>\n\n\n\n  $stInt = new \\NS_Stack\\Stack();\n  $stInt->push(100);\n  $stInt->push(10.5);\n  return $stInt;\t\t// fixes the type as Stack<num>\n}\n\n//main2(new \\NS_Stack\\Stack(), new \\NS_Stack\\Stack());\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Generics/Stack_test.php.expect",
    "content": "Inside NS_Stack\\Stack::__construct: stackPtr = 0\nInside NS_Stack\\Stack::push: stackPtr = 0\nInside NS_Stack\\Stack::pop: stackPtr = 1\npop => 100\nstack depth = 0\nInside NS_Stack\\Stack::push: stackPtr = 0\nobject(NS_Stack\\Stack)#1 (2) {\n  [\"stack\":\"NS_Stack\\Stack\":private]=>\n  array(1) {\n    [0]=>\n    float(10.5)\n  }\n  [\"stackPtr\":\"NS_Stack\\Stack\":private]=>\n  int(1)\n}\nInside NS_Stack\\Stack::pop: stackPtr = 1\npop => 10.5\nInside NS_Stack\\Stack::push: stackPtr = 0\nobject(NS_Stack\\Stack)#1 (2) {\n  [\"stack\":\"NS_Stack\\Stack\":private]=>\n  array(1) {\n    [0]=>\n    string(3) \"abc\"\n  }\n  [\"stackPtr\":\"NS_Stack\\Stack\":private]=>\n  int(1)\n}\nInside NS_Stack\\Stack::pop: stackPtr = 1\npop => abc\nInside NS_Stack\\Stack::__construct: stackPtr = 0\nInside NS_Stack\\Stack::push: stackPtr = 0\nInside NS_Stack\\Stack::push: stackPtr = 1"
  },
  {
    "path": "tests/Generics/constraints.php",
    "content": "<?hh // strict\n\nnamespace NS_generics_constraints;\n\nenum E1: int { C1 = 10; C2 = 20; }\nclass C {}\nclass CX extends C {}\ninterface I {}\nclass D1 implements I {}\nclass D2 implements I {}\ntype Point = shape('x' => int, 'y' => int);\n\nclass C1a<T as bool> { public function __construct(private T $p1) {} }\nclass C1b<T as int> {}\nclass C1c<T as float> {}\nclass C1d<T as num> {}\nclass C1e<T as string> {}\nclass C1f<T as arraykey> {}\nclass C1g<T as E1> {}\nclass C1h<T as array<int>> {}\nclass C1i<T as C> {}\nclass C1j<T as I> {}\nclass C1k<T as (int, bool, string)> {}\nclass C1l<T as Point> {}\nclass C1m<T as (function (): void)> {}\nclass C1n<T as ?int> {}\nclass C1o<T as ?string> {}\nclass C1p<T as array<int, int>> {}\n\nclass C2<T1 as I, T2 as C> {\n  public function __construct(T1 $p1, T2 $p2) {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n}\n\nfunction maxVal<T as num>(T $p1, T $p2): T {\n  return $p1 > $p2 ? $p1 : $p2;\n}\n\nfunction main(): void {\n  $c1a = new C1a(true);\t\t// OK\n  var_dump($c1a);\n  $c1a = new C1a(false);\t\t// OK\n  var_dump($c1a);\n//  $c1a = new C1a(123);\t\t// rejected; violates the constraint\n\n  $c2 = new C2(new D1(), new CX());\n  $c2 = new C2(new D2(), new C());\n\n  echo \"=============== maxVal ==================\\n\\n\";\n\n  echo \"maxVal(10, 20) = \" . maxVal(10, 20) . \"\\n\";\n  echo \"maxVal(15.6, -20.78) = \" . maxVal(15.6, -20.78) . \"\\n\";\n//  echo \"maxVal('red', 'green') = \" . maxVal('red', 'green') . \"\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Generics/constraints.php.expect",
    "content": "object(NS_generics_constraints\\C1a)#1 (1) {\n  [\"p1\":\"NS_generics_constraints\\C1a\":private]=>\n  bool(true)\n}\nobject(NS_generics_constraints\\C1a)#2 (1) {\n  [\"p1\":\"NS_generics_constraints\\C1a\":private]=>\n  bool(false)\n}\nInside NS_generics_constraints\\C2::__construct\nInside NS_generics_constraints\\C2::__construct\n=============== maxVal ==================\n\nmaxVal(10, 20) = 20\nmaxVal(15.6, -20.78) = 15.6"
  },
  {
    "path": "tests/Generics/contravariance_example.php",
    "content": "<?hh // strict\n\nnamespace NS_contravariance_example;\n\n/*\nclass Cx<T1, -T2, +T3> {\n  public function __construct(private T1 $t1, private T2 $t2, private T3 $t3) {}\n}\n*/\n\nclass C<-T> {\n  public function __construct(private T $t) {}\n}\n\nclass Animal {}\nclass Cat extends Animal {}\n\nfunction f(C<Cat> $p1): void { var_dump($p1); }\n\nfunction main(): void {\n  // UNSAFE (type error - this is not accepted)\n  f(new C(new Animal()));\t// accepted\n  // UNSAFE (type error - this is not accepted)\n  f(new C(new Cat()));\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Generics/contravariance_example.php.expect",
    "content": "object(NS_contravariance_example\\C)#1 (1) {\n  [\"t\":\"NS_contravariance_example\\C\":private]=>\n  object(NS_contravariance_example\\Animal)#2 (0) {\n  }\n}\nobject(NS_contravariance_example\\C)#1 (1) {\n  [\"t\":\"NS_contravariance_example\\C\":private]=>\n  object(NS_contravariance_example\\Cat)#2 (0) {\n  }\n}"
  },
  {
    "path": "tests/Generics/covariance_example.php",
    "content": "<?hh // strict\n\nnamespace NS_covariance_example;\n\n//class C<T> { // equivalent to the following line, as type parameters are covariant by default\nclass C<+T> {\n  public function __construct(private T $t) {}\n}\n\nclass Animal {}\nclass Cat extends Animal {}\n\nfunction f(C<Animal> $p1): void { var_dump($p1); }\n\nfunction g(array<Animal> $p1): void { var_dump($p1); }\n\nfunction main(): void {\n  f(new C(new Animal()));\n  f(new C(new Cat()));\t// accepted\n\n  g(array(new Animal(), new Animal()));\n  g(array(new Cat(), new Cat(), new Animal()));\t// arrays are covariant\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Generics/covariance_example.php.expect",
    "content": "object(NS_covariance_example\\C)#1 (1) {\n  [\"t\":\"NS_covariance_example\\C\":private]=>\n  object(NS_covariance_example\\Animal)#2 (0) {\n  }\n}\nobject(NS_covariance_example\\C)#1 (1) {\n  [\"t\":\"NS_covariance_example\\C\":private]=>\n  object(NS_covariance_example\\Cat)#2 (0) {\n  }\n}\narray(2) {\n  [0]=>\n  object(NS_covariance_example\\Animal)#1 (0) {\n  }\n  [1]=>\n  object(NS_covariance_example\\Animal)#2 (0) {\n  }\n}\narray(3) {\n  [0]=>\n  object(NS_covariance_example\\Cat)#2 (0) {\n  }\n  [1]=>\n  object(NS_covariance_example\\Cat)#3 (0) {\n  }\n  [2]=>\n  object(NS_covariance_example\\Animal)#4 (0) {\n  }\n}"
  },
  {
    "path": "tests/Generics/generic_function.php",
    "content": "<?hh // strict\n\nnamespace NS_generic_function;\n\n// ------------------------------------------\n\nfunction maxVal<T>(T $p1, T $p2): T {\n  return $p1 > $p2 ? $p1 : $p2;\n}\n\n// ------------------------------------------\n\n/*\nfunction swap<T>(T $p1, T $p2): void {\n//  $temp = new T(); // no can do! Generics can only be used in type hints since they are erased at runtime.\n}\n*/\n\n// ------------------------------------------\n\n// Won't work, as $dest is passed by value, not by reference\n\nfunction arrayCopy<T>(array<T> $dest, array<T> $source, int $count): void {\n  for ($i = 0; $i < $count; ++$i) {\n    $dest[$i] = $source[$i];\n  }\n}\n\n// ------------------------------------------\n\nclass Box<T> {\n  public T $value;\n\n  public function __construct(T $v) {\n    $this->value = $v;\n  }\n}\n\n// works, but have swapped boxed values, not the original variables themselves\n\nfunction swap<T>(Box<T> $a, Box<T> $b): void {\n  $temp = $a->value;\n  $a->value = $b->value;\n  $b->value = $temp;\n}\n\n// ------------------------------------------\n\nfunction main(): void {\n  echo \"=============== maxVal ==================\\n\\n\";\n\n  echo \"maxVal(10, 20) = \" . maxVal(10, 20) . \"\\n\";\n  echo \"maxVal(20, 10) = \" . maxVal(20, 10) . \"\\n\";\n  echo \"maxVal(10, 10) = \" . maxVal(10, 10) . \"\\n\";\n\n  echo \"maxVal(15.6, -20.78) = \" . maxVal(15.6, -20.78) . \"\\n\";\n\n  echo \"maxVal('red', 'green') = \" . maxVal('red', 'green') . \"\\n\";\n\n// all are accepted; hmm!\n\n  $res = maxVal(10, 20.5);\n  echo \"maxVal(10, 20.5) = \" . $res . \"\\n\";\n  var_dump($res);\n\n  $res = maxVal(20.5, 10);\n  echo \"maxVal(20.5, 10) = \" . $res . \"\\n\";\n  var_dump($res);\n\n  $res = maxVal(0, true);\n  echo \"maxVal(0, true) = \" . $res . \"\\n\";\n  var_dump($res);\t\t// type is bool\n\n  $res = maxVal(1, false);\n  echo \"maxVal(1, false) = \" . $res . \"\\n\";\n  var_dump($res);\t\t// type is int\n\n  echo \"\\n=============== arrayCopy ==================\\n\\n\";\n\n  $dest = array(0);\n  $source = array(10, 20, 30, 40);\n  arrayCopy($dest, $source, 2);\n  var_dump($dest);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Generics/generic_function.php.expect",
    "content": "=============== maxVal ==================\n\nmaxVal(10, 20) = 20\nmaxVal(20, 10) = 20\nmaxVal(10, 10) = 10\nmaxVal(15.6, -20.78) = 15.6\nmaxVal('red', 'green') = red\nmaxVal(10, 20.5) = 20.5\nfloat(20.5)\nmaxVal(20.5, 10) = 20.5\nfloat(20.5)\nmaxVal(0, true) = 1\nbool(true)\nmaxVal(1, false) = 1\nint(1)\n\n=============== arrayCopy ==================\n\narray(1) {\n  [0]=>\n  int(0)\n}"
  },
  {
    "path": "tests/Generics/generics.php",
    "content": "<?hh // strict\n\nnamespace T;\n\nfunction doit(): void { echo \"Hi from doit\\n\"; }\n\nnamespace NS_generics;\n\n// Type parameter names must be distinct within a given type parameter list\n\n// You cannot re-bind the type parameter T\n//class C1<T, T> {}\nclass C1<T1, T2> {}\n\n// You cannot re-bind the type parameter T\n//function f1<T, T>(): void {}\nfunction f1<T1, T2>(): void {}\n\n/*\nIf change any of the following 4 type names to start with T followed by a digit or upper/lowercase\nletter only, checker thinks it looks like a generic type parameter, and suggests, \"You probably forgot\nto bind this type parameter right? Add <TK> somewhere (after the function name definition, or after the class name)\n*/\n\nenum TE2: int { T = 10; B = 30; }\nclass TC2 {}\ninterface TI2 {}\ntype TT2 = int;\n\nclass X<T> {\n  const int T = 100;\t\t// OK; T not used in a type context\n  private ?array<TE2> $pr1;\n  private ?array<TC2> $pr2;\n  private ?array<TI2> $pr3;\n  private ?array<TT2> $pr4;\n\n  <<T>> public function T(): void { echo \"Hi from T\\n\"; }\t// OK; T as attribute and T as method\n\t\t\t\t\t\t\t\t// name not used in a type context\n\n  public function f(): void {\n    echo TE2::T . \"\\n\";\t// OK; T not used in a type context\n    \\T\\doit();\t\t// OK; T not used in a type context\n  }\n\n  // If a type parameter of g() is T, \"You cannot re-bind the type parameter T\"\n//  public function g<T>(): void { }\n//  public function g<Tx, T>(): void { }\n  public function g<Tx>(): void { echo \"Hi from g\\n\"; }\n}\n\ninterface Y<T> {\n  const int T = 100;\t\t\t// OK; T not used in a type context\n  <<T>> public function T(): void;\t// OK; T as attribute and T as method\n\t\t\t\t\t// name not used in a type context\n\n  // If a type parameter of g() is T, \"You cannot re-bind the type parameter T\"\n//  public function g<T>(): void;\n//  public function g<Tx, T>(): void;\n  public function g<Tx>(): void;\n}\n\ntrait Z<T> {\n  private ?array<TE2> $pr1;\n  private ?array<TC2> $pr2;\n  private ?array<TI2> $pr3;\n  private ?array<TT2> $pr4;\n\n  <<T>> public function T(): void { echo \"Hi from T\\n\"; }\t// OK; T as attribute and T as method\n\t\t\t\t\t\t\t\t// name not used in a type context\n\n  public function f(): void {\n    echo TE2::T . \"\\n\";\t// OK; T not used in a type context\n    \\T\\doit();\t\t// OK; T not used in a type context\n  }\n\n  // If a type parameter of g() is T, \"You cannot re-bind the type parameter T\"\n//  public function g<T>(): void { }\n//  public function g<Tx, T>(): void { }\n  public function g<Tx>(): void { echo \"Hi from g\\n\"; }\n}\n\nclass C2a {\n  public function __construct<T>() { echo \"In \" . __METHOD__ . \"\\n\"; }\n  public function __destruct<T>() { echo \"In \" . __METHOD__ . \"\\n\"; }\n}\n\nclass C2b<T2> {\n  public function __construct<T>() { echo \"In \" . __METHOD__ . \"\\n\"; }\n  public function __destruct<T>() { echo \"In \" . __METHOD__ . \"\\n\"; }\n}\n\nclass C2c<T2> {\n// You cannot re-bind the type parameter T2\n//  public function __construct<T2>() {}\n//  public function __destruct<T2>() {}\n}\n\nfunction main(): void {\n  $x = new X();\n//  var_dump($x);\n  var_dump(X::T);\n  $x->T();\n  $x->f();\n  $x->g();\n\n  $c2a = new C2a();\n  $c2b = new C2b();\n//  $c2b = new C2b<int>();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Generics/generics.php.expect",
    "content": "int(100)\nHi from T\n10\nHi from doit\nHi from g\nIn NS_generics\\C2a::__construct\nIn NS_generics\\C2b::__construct\nIn NS_generics\\C2b::__destruct\nIn NS_generics\\C2a::__destruct"
  },
  {
    "path": "tests/Interfaces/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Interfaces/MyCollection.php",
    "content": "<?hh // strict\n\nnamespace NS_MyCollectionClasses;\n\ninterface MyCollection<T> {\n  const int MAX_NUMBER_ITEMS = 1000;\n\n  public function put(T $item): void;\n  public function get(): T;\n}\n"
  },
  {
    "path": "tests/Interfaces/MyCollection.php.expect",
    "content": ""
  },
  {
    "path": "tests/Interfaces/MyList.php",
    "content": "<?hh // strict\n\nnamespace NS_MyCollectionClasses;\n\nrequire_once 'MyCollection.php';\n\nclass MyList<T> implements MyCollection<T> {\n  private array<T> $list = array();\n\n  public function put(T $item): void {\n    // ...\n  }\n\n  public function get(): T {\n    // ...\n    return $this->list[0];\n  }\n\t\n  // ...\n}\n"
  },
  {
    "path": "tests/Interfaces/MyList.php.expect",
    "content": ""
  },
  {
    "path": "tests/Interfaces/MyQueue.php",
    "content": "<?hh // strict\n\nnamespace NS_MyCollectionClasses;\n\nrequire_once 'MyCollection.php';\n\nclass MyQueue<T> implements MyCollection<T> {\n  private array<T> $list = array();\n\n  public function put(T $item): void {\n    // ...\n  }\n\n  public function get(): T {\n    // ...\n    return $this->list[0];\n  }\n\t\n  // ...\n}\n"
  },
  {
    "path": "tests/Interfaces/MyQueue.php.expect",
    "content": ""
  },
  {
    "path": "tests/Interfaces/interface_requirements.php",
    "content": "<?hh // strict\n\nnamespace NS_interface_requirements;\n\nclass C1 {\n  public function cf1(): void { }\n}\n\ninterface I1 {\n  require extends C1;\n  public function if1(): void;\n  require extends C1;\t\t// redundant but permitted\n}\n\nclass C2 extends C1 implements I1 {\n  public function if1(): void { }\n}\n"
  },
  {
    "path": "tests/Interfaces/interface_requirements.php.expect",
    "content": ""
  },
  {
    "path": "tests/Interfaces/interfaces.php",
    "content": "<?hh // strict\n\nnamespace NS_interfaces;\n\nrequire_once 'MyCollection.php';\nrequire_once 'MyList.php';\nrequire_once 'MyQueue.php';\n\nfunction processCollection<T>(\\NS_MyCollectionClasses\\MyCollection<T> $p1): void {\n  var_dump($p1);\n}\n\ninterface iX {\n  const int C1 = 123;\n//  const string C2 = \"green\";\n\n  public function f0(): void;\n//  public function f1(int $p1): void;\n//  private function f1(int $p1): void;\t// private not permitted\n//  protected function f1(int $p1): void;\t// protected not permitted\n  public static function f3(): void;\n}\n\ninterface iY {\n//  const int C1 = 123;\t\t// can't inherit duplicate constants even if defined identically\n  const string C2 = \"green\";\n\n//  public function f0(int $p1): void;\t// Declaration of iX::f0() must be compatible with iY::f0($p1)\n  public function f1(int $p1): void;\n  public function f2(int $p1, int $p2): void;\n}\n\ninterface iZ extends iX, iY {\n//  const int C1 = 123;\t\t// can't override inherited constants\n//  const string C2 = \"green\";\t// can't override inherited constants\n\n  public function f2(int $p1, int $p2): void;\n}\n\nabstract class C implements iZ {} // being abstract, it need not implement any of the methods\n\nclass D implements iZ {\n//  public function f0(int $p1): void {} // Declaration of D::f0() must be compatible with iX::f0()\n  public function f0(): void {}\n  public function f1(int $p1): void {}\n  public function f2(int $p1, int $p2): void {}\n  public static function f3(): void {}\n}\n\nfunction main(): void {\n  var_dump(D::C1);\n  var_dump(D::C2);\n\n  echo \"------------------------------------\\n\";\n\n  $list = new \\NS_MyCollectionClasses\\MyList();\n  processCollection($list);\n\n  $queue = new \\NS_MyCollectionClasses\\MyQueue();\n  processCollection($queue);\n\n  processCollection(new \\NS_MyCollectionClasses\\MyQueue());\n\n  var_dump(\\NS_MyCollectionClasses\\MyCollection::MAX_NUMBER_ITEMS);\n  var_dump(\\NS_MyCollectionClasses\\MyList::MAX_NUMBER_ITEMS);\n  var_dump(\\NS_MyCollectionClasses\\MyQueue::MAX_NUMBER_ITEMS);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Interfaces/interfaces.php.expect",
    "content": "int(123)\nstring(5) \"green\"\n------------------------------------\nobject(NS_MyCollectionClasses\\MyList)#1 (1) {\n  [\"list\":\"NS_MyCollectionClasses\\MyList\":private]=>\n  array(0) {\n  }\n}\nobject(NS_MyCollectionClasses\\MyQueue)#2 (1) {\n  [\"list\":\"NS_MyCollectionClasses\\MyQueue\":private]=>\n  array(0) {\n  }\n}\nobject(NS_MyCollectionClasses\\MyQueue)#3 (1) {\n  [\"list\":\"NS_MyCollectionClasses\\MyQueue\":private]=>\n  array(0) {\n  }\n}\nint(1000)\nint(1000)\nint(1000)"
  },
  {
    "path": "tests/Interfaces/qq.php",
    "content": "<?hh // strict\n\nnamespace NS_interface_requirements_2;\n\nabstract class Machine {\n  public function openDoors(): void {\n    return;\n  }\n  public function closeDoors(): void {\n    return;\n  }\n}\n\ninterface Fliers {\n  require extends Machine;\n  public function fly(): bool;\n}\n\nclass AirBus extends Machine implements Fliers {\n  public function takeOff(): bool {\n    $this->openDoors();\n    $this->closeDoors();\n    return $this->fly();\n  }\n\n  public function fly(): bool {\n    return true;\n  }\n}\n\n// Having this will not only cause a typechecker error, but also cause a fatal\n// error in HHVM since we did not meet the interface requirement (extending\n// Machine).\n\n/*class Paper implements Fliers {\n  public function fly(): bool {\n    return false;\n  }\n}\n*/\n\nfunction main(): void {\n  $ab = new AirBus();\n  var_dump($ab);\n  var_dump($ab->takeOff());\n  $p = new AirBus();\n  var_dump($p);\n  var_dump($p->takeOff());\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Interfaces/qq.php.expect",
    "content": "object(NS_interface_requirements_2\\AirBus)#1 (0) {\n}\nbool(true)\nobject(NS_interface_requirements_2\\AirBus)#2 (0) {\n}\nbool(true)"
  },
  {
    "path": "tests/Lexical_Structure/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Lexical_Structure/Tokens/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Lexical_Structure/Tokens/array_literals.php",
    "content": "<?hh // strict\n\nnamespace NS_array_literals;\n\nclass X {\n  private array<int> $prop10 = array();\n  private array<mixed> $prop11 = array(10, \"red\", true);\n  private array<string, mixed> $prop12 = array('a' => 10, 'r' => array(20,30));\n\n  private array<int> $prop20 = [];\n  private array<mixed> $prop21 = [10, \"red\", true];\n  private array<string, mixed> $prop22 = ['a' => 10, 'r' => [20,30]];\n}\n\nfunction main(): void {\n  $x = new X();\n  var_dump($x);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Lexical_Structure/Tokens/array_literals.php.expect",
    "content": "object(NS_array_literals\\X)#1 (6) {\n  [\"prop10\":\"NS_array_literals\\X\":private]=>\n  array(0) {\n  }\n  [\"prop11\":\"NS_array_literals\\X\":private]=>\n  array(3) {\n    [0]=>\n    int(10)\n    [1]=>\n    string(3) \"red\"\n    [2]=>\n    bool(true)\n  }\n  [\"prop12\":\"NS_array_literals\\X\":private]=>\n  array(2) {\n    [\"a\"]=>\n    int(10)\n    [\"r\"]=>\n    array(2) {\n      [0]=>\n      int(20)\n      [1]=>\n      int(30)\n    }\n  }\n  [\"prop20\":\"NS_array_literals\\X\":private]=>\n  array(0) {\n  }\n  [\"prop21\":\"NS_array_literals\\X\":private]=>\n  array(3) {\n    [0]=>\n    int(10)\n    [1]=>\n    string(3) \"red\"\n    [2]=>\n    bool(true)\n  }\n  [\"prop22\":\"NS_array_literals\\X\":private]=>\n  array(2) {\n    [\"a\"]=>\n    int(10)\n    [\"r\"]=>\n    array(2) {\n      [0]=>\n      int(20)\n      [1]=>\n      int(30)\n    }\n  }\n}"
  },
  {
    "path": "tests/Lexical_Structure/Tokens/heredoc_string_literals.php",
    "content": "<?hh // strict\n\nnamespace NS_heredoc_string_literals;\n\nfunction main(): void {\n  $v = 123;\n\n// test using unescaped \", embedded (actual) tab, variable substitution, multiple lines\n\n $s = <<<\t  ID\nS'o'me \"\\\"t e\\txt; \\$v = $v\"\nSome more text\nID;\n echo \">$s<\\n\\n\";\n\n var_dump(<<<X\nX\n);\n\n  var_dump(<<<X\nxxx\nyyy\nX\n);\n\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Lexical_Structure/Tokens/heredoc_string_literals.php.expect",
    "content": ">S'o'me \"\\\"t e\txt; $v = 123\"\nSome more text<\n\nstring(0) \"\"\nstring(7) \"xxx\nyyy\""
  },
  {
    "path": "tests/Lexical_Structure/Tokens/integer_literals_edge_cases.php",
    "content": "<?hh // strict\n\nnamespace NS_integer_literals_edge_cases;\n\nfunction main(): void {\n  if ((1 << 31) < 0) {\n    var_dump(2147483648);\n    var_dump(-2147483648);\n    var_dump(-2147483647 - 1);\n    var_dump(0x80000000);\n    var_dump(020000000000);\n    var_dump(0b10000000000000000000000000000000);\n//             10987654321098765432109876543210\n//              3         2         1         0\n  } else {\n//    var_dump(9223372036854775808);\t// number too big\n//    var_dump(-9223372036854775808);\t// number too big\n    var_dump(-9223372036854775807 - 1);\n    var_dump(0x8000000000000000);\n    var_dump(01000000000000000000000);\n    var_dump(0b1000000000000000000000000000000000000000000000000000000000000000);\n//             3210987654321098765432109876543210987654321098765432109876543210\n//             6  6         5         4         3         2         1         0\n\n// HHVM-specific test\n\n//    var_dump(9223372036854775808);\t// number too big\n//    var_dump(9223372036854775809);\t// number too big\n//    var_dump(9223372036854775810);\t// number too big\n//    var_dump(9223372036854775808888);\t// number too big\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Lexical_Structure/Tokens/integer_literals_edge_cases.php.expect",
    "content": "int(-9223372036854775808)\nint(9223372036854775807)\nint(9223372036854775807)\nint(9223372036854775807)"
  },
  {
    "path": "tests/Lexical_Structure/Tokens/name_case_sensitivity.php",
    "content": "<?hh // strict\n\nnamespace NS_name_case_sensitivity;\n\nfunction F(): void {}\n//function f(): void {}\t// name spelling differs only in capitalization\n\nclass C {\n\tpublic function F(): void {}\n\tpublic function f(): void {}\n}\n//class c {}\t\t// not permitted\n\ninterface I {}\n//interface i {}\t// not permitted\n\ntrait T {}\n//trait t {}\t\t// not permitted\n\nenum E: int {}\n//enum e: int {}\t// not permitted\n\ntype T1 = int;\n//type t1 = float;\t// not permitted\n\nnewtype NT1 = int;\n//newtype NT1 = float;\t// not permitted\n\nfunction main(): void {\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Lexical_Structure/Tokens/name_case_sensitivity.php.expectf",
    "content": "\nFatal error: Redeclared method NS_name_case_sensitivity\\C::F in %s/tests/Lexical_Structure/Tokens/name_case_sensitivity.php on line 9"
  },
  {
    "path": "tests/Lexical_Structure/Tokens/names.php",
    "content": "<?hh // strict\n\nnamespace NS_names;\n\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2015-2016 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\n/* test whether keywords are context-sensitive, thus allowing them to be used as names. */\n\n//class abstract {}\t// runtime error\n//class arraykey {} // name is reserved\n//class as {}\t\t// runtime error\n//class async {}\t// runtime error\n//class bool {}\t// name is reserved\n//class break {}\t// runtime error\n//class case {}\t\t// runtime error\n//class catch {}\t// runtime error\n//class class {}\t// runtime error\n//class clone {}\t// runtime error   \n//class const {}\t// runtime error\n//class continue {}\t// runtime error\n//class default {}\t// runtime error\n//class do {}\t\t// runtime error\n//class echo {}\t\t// runtime error\n//class else {}\t\t// runtime error\n//class elseif {}\t// runtime error   \nclass enum {}   \n//class extends {}\t// runtime error\n//class final {}\t// runtime error\n//class finally {}\t// runtime error\n//class float {} // name is reserved\n//class for {}\t\t// runtime error\n//class foreach {}\t// runtime error\n//class function {}\t// runtime error\n//class if {}\t\t// runtime error\n//class implements {}\t// runtime error\n//class instanceof {}\t// runtime error\n//class insteadof {}\t// runtime error\n//class int {}\t// name is reserved\n//class interface {}\t// runtime error\n//class mixed {} // name is reserved\n//class namespace {}\t// runtime error\n//class new {}\t\t// runtime error\nclass newtype {}\n//class num {}\t// name is reserved\n//class private {}\t// runtime error\n//class protected {}\t// runtime error\n//class public {}\t// runtime error\n//class require {}\t// runtime error\n//class require_once {}\t// runtime error\n//class return {}\t// runtime error\n//class shape {}\t// runtime error; finds a T_SHAPE\n//class static {}\t// runtime error\n//class string {} // name is reserved\n//class switch {}\t// runtime error\n//class throw {}\t// runtime error\n//class trait {}\t// runtime error\n//class try {}\t\t// runtime error\nclass tuple {}\nclass type {}\n//class use {}\t\t// runtime error\n//class void {}\t// name is reserved\n//class while {}\t// runtime error\n//class yield {}\t// runtime error\n\n//class array {} // name is reserved\n\nclass null {}\nclass true {}\nclass false {}\n\n//function abstract(): void {}\t// runtime error\nfunction arraykey(): void {}\n//function as(): void {}\t// runtime error\nfunction async(): void {}\nfunction bool(): void {}\n//function break(): void {}\t// runtime error\n//function case(): void {}\t// runtime error\n//function catch(): void {}\t// runtime error\n//function class(): void {}\t// runtime error\n//function clone(): void {}\t// runtime error   \n//function const(): void {}\t// runtime error\n//function continue(): void {}\t// runtime error\n//function default(): void {}\t// runtime error\n//function do(): void {}\t// runtime error\n//function echo(): void {}\t// runtime error\n//function else(): void {}\t// runtime error\n//function elseif(): void {}\t// runtime error   \nfunction enum(): void {}   \n//function extends(): void {}\t// runtime error\n//function final(): void {}\t// runtime error\n//function finally(): void {}\t// runtime error\nfunction float(): void {}\n//function for(): void {}\t// runtime error\n//function foreach(): void {}\t// runtime error\n//function function(): void {}\t// runtime error\n//function if(): void {}\t// runtime error\n//function implements(): void {}\t// runtime error\n//function instanceof(): void {}\t// runtime error\n//function insteadof(): void {}\t// runtime error\nfunction int(): void {}\n//function interface(): void {}\t// runtime error\nfunction mixed(): void {}\n//function namespace(): void {}\t// runtime error\n//function new(): void {}\t// runtime error\nfunction newtype(): void {}\nfunction num(): void {}\n//function private(): void {}\t// runtime error\n//function protected(): void {}\t// runtime error\n//function public(): void {}\t// runtime error\n//function require(): void {}\t// runtime error\n//function require_once(): void {}\t// runtime error\n//function return(): void {}\t// runtime error\n//function shape(): void {}\t// runtime error; finds a T_SHAPE (not a T_ARRAY, like tuple)\n//function static(): void {}\t// runtime error\nfunction string(): void {}\n//function switch(): void {}\t// runtime error\n//function throw(): void {}\t// runtime error\n//function trait(): void {}\t// runtime error\n//function try(): void {}\t// runtime error\n//function tuple(): void {}\t// runtime error; under the hood, a tuple is an array, hence T_ARRAY\nfunction type(): void {}\n//function use(): void {}\t// runtime error\nfunction void(): void {}\n//function while(): void {}\t// runtime error\n//function yield(): void {}\t// runtime error\n\n//function array(): void {}\t// runtime error\n\nfunction null(): void {}\nfunction true(): void {}\nfunction false(): void {}\n\nclass C1 {\n  public function abstract(): void {}\n  public function arraykey(): void {}\n  public function as(): void {}\n  public function async(): void {}\n  public function bool(): void {}\n  public function break(): void {}\n  public function case(): void {}\n  public function catch(): void {}\n  public function class(): void {}\n  public function clone(): void {}   \n  public function const(): void {}\n  public function continue(): void {}\n  public function default(): void {}\n  public function do(): void {}\n  public function echo(): void {}\n  public function else(): void {}\n  public function elseif(): void {}   \n  public function enum(): void {}   \n  public function extends(): void {}\n  public function final(): void {}\n  public function finally(): void {}\n  public function float(): void {}\n  public function for(): void {}\n  public function foreach(): void {}\n  public function function(): void {}\n  public function if(): void {}\n  public function implements(): void {}\n  public function instanceof(): void {}\n  public function insteadof(): void {}\n  public function int(): void {}\n  public function interface(): void {}\n  public function mixed(): void {}\n  public function namespace(): void {}\n  public function new(): void {}\n  public function newtype(): void {}\n  public function num(): void {}\n  public function private(): void {}\n  public function protected(): void {}\n  public function public(): void {}\n  public function require(): void {}\n  public function require_once(): void {}\n  public function return(): void {}\n//  public function shape(): void {}\t// runtime error; finds a T_SHAPE\n  public function static(): void {}\n  public function string(): void {}\n  public function switch(): void {}\n  public function throw(): void {}\n  public function trait(): void {}\n  public function try(): void {}\n  public function tuple(): void {}\n  public function type(): void {}\n  public function use(): void {}\n  public function void(): void {}\n  public function while(): void {}\n  public function yield(): void {}\n\n  public function array(): void {}\n\n  public function null(): void {}\n  public function true(): void {}\n  public function false(): void {}\n\n  const int abstract = 100;\n  const int arraykey = 100;\n  const int as = 100;\n  const int async = 100;\n  const int bool = 100;\n  const int break = 100;\n  const int case = 100;\n  const int catch = 100;\n//  const int class = 100;\t// runtime error; finds a T_CLASS\n  const int clone = 100;   \n  const int const = 100;\n  const int continue = 100;\n  const int default = 100;\n  const int do = 100;\n  const int echo = 100;\n  const int else = 100;\n  const int elseif = 100;   \n  const int enum = 100;   \n  const int extends = 100;\n  const int final = 100;\n  const int finally = 100;\n  const int float = 100;\n  const int for = 100;\n  const int foreach = 100;\n  const int function = 100;\n  const int if = 100;\n  const int implements = 100;\n  const int instanceof = 100;\n  const int insteadof = 100;\n  const int int = 100;\n  const int interface = 100;\n  const int mixed = 100;\n  const int namespace = 100;\n  const int new = 100;\n  const int newtype = 100;\n  const int num = 100;\n  const int private = 100;\n  const int protected = 100;\n  const int public = 100;\n  const int require = 100;\n  const int require_once = 100;\n  const int return = 100;\n//  const int shape = 100;\t// runtime error; finds a T_SHAPE\n  const int static = 100;\n  const int string = 100;\n  const int switch = 100;\n  const int throw = 100;\n  const int trait = 100;\n  const int try = 100;\n  const int tuple = 100;\n  const int type = 100;\n  const int use = 100;\n  const int void = 100;\n  const int while = 100;\n  const int yield = 100;\n\n  const int array = 100;\n\n  const int null = 100;\n  const int true = 100;\n  const int false = 100;\n}\n\nfunction main(): void {\n  new C1();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();"
  },
  {
    "path": "tests/Lexical_Structure/Tokens/names.php.expect",
    "content": ""
  },
  {
    "path": "tests/Lexical_Structure/Tokens/nowdoc_string_literals.php",
    "content": "<?hh // strict\n\nnamespace NS_nowdoc_string_literals;\n\nfunction main(): void {\n  $v = 123;\n\n// test using unescaped \", embedded (actual) tab, variable substitution, multiple lines\n\n  $s = <<<\t  'ID'\nS'o'me \"\\\"t e\\txt; \\$v = $v\"\nSome more text\nID;\n  echo \">$s<\\n\\n\";\n\n  var_dump(<<<'X'\nX\n);\n\n  var_dump(<<<'X'\nxxx\nyyy\nX\n);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Lexical_Structure/Tokens/nowdoc_string_literals.php.expect",
    "content": ">S'o'me \"\\\"t e\\txt; \\$v = $v\"\nSome more text<\n\nstring(0) \"\"\nstring(7) \"xxx\nyyy\""
  },
  {
    "path": "tests/Lexical_Structure/Tokens/string_literals.php",
    "content": "<?hh // strict\n\nnamespace NS_string_literals;\n\nclass C {\n  public int $p1 = 2;\n}\n\nfunction main(): void {\n  $x = 123;\n\n///*\n// single-quote string literals\n\n  var_dump('');\n  echo '>' . ' ' . \" <\\n\";\n  echo '>' . ' a B c ' . \"<\\n\";\n  echo '>' . '\\'.\\\".\\\\.\\$.\\eXXX.\\f.\\n.\\r.\\t.\\v.\\101.\\x41.\\X41.\\F.\\Q.\\S' . \"<\\n\";\n  echo '>\\$x.$x'.\"<\\n\";\n  echo '>xxx    // this comment-like thingy really is part of the string literal\nyyy\nzzz' . \"<\\n\";\n\n  echo var_dump('\\e');\t// Length should be 2\n//*/\n\n///*\n// double-quote string literals\n\n  var_dump(\"\");\n  echo '>' . \" \" . \"<\\n\";\n  echo '>' . \" a B c \" . \"<\\n\";\n  echo '>' . \"\\'.\\\".\\\\.\\$.\\eXXX.\\f.\\n.\\r.\\t.\\v.\\101.\\x41.\\X41.\\F.\\Q.\\S\" . \"<\\n\";\n  echo \">\\$x.$x\" . \"<\\n\";\n  echo \">xxx    // this comment-like thingy really is part of the string literal\nyyy\nzzz\".\"<\\n\";\n\n  echo var_dump(\"\\e\");\t// Length should be 1\n  echo var_dump(\"\\033\");\t// Length should be 1\n  echo var_dump(\"\\x1B\");\t// Length should be 1\n  echo var_dump(\"\\X1b\");\t// Length should be 1\n//*/\n\n///*\n// check all the scalar types for substitution\n\n  $a = 435;\t\t\tvar_dump(\"$a\");\n  $b = -12.34E23;\t\tvar_dump(\"$b\");\n  $c = false;\t\t\tvar_dump(\"$c\");\n  $d = true;\t\t\tvar_dump(\"$d\");\n  $e = null;\t\t\tvar_dump(\"$e\");\n  $f = \"blue sky\";\tvar_dump(\"$f\");\n  echo \">$a|$b|$c|$d|$e|$f<\\n\";\n\n//  $s = sprintf(\"%d|%G|%s|%s|%s|%s\", $a, $b, $c, $d, $e, $f);\n//  echo \">$s<\\n\";\n\n  $fpvalues = array(24.543567891234565, -2345e25, 6E-200, NAN, INF);\n  foreach ($fpvalues as $fpval) {\n    echo \">$fpval<--- o/p from string substition\\n\";\n//    $s = sprintf(\"%.14G\", $fpval);\n//    echo \">$s<--- using o/p from sprintf with hard-coded precision\\n\";\n//    $s = sprintf(\"%.*G\", 14, $fpval);\n//    echo \">$s<--- using o/p from sprintf with variable precision\\n\";\n  }\n\n  $fpval = NAN;\n  echo \">$fpval<--- o/p from string substition\\n\";\n  $s = sprintf(\"%.14F\", $fpval);\n  echo \">$s<--- using o/p from sprintf with hard-coded precision\\n\";\n//*/\n\n///*\n// show that the parser must form the longest possible variable name and that \n// for unknown variables a \"\" is substituted\n\n  $z = -34;\n  $zz = \"ABC\";\n  $zzz = true;\n  $zzzz = 567e12;\n  echo \">$z X|$zz _|$zzz 3|$zzzz +<\\n\";\n//  echo \">$zX|$z X|$zz_|$zz _|$zzz3|$zzz 3|$zzzz+|$zzzz +<\\n\";\n\n//  var_dump(\"$zX\");\n//  var_dump(\"$zz_\");\n//  var_dump(\"$zzz3\");\n//  var_dump(\"$zzzz+\");\n\n// $s not preceding a variable name are used verbatim\n  echo \">$1|$&<\\n\";\n//*/\n\n///*\n// use arrays and array elements\n\n  $colors = array(\"red\", \"white\", \"blue\");\n//  echo \"\\colors contains >$colors<\\n\";\n  echo \"\\colors[1] contains >$colors[1]<\\n\";\n//  echo \"\\colors[1] contains >$colors [1]<\\n\";\t\t// whitespace permitted, but semantics change\n//  echo \"\\colors[1] contains >$colors[ 1]<\\n\";\t// whitespace not permitted\n//  echo \"\\colors[1] contains >$colors[1 ]<\\n\";\t// whitespace not permitted\n  var_dump(\"$colors[1]\");\n//  var_dump(\"$colors[01]\");\t\t// invalid index\n//  var_dump(\"$colors[0x1]\");\t\t// invalid index\n//  var_dump(\"$colors[0X1]\");\t\t// invalid index\n\n  $index = 2;\n  echo \"\\$colors[$index] contains >$colors[$index]<\\n\";\n  $indices = array(2, 1, 0);\n//  echo \"\\colors[$indices[0]] contains >$colors[$indices[0]]<\\n\"; // the subscript cannot itself be\n\t\t// other than a simple variable\n//*/\n\n///*\n  $a1 = array(10,20);\n  $a2 = array(false,10.3,null);\n//  echo \">$a1|$a2<\\n\";\n\n// use class properties\n  $myC = new C();\n\n//  echo \"\\$myC = >$myC<\\n\";\t// can't use an object instance\n  echo \"\\$myC->p1 = >$myC->p1<\\n\";\n//  echo \"\\$myC ->p1 = >$myC ->p1<\\n\";\t// whitespace not permitted\n//  echo \"\\$myC-> p1 = >$myC-> p1<\\n\";\t// whitespace not permitted\n\n//  echo \"\\colors[$indices[$myC->p1]] contains >$colors[$indices[$myC->p1]]<\\n\"; // not permitted\n//*/\n\n///*\n// use brace-delimited expressions\n\n// braces can be used around varible names to stop a longer name being formed\n\n  $z = -34;\n  $zz = \"ABC\";\n  $zzz = true;\n  $zzzz = 567e12;\n  echo \">{$z}X|$z X|{$zz}_|$zz _|{$zzz}3|$zzz 3|{$zzzz}+|$zzzz +<\\n\";\n//*/\n\n///*\n// braces having no special meaning are used verbatim\n\n  echo \">{}|{q}|}|{<\\n\";\n\n  $a = 10;\n// checker balks at this\techo \">{$a  }<\\n\";\t\t// trailing white space is ignored\n///*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Lexical_Structure/Tokens/string_literals.php.expect",
    "content": "string(0) \"\"\n>  <\n> a B c <\n>'.\\\".\\.\\$.\\eXXX.\\f.\\n.\\r.\\t.\\v.\\101.\\x41.\\X41.\\F.\\Q.\\S<\n>\\$x.$x<\n>xxx    // this comment-like thingy really is part of the string literal\nyyy\nzzz<\nstring(2) \"\\e\"\nstring(0) \"\"\n> <\n> a B c <\n>\\'.\".\\.$.\u001bXXX.\f.\n.\r.\t.\u000b.A.A.A.\\F.\\Q.\\S<\n>$x.123<\n>xxx    // this comment-like thingy really is part of the string literal\nyyy\nzzz<\nstring(1) \"\u001b\"\nstring(1) \"\u001b\"\nstring(1) \"\u001b\"\nstring(1) \"\u001b\"\nstring(3) \"435\"\nstring(10) \"-1.234E+24\"\nstring(0) \"\"\nstring(1) \"1\"\nstring(0) \"\"\nstring(8) \"blue sky\"\n>435|-1.234E+24||1||blue sky<\n>24.543567891235<--- o/p from string substition\n>-2.345E+28<--- o/p from string substition\n>6.0E-200<--- o/p from string substition\n>NAN<--- o/p from string substition\n>INF<--- o/p from string substition\n>NAN<--- o/p from string substition\n>NaN<--- using o/p from sprintf with hard-coded precision\n>-34 X|ABC _|1 3|5.67E+14 +<\n>$1|$&<\n\\colors[1] contains >white<\nstring(5) \"white\"\n$colors[2] contains >blue<\n$myC->p1 = >2<\n>-34X|-34 X|ABC_|ABC _|13|1 3|5.67E+14+|5.67E+14 +<\n>{}|{q}|}|{<"
  },
  {
    "path": "tests/Lexical_Structure/Tokens/unicode_escape_sequences.php",
    "content": "<?hh // strict\n\nnamespace NS_unicode_escape_sequences;\n\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2015 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\n/* As of 2016-02-06, unicode escape sequences longer than 6 chars are rejected, even if their values are\nin-range, but just have extra leading zeros. This seems like a bug. */ \n\nfunction main(): void {\n  echo \"================= Basic checks =================\\n\\n\";\n\n  var_dump(\">\\u{41}<\");\t\t// results in \">A<\", length 3\n  var_dump(\">\\U{41}<\");\t\t// results in \">\\U{41}<\", length 8\n  var_dump(\">\\u{041}<\");\t\t// results in \">A<\", length 3\n  var_dump(\">\\u{0041}<\");\t\t// results in \">A<\", length 3\n  var_dump(\">\\u{00041}<\");\t\t// results in \">A<\", length 3\n  var_dump(\">\\u{000041}<\");\t\t// results in \">A<\", length 3\n//  var_dump(\">\\u{0000041}<\");\t\t// results in \">A<\", length 3\n//  var_dump(\">\\u{00000041}<\");\t\t// results in \">A<\", length 3\n//  var_dump(\">\\u{000000000000000000000041}<\");\t\t// results in \">A<\", length 3\n\n  var_dump(\">\\u{A9}<\");\t\t// results in \">©<\", length 4\n  var_dump(\">\\u{a9}<\");\t\t// results in \">©<\", length 4\n  var_dump(\">\\u{0000A9}<\");\t\t// results in \">©<\", length 4\n//  var_dump(\">\\u{00000000A9}<\");\t\t// results in \">©<\", length 4\n\n  var_dump(\">\\u{e6}<\");\t\t// results in \">æ<\", length 4\n\n  var_dump(\">\\u{2020}<\");\t\t// results in \">†<\", length 5\n\n  var_dump(\">\\u{20000}<\");\t\t// results in \">𠀀<\", length 6\n  var_dump(\">\\u{020000}<\");\t\t// results in \">𠀀<\", length 6\n//  var_dump(\">\\u{0020000}<\");\t\t// results in \">𠀀<\", length 6\n\n  var_dump(\">\\u{10FFFF}<\");\t\t// results in \">𠀀<\", length 6\n\n//  var_dump(\">\\u{110000}<\");\t\t// Invalid UTF-8 codepoint escape sequence: Codepoint too large (> 0x10FFFF)\n\n  echo \"\\n================= Is variable substitution allowed? =================\\n\\n\";\n\n  $v = \"41\";\n  var_dump(\">$v<\");\t\t\t\t// string(4) \">41<\"\n  var_dump(\">0$v<\");\t\t\t\t// string(5) \">041<\"\n  var_dump(\">0{$v}<\");\t\t\t// string(5) \">041<\"\n\n  var_dump(\">\\u{$v}<\");\t\t\t// string(6) \">\\u41<\"\n//  var_dump(\">\\u{0$v}<\");\t\t// Invalid UTF-8 codepoint escape sequence\n//  var_dump(\">\\u{{$v}}<\");\t\t// Invalid UTF-8 codepoint escape sequence\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Lexical_Structure/Tokens/unicode_escape_sequences.php.expect",
    "content": "================= Basic checks =================\n\nstring(3) \">A<\"\nstring(8) \">\\U{41}<\"\nstring(3) \">A<\"\nstring(3) \">A<\"\nstring(3) \">A<\"\nstring(3) \">A<\"\nstring(4) \">©<\"\nstring(4) \">©<\"\nstring(4) \">©<\"\nstring(4) \">æ<\"\nstring(5) \">†<\"\nstring(6) \">𠀀<\"\nstring(6) \">𠀀<\"\nstring(6) \">􏿿<\"\n\n================= Is variable substitution allowed? =================\n\nstring(4) \">41<\"\nstring(5) \">041<\"\nstring(5) \">041<\"\nstring(6) \">\\u41<\""
  },
  {
    "path": "tests/Lexical_Structure/comments.php",
    "content": "<?hh // strict\n\nnamespace NS_comments;\n\nfunction main(): void {\n/* this is a C-style comment\n...\n... \"#\"\" is just comment text\n... \"//\"\" is just comment text\n...\nthat runs for several whole lines */\n\n  $a = 100;\t// this is a C++-style comment, ... \"#\"\" is just comment text\n  $b = 12;\t# this is a Perl-style comment, ... \"//\"\" is just comment text\n\n  /*..*/$c/*..*/=/*..*/567/*..*/;/*..*/\t// some short C-style comments interspersed with tokens\n  var_dump($c);\n\n  $i = 2; $j = 3; $k = $i+++$j;\t# $i++ + $j\n  var_dump($k);\n  $i = 2; $j = 3; $k = $i++ +$j;\t# $i++ + $j\n  var_dump($k);\n  $i = 2; $j = 3; $k = $i+ ++$j;\t# $i + ++$j\n  var_dump($k);\n  $i = 2; $j = 3; $k = $i+ + +$j;\t# $i + + +$j; several unary +'s\n  var_dump($k);\n\n//  $i = 2; $j = 3; $k = $i++++$j;\t// correctly diagnosed; sees $i++ ++ +$j, which is invalid\n\n  $i = 2; $j = 3; $k = $i+++/*..*/++$j;\t// comment separates tokens like whitespace\n  var_dump($k);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Lexical_Structure/comments.php.expect",
    "content": "int(567)\nint(5)\nint(5)\nint(6)\nint(5)\nint(6)"
  },
  {
    "path": "tests/Lexical_Structure/keywords.php",
    "content": "<?hh // strict\n\nnamespace NS_keywords;\n\nfunction main(): void {\n  $colors = array(\"red\", \"white\", \"blue\");\n\n  foreach ($colors as $a) {\n    echo $a.' ';\n  }\n  echo \"\\n\";\n\n/* keywords must be lower-case\n\n// try various case combinations of keywords\n\n  fOREacH ($colors As $a) {\n    eChO $a.' ';\n  }\n  ECHO \"\\n\";\n*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Lexical_Structure/keywords.php.expect",
    "content": "red white blue "
  },
  {
    "path": "tests/Namespaces/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Namespaces/Circle.php",
    "content": "<?hh // strict\n\nnamespace Graphics\\D2\n{\n\nrequire_once('Point.php');\n\nclass Circle {\n  private Point $center;\n  private float $radius;\n\n  public function __construct(float $x = 0.0, float $y = 0.0, float $radius = 0.0) {\n    $this->center = new Point($x, $y);\n    $this->radius = $radius;\n  }\n\n  public function __toString(): string {\n    return '[' . $this->center . ':' . $this->radius . ']';\n  }\t\n}\n\n}\n"
  },
  {
    "path": "tests/Namespaces/Circle.php.expect",
    "content": ""
  },
  {
    "path": "tests/Namespaces/Point.php",
    "content": "<?hh // strict\n\nnamespace Graphics\\D2 {\n\nclass Point {\n  private float $x;\n  private float $y;\n\n  public function getX(): float\t \t{ return $this->x; }\n  public function setX(float $x): void\t{ $this->x = $x;   }\n  public function getY(): float\t\t{ return $this->y; }\n  public function setY(float $y): void\t{ $this->y = $y;   }\n\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    $this->x = $x;\n    $this->y = $y;\n  }\n\n  public function move(float $x, float $y): void {\n    $this->x = $x;\n    $this->y = $y;\n  }\t\n\n  public function translate(float $x, float $y): void {\n    $this->x += $x;\n    $this->y += $y;\n  }\n\n  public function __toString(): string {\n    return '(' . $this->x . ',' . $this->y . ')';\n  }\t\n}\n\n}\n"
  },
  {
    "path": "tests/Namespaces/Point.php.expect",
    "content": ""
  },
  {
    "path": "tests/Namespaces/namespaces1.php",
    "content": "<?hh // strict\n\nnamespace NS1;\t\t\t// define a level-1 namespace\n\nfunction f1(): void {\n  echo \"Inside function \" . __METHOD__. \", namespace \" . __NAMESPACE__ . \"\\n\";\n}\n\nnamespace NS1\\Sub1;\t\t// define a level-2 namespace that happens to have a level-1 prefix\n\nfunction f2(): void {\n  echo \"Inside function \" . __METHOD__. \", namespace \" . __NAMESPACE__ . \"\\n\";\n}\n\nnamespace NS2;\t\t\t// define a level-1 namespace\n\nfunction f3(): void {\n  echo \"Inside function \" . __METHOD__. \", namespace \" . __NAMESPACE__ . \"\\n\";\n}\n\nuse NS2;\n\nnamespace NS3\\Sub1;\t\t// define a level-2 namespace who's prefix is not an existing level-1 ns\n\nfunction f4(): void {\n  echo \"Inside function \" . __METHOD__. \", namespace \" . __NAMESPACE__ . \"\\n\";\n}\n\nclass C1 {\n  const CON = 123;\n\n  public function f(): void {\n    echo \"Inside function \" . __METHOD__. \", namespace \" . __NAMESPACE__ . \"\\n\";\n  }\n}\n\ninterface I1 {}\n\nfunction f5(): void {\n  echo \"Inside function \" . __METHOD__. \", namespace \" . __NAMESPACE__ . \"\\n\";\n  $c1 = new C1();\n  $c1->f();\n}\n\nfunction main(): void {\n  \\NS1\\f1();\n  \\NS1\\Sub1\\f2();\n  \\NS2\\f3();\n  \\NS3\\Sub1\\f4();\n  \\NS3\\Sub1\\f5();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Namespaces/namespaces1.php.expect",
    "content": "Inside function NS1\\f1, namespace NS1\nInside function NS1\\Sub1\\f2, namespace NS1\\Sub1\nInside function NS2\\f3, namespace NS2\nInside function NS3\\Sub1\\f4, namespace NS3\\Sub1\nInside function NS3\\Sub1\\f5, namespace NS3\\Sub1\nInside function NS3\\Sub1\\C1::f, namespace NS3\\Sub1"
  },
  {
    "path": "tests/Namespaces/namespaces2.php",
    "content": "<?hh // strict\n\nnamespace NS10 {\n  function f10(): void {\n    echo \"Inside namespace \" . __NAMESPACE__ . \"\\n\";\n    echo \"Inside function \" . __FUNCTION__ . \"\\n\";\n    echo \"Inside method \" . __METHOD__ . \"\\n\";\n  }\n}\n\nnamespace {\n  function f20(): void {\n    echo \"Inside namespace \" . __NAMESPACE__ . \"\\n\";\n    echo \"Inside function \" . __FUNCTION__ . \"\\n\";\n    echo \"Inside method \" . __METHOD__ . \"\\n\";\n  }\n}\n\nnamespace NS20 {\n  function f30(): void {\n    echo \"Inside namespace \" . __NAMESPACE__ . \"\\n\";\n    echo \"Inside function \" . __FUNCTION__ . \"\\n\";\n    echo \"Inside method \" . __METHOD__ . \"\\n\";\n  }\n}\n\nnamespace {\n  function main_namespaces2(): void {\n    \\NS10\\f10();\n    f20();\n    \\NS20\\f30();\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain_namespaces2();\n"
  },
  {
    "path": "tests/Namespaces/namespaces2.php.expectf",
    "content": "\nFatal error: No code may exist outside of namespace {}: (Line: 36, Char: 19) in %s/tests/Namespaces/namespaces2.php on line 36"
  },
  {
    "path": "tests/Namespaces/namespaces2_test.php",
    "content": "<?hh // strict\n\nnamespace NS_namespaces2_test;\n\nrequire_once \"namespaces2.php\";\n\nfunction main(): void {\n  \\NS10\\f10();\n  f20();\n  \\NS20\\f30();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();"
  },
  {
    "path": "tests/Namespaces/namespaces2_test.php.expectf",
    "content": "\nFatal error: No code may exist outside of namespace {}: (Line: 36, Char: 19) in %s/tests/Namespaces/namespaces2.php on line 36"
  },
  {
    "path": "tests/Namespaces/use_groups.php",
    "content": "// NOT YET IMPLEMENTED IN THE CHECKER <?hh // strict\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2015-2016 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\nnamespace NS_use_groups;\n\nrequire_once (\"use_groups_require_file.php\");\n\nclass CC implements I1 {};\n\nfunction main(): void {\n\n  echo \"================ class names =================\\n\\n\";\n\n  var_dump(new \\NS\\C1());\t// explicit qualification\n  use \\NS\\C1;\t\t\t// import C1\n  var_dump(new C1());\t\t// create a C1 without explicit qualification\n\n  use \\NS\\{C1 as C1B};\t\t// group of 1 allowed, but as name C1 already use'd, need to give it an alias\n  var_dump(new C1B());\t\t// create a C1/C1B without explicit qualification\n\n  use \\NS\\  {  C2, C3, I1 };\t// import C2, C3, and I1\n  var_dump(new C2());\t\t// create a C2 without explicit qualification\n  var_dump(new C3());\t\t// create a C3 without explicit qualification\n  var_dump(new CC());\n\n  echo \"\\n================ const names =================\\n\\n\";\n\n  var_dump(\\NS\\CON1);\t\t// explicit qualification\n  use const \\NS\\CON1;\t\t// import CON1\n  var_dump(CON1);\t\t// access CON1 without explicit qualification\n\n  echo \"\\n================ function names =================\\n\\n\";\n\n  \\NS\\f1();\t\t\t// explicit qualification\n  use function \\NS\\f1;\t\t// import f1\n  f1();\t\t\t\t// call f1 without explicit qualification\n\n  echo \"\\n================ class, const and function names =================\\n\\n\";\n\n  use \\NS\\ { C2 as CX, const CON2 as CZ, function f1 as FZ };\n  var_dump(new CX());\n  var_dump(CZ);\n  fZ();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Namespaces/use_groups.php.expectf",
    "content": "\nFatal error: HH mode: content before <?hh (Line: 1, Char: 38)\nsyntax error, unexpected T_HH_ERROR, expecting $end in %s/tests/Namespaces/use_groups.php on line 1"
  },
  {
    "path": "tests/Namespaces/use_groups_require_file.php",
    "content": "<?hh // strict\n\n/*\n   +-------------------------------------------------------------+\n   | Copyright (c) 2015-2016 Facebook, Inc. (http://www.facebook.com) |\n   +-------------------------------------------------------------+\n*/\n\nnamespace NS {\n\tclass C1 {}\n\tclass C2 {}\n\tclass C3 {}\n\tclass C4 {}\n\tclass C5 {}\n\tclass C6 {}\n\tclass C7 {}\n\tinterface I1 {}\n\n\tconst int CON1 = 10;\n\tconst bool CON2 = TRUE;\n\tconst float CON3 = 1.234;\n\n\tfunction f1(): void { echo \"Inside f1\\n\"; }\n\tfunction f2(): void { echo \"Inside f2\\n\"; }\n\tfunction f3(): void { echo \"Inside f3\\n\"; }\n}"
  },
  {
    "path": "tests/Namespaces/use_groups_require_file.php.expect",
    "content": ""
  },
  {
    "path": "tests/Namespaces/using_namespaces_1.php",
    "content": "<?hh // strict\n\nnamespace NS_using_namespaces1;\n\nrequire_once('Point.php');\nrequire_once('Circle.php');\n\nuse \\Graphics\\D2\\Point;\n//use \\Graphics\\D2\\Point as Point;\t\t// \"as Point\" is redundant\n\nuse \\Graphics\\D2\\Circle as Circle;\t\t// \"as Circle\" is redundant\n\nfunction main(): void {\n  $p1 = new \\Graphics\\D2\\Point(3.0, 5.0);\n  echo \"\\$p1 = $p1\\n\";\n  $p1 = new Point(-3.0, 8.0);\n  echo \"\\$p1 = $p1\\n\";\n\n  $c1 = new \\Graphics\\D2\\Circle(2.0, 4.0, 3.6);\n  echo \"\\$c1 = $c1\\n\";\n  $c2 = new Circle(1.0, -2.0, 1.4);\n  echo \"\\$c2 = $c2\\n\";\n\n//  use \\Graphics\\D2\\Point as P;\n//  $p1 = new P(-3.0, 8.0);\n//  echo \"\\$p1 = $p1\\n\";\n\n//  use \\Graphics\\D2\\Circle as C;\n//  $c2 = new C(1.0, -2.0, 1.4);\n//  echo \"\\$c2 = $c2\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Namespaces/using_namespaces_1.php.expect",
    "content": "$p1 = (3,5)\n$p1 = (-3,8)\n$c1 = [(2,4):3.6]\n$c2 = [(1,-2):1.4]"
  },
  {
    "path": "tests/Namespaces/using_namespaces_3.php",
    "content": "<?hh // strict\n\nnamespace NS17 {\n  const int CON1 = 100;\n\n  function f(): void {\n    echo \"In \" . __FUNCTION__ . \"\\n\";\n  }\n\n  class C {\n    const int C_CON = 200;\n    public function f(): void {\n      echo \"In \" . __NAMESPACE__ . \"...\" . __METHOD__ . \"\\n\";\n    }\n  }\n\n  interface I {\n    const int I_CON = 300;\n  }\n\n  trait T {\n    public function f(): void {\n      echo \"In \" . __TRAIT__ . \"...\" . __NAMESPACE__ . \"...\" . __METHOD__ . \"\\n\";\n    }\n  }\n}\n\nnamespace NS18 {\n  use \\NS17\\C, \\NS17\\I, \\NS17\\T;\n\n  class D extends C implements I {\n    use T;\n  }\n\n  function f(): void {\n    $d = new D();\n    var_dump($d);\n\n    echo \"CON1 = \" . \\NS17\\CON1 . \"\\n\";\n\n    \\NS17\\f();\n\n//  use \\NS17\\C as C2;\n//  $c2 = new C2();\n//  var_dump($c2);\n  }\n}\n"
  },
  {
    "path": "tests/Namespaces/using_namespaces_3.php.expect",
    "content": ""
  },
  {
    "path": "tests/Namespaces/using_namespaces_3_test.php",
    "content": "<?hh // strict\n\nnamespace NS_using_namespaces_3_test;\n\nrequire_once \"using_namespaces_3.php\";\n\nfunction main(): void {\n  \\NS18\\f();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Namespaces/using_namespaces_3_test.php.expect",
    "content": "object(NS18\\D)#1 (0) {\n}\nCON1 = 100\nIn NS17\\f"
  },
  {
    "path": "tests/Nullable_Types/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Nullable_Types/conversions.php",
    "content": "<?hh // strict\n\nnamespace NS_conversions_in_nullable_dir;\n\nclass Button {\n  private string $label;\n\n  public function __construct(string $label = '??') {\n      $this->label = $label;\n  }\n\n  public function __toString(): string {\n    return '[[Button: ' . $this->label . ']]';\n  }\n}\n\nclass CustomButton extends Button {\n  public function __construct(string $label = '??') {\n    parent::__construct($label);\n  }\n\n  public function __toString(): string {\n    return parent::__toString() . '[[CustomButton]]';\n  }\n}\n\ninterface MyCollection {}\n\nclass MyList implements MyCollection {\n  public function __toString(): string {\n    return '[[MyList]]';\n  }\n}\n\nclass MyQueue implements MyCollection {\n  public function __toString(): string {\n    return '[[MyQueue]]';\n  }\n}\n\nclass C1 {\n  private bool $pr_bool;\n  private int $pr_int;\n  private float $pr_float;\n  private num $pr_num;\n  private string $pr_string;\n  private resource $pr_resource;\n  private Button $pr_Button;\n  private CustomButton $pr_CustomButton;\n  private MyCollection $pr_MyCollection;\n\n  private ?bool $pr_nbool = null;\n  private ?int $pr_nint = null;\n  private ?float $pr_nfloat = null;\n  private ?num $pr_nnum = null;\n  private ?string $pr_nstring = null;\n  private ?resource $pr_nresource = null;\n  private ?Button $pr_nButton = null;\n  private ?CustomButton $pr_nCustomButton = null;\n  private ?MyCollection $pr_nMyCollection = null;\n\n  private mixed $pr_mixed = null;\n\n  public function __construct() {\n/*\n    echo \"================ Testing (unset) Cast ===================\\n\\n\";\n\n    $this->pr_bool = (unset)false;\n    echo \"(unset)false: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n    $this->pr_float = (unset)456.78;\n    echo \"(unset)456.78: pr_float = >\" . $this->pr_float . \"<\\n\";\n*/\n    echo \"\\n================ setting pr_bool ===================\\n\\n\";\n\n    $this->pr_bool = false;\n    $this->pr_bool = (bool)false;\n    echo \"(bool)false: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n    $this->pr_bool = true;\n    $this->pr_bool = (bool)true;\n    echo \"(bool)true: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = 0;\t\t// int is incompatible with bool\n    $this->pr_bool = (bool)0;\n    echo \"(bool)0: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = 100;\t\t// int is incompatible with bool\n    $this->pr_bool = (bool)100;\n    echo \"(bool)100: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = 0.0;\t\t// float is incompatible with bool\n    $this->pr_bool = (bool)0.0;\n    echo \"(bool)0.0: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = 123.45;\t// float is incompatible with bool\n    $this->pr_bool = (bool)123.45;\n    echo \"(bool)123.45: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = \"\";\t\t// string is incompatible with bool\n    $this->pr_bool = (bool)\"\";\n    echo \"(bool)\\\"\\\": pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = \"0\";\t\t// string is incompatible with bool\n    $this->pr_bool = (bool)\"0\";\n    echo \"(bool)\\\"0\\\": pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = \"123ABC\";\t// string is incompatible with bool\n    $this->pr_bool = (bool)\"123ABC\";\n    echo \"(bool)\\\"123ABC\\\": pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = \"456.78ABC\";\t// string is incompatible with bool\n    $this->pr_bool = (bool)\"456.78ABC\";\n    echo \"(bool)\\\"456.78ABC\\\": pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = null;\t\t// null is incompatible with bool\n    $this->pr_bool = (bool)null;\n    echo \"(bool)null: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = array();\t// array() is incompatible with bool\n    $this->pr_bool = (bool)array();\n    echo \"(bool)array(): pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = array(10,20,30);\t// array(...) is incompatible with bool\n    $this->pr_bool = (bool)array(10,20,30);\n    echo \"(bool)array(10,20,30): pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n//    $this->pr_bool = new Button();\t\t// Button is incompatible with bool\n    $this->pr_bool = (bool)new Button();\n    echo \"(bool)new Button(): pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n    //$this->pr_bool = STDOUT;\t\t// Uh-oh!! resource IS compatible with bool\n    $this->pr_bool = (bool)STDOUT;\n    echo \"(bool)STDOUT: pr_bool = >\" . ($this->pr_bool ? \"true\" : \"false\") . \"<\\n\";\n\n    echo \"\\n================ setting pr_int ===================\\n\\n\";\n\n//    $this->pr_int = false;\t\t// bool is incompatible with int\n    $this->pr_int = (int)false;\n    echo \"(int)false: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = true;\t\t// bool is incompatible with int\n    $this->pr_int = (int)true;\n    echo \"(int)true: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n    $this->pr_int = 0;\n    $this->pr_int = (int)0;\n    echo \"(int)0: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n    $this->pr_int = 100;\n    $this->pr_int = (int)100;\n    echo \"(int)100: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = 0.0;\t\t// float is incompatible with int\n    $this->pr_int = (int)0.0;\n    echo \"(int)0.0: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = 123.45;\t\t// float is incompatible with int\n    $this->pr_int = (int)123.45;\n    echo \"(int)123.45: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = \"\";\t\t// string is incompatible with int\n    $this->pr_int = (int)\"\";\n    echo \"(int)\\\"\\\": pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = \"0\";\t\t// string is incompatible with int\n    $this->pr_int = (int)\"0\";\n    echo \"(int)\\\"0\\\": pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = \"123ABC\";\t// string is incompatible with int\n    $this->pr_int = (int)\"123ABC\";\n    echo \"(int)\\\"123ABC\\\": pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = \"456.78ABC\";\t// string is incompatible with bool\n    $this->pr_int = (int)\"456.78ABC\";\n    echo \"(int)\\\"456.78ABC\\\": pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = null;\t\t// null is incompatible with int\n    $this->pr_int = (int)null;\n    echo \"(int)null: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = array();\t// array() is incompatible with int\n    $this->pr_int = (int)array();\n    echo \"(int)array(): pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = array(10,20,30);\t// array(...) is incompatible with int\n    $this->pr_int = (int)array(10,20,30);\n    echo \"(int)array(10,20,30): pr_int = >\" . $this->pr_int . \"<\\n\";\n\n//    $this->pr_int = new Button();\t\t// Button is incompatible with int\n    $this->pr_int = (int)new Button();\n    echo \"(int)new Button(): pr_int = >\" . $this->pr_int . \"<\\n\";\n\n    //$this->pr_int = STDOUT;\t\t// Uh-oh!! resource IS compatible with int\n    $this->pr_int = (int)STDOUT;\n    echo \"(int)STDOUT: pr_int = >\" . $this->pr_int . \"<\\n\";\n\n    echo \"\\n================ setting pr_float ===================\\n\\n\";\n\n//    $this->pr_float = false;\t// bool is incompatible with float\n    $this->pr_float = (float)false;\n    echo \"(float)false: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = true;\t\t// bool is incompatible with float\n    $this->pr_float = (float)true;\n    echo \"(float)true: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = 0;\t\t// int is incompatible with float\n    $this->pr_float = (float)0;\n    echo \"(float)0: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = 100;\t\t// int is incompatible with float\n    $this->pr_float = (float)100;\n    echo \"(float)100: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n    $this->pr_float = 0.0;\n    $this->pr_float = (float)0.0;\n    echo \"(float)0.0: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n    $this->pr_float = 123.45;\n    $this->pr_float = (float)123.45;\n    echo \"(float)123.45: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n    $this->pr_float = INF;\n    $this->pr_float = (float)INF;\n    echo \"(float)INF: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n    $this->pr_float = NAN;\n    $this->pr_float = (float)NAN;\n    echo \"(float)NAN: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = \"\";\t\t// string is incompatible with float\n    $this->pr_float = (float)\"\";\n    echo \"(float)\\\"\\\": pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = \"0\";\t\t// string is incompatible with float\n    $this->pr_float = (float)\"0\";\n    echo \"(float)\\\"0\\\": pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = \"123ABC\";\t// string is incompatible with float\n    $this->pr_float = (float)\"123ABC\";\n    echo \"(float)\\\"123ABC\\\": pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = \"456.78ABC\";\t// string is incompatible with bool\n    $this->pr_float = (float)\"456.78ABC\";\n    echo \"(float)\\\"456.78ABC\\\": pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = null;\t\t// null is incompatible with float\n    $this->pr_float = (float)null;\n    echo \"(float)null: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = array();\t// array() is incompatible with float\n    $this->pr_float = (float)array();\n    echo \"(float)array(): pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = array(10,20,30);\t// array(...) is incompatible with float\n    $this->pr_float = (float)array(10,20,30);\n    echo \"(float)array(10,20,30): pr_float = >\" . $this->pr_float . \"<\\n\";\n\n//    $this->pr_float = new Button();\t\t// Button is incompatible with float\n    $this->pr_float = (float)new Button();\n    echo \"(float)new Button(): pr_float = >\" . $this->pr_float . \"<\\n\";\n\n    //$this->pr_float = STDOUT;\t\t// Uh-oh!! resource IS compatible with float\n    $this->pr_float = (float)STDOUT;\n    echo \"(float)STDOUT: pr_float = >\" . $this->pr_float . \"<\\n\";\n\n    echo \"\\n================ setting pr_num ===================\\n\\n\";\n\n//    $this->pr_num = false;\t\t// bool is incompatible with num\n    $this->pr_num = (int)false;\n    echo \"(int)false: pr_num = >\" . $this->pr_num . \"<\\n\";\n    $this->pr_num = (float)false;\n    echo \"(float)false: pr_num = >\" . $this->pr_num . \"<\\n\";\n\n//    $this->pr_num = true;\t\t// bool is incompatible with num\n    $this->pr_num = (int)true;\n    echo \"(int)true: pr_num = >\" . $this->pr_num . \"<\\n\";\n    $this->pr_num = (float)true;\n    echo \"(float)true: pr_num = >\" . $this->pr_num . \"<\\n\";\n\n    $this->pr_num = 0;\n    echo \"0: pr_num = >\" . $this->pr_num . \"<\\n\";\n\n    $this->pr_num = 100;\n    echo \"100: pr_num = >\" . $this->pr_num . \"<\\n\";\n\n    $this->pr_num = 0.0;\n    echo \"0.0: pr_num = >\" . $this->pr_num . \"<\\n\";\n\n    $this->pr_num = 123.45;\n    echo \"123.45: pr_num = >\" . $this->pr_num . \"<\\n\";\n\n//    $this->pr_num = \"\";\t\t// string is incompatible with num\n    $this->pr_num = (int)\"\";\n    echo \"(int)\\\"\\\": pr_num = >\" . $this->pr_num . \"<\\n\";\n    $this->pr_num = (float)\"\";\n    echo \"(float)\\\"\\\": pr_num = >\" . $this->pr_num . \"<\\n\";\n\n//    $this->pr_num = \"0\";\t\t// string is incompatible with num\n    $this->pr_num = (int)\"0\";\n    echo \"(int)\\\"0\\\": pr_num = >\" . $this->pr_num . \"<\\n\";\n    $this->pr_num = (float)\"0\";\n    echo \"(float)\\\"0\\\": pr_num = >\" . $this->pr_num . \"<\\n\";\n\n//    $this->pr_num = \"123ABC\";\t// string is incompatible with num\n    $this->pr_num = (int)\"123ABC\";\n    echo \"(int)\\\"123ABC\\\": pr_num = >\" . $this->pr_num . \"<\\n\";\n    $this->pr_num = (float)\"123ABC\";\n    echo \"(float)\\\"123ABC\\\": pr_num = >\" . $this->pr_num . \"<\\n\";\n\n//    $this->pr_num = \"456.78ABC\";\t// string is incompatible with bool\n    $this->pr_num = (int)\"456.78ABC\";\n    echo \"(int)\\\"456.78ABC\\\": pr_num = >\" . $this->pr_num . \"<\\n\";\n    $this->pr_num = (float)\"456.78ABC\";\n    echo \"(float)\\\"456.78ABC\\\": pr_num = >\" . $this->pr_num . \"<\\n\";\n\n//    $this->pr_num = null;\t\t// null is incompatible with num\n    $this->pr_num = (int)null;\n    echo \"(int)null: pr_num = >\" . $this->pr_num . \"<\\n\";\n    $this->pr_num = (float)null;\n    echo \"(float)null: pr_num = >\" . $this->pr_num . \"<\\n\";\n\n//    $this->pr_num = array();\t// array() is incompatible with num\n    $this->pr_num = (int)array();\n    echo \"(int)array(): pr_num = >\" . $this->pr_num . \"<\\n\";\n    $this->pr_num = (float)array();\n    echo \"(float)array(): pr_num = >\" . $this->pr_num . \"<\\n\";\n\n//    $this->pr_num = array(10,20,30);\t// array(...) is incompatible with num\n    $this->pr_num = (int)array(10,20,30);\n    echo \"(int)array(10,20,30): pr_num = >\" . $this->pr_num . \"<\\n\";\n    $this->pr_num = (float)array(10,20,30);\n    echo \"(float)array(10,20,30): pr_num = >\" . $this->pr_num . \"<\\n\";\n\n//    $this->pr_num = new Button();\t\t// Button is incompatible with num\n    $this->pr_num = (int)new Button();\n    echo \"(int)new Button(): pr_num = >\" . $this->pr_num . \"<\\n\";\n    $this->pr_num = (float)new Button();\n    echo \"(float)new Button(): pr_num = >\" . $this->pr_num . \"<\\n\";\n\n    //$this->pr_num = STDOUT;\t\t// Uh-oh!! resource IS compatible with num\n    $this->pr_num = (int)STDOUT;\n    echo \"(int)STDOUT: pr_num = >\" . $this->pr_num . \"<\\n\";\n    $this->pr_num = (float)STDOUT;\n    echo \"(float)STDOUT: pr_num = >\" . $this->pr_num . \"<\\n\";\n\n    echo \"\\n================ setting pr_string ===================\\n\\n\";\n\n//    $this->pr_string = (binary)false;\t// cast to binary is not permitted\n\n//    $this->pr_string = false;\t\t// bool is incompatible with string\n    $this->pr_string = (string)false;\n    echo \"(string)false: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = true;\t\t// bool is incompatible with string\n    $this->pr_string = (string)true;\n    echo \"(string)true: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = 0;\n    $this->pr_string = (string)0;\n    echo \"(string)0: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = 100;\n    $this->pr_string = (string)100;\n    echo \"(string)100: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = 0.0;\t\t// float is incompatible with string\n    $this->pr_string = (string)0.0;\n    echo \"(string)0.0: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = 123.45;\t\t// float is incompatible with string\n    $this->pr_string = (string)123.45;\n    echo \"(string)123.45: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = \"\";\t\t// string is incompatible with string\n    $this->pr_string = (string)\"\";\n    echo \"(string)\\\"\\\": pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = \"0\";\t\t// string is incompatible with string\n    $this->pr_string = (string)\"0\";\n    echo \"(string)\\\"0\\\": pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = \"123ABC\";\t// string is incompatible with string\n    $this->pr_string = (string)\"123ABC\";\n    echo \"(string)\\\"123ABC\\\": pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = \"456.78ABC\";\t// string is incompatible with bool\n    $this->pr_string = (string)\"456.78ABC\";\n    echo \"(string)\\\"456.78ABC\\\": pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = null;\t\t// null is incompatible with string\n    $this->pr_string = (string)null;\n    echo \"(string)null: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = array();\t// array() is incompatible with string\n    $this->pr_string = (string)array();\n    echo \"(string)array(): pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = array(10,20,30);\t// array(...) is incompatible with string\n    $this->pr_string = (string)array(10,20,30);\n    echo \"(string)array(10,20,30): pr_string = >\" . $this->pr_string . \"<\\n\";\n\n//    $this->pr_string = new Button();\t\t// Button is incompatible with string\n    $this->pr_string = (string)new Button();\n    echo \"(string)new Button(): pr_string = >\" . $this->pr_string . \"<\\n\";\n\n    //$this->pr_string = STDOUT;\t\t// Uh-oh!! resource IS compatible with string\n    $this->pr_string = (string)STDOUT;\n    echo \"(string)STDOUT: pr_string = >\" . $this->pr_string . \"<\\n\";\n\n    echo \"\\n================ setting pr_resource ===================\\n\\n\";\n\n//    $this->pr_resource = false;\t\t// bool is incompatible with resource\n//    $this->pr_resource = (resource)false;\t// cast to resource is not permitted\n\n//    $this->pr_resource = 0;\t\t// int is incompatible with resource\n//    $this->pr_resource = 100;\t// int is incompatible with resource\n//    $this->pr_resource = 0.0;\t// float is incompatible with resource\n//    $this->pr_resource = 123.45;\t// float is incompatible with resource\n//    $this->pr_resource = \"\";\t// string is incompatible with resource\n//    $this->pr_resource = \"0\";\t// string is incompatible with resource\n//    $this->pr_resource = \"123ABC\";\t// string is incompatible with resource\n//    $this->pr_resource = \"456.78ABC\";\t// string is incompatible with resource\n//    $this->pr_resource = null;\t// null is incompatible with resource\n//    $this->pr_resource = array();\t// array() is incompatible with resource\n//    $this->pr_resource = array(10,20,30);// array(...) is incompatible with resource\n\n    $this->pr_resource = STDOUT;\n    echo \"STDOUT: pr_resource = >\" . $this->pr_resource . \"<\\n\";\n\n    echo \"\\n================ setting pr_Button ===================\\n\\n\";\n\n//    $this->pr_Button = false;\t\t// bool is incompatible with Button\n//    $this->pr_Button = (Button)false;\t// cast to Button is not permitted\n//    $this->pr_Button = (object)false;\t// cast to object is not permitted\n\n//    $this->pr_Button = 0;\t\t// int is incompatible with Button\n//    $this->pr_Button = 100;\t\t// int is incompatible with Button\n//    $this->pr_Button = 0.0;\t\t// float is incompatible with Button\n//    $this->pr_Button = 123.45;\t// float is incompatible with Button\n//    $this->pr_Button = \"\";\t\t// string is incompatible with Button\n//    $this->pr_Button = \"0\";\t\t// string is incompatible with Button\n//    $this->pr_Button = \"123ABC\";\t// string is incompatible with Button\n//    $this->pr_Button = \"456.78ABC\";\t// string is incompatible with Button\n//    $this->pr_Button = null;\t// null is incompatible with Button\n//    $this->pr_Button = array();\t// array() is incompatible with Button\n//    $this->pr_Button = array(10,20,30);// array(...) is incompatible with Button\n\n    $this->pr_Button = new Button(\"STOP\");\n    echo \"new Button(\\\"STOP\\\"): pr_Button = >\" . $this->pr_Button . \"<\\n\";\n\n    $this->pr_Button = new CustomButton(\"RAISE\");\n    echo \"new CustomButton(\\\"RAISE\\\"): pr_Button = >\" . $this->pr_Button . \"<\\n\";\n\n    //$this->pr_Button = STDOUT;\t\t// Uh-oh!! resource IS compatible with Button\n    echo \"STDOUT: pr_Button = >\" . $this->pr_Button . \"<\\n\";\n\n    echo \"\\n================ setting pr_CustomButton===================\\n\\n\";\n\n    $this->pr_CustomButton = new CustomButton(\"LOWER\");\n    echo \"new CustomButton(\\\"LOWER\\\"): pr_CustomButton= >\" . $this->pr_CustomButton. \"<\\n\";\n\n    //$this->pr_CustomButton = STDOUT;\t// Uh-oh!! resource IS compatible with CustomButton\n    echo \"STDOUT: pr_CustomButton = >\" . $this->pr_CustomButton . \"<\\n\";\n\n    echo \"\\n================ setting pr_MyCollection ===================\\n\\n\";\n\n//    $this->pr_MyCollection = false;\t\t// bool is incompatible with MyCollection\n//    $this->pr_MyCollection = (MyCollection)false;\t// cast to MyCollection is not permitted\n\n    $this->pr_MyCollection = new MyList();\n    echo \"new MyList(): pr_MyCollection = >\" . $this->pr_MyCollection . \"<\\n\";\n\n    $this->pr_MyCollection = new MyQueue();\n    echo \"new MyQueue(): pr_MyCollection = >\" . $this->pr_MyCollection . \"<\\n\";\n\n    //$this->pr_MyCollection = STDOUT;\t// Uh-oh!! resource IS compatible with MyCollection\n    //echo \"STDOUT: pr_MyCollection = >\" . $this->pr_MyCollection . \"<\\n\";\n\n    echo \"\\n================ converting non-nullable to corresponding nullable ===================\\n\\n\";\n\n    echo \"bool: pr_nbool = >\" . $this->pr_nbool . \"<\\n\";\n//    $this->pr_nbool = (?bool)true;\t\t// can't cast to any nullable type\n    $this->pr_nbool = true;\n    echo \"bool: pr_nbool = >\" . $this->pr_nbool . \"<\\n\";\n    $this->pr_nbool = false;\n    echo \"bool: pr_nbool = >\" . $this->pr_nbool . \"<\\n\";\n    $this->pr_nbool = $this->pr_bool;\n    echo \"bool: pr_nbool = >\" . $this->pr_nbool . \"<\\n\";\n\n    echo \"int: pr_nint = >\" . $this->pr_nint . \"<\\n\";\n    $this->pr_nint = 100;\n    echo \"int: pr_nint = >\" . $this->pr_nint . \"<\\n\";\n    $this->pr_nint = $this->pr_int;\n    echo \"int: pr_nint = >\" . $this->pr_nint . \"<\\n\";\n\n    echo \"float: pr_nfloat = >\" . $this->pr_nfloat . \"<\\n\";\n    $this->pr_nfloat = 123.45;\n    echo \"float: pr_nfloat = >\" . $this->pr_nfloat . \"<\\n\";\n    $this->pr_nfloat = $this->pr_float;\n    echo \"float: pr_nfloat = >\" . $this->pr_nfloat . \"<\\n\";\n\n    echo \"num: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n    $this->pr_nnum = 100;\n    echo \"num: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n    $this->pr_nnum = 123.45;\n    echo \"num: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n    $this->pr_nnum = $this->pr_num;\n    echo \"num: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n\n    echo \"string: pr_nstring = >\" . $this->pr_nstring . \"<\\n\";\n    $this->pr_nstring = \"123ABC\";\n    echo \"string: pr_nstring = >\" . $this->pr_nstring . \"<\\n\";\n    $this->pr_nstring = $this->pr_string;\n    echo \"string: pr_nstring = >\" . $this->pr_nstring . \"<\\n\";\n\n    echo \"resource: pr_nresource = >\" . $this->pr_nresource . \"<\\n\";\n    $this->pr_nresource = STDERR;\n    echo \"resource: pr_nresource = >\" . $this->pr_nresource . \"<\\n\";\n    $this->pr_nresource = $this->pr_resource;\n    echo \"resource: pr_nresource = >\" . $this->pr_nresource . \"<\\n\";\n\n    echo \"Button: pr_nButton = >\" . $this->pr_nButton . \"<\\n\";\n    $this->pr_nButton = new Button(\"HOT\");\n    echo \"Button: pr_nButton = >\" . $this->pr_nButton . \"<\\n\";\n    $this->pr_nButton = new CustomButton(\"COLD\");\n    echo \"CustomButton: pr_nButton = >\" . $this->pr_nButton . \"<\\n\";\n    $this->pr_nButton = $this->pr_Button;\n    echo \"Button: pr_nButton = >\" . $this->pr_nButton . \"<\\n\";\n\n    echo \"CustomButton: pr_nCustomButton = >\" . $this->pr_nCustomButton . \"<\\n\";\n    $this->pr_nCustomButton = new CustomButton(\"ALARM\");\n    echo \"CustomButton: pr_nCustomButton = >\" . $this->pr_nCustomButton . \"<\\n\";\n    $this->pr_nCustomButton = $this->pr_CustomButton;\n    echo \"CustomButton: pr_nCustomButton = >\" . $this->pr_nCustomButton . \"<\\n\";\n\n//    echo \"MyCollection: pr_nMyCollection = >\" . $this->pr_nMyCollection . \"<\\n\";\n    $this->pr_nMyCollection = new MyList();\n    echo \"MyCollection: pr_nMyCollection = >\" . $this->pr_nMyCollection . \"<\\n\";\n    $this->pr_nMyCollection = new MyQueue();\n    echo \"MyCollection: pr_nMyCollection = >\" . $this->pr_nMyCollection . \"<\\n\";\n    $this->pr_nMyCollection = $this->pr_MyCollection;\n\n// next line diasbale 'cos of probably bug in that property currently contains a resource when that\n// assignment shouldn't have been allowed.\n//    echo \"MyCollection: pr_nMyCollection = >\" . $this->pr_nMyCollection . \"<\\n\";\n\n    echo \"\\n================ converting one nullable to a different nullable (excluding mixed) ===================\\n\\n\";\n\n    $this->pr_nnum = $this->pr_nint;\n    echo \"nint: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n    $this->pr_nnum = $this->pr_nfloat;\n    echo \"nfloat: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n    $this->pr_nButton = $this->pr_nCustomButton;\n    echo \"nCustomButton: pr_nnum = >\" . $this->pr_nnum . \"<\\n\";\n//???    $this->pr_nCustomButton = $this->pr_nButton;\n\n    echo \"\\n================ converting nullable to corresponding non-nullable ===================\\n\\n\";\n\n    $this->pr_nbool = null;\n    $this->pr_bool = (bool)$this->pr_nbool;\n    echo \"pr->bool = >\" . $this->pr_bool . \"<\\n\";\n    $this->pr_nbool = true;\n    $this->pr_bool = (bool)$this->pr_nbool;\n    echo \"pr->bool = >\" . $this->pr_bool . \"<\\n\";\n\n    $this->pr_nint = null;\n    $this->pr_int = (int)$this->pr_nint;\n    echo \"pr->int = >\" . $this->pr_int . \"<\\n\";\n    $this->pr_nint = 100;\n    $this->pr_int = (int)$this->pr_nint;\n    echo \"pr->int = >\" . $this->pr_int . \"<\\n\";\n\n    $this->pr_nfloat = null;\n    $this->pr_float = (float)$this->pr_nfloat;\n    echo \"pr->float = >\" . $this->pr_float . \"<\\n\";\n    $this->pr_nfloat = 123.45;\n    $this->pr_float = (float)$this->pr_nfloat;\n    echo \"pr->float = >\" . $this->pr_float . \"<\\n\";\n\n    $this->pr_nstring = null;\n    $this->pr_string = (string)$this->pr_nstring;\n    echo \"pr->string = >\" . $this->pr_string . \"<\\n\";\n    $this->pr_nstring = \"123ABC\";\n    $this->pr_string = (string)$this->pr_nstring;\n    echo \"pr->string = >\" . $this->pr_string . \"<\\n\";\n\n    echo \"\\n================ setting pr_mixed ===================\\n\\n\";\n\n    $this->pr_mixed = false;\n//    $this->pr_mixed = (mixed)false;\t// cast to mixed is not permitted\n    echo \"false: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_bool;\n    echo \"pr_bool: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nbool;\n    echo \"pr_nbool: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = true;\n    echo \"true: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = 0;\n    echo \"0: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_int;\n    echo \"pr_int: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nint;\n    echo \"pr_nint: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = 100;\n    echo \"100: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = 0.0;\n    echo \"0.0: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_float;\n    echo \"pr_float: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nfloat;\n    echo \"pr_nfloat: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = 123.45;\n    echo \"123.45: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = \"\";\n    echo \"\\\"\\\": pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_string;\n    echo \"pr_string: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nstring;\n    echo \"pr_nstring: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = \"0\";\n    echo \"\\\"0\\\": pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = \"123ABC\";\n    echo \"\\\"123ABC\\\": pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = \"456.78ABC\";\n    echo \"\\\"456.78ABC\\\": pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = null;\n    echo \"null: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = array();\n    echo \"array(): pr_mixed = >\" . ((string)$this->pr_mixed) . \"<\\n\";\n\n    $this->pr_mixed = array(10,20,30);\n    echo \"array(10,20,30): pr_mixed = >\" . ((string)$this->pr_mixed) . \"<\\n\";\n\n    $this->pr_mixed = new Button();\n    echo \"new Button(): pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_Button;\n    echo \"pr_Button: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nButton;\n    echo \"pr_nButton: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = new CustomButton();\n    echo \"new CustomButton(): pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_CustomButton;\n    echo \"pr_CustomButton: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nCustomButton;\n    echo \"pr_nCustomButton: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = new MyList();\n    echo \"new MyList(): pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = new MyQueue();\n    echo \"new MyQueue(): pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_MyCollection;\n\n// next line disable 'cos of probably bug in that property currently contains a resource when that\n// assignment shouldn't have been allowed.\n//    echo \"pr_MyCollection: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nMyCollection;\n// next line disable 'cos of probably bug in that property currently contains a resource when that\n// assignment shouldn't have been allowed.\n//    echo \"pr_nMyCollection: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n    $this->pr_mixed = STDOUT;\n    echo \"STDOUT: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_resource;\n    echo \"pr_resource: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n    $this->pr_mixed = $this->pr_nresource;\n    echo \"pr_nresource: pr_mixed = >\" . $this->pr_mixed . \"<\\n\";\n\n  }\n}\n\nfunction main(): void {\n  $c1 = new C1();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Nullable_Types/conversions.php.expectf",
    "content": "\n================ setting pr_bool ===================\n\n(bool)false: pr_bool = >false<\n(bool)true: pr_bool = >true<\n(bool)0: pr_bool = >false<\n(bool)100: pr_bool = >true<\n(bool)0.0: pr_bool = >false<\n(bool)123.45: pr_bool = >true<\n(bool)\"\": pr_bool = >false<\n(bool)\"0\": pr_bool = >false<\n(bool)\"123ABC\": pr_bool = >true<\n(bool)\"456.78ABC\": pr_bool = >true<\n(bool)null: pr_bool = >false<\n(bool)array(): pr_bool = >false<\n(bool)array(10,20,30): pr_bool = >true<\n(bool)new Button(): pr_bool = >true<\n(bool)STDOUT: pr_bool = >true<\n\n================ setting pr_int ===================\n\n(int)false: pr_int = >0<\n(int)true: pr_int = >1<\n(int)0: pr_int = >0<\n(int)100: pr_int = >100<\n(int)0.0: pr_int = >0<\n(int)123.45: pr_int = >123<\n(int)\"\": pr_int = >0<\n(int)\"0\": pr_int = >0<\n(int)\"123ABC\": pr_int = >123<\n(int)\"456.78ABC\": pr_int = >456<\n(int)null: pr_int = >0<\n(int)array(): pr_int = >0<\n(int)array(10,20,30): pr_int = >1<\n\nNotice: Object of class NS_conversions_in_nullable_dir\\Button could not be converted to int in %s/tests/Nullable_Types/conversions.php on line 190\n(int)new Button(): pr_int = >1<\n(int)STDOUT: pr_int = >2<\n\n================ setting pr_float ===================\n\n(float)false: pr_float = >0<\n(float)true: pr_float = >1<\n(float)0: pr_float = >0<\n(float)100: pr_float = >100<\n(float)0.0: pr_float = >0<\n(float)123.45: pr_float = >123.45<\n(float)INF: pr_float = >INF<\n(float)NAN: pr_float = >NAN<\n(float)\"\": pr_float = >0<\n(float)\"0\": pr_float = >0<\n(float)\"123ABC\": pr_float = >123<\n(float)\"456.78ABC\": pr_float = >456.78<\n(float)null: pr_float = >0<\n(float)array(): pr_float = >0<\n(float)array(10,20,30): pr_float = >1<\n\nNotice: Object of class NS_conversions_in_nullable_dir\\Button could not be converted to int in %s/tests/Nullable_Types/conversions.php on line 260\n(float)new Button(): pr_float = >1<\n(float)STDOUT: pr_float = >2<\n\n================ setting pr_num ===================\n\n(int)false: pr_num = >0<\n(float)false: pr_num = >0<\n(int)true: pr_num = >1<\n(float)true: pr_num = >1<\n0: pr_num = >0<\n100: pr_num = >100<\n0.0: pr_num = >0<\n123.45: pr_num = >123.45<\n(int)\"\": pr_num = >0<\n(float)\"\": pr_num = >0<\n(int)\"0\": pr_num = >0<\n(float)\"0\": pr_num = >0<\n(int)\"123ABC\": pr_num = >123<\n(float)\"123ABC\": pr_num = >123<\n(int)\"456.78ABC\": pr_num = >456<\n(float)\"456.78ABC\": pr_num = >456.78<\n(int)null: pr_num = >0<\n(float)null: pr_num = >0<\n(int)array(): pr_num = >0<\n(float)array(): pr_num = >0<\n(int)array(10,20,30): pr_num = >1<\n(float)array(10,20,30): pr_num = >1<\n\nNotice: Object of class NS_conversions_in_nullable_dir\\Button could not be converted to int in %s/tests/Nullable_Types/conversions.php on line 336\n(int)new Button(): pr_num = >1<\n\nNotice: Object of class NS_conversions_in_nullable_dir\\Button could not be converted to int in %s/tests/Nullable_Types/conversions.php on line 338\n(float)new Button(): pr_num = >1<\n(int)STDOUT: pr_num = >2<\n(float)STDOUT: pr_num = >2<\n\n================ setting pr_string ===================\n\n(string)false: pr_string = ><\n(string)true: pr_string = >1<\n(string)0: pr_string = >0<\n(string)100: pr_string = >100<\n(string)0.0: pr_string = >0<\n(string)123.45: pr_string = >123.45<\n(string)\"\": pr_string = ><\n(string)\"0\": pr_string = >0<\n(string)\"123ABC\": pr_string = >123ABC<\n(string)\"456.78ABC\": pr_string = >456.78ABC<\n(string)null: pr_string = ><\n\nNotice: Array to string conversion in %s/tests/Nullable_Types/conversions.php on line 396\n(string)array(): pr_string = >Array<\n\nNotice: Array to string conversion in %s/tests/Nullable_Types/conversions.php on line 400\n(string)array(10,20,30): pr_string = >Array<\n(string)new Button(): pr_string = >[[Button: ??]]<\n(string)STDOUT: pr_string = >Resource id #2<\n\n================ setting pr_resource ===================\n\nSTDOUT: pr_resource = >Resource id #2<\n\n================ setting pr_Button ===================\n\nnew Button(\"STOP\"): pr_Button = >[[Button: STOP]]<\nnew CustomButton(\"RAISE\"): pr_Button = >[[Button: RAISE]][[CustomButton]]<\nSTDOUT: pr_Button = >Resource id #2<\n\n================ setting pr_CustomButton===================\n\nnew CustomButton(\"LOWER\"): pr_CustomButton= >[[Button: LOWER]][[CustomButton]]<\nSTDOUT: pr_CustomButton = >Resource id #2<\n\n================ setting pr_MyCollection ===================\n\nnew MyList(): pr_MyCollection = >[[MyList]]<\nnew MyQueue(): pr_MyCollection = >[[MyQueue]]<\nSTDOUT: pr_MyCollection = >Resource id #2<\n\n================ converting non-nullable to corresponding nullable ===================\n\nbool: pr_nbool = ><\nbool: pr_nbool = >1<\nbool: pr_nbool = ><\nbool: pr_nbool = >1<\nint: pr_nint = ><\nint: pr_nint = >100<\nint: pr_nint = >2<\nfloat: pr_nfloat = ><\nfloat: pr_nfloat = >123.45<\nfloat: pr_nfloat = >2<\nnum: pr_nnum = ><\nnum: pr_nnum = >100<\nnum: pr_nnum = >123.45<\nnum: pr_nnum = >2<\nstring: pr_nstring = ><\nstring: pr_nstring = >123ABC<\nstring: pr_nstring = >Resource id #2<\nresource: pr_nresource = ><\nresource: pr_nresource = >Resource id #3<\nresource: pr_nresource = >Resource id #2<\nButton: pr_nButton = ><\nButton: pr_nButton = >[[Button: HOT]]<\nCustomButton: pr_nButton = >[[Button: COLD]][[CustomButton]]<\nButton: pr_nButton = >Resource id #2<\nCustomButton: pr_nCustomButton = ><\nCustomButton: pr_nCustomButton = >[[Button: ALARM]][[CustomButton]]<\nCustomButton: pr_nCustomButton = >Resource id #2<\nMyCollection: pr_nMyCollection = >[[MyList]]<\nMyCollection: pr_nMyCollection = >[[MyQueue]]<\n\n================ converting one nullable to a different nullable (excluding mixed) ===================\n\nnint: pr_nnum = >2<\nnfloat: pr_nnum = >2<\nnCustomButton: pr_nnum = >2<\n\n================ converting nullable to corresponding non-nullable ===================\n\npr->bool = ><\npr->bool = >1<\npr->int = >0<\npr->int = >100<\npr->float = >0<\npr->float = >123.45<\npr->string = ><\npr->string = >123ABC<\n\n================ setting pr_mixed ===================\n\nfalse: pr_mixed = ><\npr_bool: pr_mixed = >1<\npr_nbool: pr_mixed = >1<\ntrue: pr_mixed = >1<\n0: pr_mixed = >0<\npr_int: pr_mixed = >100<\npr_nint: pr_mixed = >100<\n100: pr_mixed = >100<\n0.0: pr_mixed = >0<\npr_float: pr_mixed = >123.45<\npr_nfloat: pr_mixed = >123.45<\n123.45: pr_mixed = >123.45<\n\"\": pr_mixed = ><\npr_string: pr_mixed = >123ABC<\npr_nstring: pr_mixed = >123ABC<\n\"0\": pr_mixed = >0<\n\"123ABC\": pr_mixed = >123ABC<\n\"456.78ABC\": pr_mixed = >456.78ABC<\nnull: pr_mixed = ><\n\nNotice: Array to string conversion in %s/tests/Nullable_Types/conversions.php on line 641\narray(): pr_mixed = >Array<\n\nNotice: Array to string conversion in %s/tests/Nullable_Types/conversions.php on line 644\narray(10,20,30): pr_mixed = >Array<\nnew Button(): pr_mixed = >[[Button: ??]]<\npr_Button: pr_mixed = >Resource id #2<\npr_nButton: pr_mixed = >Resource id #2<\nnew CustomButton(): pr_mixed = >[[Button: ??]][[CustomButton]]<\npr_CustomButton: pr_mixed = >Resource id #2<\npr_nCustomButton: pr_mixed = >Resource id #2<\nnew MyList(): pr_mixed = >[[MyList]]<\nnew MyQueue(): pr_mixed = >[[MyQueue]]<\nSTDOUT: pr_mixed = >Resource id #2<\npr_resource: pr_mixed = >Resource id #2<\npr_nresource: pr_mixed = >Resource id #2<"
  },
  {
    "path": "tests/Nullable_Types/nullables.php",
    "content": "<?hh // strict\n\nnamespace NS_nullables;\n\nclass Button {}\nclass CustomButton extends Button {}\n\ninterface MyCollection {}\nclass MyList implements MyCollection {}\nclass MyQueue implements MyCollection {}\n\nclass C1 {\n  private ?bool $pr_nbool = null;\n  private ?int $pr_nint = null;\n  private ?float $pr_nfloat = null;\n  private ?num $pr_nnum = null;\n  private ?string $pr_nstring = null;\n  private mixed $pr_mixed = null;\t// ?mixed === mixed; ? is redundant\n  private ?resource $pr_nresource = null;\n\n  private ?Button $pr_nButton = null;\n  private ?CustomButton $pr_nCustomButton = null;\n  private ?MyCollection $pr_nMyCollection = null;\n\n///*\n  private array<?bool> $a_nbool = array(true, null);\n  private array<?int> $a_nint = array(10, null);\n  private array<?float> $a_nfloat = array(3.1, null);\n  private array<?num> $a_nnum = array(-4, 5.4, null);\n  private array<?string> $a_nstring = array('a', null);\n  private array<mixed> $a_mixed = array(10, 'b', null);\t// ?mixed === mixed; ? is redundant\n//  private array<?resource> $a_nresource = array(STDIN, null);\n\n  private array<?Button> $a_nButton = array();\n  private array<?CustomButton> $a_nCustomButton = array();\n  private array<?MyCollection> $a_nMyCollection = array();\n//*/\n\n  public function __construct() {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n\n///*\n    $this->pr_nbool = true;\n    $this->pr_nint = 10;\n    $this->pr_nfloat = 3.1;\n    $this->pr_nnum = -4; $this->pr_nnum = 5.4;\n    $this->pr_nstring = 'a';\n    $this->pr_mixed = 10; $this->pr_mixed = 'b';\n//    $this->pr_nresource = STDIN;\n\n    $this->pr_nButton = new Button();\n    $this->pr_nButton = new CustomButton();\n    $this->pr_nCustomButton = new CustomButton();\n    $this->pr_nButton = $this->pr_nCustomButton;\n    $this->pr_nCustomButton = $this->pr_nButton;\n\n    $this->pr_nMyCollection = new MyList();\n    $this->pr_nMyCollection = new MyQueue();\n//*/\n\n///*\n    $this->a_nbool = array(true, null);\n    $this->a_nint = array(10, null);\n    $this->a_nfloat = array(3.1, null);\n    $this->a_nnum = array(-4, 5.4, null);\n    $this->a_nstring = array('a', null);\n    $this->a_mixed = array(10, 'b', null);\n//    $this->a_nresource = array(STDIN, null);\n\n    $this->a_nButton = array(new Button(), null, new CustomButton());\n    $this->a_nCustomButton = array(new CustomButton(), null);\n    $this->a_nMyCollection = array(null, new MyList(), new MyQueue());\n//*/\n  }\n}\n\nfunction main(): void {\n  $c1 = new C1();\n  var_dump($c1);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Nullable_Types/nullables.php.expect",
    "content": "Inside NS_nullables\\C1::__construct\nobject(NS_nullables\\C1)#1 (19) {\n  [\"pr_nbool\":\"NS_nullables\\C1\":private]=>\n  bool(true)\n  [\"pr_nint\":\"NS_nullables\\C1\":private]=>\n  int(10)\n  [\"pr_nfloat\":\"NS_nullables\\C1\":private]=>\n  float(3.1)\n  [\"pr_nnum\":\"NS_nullables\\C1\":private]=>\n  float(5.4)\n  [\"pr_nstring\":\"NS_nullables\\C1\":private]=>\n  string(1) \"a\"\n  [\"pr_mixed\":\"NS_nullables\\C1\":private]=>\n  string(1) \"b\"\n  [\"pr_nresource\":\"NS_nullables\\C1\":private]=>\n  NULL\n  [\"pr_nButton\":\"NS_nullables\\C1\":private]=>\n  object(NS_nullables\\CustomButton)#4 (0) {\n  }\n  [\"pr_nCustomButton\":\"NS_nullables\\C1\":private]=>\n  object(NS_nullables\\CustomButton)#4 (0) {\n  }\n  [\"pr_nMyCollection\":\"NS_nullables\\C1\":private]=>\n  object(NS_nullables\\MyQueue)#6 (0) {\n  }\n  [\"a_nbool\":\"NS_nullables\\C1\":private]=>\n  array(2) {\n    [0]=>\n    bool(true)\n    [1]=>\n    NULL\n  }\n  [\"a_nint\":\"NS_nullables\\C1\":private]=>\n  array(2) {\n    [0]=>\n    int(10)\n    [1]=>\n    NULL\n  }\n  [\"a_nfloat\":\"NS_nullables\\C1\":private]=>\n  array(2) {\n    [0]=>\n    float(3.1)\n    [1]=>\n    NULL\n  }\n  [\"a_nnum\":\"NS_nullables\\C1\":private]=>\n  array(3) {\n    [0]=>\n    int(-4)\n    [1]=>\n    float(5.4)\n    [2]=>\n    NULL\n  }\n  [\"a_nstring\":\"NS_nullables\\C1\":private]=>\n  array(2) {\n    [0]=>\n    string(1) \"a\"\n    [1]=>\n    NULL\n  }\n  [\"a_mixed\":\"NS_nullables\\C1\":private]=>\n  array(3) {\n    [0]=>\n    int(10)\n    [1]=>\n    string(1) \"b\"\n    [2]=>\n    NULL\n  }\n  [\"a_nButton\":\"NS_nullables\\C1\":private]=>\n  array(3) {\n    [0]=>\n    object(NS_nullables\\Button)#7 (0) {\n    }\n    [1]=>\n    NULL\n    [2]=>\n    object(NS_nullables\\CustomButton)#8 (0) {\n    }\n  }\n  [\"a_nCustomButton\":\"NS_nullables\\C1\":private]=>\n  array(2) {\n    [0]=>\n    object(NS_nullables\\CustomButton)#9 (0) {\n    }\n    [1]=>\n    NULL\n  }\n  [\"a_nMyCollection\":\"NS_nullables\\C1\":private]=>\n  array(3) {\n    [0]=>\n    NULL\n    [1]=>\n    object(NS_nullables\\MyList)#10 (0) {\n    }\n    [2]=>\n    object(NS_nullables\\MyQueue)#11 (0) {\n    }\n  }\n}"
  },
  {
    "path": "tests/Script_Inclusion/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Script_Inclusion/Circle.php",
    "content": "<?hh // strict\n\nnamespace NS_Circle;\n\nrequire_once 'Point.php';\n\nclass Circle {\n  public function __construct(float $newX, float $newY, float $newR) {\n  }\n\n  // ...\n}\n"
  },
  {
    "path": "tests/Script_Inclusion/Circle.php.expect",
    "content": ""
  },
  {
    "path": "tests/Script_Inclusion/Point.php",
    "content": "<?hh // strict\n\nnamespace NS_Point_Script_Inclusion;\n\nclass Point {\n  public function __construct(float $newX = 0.0, float $newY = 0.0) {\n  }\n}\n"
  },
  {
    "path": "tests/Script_Inclusion/Point.php.expect",
    "content": ""
  },
  {
    "path": "tests/Script_Inclusion/Positions.php",
    "content": "<?hh // strict\n\nnamespace NS_Positions;\n\nconst int TOP = 1;\nconst int RIGHT = 2;\nconst int BOTTOM = 3;\nconst int LEFT = 3;\n"
  },
  {
    "path": "tests/Script_Inclusion/Positions.php.expect",
    "content": ""
  },
  {
    "path": "tests/Script_Inclusion/limits.php",
    "content": "<?hh // strict\n\nnamespace NS_limits;\n\nconst int MY_MIN = 10;\nconst int MY_MAX = 50;\n"
  },
  {
    "path": "tests/Script_Inclusion/limits.php.expect",
    "content": ""
  },
  {
    "path": "tests/Script_Inclusion/mycolors.php",
    "content": "<?hh // strict\n\nconst int RED = 1;\nconst int WHITE = 2;\nconst int BLUE = 3;\n"
  },
  {
    "path": "tests/Script_Inclusion/mycolors.php.expect",
    "content": ""
  },
  {
    "path": "tests/Script_Inclusion/require.php",
    "content": "<?hh // strict\n\nnamespace NS_require;\n\n//require 'unknown.php';\nrequire 'limits.php';\nrequire('mycolors.php');\nrequire('return_none.php');\nrequire('return_with_value.php');\n\nfunction main(): void {\n///*\n// Try to access constants defined in a required file\n\n  if (defined(\"MY_MIN\"))\n    echo \"MY_MIN is defined with value >\" . constant(\"MY_MIN\") . \"\\n\";\n  else\n    echo \"MY_MIN is not defined\\n\";\n//*/\n\n// get the set of included files\n\n  print_r(get_included_files());\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Script_Inclusion/require.php.expectf",
    "content": "MY_MIN is not defined\nArray\n(\n    [0] => %s/tests/Script_Inclusion/require.php\n    [1] => %s/tests/Script_Inclusion/limits.php\n    [2] => %s/tests/Script_Inclusion/mycolors.php\n    [3] => %s/tests/Script_Inclusion/return_none.php\n    [4] => %s/tests/Script_Inclusion/return_with_value.php\n)"
  },
  {
    "path": "tests/Script_Inclusion/require_once.php",
    "content": "<?hh // strict\n\nnamespace NS_require_once;\n\n//require_once('XXPositions.php');\nrequire('Positions.php');\nrequire_once('Point.php');\nrequire_once('Circle.php');\n\nfunction main(): void {\n  var_dump(\\NS_Positions\\LEFT);\n  var_dump(\\NS_Positions\\TOP);\n\n  $p1 = new \\NS_Point\\Point(10.0,20.0);\n  $p2 = new \\NS_Point\\Point(5.0, 6.0);\n  var_dump($p1, $p2);\n\n  $c1 = new \\NS_Circle\\Circle(9.0, 7.0, 2.4);\n var_dump($c1);\n\n  print_r(get_required_files());\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Script_Inclusion/require_once.php.expectf",
    "content": "int(3)\nint(1)\n\nFatal error: Class undefined: NS_Point\\Point in %s/tests/Script_Inclusion/require_once.php on line 14"
  },
  {
    "path": "tests/Script_Inclusion/return_none.php",
    "content": "<?hh // strict\n\n// no return statement, so when included, int(1) is returned\n"
  },
  {
    "path": "tests/Script_Inclusion/return_none.php.expect",
    "content": ""
  },
  {
    "path": "tests/Script_Inclusion/return_with_value.php",
    "content": "<?hh // strict\n\n// has explicit return value, so when included, that value is returned\n\n// return 987;\t// can't have a return statement at the top level\n"
  },
  {
    "path": "tests/Script_Inclusion/return_with_value.php.expect",
    "content": ""
  },
  {
    "path": "tests/Serialization/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Serialization/Point.php",
    "content": "<?hh // strict\n\nnamespace Graphics;\n\nclass Point implements \\Serializable {\t// note the interface\n  private static int $nextId = 1;\n  private int $id;\t// transient property; not serialized\n\n  private float $x;\n  private float $y;\n\n  public function __construct(float $x = 0.0, float $y = 0.0) {\n    $this->x = $x;\n    $this->y = $y;\n    $this->id = self::$nextId++;\n  }\n\n  public function __toString(): string {\n    return 'ID:' . $this->id . '(' . $this->x . ',' . $this->y . ')';\n  }\n\n  public function serialize(): string {\n    return serialize(array('y' => $this->y, 'x' => $this->x));\n  }\n\n  public function unserialize(string $sdata): void {\n    $data = unserialize($sdata);\n    $this->x = $data['x'];\n    $this->y = $data['y'];\n    $this->id = self::$nextId++;\n  }\n}\n"
  },
  {
    "path": "tests/Serialization/Point.php.expectf",
    "content": "\nFatal error: Declaration of Graphics\\Point::unserialize() must be compatible with that of Serializable::unserialize() in %s/tests/Serialization/Point.php on line 5"
  },
  {
    "path": "tests/Serialization/serialize.php",
    "content": "<?hh // strict\n\nnamespace NS_serialize;\n\nrequire_once 'Point.php';\n\nfunction main(): void {\n  $p = new \\Graphics\\Point(2.0, 5.0);\n  echo \"\\$p: $p\\n\";\n\n  $s = serialize($p);\n  var_dump($s);\n\n  $v = unserialize($s);\n  var_dump($v);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Serialization/serialize.php.expectf",
    "content": "\nFatal error: Declaration of Graphics\\Point::unserialize() must be compatible with that of Serializable::unserialize() in %s/tests/Serialization/Point.php on line 5"
  },
  {
    "path": "tests/Shapes/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Shapes/shapes.php",
    "content": "<?hh // strict\n\nnamespace NS_shapes;\n\nrequire_once 'shapes_rf.php';\n\nfunction f1(\\NS_shapes_rf\\st2a $p1): void {\n  echo \"----- dumping 'x' => int -----\\n\\n\";\n\n  var_dump($p1);\n}\n\nfunction main(): void {\n/*\n// yes, array string keys can not only be \"...\", can also contain subtitution stuff\n// testing, as double-quoted strings keys are rejected in Shape definitions.\n\n  $q = 'QQQ';\n  $a = array('x' => 10, \"y\" => 20, \"x\\n$q\\tx\" => 30,\n<<<ID\nXXX\nID\n => 40, \n<<<'ID'\nYYY\nID\n => 50);\n  var_dump($a);\n*/\n\n  echo \"----------- Play ------------\\n\\n\";\n\n//  $key = 'x';\n//  f1(shape($key => 10));\t// gags: The field '' is missing\n\t\t\t\t// like the shape definition, key must be a string literal\n\n//  var_dump(\\NS_shapes_rf\\st4b_test2());\n\n  echo \"----------- Create some shape values ------------\\n\\n\";\n\n  $point1 = shape('x' => -3, 'y' => 6);\n  echo \"\\$point1 is \" . $point1['x'] . \"\\n\";\n//  echo \"\\$point1 instanceof Point is \" . \n//    (($point1 instanceof \\NS_shapes_rf\\Point) ? \"True\" : \"False\") . \"\\n\";\t// False\n\n/*\n// a key must be a string literal; apparently can't be a class constant\n\n// ???\techo \"\\$point1 is \" . $point1[\\NS_shapes_rf\\C::KEY1] . \"\\n\";\n\t// The field  is undefined *** WHY IS THIS?\n  $key = 'x';\n  echo \"\\$point1 is \" . $point1[$key] . \"\\n\";\t// The field  is undefined\n\n  echo \"\\$point1 is \" . $point1['z'] . \"\\n\";\t// The field z is undefined\n*/\n\n// Fatal error: syntax error, unexpected '[', expecting ',' or ';'\n\n//  echo \"shape(...)['y'] is \" . shape('x' => -3, 'y' => 6)['y'] . \"\\n\";\n\n  echo \"shape(...)['y'] is \" . (shape('x' => -3, 'y' => 6))['y'] . \"\\n\";\n\t// works with parens, but shouldn't need them\n\n  $str = \\NS_shapes_rf\\Point_toString($point1);\n  echo \"\\$point1 is $str\\n\";\n//  echo \"\\$point1 instanceof Point is \" . \n//    (($point1 instanceof \\NS_shapes_rf\\Point) ? \"True\" : \"False\") . \"\\n\";\t// False\n\n// The following function-call argument is incompatible with PointNT while alias is created using 'newtype'.\n// However, it's okay when 'type' used\n\n//  $str = \\NS_shapes_rf\\PointNT_toString($point1);\n//  echo \"\\$point1 is $str\\n\";\n\n  $str = \\NS_shapes_rf\\PointNT_toString(\\NS_shapes_rf\\PointNT_getOrigin());\n  echo \"Origin is $str\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Shapes/shapes.php.expect",
    "content": "----------- Play ------------\n\n----------- Create some shape values ------------\n\n$point1 is -3\nshape(...)['y'] is 6\n$point1 is (-3,6)\nOrigin is (0,0)"
  },
  {
    "path": "tests/Shapes/shapes_rf.php",
    "content": "<?hh // strict\n\nnamespace NS_shapes_rf;\n\n// ------------------------------------------------------------\n\nclass C {\n  const string KEY1 = 'x';\n  const int KEY2 = 3;\n  const bool KEY3 = true;\n  const num KEY4 = 2.5;\n}\n\n// ----------- Is a shape really a type? ------------\n/*\n// As the shape \"type\" CANNOT be used in the usual places, is it really a type?\n\nfunction CXf1(shape('x' => int, 'y' => int) $p1): void {}\nfunction CXf2(): shape('x' => int, 'y' => int) {}\n\nclass CX {\n  private shape('x' => int, 'y' => int) $p1;\n}\n*/\n\n// However, the following is OK\n\ntype Point = shape('x' => int, 'y' => int);\nfunction CYf1(Point $p1): void {}\nfunction CYf2(): Point { return shape('x' => 10, 'y' => 12); }\n\nclass CY {\n  private Point $p1 = shape('x' => 0, 'y' => 5);\n}\n\nfunction Point_toString(Point $p): string {\n  return '(' . $p['x'] . ',' . $p['y'] . ')';\n}\n\n// It looks like the 2 forms of name can't be mixed\n\n//function CYf3(): Point { return shape(C::KEY1 => 10, 'y' => 12); }\n\n// Can the order of fields in the literal differ from the shape-specifier?\n\nfunction CYf4(): Point { return shape('y' => 12, 'x' => 10); }\t// apparently, YES\n\n// Can a shape literal initialize fewer fields than exist? NO\n\n//function CYf5(): Point { return shape('x' => 10); }\t// The field 'y' is missing\n//function CYf6(): Point { return shape('y' => 12); }\t// The field 'x' is missing\n\n//type PointNT = shape('x' => int, 'y' => int);\nnewtype PointNT = shape('x' => int, 'y' => int);\n\nfunction PointNT_toString(PointNT $p): string {\n  return '(' . $p['x'] . ',' . $p['y'] . ')';\n}\n\nfunction PointNT_getOrigin(): PointNT {\n  return shape('x' => 0, 'y' => 0);\n}\n\n\n// ----------- Shape with no fields ------------\n\ntype st1 = shape();\t\t\t// can have no fields\n\n// ----------- Shapes with literal string keys ------------\n\ntype st2a = shape('x' => int);\t\t// can have 1 field with '-quoted string key\n//type st2b = shape('x'.'x' => int);\t// gags: key must be a literal NOT an expression\n\n//type st2c = shape(\"x\" => int);\t// gags on \"-quoted string: Expected string literal or class constant\n//type st2d = shape(\"x\\tx\\$\" => int);\t// gags too\n\n/*\n// can't use a heredoc literal \n// hhvm says at <<< line: Fatal error: syntax error, unexpected T_START_HEREDOC, expecting ')'\n\ntype st2e = shape(\n<<<ID\nXXX\nID\n => int);\n*/\n\n/*\n// can't use a nowdoc literal \n// hhvm says at <<< line: Fatal error: syntax error, unexpected T_START_HEREDOC, expecting ')'\n\ntype st2f = shape(\n<<<'ID'\nYYY\nID\n => int);\n*/\n\n// ----------- Shapes with string keys, but using class constants ------------\n\ntype st3a = shape(C::KEY1 => int);\t// OK; class constant of type string\nfunction st3a_test(): st3a { return shape(C::KEY1 => 88); }\n\n// Can I mix the 2 forms? Apparently not\n\n//type st3b = shape(C::KEY1 => int, 'y' => int);\t// Shape uses class constant as field name; But expected a literal string\n//type st3c = shape('y' => int, C::KEY1 => int);\t// Shape uses literal string as field name; But expected a class constant\n\n\n\n// ----------- Shapes with int keys ------------\n\n// There seems to be confusion about whether a key can have type int\n\n//type st4a = shape(3 => int);\t\t// gags: Expected string literal or class constant\ntype st4b = shape(C::KEY2 => int);\t// but can have an int key via class constant!!!\n//function st4b_test1(): st4b { return shape(3 => 99); }\t// gags: Expected string literal or class constant\nfunction st4b_test2(): st4b { return shape(C::KEY2 => 99); }\t// but can do it through a class constant\n\n//type st4c = shape('x' => int, 3 => int);\t// gags: Expected string literal or class constant\n//type st4d = shape('x' => int, C::KEY2 => int);\t// gags: Shape uses class constant as field name;\n\t\t\t\t\t\t//       But expected a literal string\n\n//type st5a = shape(true => int);\t// gags: Expected string literal or class constant\n//type st5b = shape(C::KEY3 => int);\t// gags: A shape field name must be an int or string; Not a bool\n\n//type st6a = shape(2.5 => int);\t// gags: Expected string literal or class constant\n//type st6b = shape(C::KEY4 => int);\t// gags: A shape field name must be an int or string; Not a num\n\n// ----------- Shapes with duplicate keys ------------\n\n//type st7a = shape('abc' => int,'abc' => int);\t\t// can't have duplicate keys\n//type st7b = shape('cde' => int,'cde' => float);\t// ditto\n\n// ----------- Shapes containing exotic types (why not?) ------------\n\ntype st8 = shape('n1' => (int, float),'n2' => ?(function (array<num>): bool));\n\n// ----------- Some examples of shape literals ------------\n\ntype Point3 = shape('x' => int, 'y' => int);\nfunction getY(): int { return 123; }\nfunction get_Point3(): Point3 {\n  $prevX = 10;\n  return shape('x' => $prevX, 'y' => getY());\n}\n\ntype IdSet = shape('id' => ?string, 'url' => ?string, 'count' => int);\nfunction get_IdSet(): IdSet {\n  return shape('id' => null, 'url' => null, 'count' => 0);\n}\n\n\n\n\n\n"
  },
  {
    "path": "tests/Shapes/shapes_rf.php.expect",
    "content": ""
  },
  {
    "path": "tests/Statements/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Statements/Iteration/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Statements/Iteration/do.php",
    "content": "<?hh // strict\n\nnamespace NS_do;\n\nfunction main(): void {\n  $i = 1;\n  do {\n    echo \"$i\\t\".($i * $i).\"\\n\";\t// output a table of squares\n    ++$i;\n  }\n  while ($i <= 10);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Statements/Iteration/do.php.expect",
    "content": "1\t1\n2\t4\n3\t9\n4\t16\n5\t25\n6\t36\n7\t49\n8\t64\n9\t81\n10\t100"
  },
  {
    "path": "tests/Statements/Iteration/for.php",
    "content": "<?hh // strict\n\nnamespace NS_for;\n\nfunction main(): void {\n  for ($i = 1; $i <= 10; ++$i) {\n    echo \"$i\\t\".($i * $i).\"\\n\";\t// output a table of squares\n  }\n\n// omit 1st and 3rd expressions\n\n  $i = 1;\n  for (; $i <= 10;) {\n    echo \"$i\\t\".($i * $i).\"\\n\";\t// output a table of squares\n    ++$i;\n  }\n\n// omit all 3 expressions\n\n  $i = 1;\n  for (;;) {\n    if ($i > 10)\n      break;\n    echo \"$i\\t\".($i * $i).\"\\n\";\t// output a table of squares\n    ++$i;\n  }\n\n//  use groups of expressions\n\n  for ($a = 100, $i = 1; ++$i, $i <= 10; ++$i, $a -= 10) {\n    echo \"$i\\t$a\\n\";\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Statements/Iteration/for.php.expect",
    "content": "1\t1\n2\t4\n3\t9\n4\t16\n5\t25\n6\t36\n7\t49\n8\t64\n9\t81\n10\t100\n1\t1\n2\t4\n3\t9\n4\t16\n5\t25\n6\t36\n7\t49\n8\t64\n9\t81\n10\t100\n1\t1\n2\t4\n3\t9\n4\t16\n5\t25\n6\t36\n7\t49\n8\t64\n9\t81\n10\t100\n2\t100\n4\t90\n6\t80\n8\t70\n10\t60"
  },
  {
    "path": "tests/Statements/Iteration/foreach.php",
    "content": "<?hh // strict\n\nnamespace NS_foreach;\n\nclass C {\n  public Vector<mixed> $pVect = Vector {-1, -2};\n  public Map<string, float> $pMap = Map {'a' => -3.5};\n  public Set<string> $pSet = Set {'a'};\n  public Pair<int, string> $pPair = Pair {-10, \"aaa\"};\n}\n\nfunction main(): void {\n  $c = new C();\n\n  echo \"=========== iterate over empty array =============\\n\";\n\n  $array = array();\n  foreach ($array as $a) {\n    echo $a . \"\\n\";\n  }\n\n  echo \"=========== iterate over array of strings =============\\n\";\n\n  $colors = array(\"red\", \"white\", \"blue\");\n  foreach ($colors as $color) {\n    echo $color . \"\\n\";\n  }\n//  echo $color . \"\\n\";\t// unlike PHP, this variable is no longer in scope\n\n// access each element's value and its element number\n\n  $colors = array(\"red\", \"white\", \"blue\");\n  foreach ($colors as $index => $color) {\n    echo \"Index: $index; Color: $color\\n\";\n    var_dump($index);\n  }\n//  echo \"Index: $index; Color: $color\\n\";\t// unlike PHP, these variables are no longer in scope\n\n  echo \"=========== iterate over some vectors of string =============\\n\";\n\n  $vect = Vector {};\n  foreach ($vect as $key => $value) {\n    echo \"Key: $key ; Value: $value\\n\";\n  }\n\n  $vect = Vector {\"red\", \"white\", \"blue\"};\n  foreach ($vect as $key => $value) {\n    echo \"Key: $key ; Value: $value\\n\";\n  }\n\n  $vect = ImmVector {\"red\", \"white\", \"blue\"};\n  foreach ($vect as $key => $value) {\n    echo \"Key: $key ; Value: $value\\n\";\n  }\n\n  echo \"=========== iterate over some maps of float =============\\n\";\n\n  $map = Map {};\n  foreach ($map as $key => $value) {\n    echo \"Key: $key ; Value: $value\\n\";\n  }\n\n  $map = Map {'a' => 1.234, 'xx' => 234.45, 'qqq' => -34.54};\n  foreach ($map as $key => $value) {\n    echo \"Key: $key ; Value: $value\\n\";\n  }\n\n  $map = ImmMap {'a' => 1.234, 'xx' => 234.45, 'qqq' => -34.54};\n  foreach ($map as $key => $value) {\n    echo \"Key: $key ; Value: $value\\n\";\n  }\n\n/*\n// Sets are not KeyedTraversable, so can't iterate over them.\n\n  echo \"=========== iterate over some sets of string =============\\n\";\n\n  $set = Set {\"red\", \"white\", \"blue\"};\n  foreach ($set as $key => $value) {\n    echo \"Key: $key; Value: $value\\n\";\n  }\n*/\n\n  echo \"=========== iterate over a pair of strings =============\\n\";\n\n  $pair = Pair {\"red\", \"green\"};\n  foreach ($pair as $key => $value) {\n//    echo \"Key: $key; Value: $value\\n\";\n    var_dump($key);\n    var_dump($value);\n  }\n\n  echo \"=========== Modify the local copy of an element's value =============\\n\";\n\n  $colors = array(\"red\", \"white\", \"blue\");\n  foreach ($colors as $color) {\n    echo $color . \"<-->\";\n    $color = \"black\";\n    echo $color . \"\\n\";\n  }\n  var_dump($colors);\n\n  echo \"=========== Modify the the actual element itself =============\\n\";\n\n  $colors = array(\"red\", \"white\", \"blue\");\n  // UNSAFE (can't really use a & in strict mode)\n  foreach ($colors as & $color) {  // note the &\n    echo $color . \"<-->\";\n    $color = \"black\";\n    echo $color . \"\\n\";\n  }\n  var_dump($colors);\n\n  echo \"=========== nested iterators =============\\n\";\n\n  $ary = array();\n  $ary[0][0] = \"abc\";\n  $ary[0][1] = \"ij\";\n  $ary[1][0] = \"mnop\";\n  $ary[1][1] = \"xyz\";\n\n  foreach ($ary as $e1) {\n    foreach ($e1 as $e2) {\n      echo \"  $e2\";\n    }\n    echo \"\\n\";\n  }\n\n  $a = array(array(10, 20), array(1.2, 4.5), array(true, \"abc\"));\n  foreach ($a as $key => $value) {\n    echo \"------\\n\";\n    var_dump($key);\n    var_dump($value);\n  }\n\n  $vect = Vector{Vector {10}, Vector {1.2, 4.5, 9.2}, Vector {true, \"abc\"}};\n  foreach ($vect as $key1 => $value1) {\n    echo \"Key: $key1\\n\";\n    foreach ($value1 as $key2 => $value2) {\n      echo \"\\tKey: $key2; Value: $value2\\n\";\n    }\n    echo \"\\n\";\n  }\n\n  echo \"=========== test use of list =============\\n\";\n\n  $a = array(array(10,20), array(1.2, 4.5), array(true, \"abc\"));\n  foreach ($a as $key => list($v1, $v2)) {\n    echo \"------\\n\";\n    var_dump($key);\n    var_dump($v1);\n    var_dump($v2);\n  }\n\n  echo \"=========== test use of a vector as recipient =============\\n\";\n\n  $a = array(Vector{10}, Vector{1.2, 4.5, 9.2}, Vector {true, \"abc\"});\n  foreach ($a as $key => $c->pVect) {\n    echo \"------\\n\";\n    var_dump($key);\n    var_dump($c->pVect);\n  }\n\n  echo \"=========== test use of a map as recipient =============\\n\";\n\n  $a = array(Map {'x' => 1.2, 'z' => 4.5, 'q' => 9.2}, Map { 'zz' => 22.1, 'cc' => -2.1 });\n  foreach ($a as $key => $c->pMap) {\n    echo \"------\\n\";\n    var_dump($key);\n    var_dump($c->pMap);\n  }\n\n  echo \"=========== test use of set as recipient =============\\n\";\n\n  $a = array(Set {\"red\", \"white\", \"blue\"}, Set {\"aa\", \"bb\"});\n  foreach ($a as $key => $c->pSet) {\n    echo \"------\\n\";\n    var_dump($key);\n    var_dump($c->pSet);\n  }\n\n  echo \"=========== test use of Pair as recipient =============\\n\";\n\n  $a = array(Pair { 2, \"red\" }, Pair { 9, \"white\" }, Pair { 1, \"blue\" });\n  foreach ($a as $key => $c->pPair) {\n    echo \"------\\n\";\n    var_dump($key);\n    var_dump($c->pPair[0]);\n    var_dump($c->pPair[1]);\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Statements/Iteration/foreach.php.expect",
    "content": "=========== iterate over empty array =============\n=========== iterate over array of strings =============\nred\nwhite\nblue\nIndex: 0; Color: red\nint(0)\nIndex: 1; Color: white\nint(1)\nIndex: 2; Color: blue\nint(2)\n=========== iterate over some vectors of string =============\nKey: 0 ; Value: red\nKey: 1 ; Value: white\nKey: 2 ; Value: blue\nKey: 0 ; Value: red\nKey: 1 ; Value: white\nKey: 2 ; Value: blue\n=========== iterate over some maps of float =============\nKey: a ; Value: 1.234\nKey: xx ; Value: 234.45\nKey: qqq ; Value: -34.54\nKey: a ; Value: 1.234\nKey: xx ; Value: 234.45\nKey: qqq ; Value: -34.54\n=========== iterate over a pair of strings =============\nint(0)\nstring(3) \"red\"\nint(1)\nstring(5) \"green\"\n=========== Modify the local copy of an element's value =============\nred<-->black\nwhite<-->black\nblue<-->black\narray(3) {\n  [0]=>\n  string(3) \"red\"\n  [1]=>\n  string(5) \"white\"\n  [2]=>\n  string(4) \"blue\"\n}\n=========== Modify the the actual element itself =============\nred<-->black\nwhite<-->black\nblue<-->black\narray(3) {\n  [0]=>\n  string(5) \"black\"\n  [1]=>\n  string(5) \"black\"\n  [2]=>\n  &string(5) \"black\"\n}\n=========== nested iterators =============\n  abc  ij\n  mnop  xyz\n------\nint(0)\narray(2) {\n  [0]=>\n  int(10)\n  [1]=>\n  int(20)\n}\n------\nint(1)\narray(2) {\n  [0]=>\n  float(1.2)\n  [1]=>\n  float(4.5)\n}\n------\nint(2)\narray(2) {\n  [0]=>\n  bool(true)\n  [1]=>\n  string(3) \"abc\"\n}\nKey: 0\n\tKey: 0; Value: 10\n\nKey: 1\n\tKey: 0; Value: 1.2\n\tKey: 1; Value: 4.5\n\tKey: 2; Value: 9.2\n\nKey: 2\n\tKey: 0; Value: 1\n\tKey: 1; Value: abc\n\n=========== test use of list =============\n------\nint(0)\nint(10)\nint(20)\n------\nint(1)\nfloat(1.2)\nfloat(4.5)\n------\nint(2)\nbool(true)\nstring(3) \"abc\"\n=========== test use of a vector as recipient =============\n------\nint(0)\nobject(HH\\Vector)#21 (1) {\n  [0]=>\n  int(10)\n}\n------\nint(1)\nobject(HH\\Vector)#22 (3) {\n  [0]=>\n  float(1.2)\n  [1]=>\n  float(4.5)\n  [2]=>\n  float(9.2)\n}\n------\nint(2)\nobject(HH\\Vector)#23 (2) {\n  [0]=>\n  bool(true)\n  [1]=>\n  string(3) \"abc\"\n}\n=========== test use of a map as recipient =============\n------\nint(0)\nobject(HH\\Map)#24 (3) {\n  [\"x\"]=>\n  float(1.2)\n  [\"z\"]=>\n  float(4.5)\n  [\"q\"]=>\n  float(9.2)\n}\n------\nint(1)\nobject(HH\\Map)#25 (2) {\n  [\"zz\"]=>\n  float(22.1)\n  [\"cc\"]=>\n  float(-2.1)\n}\n=========== test use of set as recipient =============\n------\nint(0)\nobject(HH\\Set)#26 (3) {\n  string(3) \"red\"\n  string(5) \"white\"\n  string(4) \"blue\"\n}\n------\nint(1)\nobject(HH\\Set)#27 (2) {\n  string(2) \"aa\"\n  string(2) \"bb\"\n}\n=========== test use of Pair as recipient =============\n------\nint(0)\nint(2)\nstring(3) \"red\"\n------\nint(1)\nint(9)\nstring(5) \"white\"\n------\nint(2)\nint(1)\nstring(4) \"blue\""
  },
  {
    "path": "tests/Statements/Iteration/while.php",
    "content": "<?hh // strict\n\nnamespace NS_while;\n\nfunction main(): void {\n  $i = 1;\n  while ($i <= 10) {\n    echo \"$i\\t\".($i * $i).\"\\n\";\t// output a table of squares\n    ++$i;\n  }\n\n  $count = 0;\n  $done = false;\n  while (true) {\n    if (++$count == 5)\n      $done = true;\n    echo $count.\"\\n\";\n    // ...\n    if ($done)\n      break;\t// break out of the while loop\n    // ...\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Statements/Iteration/while.php.expect",
    "content": "1\t1\n2\t4\n3\t9\n4\t16\n5\t25\n6\t36\n7\t49\n8\t64\n9\t81\n10\t100\n1\n2\n3\n4\n5"
  },
  {
    "path": "tests/Statements/Jump/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Statements/Jump/break.php",
    "content": "<?hh // strict\n\nnamespace NS_break;\n\nfunction main(): void {\n  for ($i = 1; $i <= 5; ++$i) {\n    echo \"\\$i = $i\\n\";\n    if ($i == 3)\n      break;\n  }\n\n  for ($i = 10; $i <= 40; $i +=10) {\n    echo \"\\n\\$i = $i: \";\n    switch($i) {\n    case 10: echo \"ten\"; break;\n    case 20: echo \"twenty\"; break;\n    case 30: echo \"thirty\"; break;\n    }\n    echo \"\\nJust beyond the switch\";\n  }\n  echo \"\\n----------\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Statements/Jump/break.php.expect",
    "content": "$i = 1\n$i = 2\n$i = 3\n\n$i = 10: ten\nJust beyond the switch\n$i = 20: twenty\nJust beyond the switch\n$i = 30: thirty\nJust beyond the switch\n$i = 40: \nJust beyond the switch\n----------"
  },
  {
    "path": "tests/Statements/Jump/continue.php",
    "content": "<?hh // strict\n\nnamespace NS_continue;\n\nfunction main(): void {\n  for ($i = 1; $i <= 5; ++$i) {\n    if (($i % 2) == 0)\n      continue;\n    echo \"$i is odd\\n\";\n  }\n/*\n// continue N/break N not supported\n\n  for ($i = 1; $i <= 5; ++$i) {\n    $j = 20;\n    while ($j > 0) {\n      if ((($j * $i) % 2) == 0) {\n        $j -= 3;\n        continue 1;\n      }\n      echo ($j * $i).\" is odd\\n\";\n      $j -= 5;\n    }\n    echo \"In for loop\\n\";\n  }\n*/\n\n// In PHP, 'continue;' inside a switch statement is equivalent to 'break;'. Hack does not \n// support this; use 'break' if that is what you meant.\n\n  for ($i = 10; $i <= 40; $i +=10) {\n    echo \"\\n\\$i = $i: \";\n    switch($i) {\n    case 10: echo \"ten\"; break;\n//    case 20: echo \"twenty\"; continue;\n    case 30: echo \"thirty\"; break;\n    }\n    echo \"\\nJust beyond the switch\";\n  }\n  echo \"\\n----------\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Statements/Jump/continue.php.expect",
    "content": "1 is odd\n3 is odd\n5 is odd\n\n$i = 10: ten\nJust beyond the switch\n$i = 20: \nJust beyond the switch\n$i = 30: thirty\nJust beyond the switch\n$i = 40: \nJust beyond the switch\n----------"
  },
  {
    "path": "tests/Statements/Selection/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Statements/Selection/if.php",
    "content": "<?hh // strict\n\nnamespace NS_if;\n\nfunction processTransaction(): void { echo \"Inside processTransaction\\n\"; }\nfunction postMessage(): void { echo \"Inside postMessage\\n\"; }\n\nclass Name {\n  private string $firstName = \"xxx\";\n  private string $lastName = \"yyy\";\n}\n\nfunction main(): void {\n// an ordinary if having 2 actions on true and none on false\n\n  $count = 5;\n  if ($count > 0) {\n    processTransaction();\n    postMessage();\n  }\n\n// despite the indenting that suggests the truepath has 2 statements, in the\n// absence of braces, the truepath is the first statement only. The second statement\n// is always executed.\n\n  if (0)\n    echo \"Line 1\\n\";\n    echo \"Line 2\\n\";\t// always executed\n\n// use if with all scalar types + array\n\n  $colors = array(\"red\", \"white\", \"blue\");\n  $scalarValueList = array(10, -100, 0, 1.234, 0.0, true, false, null, 'xx', \"\", $colors);\n\n  foreach ($scalarValueList as $e) {\n    if ($e) {\n      echo \">\" . (string)$e . \"< is true\\t\"; var_dump($e);\n    } else {\n      echo \">\" . (string)$e . \"< is false\\t\"; var_dump($e);\n    }\n  }\n\n// use if with an instance of a class\n\n  $aName = new Name();\n  var_dump($aName);\n\n  if ($aName) {\n    echo \">\\$aName< is true\\n\";\n  } else {\n    echo \">\\$aName< is false\\n\";\n  }\n\n// show that when elses are nested, an else matches the lexically nearest preceding if that is allowed by the syntax\n\n  if (1)\n    echo \"Path 1\\n\";\n    if (0)\n      echo \"Path 2\\n\";\n  else \t// this else does NOT go with the outer if\n      echo \"Path 3\\n\";\n\n  if (1) {\n    echo \"Path 1\\n\";\n    if (0)\n      echo \"Path 2\\n\";\n  } else \t// this else does go with the outer if\n    echo \"Path 3\\n\";\n\n// test elseif\n\n  $a = 10;\n  if ($a < 0)\n    ; // ...\n  elseif ($a == 0)\n    ; // ...\n  elseif ($a < 10)\n    ; // ...\n  else\n    ; // ...\n\n/*\n// alternate syntax is not supported\n\n  if ($a < 0)  : // ...\n    ++$a; // ...\n  endif  ; // ...\n\n  if ($a < 0)  : // ...\n    ++$a; // ...\n  else :\n    --$a; // ...\n  endif  ; // ...\n\n  if ($a < 0):\n    ; // ...\n  elseif ($a == 0)  :\n    ; // ...\n  elseif ($a < 10):\n    ; // ...\n  else:\n    ; // ...\n  endif;\n*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Statements/Selection/if.php.expectf",
    "content": "Inside processTransaction\nInside postMessage\nLine 2\n>10< is true\tint(10)\n>-100< is true\tint(-100)\n>0< is false\tint(0)\n>1.234< is true\tfloat(1.234)\n>0< is false\tfloat(0)\n>1< is true\tbool(true)\n>< is false\tbool(false)\n>< is false\tNULL\n>xx< is true\tstring(2) \"xx\"\n>< is false\tstring(0) \"\"\n\nNotice: Array to string conversion in %s/tests/Statements/Selection/if.php on line 37\n>Array< is true\tarray(3) {\n  [0]=>\n  string(3) \"red\"\n  [1]=>\n  string(5) \"white\"\n  [2]=>\n  string(4) \"blue\"\n}\nobject(NS_if\\Name)#1 (2) {\n  [\"firstName\":\"NS_if\\Name\":private]=>\n  string(3) \"xxx\"\n  [\"lastName\":\"NS_if\\Name\":private]=>\n  string(3) \"yyy\"\n}\n>$aName< is true\nPath 1\nPath 3\nPath 1"
  },
  {
    "path": "tests/Statements/Selection/switch.php",
    "content": "<?hh // strict\n\nnamespace NS_switch;\n\nfunction main(): void {\n  echo \"================= empty body ====================\\n\";\n\n// Can I have an empty body?\n\n  $v = 10;\n  switch ($v) {\t\t// yes\n  }\n/*\n  echo \"================= body containing only empty statements ====================\\n\";\n\n// presumably, body can be one or more empty statements\n\n  $v = 10;\n  switch ($v) {\n    ;\t\t// unlike PHP, not even 1 is permitted\n    //;\n    //;\n  }\n*/\n\n  echo \"================= default case only ====================\\n\";\n\n  $v = 10;\n  switch ($v) {\n  default:\n    echo \"default case: \\$v is $v\\n\";\n  }\n\n  echo \"================= general switch ====================\\n\";\n\n  $v = 10;\n  switch ($v) {\n  default:\n    // FALLTHROUGH\n    echo \"default case: \\$v is $v\\n\";\n    break;\t\t// break ends \"group\" of default statements\n  case 10:\n    // FALLTHROUGH\n    // FALLTHROUGH\n    echo \"case 10\\n\";\t// no break, so control drops into next label's \"group\"\n    // FALLTHROUGH\n  case 30:\n    // FALLTHROUGH\n    echo \"case 30\\n\";\t// no break, but then none is really needed either\n    //\t\treturn;\n  case 20:\n    echo \"case 20\\n\";\n    break; \t\t// break ends \"group\" of case 20 statements\n    // FALLTHROUGH\n  }\n\n  echo \"================= duplicate case values ====================\\n\";\n\n// Check duplicate case values: allowed; choses lexically first one\n\n  $v = 30;\n  switch ($v) {\n  case 30:\n    echo \"case 30-2\\n\";\n    break;\n  default:\n    echo \"default case: \\$v is $v\\n\";\n    break;\n  case 30:\n    echo \"case 30-1\\n\";\n    break;\n  }\n\n  echo \"================= multiple case candidates ====================\\n\";\n\n// chooses first match with equal value, 30 matches 30.0 before 30\n\n  $v = 30;\n  switch ($v) {\n  case 30.0:\t// <===== this case matches with 30\n    echo \"case 30.0\\n\";\n    break;\n  default:\n    echo \"default case: \\$v is $v\\n\";\n    break;\n  case 30:\t\t// <===== rather than this case matching with 30\n    echo \"case 30\\n\";\n    break;\n  }\n\n/* Unlike PHP, the case/default label terminator must be a :\n\n  echo \"================= terminating case/default labels with ; ====================\\n\";\n\n// ; is allowed in place of : at end of case/default label; can mix-n-match\n\n  $v = 10;\n  switch ($v) {\n  case 10;\t\t// <================ ;\n    echo \"case 10\\n\";\n    break;\n  case 20:\t\t// <================ :\n    echo \"case 20\\n\";\n    break;\n  default;\t\t// <================ ;\n    echo \"default case: \\$v is $v\\n\";\n    break;\n  }\n*/\n\n  echo \"================= strings for label values ====================\\n\";\n\n// use  strings for label values \n\n  $v = \"white\";\t// note the lower-case spelling\n  switch ($v) {\n  case \"White\":\n    echo \"case White\\n\";\n    break;\n  case \"Red\":\n    echo \"case Red\\n\";\n    break;\n  default:\n    echo \"default case: \\$v is $v\\n\";\n    break;\n  }\n\n  echo \"================= Booleans for label values ====================\\n\";\n\n// use Booleans for label values \n\n  $v = true;\n  switch ($v) {\n  case false:\n    echo \"case false\\n\";\n    break;\n  case true:\n   echo \"case true\\n\";\n   break;\n  default:\n    echo \"default case: \\$v is $v\\n\";\n    break;\n  }\n\n  echo \"================= expressions for label values ====================\\n\";\n\n// use expressions for label values \n\n  $v = 22;\n  $a = 1;\n  $b = 12;\n  switch ($v) {\n  case 10 + $b:\n    echo \"case 10 + $b\\n\";\n    break;\n  case (int)($v < $a):\t\t// cast needed; otherwise, label expression type incompatible\n \t\t\t\t// with switch expression type\n    echo \"case $v < $a\\n\";\n    break;\n  default:\n    echo \"default case: \\$v is $v\\n\";\n    break;\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Statements/Selection/switch.php.expect",
    "content": "================= empty body ====================\n================= default case only ====================\ndefault case: $v is 10\n================= general switch ====================\ncase 10\ncase 30\ncase 20\n================= duplicate case values ====================\ncase 30-2\n================= multiple case candidates ====================\ncase 30.0\n================= strings for label values ====================\ndefault case: $v is white\n================= Booleans for label values ====================\ncase true\n================= expressions for label values ====================\ncase 10 + 12"
  },
  {
    "path": "tests/Statements/expression_statement.php",
    "content": "<?hh // strict\n\nnamespace NS_expression_statement;\n\nfunction DoIt(): int { return 20; }\n\nfunction main(): void {\n  $i = 10;\t// $i is assigned the value 10; result (10) is discarded\n  ++$i;\t\t// $i is incremented; result (11) is discarded\n  $i++;\t\t// $i is incremented; result (11) is discarded\n  DoIt();\t\t// function DoIt is called; result (return value) is discarded\n\n  $i;\t\t// no side effects; result is discarded, so entirely vacuous\n  123;\t\t// likewise ...\n  34.5 * 12.6 + 11.987;\n  true;\n\n  while ($i-- > 0) {\n    ;\t\t// null statement\n  }\n\n  $i = 10;\n  while ($i-- > 0) {\n    continue;\t// in this context, equivalent to using a null statement\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n\n"
  },
  {
    "path": "tests/Statements/expression_statement.php.expect",
    "content": ""
  },
  {
    "path": "tests/Traits/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Traits/trait_implements_interface.php",
    "content": "<?hh // strict\n\nnamespace NS_trait_implements_interface;\n\ninterface I1 {\n  public function f(): void;\n}\n\ninterface I2 {\n  public function g(): void;\n}\n\ntrait T implements I1, I2 {\n  public function h(): void { $this->f(); }\n}\n\nclass C {\t\t\t// implicit implements clause\n  use T;\n  public function f(): void {}\n  public function g(): void {}\n}\n\nclass C2 implements I1, I2 {\t// explicit implements clause\n  use T;\n  public function f(): void {}\n  public function g(): void {}\n}"
  },
  {
    "path": "tests/Traits/trait_implements_interface.php.expect",
    "content": ""
  },
  {
    "path": "tests/Traits/trait_requirements.php",
    "content": "<?hh // strict\n\nnamespace NS_trait_requirements;\n\nclass C1 {\n  public function cf1(): void { }\n}\n\ninterface I1 {\n  public function if1(): void;\n}\n\ntrait T1 {\n  require extends C1;\n  require implements I1;\n  public function f(): void {\n    $this->cf1();\n    $this->if1();\n  }\n}\n\nclass C2 extends C1 implements I1 {\n  use T1;\n  public function if1(): void { }\n}\n\ntrait T2 {\n  public function f(): void {\n    $this->cf1();\n    $this->if1();\n  }\n  require implements I1;\n  require extends C1;\n}\n\nclass C3 extends C1 implements I1 {\n  use T2;\n  public function if1(): void { }\n}\n\n/*\nclass Cx {\n  use T1; // Error\n}\n*/\n\ninterface I2 {\n  public function if2(): void;\n}\n\ntrait T3 {\n  require implements I1;\n  require extends C1;\t\t// redundant, as C3 already extends C1, but permitted\n  require implements I2;\n  require implements I2;\t// redundant, but permitted\n  require extends C3;\n  require extends C3;\t\t// redundant, but permitted\n}\n\nclass C4 extends C3 implements I1, I2 {\n  use T3;\n  public function if1(): void { }\n  public function if2(): void { }\n}\n\n/*\ninterface Ix {\n  use Tx;\n}\n\ntrait Tx {\n  require implements Ix;\t// cyclic definition; not permitted\n}\n*/\n\n"
  },
  {
    "path": "tests/Traits/trait_requirements.php.expect",
    "content": ""
  },
  {
    "path": "tests/Traits/traits.php",
    "content": "<?hh // strict\n\nnamespace NS_traits;\n\n///*\ntrait T1 {}\t\t// allowed to be empty\n\nclass C1 { use T1; }\n\ntrait T2a {\n  public function f(): void {\n    echo \"Inside \" . __TRAIT__ . \"\\n\";\n    echo \"Inside \" . __CLASS__ . \"\\n\";\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n}\n//*/\n\n//*\ntrait T2b {\n  public function f(): void {\n    echo \"Inside \" . __TRAIT__ . \"\\n\";\n    echo \"Inside \" . __CLASS__ . \"\\n\";\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n}\n//*/\n\n///*\nclass C2Base {\n  public function f(): void { echo \"Inside \" . __METHOD__ . \"\\n\"; }\n}\n//*/\n/*\n\nclass C2Derived extends C2Base {\n//  use T2a, T2b\t// Hack gags on  \"{ ... }, so split into following 2 lines, but still gags\n  use T2a;\t// trait containing public function f(): void\n  use T2b {\t\t// trait containing public function f(): void\n    T2a::f insteadof T2b;\n\n    T2b::f as g;\t// allow otherwise hidden T2B::f to be seen through alias g\n    T2a::f as h;\t// allow T2a::f to also be seen through alias h\n\t\t\t// don't need qualifier prefix if f is unambiguous\n  }\n}\n*/\n\n///*\ntrait T3 {\n  public function m1(): void { echo \"Inside \" . __METHOD__ . \"\\n\"; }\n  protected function m2(): void { echo \"Inside \" . __METHOD__ . \"\\n\"; }\n  private function m3(): void { echo \"Inside \" . __METHOD__ . \"\\n\"; }\n  public function m4(): void { echo \"Inside \" . __METHOD__ . \"\\n\"; }\n}\n//*/\n\n/*\nclass C3 {\n// Hack gags on \"{ ... }\n\n  use T3 {\n    m1 as protected;\t\t// reduce visibility to future, derived classes\n    m2 as private;\n    m3 as public;\n    m3 as protected z3;\n  }\n}\n*/\n\n///*\ntrait Tx1 {\n  public function k(): void {\n    echo \"Inside \" . __TRAIT__ . \"\\n\";\n    echo \"Inside \" . __CLASS__ . \"\\n\";\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n}\n//*/\n\n///*\ntrait Tx2 {\n  public function m(): void {\n    echo \"Inside \" . __TRAIT__ . \"\\n\";\n    echo \"Inside \" . __CLASS__ . \"\\n\";\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n}\n//*/\n\n/*\ntrait T4 {\n  use Tx1, Tx2;\n\n// Hack gags on \"{ ... }\n\n  use T2a, T2b, T3 {\n    Tx1::k as kk;\n    T2a::f insteadof T2b;\n  }\n}\n/*/\n\n/*\nclass C4 {\n  use T4;\n}\n*/\n\n///*\ntrait T5 {\n  public static num $prop = -99;\n}\n//*/\n\n///*\nclass C5a {\n  use T5;\n}\n//*/\n\n///*\nclass C5b {\n  use T5;\n}\n//*/\n\n///*\ntrait T6 {\n  public function f(): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n\n    static $v = 0;\t\t\t// static is class-specific\n    echo \"\\$v = \" . $v++ . \"\\n\";\n  }\n}\n//*/\n\n///*\nclass C6a {\n  use T6;\n}\n//*/\n\n///*\nclass C6b {\n  use T6;\n}\n//*/\n\n///*\ntrait T7 {\n  public static int $pubs = 123;\n\n  public function f(): void {\n    echo \"Inside \" . __TRAIT__ . \"\\n\";\n    echo \"Inside \" . __CLASS__ . \"\\n\";\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    var_dump($this);\n  }\n\n  public static function g(): void {\n    echo \"Inside \" . __TRAIT__ . \"\\n\";\n    echo \"Inside \" . __CLASS__ . \"\\n\";\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n  }\n} \n//*/\n\n///*\ntrait T9a {\n  public function compute(): void { }\n}\n//*/\n\n///*\ntrait T9b {\n  public function compute(): void { }\n}\n//*/\n\n///*\ntrait T9c {\n  public function sort(): void { }\n}\n//*/\n\n/*\ntrait T9d {\n  use T9c;\n\n// Hack gags on \"{ ... }\n\n  use T9a, T9b {\n    T9a::compute insteadof T9b;\n    T9c::sort as private sorter;\n  }\n}\n*/\n\n///*\ntrait T10 {\n  private int $prop1 = 1000;\n  protected static int $prop2 = -987;\n//  var $prop3;\n  public function compute(): void {}\n  public static function getData(): void {}\n}\n//*/\n\nfunction main(): void {\n  echo \"=== display some __***__ values ===\\n\\n\";\n\n//  echo \"Inside >\" . __TRAIT__ . \"<\\n\";\n//  echo \"Inside >\" . __CLASS__ . \"<\\n\";\n  echo \"Inside >\" . __METHOD__ . \"<\\n\";\n  echo \"Inside >\" . __FUNCTION__ . \"<\\n\";\n/*\n  echo \"\\n=== Play with C2Derived ===\\n\\n\";\n\n  $c2 = new C2Derived();\n\n  echo \"-------\\n\";\n  $c2->f();\t\t// call T2a::f\n\n  echo \"-------\\n\";\n  $c2->g();\t\t// call T2b::f via its alias g\n\n  echo \"-------\\n\";\n  $c2->h();\t\t// call T2a::f via its alias h\n*/\n/*\n  echo \"\\n=== Play with C3 ===\\n\\n\";\n\n// confirmed that lookup starts with current class, then trait(s), then base classes\n\n  $c3 = new C3();\n//  $c3->m1();\t\t// accessible, by default, but not once protected\n//  $c3->m2();\t\t// inaccessible, by default\n  $c3->m3();\t\t\t// inaccessible, by default\n  $c3->m4();\t\t\t// accessible, by default\n*/\n/*\n  echo \"\\n=== Play with C4 ===\\n\\n\";\n\n  $c4 = new C4();\n\n  echo \"-------\\n\";\n  $c4->f();\n\n  echo \"-------\\n\";\n  $c4->m1();\n\n  echo \"-------\\n\";\n  $c4->k();\n\n  echo \"-------\\n\";\n  $c4->m();\n*/\n///*\n  echo \"\\n=== Play with C5a and C5b ===\\n\\n\";\n\n  C5a::$prop = 123;\n  C5b::$prop = 43.56;\n  echo C5a::$prop . \"\\n\";\t// ==> 123\n  echo C5b::$prop . \"\\n\";\t// ==> 43.56\n//*/\n///*\n  echo \"\\n=== Play with C6a ===\\n\\n\";\n\n  $v1 = new C6a();\n  $v1->f();\t\t// method run twice with same $v\n  $v1->f();\n//*/\n///*\n  echo \"\\n=== Play with C6b ===\\n\\n\";\n\n  $v2 = new C6b();\n  $v2->f();\t\t// method run three times with a different $v\n  $v2->f();\n  $v2->f();\n//*/\n///*\n  echo \"\\n=== Play with T7 ===\\n\\n\";\n\n// Hack gags on this, but it's already \"non-standard\" in PHP\n//  T7::f(); \t// calls f like a static function with class name being the trait name\n\n  echo \"-------\\n\";\n\n  T7::g(); \n//*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Traits/traits.php.expect",
    "content": "=== display some __***__ values ===\n\nInside >NS_traits\\main<\nInside >NS_traits\\main<\n\n=== Play with C5a and C5b ===\n\n123\n43.56\n\n=== Play with C6a ===\n\nInside NS_traits\\T6::f\n$v = 0\nInside NS_traits\\T6::f\n$v = 1\n\n=== Play with C6b ===\n\nInside NS_traits\\T6::f\n$v = 0\nInside NS_traits\\T6::f\n$v = 1\nInside NS_traits\\T6::f\n$v = 2\n\n=== Play with T7 ===\n\n-------\nInside NS_traits\\T7\nInside NS_traits\\T7\nInside NS_traits\\T7::g"
  },
  {
    "path": "tests/Tuples/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Tuples/tuples.php",
    "content": "<?hh // strict\n\nnamespace NS_tuples;\n\nclass C {\n  private ?(int, (string, float)) $prop = null;\n}\n\nfunction f1((int, string) $p): void {\n  var_dump($p);\n}\n\nfunction f2(): (bool, array<int>, float) {\n  return tuple(true, array(99, 88, 77), 10.5);\n}\n\nfunction ft1((int, int) $p1): void {}\nfunction ft2(): (int, int) { return tuple(10, 20); }\n\nfunction main(?int $p1 = 123): void {\n//  $t1 = tuple();\t// must have at least 1 element\n  $t1 = tuple(10);\t// while can't declare a tuple type with only 1 element, can create a 1-element tuple\n\n//  $t1 = tuple('a' => 5, 6 => 7);\t// only (implied) int keys are allowed\n\n//  $t1 = tuple(2 => 5, 6 => 7);\t// can't specify index numbers\n\n  $t2 = tuple(10, true, 2.3, 10, 'abc', null, $p1, array(2, $p1), Vector {}, new C());\n  var_dump($t2);\n\n//  foreach ($t2 => $key as $value) { }\t//\tcan't iterate over a tuple\n\n//  $i = 0;\n//  echo \"\\$t2[0] = \" . $t2[$i] . \"\\n\";\t// tuple index must be an integer literal\n\n  echo \"\\$t2[0] = >\" . $t2[0] . \"<\\n\";\n  echo \"\\$t2[4] = >\" . $t2[4] . \"<\\n\";\n//  echo \"\\$t2[12] = >\" . $t2[12] . \"<\\n\";\n//  echo \"\\$t2[-2] = >\" . $t2[-2] . \"<\\n\";\n}\n\n//main(null);"
  },
  {
    "path": "tests/Tuples/tuples.php.expect",
    "content": ""
  },
  {
    "path": "tests/Types/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Types/Issue_109.php",
    "content": "<?hh // strict\n\nnamespace NS_Issue_109;\n\nclass C {}\n\nfunction test(): void {\n  $c = new C();\n  $v = $c instanceof C::class;\t// checker allows, but HHVM doesn't\n} \n\n//test();"
  },
  {
    "path": "tests/Types/Issue_109.php.expectf",
    "content": "\nFatal error: syntax error, unexpected T_CLASS, expecting T_VARIABLE or T_PIPE_VAR or '$' in %s/tests/Types/Issue_109.php on line 9"
  },
  {
    "path": "tests/Types/Issue_110.php",
    "content": "<?hh // strict\n\nnamespace Issue_110;\n\nclass C {\n  public static classname<C> $p1 = C::class;\n  public static string $str = 'Issue_110\\C';\n\n  public static function sf1(): void {\n    var_dump(C::$str == C::$p1);\t// value-equality\n  }\n  public static function sf2(): void {\n    var_dump(C::$str === C::$p1);\t// same-type-and-value-equality\n  }\n}\n\nfunction main(): void {\n  C::sf1();\n  C::sf2();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();"
  },
  {
    "path": "tests/Types/Issue_110.php.expect",
    "content": "bool(true)\nbool(true)"
  },
  {
    "path": "tests/Types/Testfile.txt",
    "content": "Once upon a time,\nin a land\nfar,   \nfar away,  \nthere lived an ogre called Big Bad Bruce.\n"
  },
  {
    "path": "tests/Types/arraykey.php",
    "content": "<?hh // strict\n\nnamespace NS_arraykey;\n\nclass C {\n  const arraykey KEY = 100;\n  private arraykey $prop = 'zzz';\n\n  public function setProp(arraykey $val): void {\n    $this->prop = $val;\n  }\n\n  public function getProp(): arraykey {\n    return $this->prop;\n  }\n\n  public function __construct() {\n    echo \"arraykey \" . $this->prop . (is_int($this->prop) ? \" is int\\n\" : \" is string\\n\");\n\n    $this->prop = 20;\n    echo \"arraykey \" . $this->prop . (is_int($this->prop) ? \" is int\\n\" : \" is string\\n\");\n\n    $this->prop = 'red';\n    echo \"arraykey \" . $this->prop . (is_int($this->prop) ? \" is int\\n\" : \" is string\\n\");\n  }\n}\n\nfunction main (): void {\n  $c = new C();\n  $val = $c->getProp();\n\n//  $q = $val + 10;\t// checker can't be sure teh arraykey is currently an int\n\n  if (is_int($val)) {\n    $q = $val + 10;\n  } else {\n// Checker reports: This is not a container, this is an array key (int/string)\n// It appears to not be able to deduce the type must be string; however, the true of the is_string (below) works.\n//  echo \"First character of string is \" . $val[0] . \"\\n\";\n  }\n\n  if (is_string($val)) {\n    echo \"First character of string is \" . $val[0] . \"\\n\";\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/arraykey.php.expect",
    "content": "arraykey zzz is string\narraykey 20 is int\narraykey red is string\nFirst character of string is r"
  },
  {
    "path": "tests/Types/arrays.php",
    "content": "<?hh // strict\n\nnamespace NS_arrays2;\n\nclass C2a {}\nclass C2b extends C2a {}\nclass C2c extends C2b {}\n\nclass C3 {}\n\ninterface I {}\nclass C4a implements I {}\nclass C4b implements I {}\n\nclass Button {}\nclass CustomButton extends Button {}\n\ninterface MyCollection {}\nclass MyList implements MyCollection {}\nclass MyQueue implements MyCollection {}\n\nclass C1 {\n///*\n// use int or string key types\n\n  private array<string> $a_defint_string = array('a', 'b');\n  private array<int,string> $a_int_string = array('a', 'b');\n  private array<string,bool> $a_string_bool = array('X1' => true, 'X2' => false);\n//*/\n///*\n// use non-int/non-string key types\n\n  private array<float,int> $a_float_int = array(5.5 => 10, 5.6 => 20);\n  private array<bool,int> $a_bool_int = array(true => 10, false => 20);\n  private array<num,int> $a_num_int = array(5 => 10, 5.5 => 30);\n  private array<mixed,int> $a_mixed_int = array(5 => 10, null => 20, 5.5 => 30);\n//*/\n/*\n// The following is accepted, but one can never add any elements to it. Is there a good use for it?\n\n  private array<void> $a_void = array();\n\n// Discovered to be no longer accepted as of Jan 18, 2016\n\n*/\n/*\n// HHVM ==> SegFault\n//  private array<resource> $a_resource = array(STDIN, STDOUT);\n*/\n///*\n// for completeness, have int keys with values of each built-in type\n\n  private array<bool> $a_bool = array(true, false);\n  private array<int> $a_int = array(10, 20);\n  private array<float> $a_float = array(3.1, -2.4);\n  private array<num> $a_num = array(5.4, 234);\n  private array<string> $a_string = array('a', 'b');\n  private array<mixed> $a_mixed = array(10, 'b', false);\n  private array<array<int>> $a_a_int = array(array(10,20), array(2,3));\n  private array<resource> $a_resource;\n//*/\n///*\n// have int keys with values of each nullable type\n\n  private array<?bool> $a_nbool = array(true, null);\n  private array<?int> $a_nint = array(10, null);\n  private array<?float> $a_nfloat = array(3.1, null);\n  private array<?num> $a_nnum = array(5.4, null);\n  private array<?string> $a_nstring = array('a', null);\n  private array<mixed> $a_nmixed = array(10, 'b', null);\n//*/\n///*\n// Have element value types that are from an inheritance heirarchy\n\n  private array<C2a> $a_C2a = array();\n  private array<C2b> $a_C2b = array();\n  private array<C2c> $a_C2c = array();\n//*/\n///*\n// Have element value types that are classes implementing the same interface\n\n  private array<I> $a_iI = array();\n//*/\n///*\n// use map-like arrays, and compare with vector-like arrays\n\n  private array<int> $a_int1 = array(10, 20);\n\n// a vector-like array is not compatible with a map-like array\n//  private array<int> $a_int2 = array(0 => 10, 1 => 20);\n\n// in an array initializer, can't mix implied key and explicit key\n//  private array<int,int> $a_int2 = array(0 => 10, 20);\n\n  private array<int,int> $a_int2 = array(0 => 10, 1 => 20);\n  private array<int,int> $a_int3 = array(1 => 20, 0 => 10);\n  private array<int,int> $a_int4 = array(5 => 20, -1 => 10);\n//*/\n  public function __construct() {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n///*\n    $this->a_defint_string = array('a', 'b');\n    $this->a_int_string = array('a', 'b');\n    $this->a_string_bool = array('X1' => true, 'X2' => false);\n    $this->a_float_int = array(5.5 => 10, 5.6 => 20);\n    $this->a_bool_int = array(true => 10, false => 20);\n    $this->a_num_int = array(5 => 10, 5.5 => 30);\n    $this->a_mixed_int = array(5 => 10, false => 20, null => 30);\n\n    $this->a_bool = array(true, false);\n    $this->a_int = array(10, 20);\n    $this->a_float = array(3.1, -2.4);\n    $this->a_num = array(5.4, 234);\n    $this->a_string = array('a', 'b');\n    $this->a_mixed = array(10, 'b', false);\n    $this->a_a_int = array(array(10,20), array(2,3));\n    $this->a_resource = array(STDIN, STDOUT);\n\n    $this->a_nbool = array(true, null);\n    $this->a_nint = array(10, null);\n    $this->a_nfloat = array(3.1, null);\n    $this->a_nnum = array(5.4, null);\n    $this->a_nstring = array('a', null);\n    $this->a_nmixed = array(10, 'b', null);\n\n// array type C2a exactly matches that of #1, #2, and #3\n    $this->a_C2a = array(new C2a(), new C2a(), new C2a());\n\n// array type C2a exactly matches #1, and is a base type of #2 and #3\n    $this->a_C2a = array(new C2a(), new C2b(), new C2c());\n\n// array type C2a is a base type of #1, #2, and #3\n    $this->a_C2a = array(new C2b(), new C2b(), new C2b());\n\n// array type C2a is a base type of #1, #2, and #3\n    $this->a_C2a = array(new C2c(), new C2c(), new C2c());\n\n// array type C2b exactly matches that of #1, #2, and #3\n    $this->a_C2b = array(new C2b(), new C2b(), new C2b());\n\n// array type C2c exactly matches that of #1, #2, and #3\n    $this->a_C2c = array(new C2c(), new C2c(), new C2c());\n\n// array type C2b exactly matches that of #1, #2, and is the base of #3\n    $this->a_C2b = array(new C2b(), new C2b(), new C2c());\n\n    $this->a_mixed = array(10, 'b', false, new C2b(), new C2c(), new C3());\n\n// Both classes implement interface I\n    $this->a_iI = array(new C4a(), new C4b());\n//*/\n  }\n\n  private function f(): void {\n//    $this->a_int = array(10, 20);\n//    $this->a_num = array(10, 20);\n//    $this->a_mixed = array(10, 20);\n\n//    $this->a_num = array(10, 20.5);\n//    $this->a_mixed = array(10, 20.5);\n  }\n\n  public function test_conversions(\n    array<bool> $p_a_bool1,\n    array<bool> $p_a_bool2,\n    array<int> $p_a_int1,\n    array<int> $p_a_int2\n  ): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n\n    $v = (bool)$p_a_bool1;\n    echo \"result of (bool) = $v\\n\";\n    $v = (bool)$p_a_bool2;\n    echo \"result of (bool) = $v\\n\";\n\n    $v = (int)$p_a_int1;\n    echo \"result of (int) = $v\\n\";\n    $v = (int)$p_a_int2;\n    echo \"result of (int) = $v\\n\";\n\n    $v = (string)$p_a_int1;\n    echo \"result of (string) = \"; var_dump($v);\n    $v = (string)$p_a_int2;\n    echo \"result of (string) = \"; var_dump($v);\n    $v = (string)$p_a_bool2;\n    echo \"result of (string) = \"; var_dump($v);\n\n// Can't cast to a typed array type\n//$v = (array<bool>)$p_a_bool1;\n\n/*\n// Unbound name: NS_arrays\\object\n\n    $v = (object)$p_a_bool2;\n    echo \"result of (object) = \"; var_dump($v); print_r($v);\n    $v = (object)$p_a_int2;\n    echo \"result of (object) = \"; var_dump($v); print_r($v);\n*/\n  }\n\n  public function test_intrinsics(array<int> $p): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n\n    var_dump($p);\n    list($min, $max, $avg) = $p;\n    echo \"\\$min = $min, \\$max = $max, \\$avg = $avg\\n\";\n  }\n\n  public function array_proc(\n    array<int> $p1, array<int> $p2,\n    array<float> $p3, array<num> $p4,\n    array<Button> $p5, array<CustomButton> $p6): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n\n    $v = $p1 + $p2;\n    echo \"result of p1+p2 = \"; var_dump($v);\n\n// can't concat 2 arrays of different types; good\n\n//    $v = $p1 + $p3;\n//    echo \"result of p1+p3 = \"; var_dump($v);\n\n//    $v = $p2 + $p3;\n//    echo \"result of p2+p3 = \"; var_dump($v);\n\n//    $v = $p4 + $p1;   // array<num> + array<int> disallowed\n//    $v = $p4 + $p3;   // array<num> + array<float> disallowed\n\n//    $v = $p5 + $p6;   // array<Button> + array<CustomButton> disallowed\n\n    $v = $p1 < $p2;\n    echo \"result of p1<p2 = \"; var_dump($v);\n    $v = $p1 <= $p2;\n    echo \"result of p1<=p2 = \"; var_dump($v);\n    $v = $p1 > $p2;\n    echo \"result of p1>p2 = \"; var_dump($v);\n    $v = $p1 >= $p2;\n    echo \"result of p1>=p2 = \"; var_dump($v);\n    $v = $p1 != $p2;\n    echo \"result of p1!=p2 = \"; var_dump($v);\n\n// can't compare 2 arrays of different types; good\n//    $v = $p1 < $p3;\n//    $v = $p1 <= $p3;\n//    $v = $p1 > $p3;\n//    $v = $p1 >= $p3;\n\n    $v = $p1 == $p2;\n    echo \"result of p1==p2 = $v\\n\";\n    $v = $p1 != $p2;\n    echo \"result of p1!=p2 = $v\\n\";\n//    $v = $p1 <> $p2;    // alternate form of not-equal is not supported\n    $v = $p1 === $p2;\n    echo \"result of p1===p2 = $v\\n\";\n    $v = $p1 !== $p2;\n    echo \"result of p1!==p2 = $v\\n\";\n\n    $v = $p1 == $p3;\n    echo \"result of p1==p3 = $v\\n\";\n    $v = $p1 != $p3;\n    echo \"result of p1!=p3 = $v\\n\";\n    $v = $p1 === $p3;\n    echo \"result of p1===p3 = $v\\n\";\n    $v = $p1 !== $p3;\n    echo \"result of p1!==p3 = $v\\n\";\n\n    $v = $p1;\n    echo \"\\$v[0] = \" . $v[0] . \"\\n\";\n// can't subscript a vector-like array with a non-int key\n//    echo \"\\$v['x']  = \" . $v['x'] . \"\\n\";\n//    echo \"\\$v[0.5]  = \" . $v[0.5] . \"\\n\";\n//    echo \"\\$v[true] = \" . $v[true] . \"\\n\";\n//    echo \"\\$v[null] = \" . $v[null] . \"\\n\";\n\n    var_dump($v);\n    $v[] = 123;\n    var_dump($v);\n    $v[] = 456;\n    var_dump($v);\n    $v[1] = 333;\n    var_dump($v);\n    $v[-5] = -23;\t\t// surprise! Lets me go outside the int-vector element range\n    var_dump($v);\n    $v[100] = 4444;\n    var_dump($v);\n  }\n}\n\nfunction main(): void {\n  echo \"================= Class C1 ===================\\n\\n\";\n\n  $c1 = new C1();\n  var_dump($c1);\n\n  echo \"================= Class C1::test_conversions ===================\\n\\n\";\n\n  $c1->test_conversions(\n    array(), array(true, false),\n    array(), array(10,20)\n  );\n\n  echo \"================= Class C1::test_intrinsics ===================\\n\\n\";\n\n  $c1->test_intrinsics(\n    array(0, 100, 67)\n  );\n\n  echo \"================= Class C1::array_proc ===================\\n\\n\";\n\n  $c1->array_proc(\n    array(66),\n    array(100, 200),\n    array(1.1, 2.2, 3.3),\n    array(1, 2.5),\n    array(new Button()), array(new CustomButton()));\n\n  echo \"================= Class C5 ===================\\n\\n\";\n\n  var_dump(new C5());\n\n/*\n  echo \"================= unset ===================\\n\\n\";\n\n// Unbound name: NS_arrays\\unset\n\n  $v = array(10, 20, 30);\n  unset($v[0]);\n\n  $v = array('a' => 10, 'b' => 20);\n  unset($v[0]);\n*/\n}\n\nclass C5 {\n  private array<string> $colorsV = array(\"red\", \"white\", \"blue\");\n  private array<int, string> $colorsM = array(\"red\", \"white\", \"blue\");\n  private array<int, string> $colorsM2 = array(0 => \"red\", 1 => \"white\", 2 => \"blue\");\n  private array<int, string> $colorsM3 = array(2 => \"blue\", 0 => \"red\", 1 => \"white\");\n\n  private array<string, bool> $flags = array(\"F1\"=>true,\"F2\"=>false,\"F3\"=>false,\"F4\"=>true,);\n\n  private array<num> $measurements = array(10, 25.55);\n  private array<int, mixed> $items = array(true, 123, \"red\", null);\n  private array<mixed, mixed> $things = array('X' => 10, 2 => true);\n\n  private array<Button> $buttons = array();\n  private array<MyCollection> $collections = array();\n\n  public function __construct() {\n    $this->buttons = array(new Button(), new CustomButton());\n    $this->collections = array(new MyList(), new MyQueue());\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/arrays.php.expectf",
    "content": "================= Class C1 ===================\n\nInside NS_arrays2\\C1::__construct\nobject(NS_arrays2\\C1)#1 (29) {\n  [\"a_defint_string\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    string(1) \"a\"\n    [1]=>\n    string(1) \"b\"\n  }\n  [\"a_int_string\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    string(1) \"a\"\n    [1]=>\n    string(1) \"b\"\n  }\n  [\"a_string_bool\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [\"X1\"]=>\n    bool(true)\n    [\"X2\"]=>\n    bool(false)\n  }\n  [\"a_float_int\":\"NS_arrays2\\C1\":private]=>\n  array(1) {\n    [5]=>\n    int(20)\n  }\n  [\"a_bool_int\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [1]=>\n    int(10)\n    [0]=>\n    int(20)\n  }\n  [\"a_num_int\":\"NS_arrays2\\C1\":private]=>\n  array(1) {\n    [5]=>\n    int(30)\n  }\n  [\"a_mixed_int\":\"NS_arrays2\\C1\":private]=>\n  array(3) {\n    [5]=>\n    int(10)\n    [0]=>\n    int(20)\n    [\"\"]=>\n    int(30)\n  }\n  [\"a_bool\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    bool(true)\n    [1]=>\n    bool(false)\n  }\n  [\"a_int\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    int(10)\n    [1]=>\n    int(20)\n  }\n  [\"a_float\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    float(3.1)\n    [1]=>\n    float(-2.4)\n  }\n  [\"a_num\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    float(5.4)\n    [1]=>\n    int(234)\n  }\n  [\"a_string\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    string(1) \"a\"\n    [1]=>\n    string(1) \"b\"\n  }\n  [\"a_mixed\":\"NS_arrays2\\C1\":private]=>\n  array(6) {\n    [0]=>\n    int(10)\n    [1]=>\n    string(1) \"b\"\n    [2]=>\n    bool(false)\n    [3]=>\n    object(NS_arrays2\\C2b)#23 (0) {\n    }\n    [4]=>\n    object(NS_arrays2\\C2c)#24 (0) {\n    }\n    [5]=>\n    object(NS_arrays2\\C3)#25 (0) {\n    }\n  }\n  [\"a_a_int\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    array(2) {\n      [0]=>\n      int(10)\n      [1]=>\n      int(20)\n    }\n    [1]=>\n    array(2) {\n      [0]=>\n      int(2)\n      [1]=>\n      int(3)\n    }\n  }\n  [\"a_resource\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    resource(1) of type (stream)\n    [1]=>\n    resource(2) of type (stream)\n  }\n  [\"a_nbool\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    bool(true)\n    [1]=>\n    NULL\n  }\n  [\"a_nint\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    int(10)\n    [1]=>\n    NULL\n  }\n  [\"a_nfloat\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    float(3.1)\n    [1]=>\n    NULL\n  }\n  [\"a_nnum\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    float(5.4)\n    [1]=>\n    NULL\n  }\n  [\"a_nstring\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    string(1) \"a\"\n    [1]=>\n    NULL\n  }\n  [\"a_nmixed\":\"NS_arrays2\\C1\":private]=>\n  array(3) {\n    [0]=>\n    int(10)\n    [1]=>\n    string(1) \"b\"\n    [2]=>\n    NULL\n  }\n  [\"a_C2a\":\"NS_arrays2\\C1\":private]=>\n  array(3) {\n    [0]=>\n    object(NS_arrays2\\C2c)#11 (0) {\n    }\n    [1]=>\n    object(NS_arrays2\\C2c)#12 (0) {\n    }\n    [2]=>\n    object(NS_arrays2\\C2c)#13 (0) {\n    }\n  }\n  [\"a_C2b\":\"NS_arrays2\\C1\":private]=>\n  array(3) {\n    [0]=>\n    object(NS_arrays2\\C2b)#20 (0) {\n    }\n    [1]=>\n    object(NS_arrays2\\C2b)#21 (0) {\n    }\n    [2]=>\n    object(NS_arrays2\\C2c)#22 (0) {\n    }\n  }\n  [\"a_C2c\":\"NS_arrays2\\C1\":private]=>\n  array(3) {\n    [0]=>\n    object(NS_arrays2\\C2c)#17 (0) {\n    }\n    [1]=>\n    object(NS_arrays2\\C2c)#18 (0) {\n    }\n    [2]=>\n    object(NS_arrays2\\C2c)#19 (0) {\n    }\n  }\n  [\"a_iI\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    object(NS_arrays2\\C4a)#26 (0) {\n    }\n    [1]=>\n    object(NS_arrays2\\C4b)#27 (0) {\n    }\n  }\n  [\"a_int1\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    int(10)\n    [1]=>\n    int(20)\n  }\n  [\"a_int2\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [0]=>\n    int(10)\n    [1]=>\n    int(20)\n  }\n  [\"a_int3\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [1]=>\n    int(20)\n    [0]=>\n    int(10)\n  }\n  [\"a_int4\":\"NS_arrays2\\C1\":private]=>\n  array(2) {\n    [5]=>\n    int(20)\n    [-1]=>\n    int(10)\n  }\n}\n================= Class C1::test_conversions ===================\n\nInside NS_arrays2\\C1::test_conversions\nresult of (bool) = \nresult of (bool) = 1\nresult of (int) = 0\nresult of (int) = 1\n\nNotice: Array to string conversion in %s/tests/Types/arrays.php on line 181\nresult of (string) = string(5) \"Array\"\n\nNotice: Array to string conversion in %s/tests/Types/arrays.php on line 183\nresult of (string) = string(5) \"Array\"\n\nNotice: Array to string conversion in %s/tests/Types/arrays.php on line 185\nresult of (string) = string(5) \"Array\"\n================= Class C1::test_intrinsics ===================\n\nInside NS_arrays2\\C1::test_intrinsics\narray(3) {\n  [0]=>\n  int(0)\n  [1]=>\n  int(100)\n  [2]=>\n  int(67)\n}\n$min = 0, $max = 100, $avg = 67\n================= Class C1::array_proc ===================\n\nInside NS_arrays2\\C1::array_proc\nresult of p1+p2 = array(2) {\n  [0]=>\n  int(66)\n  [1]=>\n  int(200)\n}\nresult of p1<p2 = bool(true)\nresult of p1<=p2 = bool(true)\nresult of p1>p2 = bool(false)\nresult of p1>=p2 = bool(false)\nresult of p1!=p2 = bool(true)\nresult of p1==p2 = \nresult of p1!=p2 = 1\nresult of p1===p2 = \nresult of p1!==p2 = 1\nresult of p1==p3 = \nresult of p1!=p3 = 1\nresult of p1===p3 = \nresult of p1!==p3 = 1\n$v[0] = 66\narray(1) {\n  [0]=>\n  int(66)\n}\narray(2) {\n  [0]=>\n  int(66)\n  [1]=>\n  int(123)\n}\narray(3) {\n  [0]=>\n  int(66)\n  [1]=>\n  int(123)\n  [2]=>\n  int(456)\n}\narray(3) {\n  [0]=>\n  int(66)\n  [1]=>\n  int(333)\n  [2]=>\n  int(456)\n}\narray(4) {\n  [0]=>\n  int(66)\n  [1]=>\n  int(333)\n  [2]=>\n  int(456)\n  [-5]=>\n  int(-23)\n}\narray(5) {\n  [0]=>\n  int(66)\n  [1]=>\n  int(333)\n  [2]=>\n  int(456)\n  [-5]=>\n  int(-23)\n  [100]=>\n  int(4444)\n}\n================= Class C5 ===================\n\nobject(NS_arrays2\\C5)#28 (10) {\n  [\"colorsV\":\"NS_arrays2\\C5\":private]=>\n  array(3) {\n    [0]=>\n    string(3) \"red\"\n    [1]=>\n    string(5) \"white\"\n    [2]=>\n    string(4) \"blue\"\n  }\n  [\"colorsM\":\"NS_arrays2\\C5\":private]=>\n  array(3) {\n    [0]=>\n    string(3) \"red\"\n    [1]=>\n    string(5) \"white\"\n    [2]=>\n    string(4) \"blue\"\n  }\n  [\"colorsM2\":\"NS_arrays2\\C5\":private]=>\n  array(3) {\n    [0]=>\n    string(3) \"red\"\n    [1]=>\n    string(5) \"white\"\n    [2]=>\n    string(4) \"blue\"\n  }\n  [\"colorsM3\":\"NS_arrays2\\C5\":private]=>\n  array(3) {\n    [2]=>\n    string(4) \"blue\"\n    [0]=>\n    string(3) \"red\"\n    [1]=>\n    string(5) \"white\"\n  }\n  [\"flags\":\"NS_arrays2\\C5\":private]=>\n  array(4) {\n    [\"F1\"]=>\n    bool(true)\n    [\"F2\"]=>\n    bool(false)\n    [\"F3\"]=>\n    bool(false)\n    [\"F4\"]=>\n    bool(true)\n  }\n  [\"measurements\":\"NS_arrays2\\C5\":private]=>\n  array(2) {\n    [0]=>\n    int(10)\n    [1]=>\n    float(25.55)\n  }\n  [\"items\":\"NS_arrays2\\C5\":private]=>\n  array(4) {\n    [0]=>\n    bool(true)\n    [1]=>\n    int(123)\n    [2]=>\n    string(3) \"red\"\n    [3]=>\n    NULL\n  }\n  [\"things\":\"NS_arrays2\\C5\":private]=>\n  array(2) {\n    [\"X\"]=>\n    int(10)\n    [2]=>\n    bool(true)\n  }\n  [\"buttons\":\"NS_arrays2\\C5\":private]=>\n  array(2) {\n    [0]=>\n    object(NS_arrays2\\Button)#29 (0) {\n    }\n    [1]=>\n    object(NS_arrays2\\CustomButton)#30 (0) {\n    }\n  }\n  [\"collections\":\"NS_arrays2\\C5\":private]=>\n  array(2) {\n    [0]=>\n    object(NS_arrays2\\MyList)#31 (0) {\n    }\n    [1]=>\n    object(NS_arrays2\\MyQueue)#32 (0) {\n    }\n  }\n}"
  },
  {
    "path": "tests/Types/arrays2.php",
    "content": "<?hh // strict\n\nnamespace NS_arrays;\n\nfunction v(): void {}\n\nclass C1 {}\nclass C2 {\n// the bool key initialiers are implicitly converted to int\n\n  public array<bool, bool> $pr_bool_bool = array(true => true, false => true, true => false, false => false);\n  public array<bool, int> $pr_bool_int = array(true => 25, false => -100);\n  public array<bool, float> $pr_bool_float = array(false => 12.34, true => -2e23);\n  public array<bool, num> $pr_bool_num = array(false => 12.34, true => 111);\n  public array<bool, string> $pr_bool_string = array(true => \"abc\", false => \"def\");\n//  public array<bool, void> $pr_bool_void = array();\t// previously allowed; not now\n\n// no errors from checker, but get hhvm error \n//  public array<bool, void> $pr_bool_void = array(true => v());\n\n// the int key initialiers are used as is\n\n  public array<int, bool> $pr_int_bool = array(5 => true, -2 => false);\n  public array<int, int> $pr_int_int = array(123 => 12, -1 => 1111);\n  public array<int, float> $pr_int_float = array(8 => 1.2, 2 => 3.4);\n  public array<int, num> $pr_int_num = array(5 => 12.34, -6 => 111);\n  public array<int, string> $pr_int_string = array(19 => \"abc\", -5 => \"def\");\n//  public array<int, void> $pr_int_void = array();\t// previously allowed; not now\n\n// the float key initialiers are implicitly converted to int\n\n  public array<float, bool> $pr_float_bool = array(1.2 => true, 1.4 => false, 1.5 => true);\n  public array<float, int> $pr_float_int = array(12.7 => 10, 8.3 => -5);\n  public array<float, float> $pr_float_float = array(11.2 => 1.2, -54.0 => 3.4);\n  public array<float, num> $pr_float_num = array(1.4 => 12.34, 19.4 => 111);\n  public array<float, string> $pr_float_string = array(4.5 => \"abc\", 9.88 => \"def\");\n//  public array<float, void> $pr_float_void = array();\t// previously allowed; not now\n\n// the num key initialiers are implicitly converted to int\n\n  public array<num, bool> $pr_num_bool = array(1.2 => true, 2 => false);\n  public array<num, int> $pr_num_int = array(12.7 => 10, 8 => -5);\n  public array<num, float> $pr_num_float = array(11.2 => 1.2, -54 => 3.4);\n  public array<num, num> $pr_num_num = array(1.4 => 12.34, 19 => 111);\n  public array<num, string> $pr_num_string = array(4.5 => \"abc\", 9 => \"def\");\n//  public array<num, void> $pr_num_void = array();\t// previously allowed; not now\n\n// the string key initialiers are used as is\n\n  public array<string, bool> $pr_string_bool = array(\"B\" => true, \"Z\" => false);\n  public array<string, int> $pr_string_int = array(\"X\" => 10, \"Y\" => 20);\n  public array<string, float> $pr_string_float = array('v' => 1.2, 'w' => 9.7);\n  public array<string, num> $pr_string_num = array('zz' => 12.34, 'vv' => 111);\n  public array<string, string> $pr_string_string = array('red' => 'yes', 'green' => 'no');\n//  public array<string, void> $pr_string_void = array();\t// previously allowed; not now\n\n// there is no synax for writing a void expression for any key, so can use only an empty array\n\n//  public array<void, bool> $pr_void_bool = array();\t// previously allowed; not now\n//  public array<void, int> $pr_void_int = array();\t// previously allowed; not now\n//  public array<void, float> $pr_void_float = array();\t// previously allowed; not now\n//  public array<void, num> $pr_void_num = array();\t// previously allowed; not now\n//  public array<void, string> $pr_void_string = array();\t// previously allowed; not now\n//  public array<void, void> $pr_void_void = array();\t// previously allowed; not now\n\n// Although the checker finds no errors, HHVM reports \"Warning: Invalid operand type was used: Invalid \n// type used as key\" and then ignores the initializer(s), resulting in an empty array\n\n//  public array<array<bool>, bool> $pr_arraybool_bool = array(array(true) => true, array(false) => false);\n//  public array<array<bool>, int> $pr_arraybool_int = array(array(true) => 10, array(false) => 20);\n//  public array<array<bool>, float> $pr_arraybool_float = array(array(true) => 12.3, array(false) => -9.4);\n//  public array<array<bool>, num> $pr_arraybool_num = array(array(true) => 12.3, array(false) => -9);\n//  public array<array<bool>, string> $pr_arraybool_string = array(array(true) => \"abc\", array(false) => \"def\");\n\n  public array<array<bool>, bool> $pr_arraybool_bool = array();\n  public array<array<bool>, int> $pr_arraybool_int = array();\n  public array<array<bool>, float> $pr_arraybool_float = array();\n  public array<array<bool>, num> $pr_arraybool_num = array();\n  public array<array<bool>, string> $pr_arraybool_string = array();\n//  public array<array<bool>, void> $pr_arraybool_void = array();\t// previously allowed; not now\n\n// Although the checker finds no errors, HHVM reports \"syntax error, unexpected T_NEW, expecting ')'\"\n\n//  public array<C1, bool> $pr_C1_bool = array(new C1() => true, new C1() => false);\n//  public array<C1, int> $pr_C1_int = array(new C1() => 10, new C1() => -5);\n//  public array<C1, float> $pr_C1_float = array(x => 2.9, x => 3.4);\n//  public array<C1, num> $pr_C1_num = array(x => 11.2, x => 33);\n//  public array<C1, string> $pr_C1_string = array(x => 'ccc', x => 'aaa');\n\n  public array<C1, bool> $pr_C1_bool = array();\n  public array<C1, int> $pr_C1_int = array();\n  public array<C1, float> $pr_C1_float = array();\n  public array<C1, num> $pr_C1_num = array();\n  public array<C1, string> $pr_C1_string = array();\n//  public array<C1, void> $pr_C1_void = array();\t// previously allowed; not now\n\n  public function __construct() {\n\n// an array (used like a hashtable) does not allow array append\n\n//    $this->pr_bool_int[] = 200;\n//    $this->pr_float_float[] = 1.111;\n//    $this->pr_num_num[] = 10; $this->pr_num_num[] = 6.7;\n//    $this->pr_string_bool[] = true;\n//    $this->pr_void_int[] = 123;\n//    $this->pr_arraybool_int[] = 222;\n//    $this->pr_C1_string[] = 'zzz';\n\n    $this->pr_bool_int[true] = 200;\n    $this->pr_float_float[23.5] = 1.111;\n    $this->pr_num_num[7] = 10; $this->pr_num_num[-3.5] = 6.7;\n    $this->pr_string_bool['ff'] = true;\n\n// Re the next statement, the checker is happy and hhvm takes the default null returned by a function \n// not returning an explicit value, converts it to an empty string and uses that as the index of the \n// new element, whose value is 123. Interesting, but defies the idea that a void expression (like the \n// call to v()) has no value.\n\n//    $this->pr_void_int[v()] = 123;\t// previously allowed; not now\n\n// The following appears to do nothing\n\n    $this->pr_arraybool_bool[array(true)] = true;\n\n// The following appears to do nothing\n\n    $this->pr_C1_bool[new C1()] = true;\n\n// For the following two cases:\n// Although the checker finds no errors, HHVM reports \"Warning: Invalid operand type was used: Invalid \n// type used as key\" and then ignores the initializer(s), resulting in an empty array\n\n//    $this->pr_arraybool_bool = array(array(true) => true, array(false) => false);\n//    $this->pr_C1_bool = array(new C1() => true, new C1() => false);\n  }\n}\n\nfunction main(): void {\n  $c2 = new C2();\n\n  echo \"====== bool keys (implicitly converted to int) ======\\n\\n\";\n  echo \"pr_bool_bool: \"; var_dump($c2->pr_bool_bool);\n  echo \"pr_bool_int: \"; var_dump($c2->pr_bool_int);\n  echo \"pr_bool_float: \"; var_dump($c2->pr_bool_float);\n  echo \"pr_bool_num: \"; var_dump($c2->pr_bool_num);\n  echo \"pr_bool_string: \"; var_dump($c2->pr_bool_string);\n//  echo \"pr_bool_void: \"; var_dump($c2->pr_bool_void);\n\t\n  echo \"\\n====== int keys ======\\n\\n\";\n  echo \"pr_int_bool: \"; var_dump($c2->pr_int_bool);\n  echo \"pr_int_int: \"; var_dump($c2->pr_int_int);\n  echo \"pr_int_float: \"; var_dump($c2->pr_int_float);\n  echo \"pr_int_num: \"; var_dump($c2->pr_int_num);\n  echo \"pr_int_string: \"; var_dump($c2->pr_int_string);\n//  echo \"pr_int_void: \"; var_dump($c2->pr_int_void);\n\t\n  echo \"\\n====== float keys (implicitly converted to int) ======\\n\\n\";\n  echo \"pr_float_bool: \"; var_dump($c2->pr_float_bool);\n  echo \"pr_float_int: \"; var_dump($c2->pr_float_int);\n  echo \"pr_float_float: \"; var_dump($c2->pr_float_float);\n  echo \"pr_float_num: \"; var_dump($c2->pr_float_num);\n  echo \"pr_float_string: \"; var_dump($c2->pr_float_string);\n//  echo \"pr_float_void: \"; var_dump($c2->pr_float_void);\n\t\n  echo \"\\n====== num keys (implicitly converted to int) ======\\n\\n\";\n  echo \"pr_num_bool: \"; var_dump($c2->pr_num_bool);\n  echo \"pr_num_int: \"; var_dump($c2->pr_num_int);\n  echo \"pr_num_float: \"; var_dump($c2->pr_num_float);\n  echo \"pr_num_num: \"; var_dump($c2->pr_num_num);\n  echo \"pr_num_string: \"; var_dump($c2->pr_num_string);\n//  echo \"pr_num_void: \"; var_dump($c2->pr_num_void);\n\t\n  echo \"\\n====== string keys ======\\n\\n\";\n  echo \"pr_string_bool: \"; var_dump($c2->pr_string_bool);\n  echo \"pr_string_int: \"; var_dump($c2->pr_string_int);\n  echo \"pr_string_float: \"; var_dump($c2->pr_string_float);\n  echo \"pr_string_num: \"; var_dump($c2->pr_string_num);\n  echo \"pr_string_string: \"; var_dump($c2->pr_string_string);\n//  echo \"pr_string_void: \"; var_dump($c2->pr_string_void);\n\t\n  echo \"\\n====== void keys ======\\n\\n\";\n//  echo \"pr_void_bool: \"; var_dump($c2->pr_void_bool);\n//  echo \"pr_void_int: \"; var_dump($c2->pr_void_int);\n//  echo \"pr_void_float: \"; var_dump($c2->pr_void_float);\n//  echo \"pr_void_num: \"; var_dump($c2->pr_void_num);\n//  echo \"pr_void_string: \"; var_dump($c2->pr_void_string);\n//  echo \"pr_void_void: \"; var_dump($c2->pr_void_void);\n\t\n  echo \"\\n====== array<bool> keys ======\\n\\n\";\n  echo \"pr_arraybool_bool: \"; var_dump($c2->pr_arraybool_bool);\n  echo \"pr_arraybool_int: \"; var_dump($c2->pr_arraybool_int);\n  echo \"pr_arraybool_float: \"; var_dump($c2->pr_arraybool_float);\n  echo \"pr_arraybool_num: \"; var_dump($c2->pr_arraybool_num);\n  echo \"pr_arraybool_string: \"; var_dump($c2->pr_arraybool_string);\n//  echo \"pr_arraybool_void: \"; var_dump($c2->pr_arraybool_void);\n\t\n  echo \"\\n====== C1 keys ======\\n\\n\";\n  echo \"pr_C1_bool: \"; var_dump($c2->pr_C1_bool);\n  echo \"pr_C1_int: \"; var_dump($c2->pr_C1_int);\n  echo \"pr_C1_float: \"; var_dump($c2->pr_C1_float);\n  echo \"pr_C1_num: \"; var_dump($c2->pr_C1_num);\n  echo \"pr_C1_string: \"; var_dump($c2->pr_C1_string);\n//  echo \"pr_C1_void: \"; var_dump($c2->pr_C1_void);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/arrays2.php.expectf",
    "content": "\nWarning: Illegal offset type in %s/tests/Types/arrays2.php on line 123\n\nWarning: Illegal offset type in %s/tests/Types/arrays2.php on line 127\n====== bool keys (implicitly converted to int) ======\n\npr_bool_bool: array(2) {\n  [1]=>\n  bool(false)\n  [0]=>\n  bool(false)\n}\npr_bool_int: array(2) {\n  [1]=>\n  int(200)\n  [0]=>\n  int(-100)\n}\npr_bool_float: array(2) {\n  [0]=>\n  float(12.34)\n  [1]=>\n  float(-2.0E+23)\n}\npr_bool_num: array(2) {\n  [0]=>\n  float(12.34)\n  [1]=>\n  int(111)\n}\npr_bool_string: array(2) {\n  [1]=>\n  string(3) \"abc\"\n  [0]=>\n  string(3) \"def\"\n}\n\n====== int keys ======\n\npr_int_bool: array(2) {\n  [5]=>\n  bool(true)\n  [-2]=>\n  bool(false)\n}\npr_int_int: array(2) {\n  [123]=>\n  int(12)\n  [-1]=>\n  int(1111)\n}\npr_int_float: array(2) {\n  [8]=>\n  float(1.2)\n  [2]=>\n  float(3.4)\n}\npr_int_num: array(2) {\n  [5]=>\n  float(12.34)\n  [-6]=>\n  int(111)\n}\npr_int_string: array(2) {\n  [19]=>\n  string(3) \"abc\"\n  [-5]=>\n  string(3) \"def\"\n}\n\n====== float keys (implicitly converted to int) ======\n\npr_float_bool: array(1) {\n  [1]=>\n  bool(true)\n}\npr_float_int: array(2) {\n  [12]=>\n  int(10)\n  [8]=>\n  int(-5)\n}\npr_float_float: array(3) {\n  [11]=>\n  float(1.2)\n  [-54]=>\n  float(3.4)\n  [23]=>\n  float(1.111)\n}\npr_float_num: array(2) {\n  [1]=>\n  float(12.34)\n  [19]=>\n  int(111)\n}\npr_float_string: array(2) {\n  [4]=>\n  string(3) \"abc\"\n  [9]=>\n  string(3) \"def\"\n}\n\n====== num keys (implicitly converted to int) ======\n\npr_num_bool: array(2) {\n  [1]=>\n  bool(true)\n  [2]=>\n  bool(false)\n}\npr_num_int: array(2) {\n  [12]=>\n  int(10)\n  [8]=>\n  int(-5)\n}\npr_num_float: array(2) {\n  [11]=>\n  float(1.2)\n  [-54]=>\n  float(3.4)\n}\npr_num_num: array(4) {\n  [1]=>\n  float(12.34)\n  [19]=>\n  int(111)\n  [7]=>\n  int(10)\n  [-3]=>\n  float(6.7)\n}\npr_num_string: array(2) {\n  [4]=>\n  string(3) \"abc\"\n  [9]=>\n  string(3) \"def\"\n}\n\n====== string keys ======\n\npr_string_bool: array(3) {\n  [\"B\"]=>\n  bool(true)\n  [\"Z\"]=>\n  bool(false)\n  [\"ff\"]=>\n  bool(true)\n}\npr_string_int: array(2) {\n  [\"X\"]=>\n  int(10)\n  [\"Y\"]=>\n  int(20)\n}\npr_string_float: array(2) {\n  [\"v\"]=>\n  float(1.2)\n  [\"w\"]=>\n  float(9.7)\n}\npr_string_num: array(2) {\n  [\"zz\"]=>\n  float(12.34)\n  [\"vv\"]=>\n  int(111)\n}\npr_string_string: array(2) {\n  [\"red\"]=>\n  string(3) \"yes\"\n  [\"green\"]=>\n  string(2) \"no\"\n}\n\n====== void keys ======\n\n\n====== array<bool> keys ======\n\npr_arraybool_bool: array(0) {\n}\npr_arraybool_int: array(0) {\n}\npr_arraybool_float: array(0) {\n}\npr_arraybool_num: array(0) {\n}\npr_arraybool_string: array(0) {\n}\n\n====== C1 keys ======\n\npr_C1_bool: array(0) {\n}\npr_C1_int: array(0) {\n}\npr_C1_float: array(0) {\n}\npr_C1_num: array(0) {\n}\npr_C1_string: array(0) {\n}"
  },
  {
    "path": "tests/Types/bool.php",
    "content": "<?hh // strict\n\nnamespace NS_bool;\n\nclass C {\n  const bool ON = true;\n  private bool $prop = true;\n\n  public function setProp(bool $val): void {\n    $this->prop = $val;\n  }\n\n  public function getProp(): bool {\n    return $this->prop;\n  }\n}\n"
  },
  {
    "path": "tests/Types/bool.php.expect",
    "content": ""
  },
  {
    "path": "tests/Types/classname.php",
    "content": "<?hh // strict\n\nnamespace NS_classname;\n\n/* --------------------------------------\n\nCan use as an identifier\n\n*/\n\n//function classname(): void {}\t\t\t// can be used as a function name\n\nclass C0 {\n//  public function classname(): void {}\t// can be used as a method name\n//  const type classname = int;\t\t\t// can be used as a type constant name\n  const type classname = classname<C0>;\t\t// first is an identifier, second is a keyword\n}\n\nfunction f0a(C0::classname $p): C0::classname { return $p; }\nfunction f0b(classname<C0::classname> $p): void { var_dump($p); }\n\n/* --------------------------------------\n\nUse as a keyword in all the usual (type-specifier) places\n\n*/\n\ntype TC0B = classname<C0>;\n\nclass C0B {\n  public static classname<\\Exception> $p101 = \\Exception::class;\n  public static classname<\\NS_classname\\C0> $p102 = \\NS_classname\\C0::class;\n  public static classname<C0> $p1 = C0::class;\n  public static function sf0(): void { var_dump(C0B::$p101, C0B::$p102, C0B::$p1); }\n\n  const classname<C0> P0 = C0::class;\n  public static string $str = 'NS_classname\\C0';\n/***/  public static function sf1(): void { echo \"sf1: \" . ((C0B::$str === C0B::$p1) ? 'TRUE' : 'FALSE') . \"\\n\"; }\t// surprise! accepted\n  public static function sf2(): void { echo \"sf2: \" . ((C0B::$str == C0B::$p1) ? 'TRUE' : 'FALSE') . \"\\n\"; }\n\n  public static function f(classname<C0> $p) : classname<C0> { return C0::class; }\n  const type Tp2 = classname<C0>;\n  public static array<classname<C0>> $p2 = array(C0::class);\n  public static array<string, classname<C0>> $p3 = array(\"xx\" => C0::class);\n  public static (classname<C0>, array<int>, float) $p4 = tuple(C0::class, array(99, 88, 77), 10.5);\n  public static shape('x' => classname<C0>, 'y' => int) $p5 = shape('x' => C0::class, 'y' => 20);\n  public static ?classname<C0> $p6 = C0::class;\n}\n\nclass Cj1<T as classname<C0>> {}\nclass Cj2 extends Cj1<classname<C0>> {}\n\n// --------------------------------------\n\nabstract class C1 {\n  public abstract function __construct();\n  public static function hello(): void { echo \"Inside method \" . __METHOD__ . \"\\n\"; }\n}\n\nclass C2 extends C1 {\n  public function __construct() {}\n  public static function hello(): void { echo \"Inside method \" . __METHOD__ . \"\\n\"; }\n}\n\nclass C3 extends C2 {\n  public function __construct() { parent::__construct(); }\n  public static function hello(): void { echo \"Inside method \" . __METHOD__ . \"\\n\"; }\n}\n\nfunction test2(classname<C2> $clsname): void {\n  var_dump($clsname);\n\n// implicit and explicit conversion to string\n\n  echo \"\\$classname is >\" . $clsname . \"<\\n\";\n  echo \"\\$classname is >\" . (string)$clsname . \"<\\n\";\n\n//  $v = $clsname;\n//  var_dump($v);\n\n// use classname<T> with new\n\n  $w = new $clsname();\n//  $w = new '\\NS_classname\\C2'();\t// Cannot use dynamic new in strict mode\n//  $w = new $v();\t\t\t// this works!\n\n// use classname<T> with instanceof\n\n  var_dump(new C2() instanceof $clsname);\n  var_dump(new C3() instanceof $clsname);\n\n// use classname<T> with scope-resolution operator ::\n\n  $clsname::hello();\n\n// However, can't use classname<T> with ::class\n\n//  var_dump($clsname::class);\t// invalid combo\n\n///******/  var_dump(new C2() instanceof C1::class);\t// checker allows, but HHVM doesn't\n} \n\nfunction test3(classname<C3> $clsname): void {\n  var_dump($clsname);\n} \n\nclass C4 {\n  public array<classname<C1>> $vals1 = array(C1::class, C2::class, C3::class);\n  public array<classname<I5>> $vals2 = array(I5::class, C5a::class, C5b::class);\n} \n\n<<__ConsistentConstruct>>\ninterface I5 {\n  static function hello(): void;\n}\n\nclass C5a implements I5 {\n  public static function hello(): void { echo \"Inside method \" . __METHOD__ . \"\\n\"; }\n}\n\nclass C5b implements I5 {\n  public static function hello(): void { echo \"Inside method \" . __METHOD__ . \"\\n\"; }\n}\n\nfunction test5(classname<I5> $clsname): void {\n  var_dump($clsname);\n\n// implicit and explicit conversion to string\n\n  echo \"\\$classname is >\" . $clsname . \"<\\n\";\n  echo \"\\$classname is >\" . (string)$clsname . \"<\\n\";\n\n// use classname<T> with new\n\n  $w = new $clsname();\n\n// use classname<T> with instanceof\n\n  var_dump(new C5a() instanceof $clsname);\n  var_dump(new C5b() instanceof $clsname);\n\n// use classname<T> with scope-resolution operator ::\n\n  $clsname::hello();\n} \n\n// --------------------------------------\n\n// class has to be have an abstract or final constructor or be marked with the attribute <<__ConsistentConstruct>>\n\nabstract class C8a {\n  abstract public function __construct(); \n}\n\nclass C8b {\n  final public function __construct() {} \n}\n\n<<__ConsistentConstruct>>\nclass C8c {\n}\n\nfunction f8a(classname<C8a> $p): void {\n  $v = new $p();\n}\n\nfunction f8b(classname<C8b> $p): void {\n  $v = new $p();\n}\n\nfunction f8c(classname<C8c> $p): void {\n  $v = new $p();\n}\n\n// --------------------------------------\n\nfunction main(): void {\n\n  echo \"---------- sf0() --------------\\n\\n\";\n\n  C0B::sf0();\n\n  echo \"---------- sf1() --------------\\n\\n\";\n\n  C0B::sf1();\n\n  echo \"---------- sf2() --------------\\n\\n\";\n\n  C0B::sf2();\n\n/*\n  echo \"---------- testf0() --------------\\n\\n\";\n\n  testf0(); \n*/\n\n  echo \"---------- var_dump --------------\\n\\n\";\n\n  var_dump(new C4()); \n\n  echo \"\\n---------- test2(C2::class) --------------\\n\\n\";\n\n  test2(C2::class);\n\n  echo \"\\n---------- test3(C3::class) --------------\\n\\n\";\n\n  test3(C3::class);\n\n  echo \"\\n---------- test2(C3::class) --------------\\n\\n\";\n\n  test2(C3::class);\t// treats as a C3 rather than a C2; good\n\n//  test3(C2::class);\t// incompatible type\n\n  echo \"\\n---------- test5(C5a::class) --------------\\n\\n\";\n\n  test5(C5a::class);\n\n  echo \"\\n---------- test5(C5b::class) --------------\\n\\n\";\n\n  test5(C5b::class);\n\n/*\n  echo \"\\n---------- test5(I5::class) --------------\\n\\n\";\n\n  test5(I5::class);\t// runtime error; can't use new with an interface name\n*/\n  echo \"\\n---------- end of script --------------\\n\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/classname.php.expect",
    "content": "---------- sf0() --------------\n\nstring(9) \"Exception\"\nstring(15) \"NS_classname\\C0\"\nstring(15) \"NS_classname\\C0\"\n---------- sf1() --------------\n\nsf1: TRUE\n---------- sf2() --------------\n\nsf2: TRUE\n---------- var_dump --------------\n\nobject(NS_classname\\C4)#1 (2) {\n  [\"vals1\"]=>\n  array(3) {\n    [0]=>\n    string(15) \"NS_classname\\C1\"\n    [1]=>\n    string(15) \"NS_classname\\C2\"\n    [2]=>\n    string(15) \"NS_classname\\C3\"\n  }\n  [\"vals2\"]=>\n  array(3) {\n    [0]=>\n    string(15) \"NS_classname\\I5\"\n    [1]=>\n    string(16) \"NS_classname\\C5a\"\n    [2]=>\n    string(16) \"NS_classname\\C5b\"\n  }\n}\n\n---------- test2(C2::class) --------------\n\nstring(15) \"NS_classname\\C2\"\n$classname is >NS_classname\\C2<\n$classname is >NS_classname\\C2<\nbool(true)\nbool(true)\nInside method NS_classname\\C2::hello\n\n---------- test3(C3::class) --------------\n\nstring(15) \"NS_classname\\C3\"\n\n---------- test2(C3::class) --------------\n\nstring(15) \"NS_classname\\C3\"\n$classname is >NS_classname\\C3<\n$classname is >NS_classname\\C3<\nbool(false)\nbool(true)\nInside method NS_classname\\C3::hello\n\n---------- test5(C5a::class) --------------\n\nstring(16) \"NS_classname\\C5a\"\n$classname is >NS_classname\\C5a<\n$classname is >NS_classname\\C5a<\nbool(true)\nbool(false)\nInside method NS_classname\\C5a::hello\n\n---------- test5(C5b::class) --------------\n\nstring(16) \"NS_classname\\C5b\"\n$classname is >NS_classname\\C5b<\n$classname is >NS_classname\\C5b<\nbool(false)\nbool(true)\nInside method NS_classname\\C5b::hello\n\n---------- end of script --------------\n"
  },
  {
    "path": "tests/Types/closure.php",
    "content": "<?hh // strict\n\nnamespace NS_closure;\n\nclass C {\n//  const (function (): void) T = // *** no way to write a closure constant expression\n\n  private (function (): void) $prop;\n\n  public function setProp((function (): void) $val): void {\n    $this->prop = $val;\n  }\n\n  public function getProp(): (function (): void) {\n    return $this->prop;\n  }\n\n  public function __construct() {\n    $this->prop = function (): void { echo \"Hi there!\\n\"; };\n  }\n}\n\nfunction doit(int $iValue, (function (int): int) $process): int {\n  return $process($iValue);\n}\n\nfunction main(): void {\n  $result = doit(5, function ($p) { return $p * 2; });\t// doubles 5\n  var_dump($result);\n  $result = doit(5, function ($p) { return $p * $p; });\t// squares 5\n  var_dump($result);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/closure.php.expect",
    "content": "int(10)\nint(25)"
  },
  {
    "path": "tests/Types/determined_type.php",
    "content": "<?hh // strict\n\nnamespace NS_determined_type;\n\nfunction main(?int $p1_nint, num $p2_num, ?num $p3_nnum, mixed $p4_mixed, array<?int> $p5_arynint): void {\n// play with a nullable type\n\n//  $r = $p1_nint << 2;\t\t// actual type might be int, but this has not been determined\n\n  if (is_int($p1_nint)) {\n    $r = $p1_nint << 2;\t// type determined to be int\n    var_dump($r);\n  }\n\n  if (!is_null($p1_nint)) {\n    $r = $p1_nint << 2;\t// isn't null, so type determined to be int\n    var_dump($r);\n  }\n\n  if (is_null($p1_nint)) {\n  } else {\n    $r = $p1_nint << 2;\t// isn't null, so type determined to be int\n    var_dump($r);\n  }\n\n// play with a num\n\n//  $r = $p2_num << 2;\t\t// actual type might be int, but this has not been determined\n\n  if (is_int($p2_num)) {\n    $r = $p2_num << 2;\t// type determined to be int\n    var_dump($r);\n  }\n\n  if (!is_float($p2_num)) {\n//***  \t$r = $p2_num << 2;\t// isn't float, so must be int\n//  \tvar_dump($r);\n  }\n\n  if (is_float($p2_num)) {\n  } else {\n//***  $r = $p2_num << 2;\t// isn't float, so must be int\n//  var_dump($r);\n  }\n\n// play with a nullable num\n\n//  $r = $p3_nnum << 2;\t\t// actual type might be int, but this has not been determined\n\n  if (is_int($p3_nnum)) {\n    $r = $p3_nnum << 2;\t// type determined to be int\n    var_dump($r);\n  }\n\n  if (!is_null($p3_nnum) && !is_float($p3_nnum)) {\n//***  $r = $p3_nnum << 2;\t// type should be determined to be int\n//    var_dump($r);\n  }\n\n// play with a mixed\n\n//  $r = $p4_mixed << 2;\t\t// actual type might be int, but this has not been determined\n\n  if (is_int($p4_mixed)) {\n    $r = $p4_mixed << 2;\t// type determined to be int\n    var_dump($r);\n  }\n\n// play with an array of nullable type\n\n//  $r = $p5_arynint[0] << 2;\t\t// actual type might be int, but this has not been determined\n\n  if ((count($p5_arynint) > 0) && is_int($p5_arynint[0])) {\n//***  $r = $p5_arynint[0] << 2;\t// type should be determined to be int\n//     var_dump($r);\n  }\n\n  if ((count($p5_arynint) > 0) && !is_null($p5_arynint[0])) {\n//***  $r = $p5_arynint[0] << 2;\t// isn't null, so must be an int\n//     var_dump($r);\n  }\n\n  if ((count($p5_arynint) > 0) && is_null($p5_arynint[0])) {\n  } else {\n//***  $r = $p5_arynint[0] << 2;\t// isn't null, so must be an int\n//     var_dump($r);\n  }\n}\n\n//main(10, 10, 10, 10, array(10));\n"
  },
  {
    "path": "tests/Types/determined_type.php.expect",
    "content": ""
  },
  {
    "path": "tests/Types/enum.php",
    "content": "<?hh // strict\n\nnamespace NS_enum_in_types_dir;\n\nenum ControlStatus: int {\n  Stopped = 0;\n  Stopping = 1;\n  Starting = 2;\n  Started = 3;\n}\n\nclass C {\n  const ControlStatus DEFAULT_STATE = ControlStatus::Stopped;\n  private ControlStatus $prop = ControlStatus::Stopping;\n\n  public function setProp(ControlStatus $val): void {\n    $this->prop = $val;\n  }\n\n  public function getProp(): ControlStatus {\n    return $this->prop;\n  }\n}\n\nfunction main(): void {\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/enum.php.expect",
    "content": ""
  },
  {
    "path": "tests/Types/float.php",
    "content": "<?hh // strict\n\nnamespace NS_float;\n\nclass C {\n  const float LIMIT = 99.99;\n  private float $prop = 10.5;\n\n  public function setProp(float $val): void {\n    $this->prop = $val;\n  }\n\n  public function getProp(): float {\n    return $this->prop;\n  }\n}\n"
  },
  {
    "path": "tests/Types/float.php.expect",
    "content": ""
  },
  {
    "path": "tests/Types/int.php",
    "content": "<?hh // strict\n\nnamespace NS_int;\n\nclass C {\n  const int MAX = 1000;\n  private int $prop = 10;\n\n  public function setProp(int $val): void {\n    $this->prop = $val;\n  }\n\n  public function getProp(): int {\n    return $this->prop;\n  }\n}\n\nfunction main(): void {\n  var_dump(-PHP_INT_MAX - 1);\n  var_dump(-PHP_INT_MAX - 1 - 1);\t\t// wraps to max positive\n\n  var_dump(PHP_INT_MAX);\n  var_dump(PHP_INT_MAX + 1);\t\t\t// wraps to min negative\n\n  var_dump(PHP_INT_MAX/2 + PHP_INT_MAX);\t// converts to float\n\n  var_dump(PHP_INT_MIN);\t\t\t// added in PHP7\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/int.php.expect",
    "content": "int(-9223372036854775808)\nint(9223372036854775807)\nint(9223372036854775807)\nint(-9223372036854775808)\nfloat(1.3835058055282E+19)\nint(-9223372036854775808)"
  },
  {
    "path": "tests/Types/mixed.php",
    "content": "<?hh // strict\n\nnamespace NS_mixed;\n\nclass C {\n  const mixed THING = 'abc';\n  private mixed $prop = true;\n\n  public function setProp(mixed $val): void {\n    $this->prop = $val;\n  }\n\n  public function getProp(): mixed {\n    return $this->prop;\n  }\n}\n"
  },
  {
    "path": "tests/Types/mixed.php.expect",
    "content": ""
  },
  {
    "path": "tests/Types/nullables.php",
    "content": "<?hh // strict\n\nnamespace NS_nullables_in_types_dir;\n\nclass Button {}\nclass CustomButton extends Button {}\n\ninterface MyCollection {}\nclass MyList implements MyCollection {}\nclass MyQueue implements MyCollection {}\n\nclass C1 {\n  private ?bool $pr_nbool = null;\n  private ?int $pr_nint = null;\n  private ?float $pr_nfloat = null;\n  private ?num $pr_nnum = null;\n  private ?string $pr_nstring = null;\n  private mixed $pr_mixed = null;\t// ?mixed === mixed; ? is redundant\n  private ?resource $pr_nresource = null;\n\n  private ?Button $pr_nButton = null;\n  private ?CustomButton $pr_nCustomButton = null;\n  private ?MyCollection $pr_nMyCollection = null;\n\n///*\n  private array<?bool> $a_nbool = array(true, null);\n  private array<?int> $a_nint = array(10, null);\n  private array<?float> $a_nfloat = array(3.1, null);\n  private array<?num> $a_nnum = array(-4, 5.4, null);\n  private array<?string> $a_nstring = array('a', null);\n  private array<mixed> $a_mixed = array(10, 'b', null);\t// ?mixed === mixed; ? is redundant\n//  private array<?resource> $a_nresource = array(STDIN, null);\n\n  private array<?Button> $a_nButton = array();\n  private array<?CustomButton> $a_nCustomButton = array();\n  private array<?MyCollection> $a_nMyCollection = array();\n//*/\n\n  public function __construct() {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n\n///*\n    $this->pr_nbool = true;\n    $this->pr_nint = 10;\n    $this->pr_nfloat = 3.1;\n    $this->pr_nnum = -4; $this->pr_nnum = 5.4;\n    $this->pr_nstring = 'a';\n    $this->pr_mixed = 10; $this->pr_mixed = 'b';\n//    $this->pr_nresource = STDIN;\n\n    $this->pr_nButton = new Button();\n    $this->pr_nButton = new CustomButton();\n    $this->pr_nCustomButton = new CustomButton();\n    $this->pr_nButton = $this->pr_nCustomButton;\n    $this->pr_nCustomButton = $this->pr_nButton;\n\n    $this->pr_nMyCollection = new MyList();\n    $this->pr_nMyCollection = new MyQueue();\n//*/\n\n///*\n    $this->a_nbool = array(true, null);\n    $this->a_nint = array(10, null);\n    $this->a_nfloat = array(3.1, null);\n    $this->a_nnum = array(-4, 5.4, null);\n    $this->a_nstring = array('a', null);\n    $this->a_mixed = array(10, 'b', null);\n//    $this->a_nresource = array(STDIN, null);\n\n    $this->a_nButton = array(new Button(), null, new CustomButton());\n    $this->a_nCustomButton = array(new CustomButton(), null);\n    $this->a_nMyCollection = array(null, new MyList(), new MyQueue());\n//*/\n  }\n}\n\nfunction main(): void {\n  $c1 = new C1();\n  var_dump($c1);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/nullables.php.expect",
    "content": "Inside NS_nullables_in_types_dir\\C1::__construct\nobject(NS_nullables_in_types_dir\\C1)#1 (19) {\n  [\"pr_nbool\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  bool(true)\n  [\"pr_nint\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  int(10)\n  [\"pr_nfloat\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  float(3.1)\n  [\"pr_nnum\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  float(5.4)\n  [\"pr_nstring\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  string(1) \"a\"\n  [\"pr_mixed\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  string(1) \"b\"\n  [\"pr_nresource\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  NULL\n  [\"pr_nButton\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  object(NS_nullables_in_types_dir\\CustomButton)#4 (0) {\n  }\n  [\"pr_nCustomButton\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  object(NS_nullables_in_types_dir\\CustomButton)#4 (0) {\n  }\n  [\"pr_nMyCollection\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  object(NS_nullables_in_types_dir\\MyQueue)#6 (0) {\n  }\n  [\"a_nbool\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  array(2) {\n    [0]=>\n    bool(true)\n    [1]=>\n    NULL\n  }\n  [\"a_nint\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  array(2) {\n    [0]=>\n    int(10)\n    [1]=>\n    NULL\n  }\n  [\"a_nfloat\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  array(2) {\n    [0]=>\n    float(3.1)\n    [1]=>\n    NULL\n  }\n  [\"a_nnum\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  array(3) {\n    [0]=>\n    int(-4)\n    [1]=>\n    float(5.4)\n    [2]=>\n    NULL\n  }\n  [\"a_nstring\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  array(2) {\n    [0]=>\n    string(1) \"a\"\n    [1]=>\n    NULL\n  }\n  [\"a_mixed\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  array(3) {\n    [0]=>\n    int(10)\n    [1]=>\n    string(1) \"b\"\n    [2]=>\n    NULL\n  }\n  [\"a_nButton\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  array(3) {\n    [0]=>\n    object(NS_nullables_in_types_dir\\Button)#7 (0) {\n    }\n    [1]=>\n    NULL\n    [2]=>\n    object(NS_nullables_in_types_dir\\CustomButton)#8 (0) {\n    }\n  }\n  [\"a_nCustomButton\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  array(2) {\n    [0]=>\n    object(NS_nullables_in_types_dir\\CustomButton)#9 (0) {\n    }\n    [1]=>\n    NULL\n  }\n  [\"a_nMyCollection\":\"NS_nullables_in_types_dir\\C1\":private]=>\n  array(3) {\n    [0]=>\n    NULL\n    [1]=>\n    object(NS_nullables_in_types_dir\\MyList)#10 (0) {\n    }\n    [2]=>\n    object(NS_nullables_in_types_dir\\MyQueue)#11 (0) {\n    }\n  }\n}"
  },
  {
    "path": "tests/Types/num.php",
    "content": "<?hh // strict\n\nnamespace NS_num;\n\nclass C {\n  const num COUNT = 100;\n  private num $prop = 0;\n\n  public function setProp(num $val): void {\n    $this->prop = $val;\n  }\n\n  public function getProp(): num {\n    return $this->prop;\n  }\n\n  public function __construct() {\n    echo \"num \" . $this->prop . (is_int($this->prop) ? \" is int\\n\" : \" is float\\n\");\n\n    $this->prop = 1.2;\n    echo \"num \" . $this->prop . (is_int($this->prop) ? \" is int\\n\" : \" is float\\n\");\n\n    $this->prop = 6;\n    echo \"num \" . $this->prop . (is_int($this->prop) ? \" is int\\n\" : \" is float\\n\");\n\n    $this->prop += 0.0;\n    echo \"num \" . $this->prop . (is_int($this->prop) ? \" is int\\n\" : \" is float\\n\");\n\n    $this->prop = 16;\n    echo \"num \" . $this->prop . (is_int($this->prop) ? \" is int\\n\" : \" is float\\n\");\n\n    $this->prop *= 1.0;\n    echo \"num \" . $this->prop . (is_int($this->prop) ? \" is int\\n\" : \" is float\\n\");\n\n    $this->prop = PHP_INT_MAX;\n    echo \"num \" . $this->prop . (is_int($this->prop) ? \" is int\\n\" : \" is float\\n\");\n\n    ++$this->prop;\n    echo \"num \" . $this->prop . (is_int($this->prop) ? \" is int\\n\" : \" is float\\n\");\n  }\n}\n\nfunction main (): void {\n  $c = new C();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/num.php.expect",
    "content": "num 0 is int\nnum 1.2 is float\nnum 6 is int\nnum 6 is float\nnum 16 is int\nnum 16 is float\nnum 9223372036854775807 is int\nnum -9223372036854775808 is int"
  },
  {
    "path": "tests/Types/numeric_like_strings.php",
    "content": "<?hh // strict\n\nnamespace NS_numeric_like_strings;\n\nfunction main(): void {\n  echo \"============== var_dump(numeric_like_string) ===================\\n\\n\";\n\n  var_dump(\"12345xxx\");\t\t\t// string(...)\n  var_dump(\"12345 xxx\");\t\t\t// string(...)\n  var_dump(\"12345.6xxx\");\t\t\t// string(...)\n  var_dump(\"12345.6 xxx\");\t\t// string(...)\n\n  echo \"\\n============== is_numeric(numeric_like_string) ===================\\n\\n\";\n\n  var_dump(is_numeric(\"12345xxx\"));\t// false\n  var_dump(is_numeric(\"12345 xxx\"));\t// false\n  var_dump(is_numeric(\"12345.6xxx\"));\t// false\n  var_dump(is_numeric(\"12345.6 xxx\"));\t// false\n\n  echo \"\\n============== cast of numeric_like_string ===================\\n\\n\";\n\n  var_dump((int)\"12345xxx\");\t\t// int(12345); trailing non-numerics ignored\n  var_dump((int)\"12345 xxx\");\t\t// int(12345); trailing non-numerics ignored\n  var_dump((float)\"12345.6xxx\");\t\t// float(12345.6); trailing non-numerics ignored\n  var_dump((float)\"12345.6 xxx\");\t\t// float(12345.6); trailing non-numerics ignored\n\n  echo \"\\n============== +/- numeric_like_string ===================\\n\\n\";\n\n// This is a num (int/float) because this is used in an arithmetic operation. It is incompatible with a string\n\n//  var_dump(+\"12345xxx\");\n//  var_dump(+\"12345 xxx\");\n//  var_dump(+\"12345.6xxx\");\n//  var_dump(+\"12345.6 xxx\");\n//  var_dump(-\"12345xxx\");\n//  var_dump(-\"12345 xxx\");\n//  var_dump(-\"12345.6xxx\");\n//  var_dump(-\"12345.6 xxx\");\n\n  echo \"\\n============== relational/equality ops with numeric_like_string ===================\\n\\n\";\n\n  var_dump(12345   == \"12345xxx\");\t// int(12345); trailing non-numerics ignored\n  var_dump(12345   == \"12345 xxx\");\t// int(12345)\n  var_dump(12345.6 == \"12345.6xxx\");\t// float(12345.6)\n  var_dump(12345.6 == \"12345.6 xxx\");\t// float(12345.6)\n\n  var_dump(\"12345\" == \"12345xxx\");\t// treated as a string\n  var_dump(\"12345\" == \"12345 xxx\");\t// treated as a string\n  var_dump(\"12345.6\" == \"12345.6xxx\");\t// treated as a string\n  var_dump(\"12345.6\" == \"12345.6 xxx\");\t// treated as a string\n\n  echo \"\\n============== ++/-- ops with numeric_like_string ===================\\n\\n\";\n\n  $s1 = \"12345xxx\";\n  $s2 = \"12345 xxx\";\n  $s3 = \"12345.6xxx\";\n  $s4 = \"12345.6 xxx\";\n\n// This is a num (int/float) because this is used in an arithmetic operation. It is incompatible with a string\n\n//  var_dump(++$s1);\n//  var_dump(++$s2);\n//  var_dump(++$s3);\n//  var_dump(++$s4);\n\n  $s1 = \"12345xxx\";\n  $s2 = \"12345 xxx\";\n  $s3 = \"12345.6xxx\";\n  $s4 = \"12345.6 xxx\";\n\n// This is a num (int/float) because this is used in an arithmetic operation. It is incompatible with a string\n\n//  var_dump(--$s1);\n//  var_dump(--$s2);\n//  var_dump(--$s3);\n//  var_dump(--$s4);\n\n  $s1 = \"12345xxx\";\n  $s2 = \"12345 xxx\";\n  $s3 = \"12345.6xxx\";\n  $s4 = \"12345.6 xxx\";\n\n// This is a num (int/float) because this is used in an arithmetic operation. It is incompatible with a string\n\n//  var_dump($s1++);\n//  var_dump($s2++);\n//  var_dump($s3++);\n//  var_dump($s4++);\n\n  $s1 = \"12345xxx\";\n  $s2 = \"12345 xxx\";\n  $s3 = \"12345.6xxx\";\n  $s4 = \"12345.6 xxx\";\n\n// This is a num (int/float) because this is used in an arithmetic operation. It is incompatible with a string\n\n//  var_dump($s1--);\n//  var_dump($s2--);\n//  var_dump($s3--);\n//  var_dump($s4--);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/numeric_like_strings.php.expect",
    "content": "============== var_dump(numeric_like_string) ===================\n\nstring(8) \"12345xxx\"\nstring(9) \"12345 xxx\"\nstring(10) \"12345.6xxx\"\nstring(11) \"12345.6 xxx\"\n\n============== is_numeric(numeric_like_string) ===================\n\nbool(false)\nbool(false)\nbool(false)\nbool(false)\n\n============== cast of numeric_like_string ===================\n\nint(12345)\nint(12345)\nfloat(12345.6)\nfloat(12345.6)\n\n============== +/- numeric_like_string ===================\n\n\n============== relational/equality ops with numeric_like_string ===================\n\nbool(true)\nbool(true)\nbool(true)\nbool(true)\nbool(false)\nbool(false)\nbool(false)\nbool(false)\n\n============== ++/-- ops with numeric_like_string ===================\n"
  },
  {
    "path": "tests/Types/numeric_strings.php",
    "content": "<?hh // strict\n\nnamespace NS_numeric_strings;\n\nfunction main(): void {\n/* All LC_* names are unbound\n\n  var_dump(setlocale(LC_ALL, 0));\n  var_dump(setlocale(LC_NUMERIC, \"fr-CA\"));\n  var_dump(setlocale(LC_NUMERIC, \"fr-BE\"));\n  var_dump(setlocale(LC_NUMERIC, \"fr-CH\"));\n  var_dump(setlocale(LC_NUMERIC, \"fr-FR\"));\n//  var_dump(setlocale(LC_NUMERIC, \"XXX\"));\t// returns False as there is no such locale on system\n*/\n\n$s = array(\n  \"\",\n  \"0\", \"00\", \"0377\", \"0xEEFFAA00\", \"0X1234EF\",\n  \" 0\", \"  00\", \"   0377\", \"    0xEEFFAA00\", \"     0X1234EF\",\n  \"0 \", \"00  \", \"0377   \", \"0xEEFFAA00    \", \"0X1234EF     \",\n  \"0b1010\", \"0B111111111111111\",\n  \"+0\", \"+01234567890\", \"-187654321\",\n  \"123.456\", \"-7654.\", \".7654321\",\n  \"1e12\", \"+2E21\", \"-4e+2\", \"9E-21\",\n  \"-123.762e21\", \"+876.432E37\",\n  \"INF\", \"INf\", \"InF\", \"Inf\", \"iNF\", \"iNf\", \"inF\", \"inf\",\n  \"+INF\", \"+INf\", \"+InF\", \"+Inf\", \"+iNF\", \"+iNf\", \"+inF\", \"+inf\",\n  \"-INF\", \"-INf\", \"-InF\", \"-Inf\", \"-iNF\", \"-iNf\", \"-inF\", \"-inf\",\n  \"NAN\", \"NAn\", \"NaN\", \"Nan\", \"nAN\", \"nAn\", \"naN\", \"nan\"\n);\n  foreach ($s as $e) {\n    if (is_numeric($e)) {\n      echo \"\\\"$e\\\" is numeric; value is \" . (float)$e . \"\\n\";\n    } else {\n      echo \"\\\"$e\\\" is not numeric\\t***\\n\";\n    }\n  }\n\n  $t = sprintf(\"%b,%d\", 0b1010, 0b1010);\n  var_dump($t);\n  var_dump((string)INF);\n  var_dump((string)-INF);\n  var_dump((string)NAN);\n  var_dump(-PHP_INT_MAX - 1);\n  var_dump(-PHP_INT_MAX - 1 - 1);\t// wraps to max positive\n\n  var_dump(PHP_INT_MAX);\n  var_dump(PHP_INT_MAX + 1);\t// wraps to min negative\n\n  var_dump(PHP_INT_MAX/2 + PHP_INT_MAX);\t// converts to float\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/numeric_strings.php.expect",
    "content": "\"\" is not numeric\t***\n\"0\" is numeric; value is 0\n\"00\" is numeric; value is 0\n\"0377\" is numeric; value is 377\n\"0xEEFFAA00\" is numeric; value is 0\n\"0X1234EF\" is numeric; value is 0\n\" 0\" is numeric; value is 0\n\"  00\" is numeric; value is 0\n\"   0377\" is numeric; value is 377\n\"    0xEEFFAA00\" is numeric; value is 0\n\"     0X1234EF\" is numeric; value is 0\n\"0 \" is not numeric\t***\n\"00  \" is not numeric\t***\n\"0377   \" is not numeric\t***\n\"0xEEFFAA00    \" is not numeric\t***\n\"0X1234EF     \" is not numeric\t***\n\"0b1010\" is not numeric\t***\n\"0B111111111111111\" is not numeric\t***\n\"+0\" is numeric; value is 0\n\"+01234567890\" is numeric; value is 1234567890\n\"-187654321\" is numeric; value is -187654321\n\"123.456\" is numeric; value is 123.456\n\"-7654.\" is numeric; value is -7654\n\".7654321\" is numeric; value is 0.7654321\n\"1e12\" is numeric; value is 1000000000000\n\"+2E21\" is numeric; value is 2.0E+21\n\"-4e+2\" is numeric; value is -400\n\"9E-21\" is numeric; value is 9.0E-21\n\"-123.762e21\" is numeric; value is -1.23762E+23\n\"+876.432E37\" is numeric; value is 8.76432E+39\n\"INF\" is not numeric\t***\n\"INf\" is not numeric\t***\n\"InF\" is not numeric\t***\n\"Inf\" is not numeric\t***\n\"iNF\" is not numeric\t***\n\"iNf\" is not numeric\t***\n\"inF\" is not numeric\t***\n\"inf\" is not numeric\t***\n\"+INF\" is not numeric\t***\n\"+INf\" is not numeric\t***\n\"+InF\" is not numeric\t***\n\"+Inf\" is not numeric\t***\n\"+iNF\" is not numeric\t***\n\"+iNf\" is not numeric\t***\n\"+inF\" is not numeric\t***\n\"+inf\" is not numeric\t***\n\"-INF\" is not numeric\t***\n\"-INf\" is not numeric\t***\n\"-InF\" is not numeric\t***\n\"-Inf\" is not numeric\t***\n\"-iNF\" is not numeric\t***\n\"-iNf\" is not numeric\t***\n\"-inF\" is not numeric\t***\n\"-inf\" is not numeric\t***\n\"NAN\" is not numeric\t***\n\"NAn\" is not numeric\t***\n\"NaN\" is not numeric\t***\n\"Nan\" is not numeric\t***\n\"nAN\" is not numeric\t***\n\"nAn\" is not numeric\t***\n\"naN\" is not numeric\t***\n\"nan\" is not numeric\t***\nstring(7) \"1010,10\"\nstring(3) \"INF\"\nstring(4) \"-INF\"\nstring(3) \"NAN\"\nint(-9223372036854775808)\nint(9223372036854775807)\nint(9223372036854775807)\nint(-9223372036854775808)\nfloat(1.3835058055282E+19)"
  },
  {
    "path": "tests/Types/resources.php",
    "content": "<?hh // strict\n\nnamespace NS_resources;\n\nclass C {\n  const resource INFILE = STDIN;\n  private resource $prop; // = STDOUT;   // causes segmentation fault\n\n  public function __construct() {\n    $this->prop = STDOUT;\n  }\n\n  public function setProp(resource $val): void {\n    $this->prop = $val;\n  }\n\n  public function getProp(): resource {\n    return $this->prop;\n  }\n}\n\nfunction main(): void {\n  var_dump(STDIN);\n  var_dump(is_resource(STDIN));\n  var_dump(get_resource_type(STDIN));\n\n  var_dump(STDOUT);\n  var_dump(is_resource(STDIN));\n  var_dump(get_resource_type(STDIN));\n\n  var_dump(STDERR);\n  var_dump(is_resource(STDIN));\n  var_dump(get_resource_type(STDIN));\n\n  $infile = fopen(\"Testfile.txt\", 'r');\n  var_dump($infile);\n  echo \"\\n\";\n  print_r($infile);\n  echo \"\\n\";\n\n  $infile = fopen(\"NoSuchFile.txt\", 'r');\n  var_dump($infile);\n\n  $c = new C();\n  var_dump($c);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n\n"
  },
  {
    "path": "tests/Types/resources.php.expectf",
    "content": "resource(1) of type (stream)\nbool(true)\nstring(6) \"stream\"\nresource(2) of type (stream)\nbool(true)\nstring(6) \"stream\"\nresource(3) of type (stream)\nbool(true)\nstring(6) \"stream\"\n\nWarning: No such file or directory in %s/tests/Types/resources.php on line 35\nbool(false)\n\n\n\nWarning: No such file or directory in %s/tests/Types/resources.php on line 41\nbool(false)\nobject(NS_resources\\C)#1 (1) {\n  [\"prop\":\"NS_resources\\C\":private]=>\n  resource(2) of type (stream)\n}"
  },
  {
    "path": "tests/Types/scalar_general.php",
    "content": "<?hh // strict\n\nnamespace NS_scalar_general;\n\nclass C {}\n\nfunction main(): void {\n  $infile = fopen(\"Testfile.txt\", 'r');\n\n  echo \"========== is_numeric tests ==========\\n\\n\";\n\n  echo \"is_numeric(true): \" . (is_numeric(true) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_numeric(false): \" . (is_numeric(false) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_numeric(10): \" . (is_numeric(10) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_numeric(12.34): \" . (is_numeric(12.34) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_numeric(\\\"\\\"): \" . (is_numeric(\"\") ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_numeric(\\\"123\\\"): \" . (is_numeric(\"123\") ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_numeric(\\\"123abc\\\"): \" . (is_numeric(\"123abc\") ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_numeric(\\\"abc\\\"): \" . (is_numeric(\"abc\") ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_numeric(null): \" . (is_numeric(null) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_numeric(array(10,20)): \" . (is_numeric(array(10,20)) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_numeric(new C()): \" . (is_numeric(new C()) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_numeric(resource): \" . (is_numeric($infile) ? \"True\" : \"False\") . \"\\n\";\n\n  echo \"\\n========== is_numeric tests ==========\\n\\n\";\n\n  echo \"is_scalar(true): \" . (is_scalar(true) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_scalar(10): \" . (is_scalar(10) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_scalar(12.34): \" . (is_scalar(12.34) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_scalar(\\\"123\\\"): \" . (is_scalar(\"123\") ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_scalar(null): \" . (is_scalar(null) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_scalar(array(10,20)): \" . (is_scalar(array(10,20)) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_scalar(new C()): \" . (is_scalar(new C()) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_scalar(resource): \" . (is_scalar($infile) ? \"True\" : \"False\") . \"\\n\";\n\n  echo \"\\n ========== is_numeric tests ==========\\n\\n\";\n\n  echo \"is_null(true): \" . (is_null(true) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_null(10): \" . (is_null(10) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_null(12.34): \" . (is_null(12.34) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_null(\\\"123\\\"): \" . (is_null(\"123\") ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_null(null): \" . (is_null(null) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_null(array(10,20)): \" . (is_null(array(10,20)) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_null(new C()): \" . (is_null(new C()) ? \"True\" : \"False\") . \"\\n\";\n  echo \"is_null(resource): \" . (is_null($infile) ? \"True\" : \"False\") . \"\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/scalar_general.php.expectf",
    "content": "\nWarning: No such file or directory in %s/tests/Types/scalar_general.php on line 8\n========== is_numeric tests ==========\n\nis_numeric(true): False\nis_numeric(false): False\nis_numeric(10): True\nis_numeric(12.34): True\nis_numeric(\"\"): False\nis_numeric(\"123\"): True\nis_numeric(\"123abc\"): False\nis_numeric(\"abc\"): False\nis_numeric(null): False\nis_numeric(array(10,20)): False\nis_numeric(new C()): False\nis_numeric(resource): False\n\n========== is_numeric tests ==========\n\nis_scalar(true): True\nis_scalar(10): True\nis_scalar(12.34): True\nis_scalar(\"123\"): True\nis_scalar(null): False\nis_scalar(array(10,20)): False\nis_scalar(new C()): False\nis_scalar(resource): True\n\n ========== is_numeric tests ==========\n\nis_null(true): False\nis_null(10): False\nis_null(12.34): False\nis_null(\"123\"): False\nis_null(null): True\nis_null(array(10,20)): False\nis_null(new C()): False\nis_null(resource): False"
  },
  {
    "path": "tests/Types/shape_specific_functions.php",
    "content": "<?hh // strict\n\nnamespace NS_ShapeSpecificFunctions;\n\nclass C {\n  const string KEYX = 'x';\n  const string KEYY = 'y';\n  const int KEYINTX = 10;\n  const int KEYINTY = 23;\n  const int KEYINTZ = 50;\n}\n\nfunction main(): void {\n  echo \"======== Shapes::idx ========\\n\";\n\n  $s = shape('x' => 10, 'y' => 20);\n\n  $v = Shapes::idx($s, 'x');\t\t// field exists, return 10\n  echo \"\\$v = \" . (($v == null)? \"null\" : $v) .\"\\n\";\n\n  $v = Shapes::idx($s, 'y');\t\t// field exists, return 20\n  echo \"\\$v = \" . (($v == null)? \"null\" : $v) .\"\\n\";\n\n  $v = Shapes::idx($s, 'z');\t\t// field does not exist; return implict default, null\n  echo \"\\$v = \" . (($v == null)? \"null\" : $v) .\"\\n\";\n\n  $v = Shapes::idx($s, 'z', -99);\t// field does not exist; return explicit default, -99\n  echo \"\\$v = \" . (($v == null)? \"null\" : $v) .\"\\n\";\n\n  echo \"----------------------------\\n\";\n\n  $s = shape(C::KEYINTX => 10, C::KEYINTY => 20);\n\n  $v = Shapes::idx($s, C::KEYINTX);\t\t// field exists, return 10\n  echo \"\\$v = \" . (($v == null)? \"null\" : $v) .\"\\n\";\n\n  $v = Shapes::idx($s, C::KEYINTY);\t// field exists, return 20\n  echo \"\\$v = \" . (($v == null)? \"null\" : $v) .\"\\n\";\n\n  $v = Shapes::idx($s, C::KEYINTZ);\t// field does not exist; return implict default, null\n  echo \"\\$v = \" . (($v == null)? \"null\" : $v) .\"\\n\";\n\n  $v = Shapes::idx($s, C::KEYINTZ, -99); // field does not exist; return explicit default, -99\n  echo \"\\$v = \" . (($v == null)? \"null\" : $v) .\"\\n\";\n\n  echo \"\\n======== Shapes::keyExists ========\\n\\n\";\n\n  $s = shape('id' => \"23456\", 'url' => \"www.example.com\", 'count' => 23);\n\n  $v = Shapes::keyExists($s, 'url');\t\t// field exists, return true\n  echo \"keyExists(\\$s, 'x') = \" . $v .\"\\n\";\n\n  $v = Shapes::keyExists($s, 'name');\t\t// does not exist, return false\n  echo \"keyExists(\\$s, 'name') = \" . $v .\"\\n\";\n\n  echo \"\\n======== Shapes::removeKey ========\\n\\n\";\n\n  $s = shape();\n  var_dump($s);\n  Shapes::removeKey($s, 'name');\t// no such field, so request ignored\n  $a = Shapes::toArray($s);\n  echo \"# elements in array = \" . count($a) . \"\\n\";\n  var_dump($s, $a);\n  echo \"----------------------------\\n\";\n\n  $s = shape('x' => 10, 'y' => 20);\n  var_dump($s);\n  Shapes::removeKey($s, C::KEYX);\t// field 'x' removed\n  $a = Shapes::toArray($s);\n  echo \"# elements in array = \" . count($a) . \"\\n\";\n  var_dump($s, $a);\n  echo \"----------------------------\\n\";\n\n  $s = shape('id' => \"23456\", 'url' => \"www.example.com\", 'count' => 23);\n  var_dump($s);\n  Shapes::removeKey($s, 'url');\t\t// field 'url' removed\n  $a = Shapes::toArray($s);\n  echo \"# elements in array = \" . count($a) . \"\\n\";\n  var_dump($s, $a);\n\n  echo \"\\n======== Shapes::toArray ========\\n\\n\";\n\n  $s = shape();\n  $a = Shapes::toArray($s);   // returns an array of 0 elements\n  echo \"# elements in array = \" . count($a) . \"\\n\";\n  var_dump($s, $a);\n  echo \"----------------------------\\n\";\n\n  $s = shape('x' => 10, 'y' => 20);\n  $a = Shapes::toArray($s);\n  echo \"# elements in array = \" . count($a) . \"\\n\";\n  var_dump($s, $a);\n  echo \"----------------------------\\n\";\n\n  $s = shape('y' => 20, 'x' => 10);\n  $a = Shapes::toArray($s);\n  echo \"# elements in array = \" . count($a) . \"\\n\";\n  var_dump($s, $a);\n  echo \"----------------------------\\n\";\n\n  $s = shape('id' => \"23456\", 'url' => \"www.example.com\", 'count' => 23);\n  $a = Shapes::toArray($s);   // returns an array of 3 elements, of type string, string, and int, respectively\n  echo \"# elements in array = \" . count($a) . \"\\n\";\n  var_dump($s, $a);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/shape_specific_functions.php.expect",
    "content": "======== Shapes::idx ========\n$v = 10\n$v = 20\n$v = null\n$v = -99\n----------------------------\n$v = 10\n$v = 20\n$v = null\n$v = -99\n\n======== Shapes::keyExists ========\n\nkeyExists($s, 'x') = 1\nkeyExists($s, 'name') = \n\n======== Shapes::removeKey ========\n\narray(0) {\n}\n# elements in array = 0\narray(0) {\n}\narray(0) {\n}\n----------------------------\narray(2) {\n  [\"x\"]=>\n  int(10)\n  [\"y\"]=>\n  int(20)\n}\n# elements in array = 1\narray(1) {\n  [\"y\"]=>\n  int(20)\n}\narray(1) {\n  [\"y\"]=>\n  int(20)\n}\n----------------------------\narray(3) {\n  [\"id\"]=>\n  string(5) \"23456\"\n  [\"url\"]=>\n  string(15) \"www.example.com\"\n  [\"count\"]=>\n  int(23)\n}\n# elements in array = 2\narray(2) {\n  [\"id\"]=>\n  string(5) \"23456\"\n  [\"count\"]=>\n  int(23)\n}\narray(2) {\n  [\"id\"]=>\n  string(5) \"23456\"\n  [\"count\"]=>\n  int(23)\n}\n\n======== Shapes::toArray ========\n\n# elements in array = 0\narray(0) {\n}\narray(0) {\n}\n----------------------------\n# elements in array = 2\narray(2) {\n  [\"x\"]=>\n  int(10)\n  [\"y\"]=>\n  int(20)\n}\narray(2) {\n  [\"x\"]=>\n  int(10)\n  [\"y\"]=>\n  int(20)\n}\n----------------------------\n# elements in array = 2\narray(2) {\n  [\"y\"]=>\n  int(20)\n  [\"x\"]=>\n  int(10)\n}\narray(2) {\n  [\"y\"]=>\n  int(20)\n  [\"x\"]=>\n  int(10)\n}\n----------------------------\n# elements in array = 3\narray(3) {\n  [\"id\"]=>\n  string(5) \"23456\"\n  [\"url\"]=>\n  string(15) \"www.example.com\"\n  [\"count\"]=>\n  int(23)\n}\narray(3) {\n  [\"id\"]=>\n  string(5) \"23456\"\n  [\"url\"]=>\n  string(15) \"www.example.com\"\n  [\"count\"]=>\n  int(23)\n}"
  },
  {
    "path": "tests/Types/shape_subtyping.php",
    "content": "<?hh // strict\n\nnamespace NS_shape_subtyping;\n\nenum Bank: int {\n  INVALID = 0;\n  DEPOSIT = 1;\n  WITHDRAWAL = 2;\n  TRANSFER = 3;\n}\n\ntype Transaction = shape('trtype' => Bank);\ntype Deposit = shape('trtype' => Bank, 'toaccnum' => int, 'amount' => float);\ntype Withdrawal = shape('trtype' => Bank, 'fromaccnum' => int, 'amount' => float);\ntype Transfer = shape('trtype' => Bank, 'fromaccnum' => int, 'toaccnum' => int, 'amount' => float);\n\nfunction main(): void {\n  processTransaction(shape('trtype' => Bank::DEPOSIT, 'toaccnum' => 23456, 'amount' => 100.00));\n  processTransaction(shape('trtype' => Bank::WITHDRAWAL, 'fromaccnum' => 3157, 'amount' => 100.00));\n  processTransaction(shape('trtype' => Bank::TRANSFER, 'fromaccnum' => 23456, 'toaccnum' => 3157, 'amount' => 100.00));\n}\n\nfunction processTransaction(Transaction $t): void {\n  var_dump($t);\n\n  $ary = Shapes::toArray($t);\n\n  switch ($t['trtype']) {\n  case Bank::TRANSFER:\n    echo \"Transfer: \" . ((string)$ary['amount']) . \" from Account \" . ((string)$ary['fromaccnum'])\n      . \" to Account \" . ((string)$ary['toaccnum']) . \"\\n\";\n    break;\n\n  case Bank::DEPOSIT:\n    echo \"Deposit: \" . ((string)$ary['amount']) . \" to Account \" . ((string)$ary['toaccnum']) . \"\\n\";\n    break;\n\n  case Bank::WITHDRAWAL:\n    echo \"Withdrawal: \" . ((string)$ary['amount']) . \" from Account \" . ((string)$ary['fromaccnum']) . \"\\n\";\n    break;\n\n  default:\n    break;\n  }\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();"
  },
  {
    "path": "tests/Types/shape_subtyping.php.expect",
    "content": "array(3) {\n  [\"trtype\"]=>\n  int(1)\n  [\"toaccnum\"]=>\n  int(23456)\n  [\"amount\"]=>\n  float(100)\n}\nDeposit: 100 to Account 23456\narray(3) {\n  [\"trtype\"]=>\n  int(2)\n  [\"fromaccnum\"]=>\n  int(3157)\n  [\"amount\"]=>\n  float(100)\n}\nWithdrawal: 100 from Account 3157\narray(4) {\n  [\"trtype\"]=>\n  int(3)\n  [\"fromaccnum\"]=>\n  int(23456)\n  [\"toaccnum\"]=>\n  int(3157)\n  [\"amount\"]=>\n  float(100)\n}\nTransfer: 100 from Account 23456 to Account 3157"
  },
  {
    "path": "tests/Types/shapes.php",
    "content": "<?hh // strict\n\nnamespace NS_shapes_in_types_dir;\n\nrequire_once 'shapes_rf.php';\n\nfunction f1(\\NS_shapes_rf_in_types_dir\\st2a $p1): void {\n  echo \"----- dumping 'x' => int -----\\n\\n\";\n\n  var_dump($p1);\n}\n\nfunction main(): void {\n/*\n// yes, array string keys can not only be \"...\", can also contain subtitution stuff\n// testing, as double-quoted strings keys are rejected in Shape definitions.\n\n  $q = 'QQQ';\n  $a = array('x' => 10, \"y\" => 20, \"x\\n$q\\tx\" => 30,\n<<<ID\nXXX\nID\n => 40,\n<<<'ID'\nYYY\nID\n => 50);\n\tvar_dump($a);\n*/\n\n  echo \"----------- Play ------------\\n\\n\";\n\n//  $key = 'x';\n//  f1(shape($key => 10));\t// gags: The field '' is missing\n\t\t\t\t// like the shape definition, key must be a string literal\n\n//  var_dump(\\NS_shapes_rf_in_types_dir\\st4b_test2());\n\n  echo \"----------- Create some shape values ------------\\n\\n\";\n\n  $point1 = shape('x' => -3, 'y' => 6);\n  echo \"\\$point1 is \" . $point1['x'] . \"\\n\";\n//  echo \"\\$point1 instanceof Point is \" .\n//    (($point1 instanceof \\NS_shapes_rf_in_types_dir\\Point) ? \"True\" : \"False\") . \"\\n\";\t// False\n\n/*\n// a key must be a string literal; apparently can't be a class constant\n\n// ???\techo \"\\$point1 is \" . $point1[\\NS_shapes_rf_in_types_dir\\C::KEY1] . \"\\n\";\t// The field  is undefined *** WHY IS THIS?\n  $key = 'x';\n  echo \"\\$point1 is \" . $point1[$key] . \"\\n\";\t// The field  is undefined\n\n  echo \"\\$point1 is \" . $point1['z'] . \"\\n\";\t// The field z is undefined\n*/\n\n// Fatal error: syntax error, unexpected '[', expecting ',' or ';'\n\n//  echo \"shape(...)['y'] is \" . shape('x' => -3, 'y' => 6)['y'] . \"\\n\";\n\n  echo \"shape(...)['y'] is \" . (shape('x' => -3, 'y' => 6))['y'] . \"\\n\";\t// works with parens, but shouldn't need them\n\n  $str = \\NS_shapes_rf_in_types_dir\\Point_toString($point1);\n  echo \"\\$point1 is $str\\n\";\n//  echo \"\\$point1 instanceof Point is \" .\n//    (($point1 instanceof \\NS_shapes_rf_in_types_dir\\Point) ? \"True\" : \"False\") . \"\\n\";\t// False\n\n// The following function-call argument is incompatible with PointNT while alias is created using 'newtype'.\n// However, it's okay when 'type' used\n\n//  $str = \\NS_shapes_rf_in_types_dir\\PointNT_toString($point1);\n//  echo \"\\$point1 is $str\\n\";\n\n  $str = \\NS_shapes_rf_in_types_dir\\PointNT_toString(\\NS_shapes_rf_in_types_dir\\PointNT_getOrigin());\n  echo \"Origin is $str\\n\";\n\n  echo \"----------- Create some shape values ------------\\n\\n\";\n\n  $v = is_array(shape('x' => -3, 'y' => 6));\n  echo \"A shape \" . ($v ? \"is\" : \"is not\") . \" an array\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/shapes.php.expect",
    "content": "----------- Play ------------\n\n----------- Create some shape values ------------\n\n$point1 is -3\nshape(...)['y'] is 6\n$point1 is (-3,6)\nOrigin is (0,0)\n----------- Create some shape values ------------\n\nA shape is an array\n"
  },
  {
    "path": "tests/Types/shapes.php.expectf",
    "content": "----------- Play ------------\n\n----------- Create some shape values ------------\n\n$point1 is -3\nshape(...)['y'] is 6\n\nFatal error: Call to undefined function NS_shapes_rf\\Point_toString() in %s/tests/Types/shapes.php on line 62"
  },
  {
    "path": "tests/Types/shapes2.php",
    "content": "<?hh // strict\n\nnamespace NS_shapes2;\n\ntype S1 = shape('a' => int, 'b' => int);\ntype S2 = shape('b' => int, 'a' => int);\n\ntype S3 = shape('a' => int, 'b' => string);\ntype S4 = shape('b' => string, 'a' => int);\n\nclass C {\n  public static S1 $p1 = shape('a' => 10, 'b' => 20);\n  public static S2 $p2 = shape('b' => 20, 'a' => 10);\n\n  public static S3 $p3 = shape('a' => 10, 'b' => 'bbb');\n  public static S4 $p4 = shape('b' => 'bbb', 'a' => 10);\n\n  public static shape('a' => int, 'n' => ?string) $p5a = shape('a' => 10, 'n' => null);\n  public static shape('a' => int, 'n' => ?string) $p5b = shape('a' => 10);\n\n  public shape('a' => int, 'n' => ?string) $p6a = shape('a' => 10, 'n' => null);\n  public shape('a' => int, 'n' => ?string) $p6b = shape('a' => 10);\n\n  public static (int, string) $p7 = tuple(10, 'x');\n  public static (string, int) $p8 = tuple('x', 10);\n}\n\nfunction main(): void {\n  f1(C::$p1);\n  f2(C::$p2);\n\n  echo \"\\nInside function \" . __FUNCTION__ . \"\\n\";\n\n  echo (C::$p1 == C::$p2) ? \"== is True\\n\" : \"== is False\\n\";\n  echo (C::$p1 != C::$p2) ? \"!= is True\\n\" : \"!= is False\\n\";\n  echo (C::$p1 === C::$p2) ? \"=== is True\\n\" : \"=== is False\\n\";\n  echo (C::$p1 !== C::$p2) ? \"!== is True\\n\\n\" : \"!== is False\\n\\n\";\n\n  C::$p1 = C::$p2;\n  echo (C::$p1 == C::$p2) ? \"== is True\\n\" : \"== is False\\n\";\n  echo (C::$p1 != C::$p2) ? \"!= is True\\n\" : \"!= is False\\n\";\n  echo (C::$p1 === C::$p2) ? \"=== is True\\n\" : \"=== is False\\n\";\n  echo (C::$p1 !== C::$p2) ? \"!== is True\\n\\n\" : \"!== is False\\n\\n\";\n\n  C::$p3 = C::$p4;\n  echo (C::$p3 == C::$p4) ? \"== is True\\n\" : \"== is False\\n\";\n  echo (C::$p3 != C::$p4) ? \"!= is True\\n\" : \"!= is False\\n\";\n  echo (C::$p3 === C::$p4) ? \"=== is True\\n\" : \"=== is False\\n\";\n  echo (C::$p3 !== C::$p4) ? \"!== is True\\n\\n\" : \"!== is False\\n\\n\";\n\n  echo \"\\n=== null fields ===\\n\\n\";\n\n  $c = new C();\n  var_dump(C::$p5a, C::$p5b, $c);\n\n  echo \"\\n\\n=== null field access ===\\n\\n\";\n\n  echo \"\\$p5a['a']: \" . C::$p5a['a'] . \"\\n\";\n  echo \"\\$p5a['n']: \" . C::$p5a['n'] . \"\\n\";\n  echo \"\\$p5b['a']: \" . C::$p5b['a'] . \"\\n\";\n  echo \"\\$p5b['n']: \" . C::$p5b['n'] . \"\\n\";\t\t// Undefined index: n\n  echo \"\\$p6a['a']: \" . $c->p6a['a'] . \"\\n\";\n  echo \"\\$p6a['n']: \" . $c->p6a['n'] . \"\\n\";\n  echo \"\\$p6b['a']: \" . $c->p6b['a'] . \"\\n\";\n  echo \"\\$p6b['n']: \" . $c->p6b['n'] . \"\\n\";\t\t// Undefined index: n\n\n  f3(shape('a' => 10, 'n' => 'xyz'));\n  f3(shape('a' => 10, 'n' => null));\n  f3(shape('a' => 10));\t\t\t\t\t// Undefined index: n\n\n/*\n// as tuples are implemented as arrays, do they have issues re assignment and equality?\n\n  echo \"\\n=== tuples ===\\n\";\n\n  var_dump(C::$p7, C::$p8);\n  echo (C::$p7 == C::$p8) ? \"== is True\\n\" : \"== is False\\n\";\n  echo (C::$p7 != C::$p8) ? \"!= is True\\n\" : \"!= is False\\n\";\n  echo (C::$p7 === C::$p8) ? \"=== is True\\n\" : \"=== is False\\n\";\n  echo (C::$p7 !== C::$p8) ? \"!== is True\\n\\n\" : \"!== is False\\n\\n\";\n\n  C::$p7 = C::$p8;\n  echo (C::$p7 == C::$p8) ? \"== is True\\n\" : \"== is False\\n\";\n  echo (C::$p7 != C::$p8) ? \"!= is True\\n\" : \"!= is False\\n\";\n  echo (C::$p7 === C::$p8) ? \"=== is True\\n\" : \"=== is False\\n\";\n  echo (C::$p7 !== C::$p8) ? \"!== is True\\n\" : \"!== is False\\n\";\n*/\n}\n\nfunction f1(S2 $p): void {\n  echo \"\\nInside function \" . __FUNCTION__ . \"\\n\";\n  echo $p['a'] . \", \" . $p['b'] . \"\\n\";\n\n  echo (C::$p1 == $p) ? \"== is True\\n\" : \"== is False\\n\";\n  echo (C::$p1 != $p) ? \"!= is True\\n\" : \"!= is False\\n\";\n  echo (C::$p1 === $p) ? \"=== is True\\n\" : \"=== is False\\n\";\n  echo (C::$p1 !== $p) ? \"!== is True\\n\\n\" : \"!== is False\\n\\n\";\n}\n\nfunction f2(S1 $p): void {\n  echo \"\\nInside function \" . __FUNCTION__ . \"\\n\";\n  echo $p['a'] . \", \" . $p['b'] . \"\\n\";\n\n  echo (C::$p2 == $p) ? \"== is True\\n\" : \"== is False\\n\";\n  echo (C::$p2 != $p) ? \"!= is True\\n\" : \"!= is False\\n\";\n  echo (C::$p2 === $p) ? \"=== is True\\n\" : \"=== is False\\n\";\n  echo (C::$p2 !== $p) ? \"!== is True\\n\\n\" : \"!== is False\\n\\n\";\n}\n\nfunction f3(shape('a' => int, 'n' => ?string) $p): void {\n  echo \"\\nInside function \" . __FUNCTION__ . \"\\n\";\n\n  echo \"\\$p['a']: \" . $p['a'] . \"\\n\";\n  echo \"\\$p['n']: \" . $p['n'] . \"\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/shapes2.php.expectf",
    "content": "\nInside function NS_shapes2\\f1\n10, 20\n== is True\n!= is False\n=== is True\n!== is False\n\n\nInside function NS_shapes2\\f2\n10, 20\n== is True\n!= is False\n=== is True\n!== is False\n\n\nInside function NS_shapes2\\main\n== is True\n!= is False\n=== is False\n!== is True\n\n== is True\n!= is False\n=== is True\n!== is False\n\n== is True\n!= is False\n=== is True\n!== is False\n\n\n=== null fields ===\n\narray(2) {\n  [\"a\"]=>\n  int(10)\n  [\"n\"]=>\n  NULL\n}\narray(1) {\n  [\"a\"]=>\n  int(10)\n}\nobject(NS_shapes2\\C)#1 (2) {\n  [\"p6a\"]=>\n  array(2) {\n    [\"a\"]=>\n    int(10)\n    [\"n\"]=>\n    NULL\n  }\n  [\"p6b\"]=>\n  array(1) {\n    [\"a\"]=>\n    int(10)\n  }\n}\n\n\n=== null field access ===\n\n$p5a['a']: 10\n$p5a['n']: \n$p5b['a']: 10\n\nNotice: Undefined index: n in %s/tests/Types/shapes2.php on line 61\n$p5b['n']: \n$p6a['a']: 10\n$p6a['n']: \n$p6b['a']: 10\n\nNotice: Undefined index: n in %s/tests/Types/shapes2.php on line 65\n$p6b['n']: \n\nInside function NS_shapes2\\f3\n$p['a']: 10\n$p['n']: xyz\n\nInside function NS_shapes2\\f3\n$p['a']: 10\n$p['n']: \n\nInside function NS_shapes2\\f3\n$p['a']: 10\n\nNotice: Undefined index: n in %s/tests/Types/shapes2.php on line 114\n$p['n']: "
  },
  {
    "path": "tests/Types/shapes_rf.php",
    "content": "<?hh // strict\n\nnamespace NS_shapes_rf_in_types_dir;\n\n// ------------------------------------------------------------\n\nclass C {\n  const string KEY1 = 'x';\n  const int KEY2 = 3;\n  const bool KEY3 = true;\n  const num KEY4 = 2.5;\n}\n\n// ----------- Is a shape really a type? Yes, this has changed ------------\n\nfunction CXf1(shape('x' => int, 'y' => int) $p1): void {}\nfunction CXf2(): shape('x' => int, 'y' => int) { return shape('x' => 3, 'y' => 5); }\nclass CX {\n  private ?shape('x' => int, 'y' => int) $p1 = null;\n}\n\n// Previously, we had to make a shape an alias before using it\n\ntype Point = shape('x' => int, 'y' => int);\nfunction CYf1(Point $p1): void {}\nfunction CYf2(): Point { return shape('x' => 10, 'y' => 12); }\nclass CY {\n  private Point $p1 = shape('x' => 0, 'y' => 5);\n}\n\nfunction Point_toString(Point $p): string {\n  return '(' . $p['x'] . ',' . $p['y'] . ')';\n}\n\n// It looks like the 2 forms of name can't be mixed\n//function CYf3(): Point { return shape(C::KEY1 => 10, 'y' => 12); }\n\n// Can the order of fields in the literal differ from the shape-specifier?\nfunction CYf4(): Point { return shape('y' => 12, 'x' => 10); }\t// apparently, YES\n\n// Can a shape literal initialize fewer fields than exist? NO\n//function CYf5(): Point { return shape('x' => 10); }\t// The field 'y' is missing\n//function CYf6(): Point { return shape('y' => 12); }\t// The field 'x' is missing\n\n//type PointNT = shape('x' => int, 'y' => int);\nnewtype PointNT = shape('x' => int, 'y' => int);\n\nfunction PointNT_toString(PointNT $p): string {\n  return '(' . $p['x'] . ',' . $p['y'] . ')';\n}\n\nfunction PointNT_getOrigin(): PointNT {\n  return shape('x' => 0, 'y' => 0);\n}\n\n// ----------- Shape with no fields ------------\n\ntype st1 = shape();\t\t\t// can have no fields\n\n// ----------- Shapes with literal string keys ------------\n\ntype st2a = shape('x' => int);\t\t// can have 1 field with '-quoted string key\n//type st2b = shape('x'.'x' => int);\t// gags: key must be a literal NOT an expression\n\n//type st2c = shape(\"x\" => int);\t// gags on \"-quoted string: Expected string literal or class constant\n//type st2d = shape(\"x\\tx\\$\" => int);\t// gags too\n\n/*\n// can't use a heredoc literal\n// hhvm says at <<< line: Fatal error: syntax error, unexpected T_START_HEREDOC, expecting ')'\n\ntype st2e = shape(\n<<<ID\nXXX\nID\n => int);\n*/\n\n/*\n// can't use a nowdoc literal\n// hhvm says at <<< line: Fatal error: syntax error, unexpected T_START_HEREDOC, expecting ')'\n\ntype st2f = shape(\n<<<'ID'\nYYY\nID\n => int);\n*/\n\n// ----------- Shapes with string keys, but using class constants ------------\n\ntype st3a = shape(C::KEY1 => int);\t// OK; class constant of type string\nfunction st3a_test(): st3a { return shape(C::KEY1 => 88); }\n\n// Can I mix the 2 forms? Apparently not\n\n//type st3b = shape(C::KEY1 => int, 'y' => int);\t// Shape uses class constant as field name; But expected a literal string\n//type st3c = shape('y' => int, C::KEY1 => int);\t// Shape uses literal string as field name; But expected a class constant\n\n// ----------- Shapes with int keys ------------\n\n// There seems to be confusion about whether a key can have type int. The answer is NO!\n\n//type st4a = shape(3 => int);\t\t// gags: Expected string literal or class constant\ntype st4b = shape(C::KEY2 => int);\t// but can have an int key via class constant!!!\n//function st4b_test1(): st4b { return shape(3 => 99); }\t// gags: Expected string literal or class constant\nfunction st4b_test2(): st4b { return shape(C::KEY2 => 99); }\t// but can do it through a class constant\n\n//type st4c = shape('x' => int, 3 => int);\t// gags: Expected string literal or class constant\n//type st4d = shape('x' => int, C::KEY2 => int);\t// gags: Shape uses class constant as field name;\n\t\t\t\t\t\t//       But expected a literal string\n\n//type st5a = shape(true => int);\t// gags: Expected string literal or class constant\n//type st5b = shape(C::KEY3 => int);\t// gags: A shape field name must be an int or string; Not a bool\n\n//type st6a = shape(2.5 => int);\t// gags: Expected string literal or class constant\n//type st6b = shape(C::KEY4 => int);\t// gags: A shape field name must be an int or string; Not a num\n\n// ----------- Shapes with duplicate keys ------------\n\n//type st7a = shape('abc' => int,'abc' => int);\t\t// can't have duplicate keys\n//type st7b = shape('cde' => int,'cde' => float);\t// ditto\n\n// ----------- Shapes containing exotic types (why not?) ------------\n\ntype st8 = shape('n1' => (int, float),'n2' => ?(function (array<num>): bool));\n\n// ----------- Some examples of shape literals ------------\n\ntype Point3 = shape('x' => int, 'y' => int);\nfunction getY(): int { return 123; }\nfunction get_Point3(): Point3 {\n  $prevX = 10;\n  return shape('x' => $prevX, 'y' => getY());\n}\n\ntype IdSet = shape('id' => ?string, 'url' => ?string, 'count' => int);\nfunction get_IdSet(): IdSet {\n  return shape('id' => null, 'url' => null, 'count' => 0);\n}\n\n\n\n\n\n"
  },
  {
    "path": "tests/Types/shapes_rf.php.expect",
    "content": ""
  },
  {
    "path": "tests/Types/string.php",
    "content": "<?hh // strict\n\nnamespace NS_string;\n\nclass C {\n  const string GREETING = \"Hello\";\n  private string $prop = 'Now';\n\n  public function setProp(string $val): void {\n    $this->prop = $val;\n  }\n\n  public function getProp(): string {\n    return $this->prop;\n  }\n}\n"
  },
  {
    "path": "tests/Types/string.php.expect",
    "content": ""
  },
  {
    "path": "tests/Types/this.php",
    "content": "<?hh // strict\n\nnamespace NS_this;\n\ntrait TR {\n\n// constants\n\n  abstract const ?this TRM1a;\n  const ?this TRM1c = null;\n\n// methods\n\n  abstract public function TRf(this $val): this;\n}\n\ninterface I {\n\n// constants\n\n  abstract const ?this IM1a;\n  const ?this IM1c = null;\n\n// methods\n\n  public function inf(this $val): this;\n\n// type constants\n\n  abstract const type IT1 as this;\n}\n\nabstract class C implements I {\n\n// constants\n\n  abstract const ?this M1a;\n  const ?this M1c = null;\n\n  const ?this IM1a = null;\n\n// properties\n\n//  static private this $p1s;\t// The type \"this\" cannot be used as the type of a static member variable\n//  static private ?this $p2s;\t// The type \"this\" cannot be used as the type of a static member variable\n\n  private string $name;\n\n  private ?this $p1c;\n  protected ?this $p2c;\n  public ?this $p3c;\n\n// constructor\n\n  public function __construct(string $name) {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    $this->name = $name;\n    var_dump($this); \n    $this->setProp($this);\n    $this->p2c = $this->getProp();\n    var_dump($this->p2c); \n  }\n\n// methods\n\n  public function setProp(this $val): void {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    var_dump($val); \n    $this->p1c = $val;\n  }\n\n  public function getProp(): ?this {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    var_dump($this->p1c); \n    return $this->p1c;\n  }\n\n  private function privf(this $val): this { return $val; }\n  private static function privsf(this $val): this { return $val; }\n  protected function protf(this $val): this { return $val; }\n  protected static function protsf(this $val): this { return $val; }\n  public function pubf(this $val): this { return $val; }\n  public static function pubsf(this $val): this {\n    echo \"Inside \" . __METHOD__ . \"\\n\";\n    var_dump($val); \n    return $val;\n  }\n  public function inf(this $val): this { return $val; }\n\n// type constants\n\n  abstract const type T1 as this;\n}\n\nclass D extends C {\n  const ?this M1a = null;\n  const type T1 = this;\n  const type IT1 = this;\n}\n\nclass E extends D {}\n\n//class G<T as this> {}\t\t// The type \"this\" cannot be used as a constraint on a generic class \n//class G<T as ?this> {}\t// The type \"this\" cannot be used as a constraint on a generic class \n\nfunction main(): void {\n  $d = new D(\"AA\");\n  var_dump($d);\n  D::pubsf(new D(\"BB\"));\n  E::pubsf(new E(\"CC\"));\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();"
  },
  {
    "path": "tests/Types/this.php.expectf",
    "content": "\nFatal error: Traits cannot have constants in %s/tests/Types/this.php on line 9"
  },
  {
    "path": "tests/Types/tuple.php",
    "content": "<?hh // strict\n\nnamespace NS_tuple;\n\nclass C {\n//  const (int, string) T = tuple(2, 'aa'); // *** no way to write a tuple constant expression\n  private (int, string) $prop = tuple(12, 'green');\n\n  public function setProp((int, string) $val): void {\n    $this->prop = $val;\n  }\n\n  public function getProp(): (int, string) {\n    return $this->prop;\n  }\n}\n"
  },
  {
    "path": "tests/Types/tuple.php.expect",
    "content": ""
  },
  {
    "path": "tests/Types/type_aliases.php",
    "content": "<?hh // strict\n\nrequire_once 'type_aliases_rf.php';\n\nnamespace NS_type_aliases;\n\n// TTA == Transparent type alias\n// OTA == Opaque type alias\n\nnewtype OTA1d = TTA1a;\ntype TTA1e = OTA1d;\n\n// ------------------------------------------------------\n\nfunction f1(TTA_n_bool $p1, TTA_n_bool $p2): void {\n  $p1 = true;\n  $p1 = null;\n  $p1 = false;\n\n  $p2 = true;\n  $p2 = null;\n  $p2 = false;\n}\n\n// ------------------------------------------------------\n\nfunction f2(Counter $p1, Counter $p2): void {\n  ++$p1;\t\t\t// int-like operations are allowed because of Counter's constraint\n  $v1 = $p1 + $p2;\t// int-like operations are allowed because of Counter's constraint\n}\n\n// ------------------------------------------------------\n\nclass C_bool {\n  public static function fa(bool $p1, TTA_bool1 $p2, TTA_bool2 $p3, TTA_bool3 $p4): void {}\n  public static function fc(bool $p1, OTA_bool1 $p2, OTA_bool2 $p3, OTA_bool3 $p4): void {}\n  public static function fb(bool $p1, TTA_bool1 $p2, OTA_bool1 $p3): void {\n    C_bool::fa($p1, $p1, $p1, $p1);\n    C_bool::fa($p2, $p2, $p2, $p2);\n//    C_bool::fa($p3, $p3, $p3, $p3);\t// all 4 are incompatible\n//    C_bool::fc($p1, $p1, $p1, $p1);\t// args 2, 3, 4 are incompatible\n//    C_bool::fc($p2, $p2, $p2, $p2);\t// args 2, 3, 4 are incompatible\n//    C_bool::fc($p3, $p3, $p3, $p3);\t// args 1, 3, 4 are incompatible\n  }\n\n// treat alias like a predefined type name: add ?, array<>, Vector<>\n\n  public static function fz(?TTA_bool1 $p1, array<TTA_bool2> $p2, Vector<TTA_bool3> $p3): void {}\n}\n\n// ------------------------------------------------------\n\nclass C_enum_Modes {\n  public static function fa(Modes $p1, TTA_enum_Modes $p2, OTA_enum_Modes $p3): void {}\n  public static function fb(Modes $p1, TTA_enum_Modes $p2, OTA_enum_Modes $p3): void {\n//    C_enum_Modes::fa($p1, $p1, $p1);\t// 3rd arg is incompatible\n//    C_enum_Modes::fa($p2, $p2, $p2);\t// 3rd arg is incompatible\n//    C_enum_Modes::fa($p3, $p3, $p3);\t// 1st and 3rd args are incompatible\n//    C_enum_Modes::fa(Modes::Stopped, Modes::Stopped, Modes::Stopped);\t3rd arg is incompatible\t}\n/*\n    C_enum_Modes::fa(\n      TTA_enum_Modes::Stopped,\t// all gag on xx::\n      TTA_enum_Modes::Stopped,\n      TTA_enum_Modes::Stopped\n    );\n*/\n/*\n    C_enum_Modes::fa(\n      OTA_enum_Modes::Stopped,\t// all gag on xx::\n      OTA_enum_Modes::Stopped,\n      OTA_enum_Modes::Stopped\n    );\n*/\n  }\n}\n\n// ------------------------------------------------------\n\nclass C_arrays {\n  public static function fa(TTA_array_string $p1, TTA_array_array_string $p2): void {}\n  public static function fb(TTA_array_string $p1): void {\n    C_arrays::fa($p1, array($p1, array('aa', 'bb')));\n  }\n}\n\n// ------------------------------------------------------\n\nclass C_Fullname {\n  private ?TTA_class_Fullname $pr = null;\n  public static function fa(TTA_class_Fullname $p1, array<TTA_class_Fullname> $p2): void {\n    $v = $p1->firstName;\n    $v = $p2[0]->lastName;\n  }\n  \n  public static function fb(OTA_class_Fullname $p1, array<OTA_class_Fullname> $p2): void {\n//    $v = $p1->firstName;\n//    $v = $p2[0]->lastName;\n  }\n}\n\n// ------------------------------------------------------\n\nclass C_MyCollection {\n  public static function fa(TTA_interface_MyCollection1 $p1, TTA_interface_MyCollection3 $p2): void {}\n  public static function fb(TTA_interface_MyCollection1 $p1, TTA_interface_MyCollection3 $p2): void {\n    C_MyCollection::fa($p1, $p2);\n  }\n}\n\n// ------------------------------------------------------\n\nclass C_tuple {\n  private ?TTA_tuple $pr = null;\n  public static function fa(TTA_tuple $p1, array<TTA_tuple> $p2): void {}\n}\n\n// ------------------------------------------------------\n\nclass C_closure {\n  private ?TTA_closure $pr = null;\n  public static function fa(TTA_closure $p1, array<TTA_closure> $p2): void {\n    $p1(123);\n    $p2[0](123);\n  }\n}\n\n// ------------------------------------------------------\n\nfunction CYf1(TTA_shape_point $p1): void {}\nfunction CYf2(): TTA_shape_point { return shape('x' => 10, 'y' => 12); }\nclass CY {\n  private TTA_shape_point $p1 = shape('x' => 0, 'y' => 5);\n}\n\nfunction addComplex(TTA_shape_complex $c1, TTA_shape_complex $c2): TTA_shape_complex {\n  $result = $c1;\n  //\t...\n  return $result;\n}\n\n// ------------------------------------------------------\n\nfunction main(): void {\n//  C_bool::fb(true, true, true);\t// 3rd arg incompatible\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/type_aliases.php.expectf",
    "content": "\nFatal error: Namespace declaration statement has to be the very first statement in the script: (Line: 5, Char: 26) in %s/tests/Types/type_aliases.php on line 5"
  },
  {
    "path": "tests/Types/type_aliases_rf.php",
    "content": "<?hh // strict\n\nnamespace NS_type_aliases;\n\n// TTA == Transparent type alias\n// OTA == Opaque type alias\n\n// ------------------------------------------------------\n\ntype TTA1a = int;\nnewtype OTA1b = TTA1a;\ntype TTA1c = OTA1b;\n\n// ------------------------------------------------------\n\ntype TTA_bool1 = bool;\nnewtype OTA_bool1 = bool;\ntype TTA_bool2 = bool;\t\t// duplicate aliases\nnewtype OTA_bool2 = bool;\t// duplicate aliases\ntype TTA_bool3 = TTA_bool1;\t// aliasing an alias\nnewtype OTA_bool3 = OTA_bool1;\t// aliasing an alias\n\n// ------------------------------------------------------\n\n\n/*\n// Discovered to be no longer accepted as of Jan 18, 2016\n\ntype TTA_void = void;\nnewtype OTA_void = void;\n*/\n\ntype TTA_int = int;\ntype TTA_float = float;\ntype TTA_num = num;\ntype TTA_string = string;\ntype TTA_arraykey = arraykey;\ntype TTA_resource = resource;\n\ntype TTA_n_bool = ?TTA_bool1;\t\t// using a ? modifier + an alias\nnewtype OTA_n_bool = ?OTA_bool1;\t// using a ? modifier + an alias\n\ntype TTA_n_int = ?int;\ntype TTA_n_n_int = ?TTA_n_int;\t\t// I don't think this should be allowed\n\ntype TTA_mixed = mixed;\ntype TTA_n_mixed = ?TTA_mixed;\t\t// I don't think this should be allowed\n\n// ------------------------------------------------------\n\nenum Modes: int { Stopped = 0; Stopping = 1; Starting = 2; Started = 3; }\ntype TTA_enum_Modes = Modes;\nnewtype OTA_enum_Modes = Modes;\n\n// ------------------------------------------------------\n\ntype TTA_array_string = array<string>;\nnewtype OTA_array_string = array<string>;\ntype TTA_array_array_string = array<array<string>>;\nnewtype OTA_array_array_string = array<array<string>>;\n\n// ------------------------------------------------------\n\nclass Fullname {\n  public string $firstName = '';\n  public string $lastName = '';\n}\ntype TTA_class_Fullname = Fullname;\nnewtype OTA_class_Fullname = Fullname;\n\n// ------------------------------------------------------\n\ninterface MyCollection<T> {\n  public function put(T $item): void;\n  public function get(): T;\n}\ntype TTA_interface_MyCollection1 = MyCollection;\ntype TTA_interface_MyCollection2<T> = MyCollection<T>;\t// Okay? Really?\ntype TTA_interface_MyCollection3 = MyCollection<int>;\n\n// ------------------------------------------------------\n\ntrait TR1 { public function compute(): void {} }\ntrait TR2 { public function compute(): void {} }\ntrait TR3 { public function sort(): void {} }\ntrait TR4a {\n  use TR3;\n  use TR1, TR2;\n}\n\n/*\ntype TTA_trait1 = TR1;\t// TR1 is uninstantiable\ntype TTA_trait2 = TR2;\t// TR2 is uninstantiable\ntype TTA_trait3 = TR3;\t// TR3 is uninstantiable\ntrait TR4b {\n  use TTA_trait3;\n  use TTA_trait1, TTA_trait2;\n}\n*/\n// ------------------------------------------------------\n\ntype TTA_tuple = (int, string, int);\nnewtype OTA_tuple = (int, string, int);\n\n// ------------------------------------------------------\n\ntype TTA_closure = (function (int): void);\nnewtype OTA_closure = (function (int): void);\n\n// ------------------------------------------------------\n\ntype TTA_shape_point = shape('x' => int, 'y' => int);\nnewtype OTA_shape_point = shape('x' => int, 'y' => int);\n\ntype TTA_shape_complex = shape('real' => float, 'imag' => float);\nnewtype OTA_shape_complex = shape('real' => float, 'imag' => float);\n\n// ------------------------------------------------------\n\nnewtype Counter as int = int;\n//newtype Counter as float = int;\t// float not compatible with int\n//newtype Counter as num = int;\n//newtype OTA_x1 as int = Fullname;\t// int not compatible with Fullname\n\n// ------------------------------------------------------\n"
  },
  {
    "path": "tests/Types/type_aliases_rf.php.expectf",
    "content": "\nFatal error: Method 'compute' declared in multiple traits in %s/tests/Types/type_aliases_rf.php on line 86"
  },
  {
    "path": "tests/Types/type_inferencing.php",
    "content": "<?hh // strict\n\nnamespace NS_type_inferencing;\n\nclass C {\n  const C1 = 10;\t// type omitted; int inferred from initializer\n  const string C2 = \"red\";\n}\n\nfunction f(int $p1 = -1): void {\n\t\t\t// on entry to the function, $p1 has the declared type int\n  var_dump($p1);\n  $p1 = 23.56;\t\t// $p1 has the inferred type float\n  var_dump($p1);\n\n  $v = 'acb';\t\t// $v has type string\n  var_dump($v);\n  $v = true;\t\t// $v has type bool\n  var_dump($v);\n  $v = array('red' => 10, 'green' => 15, 'white' => 20); // $v has type map-like array of int\n  var_dump($v);\n  $v = new C();\t\t// $v has type C\n  var_dump($v);\n}\n\nfunction main (): void {\n  f();\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/type_inferencing.php.expect",
    "content": "int(-1)\nfloat(23.56)\nstring(3) \"acb\"\nbool(true)\narray(3) {\n  [\"red\"]=>\n  int(10)\n  [\"green\"]=>\n  int(15)\n  [\"white\"]=>\n  int(20)\n}\nobject(NS_type_inferencing\\C)#1 (0) {\n}"
  },
  {
    "path": "tests/Types/type_side_effects.php",
    "content": "<?hh // strict\n\nnamespace NS_type_side_effects;\n\nclass Cx {\n  private ?int $prop1 = 8;\t\t// although starts out holding an int\n\n  public function m(): void {\n//    $x = $this->prop1 << 2;\t\t// disallowed; type of $this->prop1 is not int    \n\n    if (is_int($this->prop1)) {\t\t// type side effect occurs; $this->prop1 has type int\n      $x = $this->prop1 << 2;\t\t// allowed; type is int \n//      $this->n(); \n\n// As n could change the contents of $prop1 back to null, checker reports\n// \"All the local information about the member prop1 has been invalidated during this call.\n// $y is no longer guaranteed [to have the same type as before the call]\"\n\n      $x = $this->prop1 << 2;\t\t// disallowed; type of $this->prop1 might not be int \n    }\n  }\n\n  public function n(): void {\n    var_dump($this->prop1);    \n    $this->prop1 = null;  \t// make it hold an int  \n    var_dump($this->prop1);    \n  }\n}\n\nfunction F_bool(bool $p1): void {}\nfunction F_n_bool(?bool $p1): void {\n//  F_bool($p1);\t\t// type not yet determined\n\n  if (is_bool($p1)) {\t// type side effect occurs; $p1 has type bool\n    F_bool($p1);\t// allowed; type is bool\n  } else {\t\t// type side effect occurs; $p1 has type null\n//    F_bool($p1);\t// disallowed; type is not bool\n  }\n\n  if (is_null($p1)) {\t// type side effect occurs; $p1 has type null\n//  F_bool($p1);\t// disallowed; type is not bool\n  } else {\t\t// type side effect occurs; $p1 has type bool\n    F_bool($p1);\t// allowed; type is bool\n  }\n\n  if (!is_null($p1)) {\t// type side effect occurs; $p1 has type bool\n    F_bool($p1);\t// allowed; type is bool\n  }\n\n  if ($p1 !== null) {\t// type side effect occurs; $p1 has type bool\n    F_bool($p1);\t// allowed; type is bool\n  }\n\n  if ($p1) {\t\t// type side effect occurs; $p1 has type bool\n    F_bool($p1);\t// allowed; type is bool\n  } else {\n//    F_bool($p1);\t// disallowed; type is not bool\n  }\n}\n\nfunction F_n_int(?int $p1): void {\n//  $x = $p1 % 3;\t// disallowed; % not defined for ?int\n  if (is_int($p1)) {\t// type side effect occurs; $p1 has type int\n    $x = $p1 % 3;\t// allowed; type is int\n  }\n\n  if (is_null($p1)) {\t// type side effect occurs; $p1 has type null\n//  $x = $p1 % 3;\t// disallowed; type is not int\n  } else {\t\t// type side effect occurs; $p1 has type int\n    $x = $p1 % 3;\t// allowed; type is int\n  }\n\n  if (!is_null($p1)) {\t// type side effect occurs; $p1 has type int\n    $x = $p1 % 3;\t// allowed; type is int\n  }\n\n  if ($p1 !== null) {\t// type side effect occurs; $p1 has type int\n    $x = $p1 % 3;\t// allowed; type is int\n  }\n\n  if ($p1) {\t\t// type side effect occurs; $p1 has type int\n    $x = $p1 % 3;\t// allowed; type is int\n  } else {\n//    $x = $p1 % 3;\t// disallowed; type is null\n\n\n  if (is_int($p1) && $p1 > 10) {\t// type side effect occurs; $p1 has type int\n    $x = $p1 % 3;\t// accepted; % defined for int\n  }\n\n/*\n  if (is_int($p1) || $p1 > 10) {\t// type side effect not guaranteed to occur\n    $x = $p1 % 3;\t// rejected\n  }\n*/\n\n  is_int($p1) ? $x = $p1 % 3 : $x = -1;\t\t// accepted\n//  !is_int($p1) ? $x = $p1 % 3 : $x = -1;\t// rejected\n  }\n}\n\nfunction F_n_float(?float $p1): void {\n//  $x = $p1**2;\t// disallowed; ** not defined for ?float\n  if (is_float($p1)) {\t// type side effect occurs; $p1 has type float\n    $x = $p1**2;\t// allowed; type is float\n  }\n\n  if (is_null($p1)) {\t// type side effect occurs; $p1 has type null\n//  $x = $p1**2;\t// disallowed; ** not defined for null\n  } else {\t\t// type side effect occurs; $p1 has type float\n    $x = $p1**2;\t// allowed; type is float\n  }\n\n  if (!is_null($p1)) {\t// type side effect occurs; $p1 has type float\n    $x = $p1**2;\t// allowed; type is float\n  }\n\n  if ($p1 !== null) {\t// type side effect occurs; $p1 has type float\n    $x = $p1**2;\t// allowed; type is float\n  }\n\n  if ($p1) {\t\t// type side effect occurs; $p1 has type int\n    $x = $p1**2;\t// allowed; type is float\n  } else {\n//    $x = $p1**2;\t// disallowed; type is null\n  }\n}\n\nfunction F_n_num(?num $p1): void {\n//  $x = $p1**2;\t// disallowed; ** not defined for ?num\n  if (is_int($p1)) {\t// type side effect occurs; $p1 has type num\n    $x = $p1**2;\t// allowed; type is num\n  }\n\n  if (is_float($p1)) {\t// type side effect occurs; $p1 has type float\n    $x = $p1**2;\t// allowed; type is float\n  }\n\t\n  if (is_int($p1) || is_float($p1)) {\n// ***  $x = $p1**2;\t// *** one might think this is okay, but in fact is not\n  }\n\n  if (is_null($p1)) {\t// type side effect occurs; $p1 has type null\n//  $x = $p1**2;\t// disallowed; ** not defined for null\n  } else {\t\t// type side effect occurs; $p1 has type num\n    $x = $p1**2;\t// allowed; type is num\n  }\n\n  if (!is_null($p1)) {\t// type side effect occurs; $p1 has type num\n    $x = $p1**2;\t// allowed; type is num\n  }\n\n  if ($p1 !== null) {\t// type side effect occurs; $p1 has type num\n    $x = $p1**2;\t// allowed; type is num\n  }\n}\n\nfunction F_num(num $p1): void {\n//  $x = $p1 % 3;\t// disallowed; % not defined for num\n  if (is_int($p1)) {\t// type side effect occurs; $p1 has type int\n    $x = $p1 % 3;\t// allowed; type is int\n  }\n}\n\nfunction F_string(string $p1): void {}\nfunction F_n_string(?string $p1): void {\n//  F_string($p1);\t// disallowed; function requires a string\n\n  if (is_string($p1)) {\t// type side effect occurs; $p1 has type string\n    F_string($p1);\t// allowed; type is string\n  } else {\t\t// type side effect occurs; $p1 has type null\n//  F_string($p1);\t// disallowed; function requires a string\n  }\n\n  if (is_null($p1)) {\t// type side effect occurs; $p1 has type null\n//  F_string($p1);\t// disallowed; function requires a string\n  } else {\t\t// type side effect occurs; $p1 has type string\n    F_string($p1);\t// allowed; type is string\n  }\n\n  if (!is_null($p1)) {\t// type side effect occurs; $p1 has type string\n    F_string($p1);\t// allowed; type is string\n  }\n\n  if ($p1 !== null) {\t// type side effect occurs; $p1 has type string\n    F_string($p1);\t// allowed; type is string\n  }\n}\n\nfunction F_n_arraykey(?arraykey $p1): void {\n//  $x = $p1 % 3;\t// disallowed; % not defined for ?arraykey\n//  F_string($p1);\t// disallowed; function requires a string\n//  F_arraykey($p1);\t// disallowed; function requires an arraykey\n\n  if (is_int($p1)) {\t// type side effect occurs; $p1 has type int\n    $x = $p1 % 3;\t// allowed; type is int\n  }\n\n  if (is_string($p1)) {\t// type side effect occurs; $p1 has type string\n    F_string($p1);\t// allowed; type is string\n  }\n\n  if ($p1 !== null) {\t// type side effect occurs; $p1 has type arraykey\n    F_arraykey($p1);\t// allowed; type is arraykey\n  }\n}\n\nfunction F_arraykey(arraykey $p1): void {\n//  $x = $p1 % 3;\t// disallowed; % not defined for arraykey\n//  F_string($p1);\t// disallowed; function requires a string\n\n  if (is_int($p1)) {\t// type side effect occurs; $p1 has type int\n    $x = $p1 % 3;\t// allowed; type is int\n  }\n\n  if (is_string($p1)) {\t// type side effect occurs; $p1 has type string\n    F_string($p1);\t// allowed; type is string\n  }\n}\n\nfunction F_array(array<int> $p1): void {}\nfunction F_n_array(?array<int> $p1): void {\n//  F_array($p1);\t// disallowed; function requires an array<int>\n\n  if (is_array($p1)) {\t// type side effect occurs; $p1 has type array<int>\n    F_array($p1);\t// allowed; type is array<int>\n  } else {\t\t// type side effect occurs; $p1 has type null\n//  F_array($p1);\t// disallowed; function requires an array<int>\n  }\n\n  if (is_null($p1)) {\t// type side effect occurs; $p1 has type null\n//  F_array($p1);\t// disallowed; function requires an array<int>\n  } else {\t\t// type side effect occurs; $p1 has type array<int>\n    F_array($p1);\t// allowed; type is array<int>\n  }\n\n  if (!is_null($p1)) {\t// type side effect occurs; $p1 has type array<int>\n    F_array($p1);\t// allowed; type is array<int>\n  }\n\n  if ($p1 !== null) {\t// type side effect occurs; $p1 has type array<int>\n    F_array($p1);\t// allowed; type is array<int>\n  }\n}\n\nfunction F_resource(resource $p1): void {}\nfunction F_n_resource(?resource $p1): void {\n//  F_resource($p1);\t// disallowed; function requires a resource\n\n  if (is_resource($p1)) {// type side effect occurs; $p1 has type resource\n    F_resource($p1);\t// allowed; type is resource\n  } else {\t\t// type side effect occurs; $p1 has type null\n//  F_resource($p1);\t// disallowed, type is not resource\n  }\n\n  if (is_null($p1)) {\t// type side effect occurs; $p1 has type null\n//  F_resource($p1);\t// type is not resource\n  } else {\t\t// type side effect occurs; $p1 has type resource\n    F_resource($p1);\t// allowed; type is resource\n  }\n\n  if (!is_null($p1)) {\t// type side effect occurs; $p1 has type resource\n    F_resource($p1);\t// allowed; type is resource\n  }\n\n  if ($p1 !== null) {\t// type side effect occurs; $p1 has type resource\n    F_resource($p1);\t// allowed; type is resource\n  }\n}\n\nclass C {\n  public function f(): void {}\n}\n\nfunction F_n_classC(?C $p1): void {\n//  $p1->f();\t\t// disallowed; function requires a C\n\n\n// *** is_object == true does NOT determine the type as being usable as an object\n\n  if (is_object($p1)) {\n//  $p1->f();\t\t// disallowed\n  } else {\n//  $p1->f();\t\t// disallowed\n  }\n\n  if (is_null($p1)) {\t// type side effect occurs; $p1 has type null\n//  \t$p1->f();\t// disallowed; type is not C\n  } else {\n    $p1->f();\t\t// allowed; type is C\n  }\n\n  if (!is_null($p1)) {\t// type side effect occurs; $p1 has type C\n    $p1->f();\t\t// allowed; type is C\n  }\n\n  if ($p1 !== null) {\t// type side effect occurs; $p1 has type C\n    $p1->f();\t\t// allowed; type is C\n  }\n}\n\nfunction F_tuple((int, int) $p1): void {}\nfunction F_n_tuple(?(int, int) $p1): void {\n//  F_tuple($p1);\t// disallowed; function requires a tuple\n\n  if (is_null($p1)) {\t// type side effect occurs; $p1 has type null\n//  F_tuple($p1);\t// disallowed; type is not tuple\n  } else {\t\t// type side effect occurs; $p1 has type tuple\n    F_tuple($p1);\t// allowed; type is tuple\n  }\n\n  if (!is_null($p1)) {\t// type side effect occurs; $p1 has type null\n    F_tuple($p1);\t// allowed; type is tuple\n  }\n\n  if ($p1 !== null) {\t// type side effect occurs; $p1 has type null\n    F_tuple($p1);\t// allowed; type is tuple\n  }\n}\n\ntype MyPoint = shape('x' => int, 'y' => int);\nfunction F_shape(MyPoint $p1): void {}\nfunction F_n_shape(?MyPoint $p1): void {\n//  F_shape($p1);\t// disallowed; function requires a shape\n\n  if (is_null($p1)) {\t// type side effect occurs; $p1 has type null\n//  F_shape($p1);\t// disallowed; type is not shape\n  } else {\t\t// type side effect occurs; $p1 has type MyPoint\n    F_shape($p1);\t// allowed; type is shape\n  }\n\n  if (!is_null($p1)) {\t// type side effect occurs; $p1 has type MyPoint\n    F_shape($p1);\t// allowed; type is shape\n  }\n\n  if ($p1 !== null) {\t// type side effect occurs; $p1 has type MyPoint\n    F_shape($p1);\t// allowed; type is shape\n  }\n}\n\nfunction F_closure((function (int): int) $p1): void {}\nfunction F_n_closure(?(function (int): int) $p1): void {\n//  F_closure($p1);\t// disallowed; function requires a closure\n\n  if (is_callable($p1)) {\n\n// *** is_closure == true does NOT determine the type as being usable as a closure\n\n//  F_closure($p1);\t// disallowed\n  } else {\n//  F_closure($p1);\t// disallowed\n  }\n\n  if (is_null($p1)) {\t// type side effect occurs; $p1 has type null\n//  F_closure($p1);\t// type is not closure\n  } else {\t\t// type side effect occurs; $p1 has type closure\n    F_closure($p1);\t// allowed; type is closure\n  }\n\n  if (!is_null($p1)) {\t// type side effect occurs; $p1 has type closure\n    F_closure($p1);\t// allowed; type is closure\n  }\n\n  if ($p1 !== null) {\t// type side effect occurs; $p1 has type closure\n    F_closure($p1);\t// allowed; type is closure\n  }\n}\n\nclass Button {\n  public function f(): void {}\n}\n\nclass CustomButton extends Button {\n  public function g(): void {}\n}\n\nfunction F_Button(Button $p1): void {}\nfunction F_CustomButton(CustomButton $p1): void {}\nfunction F_n_class_hier(?Button $p1): void {\n//  F_Button($p1);\t\t// disallowed; function requires a Button\n//  F_CustomButton($p1);\t// disallowed; function requires a CustomButton\n\n  if (is_null($p1)) {\t\t// type side effect occurs; $p1 has type null\n//  F_Button($p1);\t\t// type is not Button\n  } else {\t\t\t// type side effect occurs; $p1 has type Button\n    F_Button($p1);\t\t// allowed; type is some kind of Button\n//  F_CustomButton($p1);\t// but not necesarily a CustomButton\n    if ($p1 instanceof CustomButton) { // type side effect occurs; $p1 has type CustomButton\n      F_CustomButton($p1);\t// allowed; type is CustomButton\n    }\n  }\n\n  if (!is_null($p1)) {\t\t// type side effect occurs; $p1 has type Button\n    F_Button($p1);\t\t// allowed; type is some kind of Button\n//  F_CustomButton($p1);\t// but not necesarily a CustomButton\n    if ($p1 instanceof CustomButton) { // type side effect occurs; $p1 has type CustomButton\n      F_CustomButton($p1);\t// allowed; type is CustomButton\n    }\n  }\n\n  if ($p1 !== null) {\t\t// type side effect occurs; $p1 has type Button\n    F_Button($p1);\t\t// allowed; type is some kind of Button\n//  F_CustomButton($p1);\t// but not necesarily a CustomButton\n    if ($p1 instanceof CustomButton) { // type side effect occurs; $p1 has type CustomButton\n      F_CustomButton($p1);\t// allowed; type is CustomButton\n    }\n  }\n}\n\nfunction getValue(): ?int {\n  return null;\n//  return 10; \n}\n\nfunction main(): void {\n  $c = new Cx();\n  $c->m();\n\n  $v = getValue();\n  if ($v !== null) {\n    $x = $v % 3;\t// accepted; % defined for int\n    echo \"\\$x = $x\\n\";\n  }\n//  $x = $v % 3;\t// rejected\n\n  $v = getValue();\n  while ($v !== null) {\n    $x = $v % 3;\t// accepted; % defined for int\n    echo \"\\$x = $x\\n\";\n    $v = null;\n  }\n//  $x = $v % 3;\t// rejected\n\n  $v = getValue();\n  for (;$v !== null;) {\n    $x = $v % 3;\t// accepted; % defined for int\n    echo \"\\$x = $x\\n\";\n    $v = null;\n  }\n//  $x = $v % 3;\t// rejected\n\n/*\n  $v = getValue();\n  do {\n    $x = $v % 3;\t// rejected; 1st time through could be null\n    echo \"\\$x = $x\\n\";\n    $v = null;\n  } while ($v !== null);\n//  $x = $v % 3;\t// rejected\n*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n\n"
  },
  {
    "path": "tests/Types/type_side_effects.php.expect",
    "content": ""
  },
  {
    "path": "tests/Types/void.php",
    "content": "<?hh // strict\n\nnamespace NS_void;\n\nfunction v(): void {}\n\nclass C {\n//  const void XX = true;\n\n// interesting behavior below\n/*\n\n  private void $prop;\t// surprise!\n\n  public function __construct() {\n    $this->prop = v();\t// the default (null) value \"returned\" from a void function is used\n  }\n*/\n//  public function setProp(void $val): void {\n//    $this->prop = $val;\n//  }\n\n  public function getProp(): void {\n  }\n}\n\nfunction main(): void {\n  $c = new C();\n  var_dump($c);\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Types/void.php.expect",
    "content": "object(NS_void\\C)#1 (0) {\n}"
  },
  {
    "path": "tests/Variables/.hhconfig",
    "content": ""
  },
  {
    "path": "tests/Variables/placeholder_variable.php",
    "content": "<?hh // strict\n\nnamespace NS_placeholder_variable;\n\nfunction f(mixed $p): void {\n  var_dump($p);\n\n  echo \"\\$_ is >\" . (string)$p . \"<\\n\";\n  $_ = 12.345;\n}\n\nfunction g(int $_): void {\t// checker accepts $_ as a parameter name, but probably shouldn't\n  echo \"\\$_ is >\" . $_ . \"<\\n\";\n}\n\nclass C {\n  public float $_ = 0.0;\t// checker accepts $_ as an instance field name, but probably shouldn't\n}\n\ntrait T {\n  public float $_ = 0.0;\t// checker accepts $_ as an instance field name, but probably shouldn't\n}\n\nfunction main(): void {\n\n  g(33);\t// Surprise! Outpus \"$_ is >33<\"\n\n  echo \"\\n\\n========================= Using \\$_ as an exception catch parameter name =========================\\n\\n\";\n\n  try {\n  }\n  catch (\\Exception $_) {\t// checker accepts $_ here, but probably shouldn't\n  }\n\n  echo \"\\n\\n========================= Is \\$_ defined by default? =========================\\n\\n\";\n\n//  var_dump($_);\t// You are using the return value of a void function (Typing[4119])\n\t\t\t// A void function doesn't return a value ($_ is a placeholder variable not meant to be used)\n//  echo \"\\$_ is >\" . $_ . \"<\\n\";\t// runtime Notice: Undefined variable: _\n\n//  f($_);\t// You are using the return value of a void function (Typing[4119])\n\t\t// A void function doesn't return a value ($_ is a placeholder variable not meant to be used)\n\n// The messages are confusing: one talks about a void function (at check time), the other about a non-existent \n// variable (at run time)\n\n  echo \"\\n\\n========================= Can the value of \\$_ be changed? =========================\\n\\n\";\n\n  $_ = \"Hello\";\t\t// allows me to change $_\n//  var_dump($_);\t// You are using the return value of a void function (Typing[4119])\n\t\t\t// A void function doesn't return a value ($_ is a placeholder variable not meant to be used)\n  echo \"\\$_ is >\" . $_ . \"<\\n\";\t// checks and outputs \"$_ is >Hello<\"\n\n//  f($_);\t// You are using the return value of a void function (Typing[4119])\n\t\t// A void function doesn't return a value ($_ is a placeholder variable not meant to be used)\n\n  $_ = 10;\t\t// allows me to change $_\n  echo \"\\$_ is >\" . $_ . \"<\\n\";\t// checks and outputs \"$_ is >Hello<\"\n//  ++$_;\t\t// This is a num (int/float) because this is used in an arithmetic operation\n\t\t// It is incompatible with void ($_ is a placeholder variable not meant to be used)\n//  $_ += 5;\t// This is a num (int/float) because this is used in an arithmetic operation\n\t\t// It is incompatible with void ($_ is a placeholder variable not meant to be used)\n//  $v = $_ + 5;\t// checker rejects ... void function and num/float\n\n// echo usage is allowed by can't pass to a function or use on some other contexts\n\n  echo \"\\n\\n========================= Odd behavior with var_dump and \\$_ =========================\\n\\n\";\n\n  $a = array('a' => 10, 'f' => 30);\n  foreach ($a as $key => $value) {\n    var_dump($key, $value, $_);\t// checks and works, as expected; 'a', 10, \"hello\", and 'f', 30, \"hello\"\n//    var_dump($_);\t// You are using the return value of a void function (Typing[4119])\n\t\t\t// A void function doesn't return a value ($_ is a placeholder variable not meant to be used)\n  }\n\n// in this context, can use $_ in var_dump, but NOT on its own!!\n\n  echo \"\\n\\n========================= An intended use of \\$_ with foreach, but ... =========================\\n\\n\";\n\n  foreach ($a as $key => $_) {\n    var_dump($key, $_);\n    $_ = 'xx';\t\t// allows me to change $_\n  }\n\n//  var_dump($_);\t// You are using the return value of a void function (Typing[4119])\n\t\t\t// A void function doesn't return a value ($_ is a placeholder variable not meant to be used)\n  echo \"\\$_ is >\" . $_ . \"<\\n\";\t// checks and works, as expected; $_ is >xx<\n\n  echo \"\\n\\n========================= An odd use of \\$_ =========================\\n\\n\";\n\n  foreach ($a as $_) {\n//    var_dump($_);\t// You are using the return value of a void function (Typing[4119])\n    echo \"\\$_ is >\" . $_ . \"<\\n\";\t// checks and works, as expected; $_ is >10<; $_ is >30<\n\n  }\n\n//  var_dump($_);\t// You are using the return value of a void function (Typing[4119])\n\t\t\t// A void function doesn't return a value ($_ is a placeholder variable not meant to be used)\n  echo \"\\$_ is >\" . $_ . \"<\\n\";\t// checks and works, as expected; $_ is >30<\n\n  echo \"\\n\\n========================= Using \\$_ for both key and value =========================\\n\\n\";\n\n  foreach ($a as $_ => $_) {\n//    var_dump($_);\t// You are using the return value of a void function (Typing[4119])\n    echo \"\\$_ is >\" . $_ . \"<\\n\";\t// checks and works, outputting $_ is >a<; $_ is >f<\n  }\n\n// shows that key wins over value, but should this be guaranteed?\n\n//  var_dump($_);\t// You are using the return value of a void function (Typing[4119])\n\t\t\t// A void function doesn't return a value ($_ is a placeholder variable not meant to be used)\n  echo \"\\$_ is >\" . $_ . \"<\\n\";\t// checks and works, as expected; $_ is >f<\n\n  echo \"\\n\\n========================= An intended use of \\$_ with list =========================\\n\\n\";\n\n  $v = Vector {1, 2, 3};\n  list($a, $_, $c) = $v;\t// checks and works, as expected\n  var_dump($a, $c);\t\t// outputs int(1); int(3)\n  list($_, $b, $_) = $v;\t// checks and works, as expected\n  var_dump($b);\t\t\t// outputs int(2)\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Variables/placeholder_variable.php.expect",
    "content": "$_ is >33<\n\n\n========================= Using $_ as an exception catch parameter name =========================\n\n\n\n========================= Is $_ defined by default? =========================\n\n\n\n========================= Can the value of $_ be changed? =========================\n\n$_ is >Hello<\n$_ is >10<\n\n\n========================= Odd behavior with var_dump and $_ =========================\n\nstring(1) \"a\"\nint(10)\nint(10)\nstring(1) \"f\"\nint(30)\nint(10)\n\n\n========================= An intended use of $_ with foreach, but ... =========================\n\nstring(1) \"a\"\nint(10)\nstring(1) \"f\"\nint(30)\n$_ is >xx<\n\n\n========================= An odd use of $_ =========================\n\n$_ is >10<\n$_ is >30<\n$_ is >30<\n\n\n========================= Using $_ for both key and value =========================\n\n$_ is >a<\n$_ is >f<\n$_ is >f<\n\n\n========================= An intended use of $_ with list =========================\n\nint(1)\nint(3)\nint(2)"
  },
  {
    "path": "tests/Variables/predefined_variables.php",
    "content": "<?hh // strict\n\nnamespace NS_predefined_variables;\n\nfunction main(): void {\n/*\n  var_dump($argc);\n  var_dump($argv);\n  var_dump($_COOKIE);\n  var_dump($_ENV);\n  var_dump($_FILES);\n  var_dump($_GET);\n  var_dump($GLOBALS);\n  var_dump($_POST);\n  var_dump($_REQUEST);\n  var_dump($_SERVER);\n  var_dump($_SESSION);\n*/\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n"
  },
  {
    "path": "tests/Variables/predefined_variables.php.expect",
    "content": ""
  },
  {
    "path": "tests/Variables/variable_kinds.php",
    "content": "<?hh // strict\n\nnamespace NS_variable_kinds;\n\n// global $min;\t\t\t// disallowed\n// global int $min;\t\t// disallowed\n// global int $min = -100;\t// disallowed\n\n// const int $gc = 10;\t\t// disallowed\n\nfunction localConst(bool $p): void {\n//  const int $lc = 10;\t// disallowed; declarations are not supported outside global scope\n\n// define()'d names are not really constants in the linguistic sense, esp. as Hack can't see them directly\n\n  echo \"Inside \" . __FUNCTION__ . \"\\n\";\n\n  define('COEFFICIENT_1', 2.345);\n  echo \"COEFFICIENT_1 = \" . constant('COEFFICIENT_1') . \"\\n\";\n\n  if ($p) {\n    echo \"COEFFICIENT_1 = \" . constant('COEFFICIENT_1') . \"\\n\";\n\n    define('FAILURE', true);\n    echo \"FAILURE = \" . constant('FAILURE') . \"\\n\";\n  }\n}\n\nfunction doit(bool $p1): void {\t// assigned the value true when called\n  $count = 10;\n\n  if ($p1) {\n    $message = \"Can't open master file.\";\n  }\n}\n\nfunction f(): void {\n  $lv = 1;\n\n  static $fs1 = 1;\n//  static int $fs1 = 1;\t// disallowed\n\n//  var_dump($fs1);\n//  $fs1 = true;\n//  var_dump($fs1);\n//  $fs1 = 123.45;\n//  var_dump($fs1);\n\n  static $fs2;\n  var_dump($fs2);\t\t// show default value is null\n\n  echo \"\\$lv = $lv, \\$fs1 = $fs1\\n\";\n  ++$lv;\n  ++$fs1;\n  if (true) {\n    static $fs3 = 99;\n    echo \"\\$fs3 = $fs3\\n\";\n    ++$fs3;\n  }\n}\n\nfunction factorial(int $i): int {\n  if ($i > 1) return $i * factorial($i - 1);\n  else if ($i == 1) return $i;\n  else return 0;\n}\n\n/*\n// globals don't appear to be supported\n\nfunction compute(bool $p): void {\n  global $min, $max;\n  global $average;\n  $average = ($max + $min)/2;\n  var_dump($min, $max, $average);\n\n  if ($p) {\n    global $result;\n    $result = 3.456;\t// initializes a global, creating it if necessary\n    var_dump($result);\n  }\n}\n*/\n\nclass Point {\n  const int MAX_COUNT = 1000;\n\n  private static int $pointCount = 0;\n\n  public float $x;\n  public float $y;\n\n  public function __construct(float $newX = 0.0, float $newY = 0.0) {\n    $this->x = $newX;\n    $this->y = $newY;\n  }\n\n  public function __toString(): string {\n    return '(' . $this->x . ',' . $this->y . ')';\n  }\t\n}\n\nfunction main(): void {\n  echo \"---------------- Local \\\"constants\\\" -------------------\\n\";\n\n  localConst(true);\n  echo \"COEFFICIENT_1 = \" . constant('COEFFICIENT_1') . \"\\n\";\n  echo \"FAILURE = \" . constant('FAILURE') . \"\\n\";\t// as it's visible here, it's not really a local!\n\n  echo \"---------------- Local variables -------------------\\n\";\n\n  doit(true);\n\n  echo \"---------------- Function statics -------------------\\n\";\n\n  for ($i = 1; $i <= 3; ++$i)\n    f();\n\n  echo \"---------------- recursive function example -------------------\\n\";\n\n  $result = factorial(10);\n  echo \"\\$result = $result\\n\";\n\n/*\n  echo \"---------------- create and use some globals -------------------\\n\";\n\n  compute(true);\n  echo \"\\$average = $average\\n\";\n  echo \"\\$result = $result\\n\";\n*/\n\n  echo \"------ instance/static properties & constants --------\\n\";\n\n  echo \"Point::MAX_COUNT: \" . Point::MAX_COUNT . \"\\n\";\n\n  $p1 = new Point();\n  echo \"\\$p1: $p1\\n\";\n\n  $p2 = new Point(5.3, 6.8);\n  echo \"\\$p2: $p2\\n\";\n}\n\n/* HH_FIXME[1002] call to main in strict*/\nmain();\n\n\n/*\n//var_dump($GLOBALS);\n\n  echo \"---------------- Global Variables using \\$GLOBALS -------------------\\n\";\n\n$GLOBALS['done'] = false;\nvar_dump($done);\n\n$GLOBALS['min'] = 10;\n$GLOBALS['max'] = 100;\n$GLOBALS['average'] = null;\n\nglobal $min, $max;\t\t// allowed, but serve no purpose\n\nfunction compute2($p) {\n  $GLOBALS['average'] = ($GLOBALS['max'] + $GLOBALS['min'])/2;\n\n  if ($p) {\n    $GLOBALS['result'] = 3.456;\t\t// initializes a global, creating it if necessary\n  }\n}\n\ncompute2(true);\necho \"\\$average = $average\\n\";\necho \"\\$result = $result\\n\";\n\n//var_dump($GLOBALS);\n*/\n"
  },
  {
    "path": "tests/Variables/variable_kinds.php.expect",
    "content": "---------------- Local \"constants\" -------------------\nInside NS_variable_kinds\\localConst\nCOEFFICIENT_1 = 2.345\nCOEFFICIENT_1 = 2.345\nFAILURE = 1\nCOEFFICIENT_1 = 2.345\nFAILURE = 1\n---------------- Local variables -------------------\n---------------- Function statics -------------------\nNULL\n$lv = 1, $fs1 = 1\n$fs3 = 99\nNULL\n$lv = 1, $fs1 = 2\n$fs3 = 100\nNULL\n$lv = 1, $fs1 = 3\n$fs3 = 101\n---------------- recursive function example -------------------\n$result = 3628800\n------ instance/static properties & constants --------\nPoint::MAX_COUNT: 1000\n$p1: (0,0)\n$p2: (5.3,6.8)"
  },
  {
    "path": "tools/README.md",
    "content": "Tools and scripts to help with rendering and enhancing the documentation in general.\n\nHere are some possible examples:\n\n1. A script to convert from Markdown to Word or PDF might live in here.\n2. A tool to help move cross reference links from Word to Markdown.\n3. A script to add numbered headings to Markdown.\n\nIf you are converting from something like Word to Markdown for the first time, this the order of tool running you might consider:\n\n1. If the documentation has been converted from Word to **one big** markdown file, you will probably want to run `split.php` first. This will split the big markdown into multiple markdown files based on primary section headings. If the document is already split, then you can go to step (2).\n2. Then you will want to run `toc.php` to create the table of contents for the split documentation.\n3. Then run `xreference.php` to get all the cross references correct. For documentation that has been split into multiple markdown files, you can specify a directory of those files so that all the files there get modified for cross-references. If the documentation is one big file still, you can just specify that file.\n\n"
  },
  {
    "path": "tools/add_hh_fixme_to_tests.php",
    "content": "<?hh\n\n// This script automatically adds \"HH_FIXME[1002]\" statements\n// to all the tests that have a main() function so the type\n// checker can actually pass AND we can run HHVM tests.\n\nfunction main(): void {\n  $tests_dir = __DIR__ . \"/../tests\";\n\n  $di = new RecursiveDirectoryIterator($tests_dir,\n                                       RecursiveDirectoryIterator::SKIP_DOTS);\n  $it = new RecursiveIteratorIterator($di);\n  foreach ($it as $test_file) {\n    if ($test_file->isFile() && $test_file->getExtension() === \"php\") {\n      $test_contents = file_get_contents($test_file);\n      $fixme_pattern = \"/HH_FIXME\\[1002\\] call to main in strict/\";\n      // Already there. Move on\n      if (preg_match($fixme_pattern, $test_contents) === 1) {\n        continue;\n      }\n      $fmain_pattern = \"/function[ ]*main[ ]*\\([\\$\\\\A-Za-z0-9:\\. ]*\\)/\";\n      if (preg_match($fmain_pattern, $test_contents) === 1) {\n        $main_call_pattern = \"/(\\/\\/)?[ ]*main[ ]*\\(([\\$\\\\A-Za-z0-9:\\. ]*)\\);/\";\n        $fixme_str = \"/* HH_FIXME[1002] call to main in strict*/\" . PHP_EOL\n                   . \"main($2);\"; // $2 is any parameters in $main_call_pattern\n        if (preg_match($main_call_pattern, $test_contents) === 1) {\n          $test_contents = preg_replace($main_call_pattern, $fixme_str,\n                                        $test_contents);\n        } else {\n          $test_contents .= PHP_EOL . $fixme_str;\n        }\n      }\n      file_put_contents($test_file, $test_contents);\n    }\n  }\n}\n\nmain();\n"
  },
  {
    "path": "tools/add_language_to_code_blocks.php",
    "content": "<?hh\n\n/**\n  Use this to add the language of your choice to Markdown code blocks.\n  This does some minimal checking to see if a language has already been\n  specified, and assumes the code blocks are of the form:\n\n  ```\n  code here\n  ```\n\n  with each ``` on a separate line\n\n  Right now, you give the script the language and it does the modification\n  for all code blocks\n**/\n\nfunction main(array<string> $argv): void {\n  if (!array_key_exists(1, $argv)) {\n    die(\"Specify a language, such as 'Hack'\");\n  }\n\n  $spec_dir = __DIR__ . \"/../spec\";\n\n  $di = new RecursiveDirectoryIterator($spec_dir,\n                                       RecursiveDirectoryIterator::SKIP_DOTS);\n  $it = new RecursiveIteratorIterator($di);\n\n  $code_block_pattern = \"/(```)(php)?(\\n.*?```\\n)/s\"; // /s matches newline for .\n  // $1 = ```\n  // $2 = php  ... match on php in case we used that before Hack was supported\n  // $3 = \\n.*?```\\n\n  $fix = \"$1\" . $argv[1] . \"$3\";\n\n  foreach($it as $spec_file) {\n    if ($spec_file->isFile() && $spec_file->getExtension() === \"md\" &&\n        $spec_file->getFilename() !== \"hack-spec-draft.md\" &&\n        $spec_file->getFilename() !== \"00-specification-for-hack.md\") {\n      $contents = file_get_contents($spec_file);\n      $matches = array();\n      preg_match_all($code_block_pattern, $contents, $matches);\n      $contents = preg_replace($code_block_pattern, $fix, $contents);\n      file_put_contents($spec_file, $contents);\n    }\n  }\n}\n\nmain($argv);\n"
  },
  {
    "path": "tools/create_test_expect_files.php",
    "content": "<?hh\n\n// Replace absolute paths with regex paths for now.\n// Could add other checks here too.\nfunction check_output(array<string> $output, string $test_file): array<string> {\n  $len = count($output);\n  $rp_test_file = realpath($test_file);\n  // /data/users/joelm/hack-langspec/tests/Script_Inclusion/require.php\n  $pattern = \"/\\/[A-Z0-9a-z\\.\\-_#\\/]+(\\/tests\\/[A-Z0-9a-z\\.\\-_#\\/]+\\.php)/\";\n  // Replace every element in the $output array %s/tests/ ... .php\n  // where $1 is the parenthesized part of the regex we actually want in\n  // expectf files.\n  $replace = \"%s$1\";\n  $output = preg_replace($pattern, $replace, $output);\n  return $output;\n}\n\nfunction main(?string $replace_option = null): void {\n  $replace_all = false;\n  if ($replace_option === 'replace') {\n    $replace_all = true;\n  }\n  $tests_dir = __DIR__ . \"/../tests\";\n\n  $di = new RecursiveDirectoryIterator($tests_dir,\n                                       RecursiveDirectoryIterator::SKIP_DOTS);\n  $it = new RecursiveIteratorIterator($di);\n  $output = array();\n  foreach ($it as $test_file) {\n    if ($test_file->isFile() && $test_file->getExtension() === \"php\") {\n      if ($replace_all ||\n          (!file_exists($test_file . \".expect\") &&\n           !file_exists($test_file . \".expectf\"))) {\n        exec(\"hhvm \" . $test_file . \" 2>&1\", $output);\n        $updated_output = check_output($output, $test_file->getRealPath());\n        $file_output = implode(PHP_EOL, $updated_output);\n        $expect_file_name = $test_file . \".expect\";\n        if ($updated_output !== $output) { // .expectf file since output changed\n           $expect_file_name = $test_file . \".expectf\";\n        }\n        file_put_contents($expect_file_name, $file_output);\n        echo \"Creating \" . $expect_file_name . PHP_EOL;\n      }\n    }\n  }\n}\n\nif (count($argv) === 2) {\n  main($argv[1]);\n} else {\n  main();\n}\n"
  },
  {
    "path": "tools/split.php",
    "content": "<?php\n\nif (!array_key_exists(1, $argv)) {\n    exit(\"Specify markdown file you want to split as argument to split.php\\n\");\n}\n\n$data = file($argv[1]);\n$filename = null;\n$counter = 0;\n$split_data = [];\n$counts = [];\n$filerefs = [];\n$filecounts = [];\n\nforeach($data as $line) {\n    if($line[0] == '#') {\n        // main header\n        if($line[1] != '#') {\n            $filename = sprintf(\"%02d-%s.md\", $counter, strtolower(str_replace(\" \", \"-\", trim(substr($line, 1)))));\n            echo $filename, \"\\n\";\n            $counter++;\n            $split_data[$filename] = '';\n        }\n        // sub-header\n        $refname = trim(ltrim($line, '#'));\n        $refname = str_replace(\" \", \"-\", $refname);\n        $refname = strtolower(preg_replace(\"/[^-_A-Za-z0-9]/\", \"\", $refname));\n        if(!empty($references[$refname])) {\n            @$counts[$refname]++;\n            $orig_refname = $refname;\n            $refname .= \"-\".$counts[$refname];\n            // Local references for repeating names may be different from global ones\n            if(!isset($filecounts[$filename][$orig_refname])) {\n                $filecounts[$filename][$orig_refname] = 0;\n                $filerefs[$filename][$refname] = $orig_refname;\n            } else {\n                @$filecounts[$filename][$orig_refname]++;\n                $filerefs[$filename][$refname] = $orig_refname . \"-\" . $filecounts[$filename][$orig_refname];\n            }\n        }\n        $references[$refname] = $filename;\n    }\n    $split_data[$filename] .= $line;\n}\n\nforeach($split_data as $filename => $contents) {\n    $contents = preg_replace_callback('@\\[(.*?)\\]\\(#(.*?)\\)@', function($data) use($references, $filename, $filerefs) {\n        if(empty($references[$data[2]])) {\n            return $data[0];\n        }\n        if($references[$data[2]]) {\n            $filepart = $references[$data[2]];\n        } else {\n            $filepart = $filename;\n        }\n        if(!empty($filerefs[$filepart][$data[2]])) {\n            // replace global ref with local one\n            $refname = $filerefs[$filepart][$data[2]];\n        } else {\n            $refname = $data[2];\n        }\n        if($filepart == $filename) {\n            $filepart = \"\";\n        }\n        $res = sprintf(\"[%s](%s#%s)\", $data[1], $filepart, $refname);\n        return $res;\n    }, $contents);\n    file_put_contents($filename, $contents);\n}\n"
  },
  {
    "path": "tools/toc.php",
    "content": "<?php error_reporting(E_ALL);\n\n$dir = __DIR__ . '/../spec/';\n$tocFile = $dir . '00-specification-for-hack.md';\n$prefix = <<<EOS\n<!-- This file is autogenerated, do not edit it manually -->\n<!-- Run tools/toc.php instead -->\n\n#Specification for Hack\nFacebook has dedicated all copyright to this specification to the public\ndomain worldwide under the CC0 Public Domain Dedication located at\n<http://creativecommons.org/publicdomain/zero/1.0/>. This specification\nis distributed without any warranty.\n\n(Initially written by Facebook, Inc., February 2015)\n\n**Table of Contents**\nEOS;\n\n$files = scandir($dir);\n$output = \"\";\n\nforeach ($files as $file) {\n    if ($file == '00-specification-for-hack.md' || $file == 'hack-spec-draft.md') {\n        continue;\n    }\n\n    $anchors = [];\n\n    $lines = file($dir . $file);\n    foreach ($lines as $line) {\n        if (!preg_match('/^(#+)\\s*(.+)/', $line, $matches)) {\n            continue;\n        }\n\n        list(, $hashes, $title) = $matches;\n        $level = strlen($hashes) - 1;\n        $indent = str_repeat('  ', $level);\n\n        $anchor = strtr(strtolower($title), ' ', '-');\n        $anchor = preg_replace('/[^\\w-]/', '', $anchor);\n\n        if (isset($anchors[$anchor])) {\n            $anchors[$anchor]++;\n            $anchor .= '-' . $anchors[$anchor];\n        } else {\n            $anchors[$anchor] = 0;\n        }\n\n        $output .= \"$indent- [$title]($file#$anchor)\\n\";\n    }\n}\n\nfile_put_contents($tocFile, \"$prefix\\n$output\");\n\n"
  },
  {
    "path": "tools/xreference/README.md",
    "content": "This tool tries to reconstruct the internal cross references that existed\nin the Word document that was used to originally create the draft spec.\n\nIf we are lucky, this will only need to be run once as we convert from .docx\nto .md.\n\nWe first manually grab all of the section numbers from the Word file and\npaste them into a CSV-aware file (like an Excel file). \n\n**BE CAREFUL** to get all the section numbers. The Word ToC normally only\ngoes up to 5 levels. But the document itself could have levels more than \nthat; so you may have to do a manual search.\n\nNow we have a column of section numbers.\n\nThen we run xreference.php. This does the following:\n\n1. Goes through our Table of Contents and maps, in line order, the current\nGitHub link anchor to the section number in our CSV file. This is fragile\nbecause it assumes that the section numbers in the CSV file map 1:1 in\nlocation to that in the ToC.\n\n2. Then it uses our final CSV mapping to replace the Word section numbers\nwith the numbers and GitHub anchor links.\n\n`§11.7.5 => §11_7_5(#the-return-statement)`\n\n3. Optionally, the numbers text can be changed to a constant character string\n\n`§11.7.5 => §§(#the-return-statement)`\n\n\nHere is an example on how to run it:\n\n```\nhhvm xreference.php -i ../../spec/00-specification-for-hack.md -m ../../spec/ -s section_map.csv -t §§\n```\n\n\n**NOTE** if you run this tool and see HHVM Notices like:\n\n> Notice: Undefined index: 10.17.2 in hack-langspec/tools/xreference/xreference.php on line 46\n\nThat means the your markdown has in it a reference that doesn't exist in the section map, so something is wrong in one of those two files.\n"
  },
  {
    "path": "tools/xreference/section_map.csv",
    "content": "1,(01-introduction.md#introduction)\n2,(02-conformance.md#conformance)\n3,(03-terms-and-definitions.md#terms-and-definitions)\n4,(04-basic-concepts.md#basic-concepts)\n4.1,(04-basic-concepts.md#program-structure)\n4.2,(04-basic-concepts.md#program-start-up)\n4.3,(04-basic-concepts.md#program-termination)\n4.4,(04-basic-concepts.md#the-memory-model)\n4.4.1,(04-basic-concepts.md#general)\n4.4.2,(04-basic-concepts.md#reclamation-and-automatic-memory-management)\n4.4.3,(04-basic-concepts.md#assignment)\n4.4.3.1,(04-basic-concepts.md#general-1)\n4.4.3.2,(04-basic-concepts.md#value-assignment-of-scalar-types-to-a-local-variable)\n4.4.3.3,(04-basic-concepts.md#value-assignment-of-object-and-resource-types-to-a-local-variable)\n4.4.3.4,(04-basic-concepts.md#byref-assignment-for-scalar-types-with-local-variables)\n4.4.3.5,(04-basic-concepts.md#byref-assignment-of-non-scalar-types-with-local-variables)\n4.4.3.6,(04-basic-concepts.md#value-assignment-of-array-types-to-local-variables)\n4.4.3.7,(04-basic-concepts.md#deferred-array-copying)\n4.4.3.8,(04-basic-concepts.md#general-value-assignment)\n4.4.3.9,(04-basic-concepts.md#general-byref-assignment)\n4.4.4,(04-basic-concepts.md#argument-passing)\n4.4.5,(04-basic-concepts.md#value-returning)\n4.4.6,(04-basic-concepts.md#cloning-objects)\n4.5,(04-basic-concepts.md#scope)\n4.6,(04-basic-concepts.md#storage-duration)\n5,(05-types.md#types)\n5.1,(05-types.md#general)\n5.2,(05-types.md#the-boolean-type)\n5.3,(05-types.md#the-integer-type)\n5.4,(05-types.md#the-floating-point-type)\n5.5,(05-types.md#the-numeric-type)\n5.6,(05-types.md#the-string-type)\n5.7,(05-types.md#the-array-key-type)\n5.8,(05-types.md#the-null-type)\n5.9,(05-types.md#enumerated-types)\n5.10,(05-types.md#the-void-type)\n5.11,(05-types.md#array-types)\n5.12,(05-types.md#class-types)\n5.13,(05-types.md#interface-types)\n5.14,(05-types.md#trait-types)\n5.15,(05-types.md#tuple-types)\n5.16,(05-types.md#shape-types)\n5.17,(05-types.md#closure-types)\n5.18,(05-types.md#resource-types)\n5.19,(05-types.md#nullable-types)\n5.20,(05-types.md#generic-types)\n5.21,(05-types.md#type-aliases)\n5.22,(05-types.md#supertypes-and-subtypes)\n5.23,(05-types.md#type-side-effects)\n5.24,(05-types.md#type-inferencing)\n6,(06-constants.md#constants)\n6.1,(06-constants.md#general)\n6.2,(06-constants.md#context-dependent-constants)\n6.3,(06-constants.md#core-predefined-constants)\n6.4,(06-constants.md#user-defined-constants)\n7,(07-variables.md#variables)\n7.1,(07-variables.md#general)\n7.2,(07-variables.md#kinds-of-variables)\n7.2.1,(07-variables.md#local-variables)\n7.2.2,(07-variables.md#array-elements)\n7.2.3,(07-variables.md#function-statics)\n7.2.4,(07-variables.md#instance-properties)\n7.2.5,(07-variables.md#static-properties)\n7.2.6,(07-variables.md#class-and-interface-constants)\n8,(08-conversions.md#conversions)\n8.1,(08-conversions.md#general)\n8.2,(08-conversions.md#converting-to-boolean-type)\n8.3,(08-conversions.md#converting-to-integer-type)\n8.4,(08-conversions.md#converting-to-floating-point-type)\n8.5,(08-conversions.md#converting-to-number-type)\n8.6,(08-conversions.md#converting-to-string-type)\n8.7,(08-conversions.md#converting-to-array-key-type)\n8.8,(08-conversions.md#converting-to-array-type)\n8.9,(08-conversions.md#converting-to-object-type)\n8.10,(08-conversions.md#converting-to-interface-type)\n8.11,(08-conversions.md#converting-to-resource-type)\n8.12,(08-conversions.md#converting-to-mixed-type)\n9,(09-lexical-structure.md#lexical-structure)\n9.1,(09-lexical-structure.md#scripts)\n9.2,(09-lexical-structure.md#grammars)\n9.3,(09-lexical-structure.md#grammar-ambiguities)\n9.4,(09-lexical-structure.md#lexical-analysis)\n9.4.1,(09-lexical-structure.md#general)\n9.4.2,(09-lexical-structure.md#comments)\n9.4.3,(09-lexical-structure.md#white-space)\n9.4.4,(09-lexical-structure.md#tokens)\n9.4.4.1,(09-lexical-structure.md#general-1)\n9.4.4.2,(09-lexical-structure.md#names)\n9.4.4.3,(09-lexical-structure.md#keywords)\n9.4.4.4,(09-lexical-structure.md#literals)\n9.4.4.4.1,(09-lexical-structure.md#general-2)\n9.4.4.4.2,(09-lexical-structure.md#boolean-literals)\n9.4.4.4.3,(09-lexical-structure.md#integer-literals)\n9.4.4.4.4,(09-lexical-structure.md#floating-point-literals)\n9.4.4.4.5,(09-lexical-structure.md#string-literals)\n9.4.4.4.5.1,(09-lexical-structure.md#single-quoted-string-literals)\n9.4.4.4.5.2,(09-lexical-structure.md#double-quoted-string-literals)\n9.4.4.4.5.3,(09-lexical-structure.md#heredoc-string-literals)\n9.4.4.4.5.4,(09-lexical-structure.md#nowdoc-string-literals)\n9.4.4.4.6,(09-lexical-structure.md#the-null-literal)\n9.4.4.5,(09-lexical-structure.md#operators-and-punctuators)\n10,(10-expressions.md#expressions)\n10.1,(10-expressions.md#general)\n10.2,(10-expressions.md#restrictions-on-arithmetic-operations)\n10.3,(10-expressions.md#operations-on-operands-having-one-or-more-subtypes)\n10.4,(10-expressions.md#primary-expressions)\n10.4.1,(10-expressions.md#general-1)\n10.4.2,(10-expressions.md#intrinsics)\n10.4.2.1,(10-expressions.md#general-2)\n10.4.2.2,(10-expressions.md#array)\n10.4.2.3,(10-expressions.md#echo)\n10.4.2.4,(10-expressions.md#exit)\n10.4.2.5,(10-expressions.md#invariant)\n10.4.2.6,(10-expressions.md#list)\n10.4.3,(10-expressions.md#collection-literals)\n10.4.4,(10-expressions.md#tuple-literals)\n10.4.5,(10-expressions.md#shape-literals)\n10.4.6,(10-expressions.md#anonymous-function-creation)\n10.5,(10-expressions.md#postfix-operators)\n10.5.1,(10-expressions.md#general-3)\n10.5.2,(10-expressions.md#the-clone-operator)\n10.5.3,(10-expressions.md#the-new-operator)\n10.5.4,(10-expressions.md#array-creation-operator)\n10.5.5,(10-expressions.md#subscript-operator)\n10.5.6,(10-expressions.md#function-call-operator)\n10.5.7,(10-expressions.md#member-selection-operator)\n10.5.8,(10-expressions.md#null-safe-member-selection-operator)\n10.5.9,(10-expressions.md#postfix-increment-and-decrement-operators)\n10.5.10,(10-expressions.md#scope-resolution-operator)\n10.5.11,(10-expressions.md#exponentiation-operator)\n10.6,(10-expressions.md#unary-operators)\n10.6.1,(10-expressions.md#general-4)\n10.6.2,(10-expressions.md#prefix-increment-and-decrement-operators)\n10.6.3,(10-expressions.md#unary-arithmetic-operators)\n10.6.4,(10-expressions.md#error-control-operator)\n10.6.5,(10-expressions.md#cast-operator)\n10.6.6,(10-expressions.md#await-operator)\n10.7,(10-expressions.md#instanceof-operator)\n10.8,(10-expressions.md#multiplicative-operators)\n10.9,(10-expressions.md#additive-operators)\n10.10,(10-expressions.md#bitwise-shift-operators)\n10.11,(10-expressions.md#relational-operators)\n10.12,(10-expressions.md#equality-operators)\n10.13,(10-expressions.md#bitwise-and-operator)\n10.14,(10-expressions.md#bitwise-exclusive-or-operator)\n10.15,(10-expressions.md#bitwise-inclusive-or-operator)\n10.16,(10-expressions.md#logical-and-operator)\n10.17,(10-expressions.md#logical-inclusive-or-operator)\n10.18,(10-expressions.md#conditional-operator)\n10.19,(10-expressions.md#lambda-expressions)\n10.20,(10-expressions.md#assignment-operators)\n10.20.1,(10-expressions.md#general-5)\n10.20.2,(10-expressions.md#simple-assignment)\n10.20.3,(10-expressions.md#compound-assignment)\n10.21,(10-expressions.md#yield-operator)\n10.22,(10-expressions.md#constant-expressions)\n11,(11-statements.md#statements)\n11.1,(11-statements.md#general)\n11.2,(11-statements.md#compound-statements)\n11.3,(11-statements.md#labeled-statements)\n11.4,(11-statements.md#expression-statements)\n11.5,(11-statements.md#selection-statements)\n11.5.1,(11-statements.md#general-1)\n11.5.2,(11-statements.md#the-if-statement)\n11.5.3,(11-statements.md#the-switch-statement)\n11.6,(11-statements.md#iteration-statements)\n11.6.1,(11-statements.md#general-2)\n11.6.2,(11-statements.md#the-while-statement)\n11.6.3,(11-statements.md#the-do-statement)\n11.6.4,(11-statements.md#the-for-statement)\n11.6.5,(11-statements.md#the-foreach-statement)\n11.7,(11-statements.md#jump-statements)\n11.7.1,(11-statements.md#general-3)\n11.7.2,(11-statements.md#the-continue-statement)\n11.7.3,(11-statements.md#the-break-statement)\n11.7.4,(11-statements.md#the-return-statement)\n11.7.5,(11-statements.md#the-throw-statement)\n11.8,(11-statements.md#the-try-statement)\n12,(12-script-inclusion.md#script-inclusion-operators)\n12.1,(12-script-inclusion.md#general)\n12.2,(12-script-inclusion.md#the-require-directive)\n12.3,(12-script-inclusion.md#the-require_once-directive)\n13,(13-enums.md#enums)\n13.1,(13-enums.md#general)\n13.2,(13-enums.md#enum-declarations)\n13.3,(13-enums.md#the-predefined-enumerated-type-methods)\n14,(14-generic-types-methods-and-functions.md#generic-types-methods-and-functions)\n14.1,(14-generic-types-methods-and-functions.md#general)\n14.2,(14-generic-types-methods-and-functions.md#type-parameters)\n14.3,(14-generic-types-methods-and-functions.md#type-constraints)\n14.4,(14-generic-types-methods-and-functions.md#type-arguments)\n14.5,(14-generic-types-methods-and-functions.md#open-and-closed-generic-types)\n14.6,(14-generic-types-methods-and-functions.md#type-inferencing-revisited)\n15,(15-functions.md#functions)\n15.1,(15-functions.md#general)\n15.2,(15-functions.md#function-calls)\n15.3,(15-functions.md#function-definitions)\n15.4,(15-functions.md#anonymous-functions)\n15.5,(15-functions.md#asynchronous-functions)\n16,(16-classes.md#classes)\n16.1,(16-classes.md#general)\n16.2,(16-classes.md#class-declarations)\n16.3,(16-classes.md#class-members)\n16.4,(16-classes.md#dynamic-methods)\n16.5,(16-classes.md#constants)\n16.6,(16-classes.md#properties)\n16.7,(16-classes.md#methods)\n16.8,(16-classes.md#constructors)\n16.9,(16-classes.md#destructors)\n16.10,(16-classes.md#methods-with-special-semantics)\n16.10.1,(16-classes.md#general-1)\n16.10.2,(16-classes.md#method-__call)\n16.10.3,(16-classes.md#method-__callstatic)\n16.10.4,(16-classes.md#method-__clone)\n16.10.5,(16-classes.md#method-__sleep)\n16.10.6,(16-classes.md#method-__tostring)\n16.10.7,(16-classes.md#method-__wakeup)\n16.11,(16-classes.md#serialization)\n16.12,(16-classes.md#predefined-classes)\n16.12.1,(16-classes.md#class-generator)\n16.12.2,(16-classes.md#class-__php_incomplete_class)\n16.12.3,(16-classes.md#class-stdclass)\n17,(17-interfaces.md#interfaces)\n17.1,(17-interfaces.md#general)\n17.2,(17-interfaces.md#interface-declarations)\n17.3,(17-interfaces.md#interface-members)\n17.4,(17-interfaces.md#constants)\n17.5,(17-interfaces.md#methods)\n17.6,(17-interfaces.md#predefined-interfaces)\n17.6.1,(17-interfaces.md#interface-arrayaccess)\n17.6.2,(17-interfaces.md#interface-awaitable)\n17.6.3,(17-interfaces.md#interface-container)\n17.6.4,(17-interfaces.md#interface-iterator)\n17.6.5,(17-interfaces.md#interface-iteratoraggregate)\n17.6.6,(17-interfaces.md#interface-keyedcontainer)\n17.6.7,(17-interfaces.md#interface-keyedtraversable)\n17.6.8,(17-interfaces.md#interface--serializable)\n17.6.9,(17-interfaces.md#interface-stringish)\n17.6.10,(17-interfaces.md#interface-traversable)\n18,(18-traits.md#traits)\n18.1,(18-traits.md#general)\n18.2,(18-traits.md#trait-declarations)\n18.3,(18-traits.md#trait-members)\n19,(19-exception-handling.md#exception-handling)\n19.1,(19-exception-handling.md#general)\n19.2,(19-exception-handling.md#class-exception)\n19.3,(19-exception-handling.md#tracing-exceptions)\n19.4,(19-exception-handling.md#user-defined-exception-classes)\n20,(20-namespaces.md#namespaces)\n20.1,(20-namespaces.md#general)\n20.2,(20-namespaces.md#name-lookup)\n20.3,(20-namespaces.md#defining-namespaces)\n20.4,(20-namespaces.md#namespace-use-declarations)\n21,(21-attributes.md#attributes)\n21.1,(21-attributes.md#general)\n21.2,(21-attributes.md#attribute-specification)\n21.3,(21-attributes.md#predefined-attributes)\n21.3.1,(21-attributes.md#general-1)\n21.3.2,(21-attributes.md#attribute-__consistentconstruct)\n21.3.3,(21-attributes.md#attribute-__memoize)\n21.3.4,(21-attributes.md#attribute-__override)\nA,(22-grammar.md#grammar)\nA.1,(22-grammar.md#general)\nA.2,(22-grammar.md#lexical-grammar)\nA.2.1,(22-grammar.md#general-1)\nA.2.2,(22-grammar.md#comments)\nA.2.3,(22-grammar.md#white-space)\nA.2.4,(22-grammar.md#tokens)\nA.2.4.1,(22-grammar.md#general-2)\nA.2.4.2,(22-grammar.md#names)\nA.2.5,(22-grammar.md#keywords)\nA.2.6,(22-grammar.md#literals)\nA.2.6.1,(22-grammar.md#general-3)\nA.2.6.2,(22-grammar.md#boolean-literals)\nA.2.6.3,(22-grammar.md#integer-literals)\nA.2.6.4,(22-grammar.md#floating-point-literals)\nA.2.6.5,(22-grammar.md#string-literals)\nA.2.6.6,(22-grammar.md#the-null-literal)\nA.2.7,(22-grammar.md#operators-and-punctuators)\nA.3,(22-grammar.md#syntactic-grammar)\nA.3.1,(22-grammar.md#program-structure)\nA.3.2,(22-grammar.md#types)\nA.3.2.1,(22-grammar.md#general-4)\nA.3.2.2,(22-grammar.md#array-types)\nA.3.2.3,(22-grammar.md#tuple-types)\nA.3.2.4,(22-grammar.md#shape-types)\nA.3.2.5,(22-grammar.md#closure-types)\nA.3.2.6,(22-grammar.md#nullable-types)\nA.3.2.7,(22-grammar.md#type-aliases)\nA.3.3,(22-grammar.md#variables)\nA.3.4,(22-grammar.md#expressions)\nA.3.4.1,(22-grammar.md#primary-expressions)\nA.3.4.2,(22-grammar.md#postfix-operators)\nA.3.4.3,(22-grammar.md#unary-operators)\nA.3.4.4,(22-grammar.md#instanceof-operator)\nA.3.4.5,(22-grammar.md#multiplicative-operators)\nA.3.4.6,(22-grammar.md#additive-operators)\nA.3.4.7,(22-grammar.md#bitwise-shift-operators)\nA.3.4.8,(22-grammar.md#relational-operators)\nA.3.4.9,(22-grammar.md#equality-operators)\nA.3.4.10,(22-grammar.md#bitwise-logical-operators)\nA.3.4.11,(22-grammar.md#logical-operators)\nA.3.4.12,(22-grammar.md#conditional-operator)\nA.3.4.13,(22-grammar.md#lambda-expressions)\nA.3.4.14,(22-grammar.md#assignment-operators)\nA.3.4.15,(22-grammar.md#yield-operator)\nA.3.4.16,(22-grammar.md#constant-expressions)\nA.3.5,(22-grammar.md#statements)\nA.3.5.1,(22-grammar.md#general-5)\nA.3.5.2,(22-grammar.md#compound-statements)\nA.3.5.3,(22-grammar.md#labeled-statements)\nA.3.5.4,(22-grammar.md#expression-statements)\nA.3.5.5,(22-grammar.md#iteration-statements)\nA.3.5.6,(22-grammar.md#jump-statements)\nA.3.5.7,(22-grammar.md#the-try-statement)\nA.3.6,(22-grammar.md#script-inclusion)\nA.3.7,(22-grammar.md#enums)\nA.3.8,(22-grammar.md#generic-types-methods-and-functions)\nA.3.9,(22-grammar.md#functions)\nA.3.10,(22-grammar.md#classes)\nA.3.11,(22-grammar.md#interfaces)\nA.3.12,(22-grammar.md#traits)\nA.3.13,(22-grammar.md#namespaces)\nA.3.14,(22-grammar.md#attributes)\nB,(23-differences-from-php.md#differences-from-php)\nB.1,(23-differences-from-php.md#general)\nB.2,(23-differences-from-php.md#program-start-up)\nB.3,(23-differences-from-php.md#constants)\nB.4,(23-differences-from-php.md#variables)\nB.5,(23-differences-from-php.md#conversions)\nB.6,(23-differences-from-php.md#lexical-structure)\nB.6.1,(23-differences-from-php.md#comments)\nB.6.2,(23-differences-from-php.md#names)\nB.6.3,(23-differences-from-php.md#keywords)\nB.7,(23-differences-from-php.md#expressions)\nB.7.1,(23-differences-from-php.md#primary-expressions)\nB.7.1.1,(23-differences-from-php.md#general-1)\nB.7.1.2,(23-differences-from-php.md#intrinsics)\nB.7.1.3,(23-differences-from-php.md#anonymous-function-creation)\nB.7.2,(23-differences-from-php.md#postfix-operators)\nB.7.2.1,(23-differences-from-php.md#the-new-operator)\nB.7.2.2,(23-differences-from-php.md#array-creation-operator)\nB.7.2.3,(23-differences-from-php.md#function-call-operator-)\nB.7.2.4,(23-differences-from-php.md#member-selection-operator---)\nB.7.2.5,(23-differences-from-php.md#postfix-increment-and-decrement-operators)\nB.7.2.6,(23-differences-from-php.md#exponentiation-operator)\nB.7.3,(23-differences-from-php.md#unary-operators)\nB.7.3.1,(23-differences-from-php.md#prefix-increment-and-decrement-operators)\nB.7.3.2,(23-differences-from-php.md#unary-arithmetic-operators)\nB.7.3.3,(23-differences-from-php.md#shell-command-operator)\nB.7.3.4,(23-differences-from-php.md#cast-operator)\nB.7.3.5,(23-differences-from-php.md#variable-name-creation-operator)\nB.7.4,(23-differences-from-php.md#instanceof-operator)\nB.7.5,(23-differences-from-php.md#multiplicative-operators)\nB.7.6,(23-differences-from-php.md#bitwise-shift-operators)\nB.7.7,(23-differences-from-php.md#bitwise-and-operator)\nB.7.8,(23-differences-from-php.md#bitwise-exclusive-or-operator)\nB.7.9,(23-differences-from-php.md#bitwise-inclusive-or-operator)\nB.7.10,(23-differences-from-php.md#assignment-operators)\nB.7.10.1,(23-differences-from-php.md#byref-assignment)\nB.7.11,(23-differences-from-php.md#logical-and-or-xor-operators-alternate-forms)\nB.8,(23-differences-from-php.md#statements)\nB.8.1,(23-differences-from-php.md#general-2)\nB.8.2,(23-differences-from-php.md#labeled-statements)\nB.8.3,(23-differences-from-php.md#the-if-statement)\nB.8.4,(23-differences-from-php.md#the-switch-statement)\nB.8.5,(23-differences-from-php.md#the-while-statement)\nB.8.6,(23-differences-from-php.md#the-for-statement)\nB.8.7,(23-differences-from-php.md#the-foreach-statement)\nB.8.8,(23-differences-from-php.md#the-goto-statement)\nB.8.9,(23-differences-from-php.md#the-continue-statement)\nB.8.10,(23-differences-from-php.md#the-break-statement)\nB.8.11,(23-differences-from-php.md#the-return-statement)\nB.8.12,(23-differences-from-php.md#the-declare-statement)\nB.9,(23-differences-from-php.md#script-inclusion)\nB.10,(23-differences-from-php.md#functions)\nB.11,(23-differences-from-php.md#classes)\nB.11.1,(23-differences-from-php.md#class-members)\nB.11.2,(23-differences-from-php.md#dynamic-members)\nB.11.3,(23-differences-from-php.md#properties)\nB.11.4,(23-differences-from-php.md#methods)\nB.11.5,(23-differences-from-php.md#constructors)\nB.11.6,(23-differences-from-php.md#methods-with-special-semantics)\nB.11.6.1,(23-differences-from-php.md#general-3)\nB.11.6.2,(23-differences-from-php.md#method-__call)\nB.11.6.3,(23-differences-from-php.md#method-__get)\nB.11.6.4,(23-differences-from-php.md#method-__invoke)\nB.11.6.5,(23-differences-from-php.md#method-__isset)\nB.11.6.6,(23-differences-from-php.md#method-__set)\nB.11.6.7,(23-differences-from-php.md#method-__set_state)\nB.11.6.8,(23-differences-from-php.md#method-__unset)\nB.11.7,(23-differences-from-php.md#predefined-classes)\nB.11.7.1,(23-differences-from-php.md#class-closure)\nB.12,(23-differences-from-php.md#interfaces)\nB.12.1,(23-differences-from-php.md#interface-members)\nB.12.2,(23-differences-from-php.md#methods-1)\nB.12.3,(23-differences-from-php.md#predefined-interfaces)\nB.13,(23-differences-from-php.md#traits)\nB.13.1,(23-differences-from-php.md#trait-declarations)\nB.14,(23-differences-from-php.md#namespaces)\nB.14.1,(23-differences-from-php.md#namespace-use-declarations)\nBibliography,(24-bibliography.md#bibliography)"
  },
  {
    "path": "tools/xreference/xreference.php",
    "content": "<?hh\n\nfunction get_section_map(string $section_map_file): array<string, string> {\n  $handle = fopen($section_map_file, \"r\");\n  $section_map = array();\n  while (($pair = fgetcsv($handle)) !== false) {\n    // section number is the key, title is the value\n    // remove spaces from title, replace inner spaces with empty string\n    $section_map[$pair[0]] = str_replace(\" \", \"\", trim($pair[1]));\n  }\n  return $section_map;\n}\n\nfunction insert_cross_references(string $md_file,\n                                 array<string, string> $section_map,\n                                 string $ref_link_text = NULL,\n                                 bool $update_only = false): void {\n  $contents = file($md_file);\n  $update = \"\";\n  // matches\n  //   §16.2\n  //   [§§]\n  //   §A.1.2\n  $pattern = \"/([\\[])?§([A-Z0-9\\.]+)([\\]])?/\";\n  $matches = array();\n  foreach ($contents as $line) {\n    // Get all the matches on this line of text\n    if (preg_match_all($pattern, $line, $matches) > 0) {\n      $ref_texts = $matches[2]; // The matches for the characters after §\n      foreach ($ref_texts as $ref_text) {\n        // Get rid of any trailing . in case the cross reference is the\n        // end of a sentence and the match occurred.\n        $ref_text = rtrim($ref_text, \".\");\n        // For each cross reference match we found, replace with\n        // markdown link in our map and create a text link to the title\n        $text = $ref_link_text === null ? $ref_text : $ref_link_text;\n        $replace = \"\";\n        if (!$update_only || ($update_only && empty($matches[0]))) {\n          $replace .= \"[\";\n        }\n        $replace .= $text;\n        if (!$update_only || ($update_only && empty($matches[0]))) {\n          $replace .= \"]\";\n        }\n        if (!$update_only){\n          $replace .= $section_map[$ref_text];\n        }\n        $line = str_replace(\"§\".$ref_text, $replace, $line);\n      }\n    }\n    $update .= $line;\n  }\n  file_put_contents($md_file, $update);\n}\n\n\nfunction map_word_sections_to_markdown_sections(string $section_map_file,\n                                                string $toc_file) {\n  $toc_contents = file_get_contents($toc_file);\n  $toc_start = strpos($toc_contents, \"**Table of Contents**\");\n  $toc_end = strlen($toc_contents);\n  $md_toc = substr($toc_contents, $toc_start, $toc_end);\n\n  // e.g., (01-introduction.md#introduction)\n  $md_section_pattern = \"/\\([a-z0-9\\-_]+\\.md#[a-z0-9\\-_]+\\)/\";\n\n  $matches = array();\n  preg_match_all($md_section_pattern, $md_toc, $matches);\n  if (empty($matches[0])) {\n    die(\"No table of contents found\" . PHP_EOL);\n  }\n  // $matches[0] will be an array of the matches we found\n  // Start at 1 because $refs[0] will actually be the ToC md file that\n  // we don't care about linking to.\n  $refs = array_slice($matches[0], 1);\n  $sm_contents = file($section_map_file, FILE_IGNORE_NEW_LINES);\n  $num_elements = count($sm_contents);\n  for ($i = 0; $i < $num_elements; $i++) {\n    if (!strpos($sm_contents[$i], $refs[$i])) {\n      $sm_contents[$i] .= \",\" . $refs[$i];\n    }\n  }\n  file_put_contents($section_map_file, implode(PHP_EOL, $sm_contents));\n}\n\nfunction usage(): string {\n  return \"Usage\" . PHP_EOL . PHP_EOL\n        . \"Make sure you run split.php and toc.php before this!!\" . PHP_EOL\n        . \"php xreference.php [options]\" . PHP_EOL\n        . \"-i <table of contents md file>\" . PHP_EOL\n        . \"-m <input markdown file or directory of files>\" . PHP_EOL\n        . \"-s <section map file>\" . PHP_EOL\n        . \"[-t <text used for clickable reference link>\" . PHP_EOL\n        . \"[-u <update reference link text only; don't change actual link>\"\n        . PHP_EOL . PHP_EOL;\n}\n\nfunction main(array<string> $argv): void {\n  $opts = getopt(\"hi:m:s:t:u\");\n  if (array_key_exists(\"h\", $opts)) {\n    die(usage());\n  }\n  if (!array_key_exists(\"m\", $opts) &&\n      !array_key_exists(\"s\", $opts) &&\n      !array_key_exists(\"i\", $opts)) {\n    die(\"Specify, ToC markdown file, input markdown file and input section map\"\n        . PHP_EOL . PHP_EOL . usage());\n  }\n  $toc_file = $opts[\"i\"];\n  $md_file = $opts[\"m\"];\n\n  $md_files = array();\n\n  // If we are given a directory of md files to cross reference\n  if (is_dir($md_file)) {\n    $md_files = scandir($md_file);\n    // Keep only .md files\n    $md_files = array_filter($md_files, function($val) {\n                                          if (strpos($val, \".md\") !== false) {\n                                            return $val;\n                                          }\n                                        });\n    // scandir only returns a list of the files with no path info\n    // so add the path info in $md_file via a callback to array_map\n    $md_files = array_map(function($val) use ($md_file) {\n                            return $md_file . $val;\n                          },\n                          $md_files);\n\n  } else {\n    $md_files[0] = $md_file;\n  }\n  $section_map_file = $opts[\"s\"];\n  $ref_link_text = null;\n  if (array_key_exists(\"t\", $opts)) {\n    $ref_link_text = $opts[\"t\"];\n  }\n  $update_only = false;\n  if (array_key_exists(\"u\", $opts)) {\n    $update_only = true;\n  }\n  map_word_sections_to_markdown_sections($section_map_file, $toc_file);\n  $section_map = get_section_map($section_map_file);\n  foreach($md_files as $file) {\n    insert_cross_references($file, $section_map, $ref_link_text,\n                            $update_only);\n  }\n}\n\nmain($argv);\n"
  }
]