blog

  • Home
  • blog
  • Re-Implementing the Range Operator in PHP

Re-Implementing the Range Operator in PHP

In the prequel to this article
(hint: make sure you’ve read it first), I showed one way to implement a range
operator in PHP. Initial implementations, however, are rarely the best, and so
it is the intention of this article to look at how the previous implementation
can be improved.

Thanks once again to Nikita Popov for proofreading
this article!

Previous Implementation Drawbacks

The initial implementation put all of the logic for the range operator into the
Zend VM, which forced computation to take place purely at runtime when the
ZEND_RANGE opcode was executed. This not only meant that computation could
not be shifted to compile time for operands that were literal, but also meant
that some features would simply not work.

In this implementation, we will shift the range operator logic out of the Zend
VM to enable for computation to be done at either compile time (for literal
operands) or runtime (for dynamic operands). This will not only provide a small
win for Opcache users, but will more importantly allow for constant expression
features to be used with the range operator.

For example:

// as constant definitions
const AN_ARRAY = 1 |> 100;

// as initial property definitions
class A
{
	private $a = 1 |> 2;
}

// as default values for optional parameters:
function a($a = 1 |> 2)
{
	//
}

So without further ado, let’s reimplement the range operator.

Updating the Lexer

The lexer implementation remains exactly the same. The token is firstly
registered in Zend/zend_language_scanner.l
(line ~1200):

<ST_IN_SCRIPTING>"|>" {
    RETURN_TOKEN(T_RANGE);
}

And then declared in Zend/zend_language_parser.y
(line ~220):

%token T_RANGE 		     "|> (T_RANGE)"

Continue reading %Re-Implementing the Range Operator in PHP%

LEAVE A REPLY