diff --git a/.gitignore b/.gitignore index 999b52e3..10184eb4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /.commit-template +*.swp diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..594e5103 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: php + +php: + - 7.3 + +script: + - REPORT_EXIT_STATUS=1 php ~/.phpenv/versions/$(phpenv version-name)/lib/php/build/run-tests.php -P -c ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini -q -x --show-diff diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0b60901b..d4979574 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,24 @@ ## Contributing to the Specification for PHP We'd love your help in improving, correcting, adding to the specification. -Please [file an issue](https://bugs.php.net/) or [submit a pull request](https://wiki.php.net/vcs/gitworkflow) -at the [spec git repo](https://github.com/php/php-langspec). +Please [file an issue](https://github.com/php/php-langspec/issues) +or [submit a pull request](https://github.com/php/php-langspec/pulls). + +## Generated content + +The grammar listings and table of contents of the specification are automatically +generated. If you want to change the grammar, you need to modify the respective +` -#Specification for PHP +# Specification for PHP Facebook has dedicated all copyright to this specification to the public domain worldwide under the CC0 Public Domain Dedication located at . This specification @@ -86,7 +86,6 @@ is distributed without any warranty. - [Names](09-lexical-structure.md#names) - [Keywords](09-lexical-structure.md#keywords) - [Literals](09-lexical-structure.md#literals) - - [General](09-lexical-structure.md#general-2) - [Integer Literals](09-lexical-structure.md#integer-literals) - [Floating-Point Literals](09-lexical-structure.md#floating-point-literals) - [String Literals](09-lexical-structure.md#string-literals) @@ -99,38 +98,37 @@ is distributed without any warranty. - [General](10-expressions.md#general) - [Primary Expressions](10-expressions.md#primary-expressions) - [General](10-expressions.md#general-1) + - [Simple Variable](10-expressions.md#simple-variable) + - [Dereferencable expression](10-expressions.md#dereferencable-expression) + - [Variables](10-expressions.md#variables) + - [Constant Access Expression](10-expressions.md#constant-access-expression) + - [Literals](10-expressions.md#literals) - [Intrinsics](10-expressions.md#intrinsics) - [General](10-expressions.md#general-2) - - [array](10-expressions.md#array) - - [echo](10-expressions.md#echo) - [empty](10-expressions.md#empty) - [eval](10-expressions.md#eval) - [exit/die](10-expressions.md#exitdie) - [isset](10-expressions.md#isset) - - [list](10-expressions.md#list) - - [print](10-expressions.md#print) - - [unset](10-expressions.md#unset) - [Anonymous Function Creation](10-expressions.md#anonymous-function-creation) - - [Postfix Operators](10-expressions.md#postfix-operators) - - [General](10-expressions.md#general-3) - - [The `clone` Operator](10-expressions.md#the-clone-operator) - [The `new` Operator](10-expressions.md#the-new-operator) - [Array Creation Operator](10-expressions.md#array-creation-operator) - [Subscript Operator](10-expressions.md#subscript-operator) - [Function Call Operator](10-expressions.md#function-call-operator) - - [Member-Selection Operator](10-expressions.md#member-selection-operator) + - [Member Access Operator](10-expressions.md#member-access-operator) + - [Member Call Operator](10-expressions.md#member-call-operator) - [Postfix Increment and Decrement Operators](10-expressions.md#postfix-increment-and-decrement-operators) + - [Prefix Increment and Decrement Operators](10-expressions.md#prefix-increment-and-decrement-operators) + - [Shell Command Operator](10-expressions.md#shell-command-operator) - [Scope-Resolution Operator](10-expressions.md#scope-resolution-operator) - - [Exponentiation Operator](10-expressions.md#exponentiation-operator) + - [The `clone` Operator](10-expressions.md#the-clone-operator) + - [Exponentiation Operator](10-expressions.md#exponentiation-operator) - [Unary Operators](10-expressions.md#unary-operators) - - [General](10-expressions.md#general-4) - - [Prefix Increment and Decrement Operators](10-expressions.md#prefix-increment-and-decrement-operators) + - [General](10-expressions.md#general-3) - [Unary Arithmetic Operators](10-expressions.md#unary-arithmetic-operators) - [Error Control Operator](10-expressions.md#error-control-operator) - - [Shell Command Operator](10-expressions.md#shell-command-operator) - [Cast Operator](10-expressions.md#cast-operator) - - [Variable-Name Creation Operator](10-expressions.md#variable-name-creation-operator) - [`instanceof` Operator](10-expressions.md#instanceof-operator) + - [Logical NOT Operator](10-expressions.md#logical-not-operator) - [Multiplicative Operators](10-expressions.md#multiplicative-operators) - [Additive Operators](10-expressions.md#additive-operators) - [Bitwise Shift Operators](10-expressions.md#bitwise-shift-operators) @@ -141,19 +139,21 @@ is distributed without any warranty. - [Bitwise Inclusive OR Operator](10-expressions.md#bitwise-inclusive-or-operator) - [Logical AND Operator (form 1)](10-expressions.md#logical-and-operator-form-1) - [Logical Inclusive OR Operator (form 1)](10-expressions.md#logical-inclusive-or-operator-form-1) - - [Conditional Operator](10-expressions.md#conditional-operator) - [Coalesce Operator](10-expressions.md#coalesce-operator) + - [Conditional Operator](10-expressions.md#conditional-operator) - [Assignment Operators](10-expressions.md#assignment-operators) - - [General](10-expressions.md#general-5) + - [General](10-expressions.md#general-4) - [Simple Assignment](10-expressions.md#simple-assignment) + - [list intrinsic](10-expressions.md#list-intrinsic) - [byRef Assignment](10-expressions.md#byref-assignment) - [Compound Assignment](10-expressions.md#compound-assignment) + - [`yield` Operator](10-expressions.md#yield-operator) + - [Print expression](10-expressions.md#print-expression) - [Logical AND Operator (form 2)](10-expressions.md#logical-and-operator-form-2) - [Logical Exclusive OR Operator](10-expressions.md#logical-exclusive-or-operator) - [Logical Inclusive OR Operator (form 2)](10-expressions.md#logical-inclusive-or-operator-form-2) - - [`yield` Operator](10-expressions.md#yield-operator) - [Script Inclusion Operators](10-expressions.md#script-inclusion-operators) - - [General](10-expressions.md#general-6) + - [General](10-expressions.md#general-5) - [The `include` Operator](10-expressions.md#the-include-operator) - [The `include_once` Operator](10-expressions.md#the-include_once-operator) - [The `require` Operator](10-expressions.md#the-require-operator) @@ -183,6 +183,8 @@ is distributed without any warranty. - [The `throw` Statement](11-statements.md#the-throw-statement) - [The `try` Statement](11-statements.md#the-try-statement) - [The `declare` Statement](11-statements.md#the-declare-statement) + - [The `echo` Statement](11-statements.md#the-echo-statement) + - [The `unset` Statement](11-statements.md#the-unset-statement) - [Arrays](12-arrays.md#arrays) - [General](12-arrays.md#general) - [Array Creation and Initialization](12-arrays.md#array-creation-and-initialization) @@ -264,50 +266,11 @@ is distributed without any warranty. - [Grammar](19-grammar.md#grammar) - [General](19-grammar.md#general) - [Lexical Grammar](19-grammar.md#lexical-grammar) - - [General](19-grammar.md#general-1) - - [Comments](19-grammar.md#comments) - - [White Space](19-grammar.md#white-space) - - [Tokens](19-grammar.md#tokens) - - [General](19-grammar.md#general-2) - - [Names](19-grammar.md#names) - - [Keywords](19-grammar.md#keywords) - - [Literals](19-grammar.md#literals) - - [General](19-grammar.md#general-3) - - [Integer Literals](19-grammar.md#integer-literals) - - [Floating-Point Literals](19-grammar.md#floating-point-literals) - - [String Literals](19-grammar.md#string-literals) - - [Operators and Punctuators](19-grammar.md#operators-and-punctuators) - [Syntactic Grammar](19-grammar.md#syntactic-grammar) - - [Program Structure](19-grammar.md#program-structure) + - [Basic Concepts](19-grammar.md#basic-concepts) - [Variables](19-grammar.md#variables) - [Expressions](19-grammar.md#expressions) - - [Primary Expressions](19-grammar.md#primary-expressions) - - [Postfix Operators](19-grammar.md#postfix-operators) - - [Unary Operators](19-grammar.md#unary-operators) - - [instanceof Operator](19-grammar.md#instanceof-operator) - - [Multiplicative Operators](19-grammar.md#multiplicative-operators) - - [Additive Operators](19-grammar.md#additive-operators) - - [Bitwise Shift Operators](19-grammar.md#bitwise-shift-operators) - - [Relational Operators](19-grammar.md#relational-operators) - - [Equality Operators](19-grammar.md#equality-operators) - - [Bitwise Logical Operators](19-grammar.md#bitwise-logical-operators) - - [Logical Operators (form 1)](19-grammar.md#logical-operators-form-1) - - [Conditional Operator](19-grammar.md#conditional-operator) - - [Coalesce Operator](19-grammar.md#coalesce-operator) - - [Assignment Operators](19-grammar.md#assignment-operators) - - [Logical Operators (form 2)](19-grammar.md#logical-operators-form-2) - - [yield Operator](19-grammar.md#yield-operator) - - [Script Inclusion Operators](19-grammar.md#script-inclusion-operators) - - [Constant Expressions](19-grammar.md#constant-expressions) - [Statements](19-grammar.md#statements) - - [General](19-grammar.md#general-4) - - [Compound Statements](19-grammar.md#compound-statements) - - [Labeled Statements](19-grammar.md#labeled-statements) - - [Expression Statements](19-grammar.md#expression-statements) - - [Iteration Statements](19-grammar.md#iteration-statements) - - [Jump Statements](19-grammar.md#jump-statements) - - [The try Statement](19-grammar.md#the-try-statement) - - [The declare Statement](19-grammar.md#the-declare-statement) - [Functions](19-grammar.md#functions) - [Classes](19-grammar.md#classes) - [Interfaces](19-grammar.md#interfaces) diff --git a/spec/01-introduction.md b/spec/01-introduction.md index c2c29b44..84953ebb 100644 --- a/spec/01-introduction.md +++ b/spec/01-introduction.md @@ -1,4 +1,4 @@ -#Introduction +# Introduction This specification is intended to provide a complete and concise definition of the syntax and semantics of the PHP language, suitable for use by the following: @@ -10,4 +10,3 @@ use by the following: For now, the runtime library has been excluded, as that is documented at [www.php.net](http://www.php.net). However, the document can contain references to the library functions, usually in the form of links to http://www.php.net. - diff --git a/spec/02-conformance.md b/spec/02-conformance.md index 9a7881d2..4ab126bb 100644 --- a/spec/02-conformance.md +++ b/spec/02-conformance.md @@ -1,4 +1,4 @@ -#Conformance +# Conformance In this specification, "must" is to be interpreted as a requirement on an implementation or on a program; conversely, "must not" is to be interpreted as a prohibition. @@ -52,4 +52,3 @@ to exist in future revisions. Usually, they are old approaches that have been superseded by new ones, and use of the old approach is discouraged. (Examples of this include the use of braces ({ }) for subscripting, and the use of old-style constructor names). - diff --git a/spec/03-terms-and-definitions.md b/spec/03-terms-and-definitions.md index 46656a5c..ae87eb6b 100644 --- a/spec/03-terms-and-definitions.md +++ b/spec/03-terms-and-definitions.md @@ -1,68 +1,66 @@ -#Terms and Definitions +# Terms and Definitions For the purposes of this document, the following terms and definitions apply:
-
argument
-
a value passed to a function, that is intended to map to a - corresponding parameter.
+
argument
+
a value passed to a function, that is intended to map to a + corresponding parameter.
-
behavior
-
external appearance or action.
+
behavior
+
external appearance or action.
-
behavior, implementation-defined
-
behavior specific to an implementation, where that implementation - must document that behavior.
+
behavior, implementation-defined
+
behavior specific to an implementation, where that implementation + must document that behavior.
-
behavior, undefined
-
behavior which is not guaranteed to produce any specific result. - Usually follows an erroneous program construct or data.
+
behavior, undefined
+
behavior which is not guaranteed to produce any specific result. + Usually follows an erroneous program construct or data.
-
behavior, unspecified
-
behavior for which this specification provides no requirements.
+
behavior, unspecified
+
behavior for which this specification provides no requirements.
-
constraint
-
restriction, either syntactic or semantic, on how language elements - can be used.
+
constraint
+
restriction, either syntactic or semantic, on how language elements + can be used.
-
error, fatal
-
a condition in which the engine cannot continue executing the script - and must terminate.
+
error, fatal
+
a condition in which the engine cannot continue executing the script + and must terminate.
-
error, fatal, catchable
-
a fatal error that can be caught by a user-defined handler.
+
error, fatal, catchable
+
a fatal error that can be caught by a user-defined handler.
-
error, non-fatal
-
an error that is not a fatal error and allows for the engine to - continue execution.
+
error, non-fatal
+
an error that is not a fatal error and allows for the engine to + continue execution.
-
lvalue
-
an expression that designates a location that can store a value.
+
lvalue
+
an expression that designates a location that can store a value.
-
lvalue, modifiable
-
an lvalue whose value can be changed.
+
lvalue, modifiable
+
an lvalue whose value can be changed.
-
lvalue, non-modifiable
-
an lvalue whose value cannot be changed.
+
lvalue, non-modifiable
+
an lvalue whose value cannot be changed.
-
notice
-
an informational message informing user of the code that may not work as intended.
+
notice
+
an informational message informing user of the code that may not work as intended.
-
parameter
-
a variable declared in the parameter list of a function that is - intended to map to a corresponding argument in a call to that - function.
+
parameter
+
a variable declared in the parameter list of a function that is + intended to map to a corresponding argument in a call to that + function.
-
PHP Run-Time Engine
-
the software that executes a PHP program. Referred to as the - Engine throughout this specification.
+
PHP Run-Time Engine
+
the software that executes a PHP program. Referred to as the + Engine throughout this specification.
-
value
-
a primitive unit of data operated by the Engine having a type - and potentially other content depending on the type.
+
value
+
a primitive unit of data operated by the Engine having a type + and potentially other content depending on the type.
Other terms are defined throughout this specification, as needed, with the first usage being typeset *like this*. - - diff --git a/spec/04-basic-concepts.md b/spec/04-basic-concepts.md index 3de18073..6f99d468 100644 --- a/spec/04-basic-concepts.md +++ b/spec/04-basic-concepts.md @@ -1,30 +1,50 @@ -#Basic Concepts -##Program Structure +# Basic Concepts +## Program Structure A PHP *program* consists of one or more source files, known formally as *scripts*. + +
-script:
- script-section
- script   script-section
+script:
+   script-section
+   script   script-section
 
-script-section:
-   textopt start-tag statement-listopt end-tagopt textopt
+script-section:
+   textopt   start-tag   statement-listopt   end-tagopt   textopt
 
-start-tag:
-  <?php
-  <?=
+start-tag:
+   <?php
+   <?=
 
-end-tag:
-  ?>
+end-tag:
+   ?>
 
-text:
-  arbitrary text not containing any of start-tag sequences
+text:
+   arbitrary text not containing any of   start-tag   sequences
 
All of the sections in a script are treated as though they belonged to one continuous section, except that any intervening text is treated as -though it were a string literal given to the [intrinsic `echo`](10-expressions.md#echo). +though it were a string literal given to the +[`echo` statement](11-statements.md#the-echo-statement). A script can import another script via a [script inclusion operator](10-expressions.md#script-inclusion-operators). @@ -32,10 +52,10 @@ A script can import another script via a [script inclusion operator](10-expressi The top level of a script is simply referred to as the *top level*. -If `[VStore null] [HStore Point [VSlot $x *] [VSlot $y *] (dead)] | | -[VSlot $b *]-->[VStore null] [VStore int 2 (dead)]<--+ V +[VSlot $b *]-->[VStore null] [VStore int 2 (dead)]<--+ V [VStore int 1 (dead)] [HStore Point [VSlot $x *] [VSlot $y *] (dead)] | | - [VStore int 4 (dead)]<--+ V + [VStore int 4 (dead)]<--+ V [VStore int 6 (dead)] ``` @@ -514,7 +535,7 @@ though they can have an arbitrarily large number of instance properties of arbitrary type. Likewise, the same mechanics apply to value assignment of all resource types. -####ByRef Assignment for Scalar Types with Local Variables +#### ByRef Assignment for Scalar Types with Local Variables Let's begin with the same value [assignment](10-expressions.md#simple-assignment) as in the previous section, `$a = 123` and `$b = false`: @@ -643,11 +664,11 @@ Note that literals, constants, and other expressions that don't designate a modifiable lvalue cannot be used on the left- or right-hand side of byRef assignment. -####ByRef Assignment of Non-Scalar Types with Local Variables +#### ByRef Assignment of Non-Scalar Types with Local Variables ByRef assignment of non-scalar types works using the same mechanism as byRef assignment for scalar types. Nevertheless, it is worthwhile to describe a few examples to clarify the semantics of byRef assignment. -Recall the [example using the `Point` class](#value-assignment-of-object-and-resource-types-to-a-local-variable): +Recall the [example using the `Point` class](#value-assignment-of-objects-to-a-local-variable): `$a = new Point(1, 3);` @@ -717,9 +738,9 @@ Once all the aliases to the VStores are gone, the VStores can be destroyed, in which case, there are no more pointers to the HStore, and it can be destoyed too. -####Value Assignment of Array Types to Local Variables +#### Value Assignment of Array Types to Local Variables The semantics of value assignment of array types is different from value -assignment of other types. Recall the `Point` class from [the examples](#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: +assignment of other types. Recall the `Point` class from [the examples](#value-assignment-of-objects-to-a-local-variable), and consider the following [value assignments](10-expressions.md#simple-assignment) and their abstract implementation: `$a = array(10, 'B' => new Point(1, 3));` @@ -729,7 +750,7 @@ assignment of other types. Recall the `Point` class from [the examples](#value-a V V [VStore int 10] [VStore Obj *] | - [HStore Point [VSlot $x *] [VSlot $y *]]<----+ + [HStore Point [VSlot $x *] [VSlot $y *]]<----+ | | V V [VStore int 1] [VStore int 3] @@ -761,7 +782,7 @@ the value assignment `$b = $a`: | | | +---------+ +---------+ | V V | -[VStore int 10] [VStore object *]-->[HStore Point [VSlot $x *] [VSlot $y *]]<---+ +[VStore int 10] [VStore object *]-->[HStore Point [VSlot $x *] [VSlot $y *]]<---+ | | V V [VStore int 1] [VStore int 3] @@ -809,7 +830,7 @@ implementation. Here is the first possible outcome: ``` [VSlot $a *]---->[VStore array *]---->[HStore Array [VSlot 0 *]] | -[VSlot $x *]-------------------------+ [VStore array *]<---+ +[VSlot $x *]-------------------------+ [VStore array *]<---+ | | [VSlot $b *]-->[VStore array *] | V | | [HStore Array [VSlot 0 *][VSlot 1 *]] @@ -831,7 +852,7 @@ Here is the second possible outcome: ``` [VSlot $a *]---->[VStore array *]---->[HStore Array [VSlot 0 *]] | -[VSlot $x *]-------------------------+ [VStore array *]<----+ +[VSlot $x *]-------------------------+ [VStore array *]<----+ | | [VSlot $b *]-->[VStore array *] | V | | [HStore Array [VSlot 0 *] [VSlot 1 *]] @@ -870,7 +891,7 @@ arrays even though they can have an arbitrarily large number of elements. As to how an HStore accommodates all of them, is unspecified and unimportant to the abstract model. -####Deferred Array Copying +#### Deferred Array Copying As mentioned in the [previous section](#value-assignment-of-array-types-to-local-variables), an implementation may choose to use a deferred copy mechanism instead of eagerly making a copy for value assignment of arrays. An implementation may use any deferred @@ -918,7 +939,7 @@ $b = $a; ``` [VSlot $a *]--->[VStore array *]--->[HStore Array [VSlot 0 *]] ^ | - | [VStore array *]<--+ + | [VStore array *]<--+ [VSlot $b *]--->[VStore Arr-D *]------+ | V [HStore Array [VSlot 0 *] [VSlot 1 *]] @@ -980,7 +1001,7 @@ outcomes: ``` [VSlot $a *]---->[VStore array *]---->[HStore Array [VSlot 0 *]] | -[VSlot $b *]-->[VStore array *] [VStore Arr *]<---+ +[VSlot $b *]-->[VStore array *] [VStore Arr *]<---+ | | +----------------------+ +----------+ V V @@ -1015,7 +1036,7 @@ possible outcome: ``` [VSlot $a *]---->[VStore array *]---->[HStore Array [VSlot 0 *]] | -[VSlot $b *]-->[VStore array *] [VStore array *]<---+ +[VSlot $b *]-->[VStore array *] [VStore array *]<---+ | | V V [HStore Array [VSlot 0 *] [VSlot 1 *]] [HStore Array [VSlot 0 *] [VSlot 1 *]] @@ -1029,15 +1050,15 @@ possible outcome: | V | | [VStore string 'hi'] | V | - [VSlot $x *]--------------------->[VStore int 123]<--------+ + [VSlot $x *]--------------------->[VStore int 123]<--------+ ``` Here is the third possible outcome: ``` [VSlot $a *]---->[VStore array *-]---->[HStore Array [VSlot 0 *]] - | -[VSlot $b *]-->[VStore array *] [VStore array *]<---+ + | +[VSlot $b *]-->[VStore array *] [VStore array *]<---+ | | V V [HStore Array [VSlot 0 *] [VSlot 1 *]] [HStore Array [VSlot 0 *] [VSlot 1 *]] @@ -1047,11 +1068,11 @@ Here is the third possible outcome: V | V [VStore Arr-D *]-->[HStore Array [VSlot 0 *] [VSlot 1 *]] | [VStore string 'hi'] | | | - [VStore int 123]<-------+ | | + [VStore int 123]<-------+ | | V | [VStore string 'hi'] | | - [VSlot $x *]--------------------->[VStore int 123]<---------+ + [VSlot $x *]--------------------->[VStore int 123]<---------+ ``` The second and third possible outcomes show what can possibly happen if @@ -1096,7 +1117,7 @@ difference, php.net's implementation produces behavior that is compatible with the abstract model's definition of deferred array copy mechanisms. -####General Value Assignment +#### General Value Assignment The sections above thus far have described the mechanics of value assignment to a local variable. The assignment to a modifiable lvalue that is not a variable, such as array element or object property, works like the local variable assignment, except that the VSlot which represented @@ -1161,7 +1182,7 @@ is considered a modifiable lvalue, and the VSlot will be created by the engine a to the appropriate HStore automatically. Static class properties are considered modifiable lvalues too, though new ones would not be created automatically. -####General ByRef Assignment +#### General ByRef Assignment The sections above thus far have described the mechanics of byref assignment with local variables. The byRef assignment to a modifiable lvalue that is not a variable, such as array element or object property, works like the local variable assignment, @@ -1183,10 +1204,10 @@ Will result in: | | | V V | [VStore int 1] [VStore int 3] | -[VSlot $b *]---------------->[VStore int 123]<---------------------------------------+ +[VSlot $b *]---------------->[VStore int 123]<---------------------------------------+ ``` -###Argument Passing +### Argument Passing Argument passing is defined in terms of [simple assignment](#assignment) or [byRef assignment](#byref-assignment-for-scalar-types-with-local-variables), depending on how the parameter is declared. That is, passing an argument to a function having a corresponding parameter is like assigning that argument to that parameter. The @@ -1194,7 +1215,7 @@ function call situations involving missing arguments or undefined variable arguments are discussed in section describing [the function call operator](10-expressions.md#function-call-operator). -###Value Returning +### Value Returning Returning a value from a function is defined in terms of [simple assignment](#assignment) or [byRef assignment](#byref-assignment-for-scalar-types-with-local-variables), depending on how the function is declared. That is, returning a value from a function to its caller is like assigning that value to the user of the caller's return @@ -1229,9 +1250,9 @@ Passing function's return to another function is considered the same as assignin the value to the corresponding function's parameter, with byRef parameters treated as byRef assignments. -###Cloning objects +### Cloning objects When an object instance is allocated, operator [`new`](10-expressions.md#the-new-operator) returns a handle -that points to that object. As described [above](#value-assignment-of-object-and-resource-types-to-a-local-variable), +that points to that object. As described [above](#value-assignment-of-objects-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. The copying of the HStore itself is performed via [operator `clone`](10-expressions.md#the-clone-operator). @@ -1246,7 +1267,7 @@ some type(s) or to an instance of some other type. V V [VStore int 10] [VStore object *] | - [HStore ...]<---------+ + [HStore ...]<---------+ ``` Let us consider the result of `$b = clone $a`: @@ -1258,7 +1279,7 @@ Let us consider the result of `$b = clone $a`: | [VStore int 10] [VStore object *] +-----------------------+ | V | - [HStore Widget [VSlot $p1 *] [VSlot $p2 *]] +--->[HStore ...]<-+ + [HStore Widget [VSlot $p1 *] [VSlot $p2 *]] +--->[HStore ...]<-+ | | | V V | [VStore int 10] [VStore object *]----------+ @@ -1275,7 +1296,7 @@ copy*. If a *deep copy* of an object is desired, the programmer must achieve this manually by using the [method `__clone`](14-classes.md#method-__clone) which is called after the initial shallow copy has been performed. -##Scope +## Scope The same name can designate different things at different places in a program. For each different thing that a name designates, that name is @@ -1314,7 +1335,7 @@ has its own scope separate from that of any function inside which that anonymous The variable scope of a parameter is the body of the function in which the parameter is declared. -The scope of a []*named-label*](11-statements.md#labeled-statements) is the body of the function in +The scope of a [*named-label*](11-statements.md#labeled-statements) is the body of the function in which the label is defined. The class scope of a [class member m](14-classes.md#class-members) that is declared in, or inherited by, a @@ -1324,10 +1345,10 @@ The class scope of an [interface member m](14-classes.md#class-members) that is an interface type I is the body of I. When a [trait](16-traits.md#general) is used by a class or an interface, the [trait's -members](16-traits.md#trait-members) take on the class scope of a member of that class or +members](16-traits.md#trait-declarations) take on the class scope of a member of that class or interface. -##Storage Duration +## Storage Duration The lifetime of a variable is the time during program execution that storage for that variable is guaranteed to exist. This lifetime is @@ -1357,7 +1378,7 @@ Engine via its garbage-collection process and the use of storage duration: [array elements](07-variables.md#array-elements) and [instance properties](07-variables.md#instance-properties). Although all three storage durations have default ends-of-life, their -lives can be shortened by calling the intrinsic [`unset`](10-expressions.md#unset), +lives can be shortened by using the [`unset` statement](11-statements.md#the-unset-statement), which destroys any given set of variables. The following example demonstrates the three storage durations: diff --git a/spec/05-types.md b/spec/05-types.md index bc5f4ea6..703da4f8 100644 --- a/spec/05-types.md +++ b/spec/05-types.md @@ -1,6 +1,6 @@ -#Types +# Types -##General +## General The meaning of a value is determined by its *type*. PHP's types are categorized as *scalar types* and *composite types*. The scalar types @@ -26,9 +26,9 @@ The same variable can contain values of different types at different times. 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). -##Scalar Types +## Scalar Types -###General +### General The integer and floating-point types are collectively known as *arithmetic types*. The library function [`is_numeric`](http://www.php.net/is_numeric) indicates if @@ -43,7 +43,7 @@ convertible to scalar types (this is currently available only to internal classe Such object types together with scalar types are called *scalar-compatible types*. Note that the same object type may be scalar-compatible for one operation but not for another. -###The Boolean Type +### The Boolean Type The Boolean type is `bool`, for which the name `boolean` is a synonym. This type is capable of storing two distinct values, which correspond to the @@ -53,7 +53,7 @@ The internal representation of this type and its values is unspecified. The library function [`is_bool`](http://www.php.net/is_bool) indicates if a given value has type `bool`. -###The Integer Type +### The Integer Type There is one integer type, `int`, for which the name `integer` is a synonym. This type is binary, signed, and uses twos-complement representation for @@ -77,7 +77,7 @@ characteristics about type `int`. The library function [`is_int`](http://www.php.net/is_int) indicates if a given value has type `int`. -###The Floating-Point Type +### The Floating-Point Type There is one floating-point type, `float`, for which the names `double` and `real` are synonyms. The `float` type must support at least the range and @@ -90,12 +90,12 @@ indicates if a given floating-point value is infinite. The library function [`is_nan`](http://www.php.net/is_nan) indicates if a given floating-point value is a `NaN`. -###The String Type +### The String Type A string is a set of contiguous bytes that represents a sequence of zero or more characters. -Conceptually, a string can be considered as an [array](#array-types) of +Conceptually, a string can be considered as an [array](#the-array-type) of bytes—the *elements*—whose keys are the `int` values starting at zero. The type of each element is `string`. However, a string is *not* considered a collection, so it cannot be iterated over. @@ -119,31 +119,43 @@ the requirements of a numeric string, and whose trailing characters are non-numeric. A *non-numeric string* is a string that is not a numeric string. -
-  str-numeric::
-    str-whitespaceopt   signopt   str-number
-
-  str-whitespace::
-    str-whitespaceopt   str-whitespace-char
-
-  str-whitespace-char::
-    new-line
-    Space character (U+0020)
-    Horizontal-tab character (U+0009)
-    Vertical-tab character (U+000B)
-    Form-feed character (U+000C)
-
-  str-number::
-    digit-sequence
-    floating-literal
-
+ + +
+str-numeric::
+   str-whitespaceopt   signopt   str-number
+
+str-whitespace::
+   str-whitespaceopt   str-whitespace-char
+
+str-whitespace-char::
+   new-line
+   Space character (0x20)
+   Horizontal-tab character (0x09)
+   Vertical-tab character (0x0B)
+   Form-feed character (0x0C)
+
+str-number::
+   digit-sequence
+   floating-literal
+
Note that *digit-sequence* is interpreted as having base-10 (so `"0377"` is treated as 377 decimal with a redundant leading zero, rather than as octal 377). @@ -154,16 +166,16 @@ assignment, which involves the simple assignment [operator =](10-expressions.md# The library function [`is_string`](http://www.php.net/is_string) indicates if a given value has type string. -###The Null Type +### The Null Type The null type has only one possible value, [`NULL`](06-constants.md#core-predefined-constants). The representation of this type and its value is unspecified. The library function [`is_null`](http://www.php.net/is_null) indicates if a given value is `NULL`. -##Composite Types +## Composite Types -###The Array Type +### The Array Type An array is a data structure that contains a collection of zero or more elements whose values are accessed through keys that are of type `int` or @@ -172,17 +184,17 @@ elements whose values are accessed through keys that are of type `int` or The library function [`is_array`](http://www.php.net/is_array) indicates if a given value is an array. -###Objects +### Objects An *object* is an instance of a [class](14-classes.md#classes). Each distinct -[]*class-declaration*](14-classes.md#class-declarations) defines a new class type, and each class +[*class-declaration*](14-classes.md#class-declarations) defines a new class type, and each class type is an object type. The representation of object types is unspecified. The library function [`is_object`](http://www.php.net/is_object) indicates if a given value is an object, and the library function [`get_class`](http://php.net/manual/function.get-class.php) indicates the name of an object's class. -###Resources +### Resources A [*resource*](http://php.net/manual/language.types.resource.php) is a descriptor to some sort of external entity. Examples include @@ -197,6 +209,3 @@ Each distinct resource has a unique identity of some unspecified form. The library function [`is_resource`](http://www.php.net/is_resource) indicates if a given value is a resource, and the library function [`get_resource_type`](http://php.net/manual/function.get-resource-type.php) indicates the type of a resource. - - - diff --git a/spec/06-constants.md b/spec/06-constants.md index 7b8532f5..8b23a2af 100644 --- a/spec/06-constants.md +++ b/spec/06-constants.md @@ -1,6 +1,6 @@ -#Constants +# Constants -##General +## General A *constant* is a [named](09-lexical-structure.md#names) value. Once defined, the value of the constant can not be changed. @@ -12,13 +12,10 @@ Specifically: - The name of a c-constant must comply with the lexical grammar for a name while that for a d-constant can contain any source character. -- The name of a c-constant is case-sensitive while that for a - d-constant can be case-sensitive or case-insensitive based on the - value of the third argument passed to `define`. - If `define` is able to define the given name, it returns `TRUE`; otherwise, it returns `FALSE`. -The constants can only hold a value of a [scalar type](05-types.md#scalar-types), an array or a [resource](05-types.md#resource-types). +The constants can only hold a value of a [scalar type](05-types.md#scalar-types), an array or a [resource](05-types.md#resources). The 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) @@ -30,11 +27,11 @@ string. ```PHP const MAX_HEIGHT = 10.5; // define two (case-sensitive) c-constants const UPPER_LIMIT = MAX_HEIGHT; -define('COEFFICIENT_1', 2.345, TRUE); // define a case-insensitive d-constant +define('COEFFICIENT_1', 2.345, TRUE); // define a case-insensitive d-constant (deprecated) define('FAILURE', FALSE, FALSE); // define a case-sensitive d-constant ``` -##Context-Dependent Constants +## Context-Dependent Constants The following constants—sometimes referred to as *magic constants*—are automatically available to all scripts; their values are not fixed and they are case-insensitive: @@ -53,7 +50,7 @@ automatically available to all scripts; their values are not fixed and they are Constant names beginning with __ are reserved for future use by the Engine. -##Core Predefined Constants +## Core Predefined Constants The following constants are automatically available to all scripts; they are case-sensitive with the exception of `NULL`, `TRUE` and `FALSE`: @@ -76,7 +73,6 @@ Constant Name | Description `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`](http://www.php.net/trigger_error). `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`](http://www.php.net/trigger_error). `E_WARNING` | `int`; Run-time warnings (non-fatal errors). Execution of the script is not halted. -`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`](http://www.php.net/trigger_error). `FALSE` | `bool`; the case-insensitive Boolean value `FALSE`. `INF` | `float`; Infinity `M_1_PI` | `float`; 1/pi @@ -109,11 +105,16 @@ Constant Name | Description `PHP_INT_MAX` | `int`; the maximum representable value for an integer. `PHP_INT_MIN` | `int`; the minimum representable value for an integer. `PHP_INT_SIZE` | `int`; the number of bytes used to represent an integer. +`PHP_FLOAT_DIG` | `int`; the number of decimal digits that can be rounded into a float and back without precision loss. +`PHP_FLOAT_EPSILON` | `float`; the smallest representable positive number `x`, so that `x + 1.0 != 1.0`. +`PHP_FLOAT_MIN` | `float`; the smallest representable normalized floating point number larger than zero. +`PHP_FLOAT_MAX` | `float`; the largest representable floating point number. `PHP_MAJOR_VERSION` | `int`; the current PHP major version `PHP_MANDIR` | `string`; the installation location of the manual pages. `PHP_MAXPATHLEN` | `int`; the maximum length of a fully qualified filename supported by this build. `PHP_MINOR_VERSION` | `int`; the current PHP minor version. `PHP_OS` | `string`; the current operating system. +`PHP_OS_FAMILY` | `string`; the operating system family PHP was built for. Either of 'Windows', 'BSD', 'Darwin', 'Solaris', 'Linux' or 'Unknown'. `PHP_PREFIX` | `string`; the value to which "--prefix" was set when configured. `PHP_RELEASE_VERSION` | `int`; the current PHP release version. `PHP_ROUND_HALF_DOWN` | `int`; Round halves down. @@ -134,10 +135,7 @@ Constant Name | Description The members of the `E_*` family have values that are powers of 2, so they can be combined meaningfully using bitwise operators. -##User-Defined Constants +## User-Defined Constants A constant may be defined inside or outside of functions, inside a [class](14-classes.md#constants), or inside an [interface](15-interfaces.md#constants). - - - diff --git a/spec/07-variables.md b/spec/07-variables.md index f2dae215..b280fda8 100644 --- a/spec/07-variables.md +++ b/spec/07-variables.md @@ -1,9 +1,10 @@ -#Variables +# Variables -##General +## General A *variable* is a named area of data storage that contains a PHP value. A variable is represented by a [VSlot](04-basic-concepts.md#general). A variable is created by [assigning a value](04-basic-concepts.md#assignment) to it. -A variable is destroyed by *unsetting* it, either by an explicit call to the intrinsic [`unset`](10-expressions.md#unset), or by the Engine. The intrinsic [`isset`](10-expressions.md#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`. +A variable is destroyed by *unsetting* it, either by an explicit call to the [`unset` statement](11-statements.md#the-unset-statement), or by the Engine. The intrinsic [`isset`](10-expressions.md#isset) tests if a given variable exists and is not set to `NULL`. +If a variable, which is not defined so far, is used in an expression, then different strategies are applied which determine whether the variable is defined implicitly or a substitution value is used instead and whether a notice is emitted or not. The strategies depend on the kind of the variable as well as on the context where the undefined variable is being used. The strategies are elaborated in the sub-sections of the different [kinds of variables](#kinds-of-variables) below. Variables have [names](09-lexical-structure.md#names). Distinct variables may have the same name provided they are in different [scopes](04-basic-concepts.md#scope). @@ -27,9 +28,9 @@ The following kinds of variable may exist in a script: - [Static class property](#static-properties). - [Class and interface constant](#class-and-interface-constants). -##Kinds of Variables +## Kinds of Variables -###Constants +### Constants **Syntax** @@ -47,6 +48,14 @@ See [constants](06-constants.md#general) and [class constants](14-classes.md#con A constant defined outside of a class or interface is a [superglobal](#general). A constant has static [storage duration](04-basic-concepts.md#storage-duration) and is a non-modifiable lvalue. +**Undefined Constants** + +Undefined constants are not defined implicitly -- forward usages of constants are also classified as undefined constants here. A distinction between class/interface constants and top level constants is made. + +For top level constants: For unqualified usages, the name of the undefined constant (as string) is used as substitution value. Moreover, a warning is emitted stating that the corresponding constant was undefined. For qualified usages, an exception of type [`Error`](14-classes.md#class-error) is thrown. + +For class/interface constants: An exception of type [`Error`](14-classes.md#class-error) is thrown, stating that the corresponding constant was undefined. + **Examples** ```PHP @@ -54,9 +63,33 @@ const MAX_HEIGHT = 10.5; // define two c-constants const UPPER_LIMIT = MAX_HEIGHT; define('COEFFICIENT_1', 2.345); // define two d-constants define('FAILURE', TRUE); + +// Examples of undefined constants +echo NON_EXISTING_CONSTANT; // uses 'NON_EXISTING_CONSTANT' as substitution + // value and emits a warning stating that the + // constant was undefined. + +echo NON_EXISTING_CONSTANT; // same here, the constant is still undefined + // and 'NON_EXISTING_CONSTANT' is used as + // substitution value and a warning is emitted + // again. + +echo MAX_LENGTH; // same here due to a forward usage + // (MAX_LENGTH is defined further below). + // 'MAX_LENGTH' is used as substitution + // value and a warning is emitted. + +echo \NON_EXISTING_CONSTANT; // qualified use of undefined constant. Throws + // an exception of type Error. + +const MAX_LENGTH = 7.5; + +echo Exception::MESSAGE; // undefined class constant. Throws an exception + // of type Error. + ``` -###Local Variables +### Local Variables **Syntax** @@ -102,52 +135,166 @@ Unlike the [function static equivalent](#function-statics), function `f` outputs See the recursive function example in [storage duration section](04-basic-concepts.md#storage-duration). -###Array Elements + +**Undefined Local Variables** + +A distinction is made based on the context where an undefined local variable is used. + +*byVal Context* + +PHP does not implicitly define an undefined local variable and uses `NULL` as substitution value instead. Furthermore, a notice is emitted, stating that the corresponding variable was undefined, unless the variable is used + +1. as the single expression in a statement. +2. as argument of [isset](10-expressions.md#isset). +3. as argument of [empty](10-expressions.md#empty). +4. as the left hand side of the [coalesce operator `??`](10-expressions.md#coalesce-operator). + +Since undefined local variables are not defined implicitly, they stay undefined. In general, a VSlot is not created for undefined variables used in a byValue context. + +*byRef Context* + +If the undefined variable is used in a byRef context then PHP defines the variable implicitly. Hence, a VSlot is created for it and `NULL` is stored in it. A notice is *not* emitted in such a case. + +*Examples of Undefined Variables* + +Following some examples which outlines the behaviour with undefined local variables. + +```PHP +// The following 4 cases outline the exceptions of undefined variables +// used in byValue context where no notice is emitted. +$a; +isset($a); +empty($a); +$a ?? 'default Value'; + +$a = 1; // a VSlot for $a was created and 1 was assigned. + +$b = $c; // a VSlot for $b was created and the value of $c was assigned to + // it. But because $c in turn was undefined, NULL was used as + // substitution value instead. In addition, a notice was + // emitted stating that $c was undefined. + +$d = $c; // a VSlot for $d was created and the value of $c was assigned to + // it. But since $c is still undefined, NULL was used as + // substitution value instead and another notice was emitted + // stating $c was undefined. + +$d + $e; // $e was undefined and `NULL` was used as substitution value + // instead. In addition, a notice was emitted stating that + // $e was undefined. + +$f = &$g; // a VSlot for $f was created which points to the VSlot of $g. + // $g in turn was undefined but was defined implicitly because the + // assignment was byRef. Thus a VSlot for $g was created and `NULL` + // was assigned to it. A notice was *not* emitted. + +$h = $g; // a VSlot for $h was created and the value of $g (which is NULL) + // was assigned to it. + +function foo($x){} + +foo($i); // $i was undefined and NULL was used as substitution value + // instead. In addition, a notice was emitted stating that $i + // was undefined. + +$j = $i; // a VSlot for $j was created and the value of $i was assigned to + // it. But because $i in turn was still undefined, NULL was used + // as substitution value instead. Another notice was emitted + // stating that $i was undefined. + +function bar(&$x){} + +bar($k); // $k was undefined but implicitly defined because it was passed to + // the function bar byRef. Thus a VSlot for $k was created and + // NULL was assigned to it. A notice was *not* emitted. + +$l = $k; // a VSlot for $l was created and the value of $k (which is NULL) + // was assigned to it. + +``` + +### Array Elements **Syntax** -[Arrays](12-arrays.md#arrays) are created via the [array-creation operator](10-expressions.md#array-creation-operator) or -the intrinsic [`array`](10-expressions.md#array). At the same time, one or more elements +[Arrays](12-arrays.md#arrays) are created using the [array-creation operator](10-expressions.md#array-creation-operator). At the same time, one or more elements may be created for that array. New elements are inserted into an existing array via the [simple-assignment operator](10-expressions.md#simple-assignment) in conjunction with the subscript [operator `[]`](10-expressions.md#subscript-operator). Elements can be -removed by calling the [`unset` intrinsic](10-expressions.md#unset). +removed by calling the [`unset` statement](11-statements.md#the-unset-statement). **Semantics** The [scope](04-basic-concepts.md#scope) of an array element is the same as the scope of that array's name. An array element has allocated [storage duration](04-basic-concepts.md#storage-duration). +**Undefined Array Elements** + +Similar to [undefined local variables](#undefined-local-variables), a distinction is made based on the context where an undefined array element is used. + +*byValue Context* + +If one tries to access an undefined array element, then `NULL` is used as substitution value and a notice is emitted, stating that an undefined offset was used. The undefined offset is not created implicitly and a subsequent access results in another notice. + +*byRef Context* + +PHP defines implicitly an undefined array element when it is accessed byRef, a VSlot for the corresponding undefined offset is created and `NULL` is assigned to it. A notice is *not* emitted in this case. + **Examples** ```PHP $colors = ["red", "white", "blue"]; // create array with 3 elements $colors[] = "green"; // insert a new element + +echo $colors[100]; // element with offset 100 is undefined and NULL is + // used as substitution value. Moreover, a notice is + // emitted stating that an undefined offset was used. + +echo $colors[100]; // element with offset 100 is still undefined and NULL + // is used as substitution value instead. Another + // notice is emitted. + +$b = &$colors[100]; // a VSlot for $b is created which points to the array + // element with the offset 100. An array element with + // offset 100 was undefined but implicitly defined + // because the assignment is byRef. Thus a VSlot for + // the array element with offset 100 is created and + // NULL is assigned to it. A notice is *not* emitted. ``` -###Function Statics +### Function Statics **Syntax** -
-  function-static-declaration:
-    static static-variable-name-list  ;
+
+
+
+function-static-declaration:
+   static   static-variable-name-list   ;
+
+static-variable-name-list:
+   static-variable-declaration
+   static-variable-name-list   ,   static-variable-declaration
 
-**Defined elsewhere**
+static-variable-declaration:
+   variable-name   function-static-initializeropt
 
-* [*variable-name*](09-lexical-structure.md#names)
-* [*constant-expression*](10-expressions.md#constant-expressions)
+function-static-initializer:
+   =   constant-expression
+
**Constraints** @@ -163,9 +310,13 @@ A function static has function [scope](04-basic-concepts.md#scope) and static [s The value of a function static is retained across calls to its parent function. Each time the function containing a function static declaration is called, that execution is dealing with an [alias](04-basic-concepts.md#general) -to that static variable. If that alias is passed to the [`unset` intrinsic](10-expressions.md#unset), +to that static variable. If that alias is passed to the [`unset` statement](11-statements.md#the-unset-statement), only that alias is destroyed. The next time that function is called, a new alias is created. +**Undefined Function Statics** + +Function statics are explicitly defined and thus cannot be undefined. + **Examples** ```PHP @@ -183,33 +334,49 @@ Unlike the [local variable equivalent](#local-variables), function `f` outputs " = 1`", "`$fs = 2`", and "`$fs = 3`", as `$fs` retains its value across calls. -###Global Variables - -**Syntax** + +Be also aware that declaring a function static can hide a local variable and/or a global variable with the same name. The value of the local or global variable is not taken over as initial value of the function static. Subsequent modifications of the variable only modify the function static and do not affect the local nor the global variable. An example: -
-  global-declaration:
-    global variable-name-list ;
+```PHP
+function f(){
+  $fs = 10;             // assign 10 to the local variable $fs
+  static $fs;           // define a function static with name $fs
+  echo "\$fs = $fs\n";  // $fs =
+  $fs = 5;              // assign 5 to the function static $fs (local variable is not modified)
+  echo "\$fs = $fs\n";  // $fs = 5
+  global $fs;           // define a global variable with name $fs
+  echo "\$fs = $fs\n";  // $fs =
+  $fs = 3;              // assign 3 to the global variable $fs (function static and local variable is not modified
+  echo "\$fs = $fs\n";  // $fs = 3
+  static $fs;
+  ++$fs;                // increment function static $fs
+  echo "\$fs = $fs\n";  // $fs = 6
+}
+f();
+echo "\$fs = $fs\n";    // $fs = 3
+```
 
-  variable-name-list:
-    global-variable
-    variable-name-list  ,  global-variable
+### Global Variables
 
-  global-variable:
-    variable-name
-	variable-name-creation-expression
-
+**Syntax** -**Defined elsewhere** + -**Constraints** +
+global-declaration:
+   global   variable-name-list   ;
 
-Each *variable-name-creation-expression* must designate a simple variable name, i.e. it can not include array elements,
-property accesses, etc. that are not inside braced expression.
+variable-name-list:
+   simple-variable
+   variable-name-list   ,   simple-variable
+
**Semantics** @@ -235,10 +402,14 @@ A global variable has global [scope](04-basic-concepts.md#scope) and static When a global value is imported into a function, each time the function is called, that execution is dealing with an [alias](04-basic-concepts.md#general) to that -global variable. If that alias is passed to the [`unset` intrinsic](10-expressions.md#unset), +global variable. If that alias is passed to the [`unset` statement](11-statements.md#the-unset-statement), only that alias is destroyed. The next time that function is called, a new alias is created with the current value of the global variable. +**Undefined Global Variables** + +The same rules as for [undefined local variables](#undefined-local-variables) apply. + **Examples** ```PHP @@ -272,26 +443,28 @@ function f() } ``` -###Instance Properties +Be also aware that declaring a variable global can hide a local variable and/or a function static with the same name. See [static variables section](#hidingNotice) for an example. + +### Instance Properties These are described in [class instance properties section](14-classes.md#properties). They have class [scope](04-basic-concepts.md#scope) of the defining class and allocated [storage duration](04-basic-concepts.md#storage-duration). Access to the instance properties is governed by [visibility rules](14-classes.md#general). -###Static Properties +### Static Properties These are described in [class static properties section](14-classes.md#properties). They have class [scope](04-basic-concepts.md#scope) of the defining class and static [storage duration](04-basic-concepts.md#storage-duration). Access to the static properties is governed by [visibility rules](14-classes.md#general). -###Class and Interface Constants +### Class and Interface Constants These are described in [class constants section](14-classes.md#constants) and [interface constants section](15-interfaces.md#constants). They have class [scope](04-basic-concepts.md#scope) of the defining class or interface and static [storage duration](04-basic-concepts.md#storage-duration). -##Predefined Variables +## Predefined Variables The following global variables are available to all scripts: diff --git a/spec/08-conversions.md b/spec/08-conversions.md index 51ba0a4c..069676d6 100644 --- a/spec/08-conversions.md +++ b/spec/08-conversions.md @@ -1,10 +1,10 @@ -#Conversions +# Conversions -##General +## General Explicit type conversion is performed using the [cast operator](10-expressions.md#cast-operator). If an operation or language construct expects operand of one type and a value of another type is given, -implict (automatic) conversion will be performed. Same will happen with most internal functions, though some +implicit (automatic) conversion will be performed. Same will happen with most internal functions, though some functions may do different things depending on argument type and thus would not perform the conversion. If an expression is converted to its own type, the type and value of the @@ -12,9 +12,9 @@ result are the same as the type and value of the expression. Conversions to `resource` and `null` types can not be performed. -##Converting to Boolean Type +## Converting to Boolean Type -The [result type] (http://www.php.net/manual/en/language.types.boolean.php#language.types.boolean.casting) is [`bool`](05-types.md#the-boolean-type). +The [result type](http://www.php.net/manual/en/language.types.boolean.php#language.types.boolean.casting) is [`bool`](05-types.md#the-boolean-type). If the source type is `int` or `float`, then if the source value tests equal to 0, the result value is `FALSE`; otherwise, the result value is `TRUE`. @@ -34,7 +34,7 @@ If the source is a resource, the result value is `TRUE`. The library function [`boolval`](http://www.php.net/boolval) allows values to be converted to `bool`. -##Converting to Integer Type +## Converting to Integer Type The [result type](http://www.php.net/manual/en/language.types.integer.php#language.types.integer.casting) is [`int`](05-types.md#the-integer-type). @@ -84,7 +84,7 @@ If the source is a resource, the result is the resource's unique ID. The library function [`intval`](http://php.net/manual/function.intval.php) allows values to be converted to `int`. -##Converting to Floating-Point Type +## Converting to Floating-Point Type The [result type](http://www.php.net/manual/en/language.types.float.php#language.types.float.casting) is [`float`](05-types.md#the-floating-point-type). @@ -110,7 +110,7 @@ For sources of all other types, the conversion result is obtained by first The library function [`floatval`](http://www.php.net/floatval) allows values to be converted to float. -##Converting to String Type +## Converting to String Type The [result type](http://www.php.net/manual/en/language.types.string.php#language.types.string.casting) is [`string`](05-types.md#the-string-type). @@ -136,7 +136,7 @@ implementation-defined string. The library function [`strval`](http://www.php.net/strval) allows values to be converted to string. -##Converting to Array Type +## Converting to Array Type The [result type](http://www.php.net/manual/en/language.types.array.php#language.types.array.casting) is [`array`](05-types.md#the-array-type). @@ -167,7 +167,7 @@ where *name* is that of the property. The value for each key is that from the corresponding property, or `NULL` if the property was not initialized. -##Converting to Object Type +## Converting to Object Type The [result type](http://www.php.net/manual/en/language.types.object.php#language.types.object.casting) is [`object`](05-types.md#objects). diff --git a/spec/09-lexical-structure.md b/spec/09-lexical-structure.md index 40a34188..537c9936 100644 --- a/spec/09-lexical-structure.md +++ b/spec/09-lexical-structure.md @@ -1,20 +1,19 @@ -#Lexical Structure +# Lexical Structure -##Scripts +## Scripts A [script](04-basic-concepts.md#program-structure) is an ordered sequence of characters. Typically, a script has a one-to-one correspondence with a file in a file system, but this correspondence is not required. +PHP scripts are parsed as a series of 8-bit bytes, rather than code points from Unicode or any other character repertoire. +Within this specification, bytes are represented by their ASCII interpretations where these are printable characters. Conceptually speaking, a script is translated using the following steps: -1. Transformation, which converts a script from a particular character - repertoire and encoding scheme into a sequence of 8-bit characters. - -2. Lexical analysis, which translates a stream of input characters into +1. Lexical analysis, which translates a stream of input characters into a stream of tokens. -3. Syntactic analysis, which translates the stream of tokens into +2. Syntactic analysis, which translates the stream of tokens into executable code. Conforming implementations must accept scripts encoded with the UTF-8 @@ -22,7 +21,7 @@ encoding form (as defined by the Unicode standard), and transform them into a sequence of characters. Implementations can choose to accept and transform additional character encoding schemes. -##Grammars +## Grammars This specification shows the syntax of the PHP programming language using two grammars. The *lexical grammar* defines how source @@ -43,13 +42,19 @@ successive indented line contains a possible expansion of the non-terminal given as a sequence of non-terminal or terminal symbols. For example, the production: + +
-  single-line-comment::
-    // input-charactersopt
-    #  input-charactersopt
+single-line-comment-example::
+   //   input-charactersopt
+   #   input-charactersopt
 
-defines the lexical grammar production *single-line-comment* as being +defines the lexical grammar production *single-line-comment-example* as being the terminals `//` or `#`, followed by an optional *input-characters*. Each expansion is listed on a separate line. @@ -57,37 +62,50 @@ Although alternatives are usually listed on separate lines, when there is a large number, the shorthand phrase “one of” may precede a list of expansions given on a single line. For example, + +
-  hexadecimal-digit:: one of
-    0   1   2   3   4   5   6   7   8   9
-    a   b   c   d   e   f
-    A   B   C   D   E   F
+hexadecimal-digit-example:: one of
+   0   1   2   3   4   5   6   7   8   9
+   a   b   c   d   e   f
+   A   B   C   D   E   F
 
-##Lexical analysis +## Lexical analysis -###General +### General The production *input-file* is the root of the lexical structure for a script. Each script must conform to this production. **Syntax** -
-  input-file::
-    input-element
-    input-file   input-element
-  input-element::
-    comment
-    white-space
-    token
-
+ -* [*comment*](#comments) -* [*white-space*](#white-space) -* [*token*](#tokens) +
+input-file::
+   input-element
+   input-file   input-element
+
+input-element::
+   comment
+   white-space
+   token
+
**Semantics** @@ -102,43 +120,68 @@ Lexical processing always results in the creation of the longest possible lexical element. (For example, `$a+++++$b` must be parsed as `$a++ ++ +$b`, which syntactically is invalid). -###Comments +### Comments Two forms of comments are supported: *delimited comments* and *single-line comments*. **Syntax** + +
-  comment::
-    single-line-comment
-    delimited-comment
+comment::
+   single-line-comment
+   delimited-comment
 
-  single-line-comment::
-    //   input-charactersopt
-    #    input-charactersopt
+single-line-comment::
+   //   input-charactersopt
+   #   input-charactersopt
 
-  input-characters::
-    input-character
-    input-characters   input-character
+input-characters::
+   input-character
+   input-characters   input-character
 
-  input-character::
-    Any source character except new-line
+input-character::
+   Any source character except   new-line
 
-  new-line::
-    Carriage-return character (U+000D)
-    Line-feed character (U+000A)
-    Carriage-return character (U+000D) followed by line-feed character (U+000A)
+new-line::
+   Carriage-return character (0x0D)
+   Line-feed character (0x0A)
+   Carriage-return character (0x0D) followed by line-feed character (0x0A)
 
-  delimited-comment::
-    /*   No characters or any source character sequence except */   */
+delimited-comment::
+   /*   No characters or any source character sequence except */   */
 
**Semantics** -Except within a string literal or a comment, the characters /\* start a -delimited comment, which ends with the characters \*/. Except within a -string literal or a comment, the characters // or \# start a single-line +Except within a string literal or a comment, the characters `/*` start a +delimited comment, which ends with the characters `*/`. Except within a +string literal or a comment, the characters `//` or `#` start a single-line comment, which ends with a new line. That new line is not part of the comment. However, if the single-line comment is the last source element in an embedded script, the trailing new line can be omitted. (Note: this @@ -154,99 +197,141 @@ space](#white-space) can occur. (For example; During tokenizing, an implementation can treat a delimited comment as though it was white space. -###White Space +### White Space White space consists of an arbitrary combination of one or more -new-line, space, horizontal tab, vertical tab, and form-feed characters. +new-line, space and horizontal tab characters. **Syntax** -
-  white-space::
-    white-space-character
-    white-space   white-space-character
-
-  white-space-character::
-    new-line
-    Space character (U+0020)
-    Horizontal-tab character (U+0009)
-
+ -* [*new-line*](#comments) +
+white-space::
+   white-space-character
+   white-space   white-space-character
+
+white-space-character::
+   new-line
+   Space character (0x20)
+   Horizontal-tab character (0x09)
+
**Semantics** The space and horizontal tab characters are considered *horizontal white-space characters*. -###Tokens +### Tokens -####General +#### General There are several kinds of source *tokens*: **Syntax** + +
-  token::
-    variable-name
-    name
-    keyword
-    literal
-    operator-or-punctuator
+token::
+   variable-name
+   name
+   keyword
+   integer-literal
+   floating-literal
+   string-literal
+   operator-or-punctuator
 
-**Defined elsewhere** +#### Names -* [*variable-name*](#names) -* [*name*](#names) -* [*keyword*](#keywords) -* [*literal*](#general-2) -* [*operator-or-punctuator*](#operators-and-punctuators) +**Syntax** -####Names + + +
+variable-name::
+   $   name
+
+namespace-name::
+   name
+   namespace-name   \   name
+
+namespace-name-as-a-prefix::
+   \
+   \opt   namespace-name   \
+   namespace   \
+   namespace   \   namespace-name   \
+
+qualified-name::
+   namespace-name-as-a-prefixopt   name
+
+name::
+   name-nondigit
+   name   name-nondigit
+   name   digit
+
+name-nondigit::
+   nondigit
+   one of the characters 0x80–0xff
+
+nondigit:: one of
+   _
+   a   b   c   d   e   f   g   h   i   j   k   l   m
+   n   o   p   q   r   s   t   u   v   w   x   y   z
+   A   B   C   D   E   F   G   H   I   J   K   L   M
+   N   O   P   Q   R   S   T   U   V   W   X   Y   Z
+
**Semantics** @@ -258,26 +343,26 @@ Names are used to identify the following: [constants](06-constants.md#general), and names in [heredoc](#heredoc-string-literals) and [nowdoc comments](#nowdoc-string-literals). A *name* begins with an underscore (_), *name-nondigit*, or extended -name character in the range U+007f–-U+00ff. Subsequent characters can +name character in the range 0x80–-0xff. Subsequent characters can also include *digits*. A *variable name* is a name with a leading dollar ($). Unless stated otherwise ([functions](13-functions.md#function-definitions), [classes](14-classes.md#class-declarations), [methods](14-classes.md#methods), [interfaces](15-interfaces.md#interface-declarations), [traits](16-traits.md#trait-declarations), -[namespaces](18-namespaces.md#defining-namespaces), names are case-sensitive, and every character in a name is significant. +[namespaces](18-namespaces.md#defining-namespaces)), names are case-sensitive, and every character in a name is significant. Names beginning with two underscores (__) are reserved by the PHP language and should not be defined by the user code. -The following names cannot be used as the names of classes, interfaces, or traits: `bool`, `FALSE`, `float`, `int`, `NULL`, `string`, and `TRUE`. +The following names cannot be used as the names of classes, interfaces, or traits: `bool`, `FALSE`, `float`, `int`, `NULL`, `string`, `TRUE`, `iterable`, and `void`. The following names are reserved for future use and should not be used as the names of classes, interfaces, or traits: `mixed`, `numeric`, `object`, and `resource`. -With the exception of `class`, all [keywords](09-lexical-structures#keywords) can be used as names for the members of a class, interface, or trait. However, `class` can be used as the name of a property or method. +With the exception of `class`, all [keywords](#keywords) can be used as names for the members of a class, interface, or trait. However, `class` can be used as the name of a property or method. Variable names and function names (when used in a function-call context) need not be defined as source tokens; they can also be created at -runtime using the [variable name-creation operator](10-expressions.md#variable-name-creation-operator). (For +runtime using [simple variable expressions](10-expressions.md#simple-variable). (For example, given `$a = "Total"; $b = 3; $c = $b + 5;`, `${$a.$b.$c} = TRUE;` is equivalent to `$Total38 = TRUE;`, and `${$a.$b.$c}()` is equivalent to `Total38()`). @@ -296,23 +381,35 @@ interface ICollection { /*...*/ } An implementation is discouraged from placing arbitrary restrictions on name lengths. -####Keywords +#### Keywords A *keyword* is a name-like sequence of characters that is reserved, and cannot be used as a name. **Syntax** + +
-  keyword:: one of
-    abstract   and   array   as   break   callable   case   catch   class   clone
-    const   continue   declare   default   die   do   echo   else   elseif   empty
-    enddeclare   endfor   endforeach   endif   endswitch   endwhile   eval   exit
-    extends   final   finally   for   foreach   function   global
-    goto   if   implements   include   include_once   instanceof
-    insteadof   interface   isset   list   namespace   new   or   print   private
-    protected   public   require   require_once   return static   switch
-    throw   trait   try   unset   use   var   while   xor   yield   yield from
+keyword:: one of
+   abstract   and   array   as   break   callable   case   catch   class   clone
+   const   continue   declare   default   die   do   echo   else   elseif   empty
+   enddeclare   endfor   endforeach   endif   endswitch   endwhile   eval   exit
+   extends   final   finally   for   foreach   function   global
+   goto   if   implements   include   include_once   instanceof
+   insteadof   interface   isset   list   namespace   new   or   print   private
+   protected   public   require   require_once   return   static   switch
+   throw   trait   try   unset   use   var   while   xor   yield   yield from
 
**Semantics** @@ -323,76 +420,106 @@ Note carefully that `yield from` is a single token that contains whitespace. How Also, all [*magic constants*](06-constants.md#context-dependent-constants) are also treated as keywords. -####Literals - -#####General +#### Literals The source code representation of a value is called a *literal*. +##### Integer Literals + **Syntax** -
-  literal::
-    integer-literal
-    floating-literal
-    string-literal
-
+
-  integer-literal::
-    decimal-literal
-    octal-literal
-    hexadecimal-literal
-    binary-literal
+integer-literal::
+   decimal-literal
+   octal-literal
+   hexadecimal-literal
+   binary-literal
 
-    decimal-literal::
-      nonzero-digit
-      decimal-literal   digit
+decimal-literal::
+   nonzero-digit
+   decimal-literal   digit
 
-    octal-literal::
-      0
-      octal-literal   octal-digit
+octal-literal::
+   0
+   octal-literal   octal-digit
 
-    hexadecimal-literal::
-      hexadecimal-prefix   hexadecimal-digit
-      hexadecimal-literal   hexadecimal-digit
+hexadecimal-literal::
+   hexadecimal-prefix   hexadecimal-digit
+   hexadecimal-literal   hexadecimal-digit
 
-    hexadecimal-prefix:: one of
-      0x  0X
+hexadecimal-prefix:: one of
+   0x   0X
 
-    binary-literal::
-      binary-prefix   binary-digit
-      binary-literal   binary-digit
+binary-literal::
+   binary-prefix   binary-digit
+   binary-literal   binary-digit
 
-    binary-prefix:: one of
-      0b  0B
+binary-prefix:: one of
+   0b   0B
 
-    digit:: one of
-      0  1  2  3  4  5  6  7  8  9
+digit:: one of
+   0   1   2   3   4   5   6   7   8   9
 
-    nonzero-digit:: one of
-      1  2  3  4  5  6  7  8  9
+nonzero-digit:: one of
+   1   2   3   4   5   6   7   8   9
 
-    octal-digit:: one of
-      0  1  2  3  4  5  6  7
+octal-digit:: one of
+   0   1   2   3   4   5   6   7
 
-    hexadecimal-digit:: one of
-      0  1  2  3  4  5  6  7  8  9
-      a  b  c  d  e  f
-      A  B  C  D  E  F
+hexadecimal-digit:: one of
+   0   1   2   3   4   5   6   7   8   9
+   a   b   c   d   e   f
+   A   B   C   D   E   F
 
-    binary-digit:: one of
-        0  1
+binary-digit:: one of
+   0   1
 
**Semantics** @@ -438,34 +565,51 @@ On an implementation using 32-bit int representation 0x80000000 -> 2147483648 (too big for int, so is a float) ``` -#####Floating-Point Literals +##### Floating-Point Literals **Syntax** -
-  floating-literal::
-    fractional-literal   exponent-partopt
-    digit-sequence   exponent-part
+
+
+
+floating-literal::
+   fractional-literal   exponent-partopt
+   digit-sequence   exponent-part
+
+fractional-literal::
+   digit-sequenceopt   .   digit-sequence
+   digit-sequence   .
 
-**Defined elsewhere**
+exponent-part::
+   e   signopt   digit-sequence
+   E   signopt   digit-sequence
 
-* [*digit*](#integer-literals)
+sign:: one of
+   +   -
+
+digit-sequence::
+   digit
+   digit-sequence   digit
+
**Constraints** @@ -487,25 +631,26 @@ A floating point literal is always a constant expression. $values = array(1.23, 3e12, 543.678E-23); ``` -#####String Literals +##### String Literals **Syntax** + +
-  string-literal::
-    single-quoted-string-literal
-    double-quoted-string-literal
-    heredoc-string-literal
-    nowdoc-string-literal
+string-literal::
+   single-quoted-string-literal
+   double-quoted-string-literal
+   heredoc-string-literal
+   nowdoc-string-literal
 
-**Defined elsewhere** - -* [*single-quoted-string-literal*](#single-quoted-string-literals) -* [*double-quoted-string-literal*](#double-quoted-string-literals) -* [*heredoc-string-literal*](#heredoc-string-literals) -* [*nowdoc-string-literal*](#nowdoc-string-literals) - **Semantics** A string literal is a sequence of zero or more characters delimited in @@ -513,36 +658,58 @@ some fashion. The delimiters are not part of the literal's content. The type of a string literal is `string`. -######Single-Quoted String Literals +###### Single-Quoted String Literals **Syntax** + +
-  single-quoted-string-literal::
-    bopt  ' sq-char-sequenceopt  '
+single-quoted-string-literal::
+   b-prefixopt   '   sq-char-sequenceopt   '
+
+sq-char-sequence::
+   sq-char
+   sq-char-sequence   sq-char
 
-  sq-char-sequence::
-    sq-char
-    sq-char-sequence   sq-char
+sq-char::
+   sq-escape-sequence
+   \opt   any member of the source character set except single-quote (') or backslash (\)
 
-  sq-char::
-    sq-escape-sequence
-    \opt   any member of the source character set except single-quote (') or backslash (\)
+sq-escape-sequence:: one of
+   \'   \\
 
-  sq-escape-sequence:: one of
-    \'  \\
+b-prefix:: one of
+   b   B
 
**Semantics** A single-quoted string literal is a string literal delimited by -single-quotes (`'`, U+0027). The literal can contain any source character except +single-quotes (`'`, 0x27). The literal can contain any source character except single-quote (`'`) and backslash (`\\`), which can only be represented by their corresponding escape sequence. -The optional `b` prefix is reserved for future use in dealing with +The optional *b-prefix* is reserved for future use in dealing with so-called *binary strings*. For now, a *single-quoted-string-literal* -with a `b` prefix is equivalent to one without. +with a *b-prefix* is equivalent to one without. A single-quoted string literal is always a constant expression. @@ -554,80 +721,114 @@ A single-quoted string literal is always a constant expression. 'Can embed a single quote (\') and a backslash (\\) like this' ``` -######Double-Quoted String Literals +###### Double-Quoted String Literals **Syntax** -
-  double-quoted-string-literal::
-    bopt  " dq-char-sequenceopt  "
-
-  dq-char-sequence::
-    dq-char
-    dq-char-sequence   dq-char
-
-  dq-char::
-    dq-escape-sequence
-    any member of the source character set except double-quote (") or backslash (\)
-    \  any member of the source character set except "\$efnrtvxX or octal-digit
-
-  dq-escape-sequence::
-    dq-simple-escape-sequence
-    dq-octal-escape-sequence
-    dq-hexadecimal-escape-sequence
-    dq-unicode-escape-sequence
-
-  dq-simple-escape-sequence:: one of
-    \"   \\   \$   \e   \f   \n   \r   \t   \v
-
-  dq-octal-escape-sequence::
-    \   octal-digit
-    \   octal-digit   octal-digit
-    \   octal-digit   octal-digit   octal-digit
-
-  dq-hexadecimal-escape-sequence::
-    \x  hexadecimal-digit   hexadecimal-digitopt
-    \X  hexadecimal-digit   hexadecimal-digitopt
-
-  dq-unicode-escape-sequence::
-    \u{  codepoint-digits  }
-
-  codepoint-digits::
-     hexadecimal-digit
-     hexadecimal-digit   codepoint-digits
-
+ + +
+double-quoted-string-literal::
+   b-prefixopt   "   dq-char-sequenceopt   "
+
+dq-char-sequence::
+   dq-char
+   dq-char-sequence   dq-char
+
+dq-char::
+   dq-escape-sequence
+   any member of the source character set except double-quote (") or backslash (\)
+   \   any member of the source character set except "\$efnrtvxX or   octal-digit
+
+dq-escape-sequence::
+   dq-simple-escape-sequence
+   dq-octal-escape-sequence
+   dq-hexadecimal-escape-sequence
+   dq-unicode-escape-sequence
+
+dq-simple-escape-sequence:: one of
+   \"   \\   \$   \e   \f   \n   \r   \t   \v
+
+dq-octal-escape-sequence::
+   \   octal-digit
+   \   octal-digit   octal-digit
+   \   octal-digit   octal-digit   octal-digit
+
+dq-hexadecimal-escape-sequence::
+   \x   hexadecimal-digit   hexadecimal-digitopt
+   \X   hexadecimal-digit   hexadecimal-digitopt
+
+dq-unicode-escape-sequence::
+   \u{   codepoint-digits   }
+
+codepoint-digits::
+   hexadecimal-digit
+   hexadecimal-digit   codepoint-digits
+
**Semantics** A double-quoted string literal is a string literal delimited by -double-quotes (`"`, U+0022). The literal can contain any source character except +double-quotes (`"`, 0x22). The literal can contain any source character except double-quote (`"`) and backslash (`\\`), which can only be represented by their corresponding escape sequence. Certain other (and sometimes non-printable) characters can also be expressed as escape sequences. -The optional `b` prefix is reserved for future use in dealing with +The optional *b-prefix* is reserved for future use in dealing with so-called *binary strings*. For now, a *double-quoted-string-literal* -with a `b` prefix is equivalent to one without. +with a *b-prefix* is equivalent to one without. An escape sequence represents a single-character encoding, as described in the table below: Escape sequence | Character name | Unicode character --------------- | --------------| ------ -\$ | Dollar sign | U+0024 -\" | Double quote | U+0022 -\\ | Backslash | U+005C -\e | Escape | U+001B -\f | Form feed | U+000C -\n | New line | U+000A -\r | Carriage Return | U+000D -\t | Horizontal Tab | U+0009 -\v | Vertical Tab | U+000B +\$ | Dollar sign | 0x24 +\" | Double quote | 0x22 +\\ | Backslash | 0x5C +\e | Escape | 0x1B +\f | Form feed | 0x0C +\n | New line | 0x0A +\r | Carriage Return | 0x0D +\t | Horizontal Tab | 0x09 +\v | Vertical Tab | 0x0B \ooo | 1–3-digit octal digit value ooo \xhh or \Xhh | 1–2-digit hexadecimal digit value hh \u{xxxxxx} | UTF-8 encoding of Unicode codepoint U+xxxxxx | U+xxxxxx @@ -661,33 +862,43 @@ ill-formed Unicode escape sequences. The variable substitution accepts the following syntax: -
-    string-variable::
-        variable-name   offset-or-propertyopt
-        ${   expression   }
+
 
-
+
+string-variable::
+   variable-name   offset-or-propertyopt
+   ${   expression   }
 
-**Defined elsewhere**
+offset-or-property::
+   offset-in-string
+   property-in-string
 
-* [*variable-name*](#names)
-* [*name*](#names)
-* [*integer-literal*](#integer-literals)
-* [*expression*](10-expressions.md#general-6)
+offset-in-string::
+   [   name   ]
+   [   variable-name   ]
+   [   integer-literal   ]
 
-*expression* works the same way as in [variable name creation operator](10-expressions.md#variable-name-creation-operator).
+property-in-string::
+   ->   name
+
+ +*expression* works the same way as in [simple variable expressions](10-expressions.md#simple-variable). After the variable defined by the syntax above is evaluated, its value is converted to string according to the rules of [string conversion](08-conversions.md#converting-to-string-type) @@ -695,7 +906,7 @@ and is substituted into the string in place of the variable substitution express Subscript or property access defined by *offset-in-string* and *property-in-string* is resolved according to the rules of the [subscript operator](10-expressions.md#subscript-operator) -and [member selection operator](10-expressions.md#member-selection-operator) respectively. +and [member access operator](10-expressions.md#member-access-operator) respectively. The exception is that *name* inside *offset-in-string* is interpreted as a string literal even if it is not quoted. @@ -735,46 +946,75 @@ $myC = new C(); echo "\$myC->p1 = >$myC->p1<\n"; // → $myC->p1 = >2< ``` -######Heredoc String Literals +###### Heredoc String Literals **Syntax** -
-  heredoc-string-literal::
-    <<<  hd-start-identifier   new-line   hd-char-sequenceopt  new-line hd-end-identifier  ;opt   new-line
+
+
+
+heredoc-string-literal::
+   b-prefixopt   <<<   hd-start-identifier   new-line   hd-bodyopt   hd-end-identifier   ;opt   new-line
+
+hd-start-identifier::
+   name
+   "   name   "
 
-**Defined elsewhere**
+hd-end-identifier::
+   name
 
-* [*name*](#names)
-* [*new-line*](#comments)
-* [*dq-octal-escape-sequence*](#double-quoted-string-literals)
-* [*dq-hexadecimal-escape-sequence*](#double-quoted-string-literals)
+hd-body::
+   hd-char-sequenceopt   new-line
+
+hd-char-sequence::
+   hd-char
+   hd-char-sequence   hd-char
+
+hd-char::
+   hd-escape-sequence
+   any member of the source character set except backslash (\)
+   \ any member of the source character set except \$efnrtvxX or   octal-digit
+
+hd-escape-sequence::
+   hd-simple-escape-sequence
+   dq-octal-escape-sequence
+   dq-hexadecimal-escape-sequence
+   dq-unicode-escape-sequence
+
+hd-simple-escape-sequence:: one of
+   \\   \$   \e   \f   \n   \r   \t   \v
+
**Constraints** @@ -799,6 +1039,8 @@ A heredoc literal supports variable substitution as defined for A heredoc string literal is a constant expression if it does not contain any variable substitution. +The optional *b-prefix* has no effect. + **Examples** ```PHP @@ -812,20 +1054,20 @@ echo ">$s<"; // Some more text< ``` -######Nowdoc String Literals +###### Nowdoc String Literals **Syntax** + +
-  nowdoc-string-literal::
-    <<<  '  name  '  new-line  hd-char-sequenceopt   new-line name  ;opt   new-line
+nowdoc-string-literal::
+   b-prefixopt   <<<   '   name   '   new-line   hd-bodyopt   name   ;opt   new-line
 
-**Defined elsewhere** - -* [*hd-char-sequence*](#heredoc-string-literals) -* [*new-line*](#comments) - **Constraints** The start and end identifier names must be the same. @@ -842,6 +1084,8 @@ not subject to variable substitution (like the single-quoted string). A nowdoc string literal is a constant expression. +The optional *b-prefix* has no effect. + **Examples** ```PHP @@ -855,16 +1099,24 @@ echo ">$s<\n\n"; // Some more text< ``` -####Operators and Punctuators +#### Operators and Punctuators **Syntax** + +
-  operator-or-punctuator:: one of
-    [   ]    (   )   {    }   .   ->   ++   --   **   *   +   -   ~   !
-    $   /   %   <<    >>   <   >   <=   >=   ==   ===   !=   !==   ^   |
-    &   &&   ||   ?   :   ;   =   **=   *=   /=   %=   +=   -=   .=   <<=
-    >>=   &=   ^=   |=   =&   ,   ??   <=>   ...
+operator-or-punctuator:: one of
+   [   ]   (   )   {   }   .   ->   ++   --   **   *   +   -   ~   !
+   $   /   %   <<   >>   <   >   <=   >=   ==   ===   !=   !==   ^   |
+   &   &&   ||   ?   :   ;   =   **=   *=   /=   %=   +=   -=   .=   <<=
+   >>=   &=   ^=   |=   ,   ??   <=>   ...   \
 
**Semantics** diff --git a/spec/10-expressions.md b/spec/10-expressions.md index 0b4de83d..a3289600 100644 --- a/spec/10-expressions.md +++ b/spec/10-expressions.md @@ -1,6 +1,6 @@ -#Expressions +# Expressions -##General +## General An *expression* involves one or more terms and zero or more operators. @@ -34,14 +34,14 @@ is a sequence point at the end of each full expression. The [logical and](#logic operators each contain a sequence point. (For example, in the following series of expression statements, `$a = 10; ++$a; $b = $a;`, there is sequence point at the end of each full expression, so the -assignment to $a is completed before `$a` is incremented, and the +assignment to `$a` is completed before `$a` is incremented, and the increment is completed before the assignment to `$b`). When an expression contains multiple operators, the *precedence* of those operators controls the order in which those operators are applied. (For example, the expression `$a - $b / $c` is evaluated as -`$a - ($b / $c)` because the / operator has higher precedence than the -binary - operator). The precedence of an operator is determined by the +`$a - ($b / $c)` because the `/` operator has higher precedence than the +binary `-` operator). The precedence of an operator is determined by the definition of its associated grammar production. If an operand occurs between two operators having the same precedence, @@ -74,7 +74,7 @@ called, is unspecified). An expression that contains no side effects and whose resulting value is not used need not be evaluated. For example, the expression statements -`6;, $i + 6;`, and `$i/$j`; are well formed, but they contain no side +`6;`, `$i + 6;`, and `$i/$j`; are well formed, but they contain no side effects and their results are not used. A side effect need not be executed if it can be determined that no other @@ -83,166 +83,274 @@ of `return $a++;` and `return ++$a;`, it is obvious what value must be returned in each case, but if `$a` is a variable local to the enclosing function, `$a` need not actually be incremented. -##Primary Expressions +## Primary Expressions -###General +### General **Syntax** + +
-  primary-expression:
-    variable-name
-    qualified-name
-    literal
-    constant-expression
-    intrinsic
-    anonymous-function-creation-expression
-    (  expression  )
-    $this
+primary-expression:
+   variable
+   class-constant-access-expression
+   constant-access-expression
+   literal
+   array-creation-expression
+   intrinsic
+   anonymous-function-creation-expression
+   object-creation-expression
+   postfix-increment-expression
+   postfix-decrement-expression
+   prefix-increment-expression
+   prefix-decrement-expression
+   byref-assignment-expression
+   shell-command-expression
+   (   expression   )
 
-**Defined elsewhere** - -* [*variable-name*](09-lexical-structure.md#names) -* [*qualified-name*](09-lexical-structure.md#names) -* [*literal*](09-lexical-structure.md#general-2) -* [*constant-expression*](#constant-expressions) -* [*intrinsic*](#general-2) -* [*anonymous-function-creation-expression*](#anonymous-function-creation) -* [*expression*](#script-inclusion-operators) - **Semantics** The type and value of parenthesized expression are identical to those of the un-parenthesized expression. -The variable `$this` is predefined inside any non-static instance method (including -constructor) when that method is called from within an object -context. The value of `$this` is the calling object or the object being constructed. +### Simple Variable -###Intrinsics +**Syntax** -####General + -**Syntax**
-  intrinsic:
-    intrisic-construct
-    intrisic-operator
-
-  intrisic-construct:
-    echo-intrinsic
-    list-intrinsic
-    unset-intrinsic
-
-  intrinsic-operator:
-    array-intrinsic
-    empty-intrinsic
-    eval-intrinsic
-    exit-intrinsic
-    isset-intrinsic
-    print-intrinsic
+simple-variable:
+   variable-name
+   $   simple-variable
+   $   {   expression   }
 
-**Defined elsewhere** +**Constraints** -* [*array-intrinsic*](#array) -* [*echo-intrinsic*](#echo) -* [*empty-intrinsic*](#empty) -* [*eval-intrinsic*](#eval) -* [*exit-intrinsic*](#exitdie) -* [*isset-intrinsic*](#isset) -* [*list-intrinsic*](#list) -* [*print-intrinsic*](#print) -* [*unset-intrinsic*](#unset) +The *simple-variable* or *expression* in the last two variants +must designate a scalar value or object convertible to string. **Semantics** -The names in this series of sections have special meaning and are -called *intrinsics*, but they are not keywords; nor are they functions, they -are language constructs that are interpreted by the Engine. +A *simple-variable* expression designates a variable with the name determined by either +the *variable-name* or the string representation of the result of the *simple-variable* or +*expression*, depending on which case is applicable. In the latter two cases the variable +name may contain characters that are not allowed in a lexical +[variable-name](09-lexical-structure.md#names). + +The behavior of a *simple-variable* in different contexts and for different types of +variables is as specified in the [variables](07-variables.md) section. + +The variable `$this` is predefined inside any non-static instance method (including +constructor) when that method is called from within an object +context. The value of `$this` is the calling object or the object being constructed. -*intrinsic-operator* can be used as part of an expression, in any place -other values or expressions could be used. +**Examples** -*intrisic-construct* can be used only as stand-alone [statement](11-statements.md#statements). +```PHP +$color = "red"; +$$color = 123; // equivalent to $red = 123 +// ----------------------------------------- +$x = 'ab'; $ab = 'fg'; $fg = 'xy'; +$$ $ $x = 'Hello'; // equivalent to $xy = Hello +// ----------------------------------------- +$v1 = 3; +$$v1 = 22; // equivalent to ${3} = 22, variable name is "3" +$v2 = 9.543; +$$v2 = TRUE; // equivalent to ${9.543} = TRUE +$v3 = NULL; +$$v3 = "abc"; // equivalent to ${NULL} = "abc", here we create a variable with empty name +// ----------------------------------------- +function f1 () { return 2.5; } +${1 + f1()} = 1000; // equivalent to ${3.5} = 1000 +``` -####array +### Dereferencable expression **Syntax** + +
-  array-intrinsic:
-    array ( array-initializeropt  )
+dereferencable-expression:
+   variable
+   (   expression   )
+   array-creation-expression
+   string-literal
+
+callable-expression:
+   callable-variable
+   (   expression   )
+   array-creation-expression
+   string-literal
 
-**Defined elsewhere** +**Constraints** -* [*array-initializer*](#array-creation-operator) +The *string-literal* must not use variable interpolation and must not be a heredoc +or nowdoc string literal. **Semantics** -This intrinsic creates and initializes an array. It is equivalent to the -array-creation operator [`[]`](#array-creation-operator). +A *dereferencable-expression* can be used as the left hand side of dereferencing operators, such +as `[]`, `->` and `::`. A *callable-expression* can be used as the left hand side of the [function +call operator](#function-call-operator). -####echo +### Variables **Syntax** -
-  echo-intrinsic:
-    echo  expression
-    echo  expression-list-two-or-more
+
 
-  expression-list-two-or-more:
-    expression  ,  expression
-    expression-list-two-or-more  ,  expression
+
+callable-variable:
+   simple-variable
+   subscript-expression
+   member-call-expression
+   scoped-call-expression
+   function-call-expression
+
+variable:
+   callable-variable
+   scoped-property-access-expression
+   member-access-expression
 
-**Defined elsewhere** +**Semantics** -* [*expression*](#general-6) +A *variable* is an expression that can *in principle* be used as an lvalue. However, the +individual possible expressions may further restrict whether they can behave as lvalues. +An expression that is not a *variable* can never act as an lvalue. -**Constraints** +### Constant Access Expression -*expression* value must be [convertable to a string](08-conversions.md#converting-to-string-type). -In particular, it should not be an array and if it is an object, it must implement -a [`__toString` method](14-classes.md#method-__tostring). + + +
+constant-access-expression:
+   qualified-name
+
**Semantics** -After converting each of its *expression*s' values to strings, if -necessary, `echo` concatenates them in order given, and writes the -resulting string to [`STDOUT`](06-constants.md#core-predefined-constants). Unlike [`print`](#print), it does -not produce a result. +A *constant-access-expression* evaluates to the value of the [constant](06-constants.md) +with name *qualified-name*. -See also: [double quioted strings](09-lexical-structure.md#double-quoted-string-literals) and -[heredoc documents](09-lexical-structure.md#heredoc-string-literals), [conversion to string](08-conversions.md#converting-to-string-type). +### Literals -**Examples** +**Syntax** -```PHP -$v1 = TRUE; -$v2 = 123; -echo '>>' . $v1 . '|' . $v2 . "<<\n"; // outputs ">>1|123<<" -echo '>>' , $v1 , '|' , $v2 , "<<\n"; // outputs ">>1|123<<" -echo ('>>' . $v1 . '|' . $v2 . "<<\n"); // outputs ">>1|123<<" -$v3 = "qqq{$v2}zzz"; -echo "$v3\n"; -``` + -####empty +
+literal:
+   integer-literal
+   floating-literal
+   string-literal
+
+ +**Semantics** + +A literal evaluates to its value, as specified in the lexical specification for +[literals](09-lexical-structure.md#literals). + +### Intrinsics + +#### General **Syntax** +
-  empty-intrinsic:
-    empty ( expression  )
+intrinsic:
+   empty-intrinsic
+   eval-intrinsic
+   exit-intrinsic
+   isset-intrinsic
 
-**Defined elsewhere** +**Semantics** + +The names in this series of sections have special meaning and are +called *intrinsics*, but they are not keywords; nor are they functions, they +are language constructs that are interpreted by the Engine. + +#### empty + +**Syntax** + + -* [*expression*](#general-6) +
+empty-intrinsic:
+   empty   (   expression   )
+
**Semantics** @@ -270,19 +378,20 @@ $v = [10, 20]; empty($v); // results in FALSE ``` -####eval +#### eval **Syntax** + +
-  eval-intrinsic:
-    eval (  expression  )
+eval-intrinsic:
+   eval   (   expression   )
 
-**Defined elsewhere** - -* [*expression*](#general-6) - **Constraints** *expression* must designate a string, or be [convertable to a string](08-conversions.md#converting-to-string-type). @@ -312,22 +421,26 @@ $str = "Hello"; eval("echo \$str . \"\\n\";"); // → echo $str . "\n"; → prints Hello ``` -####exit/die +#### exit/die **Syntax** + +
-  exit-intrinsic:
-    exit  expressionopt
-    exit  (  expressionopt  )
-    die   expressionopt
-    die   (   expressionopt )
+exit-intrinsic:
+   exit
+   exit   (   expressionopt   )
+   die
+   die   (   expressionopt   )
 
-**Defined elsewhere** - -* [*expression*](#general-6) - **Constraints** When *expression* designates an integer, its value must be in the range @@ -360,31 +473,32 @@ exit (1); exit; ``` -####isset +#### isset **Syntax** -
-  isset-intrinsic:
-    isset  (  expression-list-one-or-more  )
-
-  expression-list-one-or-more:
-    expression
-    expression-list-one-or-more  ,  expression
-
- -**Defined elsewhere** + -**Constraints** +
+isset-intrinsic:
+   isset   (   variable-list   ,opt   )
 
-Each *expression* must designate a variable.
+variable-list:
+   variable
+   variable-list   ,   variable
+
**Semantics** This intrinsic returns `TRUE` if all the variables designated by -*expression*s are set and their values are not `NULL`. Otherwise, it +*variables*s are set and their values are not `NULL`. Otherwise, it returns `FALSE`. If this intrinsic is used with an expression that designate a [dynamic @@ -405,205 +519,34 @@ $v1 = TRUE; $v2 = 12.3; $v3 = NULL; isset($v1, $v2, $v3); // results in FALSE ``` -####list - -**Syntax** - -
-  list-intrinsic:
-    list  (  list-expression-listopt  )
-
-  list-expression-list:
-    list-or-variable
-    ,
-    list-expression-list  ,  list-or-variableopt
-
-  list-or-variable:
-    list-intrinsic
-    expression
-
- -**Defined elsewhere** - -* [*expression*](#general-6) - -**Constraints** - -*list-intrinsic* must be used as the left-hand operand in a -[*simple-assignment-expression*](#simple-assignment) of which the right-hand -operand must be an expression that designates an array or object implementing -the `ArrayAccess` interface (called the *source array*). - -Each *expression* in *list-or-variable* must designate a variable (called -the *target variable*). - -At least one of the elements of the *list-expression-list* must be non-empty. - -**Semantics** - -This intrinsic assigns one or more elements of the source array to the -target variables. On success, it returns a copy of the source array. If the -source array is not an array or object implementing `ArrayAccess` no -assignments are performed and the return value is `NULL`. - -All elements in the source array having keys of type `string` are ignored. -The element having an `int` key of 0 is assigned to the first target -variable, the element having an `int` key of 1 is assigned to the second -target variable, and so on, until all target variables have been -assigned. Any other array elements are ignored. If there are -fewer source array elements having int keys than there are target -variables, the unassigned target variables are set to `NULL` and -a non-fatal error is produced. - -The assignments must occur in this order. - -Any target variable may be a list, in which case, the corresponding -element is expected to be an array. - -If the source array elements and the target variables overlap in any -way, the behavior is unspecified. - -**Examples** - -```PHP -list($min, $max, $avg) = array(0, 100, 67); - // $min is 0, $max is 100, $avg is 67 -list($min, $max, $avg) = array(2 => 67, 1 => 100, 0 => 0); - // same as example above -list($min, , $avg) = array(0, 100, 67); - // $min is 0, $avg is 67 -list($min, $max, $avg) = array(0, 2 => 100, 4 => 67); - // $min is 0, $max is NULL, $avg is 100 -list($min, list($max, $avg)) = [0, [1 => 67, 99, 0 => 100], 33]; - // $min is 0, $max is 100, $avg is 67 - -list($arr[1], $arr[0]) = [0, 1]; - // $arr is [1 => 0, 0 => 1], in this order -list($arr2[], $arr2[]) = [0, 1]; - // $arr2 is [0, 1] -``` - -####print - -**Syntax** - -
-  print-intrinsic:
-    print  expression
-    print  (  expression  )
-
- -**Defined elsewhere** - -* [*expression*](#general-6) - -**Constraints** - -*expression* value must be [convertable to a string](08-conversions.md#converting-to-string-type). -In particular, it should not be an array and if it is an object, it must implement -a [`__toString` method](14-classes.md#method-__tostring). - -**Semantics** - -After converting its *expression*'s value to a string, if necessary, -`print` writes the resulting string to [`STDOUT`](06-constants.md#core-predefined-constants). -Unlike [`echo`](#echo), `print` can be used in any context allowing an expression. It -always returns the value 1. - -See also: [double quioted strings](09-lexical-structure.md#double-quoted-string-literals) and -[heredoc documents](09-lexical-structure.md#heredoc-string-literals), [conversion to string](08-conversions.md#converting-to-string-type). - -**Examples** - -```PHP -$v1 = TRUE; -$v2 = 123; -print '>>' . $v1 . '|' . $v2 . "<<\n"; // outputs ">>1|123<<" -print ('>>' . $v1 . '|' . $v2 . "<<\n"); // outputs ">>1|123<<" -$v3 = "qqq{$v2}zzz"; -print "$v3\n"; // outputs "qqq123zzz" -$a > $b ? print "..." : print "..."; -``` - -####unset +### Anonymous Function Creation **Syntax** -
-  unset-intrinsic:
-    unset  (  expression-list-one-or-more  )
-
- -**Defined elsewhere** - -* [*expression-list-one-or-more*](#isset) - -**Constraints** - -Each *expression* must designate a variable. - -**Semantics** - -This intrinsic [unsets](07-variables.md#general) the variables designated by each -*expression* in *expression-list-one-or-more*. No value is returned. An -attempt to unset a non-existent variable (such as a non-existent element -in an array) is ignored. - -When called from inside a function, this intrinsic behaves, as follows: - -- For a variable declared `global` in that function, `unset` removes the - alias to that variable from the scope of the current call to that - function. The global variable remains set. - (To unset the global variable, use unset on the corresponding - [`$GLOBALS`](07-variables.md#predefined-variables) array entry. -- For a variable passed byRef to that function, `unset` removes the - alias to that variable from the scope of the current call to that - function. Once the function returns, the passed-in argument variable - is still set. -- For a variable declared static in that function, `unset` removes the - alias to that variable from the scope of the current call to that - function. In subsequent calls to that function, the static variable - is still set and retains its value from call to call. - -Any visible instance property may be unset, in which case, the property -is removed from that instance. - -If this intrinsic is used with an expression that designates a [dynamic -property](14-classes.md#dynamic-members), then if the class of that property has an [`__unset` -method](14-classes.md#method-__unset), that method is called. - -**Examples** - -```PHP -unset($v); -unset($v1, $v2, $v3); -unset($x->m); // if m is a dynamic property, $x->__unset("m") is called -``` +
-  anonymous-function-creation-expression:
-  staticopt function  &opt (  parameter-declaration-listopt  ) return-typeopt anonymous-function-use-clauseopt
-      compound-statement
+anonymous-function-creation-expression:
+   staticopt   function   &opt   (   parameter-declaration-listopt   )   anonymous-function-use-clauseopt   return-typeopt   compound-statement
 
-  anonymous-function-use-clause:
-    use  (  use-variable-name-list  )
+anonymous-function-use-clause:
+   use   (   use-variable-name-list   )
 
-  use-variable-name-list:
-    &opt   variable-name
-    use-variable-name-list  ,  &opt  variable-name
+use-variable-name-list:
+   &opt   variable-name
+   use-variable-name-list   ,   &opt   variable-name
 
-**Defined elsewhere** - -* [*parameter-declaration-list*](13-functions.md#function-definitions) -* [*return-type*](13-functions.md#function-definitions) -* [*compound-statement*](11-statements.md#compound-statements) -* [*variable-name*](09-lexical-structure.md#names) - **Semantics** This operator returns an object of type [`Closure`](14-classes.md#class-closure), or a derived @@ -647,7 +590,7 @@ class C public function compute(array $values) { $count = 0; - $callback1 = function () use (&$count) // has C as its scope + $callback1 = function () use (&$count) // has C as its scope { ++$count; //... @@ -663,178 +606,106 @@ class C } ``` -##Postfix Operators - -###General +### The `new` Operator **Syntax** + +
-  postfix-expression:
-    primary-expression
-    clone-expression
-    object-creation-expression
-    array-creation-expression
-    subscript-expression
-    function-call-expression
-    member-selection-expression
-    postfix-increment-expression
-    postfix-decrement-expression
-    scope-resolution-expression
-    exponentiation-expression
+object-creation-expression:
+   new   class-type-designator   (   argument-expression-listopt   )
+   new   class-type-designator   (   argument-expression-list   ,opt   )
+   new   class-type-designator
+   new   class   (   argument-expression-listopt   )   class-base-clauseopt   class-interface-clauseopt   {   class-member-declarationsopt   }
+   new   class   class-base-clauseopt   class-interface-clauseopt   {   class-member-declarationsopt   }
+
+class-type-designator:
+   qualified-name
+   new-variable
+
+new-variable:
+   simple-variable
+   new-variable   [   expressionopt   ]
+   new-variable   {   expression   }
+   new-variable   ->   member-name
+   qualified-name   ::   simple-variable
+   relative-scope   ::   simple-variable
+   new-variable   ::   simple-variable
 
-**Defined elsewhere** +**Constraints** -* [*primary-expression*](#general-1) -* [*clone-expression*](#the-clone-operator) -* [*object-creation-expression*](#the-new-operator) -* [*array-creation-expression*](#array-creation-operator) -* [*subscript-expression*](#subscript-operator) -* [*function-call-expression*](#function-call-operator) -* [*member-selection-expression*](#member-selection-operator) -* [*postfix-increment-expression*](#postfix-increment-and-decrement-operators) -* [*postfix-decrement-expression*](#postfix-increment-and-decrement-operators) -* [*scope-resolution-expression*](#scope-resolution-operator) -* [*exponentiation-expression*](#exponentiation-operator) +*qualified-name* must name a class. -**Semantics** +*new-variable* must be a value of type `string` that contains the name of a class, or an object. -These operators associate left-to-right. +*class-type-designator* must not designate an [abstract class](14-classes.md#general). -###The `clone` Operator +The number of arguments in *argument-expression-list* must be at least +as many as the number of non-optional parameters defined for the class's [constructor](14-classes.md#constructors). -**Syntax** +**Semantics** -
-  clone-expression:
-    clone  expression
-
+The `new` *class-type-designator* forms create an object of the class type specified by *class-type-designator*. The `new class` forms create an object of an *anonymous class type*, a type that has an unspecified name. In all other respects, however, an anonymous class has the same capabilities as a named class type. + +If the *class-type-designator* is a *new-variable* resulting in a string value, +that string is used as the class name. If the expression results in an object, +the class of the object is used as the class for the new object. The *new-variable* +has the same semantics as a *variable*, but the grammar is restricted to exclude +calls. -**Defined elsewhere** +The *qualified-name* is resolved according to the rules described in +[scope resolution operator](#scope-resolution-operator), including +support for `self`, `parent` and `static`. -* [*expression*](#general-6) +After the object has been created, each instance property is initialized +with the values [specified in property definition](14-classes.md#properties), +or the value `NULL` if no initializer value is provided. -**Constraints** +The object is then initialized by calling the class's [constructor](14-classes.md#constructors) +passing it the optional *argument-expression-list*. If the class has no +constructor, the constructor that class inherits (if any) is used. The class +can also specify no constructor definition, in this case the constructor call is omitted. -*expression* must designate an object. +The result of a named-type *object-creation-expression* is an object of the type specified by *class-type-designator*. The result of an anonymous class *object-creation-expression* is an object of unspecified type. However, this type will subtype all types +provided by *class-base-clause* and *class-interface-clause* and the *class-members* definition should follow the same inheritance and implementation rules as the regular [class declaration](14-classes.md#class-declarations) does. -**Semantics** +Each distinct source code expression of the form `new class` results in the class type that is different from that of all other anonymous class types. However, multiple evaluations of the same source code expression of the form `new class` result in instances of the same class type. -The `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`](14-classes.md#method-__clone), it is called to perform a deep copy. -The result is the new object. +Because a constructor call is a function call, the relevant parts of +[function call operator](#function-call-operator) section also apply. **Examples** -Consider a class `Employee`, from which is derived a class `Manager`. Let us -assume that both classes contain properties that are objects. `clone` is -used to make a copy of a `Manager` object, and behind the scenes, the -`Manager` object uses clone to copy the properties for the base class, -`Employee`. - ```PHP -class Employee +class Point { - //... - public function __clone() + public function __construct($x = 0, $y = 0) { - // make a deep copy of Employee object + ... } -} -class Manager extends Employee -{ - //... - public function __clone() - { - $v = parent::__clone(); - // make a deep copy of Manager object - - } -} -$obj1 = new Manager("Smith", 23); -$obj2 = clone $obj1; // creates a new Manager that is a deep copy -``` - -###The `new` Operator - -**Syntax** - -
-  object-creation-expression:
-    new  class-type-designator  (  argument-expression-listopt  )
-    new  class-type-designator
-    new  class  (  argument-expression-listopt  )
-        class-base-clauseopt   class-interface-clauseopt
-        {   opt   }
-    new  class class-base-clauseopt  class-interface-clauseopt
-        {   class-member-declarationsopt   }
-
-  class-type-designator:
-    qualified-name
-    expression
-
- -**Defined elsewhere** - -* [*argument-expression-list*](#function-call-operator) -* [*class-base-clause*](14-classes.md#class-declarations) -* [*class-interface-clause*](14-classes.md#class-declarations) -* [*class-member-declarations*](14-classes.md#class-members) -* [*expression*](#general-6) -* [*qualified-name*](09-lexical-structure.md#names) - -**Constraints** - -*qualified-name* must name a class. - -*expression* must be a value of type `string` (but not be a string -literal) that contains the name of a class, or an object. - -*class-type-designator* must not designate an [abstract class](14-classes.md#general). - -The number of arguments in *argument-expression-list* must be at least -as many as the number of non-optional parameters defined for the class's [constructor](14-classes.md#constructors). - -**Semantics** - -The `new` *class-type-designator* forms create an object of the class type specified by *class-type-designator*. The `new class` forms create an object of an *anonymous class type*, a type that has an unspecified name. In all other respects, however, an anonymous class has the same capabilities as a named class type. - -If the *class-type-designator* is an expression resulting in a string value, -that string is used as the class name. If the expression results in an object, -the class of the object is used as the class for the new object. - -The *qualified-name* is resolved according to the rules described in -[scope resolution operator](#scope-resolution-operator), including -support for `self`, `parent` and `static`. - -After the object has been created, each instance property is initialized -with the values [specified in property definition](14-classes.md#properties), -or the value `NULL` if no initializer value is provided. - -The object is then initialized by calling the class's [constructor](14-classes.md#constructors) -passing it the optional *argument-expression-list*. If the class has no -constructor, the constructor that class inherits (if any) is used. The class -can also specify no constructor definition, in this case the constructor call is omitted. - -The result of a named-type *object-creation-expression* is an object of the type specified by *class-type-designator*. The result of an anonymous class *object-creation-expression* is an object of unspecified type. However, this type will subtype all types -provided by *class-base-clause* and *class-interface-clause* and the *class-members* definition should follow the same inheritance and implementation rules as the regular [class declaration](14-classes.md#class-declarations) does. - -Each distinct source code expression of the form `new class` results in the class type that is different from that of all other anonymous class types. However, multiple evaluations of the same source code expression of the form `new class` result in instances of the same class type. - -Because a constructor call is a function call, the relevant parts of -[function call operator](#function-call-operator) section also apply. - -**Examples** - -```PHP -class Point -{ - public function __construct($x = 0, $y = 0) - { - ... - } - ... + ... } $p1 = new Point; // create Point(0, 0) $p1 = new Point(12); // create Point(12, 0) @@ -848,40 +719,55 @@ $v2 = new class (100) extends C1 implements I1, I2 { }; ``` -###Array Creation Operator - -An array is created and initialized by one of two equivalent ways: via -the array-creation operator `[]`, as described below, or the intrinsic -[`array`](#array). +### Array Creation Operator **Syntax** -
-  array-creation-expression:
-    array  (  array-initializeropt  )
-    [ array-initializeropt ]
+
+
+
+array-creation-expression:
+   array   (   array-initializeropt   )
+   [   array-initializeropt   ]
+
+array-initializer:
+   array-initializer-list   ,opt
+
+array-initializer-list:
+   array-element-initializer
+   array-element-initializer   ,   array-initializer-list
 
-**Defined elsewhere**
+array-element-initializer:
+   &opt   element-value
+   element-key   =>   &opt   element-value
 
-* [*expression*](#general-6)
+element-key:
+   expression
+
+element-value:
+   expression
+
**Constraints** @@ -946,29 +832,30 @@ foreach($v as $e) { /* ... */ } // iterates over keys 2, 0, 1, -1 for ($i = -1; $i <= 2; ++$i) { echo $v[$i]; } // retrieves via keys -1, 0, 1, 2 ``` -###Subscript Operator +### Subscript Operator **Syntax** + +
-  subscript-expression:
-    postfix-expression  [  expressionopt  ]
-    postfix-expression  {  expression  }   [Deprecated form]
+subscript-expression:
+   dereferencable-expression   [   expressionopt   ]
+   dereferencable-expression   {   expression   }   <b>[Deprecated form]</b>
 
-**Defined elsewhere** - -* [*postfix-expression*](#general-3) -* [*expression*](#general-6) - **Constraints** -If *postfix-expression* designates a string, *expression* must not +If *dereferencable-expression* designates a string, *expression* must not designate a string. *expression* can be omitted only if *subscript-expression* is used in a -modifiable-lvalue context and *postfix-expression* does not designate a string. -Exception from this is when *postfix-expression* is an empty string - then it is +modifiable-lvalue context and *dereferencable-expression* does not designate a string. +Exception from this is when *dereferencable-expression* is an empty string - then it is converted to an empty array. If *subscript-expression* is used in a non-lvalue context, the element @@ -987,23 +874,22 @@ or `bool` values, or strings whose contents match exactly the pattern of [*decimal-literal*](09-lexical-structure.md#integer-literals), are [converted to integer](08-conversions.md#converting-to-integer-type), and key values of all other types are [converted to string](08-conversions.md#converting-to-string-type). -If both *postfix-expression* and *expression* designate strings, +If both *dereferencable-expression* and *expression* designate strings, *expression* is treated as if it specified the `int` key zero instead and a non-fatal error is produces. A *subscript-expression* designates a modifiable lvalue if and only if -*postfix-expression* designates a modifiable lvalue. +*dereferencable-expression* designates a modifiable lvalue. -**postfix-expression designates an array** +**dereferencable-expression designates an array** If *expression* is present, if the designated element exists, the type and value of the result is the type and value of that element; otherwise, the result is `NULL`. If *expression* is omitted, a new element is inserted. Its key has type -`int` and is one more than the highest, previously assigned, non-negative -`int` key for this array. If this is the first element with a non-negative -`int` key, key `0` is used. +`int` and is one more than the highest, previously assigned `int` key for +this array. If this is the first element with an `int` key, key `0` is used. If the largest previously assigned `int` key is the largest integer value that can be represented, the new element is not added. The result is the added new element, or `NULL` if the element was not added. @@ -1019,24 +905,25 @@ The result is the added new element, or `NULL` if the element was not added. [postfix- or prefix-increment or decrement operator](#postfix-increment-and-decrement-operators), the value of the new element is considered to be `NULL`. -**postfix-expression designates a string** +**dereferencable-expression designates a string** The *expression* is converted to `int` and the result is the character of the -string at the position equal to that integer. If the integer is negative or refers +string at the position corresponding to that integer. If the integer is negative, +the position is counted backwards from the end of the string. If the position refers to a non-existing offset, the result is an empty string. If the operator is used as the left-hand side of a [*simple-assignment-expression*](#simple-assignment), -the value being assigned is converted to string and the character in the specified offset will be -replaced by the first character of the string. If the assigned string is empty, the `'\0'` character is used. -If the string before the assignment had no such offset, the string is extended to include the offset -with `'\0'` characters. + +- If the assigned string is empty, or in case of non-existing negative offset (absolute value larger than string length), a warning is raised and no assignment is performed. +- If the offset is larger than the current string length, the string is extended to a length equal to the offset value, using space (0x20) padding characters. +- The value being assigned is converted to string and the character in the specified offset is replaced by the first character of the string. The subscript operator can not be used on a string value in a byRef context or as the operand of the [postfix- or prefix-increment or decrement operators](#postfix-increment-and-decrement-operators) or on the left side of [*compound-assignment-expression*](#compound-assignment), doing so will result in a fatal error. -**postfix-expression designates an object of a type that implements `ArrayAccess`** +**dereferencable-expression designates an object of a type that implements `ArrayAccess`** If *expression* is present, @@ -1099,6 +986,7 @@ $v["red"] = TRUE; // insert a new element with string key "red" function f() { return [1000, 2000, 3000]; } f()[2]; // designates element with value 3000 "red"[1.9]; // designates "e" +"red"[-2]; // designates "e" "red"[0][0][0]; // designates "r" // ----------------------------------------- class MyVector implements ArrayAccess { /* ... */ } @@ -1108,39 +996,54 @@ $vect1[] = "xxx"; // calls Vector::offsetSet(NULL, "xxx") $x = $vect1[1]; // calls Vector::offsetGet(1) ``` -###Function Call Operator +### Function Call Operator **Syntax** -
-  function-call-expression:
-    qualified-name  (  argument-expression-listopt  )
-    postfix-expression  (  argument-expression-listopt  )
+
 
+
+function-call-expression:
+   qualified-name   (   argument-expression-listopt   )
+   qualified-name   (   argument-expression-list   ,   )
+   callable-expression   (   argument-expression-listopt   )
+   callable-expression   (   argument-expression-list   ,   )
+
+argument-expression-list:
+   argument-expression
+   argument-expression-list   ,   argument-expression
+
+argument-expression:
+   variadic-unpacking
+   expression
+
+variadic-unpacking:
+   ...   expression
 
-**Defined elsewhere** - -* [*postfix-expression*](#general-3) -* [*assignment-expression*](#general-5) - **Constraints** -*postfix-expression* must designate a function, either by being its -*name*, by being a value of type string (but not a string literal) that -contains the function's name, or by being an object of a type that implements -[`__invoke`](14-classes.md#method-__invoke) method (including [`Closure`](14-classes.md#class-closure) objects). +*callable-expression* must designate a function, by being a value of type string +that contains the function's name, or by being an object of a type that implements +[`__invoke`](14-classes.md#method-__invoke) method (including +[`Closure`](14-classes.md#class-closure) objects). The number of arguments present in a function call must be at least as many as the number of non-optional parameters defined for that function. @@ -1160,18 +1063,12 @@ An expression of the form *function-call-expression* is a *function call*. The expression designates the *called function*, and *argument-expression-list* specifies the arguments to be passed to that function. An argument can be any value. In a function call, -*postfix-expression* is evaluated first, followed by each -*assignment-expression* in the order left-to-right. There is +*callable-expression* is evaluated first, followed by each +*expression* in the order left-to-right. There is a [sequence point](#general) after each argument is evaluated and right before the function is called. For details of the result of a function call see [`return` statement](11-statements.md#the-return-statement). The value of a function call is a modifiable lvalue only if the function returns a modifiable value byRef. -When *postfix-expression* designates an instance method or constructor, -the instance used in that designation is used as the value of `$this` in -the invoked method or constructor. However, if no instance was used in -that designation (for example, in the call `C::instance_method()`) the -invoked instance has no `$this` defined. - When a function is called, the value of each argument passed to it is assigned to the corresponding parameter in that function's definition, if such a parameter exists. The assignment of argument values to @@ -1193,7 +1090,7 @@ defined, with an initial value of `NULL`. Direct and indirect recursive function calls are permitted. -If *postfix-expression* is a string, this is +If *callable-expression* is a string, this is a [variable function call](13-functions.md#variable-functions). If *variadic-unpacking* operation is used, the operand is considered to be a parameter list. @@ -1238,32 +1135,34 @@ $anon = function () { ... }; // store a Closure in $anon $anon(); // call the anonymous function encapsulated by that object ``` -###Member-Selection Operator +### Member Access Operator **Syntax** -
-  member-selection-expression:
-    postfix-expression  ->  member-selection-designator
+
 
-**Defined elsewhere**
+
+member-access-expression:
+   dereferencable-expression   ->   member-name
 
-* [*postfix-expression*](#general-3)
-* [*name*](09-lexical-structure.md#names)
-* [*expression*](#general-6)
+member-name:
+   name
+   simple-variable
+   {   expression   }
+
**Constraints** -*postfix-expression* must designate an object or be `NULL`, `FALSE`, or an -empty string. - -*name* must designate an instance property, or an instance or static -method of *postfix-expression*'s class type. +The *dereferencable-expression* must designate an object or be `NULL`, `FALSE`, +or an empty string. *expression* must be a value of type `string` (but not a string literal) that contains the name of an instance property (**without** the @@ -1272,25 +1171,24 @@ type. **Semantics** -A *member-selection-expression* designates an instance property or an -instance or static method of the object designated by -*postfix-expression*. For a property, the value is that of the property, -and is a modifiable lvalue if *postfix-expression* is a modifiable -lvalue. +A *member-access-expression* designates an instance property of the object +designated by *dereferencable-expression* with the name given by the string +representation of *member-name*. The value is that of the property, and is a +modifiable lvalue if *dereferencable-expression* is a modifiable lvalue. -When the `->` operator is used in a modifiable lvalue context and *name* -or *expression* designate a property that is not visible, the property -is treated as a [dynamic property](14-classes.md#dynamic-members). If *postfix-expression*'s class +When the `->` operator is used in a modifiable lvalue context and *member-name* +designate a property that is not visible, the property is treated as a +[dynamic property](14-classes.md#dynamic-members). If *dereferencable-expression*'s class type defines a [`__set` method](14-classes.md#method-__set), it is called to store the property's value. When the `->` operator is used in a non-lvalue context -and *name* or *expression* designate a property that is not visible, the -property is treated as a dynamic property. If *postfix-expression*'s -class type defines a [`__get` method](14-classes.md#method-__get), it is called to retrieve -the property's value. - -If *postfix-expression* is `NULL`, `FALSE`, or an empty string, an expression -of the form `$p->x = 10` causes an instance of [`stdClass`](14-classes.md#class-stdclass) to be -created with a dynamic property x having a value of 10. `$p` is then made +and *member-name* designate a property that is not visible, the property +is treated as a dynamic property. If *dereferencable-expression*'s +class type defines a [`__get` method](14-classes.md#method-__get), +it is called to retrieve the property's value. + +If *dereferencable-expression* is `NULL`, `FALSE`, or an empty string, an expression +of the form `$p->x = 10` causes an instance of [`stdClass`](14-classes.md#class-stdclass) +to be created with a dynamic property `x` having a value of 10. `$p` is then made to refer to this instance. **Examples** @@ -1308,9 +1206,10 @@ class Point public function __toString() { return '(' . $this->x . ',' . $this->y . ')'; - } // get private properties $x and $y - public function __set($name, $value) { ... } - public function __get($name) { ... } + } + // get private properties $x and $y + public function __set($name, $value) { ... } + public function __get($name) { ... } } $p1 = new Point; $p1->move(3, 9); // calls public instance method move by name @@ -1320,21 +1219,67 @@ $p1->color = "red"; // turned into $p1->__set("color", "red"); $c = $p1->color; // turned into $c = $p1->__get("color"); ``` -###Postfix Increment and Decrement Operators +### Member Call Operator **Syntax** -
-  postfix-increment-expression:
-    unary-expression  ++
+
 
-  postfix-decrement-expression:
-    unary-expression  --
+
+member-call-expression:
+   dereferencable-expression   ->   member-name   (   argument-expression-listopt   )
+   dereferencable-expression   ->   member-name   (   argument-expression-list   ,   )
 
-**Defined elsewhere** +**Constraints** + +The *dereferencable-expression* must designate an object. + +Additionally the general [function call constraints](#function-call-operator) +apply. + +**Semantics** + +A *member-call-expression* calls an instance or static method of the +object designated by *dereferencable-expression*, with the method +name given by the string representation of *member-name* and the +arguments given by *argument-expression-list*. The value of +*dereferencable-expression* is used as the value of `$this` in the +invoked method. + +The general [function call semantics](#function-call-operator) apply. + +If the called method does not exist or is not visible from the current +scope an exception is thrown, unless a [`__call` method](14-classes.md#method-__call) +exists, in which case it will be called instead. + +**Examples** + +See [member access examples](#member-access-operator). + +### Postfix Increment and Decrement Operators + +**Syntax** + + + +
+postfix-increment-expression:
+   variable   ++
+
+postfix-decrement-expression:
+   variable   --
+
**Constraints** @@ -1354,36 +1299,212 @@ $i = 10; $j = $i-- + 100; // old value of $i (10) is added to 100 $a = array(100, 200); $v = $a[1]++; // old value of $ia[1] (200) is assigned ``` -###Scope-Resolution Operator +### Prefix Increment and Decrement Operators + +**Syntax** + + + +
+prefix-increment-expression:
+   ++   variable
+
+prefix-decrement-expression:
+   --   variable
+
+ +**Constraints** + +The operand of the prefix `++` or `--` operator must be a modifiable lvalue +that has scalar-compatible type. + +**Semantics** + +*Arithmetic Operands* + +For a prefix `++` operator used with an arithmetic operand, the [side +effect](#general) of the operator is to increment the value of the operand by 1. +The result is the value of the operand after it +has been incremented. If an `int` operand's value is the largest +representable for that type, the operand is incremented as if it were `float`. + +For a prefix `--` operator used with an arithmetic operand, the side +effect of the operator is to decrement the value of the operand by 1. +The result is the value of the operand after it has been +decremented. If an `int` operand's value is the smallest representable for +that type, the operand is decremented as if it were `float`. + +For a prefix `++` or `--` operator used with an operand having the value +`INF`, `-INF`, or `NAN`, there is no side effect, and the result is the +operand's value. + +*Boolean Operands* + +For a prefix `++` or `--` operator used with a Boolean-valued operand, there +is no side effect, and the result is the operand's value. + +*NULL-valued Operands* + +For a prefix -- operator used with a `NULL`-valued operand, there is no +side effect, and the result is the operand's value. For a prefix `++` +operator used with a `NULL`-valued operand, the side effect is that the +operand's type is changed to int, the operand's value is set to zero, +and that value is incremented by 1. The result is the value of the +operand after it has been incremented. + +*String Operands* + +For a prefix `--` operator used with an operand whose value is an empty +string, the side effect is that the operand's type is changed to `int`, +the operand's value is set to zero, and that value is decremented by 1. +The result is the value of the operand after it has been incremented. + +For a prefix `++` operator used with an operand whose value is an empty +string, the side effect is that the operand's value is changed to the +string "1". The type of the operand is unchanged. The result is the new +value of the operand. + +For a prefix `--` or `++` operator used with a numeric string, the numeric +string is treated as the corresponding `int` or `float` value. + +For a prefix `--` operator used with a non-numeric string-valued operand, +there is no side effect, and the result is the operand's value. + +For a non-numeric string-valued operand that contains only alphanumeric +characters, for a prefix `++` operator, the operand is considered to be a +representation of a base-36 number (i.e., with digits 0–9 followed by A–Z or a–z) in +which letter case is ignored for value purposes. The right-most digit is +incremented by 1. For the digits 0–8, that means going to 1–9. For the +letters "A"–"Y" (or "a"–"y"), that means going to "B"–"Z" (or "b"–"z"). +For the digit 9, the digit becomes 0, and the carry is added to the next +left-most digit, and so on. For the digit "Z" (or "z"), the resulting +string has an extra digit "A" (or "a") appended. For example, when +incrementing, "a" -> "b", "Z" -> "AA", "AA" -> "AB", "F29" -> "F30", "FZ9" -> "GA0", and "ZZ9" -> "AAA0". A digit position containing a number wraps +modulo-10, while a digit position containing a letter wraps modulo-26. + +For a non-numeric string-valued operand that contains any +non-alphanumeric characters, for a prefix `++` operator, all characters up +to and including the right-most non-alphanumeric character is passed +through to the resulting string, unchanged. Characters to the right of +that right-most non-alphanumeric character are treated like a +non-numeric string-valued operand that contains only alphanumeric +characters, except that the resulting string will not be extended. +Instead, a digit position containing a number wraps modulo-10, while a +digit position containing a letter wraps modulo-26. + +*Object Operands* + +If the operand has an object type supporting the operation, +then the object semantics defines the result. Otherwise, the operation has +no effect and the result is the operand. + +**Examples** + +```PHP +$i = 10; $j = --$i + 100; // new value of $i (9) is added to 100 +$a = array(100, 200); $v = ++$a[1]; // new value of $a[1] (201) is assigned +$a = "^^Z"; ++$a; // $a is now "^^A" +$a = "^^Z^^"; ++$a; // $a is now "^^Z^^" +``` + +### Shell Command Operator **Syntax** + +
-  scope-resolution-expression:
-    scope-resolution-qualifier  ::  member-selection-designator
-    scope-resolution-qualifier  ::  class
-
-  scope-resolution-qualifier:
-    relative-scope
-    qualified-name
-    expression
-
-  relative-scope:
-    self
-    parent
-    static
+shell-command-expression:
+   `   dq-char-sequenceopt   `
 
-**Defined elsewhere** +where \` is the GRAVE ACCENT character 0x60, commonly referred to as a +*backtick*. -* [*member-selection-designator*](#member-selection-operator) +**Semantics** + +This operator passes *dq-char-sequence* to the command shell for +execution, as though it was being passed to the library function +[`shell_exec`](http://www.php.net/shell_exec). If the output from execution of that command is +written to [`STDOUT`](06-constants.md#core-predefined-constants), that output is the result of this operator +as a string. If the output is redirected away from `STDOUT`, or +*dq-char-sequence* is empty or contains only white space, the result of +the operator is `NULL`. + +If [`shell_exec`](http://php.net/manual/function.shell-exec.php) is disabled, this operator is disabled. + +**Examples** + +```PHP +$result = `ls`; // result is the output of command ls +$result = `ls >dirlist.txt`; // result is NULL +$d = "dir"; $f = "*.*"; +$result = `$d {$f}`; // result is the output of command dir *.* +``` + +### Scope-Resolution Operator + +**Syntax** + + + +
+scoped-property-access-expression:
+   scope-resolution-qualifier   ::   simple-variable
+
+scoped-call-expression:
+   scope-resolution-qualifier   ::   member-name   (   argument-expression-listopt   )
+   scope-resolution-qualifier   ::   member-name   (   argument-expression-list   ,   )
+
+class-constant-access-expression:
+   scope-resolution-qualifier   ::   name
+
+scope-resolution-qualifier:
+   relative-scope
+   qualified-name
+   dereferencable-expression
+
+relative-scope:
+   self
+   parent
+   static
+
**Constraints** *qualified-name* must be the name of a class or interface type. -*expression* must be a value of type string (but not a string literal) -that contains the name of a class or interface type. +*dereferencable-expression* must be a value of type string, which contains the name +of a class or interface type, or an object. **Semantics** @@ -1391,23 +1512,24 @@ From inside or outside a class or interface, operator `::` allows the selection of a constant. From inside or outside a class, this operator allows the selection of a static property, static method, or instance method. From within a class, it also allows the selection of an -overridden property or method. For a property, the value is that of the -property, and is a modifiable lvalue if *member-selection-designator* is -a modifiable lvalue. +overridden property or method. + +If the *scoped-property-access-expression* form is used, this operator +is accessing a static property given by *simple-variable* and can be +used as an lvalue. -If *member-selection-designator* is a [*name*](09-lexical-structure.md#names), this operator is accessing -a class constant. This form can not be used as an lvalue. +If the *class-constant-access-expression* form is used, this operator is +is accessing a class constant given by *name*. This form can not be used +as an lvalue. -If the operator is used as a *postfix-expression* for *function-call-expression* -then the operator is accessing the method - which, outside of the object context, +If the *scoped-call-expression* form is used, the operator is calling the +method given by *member-anem*, which, outside of the object context, is treated as static method call. Inside of the object context when `$this` is defined and the called method is not `static` and -the called class is the same of a parent of the class of `$this`, then the method is +the called class is the same as a parent of the class of `$this`, then the method call is non-static with the same `$this`. Otherwise it is a static method call. -Otherwise, the operator is accessing a static property. - *relative-scope* designates the class with relation to the current class scope. From within a class, `self` refers to the same class, `parent` refers to the class the current class extends from. From within a method, `static` refers @@ -1471,198 +1593,151 @@ class Point } ``` -###Exponentiation Operator +## The `clone` Operator **Syntax** -
-  exponentiation-expression:
-    expression  **  expression
-
- -**Defined elsewhere** - -* [*expression*](#general-6) - -**Semantics** - -The `**` operator produces the result of raising the value of the -left-hand operand to the power of the right-hand one. - -If either of the operands have an object type supporting `**` operation, -then the object semantics defines the result. The left operand is checked first. - -If either or both operands have non-numeric types, their values are converted to type `int` -or `float`, as appropriate. If both operands have non-negative integer -values and the result can be represented as an `int`, the result has type -`int`; otherwise, the result has type `float`. - -**Examples** - -```PHP -2**3; // int with value 8 -2**3.0; // float with value 8.0 -"2.0"**"3"; // float with value 8.0 -``` - -##Unary Operators - -###General - -**Syntax** - -
-  unary-expression:
-    postfix-expression
-    prefix-increment-expression
-    prefix-decrement-expression
-    unary-op-expression
-    error-control-expression
-    shell-command-expression
-    cast-expression
-    variable-name-creation-expression
-
- -**Defined elsewhere** - -* [*postfix-expression*](#general-3) -* [*prefix-increment-expression*](#prefix-increment-and-decrement-operators) -* [*prefix-decrement-expression*](#prefix-increment-and-decrement-operators) -* [*unary-op-expression*](#unary-arithmetic-operators) -* [*error-control-expression*](#error-control-operator) -* [*shell-command-expression*](#shell-command-operator) -* [*cast-expression*](#cast-operator) -* [*variable-name-creation-expression*](#variable-name-creation-operator) - -**Semantics** - -These operators associate right-to-left. - -###Prefix Increment and Decrement Operators - -**Syntax** +
-  prefix-increment-expression:
-    ++ unary-expression
-
-  prefix-decrement-expression:
-    -- unary-expression
+clone-expression:
+   primary-expression
+   clone   primary-expression
 
-**Defined elsewhere** - -* [*unary-expression*](#general-4) - **Constraints** -The operand of the prefix `++` or `--` operator must be a modifiable lvalue -that has scalar-compatible type. +*primary-expression* must designate an object. **Semantics** -*Arithmetic Operands* - -For a prefix `++` operator used with an arithmetic operand, the [side -effect](#general) of the operator is to increment the value of the operand by 1. -The result is the value of the operand after it -has been incremented. If an `int` operand's value is the largest -representable for that type, the operand is incremented as if it were `float`. - -For a prefix `--` operator used with an arithmetic operand, the side -effect of the operator is to decrement the value of the operand by 1. -The result is the value of the operand after it has been -decremented. If an `int` operand's value is the smallest representable for -that type, the operand is decremented as if it were `float`. - -For a prefix `++` or `--` operator used with an operand having the value -`INF`, `-INF`, or `NAN`, there is no side effect, and the result is the -operand's value. - -*Boolean Operands* +The `clone` operator creates a new object that is a shallow copy of the object designated +by *primary-expression*. +Then, if the class type of *primary-expression* has a method called +[`__clone`](14-classes.md#method-__clone), it is called to perform a deep copy. +The result is the new object. -For a prefix `++` or `--` operator used with a Boolean-valued operand, there -is no side effect, and the result is the operand's value. +**Examples** -*NULL-valued Operands* +Consider a class `Employee`, from which is derived a class `Manager`. Let us +assume that both classes contain properties that are objects. `clone` is +used to make a copy of a `Manager` object, and behind the scenes, the +`Manager` object uses clone to copy the properties for the base class, +`Employee`. -For a prefix -- operator used with a `NULL`-valued operand, there is no -side effect, and the result is the operand's value. For a prefix `++` -operator used with a `NULL`-valued operand, the side effect is that the -operand's type is changed to int, the operand's value is set to zero, -and that value is incremented by 1. The result is the value of the -operand after it has been incremented. +```PHP +class Employee +{ + //... + public function __clone() + { + // make a deep copy of Employee object + } +} +class Manager extends Employee +{ + //... + public function __clone() + { + $v = parent::__clone(); + // make a deep copy of Manager object -*String Operands* + } +} +$obj1 = new Manager("Smith", 23); +$obj2 = clone $obj1; // creates a new Manager that is a deep copy +``` -For a prefix `--` operator used with an operand whose value is an empty -string, the side effect is that the operand's type is changed to `int`, -the operand's value is set to zero, and that value is decremented by 1. -The result is the value of the operand after it has been incremented. -For a prefix `++` operator used with an operand whose value is an empty -string, the side effect is that the operand's value is changed to the -string "1". The type of the operand is unchanged. The result is the new -value of the operand. +## Exponentiation Operator -For a prefix `--` or `++` operator used with a numeric string, the numeric -string is treated as the corresponding `int` or `float` value. +**Syntax** -For a prefix `--` operator used with a non-numeric string-valued operand, -there is no side effect, and the result is the operand's value. + -For a non-numeric string-valued operand that contains only alphanumeric -characters, for a prefix `++` operator, the operand is considered to be a -representation of a base-36 number (i.e., with digits 0–9 followed by A–Z or a–z) in -which letter case is ignored for value purposes. The right-most digit is -incremented by 1. For the digits 0–8, that means going to 1–9. For the -letters "A"–"Y" (or "a"–"y"), that means going to "B"–"Z" (or "b"–"z"). -For the digit 9, the digit becomes 0, and the carry is added to the next -left-most digit, and so on. For the digit "Z" (or "z"), the resulting -string has an extra digit "A" (or "a") appended. For example, when -incrementing, "a" -> "b", "Z" -> "AA", "AA" -> "AB", "F29" -> "F30", "FZ9" -> "GA0", and "ZZ9" -> "AAA0". A digit position containing a number wraps -modulo-10, while a digit position containing a letter wraps modulo-26. +
+exponentiation-expression:
+   clone-expression
+   clone-expression   **   exponentiation-expression
+
-For a non-numeric string-valued operand that contains any -non-alphanumeric characters, for a prefix `++` operator, all characters up -to and including the right-most non-alphanumeric character is passed -through to the resulting string, unchanged. Characters to the right of -that right-most non-alphanumeric character are treated like a -non-numeric string-valued operand that contains only alphanumeric -characters, except that the resulting string will not be extended. -Instead, a digit position containing a number wraps modulo-10, while a -digit position containing a letter wraps modulo-26. +**Semantics** -*Object Operands* +The `**` operator produces the result of raising the value of the +left-hand operand to the power of the right-hand one. -If the operand has an object type supporting the operation, -then the object semantics defines the result. Otherwise, the operation has -no effect and the result is the operand. +If either of the operands have an object type supporting `**` operation, +then the object semantics defines the result. The left operand is checked first. + +If either or both operands have non-numeric types, their values are converted +to type `int` or `float`, as appropriate. If both operands have non-negative +integer values and the result can be represented as an `int`, the result has +type `int`; otherwise, the result has type `float`. If either or both operands +were leading-numeric or non-numeric strings, a non-fatal error must be produced +for each. **Examples** ```PHP -$i = 10; $j = --$i + 100; // new value of $i (9) is added to 100 -$a = array(100, 200); $v = ++$a[1]; // new value of $a[1] (201) is assigned -$a = "^^Z"; ++$a; // $a is now "^^A" -$a = "^^Z^^"; ++$a; // $a is now "^^Z^^" +2**3; // int with value 8 +2**3.0; // float with value 8.0 +"2.0"**"3"; // float with value 8.0 ``` -###Unary Arithmetic Operators +## Unary Operators + +### General **Syntax** -
-  unary-op-expression:
-    unary-operator cast-expression
+
 
-  unary-operator: one of
-    +  -  !  ~
+
+unary-expression:
+   exponentiation-expression
+   unary-op-expression
+   error-control-expression
+   cast-expression
 
-**Defined elsewhere** +**Semantics** + +These operators associate right-to-left. + + +### Unary Arithmetic Operators -* [*cast-expression*](#cast-operator) +**Syntax** + + + +
+unary-op-expression:
+   unary-operator   unary-expression
+
+unary-operator: one of
+   +   -   ~
+
**Constraints** @@ -1673,10 +1748,6 @@ an object supporting `~`. **Semantics** -For a unary `!` operator the type of the result is `bool`. -The value of the operand is [converted to type `bool`](08-conversions.md#converting-to-boolean-type) -and if it is `TRUE` then the of the operator result is `FALSE`, and the result is `TRUE` otherwise. - *Arithmetic Operands* For a unary `+` operator used with an arithmetic operand, the type and @@ -1716,7 +1787,8 @@ leading-numeric string, the string is first converted to an `int` or `float`, as appropriate, after which it is handled as an arithmetic operand. The trailing non-numeric characters in leading-numeric strings are ignored. With a non-numeric string, the result has type `int` and -value 0. +value 0. If the string was leading-numeric or non-numeric, a non-fatal error +MUST be produced. For a unary `~` operator used with a string, the result is the string with each byte being bitwise complement of the corresponding byte of the source string. @@ -1732,29 +1804,28 @@ and for `+` and `-` the object is [converted to `int`](08-conversions.md#convert ```PHP $v = +10; if ($v1 > -5) // ... -$t = TRUE; -if (!$t) // ... $v = ~0b1010101; $s = "\x86\x97"; $s = ~$s; // $s is "yh" ``` -###Error Control Operator +### Error Control Operator **Syntax** + +
-  error-control-expression:
-    @   expression
+error-control-expression:
+   @   unary-expression
 
-**Defined elsewhere** - -* [*expression*](#general-6) - **Semantics** Operator `@` suppresses the reporting of any error messages generated by the evaluation of -*expression*. +*unary-expression*. If a custom error-handler has been established using the library function [`set_error_handler`](http://php.net/manual/function.set-error-handler.php), that handler is @@ -1794,60 +1865,31 @@ if ($curER === 0) error_reporting($origER); $x = $tmp; ``` -###Shell Command Operator +### Cast Operator **Syntax** -
-  shell-command-expression:
-    `  dq-char-sequenceopt  `
-
- -where \` is the GRAVE ACCENT character U+0060, commonly referred to as a -*backtick*. - -**Defined elsewhere** - -* [*dq-char-sequence*](09-lexical-structure.md#double-quoted-string-literals) - -**Semantics** - -This operator passes *dq-char-sequence* to the command shell for -execution, as though it was being passed to the library function -[`shell_exec`](http://www.php.net/shell_exec). If the output from execution of that command is -written to [`STDOUT`](06-constants.md#core-predefined-constants), that output is the result of this operator -as a string. If the output is redirected away from `STDOUT`, or -*dq-char-sequence* is empty or contains only white space, the result of -the operator is `NULL`. - -If [`shell_exec`](http://php.net/manual/function.shell-exec.php) is disabled, this operator is disabled. - -**Examples** - -```PHP -$result = `ls`; // result is the output of command ls -$result = `ls >dirlist.txt`; // result is NULL -$d = "dir"; $f = "*.*"; -$result = `$d {$f}`; // result is the output of command dir *.* -``` - -###Cast Operator +
-  cast-expression:
-    unary-expression
-    (  cast-type  ) expression
+cast-expression:
+   (   cast-type   )   unary-expression
 
-  cast-type: one of
-    array  binary  bool  boolean  double  int  integer  float  object
-    real  string  unset
+cast-type: one of
+   array   binary   bool   boolean   double   int   integer   float   object
+   real   string   unset
 
-**Defined elsewhere** +**Constaints** -* [*unary-expression*](#general-4) +A *cast-type* of `unset` is no longer supported and results in a compile-time error. **Semantics** @@ -1875,9 +1917,6 @@ A *cast-type* of `object` results in a [conversion to type `object`](08-conversi A *cast-type* of `string` results in a [conversion to type `string`](08-conversions.md#converting-to-string-type). -A *cast-type* of `unset` always results in a value of `NULL`. (This use of -`unset` should not be confused with the [`unset` intrinsic](#unset). - **Examples** ```PHP @@ -1886,110 +1925,40 @@ A *cast-type* of `unset` always results in a value of `NULL`. (This use of (int)(float)"123.87E3" // results in the int 123870 ``` -###Variable-Name Creation Operator +## `instanceof` Operator **Syntax** -
-  variable-name-creation-expression:
-    $   expression
-    $  {  expression  }
-
- -**Defined elsewhere** - -* [*expression*](#general-6) - -**Constraints** - -In the non-brace form, *expression* must be a -*variable-name-creation-expression* or a *variable-name* that designates -a scalar value or an object convertible to string. - -In the brace form, *expression* must be a -*variable-name-creation-expression* or an expression that designates a -scalar value or an object convertible to string. - -**Semantics** - -The result of this operator is a variable name spelled using the string -representation of the value of *expression* even though such a name -might not be permitted as a [variable-name](09-lexical-structure.md#names) source code token. - -The operator will consume the following *variable-name-creation-expression* and *variable-name* tokens, and -also tokens representing [subscript operator](#subscript-operator). - -In the absense of braces, the variable is parsed with left-to-right semantics, i.e., in example `$$o->pr` -the expression is treated as `${$o}->pr`, i.e. it is parsed as "take the value of $o, consider it a variable name, -and assuming the variable with this name is an object take the property 'pr' of it". - -**Examples** - -```PHP -$color = "red"; -$$color = 123; // equivalent to $red = 123 -// ----------------------------------------- -$x = 'ab'; $ab = 'fg'; $fg = 'xy'; -$$ $ $x = 'Hello'; // equivalent to $xy = Hello -// ----------------------------------------- -$v1 = 3; -$$v1 = 22; // equivalent to ${3} = 22, variable name is "3" -$v2 = 9.543; -$$v2 = TRUE; // equivalent to ${9.543} = TRUE -$v3 = NULL; -$$v3 = "abc"; // equivalent to ${NULL} = "abc", here we create a variable with empty name -// ----------------------------------------- -function f1 () { return 2.5; } -${1 + f1()} = 1000; // equivalent to ${3.5} = 1000 -// ----------------------------------------- -$v = array(10, 20); $a = 'v'; -$$a[0] = 5; // $v is [5, 20], since $$a is on the left of [] so it gets the first shot -$v = array(10, 20); $a = 'v'; -${$a[0]} = 5; // $v is 5 -$v = array(10, 20); $a = 'v'; -${$a}[0] = 5; // $ gets first shot at $a, $v is [5, 20] -``` - -##`instanceof` Operator +
-  instanceof-expression:
-    unary-expression
-    instanceof-subject  instanceof   instanceof-type-designator
+instanceof-expression:
+   unary-expression
+   instanceof-subject   instanceof   class-type-designator
 
-  instanceof-subject:
-    expression
-
-  instanceof-type-designator:
-    qualified-name
-    expression
+instanceof-subject:
+   instanceof-expression
 
-**Defined elsewhere** - -* [*unary-expression*](#general-4) -* [*expression*](#general-6) -* [*qualified-name*](09-lexical-structure.md#names) - -**Constraints** - -The *expression* in *instanceof-type-designator* and *instanceof-subject* must not be any form of -literal. - **Semantics** Operator `instanceof` returns `TRUE` if the value designated by -*expression* in *instanceof-subject* is an object having the type specified -by *instanceof-type-designator*, is an object whose type is derived from that type, -or is an object whose type implements the interface specified by *instanceof-type-designator*. +*instanceof-subject* is an object having the type specified +by *class-type-designator*, is an object whose type is derived from that type, +or is an object whose type implements the interface specified by *class-type-designator*. Otherwise, it returns `FALSE`. -The type can be specified by *instanceof-type-designator* in one of the three forms: +The type can be specified by *class-type-designator* in one of the three forms: 1. *qualified-name* specifies the type name directly. - 2. When the *expression* form is used, *expression* may have a string value that contains a class or interface name. - 3. Alternatively, *expression* can designate an object, in which case the type of the object is used as the specified type. + 2. When the *new-variable* form is used, *new-variable* may have a string value that contains a class or interface name. + 3. Alternatively, *new-variable* can designate an object, in which case the type of the object is used as the specified type. Note that an interface can not be specified with this form. Note that `instanceof` will not invoke autoloader if the name of the type given does not @@ -2019,21 +1988,51 @@ $e2 = new E1; var_dump($e2 instanceof $e1); // TRUE ``` -##Multiplicative Operators +## Logical NOT Operator -**Syntax** +
-  multiplicative-expression:
-    instanceof-expression
-    multiplicative-expression  *  instanceof-expression
-    multiplicative-expression  /  instanceof-expression
-    multiplicative-expression  %  instanceof-expression
+logical-NOT-expression:
+   instanceof-expression
+   !   instanceof-expression
 
-**Defined elsewhere** +**Semantics** + +The value of the operand is [converted to type `bool`](08-conversions.md#converting-to-boolean-type) +and if it is `TRUE` then the result of the operator is `FALSE`. The result is `TRUE` otherwise. + +**Examples** + +```PHP +$t = TRUE; +if (!$t) // ... +``` + +## Multiplicative Operators + +**Syntax** + + -* [*instanceof-expression*](#instanceof-operator) +
+multiplicative-expression:
+   logical-NOT-expression
+   multiplicative-expression   *   logical-NOT-expression
+   multiplicative-expression   /   logical-NOT-expression
+   multiplicative-expression   %   logical-NOT-expression
+
**Constraints** @@ -2044,28 +2043,33 @@ The right-hand operand of operator `/` and operator `%` must not be zero. If either of the operands is an object supporting the operation, the result is defined by that object's semantics, with the left operand checked first. -The binary `*` operator produces the product of its operands. If either -or both operands have non-numeric types, their values are converted to -type `int` or `float`, as appropriate. Then if either operand has type -`float`, the other is converted to that type, and the result has type -`float`. Otherwise, both operands have type `int`, in which case, if the -resulting value can be represented in type `int` that is the result type. -Otherwise, the result would have type `float`. +The binary `*` operator produces the product of its operands. If either or both +operands have non-numeric types, their values are converted to type `int` or +`float`, as appropriate. If either or both operands were leading-numeric or +non-numeric strings, a non-fatal error MUST be produced for each. Then if +either operand has type `float`, the other is converted to that type, and the +result has type `float`. Otherwise, both operands have type `int`, in which +case, if the resulting value can be represented in type `int` that is the +result type. Otherwise, the result would have type `float`. Division by zero results in a non-fatal error. If the value of the numerator is positive, the result value is `INF`. If the value of the numerator is negative, the result value is `-INF`. If the value of the numerator is zero, the result value is `NAN`. The binary `/` operator produces the quotient from dividing the left-hand -operand by the right-hand one. If either or both operands have -non-numeric types, their values are converted to type `int` or `float`, as -appropriate. Then if either operand has type `float`, the other is -converted to that type, and the result has type `float`. Otherwise, both -operands have type `int`, in which case, if the mathematical value of the -computation can be preserved using type `int`, that is the result type; -otherwise, the type of the result is `float`. +operand by the right-hand one. If either or both operands have non-numeric +types, their values are converted to type `int` or `float`, as appropriate. If +either or both operands were leading-numeric or non-numeric strings, a +non-fatal error must be produced for each. Then if either operand has type +`float`, the other is converted to that type, and the result has type `float`. +Otherwise, both operands have type `int`, in which case, if the mathematical +value of the computation can be preserved using type `int`, that is the result +type; otherwise, the type of the result is `float`. The binary `%` operator produces the remainder from dividing the left-hand -operand by the right-hand one. If the type of both operands is not `int`, -their values are converted to that type. The result has type `int`. If the right-hand operand has value zero, an exception of type `DivisionByZeroError` is thrown. +operand by the right-hand one. If the type of both operands is not `int`, their +values are converted to that type. If either or both operands were +leading-numeric or non-numeric strings, a non-fatal error MUST be produced for +each. The result has type `int`. If the right-hand operand has value zero, an +exception of type `DivisionByZeroError` is thrown. These operators associate left-to-right. @@ -2085,22 +2089,26 @@ These operators associate left-to-right. 100 / "a"; // results in a diagnostic followed by bool with value false (a is converted to 0) ``` -##Additive Operators +## Additive Operators **Syntax** + +
-  additive-expression:
-    multiplicative-expression
-    additive-expression  +  multiplicative-expression
-    additive-expression  -  multiplicative-expression
-    additive-expression  .  multiplicative-expression
+additive-expression:
+   multiplicative-expression
+   additive-expression   +   multiplicative-expression
+   additive-expression   -   multiplicative-expression
+   additive-expression   .   multiplicative-expression
 
-**Defined elsewhere** - -* [*multiplicative-expression*](#multiplicative-operators) - **Constraints** If either operand of `+` has array type, the other operand must also have array @@ -2114,15 +2122,15 @@ If either of the operands is an object supporting the operation, the result is defined by that object's semantics, with the left operand checked first. For non-array operands, the binary `+` operator produces the sum of those -operands, while the binary `-` operator produces the difference of its -operands when subtracting the right-hand operand from the left-hand one. -If either or both operands have non-array, non-numeric types, their -values are converted to type `int` or `float`, as appropriate. Then if -either operand has type `float`, the other is converted to that type, and -the result has type `float`. Otherwise, both operands have type `int`, in -which case, if the resulting value can be represented in type `int` that -is the result type. -Otherwise, the result would have type `float`. +operands, while the binary `-` operator produces the difference of its operands +when subtracting the right-hand operand from the left-hand one. If either or +both operands have non-array, non-numeric types, their values are converted to +type `int` or `float`, as appropriate. If either or both operands were +leading-numeric or non-numeric strings, a non-fatal error MUST be produced for +each. Then if either operand has type `float`, the other is converted to that +type, and the result has type `float`. Otherwise, both operands have type +`int`, in which case, if the resulting value can be represented in type `int` +that is the result type. Otherwise, the result would have type `float`. If both operands have array type, the binary `+` operator produces a new array that is the union of the two operands. The result is a copy of the @@ -2159,21 +2167,24 @@ TRUE . NULL; // string with value "1" 10 + 5 . 12 . 100 - 50; // int with value 1512050; ((((10 + 5).12).100)-50) ``` -##Bitwise Shift Operators +## Bitwise Shift Operators **Syntax** + +
-  shift-expression:
-    additive-expression
-    shift-expression  <<  additive-expression
-    shift-expression  >>  additive-expression
+shift-expression:
+   additive-expression
+   shift-expression   <<   additive-expression
+   shift-expression   >>   additive-expression
 
-**Defined elsewhere** - -* [*additive-expression*](#additive-operators) - **Constraints** Each of the operands must have scalar-compatible type. @@ -2190,8 +2201,9 @@ zero bits are shifted on from the right end. Given the expression `e2` positions. Bits shifted off the right end are discarded, and the sign bit is propagated from the left end. -If either operand does not have type `int`, its value is first converted -to that type. +If either operand does not have type `int`, its value is first converted to +that type. If either or both operands were leading-numeric or non-numeric +strings, a non-fatal error MUST be produced for each. The type of the result is `int`, and the value of the result is that after the shifting is complete. The values of `e1` and `e2` are unchanged. @@ -2218,24 +2230,30 @@ These operators associate left-to-right. // it is 0x7B shifted left 33 places ``` -##Relational Operators +## Relational Operators **Syntax** + +
-  relational-expression:
-    shift-expression
-    relational-expression  <   shift-expression
-    relational-expression  >   shift-expression
-    relational-expression  <=  shift-expression
-    relational-expression  >=  shift-expression
-    relational-expression  <=> shift-expression
+relational-expression:
+   shift-expression
+   relational-expression   <   shift-expression
+   relational-expression   >   shift-expression
+   relational-expression   <=   shift-expression
+   relational-expression   >=   shift-expression
+   relational-expression   <=>   shift-expression
 
-**Defined elsewhere** - -* [*shift-expression*](#bitwise-shift-operators) - **Semantics** Operator `<=>` represents comparison operator between two expressions, with the @@ -2348,24 +2366,30 @@ function order_func($a, $b) { } ``` -##Equality Operators +## Equality Operators **Syntax** + +
-  equality-expression:
-    relational-expression
-    equality-expression  ==  relational-expression
-    equality-expression  !=  relational-expression
-    equality-expression  <>  relational-expression
-    equality-expression  ===  relational-expression
-    equality-expression  !==  relational-expression
+equality-expression:
+   relational-expression
+   equality-expression   ==   relational-expression
+   equality-expression   !=   relational-expression
+   equality-expression   <>   relational-expression
+   equality-expression   ===   relational-expression
+   equality-expression   !==   relational-expression
 
-**Defined elsewhere** - -* [*relational-expression*](#relational-operators) - **Semantics** Operator `==` represents *value equality*, operators `!=` and `<>` are @@ -2410,16 +2434,18 @@ TRUE !== 100 // result has value TRUE **Syntax** + +
-  bitwise-AND-expression:
-    equality-expression
-    bit-wise-AND-expression  &  equality-expression
+bitwise-AND-expression:
+   equality-expression
+   bitwise-AND-expression   &   equality-expression
 
-**Defined elsewhere** - -* [*equality-expression*](#equality-operators) - **Constraints** Each of the operands must have scalar-compatible type. @@ -2429,8 +2455,9 @@ Each of the operands must have scalar-compatible type. If either of the operands is an object supporting the operation, the result is defined by that object's semantics, with the left operand checked first. -If either operand does not have type `int`, its value is first converted -to that type. +If either operand does not have type `int`, its value is first converted to +that type. If either or both operands were leading-numeric or non-numeric +strings, a non-fatal error MUST be produced for each. The result of this operator is the bitwise-AND of the two operands, and the type of that result is `int`. @@ -2450,20 +2477,22 @@ $lLetter = 0x73; // letter 's' $uLetter = $lLetter & ~0x20; // clear the 6th bit to make letter 'S' ``` -##Bitwise Exclusive OR Operator +## Bitwise Exclusive OR Operator **Syntax** + +
-  bitwise-exc-OR-expression:
-    bitwise-AND-expression
-    bitwise-exc-OR-expression  ^  bitwise-AND-expression
+bitwise-exc-OR-expression:
+   bitwise-AND-expression
+   bitwise-exc-OR-expression   ^   bitwise-AND-expression
 
-**Defined elsewhere** - -* [*bitwise-AND-expression*](#bitwise-and-operator) - **Constraints** Each of the operands must have scalar-compatible type. @@ -2473,8 +2502,9 @@ Each of the operands must have scalar-compatible type. If either of the operands is an object supporting the operation, the result is defined by that object's semantics, with the left operand checked first. -If either operand does not have type `int`, its value is first converted -to that type. +If either operand does not have type `int`, its value is first converted to +that type. If either or both operands were leading-numeric or non-numeric +strings, a non-fatal error MUST be produced for each. The result of this operator is the bitwise exclusive-OR of the two operands, and the type of that result is `int`. @@ -2496,20 +2526,22 @@ $v2 = $v1 ^ $v2; $v1 = $v1 ^ $v2; // $v1 is now -987, and $v2 is now 1234 ``` -##Bitwise Inclusive OR Operator +## Bitwise Inclusive OR Operator **Syntax** + +
-  bitwise-inc-OR-expression:
-    bitwise-exc-OR-expression
-    bitwise-inc-OR-expression  |  bitwise-exc-OR-expression
+bitwise-inc-OR-expression:
+   bitwise-exc-OR-expression
+   bitwise-inc-OR-expression   |   bitwise-exc-OR-expression
 
-**Defined elsewhere** - -* [*bitwise-exc-OR-expression*](#bitwise-exclusive-or-operator) - **Constraints** Each of the operands must have scalar-compatible type. @@ -2519,8 +2551,9 @@ Each of the operands must have scalar-compatible type. If either of the operands is an object supporting the operation, the result is defined by that object's semantics, with the left operand checked first. -If either operand does not have type `int`, its value is first converted -to that type. +If either operand does not have type `int`, its value is first converted to +that type. If either or both operands were leading-numeric or non-numeric +strings, a non-fatal error MUST be produced for each. The result of this operator is the bitwise inclusive-OR of the two operands, and the type of that result is `int`. @@ -2540,20 +2573,22 @@ $uLetter = 0x41; // letter 'A' $lLetter = $upCaseLetter | 0x20; // set the 6th bit to make letter 'a' ``` -##Logical AND Operator (form 1) +## Logical AND Operator (form 1) **Syntax** + +
-  logical-AND-expression-1:
-    bitwise-incl-OR-expression
-    logical-AND-expression-1  &&  bitwise-inc-OR-expression
+logical-AND-expression-1:
+   bitwise-inc-OR-expression
+   logical-AND-expression-1   &&   bitwise-inc-OR-expression
 
-**Defined elsewhere** - -* [*bitwise-incl-OR-expression*](#bitwise-inclusive-or-operator) - **Semantics** Given the expression `e1 && e2`, `e1` is evaluated first. If `e1` [converts to `bool`](08-conversions.md#converting-to-boolean-type) as `FALSE`, `e2` is not evaluated, and the result has type `bool`, value `FALSE`. Otherwise, `e2` is evaluated. If `e2` converts to `bool` as `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`. @@ -2569,20 +2604,22 @@ same semantics as operator [`and`](#logical-and-operator-form-2). if ($month > 1 && $month <= 12) ... ``` -##Logical Inclusive OR Operator (form 1) +## Logical Inclusive OR Operator (form 1) **Syntax** + +
-  logical-inc-OR-expression-1:
-    logical-AND-expression-1
-    logical-inc-OR-expression-1  ||  logical-AND-expression-1
+logical-inc-OR-expression-1:
+   logical-AND-expression-1
+   logical-inc-OR-expression-1   ||   logical-AND-expression-1
 
-**Defined elsewhere** - -* [*logical-exc-OR-expression*](#bitwise-exclusive-or-operator) - **Semantics** Given the expression `e1 || e2`, `e1` is evaluated first. If `e1` [converts to `bool`](08-conversions.md#converting-to-boolean-type) as `TRUE`, `e2` is not evaluated, and the result has type `bool`, value `TRUE`. Otherwise, `e2` is evaluated. If `e2` converts to `bool` as `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`. @@ -2595,66 +2632,22 @@ This operator associates left-to-right. if ($month < 1 || $month > 12) ... ``` -##Conditional Operator +## Coalesce Operator **Syntax** -
-  conditional-expression:
-    logical-inc-OR-expression-1
-    logical-inc-OR-expression-1  ?  expressionopt  :  conditional-expression
-
- -**Defined elsewhere** - -* [*logical-OR-expression*](#logical-inclusive-or-operator-form-1) -* [*expression*](#general-6) - -**Semantics** -Given the expression `e1 ? e2 : e3`, `e1` is evaluated first and [converted to `bool`](08-conversions.md#converting-to-boolean-type) if it has another type. -If the result is `TRUE`, then and only then is `e2` evaluated, and the result and its type become the result and type of -the whole expression. Otherwise, then and only then is `e3` evaluated, and -the result and its type become the result and type of the whole -expression. There is a sequence point after the evaluation of `e1`. If `e2` -is omitted, the result and type of the whole expression is the value and -type of `e1` (before the conversion to `bool`). - -This operator associates left-to-right. - -**Examples** - -```PHP -for ($i = -5; $i <= 5; ++$i) - echo "$i is ".(($i & 1 == TRUE) ? "odd\n" : "even\n"); -// ----------------------------------------- -$a = 10 ? : "Hello"; // result is int with value 10 -$a = 0 ? : "Hello"; // result is string with value "Hello" -$i = PHP_INT_MAX; -$a = $i++ ? : "red"; // result is int with value 2147483647 (on a 32-bit - // system) even though $i is now the float 2147483648.0 -// ----------------------------------------- -$i++ ? f($i) : f(++$i); // the sequence point makes this well-defined -// ----------------------------------------- -function factorial($int) -{ - return ($int > 1) ? $int * factorial($int - 1) : $int; -} -``` - -##Coalesce Operator - -**Syntax** +
-  coalesce-expression:
-    logical-inc-OR-expression  ??  expression
+coalesce-expression:
+   logical-inc-OR-expression-1
+   logical-inc-OR-expression-1   ??   coalesce-expression
 
-**Defined elsewhere** - -* [*logical-OR-expression*](#logical-inclusive-or-operator-form-1) -* [*expression*](#general-6) - **Semantics** Given the expression `e1 ?? e2`, if `e1` is set and not `NULL` (i.e. TRUE for @@ -2662,8 +2655,8 @@ Given the expression `e1 ?? e2`, if `e1` is set and not `NULL` (i.e. TRUE for evaluated, and the result becomes the result of the whole expression. There is a sequence point after the evaluation of `e1`. -Note that the semantics of `??` is similar to `isset` so that uninitialized variables will not produce -warnings when used in `e1`. +Note that the semantics of `??` is similar to `isset` so that uninitialized variables will +not produce warnings when used in `e1`. This operator associates right-to-left. @@ -2677,41 +2670,86 @@ $a = $arr["foo"] ?? "bang"; // "bar" as $arr["foo"] is set and not NULL $a = $arr["qux"] ?? "bang"; // "bang" as $arr["qux"] is NULL $a = $arr["bing"] ?? "bang"; // "bang" as $arr["bing"] is not set -$a = $obj->foo ?? "bang"; // "bar" as $obj->foo is set and not NULL -$a = $obj->qux ?? "bang"; // "bang" as $obj->qux is NULL -$a = $obj->bing ?? "bang"; // "bang" as $obj->bing is not set +$a = $obj->foo ?? "bang"; // "bar" as $obj->foo is set and not NULL +$a = $obj->qux ?? "bang"; // "bang" as $obj->qux is NULL +$a = $obj->bing ?? "bang"; // "bang" as $obj->bing is not set + +$a = NULL ?? $arr["bing"] ?? 2; // 2 as NULL is NULL, and $arr["bing"] is not set + +function foo() { + echo "executed!", PHP_EOL; +} +var_dump(true ?? foo()); // outputs bool(true), "executed!" does not appear as it short-circuits +``` + +## Conditional Operator + +**Syntax** + + + +
+conditional-expression:
+   coalesce-expression
+   conditional-expression   ?   expressionopt   :   coalesce-expression
+
+ +**Semantics** +Given the expression `e1 ? e2 : e3`, `e1` is evaluated first and [converted to `bool`](08-conversions.md#converting-to-boolean-type) if it has another type. +If the result is `TRUE`, then and only then is `e2` evaluated, and the result and its type become the result and type of +the whole expression. Otherwise, then and only then is `e3` evaluated, and +the result and its type become the result and type of the whole +expression. There is a sequence point after the evaluation of `e1`. If `e2` +is omitted, the result and type of the whole expression is the value and +type of `e1` (before the conversion to `bool`). + +This operator associates left-to-right. -$a = NULL ?? $arr["bing"] ?? 2; // 2 as NULL is NULL, and $arr["bing"] is not set +**Examples** -function foo() { - echo "executed!", PHP_EOL; +```PHP +for ($i = -5; $i <= 5; ++$i) + echo "$i is ".(($i & 1 == TRUE) ? "odd\n" : "even\n"); +// ----------------------------------------- +$a = 10 ? : "Hello"; // result is int with value 10 +$a = 0 ? : "Hello"; // result is string with value "Hello" +$i = PHP_INT_MAX; +$a = $i++ ? : "red"; // result is int with value 2147483647 (on a 32-bit + // system) even though $i is now the float 2147483648.0 +// ----------------------------------------- +$i++ ? f($i) : f(++$i); // the sequence point makes this well-defined +// ----------------------------------------- +function factorial($int) +{ + return ($int > 1) ? $int * factorial($int - 1) : $int; } -var_dump(true ?? foo()); // outputs bool(true), "executed!" does not appear as it short-circuits ``` -##Assignment Operators -###General +## Assignment Operators + +### General **Syntax** + +
-  assignment-expression:
-    conditional-expression
-    coalesce-expression
-    simple-assignment-expression
-    byref-assignment-expression
-    compound-assignment-expression
+assignment-expression:
+   conditional-expression
+   simple-assignment-expression
+   compound-assignment-expression
 
-**Defined elsewhere** - -* [*conditional-expression*](#conditional-operator) -* [*simple-assignment-expression*](#simple-assignment) -* [*byref-assignment-expression*](#byref-assignment) -* [*compound-assignment-expression*](#compound-assignment) -* [*coalesce-expression*](#coalesce-operator) - **Constraints** The left-hand operand of an assignment operator must be a modifiable @@ -2721,20 +2759,22 @@ lvalue. These operators associate right-to-left. -###Simple Assignment +### Simple Assignment **Syntax** + +
-  simple-assignment-expression:
-    unary-expression  =  assignment-expression
+simple-assignment-expression:
+   variable   =   assignment-expression
+   list-intrinsic   =   assignment-expression
 
-**Defined elsewhere** - -* [*unary-expression*](#general-4) -* [*assignment-expression*](#general-5) - **Constraints** If the location designated by the left-hand operand is a string element, @@ -2745,7 +2785,7 @@ must have type `string`. If *assignment-expression* designates an expression having value type, see [assignment for scalar types](04-basic-concepts.md#byref-assignment-for-scalar-types-with-local-variables) -If *assignment-expression* designates an expression having handle type, see [assignment for object and resource types](04-basic-concepts.md#value-assignment-of-object-and-resource-types-to-a-local-variable). +If *assignment-expression* designates an expression having handle type, see [assignment for object and resource types](04-basic-concepts.md#value-assignment-of-objects-to-a-local-variable). If *assignment-expression* designates an expression having array type, see [assignment of array types](04-basic-concepts.md#value-assignment-of-array-types-to-local-variables). @@ -2764,9 +2804,9 @@ character from the right-hand operand is stored at the designated location; all other characters in the right-hand operand string are ignored. If the designated location is beyond the end of the destination string, that string is extended to the new length with -spaces (U+0020) added as padding beyond the old end and before the newly +spaces (0x20) added as padding beyond the old end and before the newly added character. If the right-hand operand is an empty string, the null -character \\0 (U+0000) is stored. +character \\0 (0x00) is stored. **Examples** @@ -2789,26 +2829,170 @@ class C { ... } $a = new C; // make $a point to the allocated object ``` -###byRef Assignment +#### list intrinsic **Syntax** + +
-  byref-assignment-expression:
-    unary-expression  =  &  assignment-expression
-
+list-intrinsic: + list ( list-expression-list ) + +list-expression-list: + unkeyed-list-expression-list + keyed-list-expression-list ,opt -**Defined elsewhere** +unkeyed-list-expression-list: + list-or-variable + , + unkeyed-list-expression-list , list-or-variableopt -* [*unary-expression*](#general-4) -* [*assignment-expression*](#general-5) +keyed-list-expression-list: + expression => list-or-variable + keyed-list-expression-list , expression => list-or-variable + +list-or-variable: + list-intrinsic + &opt variable +
**Constraints** -*unary-expression* must designate a variable. +*list-intrinsic* must be used as the left-hand operand in a +[*simple-assignment-expression*](#simple-assignment) of which the right-hand +operand must be an expression that designates an array or object implementing +the `ArrayAccess` interface (called the *source array*). + +Each *variable* in *list-or-variable* must designate a writable variable (called +the *target variable*). + +At least one of the elements of the *list-expression-list* must be non-empty. + +**Semantics** + +This intrinsic assigns one or more elements of the source array to the +target variables. Target variables may be assigned by reference. +On success, it will return a copy of the source array. If the +source array is not an array or object implementing `ArrayAccess` no +assignments are performed and the return value is `NULL`. + +For *unkeyed-list-expression-list*, all elements in the source array having +keys of type `string` are ignored. +The element having an `int` key of 0 is assigned to the first target +variable, the element having an `int` key of 1 is assigned to the second +target variable, and so on, until all target variables have been +assigned. Any other array elements are ignored. If there are +fewer source array elements having int keys than there are target +variables, the unassigned target variables are set to `NULL` and +a non-fatal error is produced. + +For *keyed-list-expression-list*, each key-variable pair is handled in turn, +with the key and variable being separated by the `=>` symbol. +The element having the first key, with the key having been converted using the +same rules as the [subscript operator](10-expressions.md#subscript-operator), +is assigned to the frst target variable. This process is repeated for the +second `=>` pair, if any, and so on. Any other array elements are ignored. +If there is no array element with a given key, the unassigned target variable +is set to `NULL` and a non-fatal error is produced. + +The assignments must occur in this order. + +Any target variable may be a list, in which case, the corresponding +element is expected to be an array. + +If the source array elements and the target variables overlap in any +way, the behavior is unspecified. + +**Examples** + +```PHP +list($min, $max, $avg) = array(0, 100, 67); + // $min is 0, $max is 100, $avg is 67 +list($min, $max, $avg) = array(2 => 67, 1 => 100, 0 => 0); + // same as example above +list($min, , $avg) = array(0, 100, 67); + // $min is 0, $avg is 67 +list($min, $max, $avg) = array(0, 2 => 100, 4 => 67); + // $min is 0, $max is NULL, $avg is 100 +list($min, list($max, $avg)) = [0, [1 => 67, 99, 0 => 100], 33]; + // $min is 0, $max is 100, $avg is 67 + +list($arr[1], $arr[0]) = [0, 1]; + // $arr is [1 => 0, 0 => 1], in this order +list($arr2[], $arr2[]) = [0, 1]; + // $arr2 is [0, 1] + +$a = [1, 2]; +list(&$one, $two) = $a; + // $a[0] is 1, $a[1] is 2 +$one++; + // $a[0] is 2, $a[1] is 2 + +list("one" => $one, "two" => $two) = ["one" => 1, "two" => 2]; + // $one is 1, $two is 2 +list( + "one" => $one, + "two" => $two, +) = [ + "one" => 1, + "two" => 2, +]; + // $one is 1, $two is 2 + +$a = ['one' => 1, 'two' => 2]; +list('one' => &$one, 'two' => $two) = $a; + // $a['one'] is 1, $a['two'] is 2 +$one++; + // $a['one'] is 2, $a['two'] is 2 + +list(list("x" => $x1, "y" => $y1), list("x" => $x2, "y" => $y2)) = [ + ["x" => 1, "y" => 2], + ["x" => 3, "y" => 4] +]; + // $x1 is 1, $y1 is 2, $x2 is 3, $y2 is 4 +list(0 => list($x1, $x2), 1 => list($x2, $y2)) = [[1, 2], [3, 4]]; + // $x1 is 1, $y1 is 2, $x2 is 3, $y2 is 4 +``` + +### byRef Assignment + +**Syntax** + + + +
+byref-assignment-expression:
+   variable   =   &   variable
+
+ +**Constraints** -*assignment-expression* must be an lvalue or a call to a function that -returns a value byRef. +The right-hand-side *variable* must be an lvalue or a call to a function +that returns a value byRef. **Semantics** @@ -2833,22 +3017,25 @@ function &g2() { $t = "xxx"; return $t; } // return byRef $b =& g2(); // make $b an alias to "xxx" ``` -##Compound Assignment +## Compound Assignment **Syntax** -
-  compound-assignment-expression:
-    unary-expression   compound-assignment-operator   assignment-expression
+
 
-**Defined elsewhere**
+
+compound-assignment-expression:
+   variable   compound-assignment-operator   assignment-expression
 
-* [*unary-expression*](#general-4)
-* [*assignment-expression*](#general-5)
+compound-assignment-operator: one of
+   **=   *=   /=   %=   +=   -=   .=   <<=   >>=   &=   ^=   |=
+
**Constraints** @@ -2871,93 +3058,32 @@ $i = 1; $a[$i++] += 50; // $a[1] = 250, $i → 2 ``` -##Logical AND Operator (form 2) - -**Syntax** - -
-  logical-AND-expression-2:
-    assignment-expression
-    logical-AND-expression-2  and  assignment-expression
-
- -**Defined elsewhere** - -* [*assignment-expression*](#general-5) - -**Semantics** - -Except for the difference in precedence, operator and has exactly the -same semantics as [operator `&&`](#logical-and-operator-form-1). - -##Logical Exclusive OR Operator - -**Syntax** - -
-  logical-exc-OR-expression:
-    logical-AND-expression-2
-    logical-exc-OR-expression  xor  logical-AND-expression-2
-
- -**Defined elsewhere** - -* [*logical-AND-expression*](#logical-and-operator-form-2) - -**Semantics** - -If either operand does not have type `bool`, its value is first converted -to that type. - -Given the expression `e1 xor e2`, `e1` is evaluated first, then `e2`. If -either `e1` or `e2` [converted to `bool`](08-conversions.md#converting-to-boolean-type) as `TRUE`, but not both, the result has type `bool`, value -`TRUE`. Otherwise, the result has type `bool`, value `FALSE`. There is a -sequence point after the evaluation of `e1`. - -This operator associates left-to-right. - -**Examples** - -```PHP -f($i++) xor g($i) // the sequence point makes this well-defined -``` - -##Logical Inclusive OR Operator (form 2) +## `yield` Operator **Syntax** -
-  logical-inc-OR-expression-2:
-    logical-exc-OR-expression
-    logical-inc-OR-expression-2  or  logical-exc-OR-expression
-
- -**Defined elsewhere** - -* [*logical-exc-OR-expression*](#logical-exclusive-or-operator) - -**Semantics** - -Except for the difference in precedence, operator and has exactly the -same semantics as [operator `||`](#logical-inclusive-or-operator-form-1). +
-  yield-expression:
-    logical-inc-OR-expression-2
-    yield  array-element-initializer
-    yield from  expression
+yield-from-expression:
+   yield from   assignment-expression
+
+yield-expression:
+   yield-from-expression
+   yield
+   yield   yield-expression
+   yield   yield-from-expression   =>   yield-expression
 
-**Defined elsewhere** - -* [*logical-inc-OR-expression*](#logical-inclusive-or-operator-form-2) -* [*array-element-initializer*](#array-creation-operator) -* [*expression*](#script-inclusion-operators) - **Semantics** Any function containing a *yield-expression* is a *generator function*. @@ -2975,22 +3101,13 @@ The `yield` operator produces the result `NULL` unless the method [`Generator->send`](14-classes.md#class-generator) was called to provide a result value. This operator has the side effect of generating the next value in the collection. -Before being used, an *element-key* must have, or be converted to, type -`int` or `string`. Keys with `float` or `bool` values, or numeric strings, are -[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). - -If *element-key* is omitted from an *array-element-initializer*, an +If the key is omitted from an a *yield-expression*, an element key of type `int` is associated with the corresponding -*element-value*. The key associated is one more than the previously +value. The key associated is one more than the previously assigned int key for this collection. However, if this is the first -element in this collection with an `int` key, key zero is used. If -*element-key* is provided, it is associated with the corresponding -*element-value*. The resulting key/value pair is made available by -`yield`. +element in this collection with an `int` key, zero is used. -If *array-element-initializer* is omitted, default int-key assignment is -used and each value is `NULL`. +If the value is also omitted, `NULL` will be used instead. If the generator function definition declares that it returns byRef, each value in a key/value pair is yielded byRef. @@ -2999,15 +3116,15 @@ The following applies only to the `yield from` form: A generator function (referred to as a *delegating generator*) can delegate to another generator function (referred to as a *subgenerator*), a Traversable object, or an array, each of which is designated by *expression*. -Each value yielded by *expression* is passed directly to the delegating generator's caller. +Each value yielded by *assignment-expression* is passed directly to the delegating generator's caller. -Each value sent to the delegating generator's `send` method is passed to the subgenerator's `send` method. If *expression* is not a generator function, any sent values are ignored. +Each value sent to the delegating generator's `send` method is passed to the subgenerator's `send` method. If *assignment-expression* is not a generator function, any sent values are ignored. -Exceptions thrown by *expression* are propagated up to the delegating generator. +Exceptions thrown by *assignment-expression* are propagated up to the delegating generator. Upon traversable completion, `NULL` is returned to the delegating generator if the traversable is not a generator. If the traversable is a generator, its return value is sent to the delegating generator as the value of the `yield from` *expression*. -An exception of type `Error` is thrown if *expression* evaluates to a generator that previously terminated with an uncaught exception, or it evaluates to something that is neither Traversable nor an array. +An exception of type `Error` is thrown if *assignment-expression* evaluates to a generator that previously terminated with an uncaught exception, or it evaluates to something that is neither Traversable nor an array. **Examples** @@ -3068,28 +3185,149 @@ foreach ($g as $yielded) { } ``` -##Script Inclusion Operators +## Print expression + +**Syntax** + + + +
+print-expression:
+   yield-expression
+   print   print-expression
+
+ +**Constraints** + +*print-expression* value must be [convertable to a string](08-conversions.md#converting-to-string-type). +In particular, it should not be an array and if it is an object, it must implement +a [`__toString` method](14-classes.md#method-__tostring). + +**Semantics** + +After converting *print-expression*'s value into a string, if necessary, +`print` writes the resulting string to [`STDOUT`](06-constants.md#core-predefined-constants). +Unlike [`echo`](11-statements.md#the-echo-statement), `print` can be used in any context +allowing an expression. It always returns the value 1. + +See also: [double quoted strings](09-lexical-structure.md#double-quoted-string-literals) and +[heredoc documents](09-lexical-structure.md#heredoc-string-literals), [conversion to string](08-conversions.md#converting-to-string-type). + +**Examples** + +```PHP +$v1 = TRUE; +$v2 = 123; +print '>>' . $v1 . '|' . $v2 . "<<\n"; // outputs ">>1|123<<" +print ('>>' . $v1 . '|' . $v2 . "<<\n"); // outputs ">>1|123<<" +$v3 = "qqq{$v2}zzz"; +print "$v3\n"; // outputs "qqq123zzz" +$a > $b ? print "..." : print "..."; +``` + +## Logical AND Operator (form 2) + +**Syntax** + + + +
+logical-AND-expression-2:
+   print-expression
+   logical-AND-expression-2   and   yield-expression
+
+ +**Semantics** + +Except for the difference in precedence, operator and has exactly the +same semantics as [operator `&&`](#logical-and-operator-form-1). + +## Logical Exclusive OR Operator + +**Syntax** + + + +
+logical-exc-OR-expression:
+   logical-AND-expression-2
+   logical-exc-OR-expression   xor   logical-AND-expression-2
+
+ +**Semantics** + +If either operand does not have type `bool`, its value is first converted +to that type. + +Given the expression `e1 xor e2`, `e1` is evaluated first, then `e2`. If +either `e1` or `e2` [converted to `bool`](08-conversions.md#converting-to-boolean-type) as `TRUE`, but not both, the result has type `bool`, value +`TRUE`. Otherwise, the result has type `bool`, value `FALSE`. There is a +sequence point after the evaluation of `e1`. + +This operator associates left-to-right. + +**Examples** + +```PHP +f($i++) xor g($i) // the sequence point makes this well-defined +``` -###General +## Logical Inclusive OR Operator (form 2) **Syntax** + +
-  expression:
-    yield-expression
-    include-expression
-    include-once-expression
-    require-expression
-    require-once-expression
+logical-inc-OR-expression-2:
+   logical-exc-OR-expression
+   logical-inc-OR-expression-2   or   logical-exc-OR-expression
 
-**Defined elsewhere** +**Semantics** + +Except for the difference in precedence, operator and has exactly the +same semantics as [operator `||`](#logical-inclusive-or-operator-form-1). + +## Script Inclusion Operators + +### General -* [*yield-expression*](#yield-operator) -* [*include-expression*](#the-include-operator) -* [*include-once-expression*](#the-include_once-operator) -* [*require-expression*](#the-require-operator) -* [*require-once-expression*](#the-require_once-operator) +**Syntax** + + + +
+expression:
+   logical-inc-OR-expression-2
+   include-expression
+   include-once-expression
+   require-expression
+   require-once-expression
+
**Semantics** @@ -3212,7 +3450,7 @@ class Bar{ include 'include.php'; } } -echo X; // emits a notice: Use of undefined constant X ... +echo X; // emits a warning: Use of undefined constant X ... echo \foo\X; // same as above since the inclusion did not happen yet $bar = new Bar(); $bar->bar(); @@ -3244,23 +3482,23 @@ echo $x; // hello ```` -###The `include` Operator +### The `include` Operator **Syntax** + +
-  include-expression:
-    include  (  expression  )
-    include  expression
+include-expression:
+   include   expression
 
-**Defined elsewhere** - -* [*expression*](#general-6) - **Constraints** -*expresssion* must be convertable to a string, which designates +*expression* must be convertable to a string, which designates a filename. **Semantics** @@ -3296,20 +3534,20 @@ $inc = include('limits.php'); If ((include 'Positions.php') == 1) ... ``` -###The `include_once` Operator +### The `include_once` Operator **Syntax** + +
-  include-once-expression:
-    include_once  (  expression  )
-    include_once  expression
+include-once-expression:
+   include_once   expression
 
-**Defined elsewhere** - -* [*expression*](#general-6) - **Semantics** This operator is identical to operator [`include`](#the-include-operator) except that in @@ -3344,40 +3582,40 @@ $p1 = new Point(10, 20); $c1 = new Circle(9, 7, 2.4); ``` -###The `require` Operator +### The `require` Operator **Syntax** + +
-  require-expression:
-    require  (  expression  )
-    require  expression
+require-expression:
+   require   expression
 
-**Defined elsewhere** - -* [*expression*](#general-6) - **Semantics** This operator is identical to operator [`include`](#the-include-operator) except that in the case of `require`, failure to find/open the designated include file produces a fatal error. -###The `require_once` Operator +### The `require_once` Operator **Syntax** + +
-  require-once-expression:
-    require_once  (  expression  )
-    require_once  expression
+require-once-expression:
+   require_once   expression
 
-**Defined elsewhere** - -* [*expression*](#general-6) - **Semantics** This operator is identical to operator [`require`](#the-require-operator) except that in @@ -3391,31 +3629,34 @@ happens. The files are identified by the full pathname, so different forms of the filename (such as full and relative path) still are considered the same file. -##Constant Expressions +## Constant Expressions **Syntax** + +
-  constant-expression:
-    array-creation-expression
-    expression
+constant-expression:
+   expression
 
-**Defined elsewhere** - -* [*array-creation-expression*](#array-creation-operator) -* [*expression*](#general-6) - **Constraints** -All of the *element-key* and *element-value* elements in -[*array-creation-expression*](#array-creation-operator) must be literals. +The *expression* may only use the following syntactic elements: -*expression* must have a scalar type, and be a literal or the name of a [c-constant](06-constants.md#general). +* [Literals](#literals). String literals must not use interpolation. +* [Array creation expressions](#array-creation-operator). +* Unary operators `+`, `-`, `~`, `!`. +* Binary operators `+`, `-`, `*`, `/`, `%`, `.`, `**`, `^`, `|`, `&`, + `<`, `>`, `<=`, `>=`, `<=>`, `==`, `!=`, `===`, `!==`, `&&`, `||`, `??`. +* [Conditional expressions](#conditional-operator). +* [Subscript expressions](#subscript-operator). +* [Constant access expressions](#constant-access-expression). +* [Class constant access expressions](#scope-resolution-operator). **Semantics** -A *constant-expression* is the value of a c-constant. A *constant-expression* -is required in several contexts, such as in initializer values in a -[*const-declaration*](14-classes.md#constants) and default initial values in a [function -definition](13-functions.md#function-definitions). +A *constant-expression* evaluates to the value of the constituent *expression*. diff --git a/spec/11-statements.md b/spec/11-statements.md index 98b5025c..61af9cc8 100644 --- a/spec/11-statements.md +++ b/spec/11-statements.md @@ -1,66 +1,76 @@ -#Statements +# Statements -##General +## General **Syntax** -
+
 
-  statement:
-    compound-statement
-    labeled-statement
-    expression-statement
-    selection-statement
-    iteration-statement
-    jump-statement
-    try-statement
-    declare-statement
-    const-declaration
-    function-definition
-    class-declaration
-    interface-declaration
-    trait-declaration
-    namespace-definition
-    namespace-use-declaration
-    global-declaration
-    function-static-declaration
+
+statement:
+   compound-statement
+   named-label-statement
+   expression-statement
+   selection-statement
+   iteration-statement
+   jump-statement
+   try-statement
+   declare-statement
+   echo-statement
+   unset-statement
+   const-declaration
+   function-definition
+   class-declaration
+   interface-declaration
+   trait-declaration
+   namespace-definition
+   namespace-use-declaration
+   global-declaration
+   function-static-declaration
 
-**Defined elsewhere** - -* [*compound-statement*](#compound-statements) -* [*labeled-statement*](#labeled-statements) -* [*expression-statement*](#expression-statements) -* [*selection-statement*](#general-1) -* [*iteration-statement*](#general-2) -* [*jump-statement*](#general-3) -* [*declare-statement*](#the-declare-statement) -* [*const-declaration*](14-classes.md#constants) -* [*function-definition*](13-functions.md#function-definitions) -* [*class-declaration*](14-classes.md#class-declarations) -* [*interface-declaration*](15-interfaces.md#interface-declarations) -* [*trait-declaration*](16-traits.md#trait-declarations) -* [*namespace-definition*](18-namespaces.md#defining-namespaces) -* [*namespace-use-declaration*](18-namespaces.md#namespace-use-declarations) -* [*global-declaration*](07-variables.md#global-variables) -* [*function-static-declaration*](07-variables.md#function-statics) - -##Compound Statements +## Compound Statements **Syntax** -
-  compound-statement:
-    {   statement-listopt  }
+
 
-**Defined elsewhere**
+
+compound-statement:
+   {   statement-listopt   }
 
-* [*statement*](#general)
+statement-list:
+   statement
+   statement-list   statement
+
**Semantics** @@ -86,63 +96,43 @@ while (condition) } ``` -##Labeled Statements +## Labeled Statements **Syntax** -
-  labeled-statement:
-    named-label-statement
-    case-statement
-    default-statement
-
-  named-label-statement:
-    name  :  statement
-
-  case-statement:
-    case   expression   case-default-label-terminator   statement
+
 
-  default-statement:
-    default  case-default-label-terminator   statement
-
-  case-default-label-terminator:
-    :
-    ;
+
+named-label-statement:
+   name   :
 
-**Defined elsewhere** - -* [*name*](09-lexical-structure.md#names) -* [*statement*](#general) -* [*expression*](10-expressions.md#general-6) - **Constraints** -A named label can be used as the target of a [`goto` statement](#the-goto-statement). - Named labels must be unique within a function. -A case and default labeled statements must only occur inside a [`switch` statement](#the-switch-statement). - **Semantics** -Any statement may be preceded by a token sequence that declares a name -as a label name. The presence of a label does not alter the flow of -execution. +A named label can be used as the target of a [`goto` statement](#the-goto-statement). +The presence of a label does not by itself alter the flow of execution. -##Expression Statements +## Expression Statements **Syntax** + +
-   expression-statement:
-     expressionopt  ;
+expression-statement:
+   expressionopt   ;
 
-**Defined elsewhere** - -* [*expression*](10-expressions.md#general-6) - **Semantics** If present, *expression* is evaluated for its side effects, if any, and @@ -181,63 +171,84 @@ done: } ``` -##Selection Statements +## Selection Statements -###General +### General **Syntax** + +
-  selection-statement:
-    if-statement
-    switch-statement
+selection-statement:
+   if-statement
+   switch-statement
 
-**Defined elsewhere** - -* [*if-statement*](#the-if-statement) -* [*switch-statement*](#the-switch-statement) - **Semantics** Based on the value of a controlling expression, a selection statement selects among a set of statements. -###The `if` Statement +### The `if` Statement **Syntax** -
-  if-statement:
-    if   (   expression   )   statement   elseif-clauses-1opt   else-clause-1opt
-    if   (   expression   )   :   statement-list   elseif-clauses-2opt   else-clause-2opt   endif   ;
+
 
-**Defined elsewhere**
+
+if-statement:
+   if   (   expression   )   statement   elseif-clauses-1opt   else-clause-1opt
+   if   (   expression   )   :   statement-list   elseif-clauses-2opt   else-clause-2opt   endif   ;
+
+elseif-clauses-1:
+   elseif-clause-1
+   elseif-clauses-1   elseif-clause-1
+
+elseif-clause-1:
+   elseif   (   expression   )   statement
+
+else-clause-1:
+   else   statement
 
-* [*expression*](10-expressions.md#general-6)
-* [*statement*](#general)
-* [*statement-list*](#compound-statements)
+elseif-clauses-2:
+   elseif-clause-2
+   elseif-clauses-2   elseif-clause-2
+
+elseif-clause-2:
+   elseif   (   expression   )   :   statement-list
+
+else-clause-2:
+   else   :   statement-list
+
**Semantics** @@ -296,27 +307,49 @@ else // this else does go with the outer if ... ``` -###The `switch` Statement +### The `switch` Statement **Syntax** + +
-  switch-statement:
-    switch  (  expression  )  { case-statementsopt }
-    switch  (  expression  )  :   case-statementsopt  endswitch;
+switch-statement:
+   switch   (   expression   )   {   case-statementsopt   }
+   switch   (   expression   )   :   case-statementsopt   endswitch   ;
 
-  case-statements:
-    case-statement statement-listopt case-statementsopt
-    default-statement statement-listopt case-statementsopt
-
+case-statements: + case-statement case-statementsopt + default-statement case-statementsopt + +case-statement: + case expression case-default-label-terminator statement-listopt -**Defined elsewhere** +default-statement: + default case-default-label-terminator statement-listopt -* [*expression*](10-expressions.md#general-6) -* [*case-statement*](#labeled-statements) -* [*default-statement*](#labeled-statements) -* [*compound-statement*](#compound-statements) -* [*statement-list*](#compound-statements) +case-default-label-terminator: + : + ; +
**Constraints** @@ -400,43 +433,44 @@ case $v < $a: // non-constant expression } ``` -##Iteration Statements +## Iteration Statements -###General +### General **Syntax** + +
-  iteration-statement:
-    while-statement
-    do-statement
-    for-statement
-    foreach-statement
+iteration-statement:
+   while-statement
+   do-statement
+   for-statement
+   foreach-statement
 
-**Defined elsewhere** - -* [*while-statement*](#the-while-statement) -* [*do-statement*](#the-do-statement) -* [*for-statement*](#the-for-statement) -* [*foreach-statement*](#the-foreach-statement) - -##The `while` Statement +## The `while` Statement **Syntax** + +
-  while-statement:
-    while  (  expression  )  statement
-    while  (  expression  )  :   statement-list  endwhile ;
+while-statement:
+   while   (   expression   )   statement
+   while   (   expression   )   :   statement-list   endwhile   ;
 
-**Defined elsewhere** - -* [*expression*](10-expressions.md#general-6) -* [*statement*](#general) -* [*statement-list*](#compound-statements) - **Semantics** The two forms of the `while` statement are equivalent; they simply provide @@ -469,22 +503,22 @@ while (TRUE) } ``` -##The `do` Statement +## The `do` Statement **Syntax** + +
-  do-statement:
-    do  statement  while  (  expression  )  ;
+do-statement:
+   do   statement   while   (   expression   )   ;
 
(Note: There is no alternate syntax). -**Defined elsewhere** - -* [*statement*](#general) -* [*expression*](10-expressions.md#general-6) - **Constraints** The controlling expression *expression* must have type `bool` or be @@ -513,39 +547,52 @@ do while ($i <= 10); ``` -##The `for` Statement +## The `for` Statement **Syntax** + +
-  for-statement:
-    for   (   for-initializeropt   ;   for-controlopt   ;   for-end-of-loopopt   )   statement
-    for   (   for-initializeropt   ;   for-controlopt   ;   for-end-of-loopopt   )   :   statement-list   endfor   ;
+for-statement:
+   for   (   for-initializeropt   ;   for-controlopt   ;   for-end-of-loopopt   )   statement
+   for   (   for-initializeropt   ;   for-controlopt   ;   for-end-of-loopopt   )   :   statement-list   endfor   ;
 
-  for-initializer:
-    for-expression-group
+for-initializer:
+   for-expression-group
 
-  for-control:
-    for-expression-group
+for-control:
+   for-expression-group
 
-  for-end-of-loop:
-    for-expression-group
+for-end-of-loop:
+   for-expression-group
 
-  for-expression-group:
-    expression
-    for-expression-group   ,   expression
+for-expression-group:
+   expression
+   for-expression-group   ,   expression
 
Note: Unlike C/C++, PHP does not support a comma operator, per se. However, the syntax for the `for` statement has been extended from that of C/C++ to achieve the same results in this context. -**Defined elsewhere** - -* [*statement*](#general) -* [*statement-list*](#compound-statements) -* [*expression*](10-expressions.md#general-6) - **Semantics** The two forms of the `for` statement are equivalent; they simply provide @@ -605,32 +652,41 @@ for ($a = 100, $i = 1; ++$i, $i <= 10; ++$i, $a -= 10) } ``` -##The `foreach` Statement +## The `foreach` Statement **Syntax** -
-  foreach-statement:
-    foreach  (  foreach-collection-name  as  foreach-keyopt  foreach-value  )   statement
-    foreach  (  foreach-collection-name  as  foreach-keyopt  foreach-value  )  :  statement-list  endforeach  ;
+
+
+
+foreach-statement:
+   foreach   (   foreach-collection-name   as   foreach-keyopt   foreach-value   )   statement
+   foreach   (   foreach-collection-name   as   foreach-keyopt   foreach-value   )   :   statement-list   endforeach   ;
+
+foreach-collection-name:
+   expression
 
-**Defined elsewhere**
+foreach-key:
+   expression   =>
 
-* [*statement*](#general)
-* [*statement-list*](#compound-statements)
-* [*list-intrinsic*](10-expressions.md#list)
-* [*expression*](10-expressions.md#general-6)
+foreach-value:
+   &opt   expression
+   list-intrinsic
+
**Constraints** @@ -688,42 +744,44 @@ foreach ($colors as &$color) // note the & } ``` -##Jump Statements +## Jump Statements -###General +### General **Syntax** + +
-  jump-statement:
-    goto-statement
-    continue-statement
-    break-statement
-    return-statement
-    throw-statement
+jump-statement:
+   goto-statement
+   continue-statement
+   break-statement
+   return-statement
+   throw-statement
 
-**Defined elsewhere** - -* [*goto-statement*](#the-goto-statement) -* [*continue-statement*](#the-continue-statement) -* [*break-statement*](#the-break-statement) -* [*return-statement*](#the-return-statement) -* [*throw-statement*](#the-throw-statement) - -###The `goto` Statement +### The `goto` Statement **Syntax** + +
-  goto-statement:
-    goto  name  ;
+goto-statement:
+   goto   name   ;
 
-**Defined elsewhere** - -* [*name*](09-lexical-structure.md#names) - **Constraints** The name in a `goto` statement must be that of a [named label](#labeled-statements) located @@ -763,21 +821,27 @@ done: } ``` -###The `continue` Statement +### The `continue` Statement **Syntax** -
-  continue-statement:
-    continue   breakout-levelopt  ;
+
 
-**Defined elsewhere**
+
+continue-statement:
+   continue   breakout-levelopt   ;
 
-* [*integer-literal*](09-lexical-structure.md#integer-literals)
+breakout-level:
+   integer-literal
+   (   breakout-level   )
+
**Constraints** @@ -796,9 +860,11 @@ number `1` and containing statements having levels increasing by 1. A `continue` statement terminates the execution of one or more enclosing [iteration](#iteration-statements) or [`switch`](#the-switch-statement) statements, up to the specified level. If the statement at the *breakout-level* is an iteration statement, -the next iteration (if any) of the next innermost enclosing iteration or switch statement is started. +the next iteration (if any) of the iteration statement is started. If that statement is a `for` statement and it has a *for-end-of-loop*, its -end-of-loop expression group for the current iteration is evaluated first. If +end-of-loop expression group for the current iteration is evaluated first. If it +is a `switch` statement, a warning is emitted and the behavior is the same as a +[`break` statement](#the-break-statement) at the same *breakout-level*. If *breakout-level* is omitted, a level of 1 is assumed. A `continue` statement may break out of a construct that is fully @@ -815,19 +881,20 @@ for ($i = 1; $i <= 5; ++$i) } ``` -###The `break` Statement +### The `break` Statement **Syntax** + +
-  break-statement:
-    break  breakout-levelopt  ;
+break-statement:
+   break   breakout-levelopt   ;
 
-**Defined elsewhere** - -* [*breakout-level*](#the-continue-statement) - **Constraints** The breakout level must be greater than zero, and it must not exceed the level of @@ -880,19 +947,20 @@ for ($i = 10; $i <= 40; $i +=10) } ``` -###The `return` Statement +### The `return` Statement **Syntax** + +
-  return-statement:
-    return  expressionopt  ;
+return-statement:
+   return   expressionopt   ;
 
-**Defined elsewhere** - -* [*expression*](10-expressions.md#general-6) - **Semantics** A `return` statement from within a function terminates the execution of @@ -903,6 +971,10 @@ by value or byRef. If *expression* is omitted the value `NULL` is used. If execution flows into the closing brace (`}`) of a function, `return NULL;` is implied. +Explicit `return` statements with *expression* given are not permitted within a +function with a `void` [return type](13-functions.md#return-typing) and cause +a fatal error. + A function may have any number of `return` statements, whose returned values may have different types. @@ -921,7 +993,8 @@ If an uncaught exception exists when a finally-block is executed, if that finally-block executes a `return` statement, the uncaught exception is discarded. -A `return` statement may occur in a script outside any function. In an [included file](10-expressions.md#general-6), +A `return` statement may occur in a script outside any function. In an +[included file](10-expressions.md#script-inclusion-operators), such statement terminates processing of that script file and returns control to the including file. If *expression* is present, that is the value returned; otherwise, the value `NULL` is returned. If @@ -988,19 +1061,20 @@ the cases of `return $a++;` and `return ++$a;`, it is obvious what value must be returned in each case, but if `$a` is a variable local to the enclosing function, `$a` need not actually be incremented. -###The `throw` Statement +### The `throw` Statement **Syntax** + +
-  throw-statement:
-    throw  expression  ;
+throw-statement:
+   throw   expression   ;
 
-**Defined elsewhere** - -* [*expression*](10-expressions.md#general-6) - **Constraints** The type of *expression* must be [Exception](17-exception-handling.md#class-exception) or a subclass of that @@ -1028,38 +1102,56 @@ class MyException extends Exception { ... } throw new MyException; ``` -##The `try` Statement +## The `try` Statement **Syntax** -
-  try-statement:
-    try  compound-statement   catch-clauses
-    try  compound-statement   finally-clause
-    try  compound-statement   catch-clauses   finally-clause
+
+
+
+try-statement:
+   try   compound-statement   catch-clauses
+   try   compound-statement   finally-clause
+   try   compound-statement   catch-clauses   finally-clause
+
+catch-clauses:
+   catch-clause
+   catch-clauses   catch-clause
 
-**Defined elsewhere**
+catch-clause:
+   catch   (   catch-name-list   variable-name   )   compound-statement
 
-* [*compound-statement*](#compound-statements)
-* [*variable-name*](09-lexical-structure.md#names)
-* [*qualified-name*](09-lexical-structure.md#names)
+catch-name-list:
+   qualified-name
+   catch-name-list   |   qualified-name
+
+finally-clause:
+   finally   compound-statement
+
**Constraints** -In a *catch-clause*, *parameter-declaration-list* must contain only one -parameter, and its type must be [`Exception`](17-exception-handling.md#class-exception) or a type derived from -that class, and that parameter must not be passed byRef. +Each *qualified-name* inside a *catch-name-list* must name a type derivated from +[`Exception`](17-exception-handling.md#class-exception). **Semantics** @@ -1080,9 +1172,10 @@ try-block that encloses the call to the current function. This process continues until a catch-block is found that can handle the current exception. -The matching is done by considering the class specified by *qualified-name* -and comparing it to the type of the exception. If the exception is an -[instance of](10-expressions.md#instanceof-operator) this class then the clause matches. +The matching is done by considering the classes specified by *qualified-name* +in *catch-name-list* and comparing it to the type of the exception. If the +exception is an [instance of](10-expressions.md#instanceof-operator) one of +the specified classes then the clause matches. If a matching catch-block is located, the Engine prepares to transfer control to the first statement of that catch-block. However, before @@ -1129,29 +1222,34 @@ catch (DeviceException $dve) { ... } finally { ... } ``` -##The `declare` Statement +## The `declare` Statement **Syntax** -
-  declare-statement:
-    declare  (  declare-directive  )  statement
-    declare  (  declare-directive  )  :  statement-list  enddeclare  ;
-    declare  (  declare-directive  )  ;
+
 
+
+declare-statement:
+   declare   (   declare-directive   )   statement
+   declare   (   declare-directive   )   :   statement-list   enddeclare   ;
+   declare   (   declare-directive   )   ;
+
+declare-directive:
+   ticks   =   literal
+   encoding   =   literal
+   strict_types   =   literal
 
-**Defined elsewhere** - -* [*statement*](#general) -* [*statement-list*](#compound-statements) -* [*literal*](09-lexical-structure.md#literals) - **Constraints** The literal for *ticks* must designate a value that is, or can be converted, to an @@ -1205,3 +1303,106 @@ declare(ticks = 1) { ... } declare(encoding = 'ISO-8859-1'); // Latin-1 Western European declare(encoding = 'ISO-8859-5'); // Latin/Cyrillic ``` + +## The `echo` Statement + +**Syntax** + + + +
+echo-statement:
+   echo   expression-list   ;
+
+expression-list:
+   expression
+   expression-list   ,   expression
+
+ +**Constraints** + +The *expression* value must be +[convertable to a string](08-conversions.md#converting-to-string-type). +In particular, it should not be an array and if it is an object, it must implement +a [`__toString` method](14-classes.md#method-__tostring). + +**Semantics** + +After converting each of its *expression*s' values to strings, if +necessary, `echo` concatenates them in order given, and writes the +resulting string to [`STDOUT`](06-constants.md#core-predefined-constants). Unlike [`print`](10-expressions.md#print-expression), it does +not produce a result. + +See also: [double quoted strings](09-lexical-structure.md#double-quoted-string-literals) and +[heredoc documents](09-lexical-structure.md#heredoc-string-literals), [conversion to string](08-conversions.md#converting-to-string-type). + +**Examples** + +```PHP +$v1 = TRUE; +$v2 = 123; +echo '>>' . $v1 . '|' . $v2 . "<<\n"; // outputs ">>1|123<<" +echo '>>' , $v1 , '|' , $v2 , "<<\n"; // outputs ">>1|123<<" +echo ('>>' . $v1 . '|' . $v2 . "<<\n"); // outputs ">>1|123<<" +$v3 = "qqq{$v2}zzz"; +echo "$v3\n"; +``` + +## The `unset` Statement + +**Syntax** + + + +
+unset-statement:
+   unset   (   variable-list   ,opt   )   ;
+
+ +**Semantics** + +This statement [unsets](07-variables.md#general) the variables designated by each +*variable* in *variable-list*. No value is returned. An +attempt to unset a non-existent variable (such as a non-existent element +in an array) is ignored. + +When called from inside a function, this statement behaves, as follows: + +- For a variable declared `global` in that function, `unset` removes the + alias to that variable from the scope of the current call to that + function. The global variable remains set. + (To unset the global variable, use unset on the corresponding + [`$GLOBALS`](07-variables.md#predefined-variables) array entry. +- For a variable passed byRef to that function, `unset` removes the + alias to that variable from the scope of the current call to that + function. Once the function returns, the passed-in argument variable + is still set. +- For a variable declared static in that function, `unset` removes the + alias to that variable from the scope of the current call to that + function. In subsequent calls to that function, the static variable + is still set and retains its value from call to call. + +Any visible instance property may be unset, in which case, the property +is removed from that instance. + +If this statement is used with an expression that designates a [dynamic +property](14-classes.md#dynamic-members), then if the class of that property has an [`__unset` +method](14-classes.md#method-__unset), that method is called. + +**Examples** + +```PHP +unset($v); +unset($v1, $v2, $v3); +unset($x->m); // if m is a dynamic property, $x->__unset("m") is called +``` diff --git a/spec/12-arrays.md b/spec/12-arrays.md index d027f19b..2021c48c 100644 --- a/spec/12-arrays.md +++ b/spec/12-arrays.md @@ -1,6 +1,6 @@ -#Arrays +# Arrays -##General +## General An [*array*](http://php.net/manual/language.types.array.php) is a data structure that contains a collection of zero or more *elements*. An array element can have any type (which allows for arrays of arrays) @@ -14,7 +14,7 @@ elements in the map is the order in which the elements were *inserted* into the array. An element is said to *exist* once it has been inserted into the array with a corresponding key. An array is *extended* by initializing a previously non-existent element using a new key. Elements -can be *removed* from an array via the intrinsic [`unset`](10-expressions.md#unset). +can be *removed* from an array via the [`unset` statement](11-statements.md#the-unset-statement). The [`foreach` statement](11-statements.md#the-foreach-statement) can be used to iterate over the collection of elements in an array in order. This statement also provides a way to access the key and value @@ -31,14 +31,12 @@ Note: Arrays in PHP are different from arrays in several other languages. Specifically, in PHP, array elements need not have the same type, the subscript index need not be an integer, and there is no concept of consecutive elements of the array occupying physically adjacent memory locations). -##Array Creation and Initialization +## Array Creation and Initialization -An 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). +An array is created and initialized using the +[array-creation operator](10-expressions.md#array-creation-operator): -##Element Access and Insertion +## Element Access and Insertion The value (and possibly the type) of an existing element is changed, and new elements are inserted, using the subscript operator [`[]`](10-expressions.md#subscript-operator). - - diff --git a/spec/13-functions.md b/spec/13-functions.md index 2d971d1e..75c48d93 100644 --- a/spec/13-functions.md +++ b/spec/13-functions.md @@ -1,6 +1,6 @@ -#Functions +# Functions -##General +## General When a function is called, information may be passed to it by the caller via an *argument list*, which contains one or more *argument @@ -17,7 +17,7 @@ case of an *outer function*, and an *inner function* defined within it. Until the outer function is called at least once, its inner function does not exist. Even if the outer function is called, if its runtime logic bypasses the definition of the inner function, that inner function still -does not exist. The conditionally defined function comes into existance when +does not exist. The conditionally defined function comes into existence when the execution flow reaches the point where the function is defined. Any function containing [`yield`](10-expressions.md#yield-operator) is a *generator function*. @@ -39,62 +39,111 @@ ucf2(); // now cf2 exists cf2(); // so we can call it ``` -##Function Calls +## Function Calls A function is called via the function-call operator [`()`](10-expressions.md#function-call-operator). -##Function Definitions +## Function Definitions **Syntax** -
-  function-definition:
-    function-definition-header   compound-statement
+
+
+
+function-definition:
+   function-definition-header   compound-statement
+
+function-definition-header:
+   function   &opt   name   (   parameter-declaration-listopt   )   return-typeopt
+
+parameter-declaration-list:
+   simple-parameter-declaration-list
+   variadic-declaration-list
+
+simple-parameter-declaration-list:
+   parameter-declaration
+   parameter-declaration-list   ,   parameter-declaration
 
-**Defined elsewhere**
+variadic-declaration-list:
+   simple-parameter-declaration-list   ,   variadic-parameter
+   variadic-parameter
 
-* [*constant-expression*](10-expressions.md#constant-expressions)
-* [*qualified-name*](09-lexical-structure.md#names)
+parameter-declaration:
+   type-declarationopt   &opt   variable-name   default-argument-specifieropt
+
+variadic-parameter:
+   type-declarationopt   &opt   ...   variable-name
+
+return-type:
+   :   type-declaration
+   :   void
+
+type-declaration:
+   ?opt   base-type-declaration
+
+base-type-declaration:
+   array
+   callable
+   iterable
+   scalar-type
+   qualified-name
+
+scalar-type:
+   bool
+   float
+   int
+   string
+
+default-argument-specifier:
+   =   constant-expression
+
**Constraints** @@ -152,10 +201,12 @@ By default, a parameter will accept an argument of any type. However, by specifying a *type-declaration*, the types of argument accepted can be restricted. By specifying `array`, only an argument of the `array` type is accepted. By specifying `callable`, only an argument designating a -function (see below) is accepted. By specifying *qualified-name*, only an instance -of a class having that type, or being derived from that type, are -accepted, or only an instance of a class that implements that interface -type directly or indirectly is accepted. The check is the same as for [`instanceof` operator](10-expressions.md#instanceof-operator). +function (see below) is accepted. By specifying `iterable`, only an argument that +is of type `array` or an object implementing the `Traversable` interface is accepted. +By specifying *qualified-name*, only an instance of a class having that type, +or being derived from that type, are accepted, or only an instance of a class that +implements that interface type directly or indirectly is accepted. The check is the +same as for [`instanceof` operator](10-expressions.md#instanceof-operator). `callable` pseudo-type accepts the following: * A string value containing the name of a function defined at the moment of the call. @@ -173,7 +224,9 @@ Parameters typed with *scalar-type* are accepted if they pass the type check for as [described below](#type-check-modes). Once the checks have been passed, the parameter types are always of the scalar type specified (or `NULL` if `NULL` is allowed). -If a parameter has a type declaration, `NULL` is not accepted unless it has a default value that evaluates to `NULL`. +If a parameter has a type declaration, `NULL` is not accepted unless the +type is nullable. A type is nullable if it is prefixed with `?` or if the +parameter has a default value that evaluates to `NULL`. The default value for a typed parameter must be of the type specified, or `NULL`, and conversion is not be performed for defaults, regardless of the mode. @@ -185,6 +238,9 @@ be compatible with the defined type, using the same rules as for parameter type are not allowed for typed returns. If the value of the [`return` statement](11-statements.md#the-return-statement) does not pass the type check, a fatal error is produced. +The `void` type is a special type that can only be used as a return type, and +not in other contexts. It has no effect at runtime, see the [`return` statement](11-statements.md#the-return-statement). + ## Type check modes The type checking can be performed in two modes, strict and coercive (default). @@ -245,14 +301,14 @@ echo substr("123", "1"); // fatal error ``` -##Variable Functions +## Variable Functions If a variable name is followed by the function-call operator [`()`](10-expressions.md#function-call-operator), and the value of that variable designates the function currently defined and visible (see description above), that function will be executed. If the variable does not designate a function or this function can not be called, a fatal error is produced. -##Anonymous Functions +## Anonymous Functions An *anonymous function*, also known as a *closure*, is a function defined with no name. As such, it must be defined in the context of an diff --git a/spec/14-classes.md b/spec/14-classes.md index 95019155..6a8639d2 100644 --- a/spec/14-classes.md +++ b/spec/14-classes.md @@ -1,6 +1,6 @@ -#Classes +# Classes -##General +## General A class is a type that may contain zero or more explicitly declared *members*, which can be any combination of [*class constants*](#constants); @@ -54,29 +54,51 @@ object. As such, assignment of a handle does not copy the object itself. While PHP supports *anonymous class types*, such a type cannot be declared using [*class-declaration*](#class-declarations). Instead, it must be specified at the time of instantiation; that is, as part of an [*object-creation-expression*](10-expressions.md#the-new-operator). -##Class Declarations +## Class Declarations **Syntax** -
-  class-declaration:
-    class-modifieropt  class  name   class-base-clauseopt  class-interface-clauseopt   {   class-member-declarationsopt }
+
+
+
+class-declaration:
+   class-modifiersopt   class   name   class-base-clauseopt   class-interface-clauseopt   {   class-member-declarationsopt   }
 
-**Defined elsewhere**
+class-modifiers:
+   class-modifier
+   class-modifiers   class-modifier
 
-* [*class-member-declarations*](#class-members)
+class-modifier:
+   abstract
+   final
+   readonly
+
+class-base-clause:
+   extends   qualified-name
+
+class-interface-clause:
+   implements   qualified-name
+   class-interface-clause   ,   qualified-name
+
**Constraints** @@ -193,32 +215,37 @@ class MyList implements MyCollection } ``` -##Class Members +## Class Members **Syntax** -
-  class-member-declarations:
-    class-member-declaration
-    class-member-declarations   class-member-declaration
-
-   class-member-declaration:
-     const-declaration
-     property-declaration
-     method-declaration
-     constructor-declaration
-     destructor-declaration
-     trait-use-clause
-
+ -* [*const-declaration*](#constants) -* [*property-declaration*](#properties) -* [*method-declaration*](#methods) -* [*constructor-declaration*](#constructors) -* [*destructor-declaration*](#destructors) -* [*trait-use-clause*](16-traits.md#trait-uses) +
+class-member-declarations:
+   class-member-declaration
+   class-member-declarations   class-member-declaration
+
+class-member-declaration:
+   class-const-declaration
+   property-declaration
+   method-declaration
+   constructor-declaration
+   destructor-declaration
+   trait-use-clause
+
**Semantics** @@ -248,14 +275,16 @@ Methods and properties can either be *static* or *instance* members. A static member is declared using `static`. An instance member is one that is not static. The name of a static or instance member can never be used on its own; it must always be used as the right-hand operand of the -[scope resolution operator](10-expressions.md#scope-resolution-operator) or the [member selection operator](10-expressions.md#member-selection-operator). +[scope resolution operator](10-expressions.md#scope-resolution-operator) +or the [member access operator](10-expressions.md#member-access-operator). Each instance of a class contains its own, unique set of instance properties of that class. An instance member is accessed via the -[`->` operator](10-expressions.md#member-selection-operator). In contrast, a static property designates -exactly one VSlot for its class, which does not belong to any instance, -per se. A static property exists whether or not any instances of that -class exist. A static member is accessed via the [`::` operator](10-expressions.md#scope-resolution-operator). +[`->` operator](10-expressions.md#member-access-operator). In contrast, +a static property designates exactly one VSlot for its class, which does +not belong to any instance, per se. A static property exists whether or +not any instances of that class exist. A static member is accessed via +the [`::` operator](10-expressions.md#scope-resolution-operator). When any instance method operates on a given instance of a class, within that method that object can be accessed via [`$this`](10-expressions.md#general-1). As a @@ -298,7 +327,7 @@ $cName = 'Point'; echo "Point count = " . $cName::getPointCount() . "\n"; ``` -##Dynamic Members +## Dynamic Members Initially, the instance only has properties that are declared explicitly in its class's definition. However, properties can be @@ -342,7 +371,7 @@ the instance method [`__get`](#method-__get), which treats that name as designating a dynamic property of the instance being operated on, and gets its value. In the case of the call to the intrinsic [`isset`](10-expressions.md#isset), this generates a call to the instance method [`__isset`](#method-__isset), -while a call to the intrinsic [`unset`](10-expressions.md#unset) generates a +while a use of the [`unset` statement](11-statements.md#the-unset-statement) generates a call to the instance method [`__unset`](#method-__unset). By defining these four special methods, the implementer of a class can control how dynamic properties are handled. @@ -380,35 +409,56 @@ and the call to `sMethod` is treated as if it were Widget::__callStatic('sMethod', array(NULL, 1.234)) ``` -##Constants +## Constants **Syntax** + +
-  const-declaration:
-    const  name  =  constant-expression   ;
-
+const-declaration: + const const-elements ; -**Defined elsewhere** +class-const-declaration: + visibility-modifieropt const const-elements ; -* [*name*](09-lexical-structure.md#names) -* [*constant-expression*](10-expressions.md#constant-expressions) +const-elements: + const-element + const-elements , const-element + +const-element: + name = constant-expression +
**Constraints:** -A *const-declaration* must only appear at the top level of a script, be -a *class constant* (inside a [*class-definition*](#class-members) or be an -[*interface constant*](15-interfaces.md#interface-members). +A *const-declaration* must only appear at the top level of a script, and +must not redefine an existing [c-constant](06-constants.md#general). -A *const-declaration* must not redefine an existing [c-constant](06-constants.md#general). +A *class-const-declaration* must be inside a [*class-declaration*](#class-members) or +[*interface-declaration*](15-interfaces.md#interface-members). -A class constant must not have visibility specifier or `static` specifier. +A class constant must not have a `static` specifier. **Semantics:** A *const-declaration* defines a c-constant. -All class constants have public visibility. +If *visibility-modifier* for a class constant is omitted, `public` is assumed. +The *visibility-modifier* applies to all constants defined in the *const-elements* list. All constants are implicitly `static`. @@ -421,52 +471,85 @@ const LOWER = MIN_VAL; class Automobile { const DEFAULT_COLOR = "white"; + public DEFAULT_BRAND = 'benz'; + protected WHEEL_NUM = 4; + private PRIVATE_CONST = 'const'; ... } $col = Automobile::DEFAULT_COLOR; ``` -##Properties +## Properties **Syntax** + +
-  property-declaration:
-    property-modifier   variable-name   property-initializeropt  ;
+property-declaration:
+   property-modifier   property-elements   ;
 
-  property-modifier:
-    var
-    visibility-modifier   static-modifieropt
-    static-modifier   visibility-modifieropt
+property-modifier:
+   var
+   visibility-modifier   static-modifieropt
+   static-modifier   visibility-modifieropt
 
-  visibility-modifier:
-    public
-    protected
-    private
+visibility-modifier:
+   public
+   protected
+   private
 
-  static-modifier:
-    static
+static-modifier:
+   static
 
-  property-initializer:
-    =  constant-expression
-
+property-elements: + property-element + property-elements property-element -**Defined elsewhere** +property-element: + variable-name property-initializeropt ; -* [*variable-name*](09-lexical-structure.md#names) -* [*constant-expression*](10-expressions.md#constant-expressions) +property-initializer: + = constant-expression +
**Semantics** -A *property-declaration* defines an instance or static property. +A *property-declaration* defines one or more instance or static properties. If [*visibility-modifier*](#general) is omitted, `public` is assumed. The `var` modifier -implies public visibility. The `static` modifier defines the member as [static member](#class-members). +implies public visibility. The `static` modifier defines the member as a [static member](#class-members). The *property-initializer* for instance properties is applied prior to the class's [constructor](#constructors) being called. -An instance property that is visible may be [`unset`](10-expressions.md#unset), in which +An instance property that is visible may be [`unset`](11-statements.md#the-unset-statement), in which case, the property is actually removed from that instance. **Examples** @@ -483,31 +566,39 @@ class Point } ``` -##Methods +## Methods **Syntax** -
-  method-declaration:
-    method-modifiersopt   function-definition
-    method-modifiers   function-definition-header  ;
-
-  method-modifiers:
-    method-modifier
-    method-modifiers   method-modifier
-
-  method-modifier:
-    visibility-modifier
-    static-modifier
-    class-modifier
-
+ + +
+method-declaration:
+   method-modifiersopt   function-definition
+   method-modifiers   function-definition-header   ;
+
+method-modifiers:
+   method-modifier
+   method-modifiers   method-modifier
+
+method-modifier:
+   visibility-modifier
+   static-modifier
+   class-modifier
+
**Constraints** @@ -541,22 +632,20 @@ If *visibility-modifier* is omitted, `public` is assumed. See [class members](#class-members) for examples of instance and static methods. See [class declarations](#class-declarations) for examples of abstract methods and their subsequent definitions. -##Constructors +## Constructors **Syntax** -
-  constructor-declaration:
-    method-modifiers  function &opt   __construct  (  parameter-declaration-listopt  )  compound-statement
+
 
+
+constructor-declaration:
+   method-modifiers   function   &opt   __construct   (   parameter-declaration-listopt   )   compound-statement
 
-**Defined elsewhere** - -* [*method-modifiers*](#methods) -* [*parameter-declaration-list*](13-functions.md#function-definitions) -* [*compound-statement*](11-statements.md#compound-statements) - **Constraints** An overriding constructor in a derived class must have the same or a @@ -629,20 +718,20 @@ class MyRangeException extends Exception } ``` -##Destructors +## Destructors **Syntax** + +
-  destructor-declaration:
-    method-modifiers  function  &opt  __destruct  ( ) compound-statement
+destructor-declaration:
+   method-modifiers   function   &opt   __destruct   (   )   compound-statement
 
-**Defined elsewhere** - -* [*method-modifiers*](#methods) -* [*compound-statement*](11-statements.md#compound-statements) - **Constraints** *method-modifiers* can not contain `static`. @@ -673,7 +762,7 @@ inhibits destructor calls from derived classes. See [constructors section](#constructors) for an example of a constructor and destructor. -##Inheritance +## Inheritance When a class `extends` another class it can *override* members of the parent class by declaring a member with the same name. Only properties and methods can be overridden. @@ -689,9 +778,9 @@ and the overriding method belonged to an implementation. If an implemented method is overridden with an incompatible method, a non-fatal error is issued, however the override is still accepted by the engine. The use of incompatible overrides is not recommended. -##Methods with Special Semantics +## Methods with Special Semantics -###General +### General If a class contains a definition for a method having one of the following names, that method must have the prescribed visibility, @@ -722,7 +811,7 @@ Note that while syntax definitions below use the [non-abstract syntax](#methods) like any methods, can be declared `abstract`. In this case the definition does not actually define a special method but defines that an overriding concrete class must declare one. Nevertheless, the constraints on special methods must still be followed in such definitions. -###Method `__call` +### Method `__call` **Syntax** @@ -730,13 +819,6 @@ an overriding concrete class must declare one. Nevertheless, the constraints on method-modifiers function __call ( $name , $arguments ) return-typeopt compound-statement
-**Defined elsewhere** - -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) -* [*return-type*](13-functions.md#function-definitions) -* [*return-type*](13-functions.md#function-definitions) - **Constraints** The method can not be static and must have public visibility. @@ -750,7 +832,8 @@ designated by `$name` using the arguments specified by the elements of the array designated by `$arguments`. It can return any value deemed appropriate. -Typically, `__call` is called implicitly, when the [`->` operator](10-expressions.md#member-selection-operator) +Typically, `__call` is called implicitly, when the +[`->` operator](10-expressions.md#member-call-operator) is used to call an instance method that is not visible. While `__call` can be called explicitly, the two scenarios do not @@ -785,7 +868,7 @@ $obj = new Widget; $obj->iMethod(10, TRUE, "abc"); // $obj->__call('iMethod', array(...)) ``` -###Method `__callStatic` +### Method `__callStatic` **Syntax** @@ -793,13 +876,6 @@ $obj->iMethod(10, TRUE, "abc"); // $obj->__call('iMethod', array(...)) method-modifiers function __callStatic ( $name , $arguments ) return-typeopt compound-statement
-**Defined elsewhere** - -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) -* [*return-type*](13-functions.md#function-definitions) -* [*return-type*](13-functions.md#function-definitions) - **Constraints** The *method-modifiers* must contain `static` and must define public visibility. @@ -848,7 +924,7 @@ class Widget Widget::sMethod(NULL, 1.234); // Widget::__callStatic('sMethod', array(...)) ``` -###Method `__clone` +### Method `__clone` **Syntax** @@ -856,11 +932,6 @@ Widget::sMethod(NULL, 1.234); // Widget::__callStatic('sMethod', array(...)) method-modifiers function __clone ( ) compound-statement
-**Defined elsewhere** - -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) - **Constraints** The *method-modifiers* must not contain `static` and must define public visibility. @@ -938,7 +1009,7 @@ $p1 = new Point; // created using the constructor $p2 = clone $p1; // created by cloning ``` -###Method `__debugInfo` +### Method `__debugInfo` **Syntax** @@ -946,11 +1017,6 @@ $p2 = clone $p1; // created by cloning method-modifiers function __debugInfo ( ) compound-statement
-**Defined elsewhere** - -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) - **Constraints** The *method-modifiers* must not contain `static` and must define public visibility. @@ -992,7 +1058,7 @@ object(File)#1 { */ ``` -###Method `__get` +### Method `__get` **Syntax** @@ -1000,13 +1066,6 @@ object(File)#1 { method-modifiers function &opt __get ( $name ) return-typeopt compound-statement
-**Defined elsewhere** - -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) -* [*return-type*](13-functions.md#function-definitions) -* [*return-type*](13-functions.md#function-definitions) - **Constraints** The *method-modifiers* must not contain `static` and must define public visibility. @@ -1016,7 +1075,8 @@ The *method-modifiers* must not contain `static` and must define public visibili This instance method gets the value of the [dynamic property](#dynamic-members) designated by `$name`. It is up to the implementor to define the return value. -Typically, `__get` is called implicitly, when the [`->` operator](10-expressions.md#member-selection-operator) +Typically, `__get` is called implicitly, when the +[`->` operator](10-expressions.md#member-access-operator) is used in a non-lvalue context and the named property is not visible. While `__get` can be called explicitly, the two scenarios do not @@ -1090,7 +1150,7 @@ While the [*name*](09-lexical-structure.md#names) source token has a prescribed restrictions on the spelling of the dynamic property name designated by `$name`. Any source character is allowed here. -###Method `__invoke` +### Method `__invoke` **Syntax** @@ -1098,13 +1158,6 @@ restrictions on the spelling of the dynamic property name designated by method-modifiers function __invoke ( parameter-declaration-listopt ) return-typeopt compound-statement
-**Defined elsewhere** - -* [*parameter-declaration-list*](13-functions.md#function-definitions) -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) -* [*return-type*](13-functions.md#function-definitions) - **Constraints** The *method-modifiers* must not contain `static` and must define public visibility. @@ -1136,7 +1189,7 @@ is_callable($c) // returns TRUE $r = $c(123); // becomes $r = $c->__invoke(123); ``` -###Method `__isset` +### Method `__isset` **Syntax** @@ -1144,12 +1197,6 @@ $r = $c(123); // becomes $r = $c->__invoke(123); method-modifiers function __isset ( $name ) return-typeopt compound-statement
-**Defined elsewhere** - -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) -* [*return-type*](13-functions.md#function-definitions) - **Constraints** The *method-modifiers* must not contain `static` and must define public visibility. @@ -1158,7 +1205,7 @@ The *method-modifiers* must not contain `static` and must define public visibili If the [dynamic property](#dynamic-members) designated by `$name` exists, this instance method returns `TRUE`; otherwise, `FALSE` is returned. The speficis of -how existance of the dynamic property is determined is left to the implementor of the method. +how existence of the dynamic property is determined is left to the implementor of the method. Typically, `__isset` is called implicitly, when the intrinsic [`isset`](10-expressions.md#isset) or intrinsic [`empty`](10-expressions.md#empty) is called with an argument that designates @@ -1199,7 +1246,7 @@ class Point See the Implementation Notes for [`__get`](#method-__get). -###Method `__set` +### Method `__set` **Syntax** @@ -1207,12 +1254,6 @@ See the Implementation Notes for [`__get`](#method-__get). method-modifiers function __set ( $name , $value ) return-typeopt compound-statement
-**Defined elsewhere** - -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) -* [*return-type*](13-functions.md#function-definitions) - **Constraints** The *method-modifiers* must not contain `static` and must define public visibility. @@ -1222,7 +1263,8 @@ The *method-modifiers* must not contain `static` and must define public visibili This instance method sets the value of the [dynamic property](#dynamic-members) designated by `$name` to `$value`. No value is expected to be returned. -Typically, `__set` is called implicitly, when the [`->` operator](10-expressions.md#member-selection-operator) +Typically, `__set` is called implicitly, when the +[`->` operator](10-expressions.md#member-access-operator) is used in a modifiable lvalue context and the named property is not visible. @@ -1271,7 +1313,7 @@ $p->thing = new X; // set dynamic property "thing" to instance with destructor See the Implementation Notes for [`__get`](#method-__get). -###Method `__set_state` +### Method `__set_state` **Syntax** @@ -1279,12 +1321,6 @@ See the Implementation Notes for [`__get`](#method-__get). method-modifiers function __set_state ( array $properties ) return-typeopt compound-statement
-**Defined elsewhere** - -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) -* [*return-type*](13-functions.md#function-definitions) - **Constraints** The *method-modifiers* must contain `static` and must define public visibility. @@ -1393,7 +1429,7 @@ eval('$z = ' . $v . ";"); var_dump($z); ``` -###Method `__sleep` +### Method `__sleep` **Syntax** @@ -1401,12 +1437,6 @@ var_dump($z); method-modifiers function __sleep ( ) return-typeopt compound-statement
-**Defined elsewhere** - -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) -* [*return-type*](13-functions.md#function-definitions) - **Constraints** The *method-modifiers* must not contain `static` and must define public visibility. @@ -1477,7 +1507,7 @@ $s = serialize($p); // serialize Point(-1,0) $v = unserialize($s); // unserialize Point(-1,0) ``` -###Method `__toString` +### Method `__toString` **Syntax** @@ -1485,12 +1515,6 @@ $v = unserialize($s); // unserialize Point(-1,0) method-modifiers function __toString ( ) return-typeopt compound-statement
-**Defined elsewhere** - -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) -* [*return-type*](13-functions.md#function-definitions) - **Constraints** The *method-modifiers* must not contain `static` and must define public visibility. @@ -1543,7 +1567,7 @@ class MyRangeException extends Exception } ``` -###Method `__unset` +### Method `__unset` **Syntax** @@ -1551,12 +1575,6 @@ class MyRangeException extends Exception method-modifiers function __unset ( $name ) return-typeopt compound-statement
-**Defined elsewhere** - -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) -* [*return-type*](13-functions.md#function-definitions) - **Constraints** The *method-modifiers* must not contain `static` and must define public visibility. @@ -1567,7 +1585,7 @@ If the [dynamic property](#dynamic-members) designated by `$name` exists, it is removed by this instance method; otherwise, the call has no effect. No value is expected to be returned. -Typically, `__unset` is called implicitly, when the intrinsic [`unset`](10-expressions.md#unset) +Typically, `__unset` is called implicitly, when the [`unset` statement](11-statements.md#the-unset-statement) is called with an argument that designates a property that is not visible. @@ -1606,7 +1624,7 @@ class Point See the Implementation Notes for [`__get`](#method-__get). -###Method `__wakeup` +### Method `__wakeup` **Syntax** @@ -1614,12 +1632,6 @@ See the Implementation Notes for [`__get`](#method-__get). method-modifiers function __wakeup ( ) return-typeopt compound-statement
-**Defined elsewhere** - -* [*compound-statement*](11-statements.md#compound-statements) -* [*method-modifiers*](#methods) -* [*return-type*](13-functions.md#function-definitions) - **Constraints** The *method-modifiers* must not contain `static` and must define public visibility. @@ -1650,7 +1662,7 @@ by `__wakeup` when that `Point` is unserialized. This means that See [`__sleep`](#method-__sleep). -##Serialization +## Serialization In PHP, variables can be converted into some external form suitable for use in file storage or inter-program communication. The process of @@ -1804,11 +1816,11 @@ $s = serialize($cp); $v = unserialize($s); ``` -Function `unserialize` takes an optional second argument, which specifies an array of trusted class names as strings. Objects found in the data stream whose type name is not in this trusted name list are converted to objects of type [`__PHP_Incomplete_Class`](#class-__PHP_Incomplete_Class). +Function `unserialize` takes an optional second argument, which specifies an array of trusted class names as strings. Objects found in the data stream whose type name is not in this trusted name list are converted to objects of type [`__PHP_Incomplete_Class`](#class-__php_incomplete_class). Any attempt to serialize an object having an anonymous class type results in an instance of type `Exception` being thrown. -##Predefined Classes +## Predefined Classes ### Class `Closure` @@ -1920,7 +1932,7 @@ case, the `Closure` object is empty. Closure objects can not be serialized or unserialized. -###Class `Generator` +### Class `Generator` This class supports the [`yield` operator](10-expressions.md#yield-operator). This class cannot be instantiated directly. It is defined, as follows: @@ -1954,7 +1966,7 @@ Name | Purpose Generator objects can not be serialized or unserialized. -###Class `__PHP_Incomplete_Class` +### Class `__PHP_Incomplete_Class` There are certain circumstances in which a program can generate an instance of this class, which on its own contains no members. One @@ -1995,21 +2007,22 @@ __PHP_Incomplete_Class } ``` -Object of this class can be serialized, however, any attemt to call its method or access its property +Object of this class can be serialized, however, any attempt to call its method or access its property for any other operation except serialization will result in a fatal error. -###Class `stdClass` +### Class `stdClass` This class contains no members. It can be instantiated and used as a base class. An instance of this type is automatically created when a -non-object is [converted to an object](08-conversions.md#converting-to-object-type), or the [member selection -operator](10-expressions.md#member-selection-operator) is applied to `NULL`, `FALSE`, or an empty string. +non-object is [converted to an object](08-conversions.md#converting-to-object-type), +or the [member selection operator](10-expressions.md#member-access-operator) +is applied to `NULL`, `FALSE`, or an empty string. -###Predefined Error Classes +### Predefined Error Classes PHP has a number of predefined classes that are used for error reporting. All these classes extend the base Error class. -####Class `Error` +#### Class `Error` This class is the base class for all internal PHP error exceptions. It is defined, as follows: @@ -2028,15 +2041,11 @@ class Error implements Throwable } ``` -**Defined elsewhere** - -* [`Throwable`](15-interfaces.md#interface-throwable) - For information about the base interface, see [Throwable](15-interfaces.md#interface-throwable). Note that the methods from Throwable are implemented as `final` in the Error class, which means the extending class can not override them. -####Class `ArithmeticError` +#### Class `ArithmeticError` An instance of this class is thrown when an error occurs during certain mathematical operations. It is defined, as follows: @@ -2046,11 +2055,7 @@ class ArithmeticError extends Error } ``` -**Defined elsewhere** - -* [`Error`](#class-error) - -####Class `AssertionError` +#### Class `AssertionError` An instance of this class is thrown when an assertion made via the intrinsic `assert` fails. The class type is defined, as follows: @@ -2060,11 +2065,7 @@ class AssertionError extends Error } ``` -**Defined elsewhere** - -* [`Error`](#class-error) - -####Class `DivisionByZeroError` +#### Class `DivisionByZeroError` An instance of this class is thrown when an attempt is made to divide a number by zero, e.g. when using the remainder operators ([`%`](10-expressions.md#multiplicative-operators) and [`%=`](10-expressions.md#compound-assignment)). Note that this happens only for integer operations, regular float division (`/`) produces a non-fatal error instead. @@ -2076,11 +2077,7 @@ class DivisionByZeroError extends Error } ``` -**Defined elsewhere** - -* [`Error`](#class-error) - -####Class `ParseError` +#### Class `ParseError` An instance of this class is thrown when an error occurs while parsing PHP code (such as when calling the intrinsic [`eval`](10-expressions.md#eval)). It is defined, as follows: @@ -2090,11 +2087,7 @@ class ParseError extends Error } ``` -**Defined elsewhere** - -* [`Error`](#class-error) - -####Class `TypeError` +#### Class `TypeError` An instance of this class is thrown when any of the following occurs: @@ -2110,8 +2103,4 @@ class TypeError extends Error } ``` -**Defined elsewhere** - -* [`Error`](#class-error) - See also class [`Exception`](17-exception-handling.md#class-exception). diff --git a/spec/15-interfaces.md b/spec/15-interfaces.md index 2bc6566f..9e0775a9 100644 --- a/spec/15-interfaces.md +++ b/spec/15-interfaces.md @@ -1,6 +1,6 @@ -#Interfaces +# Interfaces -##General +## General A class can implement a set of capabilities — herein called a *contract* — through what is called an interface. An *interface* is a set @@ -14,23 +14,27 @@ requiring those classes to share a common base class. An interface can extend one or more other interfaces, in which case, it inherits all members from its *base interface(s)*. -##Interface Declarations +## Interface Declarations **Syntax** -
-  interface-declaration:
-    interface   name   interface-base-clauseopt {  interface-member-declarationsopt  }
+
 
-**Defined elsewhere**
+
+interface-declaration:
+   interface   name   interface-base-clauseopt   {   interface-member-declarationsopt   }
 
-* [*name*](09-lexical-structure.md#names)
-* [*interface-member-declarations*](#interface-members)
+interface-base-clause:
+   extends   qualified-name
+   interface-base-clause   ,   qualified-name
+
**Constraints** @@ -78,18 +82,28 @@ processCollection(new MyList(...)); processCollection(new MyQueue(...)); ``` -##Interface Members +## Interface Members **Syntax** + +
-  interface-member-declarations:
-    interface-member-declaration
-    interface-member-declarations   interface-member-declaration
+interface-member-declarations:
+   interface-member-declaration
+   interface-member-declarations   interface-member-declaration
 
-  interface-member-declaration:
-    const-declaration
-    method-declaration
+interface-member-declaration:
+   class-const-declaration
+   method-declaration
 
* [*const-declaration*](14-classes.md#constants) @@ -107,7 +121,11 @@ An interface may contain the following members: - [Methods](#methods) – placeholders for the computations and actions that can be performed by implementers of the interface. -##Constants +## Constants + +**Constraints** + +All constants declared in an interface must be implicitly or explicitly public. **Semantics** @@ -126,7 +144,7 @@ interface MyCollection } ``` -##Methods +## Methods **Constraints** @@ -148,9 +166,9 @@ interface MyCollection } ``` -##Predefined Interfaces +## Predefined Interfaces -###Interface `ArrayAccess` +### Interface `ArrayAccess` This interface allows an instance of an implementing class to be accessed using array-like notation. This interface is defined, as @@ -175,7 +193,7 @@ Name | Purpose `offsetSet` | 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](10-expressions.md#subscript-operator) in a modifiable-lvalue context. `offsetUnset` | This instance method unsets the value having key `$offset`. It returns no value. -###Interface `Iterator` +### Interface `Iterator` This interface allows instances of an implementing class to be treated as a collection. This interface is defined, as follows: @@ -202,7 +220,7 @@ Name | Purpose `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. `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://php.net/manual/iterator.rewind.php) and [`Iterator::next()`](http://php.net/manual/iterator.next.php). -###Interface `IteratorAggregate` +### Interface `IteratorAggregate` This interface allows the creation of an external iterator. This interface is defined, as follows: @@ -220,7 +238,7 @@ Name | Purpose ---- | ------- `getIterator` | This instance method retrieves an iterator, which implements `Iterator` or `Traversable`. It throws an `Exception` on failure. -###Interface `Throwable` +### Interface `Throwable` This type is the base interface for the type of any object that can be thrown via a [throw statement](11-statements.md#the-throw-statement). A user-written class cannot @@ -254,7 +272,7 @@ Name | Purpose `getTrace` | `array`; retrieves the function stack [trace information](17-exception-handling.md#tracing-exceptions) as an array `getTraceAsString` | `string`; retrieves the function stack trace information formatted as a single string in some unspecified format -###Interface `Traversable` +### Interface `Traversable` This interface is intended as the base interface for all traversable classes. This interface is defined, as follows: @@ -267,7 +285,7 @@ interface Traversable This interface has no members. -###Interface `Serializable` +### Interface `Serializable` This interface provides support for custom serialization. It is defined, as follows: diff --git a/spec/16-traits.md b/spec/16-traits.md index ff7b5801..511c350d 100644 --- a/spec/16-traits.md +++ b/spec/16-traits.md @@ -1,6 +1,6 @@ -#Traits +# Traits -##General +## General PHP's class model allows [single inheritance](14-classes.md#general) only with contracts being enforced separately via [interfaces](15-interfaces.md#general). A *trait* can provide @@ -38,33 +38,41 @@ each class using that trait has its own instance of that property. Methods in a trait have full access to all members of any class in which that trait is used. -##Trait Declarations +## Trait Declarations **Syntax** -
-  trait-declaration:
-    trait   name   {   trait-member-declarationsopt   }
-
-  trait-member-declarations:
-    trait-member-declaration
-    trait-member-declarations   trait-member-declaration
-
-  trait-member-declaration:
-    property-declaration
-    method-declaration
-    constructor-declaration
-    destructor-declaration
-    trait-use-clauses
-
+ -* [*property-declaration*](14-classes.md#properties) -* [*method-declaration*](14-classes.md#methods) -* [*constructor-declaration*](14-classes.md#constructors) -* [*destructor-declaration*](14-classes.md#destructors) -* [*trait-use-clauses*](#trait-uses) +
+trait-declaration:
+   trait   name   {   trait-member-declarationsopt   }
+
+trait-member-declarations:
+   trait-member-declaration
+   trait-member-declarations   trait-member-declaration
+
+trait-member-declaration:
+   property-declaration
+   method-declaration
+   constructor-declaration
+   destructor-declaration
+   trait-use-clauses
+
**Semantics** @@ -102,46 +110,73 @@ trait T } ``` -##Trait Uses +## Trait Uses **Syntax** -
-  trait-use-clauses:
-    trait-use-clause
-    trait-use-clauses   trait-use-clause
+
+
+
+trait-use-clauses:
+   trait-use-clause
+   trait-use-clauses   trait-use-clause
 
-**Defined elsewhere**
+trait-use-clause:
+   use   trait-name-list   trait-use-specification
 
-* [*name*](09-lexical-structure.md#names)
-* [*visibility-modifier*](14-classes.md#properties)
+trait-name-list:
+   qualified-name
+   trait-name-list   ,   qualified-name
+
+trait-use-specification:
+   ;
+   {   trait-select-and-alias-clausesopt   }
+
+trait-select-and-alias-clauses:
+   trait-select-and-alias-clause
+   trait-select-and-alias-clauses   trait-select-and-alias-clause
+
+trait-select-and-alias-clause:
+   trait-select-insteadof-clause   ;
+   trait-alias-as-clause   ;
+
+trait-select-insteadof-clause:
+   qualified-name   ::   name   insteadof   trait-name-list
+
+trait-alias-as-clause:
+   name   as   visibility-modifieropt   name
+   name   as   visibility-modifier   nameopt
+
**Constraints** @@ -200,5 +235,3 @@ trait T4 } } ``` - - diff --git a/spec/17-exception-handling.md b/spec/17-exception-handling.md index 2dd91f4e..813a582d 100644 --- a/spec/17-exception-handling.md +++ b/spec/17-exception-handling.md @@ -1,6 +1,6 @@ -#Exception Handling +# Exception Handling -##General +## General An *exception* is some unusual condition in that it is outside the ordinary expected behavior. Examples include dealing with situations in @@ -42,7 +42,7 @@ PHP errors also can be translated to exceptions via the class [`ErrorException`](http://php.net/manual/class.errorexception.php) (which is not part of this specification). -##Class `Exception` +## Class `Exception` Class `Exception` is the base class of all exception types. This class is defined, as follows: @@ -79,7 +79,7 @@ Name | Purpose `__construct` | 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`) `__clone` | Present to inhibit the cloning of exception objects -##Tracing Exceptions +## Tracing Exceptions When an exception is caught, the `get*` functions in class `Exception` provide useful information. If one or more nested function calls were @@ -137,7 +137,7 @@ site have their values recorded in array-argument. See also, library functions [`debug_backtrace`](http://www.php.net/debug_backtrace) and [`debug_print_backtrace`](http://www.php.net/debug_print_backtrace). -##User-Defined Exception Classes +## User-Defined Exception Classes An exception class is defined simply by having it extend class [`Exception`](#class-exception). However, as that class's `__clone` method is declared [`final`](14-classes.md#methods), @@ -148,5 +148,3 @@ parent class' constructor as their first operation to ensure the base-class part of the new object is initialized appropriately. They often also provide an augmented implementation of [`__toString()`](14-classes.md#method-__tostring). - - diff --git a/spec/18-namespaces.md b/spec/18-namespaces.md index 20414058..715dff62 100644 --- a/spec/18-namespaces.md +++ b/spec/18-namespaces.md @@ -1,6 +1,6 @@ -#Namespaces +# Namespaces -##General +## General A problem encountered when managing large projects is that of avoiding the use of the same name in the same scope for different purposes. This @@ -32,21 +32,22 @@ The namespaces `PHP`, `php`, and sub-namespaces beginning with those prefixes are reserved for use by PHP. -##Defining Namespaces +## Defining Namespaces **Syntax** + +
-  namespace-definition:
-    namespace  name  ;
-    namespace  nameopt   compound-statement
+namespace-definition:
+   namespace   namespace-name   ;
+   namespace   namespace-nameopt   compound-statement
 
-**Defined elsewhere** - -* [*name*](09-lexical-structure.md#names) -* [*compound-statement*](11-statements.md#compound-statements) - **Constraints** Except for white space and [*declare-statement*](11-statements.md#the-declare-statement), the @@ -114,51 +115,79 @@ namespace NS3\Sub1; } ``` -##Namespace Use Declarations +## Namespace Use Declarations **Syntax** -
-  namespace-use-declaration:
-    use  namespace-function-or-constopt namespace-use-clauses  ;
-    use  namespace-function-or-const  \opt  namespace-name  \
-       {  namespace-use-group-clauses-1  }  ;
-    use  \opt   namespace-name   \   {  namespace-use-group-clauses-2  }  ;
+
+
+
+namespace-use-declaration:
+   use   namespace-function-or-constopt   namespace-use-clauses   ;
+   use   namespace-function-or-const   \opt   namespace-name   \   {   namespace-use-group-clauses-1   }   ;
+   use   \opt   namespace-name   \   {   namespace-use-group-clauses-2   }   ;
 
-**Defined elsewhere**
+namespace-use-clauses:
+   namespace-use-clause
+   namespace-use-clauses   ,   namespace-use-clause
 
-* [*name*](09-lexical-structure.md#names)
-* [*namespace-name*](09-lexical-structure.md#names)
-* [*qualified-name*](09-lexical-structure.md#names)
+namespace-use-clause:
+   qualified-name   namespace-aliasing-clauseopt
+
+namespace-aliasing-clause:
+   as   name
+
+namespace-function-or-const:
+   function
+   const
+
+namespace-use-group-clauses-1:
+   namespace-use-group-clause-1
+   namespace-use-group-clauses-1   ,   namespace-use-group-clause-1
+
+namespace-use-group-clause-1:
+   namespace-name   namespace-aliasing-clauseopt
+
+namespace-use-group-clauses-2:
+   namespace-use-group-clause-2
+   namespace-use-group-clauses-2   ,   namespace-use-group-clause-2
+
+namespace-use-group-clause-2:
+   namespace-function-or-constopt   namespace-name   namespace-aliasing-clauseopt
+
**Constraints** @@ -260,7 +289,7 @@ namespace a } ``` -##Name Lookup +## Name Lookup When an existing name is used in source code, the Engine must determine how that name is found with respect to namespace lookup. For this diff --git a/spec/19-grammar.md b/spec/19-grammar.md index 2c2bd530..ae4117b8 100644 --- a/spec/19-grammar.md +++ b/spec/19-grammar.md @@ -1,1249 +1,1162 @@ -#Grammar +# Grammar -##General +## General The grammar notation is described in [Grammars section](09-lexical-structure.md#grammars). -##Lexical Grammar - -###General - -
-  input-file::
-    input-element
-    input-file   input-element
-  input-element::
-    comment
-    white-space
-    token
-
- -###Comments +## Lexical Grammar
-  comment::
-    single-line-comment
-    delimited-comment
+input-file::
+   input-element
+   input-file   input-element
+
+input-element::
+   comment
+   white-space
+   token
+
+comment::
+   single-line-comment
+   delimited-comment
+
+single-line-comment::
+   //   input-charactersopt
+   #   input-charactersopt
+
+input-characters::
+   input-character
+   input-characters   input-character
+
+input-character::
+   Any source character except   new-line
+
+new-line::
+   Carriage-return character (0x0D)
+   Line-feed character (0x0A)
+   Carriage-return character (0x0D) followed by line-feed character (0x0A)
+
+delimited-comment::
+   /*   No characters or any source character sequence except */   */
+
+white-space::
+   white-space-character
+   white-space   white-space-character
+
+white-space-character::
+   new-line
+   Space character (0x20)
+   Horizontal-tab character (0x09)
+
+token::
+   variable-name
+   name
+   keyword
+   integer-literal
+   floating-literal
+   string-literal
+   operator-or-punctuator
+
+variable-name::
+   $   name
+
+namespace-name::
+   name
+   namespace-name   \   name
+
+namespace-name-as-a-prefix::
+   \
+   \opt   namespace-name   \
+   namespace   \
+   namespace   \   namespace-name   \
+
+qualified-name::
+   namespace-name-as-a-prefixopt   name
+
+name::
+   name-nondigit
+   name   name-nondigit
+   name   digit
+
+name-nondigit::
+   nondigit
+   one of the characters 0x80–0xff
+
+nondigit:: one of
+   _
+   a   b   c   d   e   f   g   h   i   j   k   l   m
+   n   o   p   q   r   s   t   u   v   w   x   y   z
+   A   B   C   D   E   F   G   H   I   J   K   L   M
+   N   O   P   Q   R   S   T   U   V   W   X   Y   Z
+
+keyword:: one of
+   abstract   and   array   as   break   callable   case   catch   class   clone
+   const   continue   declare   default   die   do   echo   else   elseif   empty
+   enddeclare   endfor   endforeach   endif   endswitch   endwhile   eval   exit
+   extends   final   finally   for   foreach   function   global
+   goto   if   implements   include   include_once   instanceof
+   insteadof   interface   isset   list   namespace   new   or   print   private
+   protected   public   require   require_once   return   static   switch
+   throw   trait   try   unset   use   var   while   xor   yield   yield from
+
+integer-literal::
+   decimal-literal
+   octal-literal
+   hexadecimal-literal
+   binary-literal
+
+decimal-literal::
+   nonzero-digit
+   decimal-literal   digit
+
+octal-literal::
+   0
+   octal-literal   octal-digit
+
+hexadecimal-literal::
+   hexadecimal-prefix   hexadecimal-digit
+   hexadecimal-literal   hexadecimal-digit
+
+hexadecimal-prefix:: one of
+   0x   0X
+
+binary-literal::
+   binary-prefix   binary-digit
+   binary-literal   binary-digit
+
+binary-prefix:: one of
+   0b   0B
+
+digit:: one of
+   0   1   2   3   4   5   6   7   8   9
+
+nonzero-digit:: one of
+   1   2   3   4   5   6   7   8   9
+
+octal-digit:: one of
+   0   1   2   3   4   5   6   7
+
+hexadecimal-digit:: one of
+   0   1   2   3   4   5   6   7   8   9
+   a   b   c   d   e   f
+   A   B   C   D   E   F
+
+binary-digit:: one of
+   0   1
+
+floating-literal::
+   fractional-literal   exponent-partopt
+   digit-sequence   exponent-part
+
+fractional-literal::
+   digit-sequenceopt   .   digit-sequence
+   digit-sequence   .
+
+exponent-part::
+   e   signopt   digit-sequence
+   E   signopt   digit-sequence
 
-  single-line-comment::
-    //   input-charactersopt
-    #    input-charactersopt
+sign:: one of
+   +   -
+
+digit-sequence::
+   digit
+   digit-sequence   digit
+
+string-literal::
+   single-quoted-string-literal
+   double-quoted-string-literal
+   heredoc-string-literal
+   nowdoc-string-literal
+
+single-quoted-string-literal::
+   b-prefixopt   '   sq-char-sequenceopt   '
+
+sq-char-sequence::
+   sq-char
+   sq-char-sequence   sq-char
+
+sq-char::
+   sq-escape-sequence
+   \opt   any member of the source character set except single-quote (') or backslash (\)
+
+sq-escape-sequence:: one of
+   \'   \\
+
+b-prefix:: one of
+   b   B
+
+double-quoted-string-literal::
+   b-prefixopt   "   dq-char-sequenceopt   "
 
-  input-characters::
-    input-character
-    input-characters   input-character
+dq-char-sequence::
+   dq-char
+   dq-char-sequence   dq-char
 
-  input-character::
-    Any source character except new-line
+dq-char::
+   dq-escape-sequence
+   any member of the source character set except double-quote (") or backslash (\)
+   \   any member of the source character set except "\$efnrtvxX or   octal-digit
 
-  new-line::
-    Carriage-return character (U+000D)
-    Line-feed character (U+000A)
-    Carriage-return character (U+000D) followed by line-feed character (U+000A)
+dq-escape-sequence::
+   dq-simple-escape-sequence
+   dq-octal-escape-sequence
+   dq-hexadecimal-escape-sequence
+   dq-unicode-escape-sequence
 
-  delimited-comment::
-    /*   No characters or any source character sequence except */   */
-
+dq-simple-escape-sequence:: one of + \" \\ \$ \e \f \n \r \t \v -###White Space +dq-octal-escape-sequence:: + \ octal-digit + \ octal-digit octal-digit + \ octal-digit octal-digit octal-digit -
-  white-space::
-    white-space-character
-    white-space   white-space-character
-
-  white-space-character::
-    new-line
-    Space character (U+0020)
-    Horizontal-tab character (U+0009)
-
+dq-hexadecimal-escape-sequence:: + \x hexadecimal-digit hexadecimal-digitopt + \X hexadecimal-digit hexadecimal-digitopt -###Tokens +dq-unicode-escape-sequence:: + \u{ codepoint-digits } -####General +codepoint-digits:: + hexadecimal-digit + hexadecimal-digit codepoint-digits -
-  token::
-    variable-name
-    name
-    keyword
-    literal
-    operator-or-punctuator
-
+string-variable:: + variable-name offset-or-propertyopt + ${ expression } -####Names +offset-or-property:: + offset-in-string + property-in-string -
-  variable-name::
-    $   name
-
-  namespace-name::
-    name
-    namespace-name   \   name
-
-  namespace-name-as-a-prefix::
-    \
-    \opt   namespace-name   \
-    namespace   \
-    namespace   \   namespace-name   \
-
-  qualified-name::
-    namespace-name-as-a-prefixopt   name
-
-  name::
-    name-nondigit
-    name   name-nondigit
-    name   digit
-
-  name-nondigit::
-    nondigit
-    one of the characters U+007f–U+00ff
-
-  nondigit:: one of
-    _
-    a   b   c   d   e   f   g   h   i   j   k   l   m
-    n   o   p   q   r   s   t   u   v   w   x   y   z
-    A   B   C   D   E   F   G   H   I   J   K   L   M
-    N   O   P   Q   R   S   T   U   V   W   X   Y   Z
-
+offset-in-string:: + [ name ] + [ variable-name ] + [ integer-literal ] -###Keywords - -
-  keyword:: one of
-    abstract   and   array   as   break   callable   case   catch   class   clone
-    const   continue   declare   default   die   do   echo   else   elseif   empty
-    enddeclare   endfor   endforeach   endif   endswitch   endwhile   eval   exit
-    extends   final   finally   for   foreach   function   global
-    goto   if   implements   include   include_once   instanceof
-    insteadof   interface   isset   list   namespace   new   or   print   private
-    protected   public   require   require_once   return static   switch
-    throw   trait   try   unset   use   var   while   xor   yield   yield from
-
- -###Literals - -####General - -
-  literal::
-    integer-literal
-    floating-literal
-    string-literal
-
- -####Integer Literals - -
-  integer-literal::
-    decimal-literal
-    octal-literal
-    hexadecimal-literal
-    binary-literal
+property-in-string::
+   ->   name
 
-    decimal-literal::
-      nonzero-digit
-      decimal-literal   digit
+heredoc-string-literal::
+   b-prefixopt   <<<   hd-start-identifier   new-line   hd-bodyopt   hd-end-identifier   ;opt   new-line
 
-    octal-literal::
-      0
-      octal-literal   octal-digit
+hd-start-identifier::
+   name
+   "   name   "
 
-    hexadecimal-literal::
-      hexadecimal-prefix   hexadecimal-digit
-      hexadecimal-literal   hexadecimal-digit
+hd-end-identifier::
+   name
 
-    hexadecimal-prefix:: one of
-      0x  0X
+hd-body::
+   hd-char-sequenceopt   new-line
 
-    binary-literal::
-      binary-prefix   binary-digit
-      binary-literal   binary-digit
+hd-char-sequence::
+   hd-char
+   hd-char-sequence   hd-char
 
-    binary-prefix:: one of
-      0b  0B
+hd-char::
+   hd-escape-sequence
+   any member of the source character set except backslash (\)
+   \ any member of the source character set except \$efnrtvxX or   octal-digit
 
-    digit:: one of
-      0  1  2  3  4  5  6  7  8  9
+hd-escape-sequence::
+   hd-simple-escape-sequence
+   dq-octal-escape-sequence
+   dq-hexadecimal-escape-sequence
+   dq-unicode-escape-sequence
 
-    nonzero-digit:: one of
-      1  2  3  4  5  6  7  8  9
+hd-simple-escape-sequence:: one of
+   \\   \$   \e   \f   \n   \r   \t   \v
 
-    octal-digit:: one of
-      0  1  2  3  4  5  6  7
+nowdoc-string-literal::
+   b-prefixopt   <<<   '   name   '   new-line   hd-bodyopt   name   ;opt   new-line
 
-    hexadecimal-digit:: one of
-      0  1  2  3  4  5  6  7  8  9
-      a  b  c  d  e  f
-      A  B  C  D  E  F
-
-    binary-digit:: one of
-        0  1
+operator-or-punctuator:: one of
+   [   ]   (   )   {   }   .   ->   ++   --   **   *   +   -   ~   !
+   $   /   %   <<   >>   <   >   <=   >=   ==   ===   !=   !==   ^   |
+   &   &&   ||   ?   :   ;   =   **=   *=   /=   %=   +=   -=   .=   <<=
+   >>=   &=   ^=   |=   ,   ??   <=>   ...   \
 
-####Floating-Point Literals - -
-  floating-literal::
-    fractional-literal   exponent-partopt
-    digit-sequence   exponent-part
-
-  fractional-literal::
-    digit-sequenceopt . digit-sequence
-    digit-sequence .
-
-  exponent-part::
-    e  signopt   digit-sequence
-    E  signopt   digit-sequence
+## Syntactic Grammar
 
-  sign:: one of
-    +  -
-
-  digit-sequence::
-    digit
-    digit-sequence   digit
-
- -####String Literals +### Basic Concepts
-  string-literal::
-    single-quoted-string-literal
-    double-quoted-string-literal
-    heredoc-string-literal
-    nowdoc-string-literal
-
-  single-quoted-string-literal::
-    bopt  ' sq-char-sequenceopt  '
-
-  sq-char-sequence::
-    sq-char
-    sq-char-sequence   sq-char
-
-  sq-char::
-    sq-escape-sequence
-    \opt   any member of the source character set except single-quote (') or backslash (\)
-
-  sq-escape-sequence:: one of
-    \'  \\
-
-  double-quoted-string-literal::
-    bopt  " dq-char-sequenceopt  "
-
-  dq-char-sequence::
-    dq-char
-    dq-char-sequence   dq-char
-
-  dq-char::
-    dq-escape-sequence
-    any member of the source character set except double-quote (") or backslash (\)
-    \  any member of the source character set except "\$efnrtvxX or octal-digit
-
-  dq-escape-sequence::
-    dq-simple-escape-sequence
-    dq-octal-escape-sequence
-    dq-hexadecimal-escape-sequence
-    dq-unicode-escape-sequence
-
-  dq-simple-escape-sequence:: one of
-    \"   \\   \$   \e   \f   \n   \r   \t   \v
-
-  dq-octal-escape-sequence::
-    \   octal-digit
-    \   octal-digit   octal-digit
-    \   octal-digit   octal-digit   octal-digit
-
-  dq-hexadecimal-escape-sequence::
-    \x  hexadecimal-digit   hexadecimal-digitopt
-    \X  hexadecimal-digit   hexadecimal-digitopt
-
-  dq-unicode-escape-sequence::
-    \u{  codepoint-digits  }
-
-  codepoint-digits::
-     hexadecimal-digit
-     hexadecimal-digit   codepoint-digits
-
-    string-variable::
-        variable-name   offset-or-propertyopt
-        ${   expression   }
+script:
+   script-section
+   script   script-section
 
-    offset-or-property::
-        offset-in-string
-        property-in-string
+script-section:
+   textopt   start-tag   statement-listopt   end-tagopt   textopt
 
-    offset-in-string::
-        [   name   ]
-        [   variable-name   ]
-        [   integer-literal   ]
+start-tag:
+   <?php
+   <?=
 
-    property-in-string::
-        ->   name
+end-tag:
+   ?>
 
-  heredoc-string-literal::
-    <<<  hd-start-identifier   new-line   hd-char-sequenceopt  new-line hd-end-identifier  ;opt   new-line
-
-  hd-start-identifier::
-    name
-    "   name  "
-
-  hd-end-identifier::
-    name
-
-  hd-char-sequence::
-    hd-char
-    hd-char-sequence   hd-char
-
-  hd-char::
-    hd-escape-sequence
-    any member of the source character set except backslash (\)
-    \  any member of the source character set except \$efnrtvxX or octal-digit
-
-  hd-escape-sequence::
-    hd-simple-escape-sequence
-    dq-octal-escape-sequence
-    dq-hexadecimal-escape-sequence
-    dq-unicode-escape-sequence
-
-  hd-simple-escape-sequence:: one of
-    \\   \$   \e   \f   \n   \r   \t   \v
-
-  nowdoc-string-literal::
-    <<<  '  name  '  new-line  hd-char-sequenceopt   new-line name  ;opt   new-line
+text:
+   arbitrary text not containing any of   start-tag   sequences
 
-###Operators and Punctuators +### Variables
-  operator-or-punctuator:: one of
-    [   ]    (   )   {    }   .   ->   ++   --   **   *   +   -   ~   !
-    $   /   %   <<    >>   <   >   <=   >=   ==   ===   !=   !==   ^   |
-    &   &&   ||   ?   :   ;   =   **=   *=   /=   %=   +=   -=   .=   <<=
-    >>=   &=   ^=   |=   =&   ,   ??   <=>   ...
-
- -##Syntactic Grammar +function-static-declaration: + static static-variable-name-list ; -###Program Structure - -
-script:
- script-section
- script   script-section
+static-variable-name-list:
+   static-variable-declaration
+   static-variable-name-list   ,   static-variable-declaration
 
-script-section:
-   textopt start-tag statement-listopt end-tagopt textopt
+static-variable-declaration:
+   variable-name   function-static-initializeropt
 
-start-tag:
-  <?php
-  <?=
+function-static-initializer:
+   =   constant-expression
 
-end-tag:
-  ?>
+global-declaration:
+   global   variable-name-list   ;
 
-text:
-  arbitrary text not containing any of start-tag sequences
+variable-name-list:
+   simple-variable
+   variable-name-list   ,   simple-variable
 
-###Variables +### Expressions
-  function-static-declaration:
-    static static-variable-name-list  ;
+primary-expression:
+   variable
+   class-constant-access-expression
+   constant-access-expression
+   literal
+   array-creation-expression
+   intrinsic
+   anonymous-function-creation-expression
+   object-creation-expression
+   postfix-increment-expression
+   postfix-decrement-expression
+   prefix-increment-expression
+   prefix-decrement-expression
+   byref-assignment-expression
+   shell-command-expression
+   (   expression   )
+
+simple-variable:
+   variable-name
+   $   simple-variable
+   $   {   expression   }
+
+dereferencable-expression:
+   variable
+   (   expression   )
+   array-creation-expression
+   string-literal
+
+callable-expression:
+   callable-variable
+   (   expression   )
+   array-creation-expression
+   string-literal
+
+callable-variable:
+   simple-variable
+   subscript-expression
+   member-call-expression
+   scoped-call-expression
+   function-call-expression
+
+variable:
+   callable-variable
+   scoped-property-access-expression
+   member-access-expression
+
+constant-access-expression:
+   qualified-name
+
+literal:
+   integer-literal
+   floating-literal
+   string-literal
+
+intrinsic:
+   empty-intrinsic
+   eval-intrinsic
+   exit-intrinsic
+   isset-intrinsic
+
+empty-intrinsic:
+   empty   (   expression   )
+
+eval-intrinsic:
+   eval   (   expression   )
+
+exit-intrinsic:
+   exit
+   exit   (   expressionopt   )
+   die
+   die   (   expressionopt   )
+
+isset-intrinsic:
+   isset   (   variable-list   ,opt   )
+
+variable-list:
+   variable
+   variable-list   ,   variable
+
+anonymous-function-creation-expression:
+   staticopt   function   &opt   (   parameter-declaration-listopt   )   anonymous-function-use-clauseopt   return-typeopt   compound-statement
+
+anonymous-function-use-clause:
+   use   (   use-variable-name-list   )
+
+use-variable-name-list:
+   &opt   variable-name
+   use-variable-name-list   ,   &opt   variable-name
+
+object-creation-expression:
+   new   class-type-designator   (   argument-expression-listopt   )
+   new   class-type-designator   (   argument-expression-list   ,opt   )
+   new   class-type-designator
+   new   class   (   argument-expression-listopt   )   class-base-clauseopt   class-interface-clauseopt   {   class-member-declarationsopt   }
+   new   class   class-base-clauseopt   class-interface-clauseopt   {   class-member-declarationsopt   }
+
+class-type-designator:
+   qualified-name
+   new-variable
+
+new-variable:
+   simple-variable
+   new-variable   [   expressionopt   ]
+   new-variable   {   expression   }
+   new-variable   ->   member-name
+   qualified-name   ::   simple-variable
+   relative-scope   ::   simple-variable
+   new-variable   ::   simple-variable
+
+array-creation-expression:
+   array   (   array-initializeropt   )
+   [   array-initializeropt   ]
+
+array-initializer:
+   array-initializer-list   ,opt
+
+array-initializer-list:
+   array-element-initializer
+   array-element-initializer   ,   array-initializer-list
+
+array-element-initializer:
+   &opt   element-value
+   element-key   =>   &opt   element-value
+
+element-key:
+   expression
+
+element-value:
+   expression
+
+subscript-expression:
+   dereferencable-expression   [   expressionopt   ]
+   dereferencable-expression   {   expression   }   <b>[Deprecated form]</b>
 
-  static-variable-name-list:
-    static-variable-declaration
-    static-variable-name-list  ,  static-variable-declaration
+function-call-expression:
+   qualified-name   (   argument-expression-listopt   )
+   qualified-name   (   argument-expression-list   ,   )
+   callable-expression   (   argument-expression-listopt   )
+   callable-expression   (   argument-expression-list   ,   )
 
-  static-variable-declaration:
-    variable-name function-static-initializeropt
+argument-expression-list:
+   argument-expression
+   argument-expression-list   ,   argument-expression
 
-  function-static-initializer:
-    = constant-expression
+argument-expression:
+   variadic-unpacking
+   expression
 
-  global-declaration:
-    global variable-name-list ;
-
-  variable-name-list:
-    expression
-    variable-name-list  ,  expression
-
- -###Expressions - -####Primary Expressions - -
-  primary-expression:
-    variable-name
-    qualified-name
-    literal
-    constant-expression
-    intrinsic
-    anonymous-function-creation-expression
-    (  expression  )
-    $this
-
-  intrinsic:
-    intrisic-construct
-    intrisic-operator
-
-  intrisic-construct:
-    echo-intrinsic
-    list-intrinsic
-    unset-intrinsic
-
-  intrinsic-operator:
-    array-intrinsic
-    empty-intrinsic
-    eval-intrinsic
-    exit-intrinsic
-    isset-intrinsic
-    print-intrinsic
-
-  array-intrinsic:
-    array ( array-initializeropt  )
-
-  echo-intrinsic:
-    echo  expression
-    echo  expression-list-two-or-more
-
-  expression-list-two-or-more:
-    expression  ,  expression
-    expression-list-two-or-more  ,  expression
-
-  empty-intrinsic:
-    empty ( expression  )
-
-  eval-intrinsic:
-    eval (  expression  )
-
-  exit-intrinsic:
-    exit  expressionopt
-    exit  (  expressionopt  )
-    die   expressionopt
-    die   (   expressionopt )
-
-  isset-intrinsic:
-    isset  (  expression-list-one-or-more  )
-
-  expression-list-one-or-more:
-    expression
-    expression-list-one-or-more  ,  expression
-
-  list-intrinsic:
-    list  (  list-expression-listopt  )
-
-  list-expression-list:
-    list-or-variable
-    ,
-    list-expression-list  ,  list-or-variableopt
-
-  list-or-variable:
-    list-intrinsic
-    expression
-
-  print-intrinsic:
-    print  expression
-    print  (  expression  )
-
-  unset-intrinsic:
-    unset  (  expression-list-one-or-more  )
-
-  anonymous-function-creation-expression:
-  staticopt function  &opt (  parameter-declaration-listopt  ) return-typeopt anonymous-function-use-clauseopt
-      compound-statement
-
-  anonymous-function-use-clause:
-    use  (  use-variable-name-list  )
-
-  use-variable-name-list:
-    &opt   variable-name
-    use-variable-name-list  ,  &opt  variable-name
-
-
- -####Postfix Operators - -
-  postfix-expression:
-    primary-expression
-    clone-expression
-    object-creation-expression
-    array-creation-expression
-    subscript-expression
-    function-call-expression
-    member-selection-expression
-    postfix-increment-expression
-    postfix-decrement-expression
-    scope-resolution-expression
-    exponentiation-expression
-
-  clone-expression:
-    clone  expression
-
-  object-creation-expression:
-    new  class-type-designator  (  argument-expression-listopt  )
-    new  class-type-designator
-    new  class  (  argument-expression-listopt  )
-        class-base-clauseopt   class-interface-clauseopt
-        {   opt   }
-    new  class class-base-clauseopt  class-interface-clauseopt
-        {   class-member-declarationsopt   }
-
-  class-type-designator:
-    qualified-name
-    expression
-
-  array-creation-expression:
-    array  (  array-initializeropt  )
-    [ array-initializeropt ]
-
-  array-initializer:
-    array-initializer-list  ,opt
-
-  array-initializer-list:
-    array-element-initializer
-    array-element-initializer  ,  array-initializer-list
-
-  array-element-initializer:
-    &opt   element-value
-    element-key  =>  &opt   element-value
-
-  element-key:
-    expression
-
-  element-value
-    expression
-
-  subscript-expression:
-    postfix-expression  [  expressionopt  ]
-    postfix-expression  {  expression  }   [Deprecated form]
-
-  function-call-expression:
-    qualified-name  (  argument-expression-listopt  )
-    postfix-expression  (  argument-expression-listopt  )
-
-  argument-expression-list:
-    argument-expression
-    argument-expression-list  ,  argument-expression
-
-  argument-expression:
-    variadic-unpacking
-    assignment-expression
-
-  variadic-unpacking:
-    ... assignment-expression
-
-  member-selection-expression:
-    postfix-expression  ->  member-selection-designator
-
-  member-selection-designator:
-    name
-    expression
-
-  postfix-increment-expression:
-    unary-expression  ++
-
-  postfix-decrement-expression:
-    unary-expression  --
-
-  scope-resolution-expression:
-    scope-resolution-qualifier  ::  member-selection-designator
-    scope-resolution-qualifier  ::  class
-
-  scope-resolution-qualifier:
-    relative-scope
-    qualified-name
-    expression
-
-  relative-scope:
-    self
-    parent
-    static
-
-  exponentiation-expression:
-    expression  **  expression
-
+variadic-unpacking: + ... expression -####Unary Operators +member-access-expression: + dereferencable-expression -> member-name -
-  unary-expression:
-    postfix-expression
-    prefix-increment-expression
-    prefix-decrement-expression
-    unary-op-expression
-    error-control-expression
-    shell-command-expression
-    cast-expression
-    variable-name-creation-expression
+member-name:
+   name
+   simple-variable
+   {   expression   }
 
-  prefix-increment-expression:
-    ++ unary-expression
+member-call-expression:
+   dereferencable-expression   ->   member-name   (   argument-expression-listopt   )
+   dereferencable-expression   ->   member-name   (   argument-expression-list   ,   )
+
+postfix-increment-expression:
+   variable   ++
+
+postfix-decrement-expression:
+   variable   --
+
+prefix-increment-expression:
+   ++   variable
+
+prefix-decrement-expression:
+   --   variable
+
+shell-command-expression:
+   `   dq-char-sequenceopt   `
+
+scoped-property-access-expression:
+   scope-resolution-qualifier   ::   simple-variable
+
+scoped-call-expression:
+   scope-resolution-qualifier   ::   member-name   (   argument-expression-listopt   )
+   scope-resolution-qualifier   ::   member-name   (   argument-expression-list   ,   )
+
+class-constant-access-expression:
+   scope-resolution-qualifier   ::   name
+
+scope-resolution-qualifier:
+   relative-scope
+   qualified-name
+   dereferencable-expression
+
+relative-scope:
+   self
+   parent
+   static
+
+clone-expression:
+   primary-expression
+   clone   primary-expression
+
+exponentiation-expression:
+   clone-expression
+   clone-expression   **   exponentiation-expression
+
+unary-expression:
+   exponentiation-expression
+   unary-op-expression
+   error-control-expression
+   cast-expression
 
-  prefix-decrement-expression:
-    -- unary-expression
+unary-op-expression:
+   unary-operator   unary-expression
+
+unary-operator: one of
+   +   -   ~
+
+error-control-expression:
+   @   unary-expression
+
+cast-expression:
+   (   cast-type   )   unary-expression
+
+cast-type: one of
+   array   binary   bool   boolean   double   int   integer   float   object
+   real   string   unset
+
+instanceof-expression:
+   unary-expression
+   instanceof-subject   instanceof   class-type-designator
+
+instanceof-subject:
+   instanceof-expression
+
+logical-NOT-expression:
+   instanceof-expression
+   !   instanceof-expression
 
-  unary-op-expression:
-    unary-operator cast-expression
+multiplicative-expression:
+   logical-NOT-expression
+   multiplicative-expression   *   logical-NOT-expression
+   multiplicative-expression   /   logical-NOT-expression
+   multiplicative-expression   %   logical-NOT-expression
+
+additive-expression:
+   multiplicative-expression
+   additive-expression   +   multiplicative-expression
+   additive-expression   -   multiplicative-expression
+   additive-expression   .   multiplicative-expression
 
-  unary-operator: one of
-    +  -  !  ~
+shift-expression:
+   additive-expression
+   shift-expression   <<   additive-expression
+   shift-expression   >>   additive-expression
+
+relational-expression:
+   shift-expression
+   relational-expression   <   shift-expression
+   relational-expression   >   shift-expression
+   relational-expression   <=   shift-expression
+   relational-expression   >=   shift-expression
+   relational-expression   <=>   shift-expression
+
+equality-expression:
+   relational-expression
+   equality-expression   ==   relational-expression
+   equality-expression   !=   relational-expression
+   equality-expression   <>   relational-expression
+   equality-expression   ===   relational-expression
+   equality-expression   !==   relational-expression
+
+bitwise-AND-expression:
+   equality-expression
+   bitwise-AND-expression   &   equality-expression
+
+bitwise-exc-OR-expression:
+   bitwise-AND-expression
+   bitwise-exc-OR-expression   ^   bitwise-AND-expression
+
+bitwise-inc-OR-expression:
+   bitwise-exc-OR-expression
+   bitwise-inc-OR-expression   |   bitwise-exc-OR-expression
+
+logical-AND-expression-1:
+   bitwise-inc-OR-expression
+   logical-AND-expression-1   &&   bitwise-inc-OR-expression
+
+logical-inc-OR-expression-1:
+   logical-AND-expression-1
+   logical-inc-OR-expression-1   ||   logical-AND-expression-1
+
+coalesce-expression:
+   logical-inc-OR-expression-1
+   logical-inc-OR-expression-1   ??   coalesce-expression
+
+conditional-expression:
+   coalesce-expression
+   conditional-expression   ?   expressionopt   :   coalesce-expression
+
+assignment-expression:
+   conditional-expression
+   simple-assignment-expression
+   compound-assignment-expression
+
+simple-assignment-expression:
+   variable   =   assignment-expression
+   list-intrinsic   =   assignment-expression
+
+list-intrinsic:
+   list   (   list-expression-list   )
+
+list-expression-list:
+   unkeyed-list-expression-list
+   keyed-list-expression-list   ,opt
+
+unkeyed-list-expression-list:
+   list-or-variable
+   ,
+   unkeyed-list-expression-list   ,   list-or-variableopt
+
+keyed-list-expression-list:
+   expression   =>   list-or-variable
+   keyed-list-expression-list   ,   expression   =>   list-or-variable
+
+list-or-variable:
+   list-intrinsic
+   &opt   variable
+
+byref-assignment-expression:
+   variable   =   &   variable
+
+compound-assignment-expression:
+   variable   compound-assignment-operator   assignment-expression
+
+compound-assignment-operator: one of
+   **=   *=   /=   %=   +=   -=   .=   <<=   >>=   &=   ^=   |=
+
+yield-from-expression:
+   yield from   assignment-expression
+
+yield-expression:
+   yield-from-expression
+   yield
+   yield   yield-expression
+   yield   yield-from-expression   =>   yield-expression
+
+print-expression:
+   yield-expression
+   print   print-expression
+
+logical-AND-expression-2:
+   print-expression
+   logical-AND-expression-2   and   yield-expression
+
+logical-exc-OR-expression:
+   logical-AND-expression-2
+   logical-exc-OR-expression   xor   logical-AND-expression-2
+
+logical-inc-OR-expression-2:
+   logical-exc-OR-expression
+   logical-inc-OR-expression-2   or   logical-exc-OR-expression
 
-  error-control-expression:
-    @   expression
+expression:
+   logical-inc-OR-expression-2
+   include-expression
+   include-once-expression
+   require-expression
+   require-once-expression
 
-  shell-command-expression:
-    `  dq-char-sequenceopt  `
+include-expression:
+   include   expression
 
-  cast-expression:
-    unary-expression
-    (  cast-type  ) expression
+include-once-expression:
+   include_once   expression
 
-  cast-type: one of
-    array  binary  bool  boolean  double  int  integer  float  object
-    real  string  unset
+require-expression:
+   require   expression
 
-  variable-name-creation-expression:
-    $   expression
-    $  {  expression  }
+require-once-expression:
+   require_once   expression
 
+constant-expression:
+   expression
 
-####instanceof Operator +### Statements
-  instanceof-expression:
-    unary-expression
-    instanceof-subject  instanceof   instanceof-type-designator
+statement:
+   compound-statement
+   named-label-statement
+   expression-statement
+   selection-statement
+   iteration-statement
+   jump-statement
+   try-statement
+   declare-statement
+   echo-statement
+   unset-statement
+   const-declaration
+   function-definition
+   class-declaration
+   interface-declaration
+   trait-declaration
+   namespace-definition
+   namespace-use-declaration
+   global-declaration
+   function-static-declaration
+
+compound-statement:
+   {   statement-listopt   }
+
+statement-list:
+   statement
+   statement-list   statement
+
+named-label-statement:
+   name   :
+
+expression-statement:
+   expressionopt   ;
+
+selection-statement:
+   if-statement
+   switch-statement
+
+if-statement:
+   if   (   expression   )   statement   elseif-clauses-1opt   else-clause-1opt
+   if   (   expression   )   :   statement-list   elseif-clauses-2opt   else-clause-2opt   endif   ;
+
+elseif-clauses-1:
+   elseif-clause-1
+   elseif-clauses-1   elseif-clause-1
+
+elseif-clause-1:
+   elseif   (   expression   )   statement
+
+else-clause-1:
+   else   statement
+
+elseif-clauses-2:
+   elseif-clause-2
+   elseif-clauses-2   elseif-clause-2
+
+elseif-clause-2:
+   elseif   (   expression   )   :   statement-list
 
-  instanceof-subject:
-    expression
+else-clause-2:
+   else   :   statement-list
 
-  instanceof-type-designator:
-    qualified-name
-    expression
-
+switch-statement: + switch ( expression ) { case-statementsopt } + switch ( expression ) : case-statementsopt endswitch ; -####Multiplicative Operators +case-statements: + case-statement case-statementsopt + default-statement case-statementsopt -
-  multiplicative-expression:
-    instanceof-expression
-    multiplicative-expression  *  instanceof-expression
-    multiplicative-expression  /  instanceof-expression
-    multiplicative-expression  %  instanceof-expression
-
+case-statement: + case expression case-default-label-terminator statement-listopt + +default-statement: + default case-default-label-terminator statement-listopt + +case-default-label-terminator: + : + ; + +iteration-statement: + while-statement + do-statement + for-statement + foreach-statement -####Additive Operators +while-statement: + while ( expression ) statement + while ( expression ) : statement-list endwhile ; + +do-statement: + do statement while ( expression ) ; + +for-statement: + for ( for-initializeropt ; for-controlopt ; for-end-of-loopopt ) statement + for ( for-initializeropt ; for-controlopt ; for-end-of-loopopt ) : statement-list endfor ; + +for-initializer: + for-expression-group + +for-control: + for-expression-group -
-  additive-expression:
-    multiplicative-expression
-    additive-expression  +  multiplicative-expression
-    additive-expression  -  multiplicative-expression
-    additive-expression  .  multiplicative-expression
-
+for-end-of-loop: + for-expression-group -####Bitwise Shift Operators +for-expression-group: + expression + for-expression-group , expression -
-  shift-expression:
-    additive-expression
-    shift-expression  <<  additive-expression
-    shift-expression  >>  additive-expression
-
+foreach-statement: + foreach ( foreach-collection-name as foreach-keyopt foreach-value ) statement + foreach ( foreach-collection-name as foreach-keyopt foreach-value ) : statement-list endforeach ; -####Relational Operators +foreach-collection-name: + expression -
-  relational-expression:
-    shift-expression
-    relational-expression  <   shift-expression
-    relational-expression  >   shift-expression
-    relational-expression  <=  shift-expression
-    relational-expression  >=  shift-expression
-    relational-expression  <=> shift-expression
-
+foreach-key: + expression => -####Equality Operators +foreach-value: + &opt expression + list-intrinsic -
-  equality-expression:
-    relational-expression
-    equality-expression  ==  relational-expression
-    equality-expression  !=  relational-expression
-    equality-expression  <>  relational-expression
-    equality-expression  ===  relational-expression
-    equality-expression  !==  relational-expression
-
+jump-statement: + goto-statement + continue-statement + break-statement + return-statement + throw-statement -####Bitwise Logical Operators +goto-statement: + goto name ; -
-  bitwise-AND-expression:
-    equality-expression
-    bit-wise-AND-expression  &  equality-expression
+continue-statement:
+   continue   breakout-levelopt   ;
 
-  bitwise-exc-OR-expression:
-    bitwise-AND-expression
-    bitwise-exc-OR-expression  ^  bitwise-AND-expression
+breakout-level:
+   integer-literal
+   (   breakout-level   )
 
-  bitwise-inc-OR-expression:
-    bitwise-exc-OR-expression
-    bitwise-inc-OR-expression  |  bitwise-exc-OR-expression
-
+break-statement: + break breakout-levelopt ; -####Logical Operators (form 1) +return-statement: + return expressionopt ; -
-  logical-AND-expression-1:
-    bitwise-incl-OR-expression
-    logical-AND-expression-1  &&  bitwise-inc-OR-expression
+throw-statement:
+   throw   expression   ;
 
-  logical-inc-OR-expression-1:
-    logical-AND-expression-1
-    logical-inc-OR-expression-1  ||  logical-AND-expression-1
-
+try-statement: + try compound-statement catch-clauses + try compound-statement finally-clause + try compound-statement catch-clauses finally-clause -####Conditional Operator +catch-clauses: + catch-clause + catch-clauses catch-clause -
-  conditional-expression:
-    logical-inc-OR-expression-1
-    logical-inc-OR-expression-1  ?  expressionopt  :  conditional-expression
-
+catch-clause: + catch ( catch-name-list variable-name ) compound-statement -####Coalesce Operator +catch-name-list: + qualified-name + catch-name-list | qualified-name -
-  coalesce-expression:
-    logical-inc-OR-expression  ??  expression
-
+finally-clause: + finally compound-statement -####Assignment Operators +declare-statement: + declare ( declare-directive ) statement + declare ( declare-directive ) : statement-list enddeclare ; + declare ( declare-directive ) ; -
-  assignment-expression:
-    conditional-expression
-    coalesce-expression
-    simple-assignment-expression
-    byref-assignment-expression
-    compound-assignment-expression
+declare-directive:
+   ticks   =   literal
+   encoding   =   literal
+   strict_types   =   literal
 
-  simple-assignment-expression:
-    unary-expression  =  assignment-expression
+echo-statement:
+   echo   expression-list   ;
 
-  byref-assignment-expression:
-    unary-expression  =  &  assignment-expression
-
-  compound-assignment-expression:
-    unary-expression   compound-assignment-operator   assignment-expression
-
-  compound-assignment-operator: one of
-    **=  *=  /=  %=  +=  -=  .=  <<=  >>=  &=  ^=  |=
-
- -####Logical Operators (form 2) - -
-  logical-AND-expression-2:
-    assignment-expression
-    logical-AND-expression-2  and  assignment-expression
-
-  logical-exc-OR-expression:
-    logical-AND-expression-2
-    logical-exc-OR-expression  xor  logical-AND-expression-2
-
-  logical-inc-OR-expression-2:
-    logical-exc-OR-expression
-    logical-inc-OR-expression-2  or  logical-exc-OR-expression
-
-
- - -####yield Operator - -
-  yield-expression:
-    logical-inc-OR-expression-2
-    yield  array-element-initializer
-
- -####Script Inclusion Operators - -
-  expression:
-    yield-expression
-    include-expression
-    include-once-expression
-    require-expression
-    require-once-expression
-
-  include-expression:
-    include  (  expression  )
-    include  expression
-
-  include-once-expression:
-    include_once  (  expression  )
-    include_once  expression
-
-  require-expression:
-    require  (  expression  )
-    require  expression
-
-  require-once-expression:
-    require_once  (  expression  )
-    require_once  expression
-
- -####Constant Expressions - -
-  constant-expression:
-    array-creation-expression
-    expression
-
- -###Statements - -####General - -
-
-  statement:
-    compound-statement
-    labeled-statement
-    expression-statement
-    selection-statement
-    iteration-statement
-    jump-statement
-    declare-statement
-    const-declaration
-    function-definition
-    class-declaration
-    interface-declaration
-    trait-declaration
-    namespace-definition
-    namespace-use-declaration
-    global-declaration
-    function-static-declaration
-
- -####Compound Statements - -
-  compound-statement:
-    {   statement-listopt  }
-
-  statement-list:
-    statement
-    statement-list   statement
-
- -####Labeled Statements - -
-  labeled-statement:
-    named-label-statement
-    case-statement
-    default-statement
-
-  named-label-statement:
-    name  :  statement
-
-  case-statement:
-    case   expression   case-default-label-terminator   statement
-
-  default-statement:
-    default  case-default-label-terminator   statement
-
-  case-default-label-terminator:
-    :
-    ;
-
- -####Expression Statements - -
-   expression-statement:
-     expressionopt  ;
-
-  selection-statement:
-    if-statement
-    switch-statement
-
-  if-statement:
-    if   (   expression   )   statement   elseif-clauses-1opt   else-clause-1opt
-    if   (   expression   )   :   statement-list   elseif-clauses-2opt   else-clause-2opt   endif   ;
-
-  elseif-clauses-1:
-    elseif-clause-1
-    elseif-clauses-1   elseif-clause-1
-
-  elseif-clause-1:
-    elseif   (   expression   )   statement
-
-  else-clause-1:
-    else   statement
-
-  elseif-clauses-2:
-    elseif-clause-2
-    elseif-clauses-2   elseif-clause-2
-
-  elseif-clause-2:
-    elseif   (   expression   )   :   statement-list
-
-  else-clause-2:
-    else   :   statement-list
-
-  switch-statement:
-    switch  (  expression  )  { case-statementsopt }
-    switch  (  expression  )  :   case-statementsopt  endswitch;
-
-  case-statements:
-    case-statement statement-listopt case-statementsopt
-    default-statement statement-listopt case-statementsopt
-
-
- -####Iteration Statements - -
-  iteration-statement:
-    while-statement
-    do-statement
-    for-statement
-    foreach-statement
-
-  while-statement:
-    while  (  expression  )  statement
-    while  (  expression  )  :   statement-list  endwhile ;
-
-  do-statement:
-    do  statement  while  (  expression  )  ;
-
-  for-statement:
-    for   (   for-initializeropt   ;   for-controlopt   ;   for-end-of-loopopt   )   statement
-    for   (   for-initializeropt   ;   for-controlopt   ;   for-end-of-loopopt   )   :   statement-list   endfor   ;
-
-  for-initializer:
-    for-expression-group
-
-  for-control:
-    for-expression-group
-
-  for-end-of-loop:
-    for-expression-group
-
-  for-expression-group:
-    expression
-    for-expression-group   ,   expression
-
-  foreach-statement:
-    foreach  (  foreach-collection-name  as  foreach-keyopt  foreach-value  )   statement
-    foreach  (  foreach-collection-name  as  foreach-keyopt  foreach-value  )  :  statement-list  endforeach  ;
-
-  foreach-collection-name:
-    expression
-
-  foreach-key:
-    expression  =>
-
-  foreach-value:
-    &opt   expression
-    list-intrinsic
+expression-list:
+   expression
+   expression-list   ,   expression
 
+unset-statement:
+   unset   (   variable-list   ,opt   )   ;
 
-####Jump Statements +### Functions
-  jump-statement:
-    goto-statement
-    continue-statement
-    break-statement
-    return-statement
-    throw-statement
-
-  goto-statement:
-    goto  name  ;
+function-definition:
+   function-definition-header   compound-statement
 
-  continue-statement:
-    continue   breakout-levelopt  ;
+function-definition-header:
+   function   &opt   name   (   parameter-declaration-listopt   )   return-typeopt
 
-  breakout-level:
-    integer-literal
+parameter-declaration-list:
+   simple-parameter-declaration-list
+   variadic-declaration-list
 
-  break-statement:
-    break  breakout-levelopt  ;
+simple-parameter-declaration-list:
+   parameter-declaration
+   parameter-declaration-list   ,   parameter-declaration
 
-  return-statement:
-    return  expressionopt  ;
-
-  throw-statement:
-    throw  expression  ;
-
- -####The try Statement - -
-  try-statement:
-    try  compound-statement   catch-clauses
-    try  compound-statement   finally-clause
-    try  compound-statement   catch-clauses   finally-clause
+variadic-declaration-list:
+   simple-parameter-declaration-list   ,   variadic-parameter
+   variadic-parameter
 
-  catch-clauses:
-    catch-clause
-    catch-clauses   catch-clause
+parameter-declaration:
+   type-declarationopt   &opt   variable-name   default-argument-specifieropt
 
-  catch-clause:
-    catch  (  qualified-name variable-name )  compound-statement
+variadic-parameter:
+   type-declarationopt   &opt   ...   variable-name
 
-  finally-clause:
-    finally   compound-statement
-
+return-type: + : type-declaration + : void -####The declare Statement +type-declaration: + ?opt base-type-declaration -
-  declare-statement:
-    declare  (  declare-directive  )  statement
-    declare  (  declare-directive  )  :  statement-list  enddeclare  ;
-    declare  (  declare-directive  )  ;
+base-type-declaration:
+   array
+   callable
+   iterable
+   scalar-type
+   qualified-name
 
-  declare-directive:
-    ticks  =  literal
-    encoding  =  literal
-    strict_types  =  literal
+scalar-type:
+   bool
+   float
+   int
+   string
 
+default-argument-specifier:
+   =   constant-expression
 
-###Functions +### Classes
-  function-definition:
-    function-definition-header   compound-statement
-
-  function-definition-header:
-    function  &opt   name  (  parameter-declaration-listopt  )  return-typeopt
-
-  parameter-declaration-list:
-    simple-parameter-declaration-list
-    variadic-declaration-list
-
-  simple-parameter-declaration-list:
-    parameter-declaration
-    parameter-declaration-list  ,  parameter-declaration
-
-  variadic-declaration-list:
-    simple-parameter-declaration-list  ,  variadic-parameter
-    variadic-parameter
+class-declaration:
+   class-modifiersopt   class   name   class-base-clauseopt   class-interface-clauseopt   {   class-member-declarationsopt   }
 
-  parameter-declaration:
-    type-declarationopt  &opt  variable-name   default-argument-specifieropt
+class-modifiers:
+   class-modifier
+   class-modifiers   class-modifier
 
-  variadic-parameter:
-	type-declarationopt  &opt  ...  variable-name
+class-modifier:
+   abstract
+   final
+   readonly
 
-  return-type:
-    : type-declaration
+class-base-clause:
+   extends   qualified-name
 
-  type-declaration:
-    array
-    callable
-    scalar-type
-    qualified-name
+class-interface-clause:
+   implements   qualified-name
+   class-interface-clause   ,   qualified-name
 
-  scalar-type:
-    bool
-    float
-    int
-    string
-
-  default-argument-specifier:
-    =  constant-expression
-
- -###Classes - -
-  class-declaration:
-    class-modifieropt  class  name   class-base-clauseopt  class-interface-clauseopt   {   class-member-declarationsopt }
+class-member-declarations:
+   class-member-declaration
+   class-member-declarations   class-member-declaration
 
-  class-modifier:
-    abstract
-    final
+class-member-declaration:
+   class-const-declaration
+   property-declaration
+   method-declaration
+   constructor-declaration
+   destructor-declaration
+   trait-use-clause
 
-  class-base-clause:
-    extends  qualified-name
+const-declaration:
+   const   const-elements   ;
 
-  class-interface-clause:
-    implements  qualified-name
-    class-interface-clause  ,  qualified-name
+class-const-declaration:
+   visibility-modifieropt   const   const-elements   ;
 
-  class-member-declarations:
-    class-member-declaration
-    class-member-declarations   class-member-declaration
+const-elements:
+   const-element
+   const-elements   ,   const-element
 
-   class-member-declaration:
-     const-declaration
-     property-declaration
-     method-declaration
-     constructor-declaration
-     destructor-declaration
-     trait-use-clause
+const-element:
+   name   =   constant-expression
 
-  const-declaration:
-    const  name  =  constant-expression   ;
+property-declaration:
+   property-modifier   property-elements   ;
 
-  property-declaration:
-    property-modifier   variable-name   property-initializeropt  ;
+property-modifier:
+   var
+   visibility-modifier   static-modifieropt
+   static-modifier   visibility-modifieropt
 
-  property-modifier:
-    var
-    visibility-modifier   static-modifieropt
-    static-modifier   visibility-modifieropt
+visibility-modifier:
+   public
+   protected
+   private
 
-  visibility-modifier:
-    public
-    protected
-    private
+static-modifier:
+   static
 
-  static-modifier:
-    static
+property-elements:
+   property-element
+   property-elements   property-element
 
-  property-initializer:
-    =  constant-expression
+property-element:
+   variable-name   property-initializeropt   ;
 
-  method-declaration:
-    method-modifiersopt   function-definition
-    method-modifiers   function-definition-header  ;
+property-initializer:
+   =   constant-expression
 
-  method-modifiers:
-    method-modifier
-    method-modifiers   method-modifier
+method-declaration:
+   method-modifiersopt   function-definition
+   method-modifiers   function-definition-header   ;
 
-  method-modifier:
-    visibility-modifier
-    static-modifier
-    class-modifier
+method-modifiers:
+   method-modifier
+   method-modifiers   method-modifier
 
-  constructor-declaration:
-    method-modifiers  function &opt   __construct  (  parameter-declaration-listopt  )  compound-statement
-    method-modifiers  function &opt    name  (  parameter-declaration-listopt  )  compound-statement     [Deprecated form]
+method-modifier:
+   visibility-modifier
+   static-modifier
+   class-modifier
 
-  destructor-declaration:
-    method-modifiers  function  &opt  __destruct  ( ) compound-statement
+constructor-declaration:
+   method-modifiers   function   &opt   __construct   (   parameter-declaration-listopt   )   compound-statement
 
+destructor-declaration:
+   method-modifiers   function   &opt   __destruct   (   )   compound-statement
 
-###Interfaces +### Interfaces
-  interface-declaration:
-    interface   name   interface-base-clauseopt {  interface-member-declarationsopt  }
+interface-declaration:
+   interface   name   interface-base-clauseopt   {   interface-member-declarationsopt   }
 
-  interface-base-clause:
-    extends   qualified-name
-    interface-base-clause  ,  qualified-name
+interface-base-clause:
+   extends   qualified-name
+   interface-base-clause   ,   qualified-name
 
-  interface-member-declarations:
-    interface-member-declaration
-    interface-member-declarations   interface-member-declaration
+interface-member-declarations:
+   interface-member-declaration
+   interface-member-declarations   interface-member-declaration
 
-  interface-member-declaration:
-    const-declaration
-    method-declaration
+interface-member-declaration:
+   class-const-declaration
+   method-declaration
 
-###Traits +### Traits
-  trait-declaration:
-    trait   name   {   trait-member-declarationsopt   }
+trait-declaration:
+   trait   name   {   trait-member-declarationsopt   }
 
-  trait-member-declarations:
-    trait-member-declaration
-    trait-member-declarations   trait-member-declaration
+trait-member-declarations:
+   trait-member-declaration
+   trait-member-declarations   trait-member-declaration
 
-  trait-member-declaration:
-    property-declaration
-    method-declaration
-    constructor-declaration
-    destructor-declaration
-    trait-use-clauses
+trait-member-declaration:
+   property-declaration
+   method-declaration
+   constructor-declaration
+   destructor-declaration
+   trait-use-clauses
 
-  trait-use-clauses:
-    trait-use-clause
-    trait-use-clauses   trait-use-clause
+trait-use-clauses:
+   trait-use-clause
+   trait-use-clauses   trait-use-clause
 
-  trait-use-clause:
-    use   trait-name-list   trait-use-specification
+trait-use-clause:
+   use   trait-name-list   trait-use-specification
 
-  trait-name-list:
-    qualified-name
-    trait-name-list   ,   qualified-name
+trait-name-list:
+   qualified-name
+   trait-name-list   ,   qualified-name
 
-  trait-use-specification:
-    ;
-    {   trait-select-and-alias-clausesopt   }
+trait-use-specification:
+   ;
+   {   trait-select-and-alias-clausesopt   }
 
-  trait-select-and-alias-clauses:
-    trait-select-and-alias-clause
-    trait-select-and-alias-clauses   trait-select-and-alias-clause
+trait-select-and-alias-clauses:
+   trait-select-and-alias-clause
+   trait-select-and-alias-clauses   trait-select-and-alias-clause
 
-  trait-select-and-alias-clause:
-    trait-select-insteadof-clause ;
-    trait-alias-as-clause ;
+trait-select-and-alias-clause:
+   trait-select-insteadof-clause   ;
+   trait-alias-as-clause   ;
 
-  trait-select-insteadof-clause:
-    name   insteadof   name
+trait-select-insteadof-clause:
+   qualified-name   ::   name   insteadof   trait-name-list
 
-  trait-alias-as-clause:
-    name   as   visibility-modifieropt   name
-    name   as   visibility-modifier   nameopt
+trait-alias-as-clause:
+   name   as   visibility-modifieropt   name
+   name   as   visibility-modifier   nameopt
 
-###Namespaces +### Namespaces
-  namespace-definition:
-    namespace  name  ;
-    namespace  nameopt   compound-statement
+namespace-definition:
+   namespace   namespace-name   ;
+   namespace   namespace-nameopt   compound-statement
 
-  namespace-use-declaration:
-    use  namespace-function-or-constopt namespace-use-clauses  ;
-    use  namespace-function-or-const  \opt  namespace-name  \
-       {  namespace-use-group-clauses-1  }  ;
-    use  \opt   namespace-name   \   {  namespace-use-group-clauses-2  }  ;
+namespace-use-declaration:
+   use   namespace-function-or-constopt   namespace-use-clauses   ;
+   use   namespace-function-or-const   \opt   namespace-name   \   {   namespace-use-group-clauses-1   }   ;
+   use   \opt   namespace-name   \   {   namespace-use-group-clauses-2   }   ;
 
-  namespace-use-clauses:
-    namespace-use-clause
-    namespace-use-clauses  ,  namespace-use-clause
+namespace-use-clauses:
+   namespace-use-clause
+   namespace-use-clauses   ,   namespace-use-clause
 
-  namespace-use-clause:
-    qualified-name   namespace-aliasing-clauseopt
+namespace-use-clause:
+   qualified-name   namespace-aliasing-clauseopt
 
-  namespace-aliasing-clause:
-    as  name
+namespace-aliasing-clause:
+   as   name
 
-  namespace-function-or-const:
-    function
-    const
+namespace-function-or-const:
+   function
+   const
 
-  namespace-use-group-clauses-1:
-    namespace-use-group-clause-1
-    namespace-use-group-clauses-1  ,  namespace-use-group-clause-1
+namespace-use-group-clauses-1:
+   namespace-use-group-clause-1
+   namespace-use-group-clauses-1   ,   namespace-use-group-clause-1
 
-  namespace-use-group-clause-1:
-    namespace-name  namespace-aliasing-clauseopt
+namespace-use-group-clause-1:
+   namespace-name   namespace-aliasing-clauseopt
 
-  namespace-use-group-clauses-2:
-    namespace-use-group-clause-2
-    namespace-use-group-clauses-2  ,  namespace-use-group-clause-2
+namespace-use-group-clauses-2:
+   namespace-use-group-clause-2
+   namespace-use-group-clauses-2   ,   namespace-use-group-clause-2
 
-  namespace-use-group-clause-2:
-    namespace-function-or-constopt  namespace-name  namespace-aliasing-clauseopt
+namespace-use-group-clause-2:
+   namespace-function-or-constopt   namespace-name   namespace-aliasing-clauseopt
 
diff --git a/spec/20-bibliography.md b/spec/20-bibliography.md index 80f56e0a..fb03bd87 100644 --- a/spec/20-bibliography.md +++ b/spec/20-bibliography.md @@ -1,4 +1,4 @@ -#Bibliography +# Bibliography The following documents are useful references for implementers and users of this specification: @@ -10,4 +10,3 @@ IEEE Standard for Binary Floating-Point Arithmetic). The Unicode Consortium. *The Unicode Standard, Version 5.0*, [www.Unicode.org](http://www.Unicode.org)). - diff --git a/spec/php-spec-draft.md b/spec/php-spec-draft.md deleted file mode 120000 index a7c2f5e4..00000000 --- a/spec/php-spec-draft.md +++ /dev/null @@ -1 +0,0 @@ -00-specification-for-php.md \ No newline at end of file diff --git a/tests/README.md b/tests/README.md index 0acf1371..f5e7e2ee 100644 --- a/tests/README.md +++ b/tests/README.md @@ -4,11 +4,6 @@ If you pass this suite, you aren't necessarily spec compliant, but it is a helpf ## Usage -To run using the PHP5 test runner, you'll need to convert to PHP5's .phpt format first. The following demonstrates writing the tests out to /tmp/phpt: +To run using the PHP test runner, do something like: - ./make_phpt . /tmp/phpt TEST_PHP_EXECUTABLE=~/php-src/sapi/cli/php ~/php-src/run-tests.php /tmp/phpt - -To use the HHVM test runner: - - ~/hhvm/hphp/test/run . diff --git a/tests/arrays/arrays.phpt b/tests/arrays/arrays.phpt index c01c5833..bbc3a29c 100644 --- a/tests/arrays/arrays.phpt +++ b/tests/arrays/arrays.phpt @@ -108,8 +108,8 @@ foreach($v as $e) // only has 3 elements ([3], [6], and [7]), not 8 ([0]-[7]) } echo "\n"; -echo "\$v[1] is >".$v[1]."<\n"; var_dump($v1[1]); // access non-existant element -echo "\$v[4] is >".$v[4]."<\n"; var_dump($v1[4]); // access non-existant element +echo "\$v[1] is >".$v[1]."<\n"; var_dump($v1[1]); // access non-existent element +echo "\$v[4] is >".$v[4]."<\n"; var_dump($v1[4]); // access non-existent element $v[1] = TRUE; // increases array to 4 elements $v[4] = 99; // increases array to 5 elements diff --git a/tests/basic_concepts/memory_model_and_array_types.phpt b/tests/basic_concepts/memory_model_and_array_types.phpt index 9e240262..968dd79a 100644 --- a/tests/basic_concepts/memory_model_and_array_types.phpt +++ b/tests/basic_concepts/memory_model_and_array_types.phpt @@ -36,7 +36,7 @@ class Point { $this->x = $x; $this->y = $y; - } + } public function translate($x, $y) { @@ -62,7 +62,7 @@ class Point public function __toString() { return '(' . $this->x . ',' . $this->y . ')'; - } + } } ///* diff --git a/tests/basic_concepts/memory_model_and_handle_types.phpt b/tests/basic_concepts/memory_model_and_handle_types.phpt index 6394d579..f4f497f3 100644 --- a/tests/basic_concepts/memory_model_and_handle_types.phpt +++ b/tests/basic_concepts/memory_model_and_handle_types.phpt @@ -36,7 +36,7 @@ class Point { $this->x = $x; $this->y = $y; - } + } public function translate($x, $y) { @@ -62,7 +62,7 @@ class Point public function __toString() { return '(' . $this->x . ',' . $this->y . ')'; - } + } } ///* @@ -166,7 +166,7 @@ function g1(&$b) // make $b alias whatever $a aliases $b = new Point(5, 7); // removes second alias from first point; // then create first alias to second new point // changing $b also changes $a as well, so $a's alias - // is also removed, alowing the destructor run + // is also removed, allowing the destructor run echo "After 'new Point(5, 7)', \$b is $b\n"; } // $b goes away, remove its alias from new point diff --git a/tests/basic_concepts/storage_duration.phpt b/tests/basic_concepts/storage_duration.phpt index bdd71637..d582314c 100644 --- a/tests/basic_concepts/storage_duration.phpt +++ b/tests/basic_concepts/storage_duration.phpt @@ -36,7 +36,7 @@ class Point { $this->x = $x; $this->y = $y; - } + } public function translate($x, $y) { @@ -62,7 +62,7 @@ class Point public function __toString() { return '(' . $this->x . ',' . $this->y . ')'; - } + } } echo "---------------- start -------------------\n"; diff --git a/tests/classes/Aircraft.inc b/tests/classes/Aircraft.inc index 5454f2ec..e49fb8bf 100644 --- a/tests/classes/Aircraft.inc +++ b/tests/classes/Aircraft.inc @@ -10,7 +10,7 @@ error_reporting(-1); include_once 'Vehicle.inc'; -abstract class Aircraft extends Vehicle +abstract class Aircraft extends Vehicle { public abstract function getMaxAltitude(); // ... diff --git a/tests/classes/MathLibrary.inc b/tests/classes/MathLibrary.inc index 3bc3fb17..7d5d4b4d 100644 --- a/tests/classes/MathLibrary.inc +++ b/tests/classes/MathLibrary.inc @@ -8,7 +8,7 @@ error_reporting(-1); -final class MathLibrary +final class MathLibrary { private function __construct() {} // disallows instantiation diff --git a/tests/classes/MyCollection.inc b/tests/classes/MyCollection.inc index e9208ded..c15f32cc 100644 --- a/tests/classes/MyCollection.inc +++ b/tests/classes/MyCollection.inc @@ -8,7 +8,7 @@ error_reporting(-1); -interface MyCollection +interface MyCollection { function put($item); function get(); diff --git a/tests/classes/PassengerJet.inc b/tests/classes/PassengerJet.inc index 7d7130f9..5d830351 100644 --- a/tests/classes/PassengerJet.inc +++ b/tests/classes/PassengerJet.inc @@ -10,7 +10,7 @@ error_reporting(-1); include_once 'Aircraft.inc'; -class PassengerJet extends Aircraft +class PassengerJet extends Aircraft { public function getMaxSpeed() { diff --git a/tests/classes/Point.inc b/tests/classes/Point.inc index f62c6596..2942d85d 100644 --- a/tests/classes/Point.inc +++ b/tests/classes/Point.inc @@ -8,7 +8,7 @@ error_reporting(-1); -class Point +class Point { private $x; // Cartesian x-coordinate private $y; // Cartesian y-coordinate @@ -19,28 +19,28 @@ class Point public function setY($y) { $this->y = $y; } // public function __construct($x, $y) // see what happens if no default values - public function __construct($x = 0, $y = 0) + public function __construct($x = 0, $y = 0) { $this->x = $x; $this->y = $y; } - public function move($x, $y) + public function move($x, $y) { $this->x = $x; $this->y = $y; - } + } - public function translate($x, $y) + public function translate($x, $y) { $this->x += $x; $this->y += $y; } - public function __toString() + public function __toString() { // throw new Exception; // throw statement is not permitted return '(' . $this->x . ',' . $this->y . ')'; - } + } } diff --git a/tests/classes/Point2.inc b/tests/classes/Point2.inc index 29e1da60..59ded534 100644 --- a/tests/classes/Point2.inc +++ b/tests/classes/Point2.inc @@ -8,31 +8,31 @@ error_reporting(-1); -class Point2 +class Point2 { private static $pointCount = 0; public $x; // Cartesian x-coordinate public $y; // Cartesian y-coordinate - public static function getPointCount() + public static function getPointCount() { return self::$pointCount; } - public function __construct($x = 0, $y = 0) + public function __construct($x = 0, $y = 0) { $this->x = $x; $this->y = $y; ++self::$pointCount; } - public function __destruct() + public function __destruct() { --self::$pointCount; } ///* - public function __clone() + public function __clone() { ++self::$pointCount; @@ -43,9 +43,9 @@ class Point2 } //*/ - public function __toString() + public function __toString() { return '(' . $this->x . ',' . $this->y . ')'; - } + } } diff --git a/tests/classes/Vehicle.inc b/tests/classes/Vehicle.inc index 9250c5a7..db9e69ef 100644 --- a/tests/classes/Vehicle.inc +++ b/tests/classes/Vehicle.inc @@ -8,7 +8,7 @@ error_reporting(-1); -abstract class Vehicle +abstract class Vehicle { public abstract function getMaxSpeed(); diff --git a/tests/classes/cloning.phpt b/tests/classes/cloning.phpt index 501dd5d6..ce2256ce 100644 --- a/tests/classes/cloning.phpt +++ b/tests/classes/cloning.phpt @@ -58,7 +58,7 @@ echo "Point count = " . Point2::getPointCount() . "\n"; var_dump($p4 = clone $p1); echo "Point count = " . Point2::getPointCount() . "\n"; -echo "================= use chained cloning in a class heirarchy =================\n"; +echo "================= use chained cloning in a class hierarchy =================\n"; class Employee { @@ -154,7 +154,7 @@ object(Point2)#6 (2) { int(0) } Point count = 4 -================= use chained cloning in a class heirarchy ================= +================= use chained cloning in a class hierarchy ================= object(Manager)#7 (2) { ["level":"Manager":private]=> int(23) diff --git a/tests/classes/dynamic_methods.phpt b/tests/classes/dynamic_methods.phpt index 0fb4b6ae..002497ec 100644 --- a/tests/classes/dynamic_methods.phpt +++ b/tests/classes/dynamic_methods.phpt @@ -50,7 +50,7 @@ $obj = new Widget; $v = $obj->iDoit(); $obj->__call('iDoit', []); -$v = $obj->iMethod(10, TRUE, "abc"); +$v = $obj->iMethod(10, TRUE, "abc",); var_dump($v); $obj->__call('iMethod', array(10, TRUE, "abc")); $obj->__call('123#$%', []); @@ -58,7 +58,7 @@ $obj->__call('123#$%', []); $v = Widget::sDoit(); Widget::__callStatic('sDoit', []); -$v = Widget::sMethod(NULL, 1.234); +$v = Widget::sMethod(NULL, 1.234,); var_dump($v); Widget::__callStatic('sMethod', array(NULL, 1.234)); Widget::__callStatic('[]{}', []); diff --git a/tests/classes/overloading_play.phpt b/tests/classes/overloading_play.phpt index 417e34aa..6bc2ba66 100644 --- a/tests/classes/overloading_play.phpt +++ b/tests/classes/overloading_play.phpt @@ -78,7 +78,7 @@ var_dump($v); echo "----------------------\n"; -var_dump(isset($obj->hidden)); // test if hidden exists and is accesible, or is dynamic +var_dump(isset($obj->hidden)); // test if hidden exists and is accessible, or is dynamic echo "----------------------\n"; @@ -88,7 +88,7 @@ echo "hidden: $v\n"; echo "----------------------\n"; -var_dump(isset($obj->hidden)); // test if hidden exists and is accesible, or is dynamic +var_dump(isset($obj->hidden)); // test if hidden exists and is accessible, or is dynamic echo "----------------------\n"; diff --git a/tests/classes/property_initializer.phpt b/tests/classes/property_initializer.phpt index 4d1eacf4..8837354a 100644 --- a/tests/classes/property_initializer.phpt +++ b/tests/classes/property_initializer.phpt @@ -26,7 +26,7 @@ class Point public function __toString() { return '(' . $this->x . ',' . $this->y . ')'; - } + } } $p = new Point; @@ -35,7 +35,7 @@ echo $p . "\n"; $p = new Point(); echo $p . "\n"; -$p = new Point(100); +$p = new Point(100,); echo $p . "\n"; $p = new Point(1000, 2000); diff --git a/tests/classes/serializable.phpt b/tests/classes/serializable.phpt index 897d8d4f..859f24a6 100644 --- a/tests/classes/serializable.phpt +++ b/tests/classes/serializable.phpt @@ -31,12 +31,12 @@ class Point implements Serializable public function __toString() { return 'ID:' . $this->id . '(' . $this->x . ',' . $this->y . ')'; - } + } public function serialize() { echo "\nInside " . __METHOD__ . ", $this\n\n"; - + return serialize(array('y' => $this->y, 'x' => $this->x)); } @@ -84,12 +84,12 @@ class ColoredPoint extends Point implements Serializable public function __toString() { return parent::__toString() . $this->color; - } + } public function serialize() { echo "\nInside " . __METHOD__ . ", $this\n\n"; - + return serialize(array( 'color' => $this->color, 'baseData' => parent::serialize() diff --git a/tests/classes/sleep_and_wakeup.phpt b/tests/classes/sleep_and_wakeup.phpt index 0974abc5..6c1d5dc4 100644 Binary files a/tests/classes/sleep_and_wakeup.phpt and b/tests/classes/sleep_and_wakeup.phpt differ diff --git a/tests/classes/visibility.phpt b/tests/classes/visibility.phpt index 49f5cae3..4b483652 100644 --- a/tests/classes/visibility.phpt +++ b/tests/classes/visibility.phpt @@ -15,10 +15,12 @@ class C { // constants - const CON1 = 123; // implicitly static, and can't say so explicitly -// public const CON2 = 123; // class constants are implicitly public; can't say explicitly -// protected const CON3 = 123; // class constants are implicitly public -// private const CON4 = 123; // class constants are implicitly public + const CON1 = 123; // implicitly static and can't say so explicitly + // implicitly public + + public const CON2 = 123; // explicitly public + protected const CON3 = 123; // protected constant + private const CON4 = 123; // private constant // properties diff --git a/tests/constants/constants.phpt b/tests/constants/constants.phpt index 66e1c079..23f3324b 100644 --- a/tests/constants/constants.phpt +++ b/tests/constants/constants.phpt @@ -11,9 +11,9 @@ PHP Spec test generated from ./constants/constants.php error_reporting(-1); -function trace($name, $value, $b = FALSE) +function trace($name, $value) { - $r = define($name, $value, $b); + $r = define($name, $value); echo "define $name " . ($r ? "succeeded" : "failed"); if (defined($name)) echo "; value is >" . constant($name) . "<\n"; @@ -26,7 +26,7 @@ function trace($name, $value, $b = FALSE) trace("STATUS1", TRUE); trace("MIN", 10); -trace("MAX", 20, TRUE); // HHVM Warning: Case insensitive constant names are not supported in HipHop +trace("MAX", 20); trace("MY_PI", 3.1415926); trace("MY_COLOR", "red"); trace("C1", NULL); @@ -149,7 +149,7 @@ function f($p) // const CON71A = 101; // unexpected 'const' trace("CON71B", 101); // succeeded } -} +} f(10); //*/ @@ -165,14 +165,21 @@ trace("FOR", 100); // succeeded class C3 { - const CON1 = 123; // implicitly static, and can't say so explicitly -// public const CON2 = 123; // all class constants are implicitly public; can't say explicitly -// protected const CON3 = 123; // all class constants are implicitly public -// private const CON4 = 123; // all class constants are implicitly public + + const CON1 = 123; // implicitly static and can't say so explicitly + // implicitly public + + public const CON2 = 123; // explicitly public + protected const CON3 = 123; // protected constant + private const CON4 = 123; // private constant } echo "CON1: " . C3::CON1 . "\n"; // use :: notation, as a const is implicitly static +// public const CON80 = 80; // top level const can not have visibility modifier +// protected const CON81 = 81; // top level const can not have visibility modifier +// private const CON82 = 82; // top level const can not have visibility modifier + //print_r(get_defined_constants()); --EXPECTF-- define STATUS1 succeeded; value is >1< @@ -199,13 +206,15 @@ define #%& succeeded; value is >200< Notice: Constant MY_COLOR already defined in %s/constants/constants.php on line 13 define MY_COLOR failed; value is >red< -define TRUE succeeded; value is >999< + +Notice: Constant TRUE already defined in %s/constants/constants.php on line 13 +define TRUE failed; value is >1< TRUE's value:1 define COLORS succeeded Notice: Array to string conversion in %s/constants/constants.php on line 16 ; value is >Array< -Warning: Constants may only evaluate to scalar values or arrays in %s/constants/constants.php on line 13 +Warning: Constants may only evaluate to scalar values, arrays or resources in %s/constants/constants.php on line 13 define MY_OBJECT failed; not defined Warning: fopen(Testfile.txt): failed to open stream: No such file or directory in %s/constants/constants.php on line 90 diff --git a/tests/exception_handling/MyRangeException.inc b/tests/exception_handling/MyRangeException.inc index feb0468b..e17c820b 100644 --- a/tests/exception_handling/MyRangeException.inc +++ b/tests/exception_handling/MyRangeException.inc @@ -8,7 +8,7 @@ error_reporting(-1); -class MyRangeException extends Exception +class MyRangeException extends Exception { private $badValue; private $lowerValue; @@ -27,7 +27,7 @@ class MyRangeException extends Exception public function getLowerValue() { return $this->lowerValue; } public function getUpperValue() { return $this->upperValue; } - public function __toString() + public function __toString() { return parent::__toString() . ", badValue: " . $this->badValue diff --git a/tests/expressions/assignment_operators/add_assignment.phpt b/tests/expressions/assignment_operators/add_assignment.phpt index 622e9146..bfec7698 100644 --- a/tests/expressions/assignment_operators/add_assignment.phpt +++ b/tests/expressions/assignment_operators/add_assignment.phpt @@ -16,7 +16,7 @@ foreach ($oper as $t) } ?> ---EXPECT-- +--EXPECTF-- >0< += >0<, result: int(0) >0< += >-10<, result: int(-10) >0< += >100<, result: int(100) @@ -29,8 +29,12 @@ foreach ($oper as $t) >0< += ><, result: int(0) >0< += >123<, result: int(123) >0< += >2e+5<, result: float(200000) ->0< += ><, result: int(0) ->0< += >abc<, result: int(0) +>0< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>0< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >0< += >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >-10< += >0<, result: int(-10) @@ -45,8 +49,12 @@ foreach ($oper as $t) >-10< += ><, result: int(-10) >-10< += >123<, result: int(113) >-10< += >2e+5<, result: float(199990) ->-10< += ><, result: int(-10) ->-10< += >abc<, result: int(-10) +>-10< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) +>-10< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) >-10< += >9223372036854775807<, result: int(9223372036854775797) ------------------------------------- >100< += >0<, result: int(100) @@ -61,8 +69,12 @@ foreach ($oper as $t) >100< += ><, result: int(100) >100< += >123<, result: int(223) >100< += >2e+5<, result: float(200100) ->100< += ><, result: int(100) ->100< += >abc<, result: int(100) +>100< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) +>100< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) >100< += >9223372036854775807<, result: float(9.2233720368548E+18) ------------------------------------- >-34000000000< += >0<, result: float(-34000000000) @@ -77,8 +89,12 @@ foreach ($oper as $t) >-34000000000< += ><, result: float(-34000000000) >-34000000000< += >123<, result: float(-33999999877) >-34000000000< += >2e+5<, result: float(-33999800000) ->-34000000000< += ><, result: float(-34000000000) ->-34000000000< += >abc<, result: float(-34000000000) +>-34000000000< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(-34000000000) +>-34000000000< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-34000000000) >-34000000000< += >9223372036854775807<, result: float(9.2233720028548E+18) ------------------------------------- >INF< += >0<, result: float(INF) @@ -93,8 +109,12 @@ foreach ($oper as $t) >INF< += ><, result: float(INF) >INF< += >123<, result: float(INF) >INF< += >2e+5<, result: float(INF) ->INF< += ><, result: float(INF) ->INF< += >abc<, result: float(INF) +>INF< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(INF) +>INF< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(INF) >INF< += >9223372036854775807<, result: float(INF) ------------------------------------- >-INF< += >0<, result: float(-INF) @@ -109,8 +129,12 @@ foreach ($oper as $t) >-INF< += ><, result: float(-INF) >-INF< += >123<, result: float(-INF) >-INF< += >2e+5<, result: float(-INF) ->-INF< += ><, result: float(-INF) ->-INF< += >abc<, result: float(-INF) +>-INF< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(-INF) +>-INF< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-INF) >-INF< += >9223372036854775807<, result: float(-INF) ------------------------------------- >NAN< += >0<, result: float(NAN) @@ -125,8 +149,12 @@ foreach ($oper as $t) >NAN< += ><, result: float(NAN) >NAN< += >123<, result: float(NAN) >NAN< += >2e+5<, result: float(NAN) ->NAN< += ><, result: float(NAN) ->NAN< += >abc<, result: float(NAN) +>NAN< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>NAN< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) >NAN< += >9223372036854775807<, result: float(NAN) ------------------------------------- >1< += >0<, result: int(1) @@ -141,8 +169,12 @@ foreach ($oper as $t) >1< += ><, result: int(1) >1< += >123<, result: int(124) >1< += >2e+5<, result: float(200001) ->1< += ><, result: int(1) ->1< += >abc<, result: int(1) +>1< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) +>1< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) >1< += >9223372036854775807<, result: float(9.2233720368548E+18) ------------------------------------- >< += >0<, result: int(0) @@ -157,8 +189,12 @@ foreach ($oper as $t) >< += ><, result: int(0) >< += >123<, result: int(123) >< += >2e+5<, result: float(200000) ->< += ><, result: int(0) ->< += >abc<, result: int(0) +>< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< += >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >< += >0<, result: int(0) @@ -173,8 +209,12 @@ foreach ($oper as $t) >< += ><, result: int(0) >< += >123<, result: int(123) >< += >2e+5<, result: float(200000) ->< += ><, result: int(0) ->< += >abc<, result: int(0) +>< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< += >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >123< += >0<, result: int(123) @@ -189,8 +229,12 @@ foreach ($oper as $t) >123< += ><, result: int(123) >123< += >123<, result: int(246) >123< += >2e+5<, result: float(200123) ->123< += ><, result: int(123) ->123< += >abc<, result: int(123) +>123< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(123) +>123< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(123) >123< += >9223372036854775807<, result: float(9.2233720368548E+18) ------------------------------------- >2e+5< += >0<, result: float(200000) @@ -205,41 +249,113 @@ foreach ($oper as $t) >2e+5< += ><, result: float(200000) >2e+5< += >123<, result: float(200123) >2e+5< += >2e+5<, result: float(400000) ->2e+5< += ><, result: float(200000) ->2e+5< += >abc<, result: float(200000) +>2e+5< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(200000) +>2e+5< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(200000) >2e+5< += >9223372036854775807<, result: float(9.223372036855E+18) ------------------------------------- ->< += >0<, result: int(0) ->< += >-10<, result: int(-10) ->< += >100<, result: int(100) ->< += >-34000000000<, result: float(-34000000000) ->< += >INF<, result: float(INF) ->< += >-INF<, result: float(-INF) ->< += >NAN<, result: float(NAN) ->< += >1<, result: int(1) ->< += ><, result: int(0) ->< += ><, result: int(0) ->< += >123<, result: int(123) ->< += >2e+5<, result: float(200000) ->< += ><, result: int(0) ->< += >abc<, result: int(0) ->< += >9223372036854775807<, result: int(9223372036854775807) +>< += >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< += >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) +>< += >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) +>< += >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-34000000000) +>< += >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(INF) +>< += >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-INF) +>< += >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>< += >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) +>< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< += >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(123) +>< += >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +float(200000) +>< += ><, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< += >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) ------------------------------------- ->abc< += >0<, result: int(0) ->abc< += >-10<, result: int(-10) ->abc< += >100<, result: int(100) ->abc< += >-34000000000<, result: float(-34000000000) ->abc< += >INF<, result: float(INF) ->abc< += >-INF<, result: float(-INF) ->abc< += >NAN<, result: float(NAN) ->abc< += >1<, result: int(1) ->abc< += ><, result: int(0) ->abc< += ><, result: int(0) ->abc< += >123<, result: int(123) ->abc< += >2e+5<, result: float(200000) ->abc< += ><, result: int(0) ->abc< += >abc<, result: int(0) ->abc< += >9223372036854775807<, result: int(9223372036854775807) +>abc< += >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< += >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) +>abc< += >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) +>abc< += >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-34000000000) +>abc< += >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(INF) +>abc< += >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-INF) +>abc< += >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>abc< += >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) +>abc< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< += >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(123) +>abc< += >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +float(200000) +>abc< += ><, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< += >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) ------------------------------------- >9223372036854775807< += >0<, result: int(9223372036854775807) >9223372036854775807< += >-10<, result: int(9223372036854775797) @@ -253,7 +369,11 @@ foreach ($oper as $t) >9223372036854775807< += ><, result: int(9223372036854775807) >9223372036854775807< += >123<, result: float(9.2233720368548E+18) >9223372036854775807< += >2e+5<, result: float(9.223372036855E+18) ->9223372036854775807< += ><, result: int(9223372036854775807) ->9223372036854775807< += >abc<, result: int(9223372036854775807) +>9223372036854775807< += ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) +>9223372036854775807< += >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) >9223372036854775807< += >9223372036854775807<, result: float(1.844674407371E+19) -------------------------------------- \ No newline at end of file +------------------------------------- diff --git a/tests/expressions/assignment_operators/and_assignment.phpt b/tests/expressions/assignment_operators/and_assignment.phpt index 4a8259f5..e32149bb 100644 --- a/tests/expressions/assignment_operators/and_assignment.phpt +++ b/tests/expressions/assignment_operators/and_assignment.phpt @@ -16,7 +16,7 @@ foreach ($oper as $t) } ?> ---EXPECT-- +--EXPECTF-- >0< &= >0<, result: int(0) >0< &= >-10<, result: int(0) >0< &= >100<, result: int(0) @@ -29,8 +29,12 @@ foreach ($oper as $t) >0< &= ><, result: int(0) >0< &= >123<, result: int(0) >0< &= >2e+5<, result: int(0) ->0< &= ><, result: int(0) ->0< &= >abc<, result: int(0) +>0< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>0< &= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >0< &= >9223372036854775807<, result: int(0) ------------------------------------- >-10< &= >0<, result: int(0) @@ -44,9 +48,13 @@ foreach ($oper as $t) >-10< &= ><, result: int(0) >-10< &= ><, result: int(0) >-10< &= >123<, result: int(114) ->-10< &= >2e+5<, result: int(2) ->-10< &= ><, result: int(0) ->-10< &= >abc<, result: int(0) +>-10< &= >2e+5<, result: int(200000) +>-10< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>-10< &= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >-10< &= >9223372036854775807<, result: int(9223372036854775798) ------------------------------------- >100< &= >0<, result: int(0) @@ -60,9 +68,13 @@ foreach ($oper as $t) >100< &= ><, result: int(0) >100< &= ><, result: int(0) >100< &= >123<, result: int(96) ->100< &= >2e+5<, result: int(0) ->100< &= ><, result: int(0) ->100< &= >abc<, result: int(0) +>100< &= >2e+5<, result: int(64) +>100< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>100< &= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >100< &= >9223372036854775807<, result: int(100) ------------------------------------- >-34000000000< &= >0<, result: int(0) @@ -76,9 +88,13 @@ foreach ($oper as $t) >-34000000000< &= ><, result: int(0) >-34000000000< &= ><, result: int(0) >-34000000000< &= >123<, result: int(0) ->-34000000000< &= >2e+5<, result: int(0) ->-34000000000< &= ><, result: int(0) ->-34000000000< &= >abc<, result: int(0) +>-34000000000< &= >2e+5<, result: int(68608) +>-34000000000< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>-34000000000< &= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >-34000000000< &= >9223372036854775807<, result: int(9223372002854775808) ------------------------------------- >INF< &= >0<, result: int(0) @@ -93,8 +109,12 @@ foreach ($oper as $t) >INF< &= ><, result: int(0) >INF< &= >123<, result: int(0) >INF< &= >2e+5<, result: int(0) ->INF< &= ><, result: int(0) ->INF< &= >abc<, result: int(0) +>INF< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>INF< &= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >INF< &= >9223372036854775807<, result: int(0) ------------------------------------- >-INF< &= >0<, result: int(0) @@ -109,8 +129,12 @@ foreach ($oper as $t) >-INF< &= ><, result: int(0) >-INF< &= >123<, result: int(0) >-INF< &= >2e+5<, result: int(0) ->-INF< &= ><, result: int(0) ->-INF< &= >abc<, result: int(0) +>-INF< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>-INF< &= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >-INF< &= >9223372036854775807<, result: int(0) ------------------------------------- >NAN< &= >0<, result: int(0) @@ -125,8 +149,12 @@ foreach ($oper as $t) >NAN< &= ><, result: int(0) >NAN< &= >123<, result: int(0) >NAN< &= >2e+5<, result: int(0) ->NAN< &= ><, result: int(0) ->NAN< &= >abc<, result: int(0) +>NAN< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>NAN< &= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >NAN< &= >9223372036854775807<, result: int(0) ------------------------------------- >1< &= >0<, result: int(0) @@ -141,8 +169,12 @@ foreach ($oper as $t) >1< &= ><, result: int(0) >1< &= >123<, result: int(1) >1< &= >2e+5<, result: int(0) ->1< &= ><, result: int(0) ->1< &= >abc<, result: int(0) +>1< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>1< &= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >1< &= >9223372036854775807<, result: int(1) ------------------------------------- >< &= >0<, result: int(0) @@ -157,8 +189,12 @@ foreach ($oper as $t) >< &= ><, result: int(0) >< &= >123<, result: int(0) >< &= >2e+5<, result: int(0) ->< &= ><, result: int(0) ->< &= >abc<, result: int(0) +>< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< &= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< &= >9223372036854775807<, result: int(0) ------------------------------------- >< &= >0<, result: int(0) @@ -173,8 +209,12 @@ foreach ($oper as $t) >< &= ><, result: int(0) >< &= >123<, result: int(0) >< &= >2e+5<, result: int(0) ->< &= ><, result: int(0) ->< &= >abc<, result: int(0) +>< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< &= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< &= >9223372036854775807<, result: int(0) ------------------------------------- >123< &= >0<, result: int(0) @@ -194,9 +234,9 @@ foreach ($oper as $t) >123< &= >9223372036854775807<, result: int(123) ------------------------------------- >2e+5< &= >0<, result: int(0) ->2e+5< &= >-10<, result: int(2) ->2e+5< &= >100<, result: int(0) ->2e+5< &= >-34000000000<, result: int(0) +>2e+5< &= >-10<, result: int(200000) +>2e+5< &= >100<, result: int(64) +>2e+5< &= >-34000000000<, result: int(68608) >2e+5< &= >INF<, result: int(0) >2e+5< &= >-INF<, result: int(0) >2e+5< &= >NAN<, result: int(0) @@ -207,39 +247,83 @@ foreach ($oper as $t) >2e+5< &= >2e+5<, result: string(4) "2e+5" >2e+5< &= ><, result: string(0) "" >2e+5< &= >abc<, result: string(3) " `#" ->2e+5< &= >9223372036854775807<, result: int(2) +>2e+5< &= >9223372036854775807<, result: int(200000) ------------------------------------- ->< &= >0<, result: int(0) ->< &= >-10<, result: int(0) ->< &= >100<, result: int(0) ->< &= >-34000000000<, result: int(0) ->< &= >INF<, result: int(0) ->< &= >-INF<, result: int(0) ->< &= >NAN<, result: int(0) ->< &= >1<, result: int(0) ->< &= ><, result: int(0) ->< &= ><, result: int(0) +>< &= >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< &= >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< &= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< &= >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< &= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< &= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< &= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< &= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< &= >123<, result: string(0) "" >< &= >2e+5<, result: string(0) "" >< &= ><, result: string(0) "" >< &= >abc<, result: string(0) "" ->< &= >9223372036854775807<, result: int(0) +>< &= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- ->abc< &= >0<, result: int(0) ->abc< &= >-10<, result: int(0) ->abc< &= >100<, result: int(0) ->abc< &= >-34000000000<, result: int(0) ->abc< &= >INF<, result: int(0) ->abc< &= >-INF<, result: int(0) ->abc< &= >NAN<, result: int(0) ->abc< &= >1<, result: int(0) ->abc< &= ><, result: int(0) ->abc< &= ><, result: int(0) +>abc< &= >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< &= >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< &= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< &= >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< &= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< &= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< &= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< &= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >abc< &= >123<, result: string(3) "!"#" >abc< &= >2e+5<, result: string(3) " `#" >abc< &= ><, result: string(0) "" >abc< &= >abc<, result: string(3) "abc" ->abc< &= >9223372036854775807<, result: int(0) +>abc< &= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- >9223372036854775807< &= >0<, result: int(0) >9223372036854775807< &= >-10<, result: int(9223372036854775798) @@ -252,8 +336,12 @@ foreach ($oper as $t) >9223372036854775807< &= ><, result: int(0) >9223372036854775807< &= ><, result: int(0) >9223372036854775807< &= >123<, result: int(123) ->9223372036854775807< &= >2e+5<, result: int(2) ->9223372036854775807< &= ><, result: int(0) ->9223372036854775807< &= >abc<, result: int(0) +>9223372036854775807< &= >2e+5<, result: int(200000) +>9223372036854775807< &= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>9223372036854775807< &= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >9223372036854775807< &= >9223372036854775807<, result: int(9223372036854775807) -------------------------------------- \ No newline at end of file +------------------------------------- diff --git a/tests/expressions/assignment_operators/concat_assignment.phpt b/tests/expressions/assignment_operators/concat_assignment.phpt index 07467a0a..80d21d80 100644 --- a/tests/expressions/assignment_operators/concat_assignment.phpt +++ b/tests/expressions/assignment_operators/concat_assignment.phpt @@ -256,4 +256,4 @@ foreach ($oper as $t) >9223372036854775807< .= ><, result: string(19) "9223372036854775807" >9223372036854775807< .= >abc<, result: string(22) "9223372036854775807abc" >9223372036854775807< .= >9223372036854775807<, result: string(38) "92233720368547758079223372036854775807" -------------------------------------- \ No newline at end of file +------------------------------------- diff --git a/tests/expressions/assignment_operators/div_assignment.phpt b/tests/expressions/assignment_operators/div_assignment.phpt index baa6471b..ddb2c315 100644 --- a/tests/expressions/assignment_operators/div_assignment.phpt +++ b/tests/expressions/assignment_operators/div_assignment.phpt @@ -18,7 +18,7 @@ foreach ($oper as $t) } ?> ---EXPECT-- +--EXPECTF-- >0< /= >-10<, result: int(0) >0< /= >100<, result: int(0) >0< /= >-34000000000<, result: float(-0) @@ -151,27 +151,67 @@ foreach ($oper as $t) >2e+5< /= >2e+5<, result: float(1) >2e+5< /= >9223372036854775807<, result: float(2.168404344971E-14) ------------------------------------- ->< /= >-10<, result: int(0) ->< /= >100<, result: int(0) ->< /= >-34000000000<, result: float(-0) ->< /= >INF<, result: float(0) ->< /= >-INF<, result: float(-0) ->< /= >NAN<, result: float(NAN) ->< /= >1<, result: int(0) ->< /= >123<, result: int(0) ->< /= >2e+5<, result: float(0) ->< /= >9223372036854775807<, result: int(0) +>< /= >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< /= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< /= >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>< /= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>< /= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>< /= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>< /= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< /= >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< /= >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>< /= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- ->abc< /= >-10<, result: int(0) ->abc< /= >100<, result: int(0) ->abc< /= >-34000000000<, result: float(-0) ->abc< /= >INF<, result: float(0) ->abc< /= >-INF<, result: float(-0) ->abc< /= >NAN<, result: float(NAN) ->abc< /= >1<, result: int(0) ->abc< /= >123<, result: int(0) ->abc< /= >2e+5<, result: float(0) ->abc< /= >9223372036854775807<, result: int(0) +>abc< /= >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< /= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< /= >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>abc< /= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>abc< /= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>abc< /= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>abc< /= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< /= >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< /= >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>abc< /= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- >9223372036854775807< /= >-10<, result: float(-9.2233720368548E+17) >9223372036854775807< /= >100<, result: float(9.2233720368548E+16) @@ -183,4 +223,4 @@ foreach ($oper as $t) >9223372036854775807< /= >123<, result: float(7.4986764527275E+16) >9223372036854775807< /= >2e+5<, result: float(46116860184274) >9223372036854775807< /= >9223372036854775807<, result: int(1) -------------------------------------- \ No newline at end of file +------------------------------------- diff --git a/tests/expressions/assignment_operators/mod_assignment.phpt b/tests/expressions/assignment_operators/mod_assignment.phpt index 87681300..252fdbb2 100644 --- a/tests/expressions/assignment_operators/mod_assignment.phpt +++ b/tests/expressions/assignment_operators/mod_assignment.phpt @@ -1,5 +1,5 @@ --TEST-- -/= operator +%= operator --FILE-- ---EXPECT-- +--EXPECTF-- >0< %= >-10<, result: int(0) >0< %= >100<, result: int(0) >0< %= >-34000000000<, result: int(0) @@ -32,7 +32,7 @@ foreach ($oper as $t) >-10< %= >-34000000000<, result: int(-10) >-10< %= >1<, result: int(0) >-10< %= >123<, result: int(-10) ->-10< %= >2e+5<, result: int(0) +>-10< %= >2e+5<, result: int(-10) >-10< %= >9223372036854775807<, result: int(-10) ------------------------------------- >100< %= >-10<, result: int(0) @@ -40,7 +40,7 @@ foreach ($oper as $t) >100< %= >-34000000000<, result: int(100) >100< %= >1<, result: int(0) >100< %= >123<, result: int(100) ->100< %= >2e+5<, result: int(0) +>100< %= >2e+5<, result: int(100) >100< %= >9223372036854775807<, result: int(100) ------------------------------------- >-34000000000< %= >-10<, result: int(0) @@ -104,38 +104,66 @@ foreach ($oper as $t) >123< %= >-34000000000<, result: int(123) >123< %= >1<, result: int(0) >123< %= >123<, result: int(0) ->123< %= >2e+5<, result: int(1) +>123< %= >2e+5<, result: int(123) >123< %= >9223372036854775807<, result: int(123) ------------------------------------- ->2e+5< %= >-10<, result: int(2) ->2e+5< %= >100<, result: int(2) ->2e+5< %= >-34000000000<, result: int(2) +>2e+5< %= >-10<, result: int(0) +>2e+5< %= >100<, result: int(0) +>2e+5< %= >-34000000000<, result: int(200000) >2e+5< %= >1<, result: int(0) >2e+5< %= >123<, result: int(2) >2e+5< %= >2e+5<, result: int(0) ->2e+5< %= >9223372036854775807<, result: int(2) +>2e+5< %= >9223372036854775807<, result: int(200000) ------------------------------------- ->< %= >-10<, result: int(0) ->< %= >100<, result: int(0) ->< %= >-34000000000<, result: int(0) ->< %= >1<, result: int(0) ->< %= >123<, result: int(0) ->< %= >2e+5<, result: int(0) ->< %= >9223372036854775807<, result: int(0) +>< %= >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< %= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< %= >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< %= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< %= >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< %= >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< %= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- ->abc< %= >-10<, result: int(0) ->abc< %= >100<, result: int(0) ->abc< %= >-34000000000<, result: int(0) ->abc< %= >1<, result: int(0) ->abc< %= >123<, result: int(0) ->abc< %= >2e+5<, result: int(0) ->abc< %= >9223372036854775807<, result: int(0) +>abc< %= >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< %= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< %= >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< %= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< %= >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< %= >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< %= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- >9223372036854775807< %= >-10<, result: int(7) >9223372036854775807< %= >100<, result: int(7) >9223372036854775807< %= >-34000000000<, result: int(4854775807) >9223372036854775807< %= >1<, result: int(0) >9223372036854775807< %= >123<, result: int(7) ->9223372036854775807< %= >2e+5<, result: int(1) +>9223372036854775807< %= >2e+5<, result: int(175807) >9223372036854775807< %= >9223372036854775807<, result: int(0) -------------------------------------- \ No newline at end of file +------------------------------------- diff --git a/tests/expressions/assignment_operators/mul_assignment.phpt b/tests/expressions/assignment_operators/mul_assignment.phpt index 833066de..ab33ab36 100644 --- a/tests/expressions/assignment_operators/mul_assignment.phpt +++ b/tests/expressions/assignment_operators/mul_assignment.phpt @@ -16,7 +16,7 @@ foreach ($oper as $t) } ?> ---EXPECT-- +--EXPECTF-- >0< *= >0<, result: int(0) >0< *= >-10<, result: int(0) >0< *= >100<, result: int(0) @@ -29,8 +29,12 @@ foreach ($oper as $t) >0< *= ><, result: int(0) >0< *= >123<, result: int(0) >0< *= >2e+5<, result: float(0) ->0< *= ><, result: int(0) ->0< *= >abc<, result: int(0) +>0< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>0< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >0< *= >9223372036854775807<, result: int(0) ------------------------------------- >-10< *= >0<, result: int(0) @@ -45,8 +49,12 @@ foreach ($oper as $t) >-10< *= ><, result: int(0) >-10< *= >123<, result: int(-1230) >-10< *= >2e+5<, result: float(-2000000) ->-10< *= ><, result: int(0) ->-10< *= >abc<, result: int(0) +>-10< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>-10< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >-10< *= >9223372036854775807<, result: float(-9.2233720368548E+19) ------------------------------------- >100< *= >0<, result: int(0) @@ -61,8 +69,12 @@ foreach ($oper as $t) >100< *= ><, result: int(0) >100< *= >123<, result: int(12300) >100< *= >2e+5<, result: float(20000000) ->100< *= ><, result: int(0) ->100< *= >abc<, result: int(0) +>100< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>100< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >100< *= >9223372036854775807<, result: float(9.2233720368548E+20) ------------------------------------- >-34000000000< *= >0<, result: float(-0) @@ -77,8 +89,12 @@ foreach ($oper as $t) >-34000000000< *= ><, result: float(-0) >-34000000000< *= >123<, result: float(-4182000000000) >-34000000000< *= >2e+5<, result: float(-6.8E+15) ->-34000000000< *= ><, result: float(-0) ->-34000000000< *= >abc<, result: float(-0) +>-34000000000< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>-34000000000< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) >-34000000000< *= >9223372036854775807<, result: float(-3.1359464925306E+29) ------------------------------------- >INF< *= >0<, result: float(NAN) @@ -93,8 +109,12 @@ foreach ($oper as $t) >INF< *= ><, result: float(NAN) >INF< *= >123<, result: float(INF) >INF< *= >2e+5<, result: float(INF) ->INF< *= ><, result: float(NAN) ->INF< *= >abc<, result: float(NAN) +>INF< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>INF< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) >INF< *= >9223372036854775807<, result: float(INF) ------------------------------------- >-INF< *= >0<, result: float(NAN) @@ -109,8 +129,12 @@ foreach ($oper as $t) >-INF< *= ><, result: float(NAN) >-INF< *= >123<, result: float(-INF) >-INF< *= >2e+5<, result: float(-INF) ->-INF< *= ><, result: float(NAN) ->-INF< *= >abc<, result: float(NAN) +>-INF< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>-INF< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) >-INF< *= >9223372036854775807<, result: float(-INF) ------------------------------------- >NAN< *= >0<, result: float(NAN) @@ -125,8 +149,12 @@ foreach ($oper as $t) >NAN< *= ><, result: float(NAN) >NAN< *= >123<, result: float(NAN) >NAN< *= >2e+5<, result: float(NAN) ->NAN< *= ><, result: float(NAN) ->NAN< *= >abc<, result: float(NAN) +>NAN< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>NAN< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) >NAN< *= >9223372036854775807<, result: float(NAN) ------------------------------------- >1< *= >0<, result: int(0) @@ -141,8 +169,12 @@ foreach ($oper as $t) >1< *= ><, result: int(0) >1< *= >123<, result: int(123) >1< *= >2e+5<, result: float(200000) ->1< *= ><, result: int(0) ->1< *= >abc<, result: int(0) +>1< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>1< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >1< *= >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >< *= >0<, result: int(0) @@ -157,8 +189,12 @@ foreach ($oper as $t) >< *= ><, result: int(0) >< *= >123<, result: int(0) >< *= >2e+5<, result: float(0) ->< *= ><, result: int(0) ->< *= >abc<, result: int(0) +>< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< *= >9223372036854775807<, result: int(0) ------------------------------------- >< *= >0<, result: int(0) @@ -173,8 +209,12 @@ foreach ($oper as $t) >< *= ><, result: int(0) >< *= >123<, result: int(0) >< *= >2e+5<, result: float(0) ->< *= ><, result: int(0) ->< *= >abc<, result: int(0) +>< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< *= >9223372036854775807<, result: int(0) ------------------------------------- >123< *= >0<, result: int(0) @@ -189,8 +229,12 @@ foreach ($oper as $t) >123< *= ><, result: int(0) >123< *= >123<, result: int(15129) >123< *= >2e+5<, result: float(24600000) ->123< *= ><, result: int(0) ->123< *= >abc<, result: int(0) +>123< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>123< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >123< *= >9223372036854775807<, result: float(1.1344747605331E+21) ------------------------------------- >2e+5< *= >0<, result: float(0) @@ -205,41 +249,113 @@ foreach ($oper as $t) >2e+5< *= ><, result: float(0) >2e+5< *= >123<, result: float(24600000) >2e+5< *= >2e+5<, result: float(40000000000) ->2e+5< *= ><, result: float(0) ->2e+5< *= >abc<, result: float(0) +>2e+5< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>2e+5< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) >2e+5< *= >9223372036854775807<, result: float(1.844674407371E+24) ------------------------------------- ->< *= >0<, result: int(0) ->< *= >-10<, result: int(0) ->< *= >100<, result: int(0) ->< *= >-34000000000<, result: float(-0) ->< *= >INF<, result: float(NAN) ->< *= >-INF<, result: float(NAN) ->< *= >NAN<, result: float(NAN) ->< *= >1<, result: int(0) ->< *= ><, result: int(0) ->< *= ><, result: int(0) ->< *= >123<, result: int(0) ->< *= >2e+5<, result: float(0) ->< *= ><, result: int(0) ->< *= >abc<, result: int(0) ->< *= >9223372036854775807<, result: int(0) +>< *= >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< *= >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< *= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< *= >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>< *= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>< *= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>< *= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>< *= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< *= >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< *= >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< *= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- ->abc< *= >0<, result: int(0) ->abc< *= >-10<, result: int(0) ->abc< *= >100<, result: int(0) ->abc< *= >-34000000000<, result: float(-0) ->abc< *= >INF<, result: float(NAN) ->abc< *= >-INF<, result: float(NAN) ->abc< *= >NAN<, result: float(NAN) ->abc< *= >1<, result: int(0) ->abc< *= ><, result: int(0) ->abc< *= ><, result: int(0) ->abc< *= >123<, result: int(0) ->abc< *= >2e+5<, result: float(0) ->abc< *= ><, result: int(0) ->abc< *= >abc<, result: int(0) ->abc< *= >9223372036854775807<, result: int(0) +>abc< *= >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< *= >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< *= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< *= >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>abc< *= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>abc< *= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>abc< *= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>abc< *= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< *= >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< *= >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>abc< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< *= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- >9223372036854775807< *= >0<, result: int(0) >9223372036854775807< *= >-10<, result: float(-9.2233720368548E+19) @@ -253,7 +369,11 @@ foreach ($oper as $t) >9223372036854775807< *= ><, result: int(0) >9223372036854775807< *= >123<, result: float(1.1344747605331E+21) >9223372036854775807< *= >2e+5<, result: float(1.844674407371E+24) ->9223372036854775807< *= ><, result: int(0) ->9223372036854775807< *= >abc<, result: int(0) +>9223372036854775807< *= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>9223372036854775807< *= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >9223372036854775807< *= >9223372036854775807<, result: float(8.5070591730235E+37) -------------------------------------- \ No newline at end of file +------------------------------------- diff --git a/tests/expressions/assignment_operators/or_assignment.phpt b/tests/expressions/assignment_operators/or_assignment.phpt index 7479d823..06eebc63 100644 --- a/tests/expressions/assignment_operators/or_assignment.phpt +++ b/tests/expressions/assignment_operators/or_assignment.phpt @@ -16,7 +16,7 @@ foreach ($oper as $t) } ?> ---EXPECT-- +--EXPECTF-- >0< |= >0<, result: int(0) >0< |= >-10<, result: int(-10) >0< |= >100<, result: int(100) @@ -28,9 +28,13 @@ foreach ($oper as $t) >0< |= ><, result: int(0) >0< |= ><, result: int(0) >0< |= >123<, result: int(123) ->0< |= >2e+5<, result: int(2) ->0< |= ><, result: int(0) ->0< |= >abc<, result: int(0) +>0< |= >2e+5<, result: int(200000) +>0< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>0< |= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >0< |= >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >-10< |= >0<, result: int(-10) @@ -45,8 +49,12 @@ foreach ($oper as $t) >-10< |= ><, result: int(-10) >-10< |= >123<, result: int(-1) >-10< |= >2e+5<, result: int(-10) ->-10< |= ><, result: int(-10) ->-10< |= >abc<, result: int(-10) +>-10< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) +>-10< |= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) >-10< |= >9223372036854775807<, result: int(-1) ------------------------------------- >100< |= >0<, result: int(100) @@ -60,9 +68,13 @@ foreach ($oper as $t) >100< |= ><, result: int(100) >100< |= ><, result: int(100) >100< |= >123<, result: int(127) ->100< |= >2e+5<, result: int(102) ->100< |= ><, result: int(100) ->100< |= >abc<, result: int(100) +>100< |= >2e+5<, result: int(200036) +>100< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) +>100< |= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) >100< |= >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >-34000000000< |= >0<, result: int(-34000000000) @@ -76,9 +88,13 @@ foreach ($oper as $t) >-34000000000< |= ><, result: int(-34000000000) >-34000000000< |= ><, result: int(-34000000000) >-34000000000< |= >123<, result: int(-33999999877) ->-34000000000< |= >2e+5<, result: int(-33999999998) ->-34000000000< |= ><, result: int(-34000000000) ->-34000000000< |= >abc<, result: int(-34000000000) +>-34000000000< |= >2e+5<, result: int(-33999868608) +>-34000000000< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(-34000000000) +>-34000000000< |= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-34000000000) >-34000000000< |= >9223372036854775807<, result: int(-1) ------------------------------------- >INF< |= >0<, result: int(0) @@ -92,9 +108,13 @@ foreach ($oper as $t) >INF< |= ><, result: int(0) >INF< |= ><, result: int(0) >INF< |= >123<, result: int(123) ->INF< |= >2e+5<, result: int(2) ->INF< |= ><, result: int(0) ->INF< |= >abc<, result: int(0) +>INF< |= >2e+5<, result: int(200000) +>INF< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>INF< |= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >INF< |= >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >-INF< |= >0<, result: int(0) @@ -108,9 +128,13 @@ foreach ($oper as $t) >-INF< |= ><, result: int(0) >-INF< |= ><, result: int(0) >-INF< |= >123<, result: int(123) ->-INF< |= >2e+5<, result: int(2) ->-INF< |= ><, result: int(0) ->-INF< |= >abc<, result: int(0) +>-INF< |= >2e+5<, result: int(200000) +>-INF< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>-INF< |= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >-INF< |= >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >NAN< |= >0<, result: int(0) @@ -124,9 +148,13 @@ foreach ($oper as $t) >NAN< |= ><, result: int(0) >NAN< |= ><, result: int(0) >NAN< |= >123<, result: int(123) ->NAN< |= >2e+5<, result: int(2) ->NAN< |= ><, result: int(0) ->NAN< |= >abc<, result: int(0) +>NAN< |= >2e+5<, result: int(200000) +>NAN< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>NAN< |= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >NAN< |= >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >1< |= >0<, result: int(1) @@ -140,9 +168,13 @@ foreach ($oper as $t) >1< |= ><, result: int(1) >1< |= ><, result: int(1) >1< |= >123<, result: int(123) ->1< |= >2e+5<, result: int(3) ->1< |= ><, result: int(1) ->1< |= >abc<, result: int(1) +>1< |= >2e+5<, result: int(200001) +>1< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) +>1< |= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) >1< |= >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >< |= >0<, result: int(0) @@ -156,9 +188,13 @@ foreach ($oper as $t) >< |= ><, result: int(0) >< |= ><, result: int(0) >< |= >123<, result: int(123) ->< |= >2e+5<, result: int(2) ->< |= ><, result: int(0) ->< |= >abc<, result: int(0) +>< |= >2e+5<, result: int(200000) +>< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< |= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< |= >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >< |= >0<, result: int(0) @@ -172,9 +208,13 @@ foreach ($oper as $t) >< |= ><, result: int(0) >< |= ><, result: int(0) >< |= >123<, result: int(123) ->< |= >2e+5<, result: int(2) ->< |= ><, result: int(0) ->< |= >abc<, result: int(0) +>< |= >2e+5<, result: int(200000) +>< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< |= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< |= >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >123< |= >0<, result: int(123) @@ -193,53 +233,97 @@ foreach ($oper as $t) >123< |= >abc<, result: string(3) "qrs" >123< |= >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- ->2e+5< |= >0<, result: int(2) +>2e+5< |= >0<, result: int(200000) >2e+5< |= >-10<, result: int(-10) ->2e+5< |= >100<, result: int(102) ->2e+5< |= >-34000000000<, result: int(-33999999998) ->2e+5< |= >INF<, result: int(2) ->2e+5< |= >-INF<, result: int(2) ->2e+5< |= >NAN<, result: int(2) ->2e+5< |= >1<, result: int(3) ->2e+5< |= ><, result: int(2) ->2e+5< |= ><, result: int(2) +>2e+5< |= >100<, result: int(200036) +>2e+5< |= >-34000000000<, result: int(-33999868608) +>2e+5< |= >INF<, result: int(200000) +>2e+5< |= >-INF<, result: int(200000) +>2e+5< |= >NAN<, result: int(200000) +>2e+5< |= >1<, result: int(200001) +>2e+5< |= ><, result: int(200000) +>2e+5< |= ><, result: int(200000) >2e+5< |= >123<, result: string(4) "3w;5" >2e+5< |= >2e+5<, result: string(4) "2e+5" >2e+5< |= ><, result: string(4) "2e+5" >2e+5< |= >abc<, result: string(4) "sgk5" >2e+5< |= >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- ->< |= >0<, result: int(0) ->< |= >-10<, result: int(-10) ->< |= >100<, result: int(100) ->< |= >-34000000000<, result: int(-34000000000) ->< |= >INF<, result: int(0) ->< |= >-INF<, result: int(0) ->< |= >NAN<, result: int(0) ->< |= >1<, result: int(1) ->< |= ><, result: int(0) ->< |= ><, result: int(0) +>< |= >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< |= >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) +>< |= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) +>< |= >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-34000000000) +>< |= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< |= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< |= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< |= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) +>< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< |= >123<, result: string(3) "123" >< |= >2e+5<, result: string(4) "2e+5" >< |= ><, result: string(0) "" >< |= >abc<, result: string(3) "abc" ->< |= >9223372036854775807<, result: int(9223372036854775807) +>< |= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) ------------------------------------- ->abc< |= >0<, result: int(0) ->abc< |= >-10<, result: int(-10) ->abc< |= >100<, result: int(100) ->abc< |= >-34000000000<, result: int(-34000000000) ->abc< |= >INF<, result: int(0) ->abc< |= >-INF<, result: int(0) ->abc< |= >NAN<, result: int(0) ->abc< |= >1<, result: int(1) ->abc< |= ><, result: int(0) ->abc< |= ><, result: int(0) +>abc< |= >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< |= >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) +>abc< |= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) +>abc< |= >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-34000000000) +>abc< |= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< |= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< |= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< |= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) +>abc< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >abc< |= >123<, result: string(3) "qrs" >abc< |= >2e+5<, result: string(4) "sgk5" >abc< |= ><, result: string(3) "abc" >abc< |= >abc<, result: string(3) "abc" ->abc< |= >9223372036854775807<, result: int(9223372036854775807) +>abc< |= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) ------------------------------------- >9223372036854775807< |= >0<, result: int(9223372036854775807) >9223372036854775807< |= >-10<, result: int(-1) @@ -253,7 +337,11 @@ foreach ($oper as $t) >9223372036854775807< |= ><, result: int(9223372036854775807) >9223372036854775807< |= >123<, result: int(9223372036854775807) >9223372036854775807< |= >2e+5<, result: int(9223372036854775807) ->9223372036854775807< |= ><, result: int(9223372036854775807) ->9223372036854775807< |= >abc<, result: int(9223372036854775807) +>9223372036854775807< |= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) +>9223372036854775807< |= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) >9223372036854775807< |= >9223372036854775807<, result: int(9223372036854775807) -------------------------------------- \ No newline at end of file +------------------------------------- diff --git a/tests/expressions/assignment_operators/sl_assignment.phpt b/tests/expressions/assignment_operators/sl_assignment.phpt index 69cb1017..2d6fc1ae 100644 --- a/tests/expressions/assignment_operators/sl_assignment.phpt +++ b/tests/expressions/assignment_operators/sl_assignment.phpt @@ -18,7 +18,7 @@ foreach ($oper as $t) } ?> ---EXPECT-- +--EXPECTF-- >0< <<= >0<, result: int(0) >0< <<= >100<, result: int(0) >0< <<= >INF<, result: int(0) @@ -29,8 +29,12 @@ foreach ($oper as $t) >0< <<= ><, result: int(0) >0< <<= >123<, result: int(0) >0< <<= >2e+5<, result: int(0) ->0< <<= ><, result: int(0) ->0< <<= >abc<, result: int(0) +>0< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>0< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >0< <<= >9223372036854775807<, result: int(0) ------------------------------------- >-10< <<= >0<, result: int(-10) @@ -42,9 +46,13 @@ foreach ($oper as $t) >-10< <<= ><, result: int(-10) >-10< <<= ><, result: int(-10) >-10< <<= >123<, result: int(0) ->-10< <<= >2e+5<, result: int(-40) ->-10< <<= ><, result: int(-10) ->-10< <<= >abc<, result: int(-10) +>-10< <<= >2e+5<, result: int(0) +>-10< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) +>-10< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) >-10< <<= >9223372036854775807<, result: int(0) ------------------------------------- >100< <<= >0<, result: int(100) @@ -56,9 +64,13 @@ foreach ($oper as $t) >100< <<= ><, result: int(100) >100< <<= ><, result: int(100) >100< <<= >123<, result: int(0) ->100< <<= >2e+5<, result: int(400) ->100< <<= ><, result: int(100) ->100< <<= >abc<, result: int(100) +>100< <<= >2e+5<, result: int(0) +>100< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) +>100< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) >100< <<= >9223372036854775807<, result: int(0) ------------------------------------- >-34000000000< <<= >0<, result: int(-34000000000) @@ -70,9 +82,13 @@ foreach ($oper as $t) >-34000000000< <<= ><, result: int(-34000000000) >-34000000000< <<= ><, result: int(-34000000000) >-34000000000< <<= >123<, result: int(0) ->-34000000000< <<= >2e+5<, result: int(-136000000000) ->-34000000000< <<= ><, result: int(-34000000000) ->-34000000000< <<= >abc<, result: int(-34000000000) +>-34000000000< <<= >2e+5<, result: int(0) +>-34000000000< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(-34000000000) +>-34000000000< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-34000000000) >-34000000000< <<= >9223372036854775807<, result: int(0) ------------------------------------- >INF< <<= >0<, result: int(0) @@ -85,8 +101,12 @@ foreach ($oper as $t) >INF< <<= ><, result: int(0) >INF< <<= >123<, result: int(0) >INF< <<= >2e+5<, result: int(0) ->INF< <<= ><, result: int(0) ->INF< <<= >abc<, result: int(0) +>INF< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>INF< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >INF< <<= >9223372036854775807<, result: int(0) ------------------------------------- >-INF< <<= >0<, result: int(0) @@ -99,8 +119,12 @@ foreach ($oper as $t) >-INF< <<= ><, result: int(0) >-INF< <<= >123<, result: int(0) >-INF< <<= >2e+5<, result: int(0) ->-INF< <<= ><, result: int(0) ->-INF< <<= >abc<, result: int(0) +>-INF< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>-INF< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >-INF< <<= >9223372036854775807<, result: int(0) ------------------------------------- >NAN< <<= >0<, result: int(0) @@ -113,8 +137,12 @@ foreach ($oper as $t) >NAN< <<= ><, result: int(0) >NAN< <<= >123<, result: int(0) >NAN< <<= >2e+5<, result: int(0) ->NAN< <<= ><, result: int(0) ->NAN< <<= >abc<, result: int(0) +>NAN< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>NAN< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >NAN< <<= >9223372036854775807<, result: int(0) ------------------------------------- >1< <<= >0<, result: int(1) @@ -126,9 +154,13 @@ foreach ($oper as $t) >1< <<= ><, result: int(1) >1< <<= ><, result: int(1) >1< <<= >123<, result: int(0) ->1< <<= >2e+5<, result: int(4) ->1< <<= ><, result: int(1) ->1< <<= >abc<, result: int(1) +>1< <<= >2e+5<, result: int(0) +>1< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) +>1< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) >1< <<= >9223372036854775807<, result: int(0) ------------------------------------- >< <<= >0<, result: int(0) @@ -141,8 +173,12 @@ foreach ($oper as $t) >< <<= ><, result: int(0) >< <<= >123<, result: int(0) >< <<= >2e+5<, result: int(0) ->< <<= ><, result: int(0) ->< <<= >abc<, result: int(0) +>< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< <<= >9223372036854775807<, result: int(0) ------------------------------------- >< <<= >0<, result: int(0) @@ -155,8 +191,12 @@ foreach ($oper as $t) >< <<= ><, result: int(0) >< <<= >123<, result: int(0) >< <<= >2e+5<, result: int(0) ->< <<= ><, result: int(0) ->< <<= >abc<, result: int(0) +>< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< <<= >9223372036854775807<, result: int(0) ------------------------------------- >123< <<= >0<, result: int(123) @@ -168,52 +208,120 @@ foreach ($oper as $t) >123< <<= ><, result: int(123) >123< <<= ><, result: int(123) >123< <<= >123<, result: int(0) ->123< <<= >2e+5<, result: int(492) ->123< <<= ><, result: int(123) ->123< <<= >abc<, result: int(123) +>123< <<= >2e+5<, result: int(0) +>123< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(123) +>123< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(123) >123< <<= >9223372036854775807<, result: int(0) ------------------------------------- ->2e+5< <<= >0<, result: int(2) +>2e+5< <<= >0<, result: int(200000) >2e+5< <<= >100<, result: int(0) ->2e+5< <<= >INF<, result: int(2) ->2e+5< <<= >-INF<, result: int(2) ->2e+5< <<= >NAN<, result: int(2) ->2e+5< <<= >1<, result: int(4) ->2e+5< <<= ><, result: int(2) ->2e+5< <<= ><, result: int(2) +>2e+5< <<= >INF<, result: int(200000) +>2e+5< <<= >-INF<, result: int(200000) +>2e+5< <<= >NAN<, result: int(200000) +>2e+5< <<= >1<, result: int(400000) +>2e+5< <<= ><, result: int(200000) +>2e+5< <<= ><, result: int(200000) >2e+5< <<= >123<, result: int(0) ->2e+5< <<= >2e+5<, result: int(8) ->2e+5< <<= ><, result: int(2) ->2e+5< <<= >abc<, result: int(2) +>2e+5< <<= >2e+5<, result: int(0) +>2e+5< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(200000) +>2e+5< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(200000) >2e+5< <<= >9223372036854775807<, result: int(0) ------------------------------------- ->< <<= >0<, result: int(0) ->< <<= >100<, result: int(0) ->< <<= >INF<, result: int(0) ->< <<= >-INF<, result: int(0) ->< <<= >NAN<, result: int(0) ->< <<= >1<, result: int(0) ->< <<= ><, result: int(0) ->< <<= ><, result: int(0) ->< <<= >123<, result: int(0) ->< <<= >2e+5<, result: int(0) ->< <<= ><, result: int(0) ->< <<= >abc<, result: int(0) ->< <<= >9223372036854775807<, result: int(0) +>< <<= >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< <<= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- ->abc< <<= >0<, result: int(0) ->abc< <<= >100<, result: int(0) ->abc< <<= >INF<, result: int(0) ->abc< <<= >-INF<, result: int(0) ->abc< <<= >NAN<, result: int(0) ->abc< <<= >1<, result: int(0) ->abc< <<= ><, result: int(0) ->abc< <<= ><, result: int(0) ->abc< <<= >123<, result: int(0) ->abc< <<= >2e+5<, result: int(0) ->abc< <<= ><, result: int(0) ->abc< <<= >abc<, result: int(0) ->abc< <<= >9223372036854775807<, result: int(0) +>abc< <<= >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< <<= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< <<= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< <<= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< <<= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< <<= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< <<= >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< <<= >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< <<= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- >9223372036854775807< <<= >0<, result: int(9223372036854775807) >9223372036854775807< <<= >100<, result: int(0) @@ -224,8 +332,12 @@ foreach ($oper as $t) >9223372036854775807< <<= ><, result: int(9223372036854775807) >9223372036854775807< <<= ><, result: int(9223372036854775807) >9223372036854775807< <<= >123<, result: int(0) ->9223372036854775807< <<= >2e+5<, result: int(-4) ->9223372036854775807< <<= ><, result: int(9223372036854775807) ->9223372036854775807< <<= >abc<, result: int(9223372036854775807) +>9223372036854775807< <<= >2e+5<, result: int(0) +>9223372036854775807< <<= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) +>9223372036854775807< <<= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) >9223372036854775807< <<= >9223372036854775807<, result: int(0) -------------------------------------- \ No newline at end of file +------------------------------------- diff --git a/tests/expressions/assignment_operators/sr_assignment.phpt b/tests/expressions/assignment_operators/sr_assignment.phpt index 7d80e7b0..43c08968 100644 --- a/tests/expressions/assignment_operators/sr_assignment.phpt +++ b/tests/expressions/assignment_operators/sr_assignment.phpt @@ -12,220 +12,332 @@ foreach ($oper as $t) if ((int)($e2) < 0) continue; // skip negative shifts $e1 = $t; - echo ">$e1< <<= >$e2<, result: "; var_dump($e1 <<= $e2); + echo ">$e1< >>= >$e2<, result: "; var_dump($e1 <<= $e2); } echo "-------------------------------------\n"; } ?> ---EXPECT-- ->0< <<= >0<, result: int(0) ->0< <<= >100<, result: int(0) ->0< <<= >INF<, result: int(0) ->0< <<= >-INF<, result: int(0) ->0< <<= >NAN<, result: int(0) ->0< <<= >1<, result: int(0) ->0< <<= ><, result: int(0) ->0< <<= ><, result: int(0) ->0< <<= >123<, result: int(0) ->0< <<= >2e+5<, result: int(0) ->0< <<= ><, result: int(0) ->0< <<= >abc<, result: int(0) ->0< <<= >9223372036854775807<, result: int(0) +--EXPECTF-- +>0< >>= >0<, result: int(0) +>0< >>= >100<, result: int(0) +>0< >>= >INF<, result: int(0) +>0< >>= >-INF<, result: int(0) +>0< >>= >NAN<, result: int(0) +>0< >>= >1<, result: int(0) +>0< >>= ><, result: int(0) +>0< >>= ><, result: int(0) +>0< >>= >123<, result: int(0) +>0< >>= >2e+5<, result: int(0) +>0< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>0< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>0< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->-10< <<= >0<, result: int(-10) ->-10< <<= >100<, result: int(0) ->-10< <<= >INF<, result: int(-10) ->-10< <<= >-INF<, result: int(-10) ->-10< <<= >NAN<, result: int(-10) ->-10< <<= >1<, result: int(-20) ->-10< <<= ><, result: int(-10) ->-10< <<= ><, result: int(-10) ->-10< <<= >123<, result: int(0) ->-10< <<= >2e+5<, result: int(-40) ->-10< <<= ><, result: int(-10) ->-10< <<= >abc<, result: int(-10) ->-10< <<= >9223372036854775807<, result: int(0) +>-10< >>= >0<, result: int(-10) +>-10< >>= >100<, result: int(0) +>-10< >>= >INF<, result: int(-10) +>-10< >>= >-INF<, result: int(-10) +>-10< >>= >NAN<, result: int(-10) +>-10< >>= >1<, result: int(-20) +>-10< >>= ><, result: int(-10) +>-10< >>= ><, result: int(-10) +>-10< >>= >123<, result: int(0) +>-10< >>= >2e+5<, result: int(0) +>-10< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) +>-10< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) +>-10< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->100< <<= >0<, result: int(100) ->100< <<= >100<, result: int(0) ->100< <<= >INF<, result: int(100) ->100< <<= >-INF<, result: int(100) ->100< <<= >NAN<, result: int(100) ->100< <<= >1<, result: int(200) ->100< <<= ><, result: int(100) ->100< <<= ><, result: int(100) ->100< <<= >123<, result: int(0) ->100< <<= >2e+5<, result: int(400) ->100< <<= ><, result: int(100) ->100< <<= >abc<, result: int(100) ->100< <<= >9223372036854775807<, result: int(0) +>100< >>= >0<, result: int(100) +>100< >>= >100<, result: int(0) +>100< >>= >INF<, result: int(100) +>100< >>= >-INF<, result: int(100) +>100< >>= >NAN<, result: int(100) +>100< >>= >1<, result: int(200) +>100< >>= ><, result: int(100) +>100< >>= ><, result: int(100) +>100< >>= >123<, result: int(0) +>100< >>= >2e+5<, result: int(0) +>100< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) +>100< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) +>100< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->-34000000000< <<= >0<, result: int(-34000000000) ->-34000000000< <<= >100<, result: int(0) ->-34000000000< <<= >INF<, result: int(-34000000000) ->-34000000000< <<= >-INF<, result: int(-34000000000) ->-34000000000< <<= >NAN<, result: int(-34000000000) ->-34000000000< <<= >1<, result: int(-68000000000) ->-34000000000< <<= ><, result: int(-34000000000) ->-34000000000< <<= ><, result: int(-34000000000) ->-34000000000< <<= >123<, result: int(0) ->-34000000000< <<= >2e+5<, result: int(-136000000000) ->-34000000000< <<= ><, result: int(-34000000000) ->-34000000000< <<= >abc<, result: int(-34000000000) ->-34000000000< <<= >9223372036854775807<, result: int(0) +>-34000000000< >>= >0<, result: int(-34000000000) +>-34000000000< >>= >100<, result: int(0) +>-34000000000< >>= >INF<, result: int(-34000000000) +>-34000000000< >>= >-INF<, result: int(-34000000000) +>-34000000000< >>= >NAN<, result: int(-34000000000) +>-34000000000< >>= >1<, result: int(-68000000000) +>-34000000000< >>= ><, result: int(-34000000000) +>-34000000000< >>= ><, result: int(-34000000000) +>-34000000000< >>= >123<, result: int(0) +>-34000000000< >>= >2e+5<, result: int(0) +>-34000000000< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(-34000000000) +>-34000000000< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-34000000000) +>-34000000000< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->INF< <<= >0<, result: int(0) ->INF< <<= >100<, result: int(0) ->INF< <<= >INF<, result: int(0) ->INF< <<= >-INF<, result: int(0) ->INF< <<= >NAN<, result: int(0) ->INF< <<= >1<, result: int(0) ->INF< <<= ><, result: int(0) ->INF< <<= ><, result: int(0) ->INF< <<= >123<, result: int(0) ->INF< <<= >2e+5<, result: int(0) ->INF< <<= ><, result: int(0) ->INF< <<= >abc<, result: int(0) ->INF< <<= >9223372036854775807<, result: int(0) +>INF< >>= >0<, result: int(0) +>INF< >>= >100<, result: int(0) +>INF< >>= >INF<, result: int(0) +>INF< >>= >-INF<, result: int(0) +>INF< >>= >NAN<, result: int(0) +>INF< >>= >1<, result: int(0) +>INF< >>= ><, result: int(0) +>INF< >>= ><, result: int(0) +>INF< >>= >123<, result: int(0) +>INF< >>= >2e+5<, result: int(0) +>INF< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>INF< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>INF< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->-INF< <<= >0<, result: int(0) ->-INF< <<= >100<, result: int(0) ->-INF< <<= >INF<, result: int(0) ->-INF< <<= >-INF<, result: int(0) ->-INF< <<= >NAN<, result: int(0) ->-INF< <<= >1<, result: int(0) ->-INF< <<= ><, result: int(0) ->-INF< <<= ><, result: int(0) ->-INF< <<= >123<, result: int(0) ->-INF< <<= >2e+5<, result: int(0) ->-INF< <<= ><, result: int(0) ->-INF< <<= >abc<, result: int(0) ->-INF< <<= >9223372036854775807<, result: int(0) +>-INF< >>= >0<, result: int(0) +>-INF< >>= >100<, result: int(0) +>-INF< >>= >INF<, result: int(0) +>-INF< >>= >-INF<, result: int(0) +>-INF< >>= >NAN<, result: int(0) +>-INF< >>= >1<, result: int(0) +>-INF< >>= ><, result: int(0) +>-INF< >>= ><, result: int(0) +>-INF< >>= >123<, result: int(0) +>-INF< >>= >2e+5<, result: int(0) +>-INF< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>-INF< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>-INF< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->NAN< <<= >0<, result: int(0) ->NAN< <<= >100<, result: int(0) ->NAN< <<= >INF<, result: int(0) ->NAN< <<= >-INF<, result: int(0) ->NAN< <<= >NAN<, result: int(0) ->NAN< <<= >1<, result: int(0) ->NAN< <<= ><, result: int(0) ->NAN< <<= ><, result: int(0) ->NAN< <<= >123<, result: int(0) ->NAN< <<= >2e+5<, result: int(0) ->NAN< <<= ><, result: int(0) ->NAN< <<= >abc<, result: int(0) ->NAN< <<= >9223372036854775807<, result: int(0) +>NAN< >>= >0<, result: int(0) +>NAN< >>= >100<, result: int(0) +>NAN< >>= >INF<, result: int(0) +>NAN< >>= >-INF<, result: int(0) +>NAN< >>= >NAN<, result: int(0) +>NAN< >>= >1<, result: int(0) +>NAN< >>= ><, result: int(0) +>NAN< >>= ><, result: int(0) +>NAN< >>= >123<, result: int(0) +>NAN< >>= >2e+5<, result: int(0) +>NAN< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>NAN< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>NAN< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->1< <<= >0<, result: int(1) ->1< <<= >100<, result: int(0) ->1< <<= >INF<, result: int(1) ->1< <<= >-INF<, result: int(1) ->1< <<= >NAN<, result: int(1) ->1< <<= >1<, result: int(2) ->1< <<= ><, result: int(1) ->1< <<= ><, result: int(1) ->1< <<= >123<, result: int(0) ->1< <<= >2e+5<, result: int(4) ->1< <<= ><, result: int(1) ->1< <<= >abc<, result: int(1) ->1< <<= >9223372036854775807<, result: int(0) +>1< >>= >0<, result: int(1) +>1< >>= >100<, result: int(0) +>1< >>= >INF<, result: int(1) +>1< >>= >-INF<, result: int(1) +>1< >>= >NAN<, result: int(1) +>1< >>= >1<, result: int(2) +>1< >>= ><, result: int(1) +>1< >>= ><, result: int(1) +>1< >>= >123<, result: int(0) +>1< >>= >2e+5<, result: int(0) +>1< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) +>1< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) +>1< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->< <<= >0<, result: int(0) ->< <<= >100<, result: int(0) ->< <<= >INF<, result: int(0) ->< <<= >-INF<, result: int(0) ->< <<= >NAN<, result: int(0) ->< <<= >1<, result: int(0) ->< <<= ><, result: int(0) ->< <<= ><, result: int(0) ->< <<= >123<, result: int(0) ->< <<= >2e+5<, result: int(0) ->< <<= ><, result: int(0) ->< <<= >abc<, result: int(0) ->< <<= >9223372036854775807<, result: int(0) +>< >>= >0<, result: int(0) +>< >>= >100<, result: int(0) +>< >>= >INF<, result: int(0) +>< >>= >-INF<, result: int(0) +>< >>= >NAN<, result: int(0) +>< >>= >1<, result: int(0) +>< >>= ><, result: int(0) +>< >>= ><, result: int(0) +>< >>= >123<, result: int(0) +>< >>= >2e+5<, result: int(0) +>< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->< <<= >0<, result: int(0) ->< <<= >100<, result: int(0) ->< <<= >INF<, result: int(0) ->< <<= >-INF<, result: int(0) ->< <<= >NAN<, result: int(0) ->< <<= >1<, result: int(0) ->< <<= ><, result: int(0) ->< <<= ><, result: int(0) ->< <<= >123<, result: int(0) ->< <<= >2e+5<, result: int(0) ->< <<= ><, result: int(0) ->< <<= >abc<, result: int(0) ->< <<= >9223372036854775807<, result: int(0) +>< >>= >0<, result: int(0) +>< >>= >100<, result: int(0) +>< >>= >INF<, result: int(0) +>< >>= >-INF<, result: int(0) +>< >>= >NAN<, result: int(0) +>< >>= >1<, result: int(0) +>< >>= ><, result: int(0) +>< >>= ><, result: int(0) +>< >>= >123<, result: int(0) +>< >>= >2e+5<, result: int(0) +>< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->123< <<= >0<, result: int(123) ->123< <<= >100<, result: int(0) ->123< <<= >INF<, result: int(123) ->123< <<= >-INF<, result: int(123) ->123< <<= >NAN<, result: int(123) ->123< <<= >1<, result: int(246) ->123< <<= ><, result: int(123) ->123< <<= ><, result: int(123) ->123< <<= >123<, result: int(0) ->123< <<= >2e+5<, result: int(492) ->123< <<= ><, result: int(123) ->123< <<= >abc<, result: int(123) ->123< <<= >9223372036854775807<, result: int(0) +>123< >>= >0<, result: int(123) +>123< >>= >100<, result: int(0) +>123< >>= >INF<, result: int(123) +>123< >>= >-INF<, result: int(123) +>123< >>= >NAN<, result: int(123) +>123< >>= >1<, result: int(246) +>123< >>= ><, result: int(123) +>123< >>= ><, result: int(123) +>123< >>= >123<, result: int(0) +>123< >>= >2e+5<, result: int(0) +>123< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(123) +>123< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(123) +>123< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->2e+5< <<= >0<, result: int(2) ->2e+5< <<= >100<, result: int(0) ->2e+5< <<= >INF<, result: int(2) ->2e+5< <<= >-INF<, result: int(2) ->2e+5< <<= >NAN<, result: int(2) ->2e+5< <<= >1<, result: int(4) ->2e+5< <<= ><, result: int(2) ->2e+5< <<= ><, result: int(2) ->2e+5< <<= >123<, result: int(0) ->2e+5< <<= >2e+5<, result: int(8) ->2e+5< <<= ><, result: int(2) ->2e+5< <<= >abc<, result: int(2) ->2e+5< <<= >9223372036854775807<, result: int(0) +>2e+5< >>= >0<, result: int(200000) +>2e+5< >>= >100<, result: int(0) +>2e+5< >>= >INF<, result: int(200000) +>2e+5< >>= >-INF<, result: int(200000) +>2e+5< >>= >NAN<, result: int(200000) +>2e+5< >>= >1<, result: int(400000) +>2e+5< >>= ><, result: int(200000) +>2e+5< >>= ><, result: int(200000) +>2e+5< >>= >123<, result: int(0) +>2e+5< >>= >2e+5<, result: int(0) +>2e+5< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(200000) +>2e+5< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(200000) +>2e+5< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->< <<= >0<, result: int(0) ->< <<= >100<, result: int(0) ->< <<= >INF<, result: int(0) ->< <<= >-INF<, result: int(0) ->< <<= >NAN<, result: int(0) ->< <<= >1<, result: int(0) ->< <<= ><, result: int(0) ->< <<= ><, result: int(0) ->< <<= >123<, result: int(0) ->< <<= >2e+5<, result: int(0) ->< <<= ><, result: int(0) ->< <<= >abc<, result: int(0) ->< <<= >9223372036854775807<, result: int(0) +>< >>= >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< >>= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +------------------------------------- +>abc< >>= >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< >>= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< >>= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< >>= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< >>= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< >>= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< >>= >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< >>= >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< >>= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- ->abc< <<= >0<, result: int(0) ->abc< <<= >100<, result: int(0) ->abc< <<= >INF<, result: int(0) ->abc< <<= >-INF<, result: int(0) ->abc< <<= >NAN<, result: int(0) ->abc< <<= >1<, result: int(0) ->abc< <<= ><, result: int(0) ->abc< <<= ><, result: int(0) ->abc< <<= >123<, result: int(0) ->abc< <<= >2e+5<, result: int(0) ->abc< <<= ><, result: int(0) ->abc< <<= >abc<, result: int(0) ->abc< <<= >9223372036854775807<, result: int(0) +>9223372036854775807< >>= >0<, result: int(9223372036854775807) +>9223372036854775807< >>= >100<, result: int(0) +>9223372036854775807< >>= >INF<, result: int(9223372036854775807) +>9223372036854775807< >>= >-INF<, result: int(9223372036854775807) +>9223372036854775807< >>= >NAN<, result: int(9223372036854775807) +>9223372036854775807< >>= >1<, result: int(-2) +>9223372036854775807< >>= ><, result: int(9223372036854775807) +>9223372036854775807< >>= ><, result: int(9223372036854775807) +>9223372036854775807< >>= >123<, result: int(0) +>9223372036854775807< >>= >2e+5<, result: int(0) +>9223372036854775807< >>= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) +>9223372036854775807< >>= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) +>9223372036854775807< >>= >9223372036854775807<, result: int(0) ------------------------------------- ->9223372036854775807< <<= >0<, result: int(9223372036854775807) ->9223372036854775807< <<= >100<, result: int(0) ->9223372036854775807< <<= >INF<, result: int(9223372036854775807) ->9223372036854775807< <<= >-INF<, result: int(9223372036854775807) ->9223372036854775807< <<= >NAN<, result: int(9223372036854775807) ->9223372036854775807< <<= >1<, result: int(-2) ->9223372036854775807< <<= ><, result: int(9223372036854775807) ->9223372036854775807< <<= ><, result: int(9223372036854775807) ->9223372036854775807< <<= >123<, result: int(0) ->9223372036854775807< <<= >2e+5<, result: int(-4) ->9223372036854775807< <<= ><, result: int(9223372036854775807) ->9223372036854775807< <<= >abc<, result: int(9223372036854775807) ->9223372036854775807< <<= >9223372036854775807<, result: int(0) -------------------------------------- \ No newline at end of file diff --git a/tests/expressions/assignment_operators/sub_assignment.phpt b/tests/expressions/assignment_operators/sub_assignment.phpt index 4460d014..345d695c 100644 --- a/tests/expressions/assignment_operators/sub_assignment.phpt +++ b/tests/expressions/assignment_operators/sub_assignment.phpt @@ -16,7 +16,7 @@ foreach ($oper as $t) } ?> ---EXPECT-- +--EXPECTF-- >0< -= >0<, result: int(0) >0< -= >-10<, result: int(10) >0< -= >100<, result: int(-100) @@ -29,8 +29,12 @@ foreach ($oper as $t) >0< -= ><, result: int(0) >0< -= >123<, result: int(-123) >0< -= >2e+5<, result: float(-200000) ->0< -= ><, result: int(0) ->0< -= >abc<, result: int(0) +>0< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>0< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >0< -= >9223372036854775807<, result: int(-9223372036854775807) ------------------------------------- >-10< -= >0<, result: int(-10) @@ -45,8 +49,12 @@ foreach ($oper as $t) >-10< -= ><, result: int(-10) >-10< -= >123<, result: int(-133) >-10< -= >2e+5<, result: float(-200010) ->-10< -= ><, result: int(-10) ->-10< -= >abc<, result: int(-10) +>-10< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) +>-10< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-10) >-10< -= >9223372036854775807<, result: float(-9.2233720368548E+18) ------------------------------------- >100< -= >0<, result: int(100) @@ -61,8 +69,12 @@ foreach ($oper as $t) >100< -= ><, result: int(100) >100< -= >123<, result: int(-23) >100< -= >2e+5<, result: float(-199900) ->100< -= ><, result: int(100) ->100< -= >abc<, result: int(100) +>100< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) +>100< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(100) >100< -= >9223372036854775807<, result: int(-9223372036854775707) ------------------------------------- >-34000000000< -= >0<, result: float(-34000000000) @@ -77,8 +89,12 @@ foreach ($oper as $t) >-34000000000< -= ><, result: float(-34000000000) >-34000000000< -= >123<, result: float(-34000000123) >-34000000000< -= >2e+5<, result: float(-34000200000) ->-34000000000< -= ><, result: float(-34000000000) ->-34000000000< -= >abc<, result: float(-34000000000) +>-34000000000< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(-34000000000) +>-34000000000< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-34000000000) >-34000000000< -= >9223372036854775807<, result: float(-9.2233720708548E+18) ------------------------------------- >INF< -= >0<, result: float(INF) @@ -93,8 +109,12 @@ foreach ($oper as $t) >INF< -= ><, result: float(INF) >INF< -= >123<, result: float(INF) >INF< -= >2e+5<, result: float(INF) ->INF< -= ><, result: float(INF) ->INF< -= >abc<, result: float(INF) +>INF< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(INF) +>INF< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(INF) >INF< -= >9223372036854775807<, result: float(INF) ------------------------------------- >-INF< -= >0<, result: float(-INF) @@ -109,8 +129,12 @@ foreach ($oper as $t) >-INF< -= ><, result: float(-INF) >-INF< -= >123<, result: float(-INF) >-INF< -= >2e+5<, result: float(-INF) ->-INF< -= ><, result: float(-INF) ->-INF< -= >abc<, result: float(-INF) +>-INF< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(-INF) +>-INF< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-INF) >-INF< -= >9223372036854775807<, result: float(-INF) ------------------------------------- >NAN< -= >0<, result: float(NAN) @@ -125,8 +149,12 @@ foreach ($oper as $t) >NAN< -= ><, result: float(NAN) >NAN< -= >123<, result: float(NAN) >NAN< -= >2e+5<, result: float(NAN) ->NAN< -= ><, result: float(NAN) ->NAN< -= >abc<, result: float(NAN) +>NAN< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>NAN< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) >NAN< -= >9223372036854775807<, result: float(NAN) ------------------------------------- >1< -= >0<, result: int(1) @@ -141,8 +169,12 @@ foreach ($oper as $t) >1< -= ><, result: int(1) >1< -= >123<, result: int(-122) >1< -= >2e+5<, result: float(-199999) ->1< -= ><, result: int(1) ->1< -= >abc<, result: int(1) +>1< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) +>1< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(1) >1< -= >9223372036854775807<, result: int(-9223372036854775806) ------------------------------------- >< -= >0<, result: int(0) @@ -157,8 +189,12 @@ foreach ($oper as $t) >< -= ><, result: int(0) >< -= >123<, result: int(-123) >< -= >2e+5<, result: float(-200000) ->< -= ><, result: int(0) ->< -= >abc<, result: int(0) +>< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< -= >9223372036854775807<, result: int(-9223372036854775807) ------------------------------------- >< -= >0<, result: int(0) @@ -173,8 +209,12 @@ foreach ($oper as $t) >< -= ><, result: int(0) >< -= >123<, result: int(-123) >< -= >2e+5<, result: float(-200000) ->< -= ><, result: int(0) ->< -= >abc<, result: int(0) +>< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< -= >9223372036854775807<, result: int(-9223372036854775807) ------------------------------------- >123< -= >0<, result: int(123) @@ -189,8 +229,12 @@ foreach ($oper as $t) >123< -= ><, result: int(123) >123< -= >123<, result: int(0) >123< -= >2e+5<, result: float(-199877) ->123< -= ><, result: int(123) ->123< -= >abc<, result: int(123) +>123< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(123) +>123< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(123) >123< -= >9223372036854775807<, result: int(-9223372036854775684) ------------------------------------- >2e+5< -= >0<, result: float(200000) @@ -205,41 +249,113 @@ foreach ($oper as $t) >2e+5< -= ><, result: float(200000) >2e+5< -= >123<, result: float(199877) >2e+5< -= >2e+5<, result: float(0) ->2e+5< -= ><, result: float(200000) ->2e+5< -= >abc<, result: float(200000) +>2e+5< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(200000) +>2e+5< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(200000) >2e+5< -= >9223372036854775807<, result: float(-9.2233720368546E+18) ------------------------------------- ->< -= >0<, result: int(0) ->< -= >-10<, result: int(10) ->< -= >100<, result: int(-100) ->< -= >-34000000000<, result: float(34000000000) ->< -= >INF<, result: float(-INF) ->< -= >-INF<, result: float(INF) ->< -= >NAN<, result: float(NAN) ->< -= >1<, result: int(-1) ->< -= ><, result: int(0) ->< -= ><, result: int(0) ->< -= >123<, result: int(-123) ->< -= >2e+5<, result: float(-200000) ->< -= ><, result: int(0) ->< -= >abc<, result: int(0) ->< -= >9223372036854775807<, result: int(-9223372036854775807) +>< -= >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< -= >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(10) +>< -= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-100) +>< -= >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +float(34000000000) +>< -= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-INF) +>< -= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(INF) +>< -= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>< -= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-1) +>< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< -= >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-123) +>< -= >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-200000) +>< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< -= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-9223372036854775807) ------------------------------------- ->abc< -= >0<, result: int(0) ->abc< -= >-10<, result: int(10) ->abc< -= >100<, result: int(-100) ->abc< -= >-34000000000<, result: float(34000000000) ->abc< -= >INF<, result: float(-INF) ->abc< -= >-INF<, result: float(INF) ->abc< -= >NAN<, result: float(NAN) ->abc< -= >1<, result: int(-1) ->abc< -= ><, result: int(0) ->abc< -= ><, result: int(0) ->abc< -= >123<, result: int(-123) ->abc< -= >2e+5<, result: float(-200000) ->abc< -= ><, result: int(0) ->abc< -= >abc<, result: int(0) ->abc< -= >9223372036854775807<, result: int(-9223372036854775807) +>abc< -= >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< -= >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(10) +>abc< -= >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-100) +>abc< -= >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +float(34000000000) +>abc< -= >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-INF) +>abc< -= >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(INF) +>abc< -= >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>abc< -= >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-1) +>abc< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< -= >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-123) +>abc< -= >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-200000) +>abc< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< -= >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(-9223372036854775807) ------------------------------------- >9223372036854775807< -= >0<, result: int(9223372036854775807) >9223372036854775807< -= >-10<, result: float(9.2233720368548E+18) @@ -253,7 +369,11 @@ foreach ($oper as $t) >9223372036854775807< -= ><, result: int(9223372036854775807) >9223372036854775807< -= >123<, result: int(9223372036854775684) >9223372036854775807< -= >2e+5<, result: float(9.2233720368546E+18) ->9223372036854775807< -= ><, result: int(9223372036854775807) ->9223372036854775807< -= >abc<, result: int(9223372036854775807) +>9223372036854775807< -= ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) +>9223372036854775807< -= >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(9223372036854775807) >9223372036854775807< -= >9223372036854775807<, result: int(0) -------------------------------------- \ No newline at end of file +------------------------------------- diff --git a/tests/expressions/assignment_operators/xor_assignment.phpt b/tests/expressions/assignment_operators/xor_assignment.phpt index 357f92a1..904d5853 100644 Binary files a/tests/expressions/assignment_operators/xor_assignment.phpt and b/tests/expressions/assignment_operators/xor_assignment.phpt differ diff --git a/tests/expressions/bitwise_shift_operators/bitwise_shift.phpt b/tests/expressions/bitwise_shift_operators/bitwise_shift.phpt index d58309d7..d271a633 100644 --- a/tests/expressions/bitwise_shift_operators/bitwise_shift.phpt +++ b/tests/expressions/bitwise_shift_operators/bitwise_shift.phpt @@ -37,7 +37,7 @@ foreach ($scalarValueList as $v) { printf("%d(%08X): >> %2d = %08X\t<< %2d = %08X\n", $v, $v, 3, $v >> 3, 5, $v << 5); } ---EXPECT-- +--EXPECTF-- 1000(000003E8): >> 0 = 000003E8 << 0 = 000003E8 1000(000003E8): >> 1 = 000001F4 << 1 = 000007D0 1000(000003E8): >> 2 = 000000FA << 2 = 00000FA0 @@ -179,5 +179,13 @@ foreach ($scalarValueList as $v) 0(00000000): >> 3 = 00000000 << 5 = 00000000 0(00000000): >> 3 = 00000000 << 5 = 00000000 123(0000007B): >> 3 = 0000000F << 5 = 00000F60 + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d 0(00000000): >> 3 = 00000000 << 5 = 00000000 + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d 0(00000000): >> 3 = 00000000 << 5 = 00000000 diff --git a/tests/expressions/list/list_001.phpt b/tests/expressions/list/list_001.phpt new file mode 100644 index 00000000..a9fff550 --- /dev/null +++ b/tests/expressions/list/list_001.phpt @@ -0,0 +1,14 @@ +--TEST-- +"Nested" list() +--FILE-- + +--EXPECT-- +object(stdClass)#1 (0) { +} +object(stdClass)#2 (0) { +} diff --git a/tests/expressions/list/list_002.phpt b/tests/expressions/list/list_002.phpt new file mode 100644 index 00000000..ac0d8974 --- /dev/null +++ b/tests/expressions/list/list_002.phpt @@ -0,0 +1,20 @@ +--TEST-- +Testing full-reference on list() +--FILE-- + +--EXPECT-- +object(stdClass)#1 (0) { +} +object(stdClass)#1 (0) { +} +bool(true) diff --git a/tests/expressions/list/list_003.phpt b/tests/expressions/list/list_003.phpt new file mode 100644 index 00000000..4a509f6a --- /dev/null +++ b/tests/expressions/list/list_003.phpt @@ -0,0 +1,24 @@ +--TEST-- +list() with non-array +--FILE-- + +--EXPECT-- +NULL +NULL +NULL +NULL +NULL diff --git a/tests/expressions/list/list_004.phpt b/tests/expressions/list/list_004.phpt new file mode 100644 index 00000000..862a4e43 --- /dev/null +++ b/tests/expressions/list/list_004.phpt @@ -0,0 +1,21 @@ +--TEST-- +list() with array reference +--FILE-- + +--EXPECT-- +int(1) +array(2) { + [0]=> + int(2) + [1]=> + int(1) +} diff --git a/tests/expressions/list/list_005.phpt b/tests/expressions/list/list_005.phpt new file mode 100644 index 00000000..7dc3bf6f --- /dev/null +++ b/tests/expressions/list/list_005.phpt @@ -0,0 +1,50 @@ +--TEST-- +Testing list() with several variables +--FILE-- + +--EXPECTF-- +NULL +NULL +NULL +---- +NULL +NULL +NULL +---- + +Fatal error: Uncaught Error: Cannot use object of type stdClass as array in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/tests/expressions/list/list_006.phpt b/tests/expressions/list/list_006.phpt new file mode 100644 index 00000000..d380235d --- /dev/null +++ b/tests/expressions/list/list_006.phpt @@ -0,0 +1,12 @@ +--TEST-- +Testing nested list() with empty array +--FILE-- + +--EXPECTF-- +Notice: Undefined offset: 0 in %s on line %d + +Notice: Undefined offset: 1 in %s on line %d diff --git a/tests/expressions/list/list_007.phpt b/tests/expressions/list/list_007.phpt new file mode 100644 index 00000000..67c65245 --- /dev/null +++ b/tests/expressions/list/list_007.phpt @@ -0,0 +1,15 @@ +--TEST-- +Using lambda with list() +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Error: Cannot use object of type Closure as array in %slist_007.php:3 +Stack trace: +#0 {main} + thrown in %slist_007.php on line 3 diff --git a/tests/expressions/list/list_destructuring_to_special_variables.phpt b/tests/expressions/list/list_destructuring_to_special_variables.phpt new file mode 100644 index 00000000..4418c967 --- /dev/null +++ b/tests/expressions/list/list_destructuring_to_special_variables.phpt @@ -0,0 +1,49 @@ +--TEST-- +list() can be used to destructure to string offsets, __set and ArrayAccess::offsetSet +--FILE-- +values[$name] = $value; + } +} + +class Arr implements ArrayAccess { + public $values = []; + public function offsetSet($name, $value) { + $this->values[$name] = $value; + } + public function offsetGet($name) {} + public function offsetExists($name) {} + public function offsetUnset($name) {} +} + +$str = 'ab'; +list($str[0], $str[1]) = ['x', 'y']; +var_dump($str); + +$obj = new Obj; +list($obj->foo, $obj->bar) = ['foo', 'bar']; +var_dump($obj->values); + +$arr = new Arr; +list($arr['foo'], $arr['bar']) = ['foo', 'bar']; +var_dump($arr->values); + +?> +--EXPECT-- +string(2) "xy" +array(2) { + ["foo"]=> + string(3) "foo" + ["bar"]=> + string(3) "bar" +} +array(2) { + ["foo"]=> + string(3) "foo" + ["bar"]=> + string(3) "bar" +} diff --git a/tests/expressions/list/list_empty_error.phpt b/tests/expressions/list/list_empty_error.phpt new file mode 100644 index 00000000..78de2e95 --- /dev/null +++ b/tests/expressions/list/list_empty_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +Empty list() assignments are not allowed +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use empty list in %s on line %d diff --git a/tests/expressions/list/list_keyed.phpt b/tests/expressions/list/list_keyed.phpt new file mode 100644 index 00000000..b549ed9b --- /dev/null +++ b/tests/expressions/list/list_keyed.phpt @@ -0,0 +1,71 @@ +--TEST-- +list() with keys +--FILE-- + "bad", + "happy" => "sad", +]; + +list("good" => $good_antonym, "happy" => $happy_antonym) = $antonyms; +var_dump($good_antonym, $happy_antonym); + +echo PHP_EOL; + +$powersOfTwo = [ + 1 => 2, + 2 => 4, + 3 => 8 +]; + +list(1 => $two_1, 2 => $two_2, 3 => $two_3) = $powersOfTwo; +var_dump($two_1, $two_2, $two_3); + +echo PHP_EOL; + +$contrivedMixedKeyTypesExample = [ + 7 => "the best PHP version", + "elePHPant" => "the cutest mascot" +]; + +list(7 => $seven, "elePHPant" => $elePHPant) = $contrivedMixedKeyTypesExample; +var_dump($seven, $elePHPant); + +echo PHP_EOL; + +$allTogetherNow = [ + "antonyms" => $antonyms, + "powersOfTwo" => $powersOfTwo, + "contrivedMixedKeyTypesExample" => $contrivedMixedKeyTypesExample +]; + +list( + "antonyms" => list("good" => $good_antonym, "happy" => $happy_antonym), + "powersOfTwo" => list(1 => $two_1, 2 => $two_2, 3 => $two_3), + "contrivedMixedKeyTypesExample" => list(7 => $seven, "elePHPant" => $elePHPant) +) = $allTogetherNow; + +var_dump($good_antonym, $happy_antonym); +var_dump($two_1, $two_2, $two_3); +var_dump($seven, $elePHPant); + +?> +--EXPECT-- +string(3) "bad" +string(3) "sad" + +int(2) +int(4) +int(8) + +string(20) "the best PHP version" +string(17) "the cutest mascot" + +string(3) "bad" +string(3) "sad" +int(2) +int(4) +int(8) +string(20) "the best PHP version" +string(17) "the cutest mascot" diff --git a/tests/expressions/list/list_keyed_ArrayAccess.phpt b/tests/expressions/list/list_keyed_ArrayAccess.phpt new file mode 100644 index 00000000..1bb20130 --- /dev/null +++ b/tests/expressions/list/list_keyed_ArrayAccess.phpt @@ -0,0 +1,54 @@ +--TEST-- +list() with keys and ArrayAccess +--FILE-- + $good, "happy" => $happy) = $antonymObject; +var_dump($good, $happy); + +echo PHP_EOL; + +$stdClassCollection = new SplObjectStorage; +$foo = new StdClass; +$stdClassCollection[$foo] = "foo"; +$bar = new StdClass; +$stdClassCollection[$bar] = "bar"; + +list($foo => $fooStr, $bar => $barStr) = $stdClassCollection; +var_dump($fooStr, $barStr); + +echo PHP_EOL; + +class IndexPrinter implements ArrayAccess +{ + public function offsetGet($offset) { + echo "GET "; + var_dump($offset); + } + public function offsetSet($offset, $value) { + } + public function offsetExists($offset) { + } + public function offsetUnset($offset) { + } +} + +$op = new IndexPrinter; +list(123 => $x) = $op; +// PHP shouldn't convert this to an integer offset, because it's ArrayAccess +list("123" => $x) = $op; + +?> +--EXPECT-- +string(3) "bad" +string(3) "sad" + +string(3) "foo" +string(3) "bar" + +GET int(123) +GET string(3) "123" diff --git a/tests/expressions/list/list_keyed_conversions.phpt b/tests/expressions/list/list_keyed_conversions.phpt new file mode 100644 index 00000000..c1837a96 --- /dev/null +++ b/tests/expressions/list/list_keyed_conversions.phpt @@ -0,0 +1,34 @@ +--TEST-- +list() with non-integer-or-string keys +--FILE-- + 0, + 1 => 1, + "" => "" +]; + +list(NULL => $NULL, 1.5 => $float, FALSE => $FALSE, TRUE => $TRUE) = $results; +var_dump($NULL, $float, $FALSE, $TRUE); + +echo PHP_EOL; + +list("0" => $zeroString, "1" => $oneString) = $results; +var_dump($zeroString, $oneString); + +list(STDIN => $resource) = []; + +?> +--EXPECTF-- +string(0) "" +int(1) +int(0) +int(1) + +int(0) +int(1) + +Notice: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d + +Notice: Undefined offset: %d in %s on line %d diff --git a/tests/expressions/list/list_keyed_evaluation_order.inc b/tests/expressions/list/list_keyed_evaluation_order.inc new file mode 100644 index 00000000..d4ee778b --- /dev/null +++ b/tests/expressions/list/list_keyed_evaluation_order.inc @@ -0,0 +1,60 @@ +name = $name; + } + + public function __toString(): string { + echo "$this->name evaluated.", PHP_EOL; + return $this->name; + } +} + +class Indexable implements ArrayAccess +{ + private $array; + public function __construct(array $array) { + $this->array = $array; + } + + public function offsetExists($offset): bool { + echo "Existence of offset $offset checked for.", PHP_EOL; + return isset($this->array[$offset]); + } + + public function offsetUnset($offset): void { + unset($this->array[$offset]); + echo "Offset $offset removed.", PHP_EOL; + } + + public function offsetGet($offset) { + echo "Offset $offset retrieved.", PHP_EOL; + return $this->array[$offset]; + } + + public function offsetSet($offset, $value): void { + $this->array[$offset] = $value; + echo "Offset $offset set to $value.", PHP_EOL; + } +} + +class IndexableRetrievable +{ + private $label; + private $indexable; + + public function __construct(string $label, Indexable $indexable) { + $this->label = $label; + $this->indexable = $indexable; + } + + public function getIndexable(): Indexable { + echo "Indexable $this->label retrieved.", PHP_EOL; + return $this->indexable; + } +} diff --git a/tests/expressions/list/list_keyed_evaluation_order.phpt b/tests/expressions/list/list_keyed_evaluation_order.phpt new file mode 100644 index 00000000..0f0652b6 --- /dev/null +++ b/tests/expressions/list/list_keyed_evaluation_order.phpt @@ -0,0 +1,35 @@ +--TEST-- +list() with keys, evaluation order +--FILE-- + "value for offset A", "C" => "value for offset C"])); + +$store = new Indexable([]); + +// list($a => $b, $c => $d) = $e; +// Should be evaluated in the order: +// 1. Evaluate $e +// 2. Evaluate $a +// 3. Evaluate $e[$a] +// 4. Assign $b from $e[$a] +// 5. Evaluate $c +// 6. Evaluate $e[$c] +// 7. Assign $c from $e[$a] + +list((string)$a => $store["B"], (string)$c => $store["D"]) = $e->getIndexable(); + +?> +--EXPECT-- +Indexable E retrieved. +A evaluated. +Offset A retrieved. +Offset B set to value for offset A. +C evaluated. +Offset C retrieved. +Offset D set to value for offset C. diff --git a/tests/expressions/list/list_keyed_evaluation_order_2.phpt b/tests/expressions/list/list_keyed_evaluation_order_2.phpt new file mode 100644 index 00000000..ddfba68c --- /dev/null +++ b/tests/expressions/list/list_keyed_evaluation_order_2.phpt @@ -0,0 +1,77 @@ +--TEST-- +list() with keys, evaluation order #2 +--FILE-- + $a, 1 => $b) = ['a', 'b']; +var_dump($a); +var_dump($b); + +list(1 => $b, 0 => $a) = ['a', 'b']; +var_dump($a); +var_dump($b); + +$arr = []; +list($arr[], $arr[]) = ['a', 'b']; +var_dump($arr[0]); +var_dump($arr[1]); + +$arr = []; +list(0 => $arr[], 1 => $arr[]) = ['a', 'b']; +var_dump($arr[0]); +var_dump($arr[1]); + +$arr = []; +list(1 => $arr[], 0 => $arr[]) = ['b', 'a']; +var_dump($arr[0]); +var_dump($arr[1]); + +$arr = []; +list(list(1 => $arr[], 0 => $arr[])) = [['b', 'a']]; +var_dump($arr[0]); +var_dump($arr[1]); + +$arr = []; +list('key1' => $arr[], 'key2' => $arr[]) = ['key2' => 'b', 'key1' => 'a']; +var_dump($arr[0]); +var_dump($arr[1]); + +// This should print 'foo' +$a = 0; +list($a => $a) = ['foo', 'bar']; +var_dump($a); + +// This should print 'bar' then 'foo' +$a = 0; +$b = 1; +list($b => $a, $a => $c) = ['bar' => 'foo', 1 => 'bar']; +var_dump($a); +var_dump($c); + +?> +--EXPECT-- +string(1) "a" +string(1) "b" +string(1) "a" +string(1) "b" +string(1) "a" +string(1) "b" +string(1) "a" +string(1) "b" +string(1) "a" +string(1) "b" +string(1) "a" +string(1) "b" +string(1) "a" +string(1) "b" +string(1) "a" +string(1) "b" +string(3) "foo" +string(3) "bar" +string(3) "foo" diff --git a/tests/expressions/list/list_keyed_evaluation_order_3.phpt b/tests/expressions/list/list_keyed_evaluation_order_3.phpt new file mode 100644 index 00000000..7850834c --- /dev/null +++ b/tests/expressions/list/list_keyed_evaluation_order_3.phpt @@ -0,0 +1,24 @@ +--TEST-- +list() with keys, evaluation order #3 +--FILE-- + [ + 'b' => 'bar', + 'a' => 'foo', + ], + 1 => 'a', + 3 => 'b', +]; +list($a[$i++] => $a[$i++], $a[$i++] => $a[$i++]) = $a[$i++]; +var_dump($i); // should be 5 +var_dump($a[2]); // should be 'foo' +var_dump($a[4]); // should be 'bar' + +?> +--EXPECT-- +int(5) +string(3) "foo" +string(3) "bar" diff --git a/tests/expressions/list/list_keyed_evaluation_order_nested.phpt b/tests/expressions/list/list_keyed_evaluation_order_nested.phpt new file mode 100644 index 00000000..8a7725d4 --- /dev/null +++ b/tests/expressions/list/list_keyed_evaluation_order_nested.phpt @@ -0,0 +1,77 @@ +--TEST-- +list() with keys, evaluation order: nested +--FILE-- + "offset value for A", + "C" => new Indexable([ + 0 => "offset value for 0", + 1 => "offset value for 1" + ]), + "F" => new Indexable([ + "G" => "offset value for G", + "I" => "offset value for I" + ]) +])); + +$store = new Indexable([]); + +// list($a => $b, $c => list($d, $e), $f => list($g => $h, $i => $j)) = $k; +// Should be evaluated in the order: +// 1. Evaluate $k +// 2. Evaluate $a +// 3. Evaluate $k[$a] +// 4. Assign $b from $k[$a] +// 5. Evaluate $c +// 6. Evaluate $k[$c] +// 7. Evaluate $k[$c][0] +// 8. Assign $d from $k[$c][0] +// 9. Evaluate $k[$c][1] +// 10. Assign $e from $k[$c][1] +// 11. Evaluate $f +// 12. Evaluate $k[$f] +// 13. Evaluate $g +// 14. Evaluate $k[$f][$g] +// 15. Assign $h from $k[$f][$g] +// 16. Evaluate $i +// 17. Evaluate $k[$f][$i] +// 18. Assign $j from $k[$f][$i] + +list( + (string)$a => $store["B"], + (string)$c => list($store["D"], $store["E"]), + (string)$f => list( + (string)$g => $store["H"], + (string)$i => $store["J"] + ) +) = $k->getIndexable(); + +?> +--EXPECT-- +Indexable K retrieved. +A evaluated. +Offset A retrieved. +Offset B set to offset value for A. +C evaluated. +Offset C retrieved. +Offset 0 retrieved. +Offset D set to offset value for 0. +Offset 1 retrieved. +Offset E set to offset value for 1. +F evaluated. +Offset F retrieved. +G evaluated. +Offset G retrieved. +Offset H set to offset value for G. +I evaluated. +Offset I retrieved. +Offset J set to offset value for I. diff --git a/tests/expressions/list/list_keyed_non_literals.phpt b/tests/expressions/list/list_keyed_non_literals.phpt new file mode 100644 index 00000000..80f22eda --- /dev/null +++ b/tests/expressions/list/list_keyed_non_literals.phpt @@ -0,0 +1,30 @@ +--TEST-- +list() with constant keys +--FILE-- + "one", + 2 => "two", + 3 => "three" +]; + +const COMPILE_TIME_RESOLVABLE = 1; + +define('PROBABLY_NOT_COMPILE_TIME_RESOLVABLE', file_get_contents("data:text/plain,2")); + +$probablyNotCompileTimeResolvable3 = cos(0) * 3; + +list( + COMPILE_TIME_RESOLVABLE => $one, + PROBABLY_NOT_COMPILE_TIME_RESOLVABLE => $two, + $probablyNotCompileTimeResolvable3 => $three +) = $arr; + +var_dump($one, $two, $three); + +?> +--EXPECTF-- +string(3) "one" +string(3) "two" +string(5) "three" diff --git a/tests/expressions/list/list_keyed_trailing_comma.phpt b/tests/expressions/list/list_keyed_trailing_comma.phpt new file mode 100644 index 00000000..e0af0aed --- /dev/null +++ b/tests/expressions/list/list_keyed_trailing_comma.phpt @@ -0,0 +1,38 @@ +--TEST-- +list() with keys and a trailing comma +--FILE-- + "bad", + "happy" => "sad", +]; + +list( + "good" => $good, + "happy" => $happy +) = $antonyms; + +var_dump($good, $happy); + +echo PHP_EOL; + +$antonyms = [ + "good" => "bad", + "happy" => "sad", +]; + +list( + "good" => $good, + "happy" => $happy, +) = $antonyms; + +var_dump($good, $happy); + +?> +--EXPECT-- +string(3) "bad" +string(3) "sad" + +string(3) "bad" +string(3) "sad" diff --git a/tests/expressions/list/list_keyed_undefined.phpt b/tests/expressions/list/list_keyed_undefined.phpt new file mode 100644 index 00000000..a18e3b4d --- /dev/null +++ b/tests/expressions/list/list_keyed_undefined.phpt @@ -0,0 +1,22 @@ +--TEST-- +list() with undefined keys +--FILE-- + "the best PHP version", + "elePHPant" => "the cutest mascot" +]; + +list(5 => $five, "duke" => $duke) = $contrivedMixedKeyTypesExample; + +var_dump($five, $duke); + +?> +--EXPECTF-- + +Notice: Undefined offset: 5 in %s on line %d + +Notice: Undefined index: duke in %s on line %d +NULL +NULL diff --git a/tests/expressions/list/list_mixed_keyed_unkeyed.phpt b/tests/expressions/list/list_mixed_keyed_unkeyed.phpt new file mode 100644 index 00000000..11073a43 --- /dev/null +++ b/tests/expressions/list/list_mixed_keyed_unkeyed.phpt @@ -0,0 +1,16 @@ +--TEST-- +list() with both keyed and unkeyed elements +--FILE-- + 1, + "foo" => "bar" +]; + +list($zero, 1 => $one, "foo" => $foo) = $contrivedKeyedAndUnkeyedArrayExample; + +?> +--EXPECTF-- +Fatal error: Cannot mix keyed and unkeyed array entries in assignments in %s diff --git a/tests/expressions/list/list_mixed_nested_keyed_unkeyed.phpt b/tests/expressions/list/list_mixed_nested_keyed_unkeyed.phpt new file mode 100644 index 00000000..3087775b --- /dev/null +++ b/tests/expressions/list/list_mixed_nested_keyed_unkeyed.phpt @@ -0,0 +1,34 @@ +--TEST-- +list() with nested unkeyed and keyed list() +--FILE-- + 1, "y" => 2], + ["x" => 2, "y" => 1] +]; + +list(list("x" => $x1, "y" => $y1), list("x" => $x2, "y" => $y2)) = $points; +var_dump($x1, $y1, $x2, $y2); + +echo PHP_EOL; + +$invertedPoints = [ + "x" => [1, 2], + "y" => [2, 1] +]; + +list("x" => list($x1, $x2), "y" => list($y1, $y2)) = $invertedPoints; +var_dump($x1, $y1, $x2, $y2); + +?> +--EXPECT-- +int(1) +int(2) +int(2) +int(1) + +int(1) +int(2) +int(2) +int(1) diff --git a/tests/expressions/list/list_self_assign.phpt b/tests/expressions/list/list_self_assign.phpt new file mode 100644 index 00000000..33993c50 --- /dev/null +++ b/tests/expressions/list/list_self_assign.phpt @@ -0,0 +1,56 @@ +--TEST-- +Test variable occurring on both LHS and RHS of list() +--FILE-- + +--EXPECT-- +int(1) +int(2) +int(3) +int(1) +int(2) +int(3) +int(1) +int(2) +int(3) +int(1) +int(2) +int(3) +int(1) +int(2) +int(3) +int(1) +int(2) +int(3) +int(1) +int(2) +int(3) diff --git a/tests/expressions/multiplicative_operators/multiplication_division_modulus.phpt b/tests/expressions/multiplicative_operators/multiplication_division_modulus.phpt index b1efcbce..5ab91c30 100644 --- a/tests/expressions/multiplicative_operators/multiplication_division_modulus.phpt +++ b/tests/expressions/multiplicative_operators/multiplication_division_modulus.phpt @@ -63,8 +63,12 @@ foreach ($oper as $e1) >0< * ><, result: int(0) >0< * >123<, result: int(0) >0< * >2e+5<, result: float(0) ->0< * ><, result: int(0) ->0< * >abc<, result: int(0) +>0< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>0< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >0< * >9223372036854775807<, result: int(0) ------------------------------------- >-10< * >0<, result: int(0) @@ -79,8 +83,12 @@ foreach ($oper as $e1) >-10< * ><, result: int(0) >-10< * >123<, result: int(-1230) >-10< * >2e+5<, result: float(-2000000) ->-10< * ><, result: int(0) ->-10< * >abc<, result: int(0) +>-10< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>-10< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >-10< * >9223372036854775807<, result: float(-9.2233720368548E+19) ------------------------------------- >100< * >0<, result: int(0) @@ -95,8 +103,12 @@ foreach ($oper as $e1) >100< * ><, result: int(0) >100< * >123<, result: int(12300) >100< * >2e+5<, result: float(20000000) ->100< * ><, result: int(0) ->100< * >abc<, result: int(0) +>100< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>100< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >100< * >9223372036854775807<, result: float(9.2233720368548E+20) ------------------------------------- >-34000000000< * >0<, result: float(-0) @@ -111,8 +123,12 @@ foreach ($oper as $e1) >-34000000000< * ><, result: float(-0) >-34000000000< * >123<, result: float(-4182000000000) >-34000000000< * >2e+5<, result: float(-6.8E+15) ->-34000000000< * ><, result: float(-0) ->-34000000000< * >abc<, result: float(-0) +>-34000000000< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>-34000000000< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) >-34000000000< * >9223372036854775807<, result: float(-3.1359464925306E+29) ------------------------------------- >INF< * >0<, result: float(NAN) @@ -127,8 +143,12 @@ foreach ($oper as $e1) >INF< * ><, result: float(NAN) >INF< * >123<, result: float(INF) >INF< * >2e+5<, result: float(INF) ->INF< * ><, result: float(NAN) ->INF< * >abc<, result: float(NAN) +>INF< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>INF< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) >INF< * >9223372036854775807<, result: float(INF) ------------------------------------- >-INF< * >0<, result: float(NAN) @@ -143,8 +163,12 @@ foreach ($oper as $e1) >-INF< * ><, result: float(NAN) >-INF< * >123<, result: float(-INF) >-INF< * >2e+5<, result: float(-INF) ->-INF< * ><, result: float(NAN) ->-INF< * >abc<, result: float(NAN) +>-INF< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>-INF< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) >-INF< * >9223372036854775807<, result: float(-INF) ------------------------------------- >NAN< * >0<, result: float(NAN) @@ -159,8 +183,12 @@ foreach ($oper as $e1) >NAN< * ><, result: float(NAN) >NAN< * >123<, result: float(NAN) >NAN< * >2e+5<, result: float(NAN) ->NAN< * ><, result: float(NAN) ->NAN< * >abc<, result: float(NAN) +>NAN< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>NAN< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) >NAN< * >9223372036854775807<, result: float(NAN) ------------------------------------- >1< * >0<, result: int(0) @@ -175,8 +203,12 @@ foreach ($oper as $e1) >1< * ><, result: int(0) >1< * >123<, result: int(123) >1< * >2e+5<, result: float(200000) ->1< * ><, result: int(0) ->1< * >abc<, result: int(0) +>1< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>1< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >1< * >9223372036854775807<, result: int(9223372036854775807) ------------------------------------- >< * >0<, result: int(0) @@ -191,8 +223,12 @@ foreach ($oper as $e1) >< * ><, result: int(0) >< * >123<, result: int(0) >< * >2e+5<, result: float(0) ->< * ><, result: int(0) ->< * >abc<, result: int(0) +>< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< * >9223372036854775807<, result: int(0) ------------------------------------- >< * >0<, result: int(0) @@ -207,8 +243,12 @@ foreach ($oper as $e1) >< * ><, result: int(0) >< * >123<, result: int(0) >< * >2e+5<, result: float(0) ->< * ><, result: int(0) ->< * >abc<, result: int(0) +>< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >< * >9223372036854775807<, result: int(0) ------------------------------------- >123< * >0<, result: int(0) @@ -223,8 +263,12 @@ foreach ($oper as $e1) >123< * ><, result: int(0) >123< * >123<, result: int(15129) >123< * >2e+5<, result: float(24600000) ->123< * ><, result: int(0) ->123< * >abc<, result: int(0) +>123< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>123< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >123< * >9223372036854775807<, result: float(1.1344747605331E+21) ------------------------------------- >2e+5< * >0<, result: float(0) @@ -239,41 +283,113 @@ foreach ($oper as $e1) >2e+5< * ><, result: float(0) >2e+5< * >123<, result: float(24600000) >2e+5< * >2e+5<, result: float(40000000000) ->2e+5< * ><, result: float(0) ->2e+5< * >abc<, result: float(0) +>2e+5< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>2e+5< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) >2e+5< * >9223372036854775807<, result: float(1.844674407371E+24) ------------------------------------- ->< * >0<, result: int(0) ->< * >-10<, result: int(0) ->< * >100<, result: int(0) ->< * >-34000000000<, result: float(-0) ->< * >INF<, result: float(NAN) ->< * >-INF<, result: float(NAN) ->< * >NAN<, result: float(NAN) ->< * >1<, result: int(0) ->< * ><, result: int(0) ->< * ><, result: int(0) ->< * >123<, result: int(0) ->< * >2e+5<, result: float(0) ->< * ><, result: int(0) ->< * >abc<, result: int(0) ->< * >9223372036854775807<, result: int(0) -------------------------------------- ->abc< * >0<, result: int(0) ->abc< * >-10<, result: int(0) ->abc< * >100<, result: int(0) ->abc< * >-34000000000<, result: float(-0) ->abc< * >INF<, result: float(NAN) ->abc< * >-INF<, result: float(NAN) ->abc< * >NAN<, result: float(NAN) ->abc< * >1<, result: int(0) ->abc< * ><, result: int(0) ->abc< * ><, result: int(0) ->abc< * >123<, result: int(0) ->abc< * >2e+5<, result: float(0) ->abc< * ><, result: int(0) ->abc< * >abc<, result: int(0) ->abc< * >9223372036854775807<, result: int(0) +>< * >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< * >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< * >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< * >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>< * >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>< * >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>< * >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>< * >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< * >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< * >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>< * ><, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< * >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +------------------------------------- +>abc< * >0<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< * >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< * >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< * >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>abc< * >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>abc< * >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>abc< * >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>abc< * >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< * >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< * >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>abc< * ><, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< * >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- >9223372036854775807< * >0<, result: int(0) >9223372036854775807< * >-10<, result: float(-9.2233720368548E+19) @@ -287,8 +403,12 @@ foreach ($oper as $e1) >9223372036854775807< * ><, result: int(0) >9223372036854775807< * >123<, result: float(1.1344747605331E+21) >9223372036854775807< * >2e+5<, result: float(1.844674407371E+24) ->9223372036854775807< * ><, result: int(0) ->9223372036854775807< * >abc<, result: int(0) +>9223372036854775807< * ><, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>9223372036854775807< * >abc<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) >9223372036854775807< * >9223372036854775807<, result: float(8.5070591730235E+37) ------------------------------------- >0< / >-10<, result: int(0) @@ -423,27 +543,67 @@ foreach ($oper as $e1) >2e+5< / >2e+5<, result: float(1) >2e+5< / >9223372036854775807<, result: float(2.168404344971E-14) ------------------------------------- ->< / >-10<, result: int(0) ->< / >100<, result: int(0) ->< / >-34000000000<, result: float(-0) ->< / >INF<, result: float(0) ->< / >-INF<, result: float(-0) ->< / >NAN<, result: float(NAN) ->< / >1<, result: int(0) ->< / >123<, result: int(0) ->< / >2e+5<, result: float(0) ->< / >9223372036854775807<, result: int(0) -------------------------------------- ->abc< / >-10<, result: int(0) ->abc< / >100<, result: int(0) ->abc< / >-34000000000<, result: float(-0) ->abc< / >INF<, result: float(0) ->abc< / >-INF<, result: float(-0) ->abc< / >NAN<, result: float(NAN) ->abc< / >1<, result: int(0) ->abc< / >123<, result: int(0) ->abc< / >2e+5<, result: float(0) ->abc< / >9223372036854775807<, result: int(0) +>< / >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< / >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< / >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>< / >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>< / >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>< / >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>< / >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< / >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>< / >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>< / >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +------------------------------------- +>abc< / >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< / >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< / >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>abc< / >INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>abc< / >-INF<, result: +Warning: A non-numeric value encountered in %s on line %d +float(-0) +>abc< / >NAN<, result: +Warning: A non-numeric value encountered in %s on line %d +float(NAN) +>abc< / >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< / >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +>abc< / >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +float(0) +>abc< / >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) ------------------------------------- >9223372036854775807< / >-10<, result: float(-9.2233720368548E+17) >9223372036854775807< / >100<, result: float(9.2233720368548E+16) @@ -467,7 +627,7 @@ foreach ($oper as $e1) >0< % >123<, result: int(0) (int) >0< % >(int) >123<, result: int(0) >0< % >2e+5<, result: int(0) -(int) >0< % >(int) >2<, result: int(0) +(int) >0< % >(int) >200000<, result: int(0) >0< % >9223372036854775807<, result: int(0) (int) >0< % >(int) >9223372036854775807<, result: int(0) ------------------------------------- @@ -481,8 +641,8 @@ foreach ($oper as $e1) (int) >-10< % >(int) >1<, result: int(0) >-10< % >123<, result: int(-10) (int) >-10< % >(int) >123<, result: int(-10) - >-10< % >2e+5<, result: int(0) -(int) >-10< % >(int) >2<, result: int(0) + >-10< % >2e+5<, result: int(-10) +(int) >-10< % >(int) >200000<, result: int(-10) >-10< % >9223372036854775807<, result: int(-10) (int) >-10< % >(int) >9223372036854775807<, result: int(-10) ------------------------------------- @@ -496,8 +656,8 @@ foreach ($oper as $e1) (int) >100< % >(int) >1<, result: int(0) >100< % >123<, result: int(100) (int) >100< % >(int) >123<, result: int(100) - >100< % >2e+5<, result: int(0) -(int) >100< % >(int) >2<, result: int(0) + >100< % >2e+5<, result: int(100) +(int) >100< % >(int) >200000<, result: int(100) >100< % >9223372036854775807<, result: int(100) (int) >100< % >(int) >9223372036854775807<, result: int(100) ------------------------------------- @@ -512,7 +672,7 @@ foreach ($oper as $e1) >-34000000000< % >123<, result: int(-28) (int) >-34000000000< % >(int) >123<, result: int(-28) >-34000000000< % >2e+5<, result: int(0) -(int) >-34000000000< % >(int) >2<, result: int(0) +(int) >-34000000000< % >(int) >200000<, result: int(0) >-34000000000< % >9223372036854775807<, result: int(-34000000000) (int) >-34000000000< % >(int) >9223372036854775807<, result: int(-34000000000) ------------------------------------- @@ -527,7 +687,7 @@ foreach ($oper as $e1) >INF< % >123<, result: int(0) (int) >0< % >(int) >123<, result: int(0) >INF< % >2e+5<, result: int(0) -(int) >0< % >(int) >2<, result: int(0) +(int) >0< % >(int) >200000<, result: int(0) >INF< % >9223372036854775807<, result: int(0) (int) >0< % >(int) >9223372036854775807<, result: int(0) ------------------------------------- @@ -542,7 +702,7 @@ foreach ($oper as $e1) >-INF< % >123<, result: int(0) (int) >0< % >(int) >123<, result: int(0) >-INF< % >2e+5<, result: int(0) -(int) >0< % >(int) >2<, result: int(0) +(int) >0< % >(int) >200000<, result: int(0) >-INF< % >9223372036854775807<, result: int(0) (int) >0< % >(int) >9223372036854775807<, result: int(0) ------------------------------------- @@ -557,7 +717,7 @@ foreach ($oper as $e1) >NAN< % >123<, result: int(0) (int) >0< % >(int) >123<, result: int(0) >NAN< % >2e+5<, result: int(0) -(int) >0< % >(int) >2<, result: int(0) +(int) >0< % >(int) >200000<, result: int(0) >NAN< % >9223372036854775807<, result: int(0) (int) >0< % >(int) >9223372036854775807<, result: int(0) ------------------------------------- @@ -572,7 +732,7 @@ foreach ($oper as $e1) >1< % >123<, result: int(1) (int) >1< % >(int) >123<, result: int(1) >1< % >2e+5<, result: int(1) -(int) >1< % >(int) >2<, result: int(1) +(int) >1< % >(int) >200000<, result: int(1) >1< % >9223372036854775807<, result: int(1) (int) >1< % >(int) >9223372036854775807<, result: int(1) ------------------------------------- @@ -587,7 +747,7 @@ foreach ($oper as $e1) >< % >123<, result: int(0) (int) >0< % >(int) >123<, result: int(0) >< % >2e+5<, result: int(0) -(int) >0< % >(int) >2<, result: int(0) +(int) >0< % >(int) >200000<, result: int(0) >< % >9223372036854775807<, result: int(0) (int) >0< % >(int) >9223372036854775807<, result: int(0) ------------------------------------- @@ -602,7 +762,7 @@ foreach ($oper as $e1) >< % >123<, result: int(0) (int) >0< % >(int) >123<, result: int(0) >< % >2e+5<, result: int(0) -(int) >0< % >(int) >2<, result: int(0) +(int) >0< % >(int) >200000<, result: int(0) >< % >9223372036854775807<, result: int(0) (int) >0< % >(int) >9223372036854775807<, result: int(0) ------------------------------------- @@ -616,54 +776,82 @@ foreach ($oper as $e1) (int) >123< % >(int) >1<, result: int(0) >123< % >123<, result: int(0) (int) >123< % >(int) >123<, result: int(0) - >123< % >2e+5<, result: int(1) -(int) >123< % >(int) >2<, result: int(1) + >123< % >2e+5<, result: int(123) +(int) >123< % >(int) >200000<, result: int(123) >123< % >9223372036854775807<, result: int(123) (int) >123< % >(int) >9223372036854775807<, result: int(123) ------------------------------------- - >2e+5< % >-10<, result: int(2) -(int) >2< % >(int) >-10<, result: int(2) - >2e+5< % >100<, result: int(2) -(int) >2< % >(int) >100<, result: int(2) - >2e+5< % >-34000000000<, result: int(2) -(int) >2< % >(int) >-34000000000<, result: int(2) + >2e+5< % >-10<, result: int(0) +(int) >200000< % >(int) >-10<, result: int(0) + >2e+5< % >100<, result: int(0) +(int) >200000< % >(int) >100<, result: int(0) + >2e+5< % >-34000000000<, result: int(200000) +(int) >200000< % >(int) >-34000000000<, result: int(200000) >2e+5< % >1<, result: int(0) -(int) >2< % >(int) >1<, result: int(0) +(int) >200000< % >(int) >1<, result: int(0) >2e+5< % >123<, result: int(2) -(int) >2< % >(int) >123<, result: int(2) +(int) >200000< % >(int) >123<, result: int(2) >2e+5< % >2e+5<, result: int(0) -(int) >2< % >(int) >2<, result: int(0) - >2e+5< % >9223372036854775807<, result: int(2) -(int) >2< % >(int) >9223372036854775807<, result: int(2) +(int) >200000< % >(int) >200000<, result: int(0) + >2e+5< % >9223372036854775807<, result: int(200000) +(int) >200000< % >(int) >9223372036854775807<, result: int(200000) ------------------------------------- - >< % >-10<, result: int(0) + >< % >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) (int) >0< % >(int) >-10<, result: int(0) - >< % >100<, result: int(0) + >< % >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) (int) >0< % >(int) >100<, result: int(0) - >< % >-34000000000<, result: int(0) + >< % >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) (int) >0< % >(int) >-34000000000<, result: int(0) - >< % >1<, result: int(0) + >< % >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) (int) >0< % >(int) >1<, result: int(0) - >< % >123<, result: int(0) + >< % >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) (int) >0< % >(int) >123<, result: int(0) - >< % >2e+5<, result: int(0) -(int) >0< % >(int) >2<, result: int(0) - >< % >9223372036854775807<, result: int(0) + >< % >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +(int) >0< % >(int) >200000<, result: int(0) + >< % >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) (int) >0< % >(int) >9223372036854775807<, result: int(0) ------------------------------------- - >abc< % >-10<, result: int(0) + >abc< % >-10<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) (int) >0< % >(int) >-10<, result: int(0) - >abc< % >100<, result: int(0) + >abc< % >100<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) (int) >0< % >(int) >100<, result: int(0) - >abc< % >-34000000000<, result: int(0) + >abc< % >-34000000000<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) (int) >0< % >(int) >-34000000000<, result: int(0) - >abc< % >1<, result: int(0) + >abc< % >1<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) (int) >0< % >(int) >1<, result: int(0) - >abc< % >123<, result: int(0) + >abc< % >123<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) (int) >0< % >(int) >123<, result: int(0) - >abc< % >2e+5<, result: int(0) -(int) >0< % >(int) >2<, result: int(0) - >abc< % >9223372036854775807<, result: int(0) + >abc< % >2e+5<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) +(int) >0< % >(int) >200000<, result: int(0) + >abc< % >9223372036854775807<, result: +Warning: A non-numeric value encountered in %s on line %d +int(0) (int) >0< % >(int) >9223372036854775807<, result: int(0) ------------------------------------- >9223372036854775807< % >-10<, result: int(7) @@ -676,8 +864,8 @@ foreach ($oper as $e1) (int) >9223372036854775807< % >(int) >1<, result: int(0) >9223372036854775807< % >123<, result: int(7) (int) >9223372036854775807< % >(int) >123<, result: int(7) - >9223372036854775807< % >2e+5<, result: int(1) -(int) >9223372036854775807< % >(int) >2<, result: int(1) + >9223372036854775807< % >2e+5<, result: int(175807) +(int) >9223372036854775807< % >(int) >200000<, result: int(175807) >9223372036854775807< % >9223372036854775807<, result: int(0) (int) >9223372036854775807< % >(int) >9223372036854775807<, result: int(0) -------------------------------------- \ No newline at end of file +------------------------------------- diff --git a/tests/expressions/postfix_operators/member_selection_operator.phpt b/tests/expressions/postfix_operators/member_selection_operator.phpt index a5155d40..95ca7598 100644 --- a/tests/expressions/postfix_operators/member_selection_operator.phpt +++ b/tests/expressions/postfix_operators/member_selection_operator.phpt @@ -34,7 +34,7 @@ class Point { $this->x = $x; $this->y = $y; - } + } public function translate($x, $y) { diff --git a/tests/expressions/postfix_operators/scope_resolution_operator.phpt b/tests/expressions/postfix_operators/scope_resolution_operator.phpt index 9c904f8f..d42c112d 100644 --- a/tests/expressions/postfix_operators/scope_resolution_operator.phpt +++ b/tests/expressions/postfix_operators/scope_resolution_operator.phpt @@ -20,7 +20,7 @@ class M const MYPI = 3.14; const CON1 = -222; -// method b1 demostrates self vs. static +// method b1 demonstrates self vs. static public function b1() { @@ -93,7 +93,7 @@ class P extends N echo "Inside static " . __METHOD__ . "\n"; } -// method f1 demostrates self and parent +// method f1 demonstrates self and parent public static function f1() { diff --git a/tests/expressions/postfix_operators/subscripting.phpt b/tests/expressions/postfix_operators/subscripting.phpt index dfd46e23..1f8fe603 100644 --- a/tests/expressions/postfix_operators/subscripting.phpt +++ b/tests/expressions/postfix_operators/subscripting.phpt @@ -26,7 +26,7 @@ foreach ($v as $k => $e) echo "key: ".$k.", value: ".$e."\n"; } -// try to access non-existant elements +// try to access non-existent elements echo "[7] contains >".($v[7] == NULL ? "NULL" : "??") ."<, [12] contains >".($v[12] == NULL ? "NULL" : "??")."<\n"; @@ -76,7 +76,7 @@ var_dump($z); $z = [array(2,4,6,8), array(5,10), array(100,200,300)][0][2]; var_dump($z); -$z = [[2,4,6,8], [5,10], [100,200,300]][0][2]; // acceses element with value 6 +$z = [[2,4,6,8], [5,10], [100,200,300]][0][2]; // accesses element with value 6 var_dump($z); var_dump(["black", "white", "yellow"][1]); // white @@ -89,7 +89,7 @@ function f() } //*/ ///* -var_dump(f()[2]); // acceses element with value 3000 +var_dump(f()[2]); // accesses element with value 3000 //*/ ///* @@ -144,7 +144,7 @@ var_dump($v[1]); // OK, results in NULL "red"[1]; var_dump("red"[1]); // OK, results in "e" var_dump("red"[1.9]); // OK, results in "e" -var_dump("red"[-1]); // OK, results in "" +var_dump("red"[-1]); // OK, results in "d" var_dump("red"[10]); // OK, results in "" var_dump("red"["abc"]); // Warning, results in "r" from [0] @@ -179,7 +179,7 @@ $s[0] = "DEF"; // "r" -> "D"; only 1 char changed var_dump($s); $s[0] = "MN"; // "D" -> "M"; only 1 char changed var_dump($s); -$s[0] = ""; // "M" -> "\0" +$s[0] = ""; // warning; nothing changed var_dump($s); $s["zz"] = "Q"; // warning; "Q" goes into [0] var_dump($s); @@ -364,9 +364,7 @@ string(1) "e" Notice: String offset cast occurred in %s/expressions/postfix_operators/subscripting.php on line 143 string(1) "e" - -Notice: Uninitialized string offset: -1 in %s/expressions/postfix_operators/subscripting.php on line 144 -string(0) "" +string(1) "d" Notice: Uninitialized string offset: 10 in %s/expressions/postfix_operators/subscripting.php on line 145 string(0) "" @@ -393,7 +391,9 @@ string(6) "rXd Z" [5] is not a space string(6) "DXd Z" string(6) "MXd Z" -string(6) "Xd Z" + +Warning: Cannot assign an empty string to a string offset in %s +string(6) "MXd Z" Warning: Illegal string offset 'zz' in %s/expressions/postfix_operators/subscripting.php on line 181 string(6) "QXd Z" diff --git a/tests/expressions/postfix_operators/subscripting_2.phpt b/tests/expressions/postfix_operators/subscripting_2.phpt index c9c2b490..a269350d 100644 --- a/tests/expressions/postfix_operators/subscripting_2.phpt +++ b/tests/expressions/postfix_operators/subscripting_2.phpt @@ -11,7 +11,7 @@ var_dump($a); echo "------\n"; $a = array(-30 => 33, -10 => -11); -var_dump($a[] = 991); // creates $a[0] +var_dump($a[] = 991); // creates $a[-9] var_dump($a); echo "------\n"; @@ -170,7 +170,7 @@ array(3) { int(33) [-10]=> int(-11) - [0]=> + [-9]=> int(991) } ------ diff --git a/tests/expressions/primary_expressions/Point.inc b/tests/expressions/primary_expressions/Point.inc index f62c6596..2942d85d 100644 --- a/tests/expressions/primary_expressions/Point.inc +++ b/tests/expressions/primary_expressions/Point.inc @@ -8,7 +8,7 @@ error_reporting(-1); -class Point +class Point { private $x; // Cartesian x-coordinate private $y; // Cartesian y-coordinate @@ -19,28 +19,28 @@ class Point public function setY($y) { $this->y = $y; } // public function __construct($x, $y) // see what happens if no default values - public function __construct($x = 0, $y = 0) + public function __construct($x = 0, $y = 0) { $this->x = $x; $this->y = $y; } - public function move($x, $y) + public function move($x, $y) { $this->x = $x; $this->y = $y; - } + } - public function translate($x, $y) + public function translate($x, $y) { $this->x += $x; $this->y += $y; } - public function __toString() + public function __toString() { // throw new Exception; // throw statement is not permitted return '(' . $this->x . ',' . $this->y . ')'; - } + } } diff --git a/tests/expressions/primary_expressions/Point2.inc b/tests/expressions/primary_expressions/Point2.inc index 29e1da60..59ded534 100644 --- a/tests/expressions/primary_expressions/Point2.inc +++ b/tests/expressions/primary_expressions/Point2.inc @@ -8,31 +8,31 @@ error_reporting(-1); -class Point2 +class Point2 { private static $pointCount = 0; public $x; // Cartesian x-coordinate public $y; // Cartesian y-coordinate - public static function getPointCount() + public static function getPointCount() { return self::$pointCount; } - public function __construct($x = 0, $y = 0) + public function __construct($x = 0, $y = 0) { $this->x = $x; $this->y = $y; ++self::$pointCount; } - public function __destruct() + public function __destruct() { --self::$pointCount; } ///* - public function __clone() + public function __clone() { ++self::$pointCount; @@ -43,9 +43,9 @@ class Point2 } //*/ - public function __toString() + public function __toString() { return '(' . $this->x . ',' . $this->y . ')'; - } + } } diff --git a/tests/expressions/primary_expressions/intrinsics_empty.phpt b/tests/expressions/primary_expressions/intrinsics_empty.phpt index 9500a634..2eca9045 100644 --- a/tests/expressions/primary_expressions/intrinsics_empty.phpt +++ b/tests/expressions/primary_expressions/intrinsics_empty.phpt @@ -114,18 +114,6 @@ class XX {} $v = new XX; var_dump(empty($v)); -echo "--------- undefined parameter -------------\n"; - -function f($p) -{ - var_dump($p); - var_dump(empty($p)); -} - -f(); -f(NULL); -f(10); - echo "---------- resource STDIN ------------\n"; var_dump(empty(STDIN)); @@ -205,17 +193,6 @@ bool(false) bool(false) --------- instance of class having no properties ------------- bool(false) ---------- undefined parameter ------------- - -Warning: %s - -Notice: Undefined variable: p in %s/expressions/primary_expressions/intrinsics_empty.php on line 118 -NULL -bool(true) -NULL -bool(true) -int(10) -bool(false) ---------- resource STDIN ------------ bool(false) bool(false) diff --git a/tests/expressions/primary_expressions/intrinsics_isset.phpt b/tests/expressions/primary_expressions/intrinsics_isset.phpt index 8df019e4..2dfd4907 100644 --- a/tests/expressions/primary_expressions/intrinsics_isset.phpt +++ b/tests/expressions/primary_expressions/intrinsics_isset.phpt @@ -15,6 +15,10 @@ echo "--------- TRUE -------------\n"; $v = TRUE; var_dump(isset($v)); +echo "--------- TRUE -------------\n"; + +$v = TRUE; +var_dump(isset($v,)); echo "--------- NULL -------------\n"; @@ -26,18 +30,6 @@ echo "--------- TRUE, 12.3, NULL -------------\n"; $v1 = TRUE; $v2 = 12.3; $v3 = NULL; var_dump(isset($v1, $v2, $v3)); -echo "--------- undefined parameter -------------\n"; - -function f($p) -{ - var_dump($p); - var_dump(isset($p)); -} - -f(); -f(NULL); -f(10); - echo "---------- dynamic property ------------\n"; class X1 @@ -64,21 +56,12 @@ var_dump(isset($x2->m)); --EXPECTF-- --------- TRUE ------------- bool(true) +--------- TRUE ------------- +bool(true) --------- NULL ------------- bool(false) --------- TRUE, 12.3, NULL ------------- bool(false) ---------- undefined parameter ------------- - -Warning: %s - -Notice: Undefined variable: p in %s/expressions/primary_expressions/intrinsics_isset.php on line 30 -NULL -bool(false) -NULL -bool(false) -int(10) -bool(true) ---------- dynamic property ------------ bool(false) bool(true) diff --git a/tests/expressions/primary_expressions/intrinsics_unset.phpt b/tests/expressions/primary_expressions/intrinsics_unset.phpt index 8438d2dd..7ec56a45 100644 --- a/tests/expressions/primary_expressions/intrinsics_unset.phpt +++ b/tests/expressions/primary_expressions/intrinsics_unset.phpt @@ -18,6 +18,13 @@ var_dump(isset($v)); unset($v); var_dump(isset($v)); +echo "--------- TRUE -------------\n"; + +$v = TRUE; +var_dump(isset($v)); +unset($v,); +var_dump(isset($v)); + echo "--------- NULL -------------\n"; $v = NULL; @@ -32,20 +39,6 @@ var_dump(isset($v1, $v2, $v3)); unset($v1, $v2, $v3); var_dump(isset($v1, $v2, $v3)); -echo "--------- undefined parameter -------------\n"; - -function f($p) -{ - var_dump($p); - var_dump(isset($p)); - unset($p); - var_dump(isset($p)); -} - -f(); -f(NULL); -f(10); - echo "---------- dynamic property ------------\n"; class X1 @@ -162,32 +155,6 @@ $c2 = new C; var_dump($c2); var_dump(isset($c2->prop)); -echo "---------- unsetting \$this ------------\n"; - -class D -{ - public function f() - { - echo "Inside ". __METHOD__ . "\n"; - - var_dump(isset($this)); - unset($this); - var_dump(isset($this)); - - $this->g(); // use $this to call sibling instance method - } - - private function g() - { - echo "Inside ". __METHOD__ . "\n"; - - var_dump(isset($this)); - } -} - -$d = new D; -$d->f(); - echo "---------- unsetting array elements ------------\n"; $a = array(10, 20, "xx" => 30); @@ -204,24 +171,13 @@ print_r($a); --------- TRUE ------------- bool(true) bool(false) ---------- NULL ------------- -bool(false) -bool(false) ---------- TRUE, 12.3, NULL ------------- +--------- TRUE ------------- bool(true) bool(false) ---------- undefined parameter ------------- - -Warning: %s - -Notice: Undefined variable: p in %s/expressions/primary_expressions/intrinsics_unset.php on line 36 -NULL -bool(false) -bool(false) -NULL +--------- NULL ------------- bool(false) bool(false) -int(10) +--------- TRUE, 12.3, NULL ------------- bool(true) bool(false) ---------- dynamic property ------------ @@ -270,12 +226,6 @@ object(C)#4 (1) { int(10) } bool(true) ----------- unsetting $this ------------ -Inside D::f -bool(true) -bool(false) -Inside D::g -bool(true) ---------- unsetting array elements ------------ Array ( diff --git a/tests/expressions/relational_operators/comparisons1.phpt b/tests/expressions/relational_operators/comparisons1.phpt index 80596132..ab2a4941 100644 --- a/tests/expressions/relational_operators/comparisons1.phpt +++ b/tests/expressions/relational_operators/comparisons1.phpt @@ -27,7 +27,7 @@ echo "\n"; ///* // NULL operand with all kinds of operands, swapping them over to make -// LHS/RHS order is irrelevent. +// LHS/RHS order is irrelevant. $oper1 = array(NULL); $oper2 = array(0, 100, -3.4, TRUE, FALSE, NULL, "", "123", "abc", [], [10,2.3]); diff --git a/tests/expressions/relational_operators/comparisons3.phpt b/tests/expressions/relational_operators/comparisons3.phpt index e2be80ab..8fa0540e 100644 --- a/tests/expressions/relational_operators/comparisons3.phpt +++ b/tests/expressions/relational_operators/comparisons3.phpt @@ -13,7 +13,7 @@ error_reporting(-1); ///* // Boolean operand with all kinds of operands, swapping them over to make -// LHS/RHS order is irrelevent. +// LHS/RHS order is irrelevant. $oper1 = array(TRUE, FALSE); $oper2 = array(0, 100, -3.4, TRUE, FALSE, NULL, "", "123", "abc", [], [10,2.3]); diff --git a/tests/expressions/relational_operators/comparisons4.phpt b/tests/expressions/relational_operators/comparisons4.phpt index 6f077695..d22935af 100644 --- a/tests/expressions/relational_operators/comparisons4.phpt +++ b/tests/expressions/relational_operators/comparisons4.phpt @@ -13,7 +13,7 @@ error_reporting(-1); ///* // Numeric strings with all kinds of operands, swapping them over to make -// LHS/RHS order is irrelevent. +// LHS/RHS order is irrelevant. $oper1 = array("10", "-5.1"); $oper2 = array(0, 100, -3.4, TRUE, FALSE, NULL, "", "123", "abc", [], [10,2.3]); diff --git a/tests/expressions/source_file_inclusion/Point.inc b/tests/expressions/source_file_inclusion/Point.inc index 54a65d8e..27c0da27 100644 --- a/tests/expressions/source_file_inclusion/Point.inc +++ b/tests/expressions/source_file_inclusion/Point.inc @@ -8,9 +8,9 @@ error_reporting(-1); -class Point +class Point { - public function __construct($newX = 0, $newY = 0) + public function __construct($newX = 0, $newY = 0) { } } diff --git a/tests/expressions/source_file_inclusion/include.phpt b/tests/expressions/source_file_inclusion/include.phpt index 55b8f4ac..89fc0c02 100644 --- a/tests/expressions/source_file_inclusion/include.phpt +++ b/tests/expressions/source_file_inclusion/include.phpt @@ -17,7 +17,7 @@ echo "Inside file >" . __FILE__ . "< at line >" . __LINE__ . //var_dump(MY_MIN); //var_dump(MY_MAX); -// Try to include a non-existant file +// Try to include a non-existent file $fileName = 'unknown.inc'; $inc = include $fileName; diff --git a/tests/expressions/source_file_inclusion/include_once.phpt b/tests/expressions/source_file_inclusion/include_once.phpt index 305f5731..2dd96ded 100644 --- a/tests/expressions/source_file_inclusion/include_once.phpt +++ b/tests/expressions/source_file_inclusion/include_once.phpt @@ -11,7 +11,7 @@ PHP Spec test generated from ./expressions/source_file_inclusion/include_once.ph error_reporting(-1); -// Try to include a non-existant file +// Try to include a non-existent file $inc = include_once 'XXPositions.inc'; var_dump($inc); diff --git a/tests/expressions/source_file_inclusion/require.phpt b/tests/expressions/source_file_inclusion/require.phpt index e8db28bd..a357d3d1 100644 --- a/tests/expressions/source_file_inclusion/require.phpt +++ b/tests/expressions/source_file_inclusion/require.phpt @@ -17,7 +17,7 @@ echo "Inside file >" . __FILE__ . "< at line >" . __LINE__ . //var_dump(MY_MIN); //var_dump(MY_MAX); -// Try to require a non-existant file +// Try to require a non-existent file $fileName = 'unknown.inc'; //$inc = require $fileName; diff --git a/tests/expressions/source_file_inclusion/require_once.phpt b/tests/expressions/source_file_inclusion/require_once.phpt index 7e8410c7..e3a6aaad 100644 --- a/tests/expressions/source_file_inclusion/require_once.phpt +++ b/tests/expressions/source_file_inclusion/require_once.phpt @@ -11,7 +11,7 @@ PHP Spec test generated from ./expressions/source_file_inclusion/require_once.ph error_reporting(-1); -// Try to require a non-existant file +// Try to require a non-existent file //$inc = require_once('XXPositions.inc'); //var_dump($inc); diff --git a/tests/expressions/unary_operators/cast.phpt b/tests/expressions/unary_operators/cast.phpt index 7805253d..9c714384 100644 --- a/tests/expressions/unary_operators/cast.phpt +++ b/tests/expressions/unary_operators/cast.phpt @@ -29,8 +29,10 @@ echo var_dump((binary)""); echo var_dump((binary)"abcdef"); echo var_dump($v); -echo var_dump((unset)$v); -echo var_dump($v); + +// The (unset) cast is no longer supported +//echo var_dump((unset)$v); +//echo var_dump($v); //*/ ///* @@ -90,9 +92,9 @@ echo "---------------\n"; class E { - const CON1 = 123; // constants irrelevent for conversion purposes - public function f() {} // methods irrelevent for conversion purposes - private static $fsprop = 0; // static properties irrelevent for conversion purposes + const CON1 = 123; // constants irrelevant for conversion purposes + public function f() {} // methods irrelevant for conversion purposes + private static $fsprop = 0; // static properties irrelevant for conversion purposes private $priv_prop; protected $prot_prop = 12.345; @@ -166,8 +168,6 @@ string(1) "0" string(0) "" string(6) "abcdef" int(0) -NULL -int(0) int(10) bool(true) bool(true) @@ -455,7 +455,7 @@ array(2) { int(1) float(1) -Notice: Array to string conversion in %s/expressions/unary_operators/cast.php on line 50 +Notice: Array to string conversion in %s/expressions/unary_operators/cast.php on line %d string(5) "Array" array(2) { [5]=> @@ -464,9 +464,9 @@ string(5) "Array" int(20) } >>---object(stdClass)#1 (2) { - [5]=> + ["5"]=> int(10) - [2]=> + ["2"]=> int(20) } array(4) { @@ -484,7 +484,7 @@ array(4) { int(1) float(1) -Notice: Array to string conversion in %s/expressions/unary_operators/cast.php on line 50 +Notice: Array to string conversion in %s/expressions/unary_operators/cast.php on line %d string(5) "Array" array(4) { [0]=> @@ -497,13 +497,13 @@ string(5) "Array" NULL } >>---object(stdClass)#1 (4) { - [0]=> + ["0"]=> float(1.23) - [1]=> + ["1"]=> bool(true) - [2]=> + ["2"]=> string(5) "Hello" - [3]=> + ["3"]=> NULL } float(3.3333333333333) @@ -554,7 +554,7 @@ object(E)#3 (3) { $key: >Epriv_prop<, len: 12, $val: >< $key: >*prot_prop<, len: 12, $val: >12.345< -Notice: Array to string conversion in %s/expressions/unary_operators/cast.php on line 115 +Notice: Array to string conversion in %s/expressions/unary_operators/cast.php on line %d $key: >publ_prop<, len: 9, $val: >Array< --------------- resource(1) of type (stream) diff --git a/tests/expressions/unary_operators/pre-increment_and_decrement.phpt b/tests/expressions/unary_operators/pre-increment_and_decrement.phpt index c111f7fb..c417cc14 100644 --- a/tests/expressions/unary_operators/pre-increment_and_decrement.phpt +++ b/tests/expressions/unary_operators/pre-increment_and_decrement.phpt @@ -257,7 +257,7 @@ $x = "zza"; var_dump($x); var_dump(--$x); var_dump(--$x); ---EXPECT-- +--EXPECTF-- --------------------------------------- start incdec --- $a = 5 <---> int(5) $a = 4 <---> int(4) @@ -389,6 +389,8 @@ $a = <---> bool(false) --------------------------------------- start incdec --- $a = <---> string(0) "" $a = -1 <---> int(-1) + +Warning: A non-numeric value encountered in %s on line %d $a = -2 <---> int(-2) $a = -1 <---> int(-1) $a = 0 @@ -397,6 +399,8 @@ $a = 0 <---> int(0) --------------------------------------- start incdecrev --- $a = <---> string(0) "" $a = 1 <---> string(1) "1" + +Warning: A non-numeric value encountered in %s on line %d $a = 2 <---> int(2) $a = 1 <---> int(1) $a = 2 @@ -501,6 +505,8 @@ $a = 14 <---> int(14) --------------------------------------- start incdec --- $a = 0x12 <---> string(4) "0x12" $a = 0x12 <---> string(4) "0x12" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 0x12 <---> string(4) "0x12" $a = 0x13 <---> string(4) "0x13" $a = 0x14 @@ -509,6 +515,8 @@ $a = 0x14 <---> string(4) "0x14" --------------------------------------- start incdecrev --- $a = 0x12 <---> string(4) "0x12" $a = 0x13 <---> string(4) "0x13" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 0x14 <---> string(4) "0x14" $a = 0x14 <---> string(4) "0x14" $a = 0x15 @@ -517,6 +525,8 @@ $a = 0x15 <---> string(4) "0x15" --------------------------------------- start incdec --- $a = 0X12 <---> string(4) "0X12" $a = 0X12 <---> string(4) "0X12" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 0X12 <---> string(4) "0X12" $a = 0X13 <---> string(4) "0X13" $a = 0X14 @@ -525,6 +535,8 @@ $a = 0X14 <---> string(4) "0X14" --------------------------------------- start incdecrev --- $a = 0X12 <---> string(4) "0X12" $a = 0X13 <---> string(4) "0X13" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 0X14 <---> string(4) "0X14" $a = 0X14 <---> string(4) "0X14" $a = 0X15 @@ -533,6 +545,8 @@ $a = 0X15 <---> string(4) "0X15" --------------------------------------- start incdec --- $a = 0b101 <---> string(5) "0b101" $a = 0b101 <---> string(5) "0b101" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 0b101 <---> string(5) "0b101" $a = 0b102 <---> string(5) "0b102" $a = 0b103 @@ -541,6 +555,8 @@ $a = 0b103 <---> string(5) "0b103" --------------------------------------- start incdecrev --- $a = 0b101 <---> string(5) "0b101" $a = 0b102 <---> string(5) "0b102" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 0b103 <---> string(5) "0b103" $a = 0b103 <---> string(5) "0b103" $a = 0b104 @@ -549,6 +565,8 @@ $a = 0b104 <---> string(5) "0b104" --------------------------------------- start incdec --- $a = 0B101 <---> string(5) "0B101" $a = 0B101 <---> string(5) "0B101" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 0B101 <---> string(5) "0B101" $a = 0B102 <---> string(5) "0B102" $a = 0B103 @@ -557,6 +575,8 @@ $a = 0B103 <---> string(5) "0B103" --------------------------------------- start incdecrev --- $a = 0B101 <---> string(5) "0B101" $a = 0B102 <---> string(5) "0B102" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 0B103 <---> string(5) "0B103" $a = 0B103 <---> string(5) "0B103" $a = 0B104 @@ -565,6 +585,8 @@ $a = 0B104 <---> string(5) "0B104" --------------------------------------- start incdec --- $a = 0Q101 <---> string(5) "0Q101" $a = 0Q101 <---> string(5) "0Q101" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 0Q101 <---> string(5) "0Q101" $a = 0Q102 <---> string(5) "0Q102" $a = 0Q103 @@ -573,6 +595,8 @@ $a = 0Q103 <---> string(5) "0Q103" --------------------------------------- start incdecrev --- $a = 0Q101 <---> string(5) "0Q101" $a = 0Q102 <---> string(5) "0Q102" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 0Q103 <---> string(5) "0Q103" $a = 0Q103 <---> string(5) "0Q103" $a = 0Q104 @@ -665,6 +689,8 @@ $a = 96 <---> int(96) --------------------------------------- start incdec --- $a = 987 <---> string(4) "987 " $a = 987 <---> string(4) "987 " + +Notice: A non well formed numeric value encountered in %s on line %d $a = 987 <---> string(4) "987 " $a = 987 <---> string(4) "987 " $a = 987 @@ -673,6 +699,8 @@ $a = 987 <---> string(4) "987 " --------------------------------------- start incdecrev --- $a = 987 <---> string(4) "987 " $a = 987 <---> string(4) "987 " + +Notice: A non well formed numeric value encountered in %s on line %d $a = 987 <---> string(4) "987 " $a = 987 <---> string(4) "987 " $a = 987 @@ -685,6 +713,8 @@ $a = 15 $a = 15 <---> string(9) "15 " + +Notice: A non well formed numeric value encountered in %s on line %d $a = 15 <---> string(9) "15 " @@ -704,6 +734,8 @@ $a = 15 $a = 15 <---> string(9) "15 " + +Notice: A non well formed numeric value encountered in %s on line %d $a = 15 <---> string(9) "15 " @@ -815,6 +847,8 @@ $a = 11.87 <---> float(11.87) --------------------------------------- start incdec --- $a = a <---> string(1) "a" $a = a <---> string(1) "a" + +Warning: A non-numeric value encountered in %s on line %d $a = a <---> string(1) "a" $a = b <---> string(1) "b" $a = c @@ -823,6 +857,8 @@ $a = c <---> string(1) "c" --------------------------------------- start incdecrev --- $a = a <---> string(1) "a" $a = b <---> string(1) "b" + +Warning: A non-numeric value encountered in %s on line %d $a = c <---> string(1) "c" $a = c <---> string(1) "c" $a = d @@ -831,6 +867,8 @@ $a = d <---> string(1) "d" --------------------------------------- start incdec --- $a = z <---> string(1) "z" $a = z <---> string(1) "z" + +Warning: A non-numeric value encountered in %s on line %d $a = z <---> string(1) "z" $a = aa <---> string(2) "aa" $a = ab @@ -839,6 +877,8 @@ $a = ab <---> string(2) "ab" --------------------------------------- start incdecrev --- $a = z <---> string(1) "z" $a = aa <---> string(2) "aa" + +Warning: A non-numeric value encountered in %s on line %d $a = ab <---> string(2) "ab" $a = ab <---> string(2) "ab" $a = ac @@ -847,6 +887,8 @@ $a = ac <---> string(2) "ac" --------------------------------------- start incdec --- $a = A <---> string(1) "A" $a = A <---> string(1) "A" + +Warning: A non-numeric value encountered in %s on line %d $a = A <---> string(1) "A" $a = B <---> string(1) "B" $a = C @@ -855,6 +897,8 @@ $a = C <---> string(1) "C" --------------------------------------- start incdecrev --- $a = A <---> string(1) "A" $a = B <---> string(1) "B" + +Warning: A non-numeric value encountered in %s on line %d $a = C <---> string(1) "C" $a = C <---> string(1) "C" $a = D @@ -863,6 +907,8 @@ $a = D <---> string(1) "D" --------------------------------------- start incdec --- $a = Z <---> string(1) "Z" $a = Z <---> string(1) "Z" + +Warning: A non-numeric value encountered in %s on line %d $a = Z <---> string(1) "Z" $a = AA <---> string(2) "AA" $a = AB @@ -871,6 +917,8 @@ $a = AB <---> string(2) "AB" --------------------------------------- start incdecrev --- $a = Z <---> string(1) "Z" $a = AA <---> string(2) "AA" + +Warning: A non-numeric value encountered in %s on line %d $a = AB <---> string(2) "AB" $a = AB <---> string(2) "AB" $a = AC @@ -879,6 +927,8 @@ $a = AC <---> string(2) "AC" --------------------------------------- start incdec --- $a = F28 <---> string(3) "F28" $a = F28 <---> string(3) "F28" + +Warning: A non-numeric value encountered in %s on line %d $a = F28 <---> string(3) "F28" $a = F29 <---> string(3) "F29" $a = F30 @@ -887,6 +937,8 @@ $a = F30 <---> string(3) "F30" --------------------------------------- start incdecrev --- $a = F28 <---> string(3) "F28" $a = F29 <---> string(3) "F29" + +Warning: A non-numeric value encountered in %s on line %d $a = F30 <---> string(3) "F30" $a = F30 <---> string(3) "F30" $a = F31 @@ -895,6 +947,8 @@ $a = F31 <---> string(3) "F31" --------------------------------------- start incdec --- $a = F28 <---> string(3) "F28" $a = F28 <---> string(3) "F28" + +Warning: A non-numeric value encountered in %s on line %d $a = F28 <---> string(3) "F28" $a = F29 <---> string(3) "F29" $a = F30 @@ -903,6 +957,8 @@ $a = F30 <---> string(3) "F30" --------------------------------------- start incdecrev --- $a = F98 <---> string(3) "F98" $a = F99 <---> string(3) "F99" + +Warning: A non-numeric value encountered in %s on line %d $a = G00 <---> string(3) "G00" $a = G00 <---> string(3) "G00" $a = G01 @@ -911,6 +967,8 @@ $a = G01 <---> string(3) "G01" --------------------------------------- start incdec --- $a = F98 <---> string(3) "F98" $a = F98 <---> string(3) "F98" + +Warning: A non-numeric value encountered in %s on line %d $a = F98 <---> string(3) "F98" $a = F99 <---> string(3) "F99" $a = G00 @@ -919,6 +977,8 @@ $a = G00 <---> string(3) "G00" --------------------------------------- start incdecrev --- $a = FZ8 <---> string(3) "FZ8" $a = FZ9 <---> string(3) "FZ9" + +Warning: A non-numeric value encountered in %s on line %d $a = GA0 <---> string(3) "GA0" $a = GA0 <---> string(3) "GA0" $a = GA1 @@ -927,6 +987,8 @@ $a = GA1 <---> string(3) "GA1" --------------------------------------- start incdec --- $a = ZZ8 <---> string(3) "ZZ8" $a = ZZ8 <---> string(3) "ZZ8" + +Warning: A non-numeric value encountered in %s on line %d $a = ZZ8 <---> string(3) "ZZ8" $a = ZZ9 <---> string(3) "ZZ9" $a = AAA0 @@ -935,6 +997,8 @@ $a = AAA0 <---> string(4) "AAA0" --------------------------------------- start incdecrev --- $a = ZZ8 <---> string(3) "ZZ8" $a = ZZ9 <---> string(3) "ZZ9" + +Warning: A non-numeric value encountered in %s on line %d $a = AAA0 <---> string(4) "AAA0" $a = AAA0 <---> string(4) "AAA0" $a = AAA1 @@ -943,6 +1007,8 @@ $a = AAA1 <---> string(4) "AAA1" --------------------------------------- start incdecrev --- $a = 543J <---> string(4) "543J" $a = 543K <---> string(4) "543K" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 543L <---> string(4) "543L" $a = 543L <---> string(4) "543L" $a = 543M @@ -951,6 +1017,8 @@ $a = 543M <---> string(4) "543M" --------------------------------------- start incdec --- $a = 543J <---> string(4) "543J" $a = 543J <---> string(4) "543J" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 543J <---> string(4) "543J" $a = 543K <---> string(4) "543K" $a = 543L @@ -959,6 +1027,8 @@ $a = 543L <---> string(4) "543L" --------------------------------------- start incdecrev --- $a = 543J9 <---> string(5) "543J9" $a = 543K0 <---> string(5) "543K0" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 543K1 <---> string(5) "543K1" $a = 543K1 <---> string(5) "543K1" $a = 543K2 @@ -967,6 +1037,8 @@ $a = 543K2 <---> string(5) "543K2" --------------------------------------- start incdec --- $a = 543J9 <---> string(5) "543J9" $a = 543J9 <---> string(5) "543J9" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 543J9 <---> string(5) "543J9" $a = 543K0 <---> string(5) "543K0" $a = 543K1 @@ -975,6 +1047,8 @@ $a = 543K1 <---> string(5) "543K1" --------------------------------------- start incdec --- $a = & <---> string(1) "&" $a = & <---> string(1) "&" + +Warning: A non-numeric value encountered in %s on line %d $a = & <---> string(1) "&" $a = & <---> string(1) "&" $a = & @@ -983,6 +1057,8 @@ $a = & <---> string(1) "&" --------------------------------------- start incdecrev --- $a = & <---> string(1) "&" $a = & <---> string(1) "&" + +Warning: A non-numeric value encountered in %s on line %d $a = & <---> string(1) "&" $a = & <---> string(1) "&" $a = & @@ -991,6 +1067,8 @@ $a = & <---> string(1) "&" --------------------------------------- start incdec --- $a = 83& <---> string(3) "83&" $a = 83& <---> string(3) "83&" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 83& <---> string(3) "83&" $a = 83& <---> string(3) "83&" $a = 83& @@ -999,6 +1077,8 @@ $a = 83& <---> string(3) "83&" --------------------------------------- start incdecrev --- $a = 83& <---> string(3) "83&" $a = 83& <---> string(3) "83&" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 83& <---> string(3) "83&" $a = 83& <---> string(3) "83&" $a = 83& @@ -1007,6 +1087,8 @@ $a = 83& <---> string(3) "83&" --------------------------------------- start incdec --- $a = 83&8 <---> string(4) "83&8" $a = 83&8 <---> string(4) "83&8" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 83&8 <---> string(4) "83&8" $a = 83&9 <---> string(4) "83&9" $a = 83&0 @@ -1015,6 +1097,8 @@ $a = 83&0 <---> string(4) "83&0" --------------------------------------- start incdecrev --- $a = 83&8 <---> string(4) "83&8" $a = 83&9 <---> string(4) "83&9" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 83&0 <---> string(4) "83&0" $a = 83&0 <---> string(4) "83&0" $a = 83&1 @@ -1023,6 +1107,8 @@ $a = 83&1 <---> string(4) "83&1" --------------------------------------- start incdec --- $a = 83&Z8 <---> string(5) "83&Z8" $a = 83&Z8 <---> string(5) "83&Z8" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 83&Z8 <---> string(5) "83&Z8" $a = 83&Z9 <---> string(5) "83&Z9" $a = 83&A0 @@ -1031,6 +1117,8 @@ $a = 83&A0 <---> string(5) "83&A0" --------------------------------------- start incdecrev --- $a = 83&Z8 <---> string(5) "83&Z8" $a = 83&Z9 <---> string(5) "83&Z9" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 83&A0 <---> string(5) "83&A0" $a = 83&A0 <---> string(5) "83&A0" $a = 83&A1 @@ -1039,6 +1127,8 @@ $a = 83&A1 <---> string(5) "83&A1" --------------------------------------- start incdec --- $a = 83&z8 <---> string(5) "83&z8" $a = 83&z8 <---> string(5) "83&z8" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 83&z8 <---> string(5) "83&z8" $a = 83&z9 <---> string(5) "83&z9" $a = 83&a0 @@ -1047,6 +1137,8 @@ $a = 83&a0 <---> string(5) "83&a0" --------------------------------------- start incdecrev --- $a = 83&z8 <---> string(5) "83&z8" $a = 83&z9 <---> string(5) "83&z9" + +Notice: A non well formed numeric value encountered in %s on line %d $a = 83&a0 <---> string(5) "83&a0" $a = 83&a0 <---> string(5) "83&a0" $a = 83&a1 @@ -1055,6 +1147,8 @@ $a = 83&a1 <---> string(5) "83&a1" --------------------------------------- start incdec --- $a = &28 <---> string(3) "&28" $a = &28 <---> string(3) "&28" + +Warning: A non-numeric value encountered in %s on line %d $a = &28 <---> string(3) "&28" $a = &29 <---> string(3) "&29" $a = &30 @@ -1063,6 +1157,8 @@ $a = &30 <---> string(3) "&30" --------------------------------------- start incdecrev --- $a = &28 <---> string(3) "&28" $a = &29 <---> string(3) "&29" + +Warning: A non-numeric value encountered in %s on line %d $a = &30 <---> string(3) "&30" $a = &30 <---> string(3) "&30" $a = &31 @@ -1071,6 +1167,8 @@ $a = &31 <---> string(3) "&31" --------------------------------------- start incdec --- $a = &98 <---> string(3) "&98" $a = &98 <---> string(3) "&98" + +Warning: A non-numeric value encountered in %s on line %d $a = &98 <---> string(3) "&98" $a = &99 <---> string(3) "&99" $a = &00 @@ -1079,6 +1177,8 @@ $a = &00 <---> string(3) "&00" --------------------------------------- start incdecrev --- $a = &98 <---> string(3) "&98" $a = &99 <---> string(3) "&99" + +Warning: A non-numeric value encountered in %s on line %d $a = &00 <---> string(3) "&00" $a = &00 <---> string(3) "&00" $a = &01 diff --git a/tests/expressions/unary_operators/unary_arithmetic_operators.phpt b/tests/expressions/unary_operators/unary_arithmetic_operators.phpt index c795a625..88055f61 100644 --- a/tests/expressions/unary_operators/unary_arithmetic_operators.phpt +++ b/tests/expressions/unary_operators/unary_arithmetic_operators.phpt @@ -80,7 +80,7 @@ DoIt("-25.5e-10"); DoIt(""); DoIt("ABC"); //*/ ---EXPECT-- +--EXPECTF-- --- start DoIt ------------------------- original: int(0) @@ -229,10 +229,18 @@ DoIt("ABC"); original: string(0) "" +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d + --- end DoIt ------------------------- --- start DoIt ------------------------- original: string(3) "ABC" +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d + --- end DoIt ------------------------- diff --git a/tests/expressions/yield_operator/yield.phpt b/tests/expressions/yield_operator/yield.phpt index 55c383d3..0e472dae 100644 --- a/tests/expressions/yield_operator/yield.phpt +++ b/tests/expressions/yield_operator/yield.phpt @@ -54,7 +54,7 @@ echo "===========================\n"; //*/ ///* -// define a generator that returns sucessive lines from a file of text +// define a generator that returns successive lines from a file of text function getTextFileLines($filename) { diff --git a/tests/functions/basics.phpt b/tests/functions/basics.phpt index 299a9c59..2a3bc2c8 100644 --- a/tests/functions/basics.phpt +++ b/tests/functions/basics.phpt @@ -30,16 +30,14 @@ function f1() } var_dump(f1()); // call f1, default return value is NULL -f1; // valid, but vacuous, as it has no side effect and its value is not used -var_dump(f1); // string with value "f1" -$f = f1; // assign this string to a variable +$f = "f1"; // assign the name of the function to a variable $f(); // call f1 indirectly via $f -//"f1"(); // call f1 via the string "f1" -- Can't be a string literal!!! +"f1"(); // call f1 via the string "f1" // f1() = 123; // a function return is not an lvalue f1(); -f1(10); +f1(10,); f1(TRUE, "green"); f1(23.45, NULL, array(1,2,3)); @@ -53,11 +51,20 @@ function f2($p1, $p2) ", \$p2 = ".($p2 == NULL ? "NULL" : $p2)."\n"; } -// if fewer arguments are passed than there are paramaters declared, a warning is issued -// and the parameters corresponding to each each omitted argument are undefined +// if fewer arguments are passed than there are parameters declared, an ArgumentCountError is thrown -f2(); // pass 0 (< 2) -f2(10); // pass 1 (< 2) +try { + f2(); +} +catch (ArgumentCountError $e) { + echo $e->getMessage() . PHP_EOL; +} +try { + f2(10); +} +catch (ArgumentCountError $e) { + echo $e->getMessage() . PHP_EOL; +} f2(10, 20); // pass 2 (== 2) f2(10, 20, 30); // pass 3 (> 2) @@ -65,20 +72,14 @@ f2(10, 20, 30); // pass 3 (> 2) function square($v) { return $v * $v; } echo "5 squared = ".square(5)."\n"; -var_dump($funct = square); +$funct = "square"; var_dump($funct(-2.3)); echo strlen("abcedfg")."\n"; --EXPECTF-- f1: # arguments passed is 0 NULL - -Notice: Use of undefined constant f1 - assumed 'f1' in %s/functions/basics.php on line 30 - -Notice: Use of undefined constant f1 - assumed 'f1' in %s/functions/basics.php on line 31 -string(2) "f1" - -Notice: Use of undefined constant f1 - assumed 'f1' in %s/functions/basics.php on line 32 +f1: # arguments passed is 0 f1: # arguments passed is 0 f1: # arguments passed is 0 f1: # arguments passed is 1 @@ -92,23 +93,10 @@ f1: # arguments passed is 3 Notice: Array to string conversion in %s/functions/basics.php on line 25 arg[2] = >Array< - -Warning: %a - -Notice: Undefined variable: p1 in %s/functions/basics.php on line 49 - -Notice: Undefined variable: p2 in %s/functions/basics.php on line 50 -f2: $p1 = NULL, $p2 = NULL - -Warning: %s - -Notice: Undefined variable: p2 in %s/functions/basics.php on line 50 -f2: $p1 = 10, $p2 = NULL +Too few arguments to function f2(), 0 passed in %s on line %d and exactly 2 expected +Too few arguments to function f2(), 1 passed in %s on line %d and exactly 2 expected f2: $p1 = 10, $p2 = 20 f2: $p1 = 10, $p2 = 20 5 squared = 25 - -Notice: Use of undefined constant square - assumed 'square' in %s/functions/basics.php on line 65 -string(6) "square" float(5.29) 7 diff --git a/tests/functions/byrefs.phpt b/tests/functions/byrefs.phpt index ee562236..64be343d 100644 --- a/tests/functions/byrefs.phpt +++ b/tests/functions/byrefs.phpt @@ -66,8 +66,8 @@ class C unset($a); var_dump($a); -$a = new C; // make $a an alias to the allocated object -//$a = &new C; // use of & here is deprecated +$a = new C; // make $a an alias to the allocated object +//$a = &new C; // use of & here is deprecated var_dump($a); $a->m = "abc"; var_dump($a); diff --git a/tests/functions/default_arguments.phpt b/tests/functions/default_arguments.phpt index 36693f3d..8481d41f 100644 --- a/tests/functions/default_arguments.phpt +++ b/tests/functions/default_arguments.phpt @@ -36,7 +36,7 @@ f1(10, 20, 30, 40, 50, 60); f1(1, 2, 3, 4, 5, 6, 7); //*/ ///* -// 2 default followed by one non-default; unusual, but permitted +// 2 default followed by one non-default; function f2($p1 = 100, $p2 = 1.23, $p3) { @@ -52,13 +52,31 @@ function f2($p1 = 100, $p2 = 1.23, $p3) ", \$p3: ".($p3 == NULL ? "NULL" : $p3)."\n"; } -f2(); -f2(10); -f2(10, 20); +// if a non-default parameter is present and not all the arguments before it are provided, +// an ArgumentCountError is thrown + +try { + f2(); +} +catch (ArgumentCountError $e) { + echo $e->getMessage() . PHP_EOL; +} +try { + f2(10); +} +catch (ArgumentCountError $e) { + echo $e->getMessage() . PHP_EOL; +} +try { + f2(10, 20); +} +catch (ArgumentCountError $e) { + echo $e->getMessage() . PHP_EOL; +} f2(10, 20, 30); //*/ ///* -// 1 default followed by one non-default followed by 1 default; unusual, but permitted +// 1 default followed by one non-default followed by 1 default; function f3($p1 = 100, $p2, $p3 = "abc") { @@ -74,8 +92,21 @@ function f3($p1 = 100, $p2, $p3 = "abc") ", \$p3: ".($p3 == NULL ? "NULL" : $p3)."\n"; } -f3(); -f3(10); +// if a non-default parameter is present and not all the arguments before it are provided, +// an ArgumentCountError is thrown + +try { + f3(); +} +catch (ArgumentCountError $e) { + echo $e->getMessage() . PHP_EOL; +} +try { + f3(10); +} +catch (ArgumentCountError $e) { + echo $e->getMessage() . PHP_EOL; +} f3(10, 20); f3(10, 20, 30); //*/ @@ -96,7 +127,15 @@ function f4($p1, $p2 = 1.23, $p3 = "abc") ", \$p3: ".($p3 == NULL ? "NULL" : $p3)."\n"; } -f4(); +// if a non-default parameter is present and not all the arguments before it are provided, +// an ArgumentCountError is thrown + +try { + f4(); +} +catch (ArgumentCountError $e) { + echo $e->getMessage() . PHP_EOL; +} f4(10); f4(10, 20); f4(10, 20, 30); @@ -104,37 +143,37 @@ f4(10, 20, 30); --EXPECTF-- f1: # arguments passed is 0 -Notice: Array to string conversion in %s/functions/default_arguments.php on line 23 +Notice: Array to string conversion %s $p1: 10, $p2: 1.23, $p3: 1, $p4: , $p5: abc, $p6: Array f1: # arguments passed is 1 arg[0] = >20< -Notice: Array to string conversion in %s/functions/default_arguments.php on line 23 +Notice: Array to string conversion %s $p1: 20, $p2: 1.23, $p3: 1, $p4: , $p5: abc, $p6: Array f1: # arguments passed is 2 arg[0] = >10< arg[1] = >1< -Notice: Array to string conversion in %s/functions/default_arguments.php on line 23 +Notice: Array to string conversion %s $p1: 10, $p2: 1, $p3: 1, $p4: , $p5: abc, $p6: Array f1: # arguments passed is 3 arg[0] = >< arg[1] = >12< arg[2] = >1.234< -Notice: Array to string conversion in %s/functions/default_arguments.php on line 23 +Notice: Array to string conversion %s $p1: , $p2: 12, $p3: 1.234, $p4: , $p5: abc, $p6: Array f1: # arguments passed is 4 arg[0] = >< arg[1] = >1200< -Notice: Array to string conversion in %s/functions/default_arguments.php on line 21 +Notice: Array to string conversion %s arg[2] = >Array< arg[3] = >abc< -Notice: Array to string conversion in %s/functions/default_arguments.php on line 23 +Notice: Array to string conversion %s -Notice: Array to string conversion in %s/functions/default_arguments.php on line 23 +Notice: Array to string conversion %s $p1: , $p2: 1200, $p3: Array, $p4: abc, $p5: abc, $p6: Array f1: # arguments passed is 5 arg[0] = >9< @@ -143,7 +182,7 @@ f1: # arguments passed is 5 arg[3] = >6< arg[4] = >5< -Notice: Array to string conversion in %s/functions/default_arguments.php on line 23 +Notice: Array to string conversion %s $p1: 9, $p2: 8, $p3: 7, $p4: 6, $p5: 5, $p6: Array f1: # arguments passed is 6 arg[0] = >10< @@ -162,45 +201,16 @@ f1: # arguments passed is 7 arg[5] = >6< arg[6] = >7< $p1: 1, $p2: 2, $p3: 3, $p4: 4, $p5: 5, $p6: 6 - -Warning: %s -f2: # arguments passed is 0 - -Notice: Undefined variable: p3 in %s/functions/default_arguments.php on line 49 -$p1: 100, $p2: 1.23, $p3: NULL - -Warning: %s -f2: # arguments passed is 1 - arg[0] = >10< - -Notice: Undefined variable: p3 in %s/functions/default_arguments.php on line 49 -$p1: 10, $p2: 1.23, $p3: NULL - -Warning: %s -f2: # arguments passed is 2 - arg[0] = >10< - arg[1] = >20< - -Notice: Undefined variable: p3 in %s/functions/default_arguments.php on line 49 -$p1: 10, $p2: 20, $p3: NULL +Too few arguments to function f2(), 0 passed in %s and exactly 3 expected +Too few arguments to function f2(), 1 passed in %s and exactly 3 expected +Too few arguments to function f2(), 2 passed in %s and exactly 3 expected f2: # arguments passed is 3 arg[0] = >10< arg[1] = >20< arg[2] = >30< $p1: 10, $p2: 20, $p3: 30 - -Warning: %s -f3: # arguments passed is 0 - -Notice: Undefined variable: p2 in %s/functions/default_arguments.php on line 70 -$p1: 100, $p2: NULL, $p3: abc - -Warning: %s -f3: # arguments passed is 1 - arg[0] = >10< - -Notice: Undefined variable: p2 in %s/functions/default_arguments.php on line 70 -$p1: 10, $p2: NULL, $p3: abc +Too few arguments to function f3(), 0 passed in %s and at least 2 expected +Too few arguments to function f3(), 1 passed in %s and at least 2 expected f3: # arguments passed is 2 arg[0] = >10< arg[1] = >20< @@ -210,12 +220,7 @@ f3: # arguments passed is 3 arg[1] = >20< arg[2] = >30< $p1: 10, $p2: 20, $p3: 30 - -Warning: %s -f4: # arguments passed is 0 - -Notice: Undefined variable: p1 in %s/functions/default_arguments.php on line 91 -$p1: NULL, $p2: 1.23, $p3: abc +Too few arguments to function f4(), 0 passed in %s and at least 1 expected f4: # arguments passed is 1 arg[0] = >10< $p1: 10, $p2: 1.23, $p3: abc diff --git a/tests/functions/order_of_evaluation.phpt b/tests/functions/order_of_evaluation.phpt index f1ac1e7d..356b10fd 100644 --- a/tests/functions/order_of_evaluation.phpt +++ b/tests/functions/order_of_evaluation.phpt @@ -34,9 +34,9 @@ function h($p1, $p2, $p3, $p4, $p5) // Create a table of function designators -$funcTable = array(f, g, h); // list of 3 functions -var_dump($funcTable); // array of 3 strings -var_dump($funcTable[0]); // a string +$funcTable = array("f", "g", "h"); // list of 3 functions +var_dump($funcTable); // array of 3 strings +var_dump($funcTable[0]); // a string // Call all 3 functions indirectly through table @@ -52,12 +52,6 @@ $funcTable[$i++]($i, ++$i, $i, $i = 12, --$i); // function designator side effec // g: $p1 = 2, $p2 = 3, $p3 = 3, $p4 = 12, $p5 = 11 --EXPECTF-- f: $p1 = 0, $p2 = 1, $p3 = 1, $p4 = 12, $p5 = 11 - -Notice: Use of undefined constant f - assumed 'f' in %s/functions/order_of_evaluation.php on line 34 - -Notice: Use of undefined constant g - assumed 'g' in %s/functions/order_of_evaluation.php on line 34 - -Notice: Use of undefined constant h - assumed 'h' in %s/functions/order_of_evaluation.php on line 34 array(3) { [0]=> string(1) "f" diff --git a/tests/functions/passing_by_reference.phpt b/tests/functions/passing_by_reference.phpt index 3b232c29..bff4d3fa 100644 --- a/tests/functions/passing_by_reference.phpt +++ b/tests/functions/passing_by_reference.phpt @@ -53,9 +53,8 @@ var_dump($a); // so using it will raise a fatal error." var_dump($a); -f(); // So just what is f's $p aliased to? Presumably, nothing; $p is simply - // undefined on entry to f. Then when assigned 200, $p becomes a local - // variable that dies when it goes out of scope when the function terminates. +// f(); // PHP7.1, Fatal error: Uncaught ArgumentCountError: Too few arguments + // to function f(), 0 passed //*/ ///* @@ -71,7 +70,7 @@ function g(&$p = "red") // pass a variable by reference; f changes its value -g(); // like the f() call above +g(); // Unlike the f() call above, here the default parameter is used $a = 10; var_dump($a); @@ -103,13 +102,6 @@ f In: $p: 10 f Out: $p: 200 int(200) int(200) - -Warning: %s -$p is not set - -Notice: Undefined variable: p in %s/functions/passing_by_reference.php on line 34 -f In: $p: -f Out: $p: 200 $p is set g In: $p: red g Out: $p: 200 diff --git a/tests/functions/using_byrefs_to_undefined_variables.phpt b/tests/functions/using_byrefs_to_undefined_variables.phpt index 6e18e245..ed8ceb80 100644 --- a/tests/functions/using_byrefs_to_undefined_variables.phpt +++ b/tests/functions/using_byrefs_to_undefined_variables.phpt @@ -31,10 +31,11 @@ function g(&$q) $q = -10; } -f(); +// f(); // PHP7.1, Fatal error: Uncaught ArgumentCountError: Too few arguments + // to function f(), 0 passed var_dump($x); -f($x); // non-existant variable going in +f($x); // non-existent variable going in var_dump($x); $a = array(10, 20, 30); @@ -43,10 +44,10 @@ var_dump($a); f($a[0]); var_dump($a); -f($a[5]); // non-existant element going in +f($a[5]); // non-existent element going in var_dump($a); -f($a["red"]); // non-existant element going in +f($a["red"]); // non-existent element going in var_dump($a); //*/ ///* @@ -63,10 +64,11 @@ function h(&$p) var_dump($b); } -h(); +// h(); // PHP7.1, Fatal error: Uncaught ArgumentCountError: Too few arguments + // to function f(), 0 passed var_dump($x); -h($x); // non-existant variable going in +h($x); // non-existent variable going in var_dump($x); $a = array(10, 20, 30); @@ -75,10 +77,10 @@ var_dump($a); h($a[0]); var_dump($a); -h($a[5]); // non-existant element going in +h($a[5]); // non-existent element going in var_dump($a); -h($a["red"]); // non-existant element going in +h($a["red"]); // non-existent element going in var_dump($a); //*/ ///* @@ -100,11 +102,11 @@ $d = &k($a[0]); var_dump($d); var_dump($a); -$d = &k($a[5]); // non-existant element going in +$d = &k($a[5]); // non-existent element going in var_dump($d); var_dump($a); -$d = &k($a["red"]); // non-existant element going in +$d = &k($a["red"]); // non-existent element going in var_dump($d); var_dump($a); //*/ @@ -130,13 +132,7 @@ $d = &m2(); var_dump($d); //*/ --EXPECTF-- -Warning: %s -$p is not set -$q is not set -$p is set -int(-10) - -Notice: Undefined variable: x in %s/functions/using_byrefs_to_undefined_variables.php on line 33 +Notice: Undefined variable: x %s NULL $p is not set $q is not set @@ -193,12 +189,6 @@ array(5) { ["red"]=> int(-10) } - -Warning: %s -$p is not set -$p is not set -NULL -NULL int(-10) $p is set $p is set diff --git a/tests/functions/void_allowed.phpt b/tests/functions/void_allowed.phpt new file mode 100644 index 00000000..8f07c739 --- /dev/null +++ b/tests/functions/void_allowed.phpt @@ -0,0 +1,20 @@ +--TEST-- +void return type: acceptable cases +--FILE-- +$offset<\n"; - + return isset($this->elements[$offset]); } public function offsetSet($offset, $value) { echo "Inside " . __METHOD__ . " with offset >$offset<\n"; - + if (is_null($offset)) { $this->elements[] = $value; @@ -58,7 +58,7 @@ class MyVector implements ArrayAccess public function offsetUnset($offset) { echo "Inside " . __METHOD__ . " with offset >$offset<\n"; - + unset($this->elements[$offset]); } } diff --git a/tests/lexical_structure/tokens/point.phpt b/tests/lexical_structure/tokens/point.phpt index c51216f5..b4b4fea8 100644 --- a/tests/lexical_structure/tokens/point.phpt +++ b/tests/lexical_structure/tokens/point.phpt @@ -26,7 +26,7 @@ class Point { $this->x = $x; $this->y = $y; - } + } public function translate($x, $y) { @@ -37,6 +37,6 @@ class Point public function __toString() { return '(' . $this->x . ',' . $this->y . ')'; - } + } } --EXPECT-- diff --git a/tests/lexical_structure/tokens/point2.phpt b/tests/lexical_structure/tokens/point2.phpt index 02e134a3..fbcf0d4a 100644 --- a/tests/lexical_structure/tokens/point2.phpt +++ b/tests/lexical_structure/tokens/point2.phpt @@ -26,7 +26,7 @@ class Point2 public function __construct($x = 0, $y = 0) { // echo "Inside " . __METHOD__ . "\n"; - + $this->x = $x; $this->y = $y; ++self::$pointCount; @@ -49,6 +49,6 @@ class Point2 public function __toString() { return '(' . $this->x . ',' . $this->y . ')'; - } + } } --EXPECT-- diff --git a/tests/lexical_structure/tokens/string_literals.phpt b/tests/lexical_structure/tokens/string_literals.phpt index 99d8bbd8..5d5ea075 100644 --- a/tests/lexical_structure/tokens/string_literals.phpt +++ b/tests/lexical_structure/tokens/string_literals.phpt @@ -143,7 +143,7 @@ echo "\$myC->p1 = >$myC->p1<\n"; ///* // use brace-delimited expressions -// braces can be use around varible names to stop a longer name being formed +// braces can be use around variable names to stop a longer name being formed echo ">{$z}X|$z X|{$zz}_|$zz _|{$zzz}3|$zzz 3|{$zzzz}+|$zzzz +<\n"; //*/ diff --git a/tests/namespaces/Circle.inc b/tests/namespaces/Circle.inc index c9880941..a37cdf35 100644 --- a/tests/namespaces/Circle.inc +++ b/tests/namespaces/Circle.inc @@ -11,21 +11,21 @@ namespace Graphics\D2 error_reporting(-1); include_once 'Point.inc'; -class Circle +class Circle { private $center; private $radius; - public function __construct($x = 0, $y = 0, $radius = 0) + public function __construct($x = 0, $y = 0, $radius = 0) { $this->center = new Point($x, $y); $this->radius = $radius; } - public function __toString() + public function __toString() { return '[' . $this->center . ':' . $this->radius . ']'; - } + } } } diff --git a/tests/namespaces/Point.inc b/tests/namespaces/Point.inc index 057ae8f6..c2bf5f17 100644 --- a/tests/namespaces/Point.inc +++ b/tests/namespaces/Point.inc @@ -10,7 +10,7 @@ namespace Graphics\D2 { error_reporting(-1); -class Point +class Point { private $x; private $y; @@ -20,28 +20,28 @@ class Point public function getY() { return $this->y; } public function setY($y) { $this->y = $y; } - public function __construct($x = 0, $y = 0) + public function __construct($x = 0, $y = 0) { $this->x = $x; $this->y = $y; } - public function move($x, $y) + public function move($x, $y) { $this->x = $x; $this->y = $y; - } + } - public function translate($x, $y) + public function translate($x, $y) { $this->x += $x; $this->y += $y; } - public function __toString() + public function __toString() { return '(' . $this->x . ',' . $this->y . ')'; - } + } } } diff --git a/tests/serialization/Point.inc b/tests/serialization/Point.inc index bdabd4f9..816e6106 100644 --- a/tests/serialization/Point.inc +++ b/tests/serialization/Point.inc @@ -8,31 +8,31 @@ error_reporting(-1); -class Point implements Serializable +class Point implements Serializable { private static $pointCount = 0; public $x; public $y; - public static function getPointCount() + public static function getPointCount() { return self::$pointCount; } - public function __construct($x = 0, $y = 0) + public function __construct($x = 0, $y = 0) { $this->x = $x; $this->y = $y; ++self::$pointCount; } - public function __destruct() + public function __destruct() { --self::$pointCount; } ///* - public function __clone() + public function __clone() { ++self::$pointCount; @@ -40,7 +40,7 @@ class Point implements Serializable } //*/ - public function __toString() + public function __toString() { return '(' . $this->x . ',' . $this->y . ')'; } diff --git a/tests/statements/jump/continue.phpt b/tests/statements/jump/continue.phpt index 3efcd997..040b06e7 100644 --- a/tests/statements/jump/continue.phpt +++ b/tests/statements/jump/continue.phpt @@ -85,7 +85,8 @@ for ($i = 10; $i <= 40; $i +=10) echo "\nJust beyond the switch"; } echo "\n----------\n"; ---EXPECT-- +--EXPECTF-- +Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in %s on line %d 1 is odd 3 is odd 5 is odd diff --git a/tests/traits/traits.phpt b/tests/traits/traits.phpt index 9526b731..6887badb 100644 --- a/tests/traits/traits.phpt +++ b/tests/traits/traits.phpt @@ -227,7 +227,7 @@ trait T7 echo "Inside " . __TRAIT__ . "\n"; echo "Inside " . __CLASS__ . "\n"; echo "Inside " . __METHOD__ . "\n"; - var_dump($this); + // var_dump($this); // Fatal error: Uncaught Error: Using $this when not in object context } public static function g() @@ -238,9 +238,8 @@ trait T7 } } -T7::f(); // calls f like a static function with class name being the trait name +// T7::f(); // Static call to non-static method is not allowed -echo "-------\n"; T7::g(); /* @@ -336,13 +335,6 @@ $v = 1 Inside T6::f $v = 2 ===================== Using a Trait without a Class ========================= -%AInside T7 -Inside T7 -Inside T7::f - -Notice: Undefined variable: this in %s/traits/traits.php on line 227 -NULL -------- Inside T7 Inside T7 Inside T7::g diff --git a/tests/types/string/numeric_like_strings.phpt b/tests/types/string/numeric_like_strings.phpt index f1621b42..51aa0327 100644 --- a/tests/types/string/numeric_like_strings.phpt +++ b/tests/types/string/numeric_like_strings.phpt @@ -94,7 +94,7 @@ var_dump($s1--); var_dump($s2--); var_dump($s3--); var_dump($s4--); ---EXPECT-- +--EXPECTF-- ============== var_dump(numeric_like_string) =================== string(8) "12345xxx" @@ -118,13 +118,29 @@ float(12345.6) ============== +/- numeric_like_string =================== + +Notice: A non well formed numeric value encountered in %s on line %d int(12345) + +Notice: A non well formed numeric value encountered in %s on line %d int(12345) + +Notice: A non well formed numeric value encountered in %s on line %d float(12345.6) + +Notice: A non well formed numeric value encountered in %s on line %d float(12345.6) + +Notice: A non well formed numeric value encountered in %s on line %d int(-12345) + +Notice: A non well formed numeric value encountered in %s on line %d int(-12345) + +Notice: A non well formed numeric value encountered in %s on line %d float(-12345.6) + +Notice: A non well formed numeric value encountered in %s on line %d float(-12345.6) ============== relational/equality ops with numeric_like_string =================== diff --git a/tests/variables/unsetting_variables.phpt b/tests/variables/unsetting_variables.phpt index b776bc32..dddd39f1 100644 --- a/tests/variables/unsetting_variables.phpt +++ b/tests/variables/unsetting_variables.phpt @@ -69,7 +69,7 @@ function f($p) echo "f:2 \$sVar1 = " . $sVar1 . "\n"; ++$sVar1; // unset($sVar1); // removes this alias; doesn't unset the inner static itself - + global $gVar1; echo "f:2 \$gVar1 = " . $gVar1 . "\n"; $gVar1 = 25; diff --git a/tests/variables/variable_names.phpt b/tests/variables/variable_names.phpt index e50b92bf..d236317d 100644 --- a/tests/variables/variable_names.phpt +++ b/tests/variables/variable_names.phpt @@ -25,7 +25,7 @@ ${TRUE} = 104; ${FALSE} = 105; ${NULL} = 106; -${total} = 1000; // allowed after warning: Use of undefined constant total - assumed 'total' +//${total} = 1000; // disallowed; undefined constant total //${t o tal} = 1000; // disallowed; ill-formed expression //${+} = 1000; // disallowed; ill-formed expression ${10 + 4} = 1000; // allowed @@ -53,9 +53,7 @@ print_globals(); int(99) int(100) int(101) - -Notice: Use of undefined constant total - assumed 'total' in %s/variables/variable_names.php on line 25 -array(12) { +array(11) { ["argc"]=> int(1) ["v"]=> @@ -70,8 +68,6 @@ array(12) { int(104) [""]=> int(106) - ["total"]=> - int(1000) [14]=> int(1000) ["abxy"]=> diff --git a/tests/variables/variable_variables.phpt b/tests/variables/variable_variables.phpt index fba58fcf..b287377a 100644 --- a/tests/variables/variable_variables.phpt +++ b/tests/variables/variable_variables.phpt @@ -130,20 +130,20 @@ echo "================== complex cases, [] ====================\n"; $v = array(10, 20); $a = 'v'; -$$a[0] = 5; +$$a[0] = 5; var_dump($v); unset($v, $a); $v = array(10, 20); $a = 'v'; -${$a[0]} = 5; +${$a[0]} = 5; var_dump($v); unset($v, $a); $v = array(10, 20); $a = 'v'; -${$a}[0] = 5; +${$a}[0] = 5; var_dump($v); unset($v, $a); //*/ diff --git a/tools/README.md b/tools/README.md index c8a4f703..8a08ee89 100644 --- a/tools/README.md +++ b/tools/README.md @@ -5,4 +5,3 @@ Here are some possible examples: 1. A script to convert from Markdown to Word or PDF might live in here. 2. A tool to help move cross reference links from Word to Markdown. 3. A script to add numbered headings to Markdown. - diff --git a/tools/check_refs.php b/tools/check_refs.php new file mode 100644 index 00000000..aede04a8 --- /dev/null +++ b/tools/check_refs.php @@ -0,0 +1,51 @@ + $path) { + $contents = file_get_contents($path); + foreach (heading_info($contents) as $info) { + $fullAnchor = $fileName . '#' . $info['anchor']; + $anchors[$fullAnchor] = true; + } + + // Collect manual anchors as well + if (preg_match_all('//', $contents, $matches)) { + foreach ($matches[1] as $anchor) { + $fullAnchor = $fileName . '#' . $anchor; + $anchors[$fullAnchor] = true; + } + } +} + +// Find unknown anchor references +$foundUnknown = false; +foreach (spec_files() as $fileName => $path) { + $contents = file_get_contents($path); + + if (!preg_match_all('/\]\(([^)]+)\)/', $contents, $matches)) { + continue; + } + + foreach ($matches[1] as $anchor) { + if (false === strpos($anchor, '#')) { + continue; + } + if (!preg_match('/^(#|\d{2})/', $anchor)) { + continue; + } + + if ('#' === $anchor[0]) { + $anchor = $fileName . $anchor; + } + + if (!isset($anchors[$anchor])) { + $foundUnknown = true; + echo "Unknown anchor $anchor in $fileName\n"; + } + } +} + +exit($foundUnknown ? 1 : 0); diff --git a/tools/grammar.php b/tools/grammar.php new file mode 100644 index 00000000..a7494503 --- /dev/null +++ b/tools/grammar.php @@ -0,0 +1,98 @@ + $path) { + $code = file_get_contents($path); + $defs = Grammar\get_all_defs($code); + foreach ($defs as $def) { + if (isset($names[$def->name])) { + throw new Exception("Duplicate definition for $def->name"); + } + $names[$def->name] = $fileName; + } +} + +// Render grammars +foreach (spec_files() as $fileName => $path) { + $code = $origCode = file_get_contents($path); + $code = preg_replace_callback( + '/()\s+
.*?<\/pre>/s',
+        function($matches) use($names, $fileName) {
+            $defs = Grammar\parse_grammar($matches[2]);
+            $rendered = Grammar\render_grammar($defs, $names, $fileName);
+            return $matches[1] . "\n\n" . $rendered;
+        },
+        $code
+    );
+    if ($code !== $origCode) {
+        file_put_contents($path, $code);
+    }
+}
+
+/*
+ * Generate summary grammar chapter
+ */
+
+// Pretend that all definitions are inside 19-grammar.md now
+$names = array_fill_keys(array_keys($names), '19-grammar.md');
+
+$dir = __DIR__ . '/../spec/';
+$grammarFile = $dir . '19-grammar.md';
+
+$output = <<<'END'
+# Grammar
+
+## General
+
+The grammar notation is described in [Grammars section](09-lexical-structure.md#grammars).
+
+## Lexical Grammar
+
+
+END;
+
+$lexical = file_get_contents($dir . '09-lexical-structure.md');
+$lexical = strstr($lexical, '## Lexical analysis');
+$output .= extract_grammar($lexical, $names);
+
+$output .= "\n\n## Syntactic Grammar";
+
+$skipFiles = ['05-types.md', '09-lexical-structure.md', '19-grammar.md'];
+foreach (spec_files($skipFiles) as $fileName => $path) {
+    $code = file_get_contents($path);
+    $grammar = extract_grammar($code, $names);
+    if (null === $grammar) {
+        continue;
+    }
+
+    $heading = extract_heading($code);
+    $output .= "\n\n### $heading\n\n" . $grammar;
+}
+
+$output .= "\n";
+
+file_put_contents($grammarFile, $output);
+
+function extract_heading($code) {
+    if (!preg_match('/#\s*(.*)/', $code, $matches)) {
+        throw new Exception('No heading found');
+    }
+
+    return $matches[1];
+}
+
+function extract_grammar($code, $names) {
+    $defs = Grammar\get_all_defs($code);
+    if (empty($defs)) {
+        return null;
+    }
+    return Grammar\render_grammar($defs, $names, '19-grammar.md');
+}
diff --git a/tools/grammar_util.php b/tools/grammar_util.php
new file mode 100644
index 00000000..c25d1657
--- /dev/null
+++ b/tools/grammar_util.php
@@ -0,0 +1,140 @@
+/s', $code, $matches)) {
+        return [];
+    }
+    $defs = [];
+    foreach ($matches[1] as $grammar) {
+        $defs = array_merge($defs, parse_grammar($grammar));
+    }
+    return $defs;
+}
+
+function parse_grammar($grammar) {
+    $defTexts = explode("\n\n", trim($grammar));
+    $defs = [];
+    foreach ($defTexts as $defText) {
+        if (!preg_match('/^([a-zA-Z0-9-]+)(::?)(\s+one\s+of)?\n(.*?)$/s', $defText, $matches)) {
+            throw new \Exception('Invalid definition');
+        }
+
+        $rules = array_map('Grammar\parse_rule', explode("\n", $matches[4]));
+        $defs[] = new Definition(
+            $matches[1], $matches[2] === '::', $matches[3] !== '', $rules
+        );
+    }
+    return $defs;
+}
+
+function parse_rule($rule) {
+    $regex = <<<'REGEX'
+/(?:
+    '[^']*(?:''[^']*)*'
+  | "[^"]*(?:""[^"]*)*"
+)(*SKIP)(*F)|\s+/x
+REGEX;
+    $parts = array_map('Grammar\parse_rule_part', preg_split($regex, trim($rule)));
+    return new Rule($parts);
+}
+
+function parse_rule_part($part) {
+    if (substr($part, -1) === '?') {
+        return new Opt(parse_rule_part(substr($part, 0, -1)));
+    }
+    if ($part[0] === "'") {
+        $contents = str_replace("''", "'", substr($part, 1, -1));
+        return new Plain($contents);
+    }
+    if ($part[0] === '"') {
+        $contents = str_replace('""', '"', substr($part, 1, -1));
+        return new Plain($contents);
+    }
+    return new Reference($part);
+}
+
+function render_grammar($defs, $names, $currentFile) {
+    $ctx = new RenderContext;
+    $ctx->names = $names;
+    $ctx->currentFile = $currentFile;
+
+    $result = [];
+    foreach ($defs as $def) {
+        $result[] = $def->render($ctx);
+    }
+    return "
\n" . implode("\n\n", $result) . "\n
"; +} + +class RenderContext { + public $names; + public $currentFile; +} + +class Definition { + public $name, $isLexical, $isOneOf, $rules; + public function __construct($name, $isLexical, $isOneOf, $rules) { + $this->name = $name; + $this->isLexical = $isLexical; + $this->isOneOf = $isOneOf; + $this->rules = $rules; + } + public function render($ctx) { + $sep = $this->isLexical ? '::' : ':'; + $oneOf = $this->isOneOf ? ' one of' : ''; + $result = "name\">$this->name$sep$oneOf"; + foreach ($this->rules as $rule) { + $result .= "\n " . $rule->render($ctx); + } + return $result; + } +} +class Rule { + public $parts; + public function __construct($parts) { + $this->parts = $parts; + } + public function render($ctx) { + $parts = []; + foreach ($this->parts as $part) { + $parts[] = $part->render($ctx); + } + return implode(' ', $parts); + } +} +class Reference { + public $name; + public function __construct($name) { + $this->name = $name; + } + public function render($ctx) { + if (!isset($ctx->names[$this->name])) { + throw new \Exception("Reference to unknown name $this->name"); + } + $fileName = $ctx->names[$this->name]; + $anchor = "#grammar-$this->name"; + if ($fileName != $ctx->currentFile) { + $anchor = $fileName . $anchor; + } + return "
$this->name"; + } +} +class Plain { + public $string; + public function __construct($string) { + $this->string = $string; + } + public function render($ctx) { + return htmlspecialchars($this->string); + } +} +class Opt { + public $inner; + public function __construct($inner) { + $this->inner = $inner; + } + public function render($ctx) { + return $this->inner->render($ctx) . 'opt'; + } +} diff --git a/tools/pre-commit b/tools/pre-commit new file mode 100755 index 00000000..3fb22d32 --- /dev/null +++ b/tools/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +php tools/grammar.php && \ +php tools/toc.php && \ +php tools/check_refs.php diff --git a/tools/split.php b/tools/split.php index eb765dea..6cf19203 100644 --- a/tools/split.php +++ b/tools/split.php @@ -15,7 +15,7 @@ echo $filename, "\n"; $counter++; $split_data[$filename] = ''; - } + } // sub-header $refname = trim(ltrim($line, '#')); $refname = str_replace(" ", "-", $refname); @@ -30,7 +30,7 @@ $filerefs[$filename][$refname] = $orig_refname; } else { @$filecounts[$filename][$orig_refname]++; - $filerefs[$filename][$refname] = $orig_refname . "-" . $filecounts[$filename][$orig_refname]; + $filerefs[$filename][$refname] = $orig_refname . "-" . $filecounts[$filename][$orig_refname]; } } $references[$refname] = $filename; @@ -39,8 +39,8 @@ } foreach($split_data as $filename => $contents) { - $contents = preg_replace_callback('@\[(.*?)\]\(#(.*?)\)@', function($data) use($references, $filename, $filerefs) { - if(empty($references[$data[2]])) { + $contents = preg_replace_callback('@\[(.*?)\]\(#(.*?)\)@', function($data) use($references, $filename, $filerefs) { + if(empty($references[$data[2]])) { return $data[0]; } if($references[$data[2]]) { @@ -61,4 +61,4 @@ return $res; }, $contents); file_put_contents($filename, $contents); -} \ No newline at end of file +} diff --git a/tools/toc.php b/tools/toc.php index 17b51ce8..774c7fac 100644 --- a/tools/toc.php +++ b/tools/toc.php @@ -1,12 +1,14 @@ -#Specification for PHP +# Specification for PHP Facebook has dedicated all copyright to this specification to the public domain worldwide under the CC0 Public Domain Dedication located at . This specification @@ -17,42 +19,15 @@ **Table of Contents** EOS; -$files = scandir($dir); $output = ""; - -foreach ($files as $file) { - if(pathinfo($file, PATHINFO_EXTENSION) != 'md') { - continue; - } - if ($file == '00-specification-for-php.md' || $file == 'php-spec-draft.md') { - continue; - } - - $anchors = []; - - $lines = file($dir . $file); - foreach ($lines as $line) { - if (!preg_match('/^(#+)\s*(.+)/', $line, $matches)) { - continue; - } - - list(, $hashes, $title) = $matches; - $level = strlen($hashes) - 1; - $indent = str_repeat(' ', $level); - - $anchor = strtr(strtolower($title), ' ', '-'); - $anchor = preg_replace('/[^\w-]/', '', $anchor); - - if (isset($anchors[$anchor])) { - $anchors[$anchor]++; - $anchor .= '-' . $anchors[$anchor]; - } else { - $anchors[$anchor] = 0; - } - - $output .= "$indent- [$title]($file#$anchor)\n"; +foreach (spec_files() as $fileName => $path) { + $contents = file_get_contents($path); + foreach (heading_info($contents) as $info) { + $title = $info['title']; + $anchor = $info['anchor']; + $indent = str_repeat(' ', $info['level']); + $output .= "$indent- [$title]($fileName#$anchor)\n"; } } file_put_contents($tocFile, "$prefix\n$output"); - diff --git a/tools/util.php b/tools/util.php new file mode 100644 index 00000000..8cd521e0 --- /dev/null +++ b/tools/util.php @@ -0,0 +1,49 @@ + $path. */ +function spec_files($skipFiles = []) { + $dir = __DIR__ . '/../spec/'; + $files = scandir($dir); + + foreach ($files as $file) { + if (pathinfo($file, PATHINFO_EXTENSION) != 'md') { + continue; + } + if ($file == '00-specification-for-php.md' + || in_array($file, $skipFiles)) { + continue; + } + + yield $file => $dir . $file; + } +} + +/* Iterator of heading information. + * Assoc array with title, anchor, level. */ +function heading_info($code) { + $anchors = []; + $lines = explode("\n", $code); + foreach ($lines as $line) { + if (!preg_match('/^(#+)\s*(.+)/', $line, $matches)) { + continue; + } + + list(, $hashes, $title) = $matches; + + $anchor = strtr(strtolower($title), ' ', '-'); + $anchor = preg_replace('/[^\w-]/', '', $anchor); + + if (isset($anchors[$anchor])) { + $anchors[$anchor]++; + $anchor .= '-' . $anchors[$anchor]; + } else { + $anchors[$anchor] = 0; + } + + yield [ + 'title' => $title, + 'anchor' => $anchor, + 'level' => strlen($hashes) - 1 + ]; + } +} diff --git a/tools/xreference/section_map.csv b/tools/xreference/section_map.csv index e80f4775..dc5a59e7 100644 --- a/tools/xreference/section_map.csv +++ b/tools/xreference/section_map.csv @@ -290,4 +290,4 @@ A.3.6,classes-1 A.3.7,interfaces-1 A.3.8,traits-1 A.3.9,namespaces-1 -Bibliography,bibliography \ No newline at end of file +Bibliography,bibliography