Symisc PH7 Engine
An Embeddable PHP5 Engine

Distinctive Features of the PH7 Engine.

The following page enumerates distinctive features and powerful extensions introduced by the PH7 Engine to the PHP programming language, these are:

Features in details

We describe now, some of the important PH7 features in details.


Function Overloading

Function overloading or method overloading is a feature found in various programming languages such as C++ or Java, that allows creating several function and/or methods with the same name which differ from each other in the type of the input and the output of the function. It is simply defined as the ability of one function to perform different tasks. (src: Wikipedia)

Function overloading means two or more functions can have the same name but either the number of arguments or the data type of arguments has to be different.

The PH7 engine introduces this powerful mechanism as an extension to the PHP programming language. That is, you define two ore more standard PHP functions with the same name (PH7 is case-sensitive unlike the standard PHP engine) but with different arguments number and/or types and finally you perform a simple function call and let PH7 peek the appropriate function for this call context.

Example: (Overloading without the full type hinting extension)


function foo($a) {
    //foo() accepts only a single argument
   return $a.PHP_EOL;
}
function foo($a, $b) {
   // foo() accepts two arguments and perform their addition.

     return $a + $b;

}

echo foo(5); // Prints "5"

echo foo(10, 2); // Prints "12"


Here, we define two functions with the same name but with different purposes. That is, the first foo() accepts only a single argument and return its value while the second foo() accepts two arguments, perform their addition and return the result. So if we call foo with a single argument the first foo() will be invoked while if we call foo with two or more arguments,the second foo() will be invoked.

Example 2: (Overloading With the full type hinting extensions)


function foo(string $a)

{

  echo "a is a string\n";

  var_dump($a);

}

function foo(int $a)

{

  echo "a is integer\n";

  var_dump($a);

}

function foo(array $a)

{

  echo "a is an array\n";

  var_dump($a);

}

/* Test the mechanism */

foo('This is a great feature'); /* a is a string (first foo) */

foo(52); /* a is integer (second foo) */

foo(array(14,__TIME__,__DATE__)); /* a is an array (third foo) */


Here, we define three functions with the same name and the same number of arguments but with different signatures. That is, each function accepts a single argument but with a different type than the others. This was possible by the powerful full type hinting extension introduced by the PH7 engine which permit functions to have their own signatures. So if we call foo with a string argument as follows foo('This is a great feature'); The first foo() that expect a string argument will be invoked while if we call foo with a array argument as follows foo(array(14,__TIME__,__DATE__)); the last foo() that expect a array will be invoked.

Example 3: (Wikipedia example ported to PH7 PHP)


// volume of a cube
function
volume(int $s)
{
  return $s*$s*$s;
}
// volume of a cylinder
function volume(float $r,int $h)
{
  return 3.14*$r*$r*$h;
}
// volume of a cuboid
function volume(float $l,int $b,int $h)
{
  return $l*$b*$h;
}
/* Test the overloading mechanism */
echo volume(10).PHP_EOL; /* You should see 1000 */
echo volume(2.5,8).PHP_EOL; /* You should see 157 */
echo volume(100,75,15); /* You should see 112500 */


Again, three functions with the same name but each one expects a different number and different types of arguments, PH7 is smart enough to peek the appropriate function for the call context.

Example 4: (With Class methods)


class a {

   public static function foo($a) {

     return $a.PHP_EOL;

  }

  static function foo($a, $b) {

     return $a + $b;

  }

}

$c = new a();

echo $c->foo(rand()&1023); //print a random number

echo $c->foo(25,50); //print 75


Function overloading is not restricted to standard PHP function, you can also make your class methods candidate for overloading exactly like standard function would do. As a bonus side, overloading apply also to class constructors. That is, define a class with two or more constructors but with different signature and let PH7 peek the appropriate constructor for you.

Example:


class a {

  function __construct($a) {

    echo $a.PHP_EOL;

 }

  function __construct($a, $b) {

    echo $a + $b;

  }

}

$c = new a(150); /* You should see: 150 */

$c = new a(60,200); /* You should see: 260 */


We recommend to the PH7 enthusiastic users to experiment with this powerful mechanism and to report any unexpected result or inconsistency and/or their feedback to the PH7 public forums or using the PH7 mailing list.

Full Type Hinting

PHP 5 introduces type hinting. Functions are now able to force parameters to be only objects (by specifying the name of the class in the function prototype), interfaces or arrays (since PHP 5.1).

PH7 goes further and extends the type hinting mechanism to be used with scalar types such as string, int, float or even the Boolean type.

With type hinting, arguments are automatically and silently converted to the desired type. By doing so there is no need to add the ugly test statements at the beginning of function prolog to check for the expected argument types using the is_string(), is_float(), etc. functions. All of this is done automatically by the engine freeing the programmer from a boring task.

Example: Type hinting with scalar values (string).


function test(string $a)
{
 var_dump($a);
}
/* Call with a string argument */
test("Hello world"); //Output string(11 'Hello world');
/* Call with an int argument */
test(0xFFFFFFFF); //Output string(10 '4294967295');
/* Call with a float argument */
test(25.e-1); //Output string(3 '2.5');


Here if we call the test() function with an int argument, an automatic cast is performed and the given integer value (hexadecimal 0xFFFFFFFF) is converted to a decimal number (4294967295) first, then a string cast is performed. The same operation is done if we call test() with a float argument. The float number is converted to a string and the result is outputted (2,5).

Example 2: Type hinting with scalar values (integer)


function test(int $a)
{
 var_dump($a);
}
/* Call with a string argument */
test(" 256garbage"); //Output int(256);
/* Call with a float argument */
test(14.52e+2); //Output int(1452)


Again, before dumping the result, PH7 internally convert the given argument to the type integer. So if we call our test function with a string argument, this parameter gets converted to the best representation of an integer. That is, the conversion stops at the first character that is not a digit or a hexadecimal character (white space is completely ignored).


We recommend to the PH7 enthusiastic users to experiment with this powerful mechanism and to report any unexpected result or inconsistency and/or their feedback to the PH7 public forums or using the PH7 mailing list.

Comma expressions

Again, another powerful mechanism borrowed from the C/C++ world and introduced as an extension to the PHP programming language.

A comma expression contains two operands of any type separated by a comma and has left-to-right associativity. The left operand is fully evaluated, possibly producing side effects, and its value, if there is one, is discarded. The right operand is then evaluated. The type and value of the result of a comma expression are those of its right operand, after the usual unary conversions.

Any number of expressions separated by commas can form a single expression because the comma operator is associative. The use of the comma operator guarantees that the sub-expressions will be evaluated in left-to-right order, and the value of the last becomes the value of the entire expression.

The following example assign the value 25 to the variable $a, multiply the value of $a with 2 and assign the result to variable $b and finally we call a test function to output the value of $a and $b. Keep-in mind that all theses operations are done in a single expression using the comma operator.


$a = 25,$b = $a << 1 /* $a * 2 */,test();
/* Output the value of $a and $b */
function test(){
  global $a,$b;
  echo "\$a = $a \$b= $b\n"; /* You should see: $a = 25 $b = 50*/
}


The primary use of comma expressions is to produce side effects in the following situations:

 In some contexts where the comma character is used, parentheses are required to avoid ambiguity.

 The following table gives some usage example of comma expressions.


if(++$x,$y = 100, $x > $y,foo())
{
/* Block will execute only if foo() return TRUE regardless of the first three expressions */
}

function foo(){ return TRUE; }

An if statement in which, variable $x is incremented, variable $y is assigned the value 100 and variable x is tested against variable $y and finally function foo()gets called. The first two expressions within this comma expression are evaluated before the call to foo(). Regardless of the results of the first three expressions, the fourth is evaluated (call to function foo()) and its result determines whether the if statement is processed.

We recommend to the PH7 enthusiastic users to experiment with this powerful mechanism and to report any unexpected result or inconsistency and/or their feedback to the PH7 public forums or using the PH7 mailing list.

Introducing the eq and ne operators.

The eq and ne operators are borrowed from the Perl world. They are used for strict string comparison. The reason why they have been implemented by the PH7 engine and introduced as an extension to the PHP programming language is due to the confusion introduced by the standard PHP comparison operators ('==' or '===') especially if you compare strings with numbers.

Take the following example: 


var_dump( 0xFF == '255' ); // bool(true) ???
// use the type equal operator by adding a single space to one of the operand

var_dump
( '255 ' === '255' ); //bool(true) depending on the PHP version


That is, if one of the operand looks like a number (either integer or float) then PHP will internally convert the two operands to numbers and then a numeric comparison is performed.


This is what the PHP language reference manual says:

If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically.


Bummer, if you ask me, this is broken, badly broken. I mean, the programmer cannot dictate it's comparison rule, it's the underlying engine who decides in it's place and perform the internal conversion. In most cases, PHP developers wants simple string comparison and they are stuck to use the ugly and inefficient strcmp() function or it's variants instead. This is the big reason why we have introduced these two operators.


The eq operator is used to compare two strings byte per byte. If you came from the C/C++ world, think of this operator as a barebone implementation of  the memcmp() C standard library function. Keep in mind that if you are comparing two ASCII strings then the capital letters and their lowercase letters are completely different and so this example will output false.


var_dump('allo' eq 'Allo'); //bool(FALSE)


The ne operator perform the opposite operation of the eq operator and is used to test for string inequality. This example will output true


var_dump('allo' ne 'Allo'); //bool(TRUE) unequal strings


The eq operator return a Boolean true if and only if the two strings are identical while the ne operator return a Boolean true if and only if the two strings are different. Otherwise a Boolean false is returned (equal strings).

Note that the comparison is performed only if the two strings are of the same length. Otherwise the eq and ne operators return a Boolean false without performing any comparison and avoid us wasting CPU time for nothing.

Keep in mind that we talk about low level byte per byte comparison and nothing else. Also remember that zero length strings are always equal.

Some example and their outputs:


var_dump( '0xff' eq '255' ); //bool(FALSE)
//Append a single space to the first operand

var_dump(' 255 ' eq '255'); //bool(FALSE) Not of the same length
//Operand one is a prefix of the second.

var_dump
('TES' eq 'TEST'); //bool(FALSE) What do you expect!

var_dump
('A7lan' eq 'A7lan'); //bool(TRUE)

// Test the not equal 'ne' operator

var_dump
( '255' ne 0xFF ); //bool(TRUE)

//Append a single space to the first operand

var_dump(' 255 ' ne '255'); //bool(FALSE) (Not of the same length)

Improved Operators Precedence Table

PH7 implements all the 60 PHP operators and introduced the eq and ne operators. The operators precedence table have been improved dramatically so that you can do same amazing things now such as array dereferencing, on the fly function call, anonymous function as array values, class member access on instantiation and so on. We discuss some of the improvements in details:

Array Dereferencing:


With this improvements, there is no need for a temporary variable to extract array entries values. Let's just say you want to output the middle name of Alan Mathison Turing in one statement without any assignment:


echo explode(' ', 'Alan Mathison Turing')[1]; //Output: Mathison


As you can see, there is no need for a temporary variable, the entry value was extracted by dereferencing the array returned by the explode() built-in function. You can even extract array values directly from functions return value as follows:


function test(){
 return
array( 'Machine' => 'Turing');

}
//Call the test function and output the 'Machine' entry value without any assignment
echo
test()['Machine']; //Output: Turing


  More, you can even insert anonymous functions in a array and invoke them directly as follows:


function test(){
 return
array( 'Anon' => function(){echo "Hello World\n";});

}
//Invoke the anonymous function stored in the 'Anon' entry from the returned array
echo
test()['Anon'](); //Hello World

Anonymous Functions as Array Values

$a = array(
     'add'
=> function ($x,$y){ return $x+$y; },

     'mul'
=> function ($x,$y){ return $x*$y; },
     'div' => function ($x,$y){ return $x/$y; }
);
/* Extract the anonymous function performing an addition */
$add = $a['add'];
/* Invoke */
echo $add(100,200); //Output: 300
/* Invoke our anonymous function directly by dereferencing the array */

echo
$a['add'](50,20).PHP_EOL; //Addition: Output 70

echo
$a['mul'](10,20).PHP_EOL; //Multiplication: Output 200

echo
$a['div'](50,2); //Division: Output 25


Here, the test array hold three anonymous functions. All of them expects two arguments and all perform an arithmetic operation. The first anonymous function perform an addition and it's associated key in the array is add, the second perform a multiplication and its key is mul while the third perform a division and it's key is div. If we call one if them either on the fly or via variable assignment, you will get the result of the desired arithmetic operation (addition, multiplication or division).


Class Member Access On Instantiation

class Test{
 public
$attr = 'Some '.'Value'; // Complex expression: Concatenation of two strings: Some + Value

};

//Access the class member without assigning the instantiated class to a variable

echo
(new Test())->attr; //You should see: Some Value


We have outputted the class attribute value without any kind of assignment. The garbage collector subsystem will automatically release this instance since it will not be used anywhere.

Powerful OO Subsystem

PH7 implements most of the PHP(5) OO subsystem including standard classes, interfaces, inheritance, magic methods, cloning, abstract and final methods, constructors and destrcutors, type hinting and so on. PH7 goes further and introduces some powerful extensions to the OO subsystem and we list some of the important extensions here:

64-Bit Integer Arithmetic For All Platforms

Under the standard PHP engine, The size of an integer is platform-dependent which mean that when running on 32-bit systems, the size of an integer is stored in 4 bytes and 8 bytes on 64-bit systems. This lead to non portable code especially if you are working with large integers. PH7 have standardized this and integers now are stored in 8 bytes (64 bits) regardless of the host environment. Because there is no cross-platform way to specify 64-bit integer types PH7 includes typedefs for 64-bit signed integers. The ph7_int64 type can store integer values between -9223372036854775808 and +9223372036854775807 inclusive.

Example:

echo PHP_INT_SIZE,' ',PHP_INT_MAX; //8 9223372036854775807

If you run this example on 32-bit or 64-bit (Windows or UNIX) systems, you will get the same output as follows: 8 9223372036854775807

Complex expressions for arguments default values

While the standard PHP engine would allow simple scalar values for function arguments default values, PH7 goes further and let you use any complex expressions including function calls, math or string expressions and so on as a default values for your function arguments.

Example:


function test($name = 'PH7 '.rand_str(4),$age = 10 * 2 + 5)
{
 echo "Name = $name\n";
 echo "Age = $age\n";

}
/* Call without arguments */

test(); /* You should see: name = PH7 rscd age = 25 */
/* Call with a single argument */

test('Me'); /* You should see: name = Me age = 25 */


The $name parameter takes as it's default value a complex expression which is the concatenation of the string 'PH7' and a random string of length 4 bytes generated by the built-in rand_str() function. The default value for the $age parameter is a constant math expression. If you run this example using the standard PHP engine, you will get a fatal error while under PH7 this example would run perfectly.

PH7 goes further and let you even use anonymous functions as a default value for your function arguments.

Example:


function test($callback = function(){ echo "Hello World!\n";})
{
 /* Check if we are dealing with a callback */
if( !is_callable($callback) ){
 
die("Expecting a callback");
}
/* Invoke the callback */
$callback();
}
/* Call without arguments */
test(); /* You should see: Hello World */
/* Call with a single argument */
test(function(){ echo "Welcome guest";}); /* You should see: Welcome guest */


That is, the $callback parameter takes as it's default value an anonymous function that echo “hello world” . This anonymous function will be invoked when the user calls the test() function without arguments.

UTF-8 Variables and Function names

PH7 has native support for UTF-8. That is, you are not restricted to use plain-English to name your variables or functions. Any UTF-8 encoded natural language (i.e: Japanese, Chinese, Arabic, etc.) can do the job.

Example:


$概要 = "PH7 engine";
$文書 = "http://ph7.symisc.net";
function ダウンロード(){
 
echo "http://ph7.symisc.net/downloads.html";
}
/* Test */
var_dump($概要,$文書);
/* Call the download function */
ダウンロード();


As you can see, there is no need for ICU or any other internationalization packages, all you need to do is write you PHP variables and function names in your natural language.

Complex expressions for static variables and constant

Again, PH7 goes further and let you use any complex expressions including function calls as an initialization values for your static variables and constants.

Example:


function test()
{
 /* Random number between 0 and 1023 as the initialization value for the static variable  */
 static $salt = rand() & 0x3FF;
 /* Echo the random number and increment it's value by 1*/

 echo
$salt++.PHP_EOL;
}
/* Random string of length 6 for our test constant */
const MY_CONST = rand_str(6);
/* Test */
test(); /* You should see a random number between 0 and 1023 [ex: 596 ] */
test(); /* 597 */
test(); /* 598 */
echo "MY_CONST value = ",MY_CONST,PHP_EOL;


Here, the static variable $salt takes as its initialization value a random number between 0 and 1023 inclusive generated by the built-in rand() function while the constant MY_CONST takes at its initialization value a random string generated by the built-in rand_str() function. Also note that the 'const' construct can be used outside a class definition.

Anonymous functions extensions

PH7 implements anonymous functions as well closures and introduces some amazing extensions to these constructs such as:

$anon = function(string $msg = 'Hello'.' '.'World!' /* Complex expression */){
        echo $msg.PHP_EOL;
}; //Don't forget the semi-colon here
/* Call the anonymous function without arguments */
$anon(); //You should see 'Hello World!'
/* Now,call the anonymous function with a simple argument */

$anon('Welcome guest'); //You should see 'Welcome guest'

/* Delimit the anonymous function in parenthesis,then  perform the invocation*/

(function(){echo 'Hello World!'.PHP_EOL;})(); //You should see 'Hello Wold!'

/* On the fly call, with arguments*/

(function(string $msg){echo $msg.PHP_EOL;})('Welcome Guest'); //You should see 'Welcome Guest!';

$anon = function(){echo 'Hello World!'.PHP_EOL;};
$anon(); //You should see 'Hello Wold!';

No Fatal Errors

Under PH7, the concept of run-time error is ignored and PH7 will try everything possible to let your program continue it's execution normally. A run-time error is an error that occurs while executing your program. Same example of run-time error includes a call to an undefined function or a instantiation of an undefined class. In both scenario PH7 will throw a simple warning and assume a null return value.

Suppose you have called an undefined function (PH7 does not implements all PHP functions such as crypt() ereg_replace() and so on). Rather than aborting program execution and following the standard PHP engine behavior, PH7 will set a null return value instead so that your program can continue its execution normally giving the illusion that the undefined function have been called and returned null.

Example: (Call an undefined function)


/* Call the undefined function */
$a = undefined_function(1,2,3);

var_dump
($a); /* NULL */

echo
"I'm not dead at: ",__DATE__,' ',__TIME__; //Output: I'm not dead at 2012-05-10 23:05:59


Here, $a have been assigned the null value since the undefined_function does not exists and thus cannot be called. The program continue its execution normally, dumping $a and outputting a message.

Example 2: (Call to an undefined class)


/* Try to instantiate an undefined class */
$a = new Undefined_Class();
var_dump($a); /* NULL */
echo "I'm not dead at: ",__DATE__,' ',__TIME__; //Output: I'm not dead at 2012-05-10 00:27:17


Here, we have tried to instantiate an undefined class. PH7 will throw a warning and return NULL instead so that the program can continue its execution normally.

The same rule apply, if you access an undefined array entry (I.e: $arr['undefined_index']) or an undefined class attribute (I.e: $class->undefined_attr). In each cases, PH7 throw a warning and return NULL instead.

The only fatal run-time error under PH7 that really could stop program execution is an out of memory. Fortunately PH7 have a tiny memory footprint (depending of course on the executed program an it's proper memory usage) and running out of memory on modern hardware even on modern embedded devices is an extremely rare scenario and we can say that your program is pretty safe.

Remember not to confuse run-time errors with compile-time error that occurs while compiling your PHP script using one of the compile interfaces. These compile-time errors are generally due to malformed PHP programs (that you must fix manually after viewing the compile error log) while run-time errors occurs during execution of the compiled program.

Single statement without parenthesis

Standard PHP functions (not anonymous) can omit the curly braces if their body comprise only a single statement (This behavior is identical to the if statement).

Example:


function test()
 echo 'Hello World!'.PHP_EOL; // single statement
//Invoke the previous function
test(); //You should see 'Hello Wold!'


Example 2:


function test(bool $arg)

  if( $arg )

    echo "Boolean TRUE\n";

  else

    echo "Boolean FALSE\n";

//Invoke with a boolean true
test(TRUE); // You should see 'Boolean TRUE'

Arrays are always passed by reference

PH7 pass and return arrays by reference exactly the same way PHP(5) pass objects (class instances) by reference. That is, when assigning an already created instance of an array to a new variable, the new variable will access the same instance as the array that was assigned. This behavior is the same when passing instances to a function. A copy of an already created array can be made by calling the built-in array_copy($src); function. an array variable doesn't contain the array itself as value anymore. It only contains an array identifier which allows array accessors to find the actual array. When an array is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier which points to the same array. If you came from C/C++ thinks of this as two variables pointing to the same instance of a malloc'ed structure.

Example: Array assignments


$a = array('sample',50,'value'); /* Create a new array instance */
$b = $a; /* After this assignment, the two variables point to the same array instance */
/* Remove the middle entry using variable $b */
unset($b[1] /* 50 */);
/* Dump using variable $a */
var_dump($a); /* Output: array 2( 0 => 'sample' , 2 => 'value' ); */
/* Check if the two variable point to the same instance */
var_dump( $a == $b ); /* bool(TRUE) */


Here, variable $a and $b point to the same array instance, so if you remove one entry using variable $a, the change is immediately seen in variable $b if you dump it. In other words, $a and $b point to the same instance.

Example 2: Passing array to function


function pop(array $arg)
{
 /* Remove the last array entry */
 array_pop($arg);
}
$a = array('sample',50,'value'); /* Create a new array instance */
/* Call the pop() function */
pop($a);
/* Dump $a */
var_dump($a); /* Output: array 2( 0 => 'sample' , 1 => '50' )*/

Here, even without including the reference operator & to the function argument, the array is passed by reference and the change is immediately seen (the pop operation) in variable $a.

To mimic the standard PHP engine behavior and to get a private copy of a array for each variable, you can use the array_copy() function as follows:


$a = array('sample',50,'value'); /* Create a new array instance */
/* Let $b have a private copy of the array instance assigned to $a */
$b = array_copy($a);
/* Now $a and $b point to a completely different instances */
array_pop($a);
var_dump($a); //Output array 2(0 => 'sample' , 1 => 50 );
/* Dump $b */
var_dump($b); //Output array 3(0 => 'sample' , 1 => 50 , 2 => 'value');

After calling array_copy(), $a and $b points to completely different instances. This is the solution if you want to pass and/or assign arrays by copy, but remember for performance reason it's recommended that you let PH7 pass array by reference and thus you avoid a heavy copy operation.

Hand-coded Project

The reason why performance rocks under PH7 relies in the fact that is a hand-coded project. That is, PH7 does not use any external tools to generate it's lexical analyzer such as lex or flex nor does not use LALR(1) parsers such as lemon, Bison or YACC to generate it's parser, everything is hand-coded by the Symisc Development Team. By acting so, the lexer and the parser are now thread-safe, full re-entrant, generate better error message, takes less space (100 KB together) in the source tree and are easy to maintain.


PH7 is a compact library. With all features enabled, the library size can be less than 600KiB, depending on compiler optimization settings. (Some compiler optimizations such as aggressive function inlining and loop unrolling can cause the object code to be much larger.) If optional features are omitted, the size of the PH7 library can be reduced below 220KiB. PH7 can also be made to run in very little heap (2MB), making PH7 a popular PHP engine choice on memory constrained gadgets such as cellphones ,tablets, numeric devices and so on.


PH7 is written in ANSI C, compile and run unmodified in any platform including restricted embedded device with a C compiler. PH7 have been extensively tested under Windows and UNIX including Linux (and its' flavours), FreeBSD (main development platform with Windows 7), Oracle Solaris and Mac OS X.

If you have successfully compiled and tested PH7 in an exotic environment or a proprietary UNIX such as HP-UX or AIX, please post a report in the PH7 forums or send an email to devel@symisc.net.

Amalgamation

PH7 source tree includes a little script written in PHP that is responsible of building an object called the "amalgamation" after successful compilation of the PH7 project. The amalgamation (Concept introduced by the SQLite project) is a single C code file, named "ph7.c", that contains all C code for the core PH7 library and it's extensions. This file contains about 61K lines of code and is over 1.9 megabytes in size.

The amalgamation contains everything you need to integrate PH7 into a larger project. Just copy the amalgamation into your source directory and compile it along with the other C code files in your project. You may also want to make use of the "ph7.h" header file that defines the programming API for PH7. The ph7.h header file is available separately. The ph7.h file is also contained within the amalgamation, in the first couple of thousand lines. So if you have a copy of ph7.c but cannot seem to locate ph7.h, you can always regenerate the ph7.h by copying and pasting from the amalgamation.

In addition to making PH7 easier to incorporate into other projects, the amalgamation also makes it run faster. Many compilers are able to do additional optimizations on code when it is contained with in a single translation unit such as it is in the amalgamation.

The amalgamation and the ph7.h header file are available on the download page as a file named ph7-amalgamation-X_X_X.zip where the X's are replaced by the appropriate version number.

Built-in HTTP Request Parser

PH7 includes a powerful HTTP request parser with the ability to extract MIME headers, decode GET/POST raw queries and populate the appropriate arrays such as $_GET, $_POST, $_SERVER and so on. This feature is popular for network oriented application such as web servers that embed the PH7 engine and need to pass HTTP informations to their PHP scripts. Refer to the PH7_VM_CONFIG_HTTP_REQUEST configuration option for additional information.

Hash-maps to represent arrays

PH7 uses the hashmap data structure internally to represent the array type. A hashmap is is a data structure that uses a hash function to map identifying values, known as keys, to their associated values. The hashmap implementation is written from scratch by the Symisc Development Team and uses two distinct (Inter-changeable) hash functions for it's operation. The first hash function is used to map 64-bit integer keys (Automatic indexes) to their bucket address in the table while the second hash function (DJB based implementation) is used for string keys. The hasmap implementation is found in the hashmap.c source file from the PH7 source tree.

Built-in sorting functions such as sort(), usort(), ksort(), rsort() and so on uses an efficient implementation of the stable merge-sort algorithm. The PH7 merge-sort implementation is based on the one found in the SQLite source tree.

Language construct in the context of a function call

You can now use language constructs such as echo, include, print and so on in the context of a function call as follows:


$my_echo = 'echo';
$my_echo("Hello World\n"); //Output Hello World
//or
fopen("Sample.txt") or echo "IO error while opening file";


You can store constructs names in a array and perform a call by dereferencing the array directly as follows:


$lang_constrcut = array('echo','print','include');
//Call the print function on the fly

$lang_constrcut[1 /* print index*/]("Hello World\n"); //Outputs: Hello World

//Include a dummy file on the fly

$lang_constrcut[2]('dummy_file'); //Output: IO error while importing dummy_file


Thanks to the improved operators precedence table for letting us introduce this smart extension.

Floating Point Comparison

The standard PHP engine is reputed for his inconsistency while playing with floating point numbers. Under PH7, you can work and compare floating point numbers exactly the same way you work with integers without any unexpected or inconsistent result.

Example:


var_dump(25.e-1 == 2.5); //bool(TRUE)
var_dump
(0.41 == 1.4); //bool(FALSE)

var_dump
(15.00 == 15 ); //bool(TRUE)

Correct implementation of the ternary operator

Unlike the standard PHP engine, the ternary operator under PH7 now evaluates left-to-right, associates right-to-left. That is, there is no need for parenthesis for nested ternary operators.

Example:


echo true?'true':false?'t':'f';

The following PHP expression will output 't' when running using the standard PHP engine and is an unexpected result, but if your run this code using the PH7 engine this will output 'true' as you might expect.

Another example (using concatenation) to test right to left associativity:


print '<div>'.(FALSE) ? 'TRUE [good ternary]' : 'FALSE [bad ternary]';


This will output 'FALSE [bad ternary]' when running using the standard PHP engine but outputs 'TRUE [good ternary]' when running using the PH7 engine.

Array cursor is automatically reset.

The array cursor is automatically reset to the beginning at the end of a running foreach() loop. That is, there in no need to manually call the built-in reset() function to reset the array cursor, this operation is done automatically.

const/var statements outside class definition

The const construct can be used now to declare constants outside a class definition. Note that as an extension, constants initialization values can be any complex expression including function calls as follows:


// Declare a constant named MY_CONST with an initialization value

// set to the the string 'PH7' with a random generated string of length 6
const MY_CONST = 'PH7 '.rand_str(6);

//Expand the constant
echo
MY_CONST ; //You should see something like 'PH7 dxthob'


Similarly, the var construct which is used to declare public class attributes can be used now to declare variables outside a class definition.

call_user_func() support pass by reference

As of this release, you can pass argument by reference as by copy to the built-in call_user_func() function, this smart extension allow the called function to modify the contents of the passed variable like a standard PHP function would do.

Example:


function add(&$var)
{

 $var += 10;

}

$a = 25;

call_user_func('add', $a);

echo $a."\n"; //You should see 35 now,since $a was passed by reference to the add() function

Caveats

While PH7 implements most of the PHP(5.3) constructs, they are some constructs and behavior that was omitted or cannot be implemented due to the embedded nature of the engine. Some of them are:


Symisc Systems
Copyright © Symisc Systems