Pastakhov has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/191858

Change subject: new Runtime (v 5.0.0)
......................................................................

new Runtime (v 5.0.0)

Change-Id: Idbfcca925f6668a6d1ec9810e6f8c1df75c31c58
---
M PhpTags.php
M includes/Compiler.php
M includes/PhpTagsException.php
M includes/Runtime.php
4 files changed, 1,334 insertions(+), 714 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/PhpTags 
refs/changes/58/191858/1

diff --git a/PhpTags.php b/PhpTags.php
index 916b474..700ccfe 100644
--- a/PhpTags.php
+++ b/PhpTags.php
@@ -15,13 +15,13 @@
        die( 'This file is an extension to MediaWiki and thus not a valid entry 
point.' );
 }
 
-const PHPTAGS_MAJOR_VERSION = 4;
-const PHPTAGS_MINOR_VERSION = 2;
+const PHPTAGS_MAJOR_VERSION = 5;
+const PHPTAGS_MINOR_VERSION = 0;
 const PHPTAGS_RELEASE_VERSION = 0;
 define( 'PHPTAGS_VERSION', PHPTAGS_MAJOR_VERSION . '.' . PHPTAGS_MINOR_VERSION 
. '.' . PHPTAGS_RELEASE_VERSION );
 
 const PHPTAGS_HOOK_RELEASE = 6;
-const PHPTAGS_RUNTIME_RELEASE = 3;
+const PHPTAGS_RUNTIME_RELEASE = 4;
 const PHPTAGS_JSONLOADER_RELEASE = 1;
 
 // Register this extension on Special:Version
diff --git a/includes/Compiler.php b/includes/Compiler.php
index 4d74bf7..47d7fd4 100644
--- a/includes/Compiler.php
+++ b/includes/Compiler.php
@@ -17,6 +17,9 @@
  */
 class Compiler {
 
+       //                                                                      
                +=                      -=                              *=      
                /=                      .=                              %=      
                        &=                      |=                      ^=      
                <<=                     >>=
+       protected static $assignmentOperators = array( '=', T_PLUS_EQUAL, 
T_MINUS_EQUAL, T_MUL_EQUAL, T_DIV_EQUAL, T_CONCAT_EQUAL, T_MOD_EQUAL, 
T_AND_EQUAL, T_OR_EQUAL, T_XOR_EQUAL, T_SL_EQUAL, T_SR_EQUAL );
+
        /**
         * Operator Precedence
         * @see http://www.php.net/manual/en/language.operators.precedence.php
@@ -41,8 +44,7 @@
                array( T_BOOLEAN_AND ), // &&
                array( T_BOOLEAN_OR ), // ||
                array( '?', ':' ),
-               //                              +=                      -=      
                        *=                      /=                      .=      
                        %=                              &=                      
|=                      ^=                      <<=                     >>=
-               array( '=', T_PLUS_EQUAL, T_MINUS_EQUAL, T_MUL_EQUAL, 
T_DIV_EQUAL, T_CONCAT_EQUAL, T_MOD_EQUAL, T_AND_EQUAL, T_OR_EQUAL, T_XOR_EQUAL, 
T_SL_EQUAL, T_SR_EQUAL ),
+               null, // self::$assignmentOperators
                array( T_LOGICAL_AND ), // and
                array( T_LOGICAL_XOR ), // xor
                array( T_LOGICAL_OR ), // or
@@ -55,20 +57,23 @@
         * @var array
         */
        protected static $runtimeOperators = array(
-               '~' => '~',
-               '!' => '!',
-               '*' => '*',
-               '/' => '/',
-               '%' => '%',
-               '+' => '+',
-               '-' => '-',
-               '.' => '.',
-               '<' => '<',
-               '>' => '>',
-               '&' => '&',
-               '^' => '^',
-               '|' => '|',
-               '=' => '=',
+               '~' => PHPTAGS_T_NOT,
+               '!' => PHPTAGS_T_IS_NOT,
+               '*' => PHPTAGS_T_MUL,
+               '/' => PHPTAGS_T_DIV,
+               '%' => PHPTAGS_T_MOD,
+               '+' => PHPTAGS_T_PLUS,
+               '-' => PHPTAGS_T_MINUS,
+               '.' => PHPTAGS_T_CONCAT,
+               '<' => PHPTAGS_T_IS_SMALLER,
+               '>' => PHPTAGS_T_IS_GREATER,
+               '&' => PHPTAGS_T_AND,
+               '^' => PHPTAGS_T_XOR,
+               '|' => PHPTAGS_T_OR,
+               '=' => PHPTAGS_T_EQUAL,
+               '"' => PHPTAGS_T_QUOTE,
+               '@' => PHPTAGS_T_IGNORE_ERROR,
+               '?' => PHPTAGS_T_TERNARY,
                T_LOGICAL_OR => PHPTAGS_T_LOGICAL_OR,
                T_BOOLEAN_OR => PHPTAGS_T_LOGICAL_OR,
                T_LOGICAL_XOR => PHPTAGS_T_LOGICAL_XOR,
@@ -107,6 +112,8 @@
                T_ISSET => PHPTAGS_T_ISSET,
                T_EMPTY => PHPTAGS_T_EMPTY,
                T_NEW => PHPTAGS_T_NEW,
+               T_GLOBAL => PHPTAGS_T_GLOBAL,
+               T_STATIC => PHPTAGS_T_STATIC,
        );
 
        /**
@@ -129,6 +136,7 @@
 
        function __construct() {
                if ( !self::$precedencesMatrix ) {
+                       self::$operatorsPrecedence[13] = 
self::$assignmentOperators;
                        foreach ( self::$operatorsPrecedence as $key => &$value 
) {
                                self::$precedencesMatrix += array_fill_keys( 
$value, $key );
                        }
@@ -214,6 +222,8 @@
                                return $this->stepForeachConstruct( 
$throwEndTag ); // return true
                        case T_FOR:
                                return $this->stepForConstruct( $throwEndTag ); 
// return true
+//                     case T_SWITCH:
+//                             return $this->stepSwitchConstruct( $throwEndTag 
); // return true
                        case T_CONTINUE:
                        case T_BREAK:
                                $this->stepUP( true );
@@ -245,7 +255,7 @@
                                                // PHP Parse error:  syntax 
error, unexpected $id,
                                                throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id ), 
$this->tokenLine, $this->place );
                                        }
-                                       if ( $value[PHPTAGS_STACK_COMMAND] != 
PHPTAGS_T_VARIABLE ) { // Example global $foo=5;
+                                       if ( $value[PHPTAGS_STACK_COMMAND] !== 
PHPTAGS_T_VARIABLE ) { // Example global $foo=5;
                                                throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( 
$value[PHPTAGS_STACK_COMMAND], 'T_VARIABLE' ), $this->tokenLine, $this->place );
                                        }
                                        if ( 
isset($value[PHPTAGS_STACK_ARRAY_INDEX]) ) {
@@ -288,7 +298,7 @@
                                                        
PHPTAGS_STACK_TOKEN_LINE => $this->tokenLine,
                                                        PHPTAGS_STACK_DEBUG => 
$text );
                                                $this->stack_push_memory();
-                                       } elseif ( 
$value[PHPTAGS_STACK_COMMAND] === '=' ) {
+                                       } elseif ( 
$value[PHPTAGS_STACK_COMMAND] === PHPTAGS_T_EQUAL ) {
                                                if ( 
isset($value[PHPTAGS_STACK_PARAM][PHPTAGS_STACK_ARRAY_INDEX]) ) {
                                                        throw new 
PhpTagsException( PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( '[', 
"','", "';'" ), $this->tokenLine, $this->place );
                                                }
@@ -537,7 +547,7 @@
                                                $i++;
                                        }
                                }
-                               $result = array( PHPTAGS_STACK_COMMAND=>'"', 
PHPTAGS_STACK_PARAM=>&$strings, PHPTAGS_STACK_RESULT=>null, 
PHPTAGS_STACK_TOKEN_LINE=>$this->tokenLine, PHPTAGS_STACK_DEBUG=>$text );
+                               $result = array( 
PHPTAGS_STACK_COMMAND=>PHPTAGS_T_QUOTE, PHPTAGS_STACK_PARAM=>&$strings, 
PHPTAGS_STACK_RESULT=>null, PHPTAGS_STACK_TOKEN_LINE=>$this->tokenLine, 
PHPTAGS_STACK_DEBUG=>$text );
                                break;
                        case T_VARIABLE:
                                $cannotRead = false;
@@ -572,7 +582,7 @@
 
                                $id = $this->id;
                                $text = $this->text;
-                               if ( in_array($id, 
self::$operatorsPrecedence[13]) ) { // It is assignment operator
+                               if ( in_array($id, self::$assignmentOperators) 
) { // It is assignment operator
                                        $this->stepUP();
                                        $val =& $this->getNextValue( '=' );
                                        if ( $val == false ) { // Example: 
$foo=;
@@ -751,7 +761,7 @@
                                        throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id, "'('" ), 
$this->tokenLine, $this->place );
                                }
                                $param = array();
-                               $i = 0;
+                               $i = -1;
                                do {
                                        $this->stepUP();
                                        if ( $this->id === T_LIST ) { // T_LIST 
inside T_LIST. Example: list( $foo, list
@@ -760,13 +770,13 @@
                                                $value =& $this->getNextValue();
                                                if ( $value === false ) { // 
Example: list($foo, ,
                                                        $value = null;
-                                               } elseif ( 
$value[PHPTAGS_STACK_COMMAND] != PHPTAGS_T_VARIABLE && 
$value[PHPTAGS_STACK_COMMAND] != PHPTAGS_T_LIST ) { // Example: unset( $foo+1 );
+                                               } elseif ( 
$value[PHPTAGS_STACK_COMMAND] !== PHPTAGS_T_VARIABLE && 
$value[PHPTAGS_STACK_COMMAND] !== PHPTAGS_T_LIST ) { // Example: unset( $foo+1 
);
                                                        throw new 
PhpTagsException( PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( 
$value[PHPTAGS_STACK_COMMAND], 'T_VARIABLE' ), $this->tokenLine, $this->place );
                                                }
                                        }
                                        $tmp = array( 
PHPTAGS_STACK_COMMAND=>null, PHPTAGS_STACK_RESULT=>&$value );
-                                       $param[$i] = null;
-                                       $this->addValueIntoStack( $tmp, $param, 
$i++ );
+                                       $param[++$i] = null;
+                                       $this->addValueIntoStack( $tmp, $param, 
$i );
                                        unset( $value, $tmp );
                                } while ( $this->id === ',' );
                                if ( $this->id != ')' ) {
@@ -776,6 +786,8 @@
                                $result = array(
                                        PHPTAGS_STACK_COMMAND => PHPTAGS_T_LIST,
                                        PHPTAGS_STACK_PARAM => &$param,
+                                       PHPTAGS_STACK_PARAM_2 => null,
+                                       PHPTAGS_STACK_RESULT => null,
                                        PHPTAGS_STACK_TOKEN_LINE => 
$this->tokenLine,
                                        PHPTAGS_STACK_DEBUG => $text,
                                );
@@ -791,16 +803,8 @@
                                                // PHP Parse error:  syntax 
error, unexpected $id
                                                throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id ), 
$this->tokenLine, $this->place );
                                        }
-                                       $return = array(
-                                               PHPTAGS_STACK_COMMAND => '=',
-                                               PHPTAGS_STACK_PARAM => $result,
-                                               PHPTAGS_STACK_PARAM_2 => null,
-                                               PHPTAGS_STACK_RESULT => null,
-                                               PHPTAGS_STACK_TOKEN_LINE => 
$this->tokenLine,
-                                               PHPTAGS_STACK_DEBUG => '=',
-                                       );
-                                       $this->addValueIntoStack( $val, 
$return, PHPTAGS_STACK_PARAM_2 );
-                                       return $return; // *********** EXIT 
***********
+                                       $this->addValueIntoStack( $val, 
$result, PHPTAGS_STACK_PARAM_2 );
+                                       return $result; // *********** EXIT 
***********
                                }
                                break;
                        case T_PRINT:
@@ -839,7 +843,7 @@
                                                // PHP Parse error:  syntax 
error, unexpected $id,
                                                throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id ), 
$this->tokenLine, $this->place );
                                        }
-                                       if ( $value[PHPTAGS_STACK_COMMAND] != 
PHPTAGS_T_VARIABLE ) { // Example: unset( $foo+1 );
+                                       if ( $value[PHPTAGS_STACK_COMMAND] !== 
PHPTAGS_T_VARIABLE ) { // Example: unset( $foo+1 );
                                                throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( 
$value[PHPTAGS_STACK_COMMAND], 'T_VARIABLE' ), $this->tokenLine, $this->place );
                                        }
                                        $param[] =& $value;
@@ -894,7 +898,7 @@
                        case '@': // Error Control Operator
                                $this->stepUP();
                                if ( $this->ignoreErrors === false ) {
-                                       $this->stack[] = array( 
PHPTAGS_STACK_COMMAND => '@', PHPTAGS_STACK_PARAM => true );
+                                       $this->stack[] = array( 
PHPTAGS_STACK_COMMAND => PHPTAGS_T_IGNORE_ERROR, PHPTAGS_STACK_PARAM => true );
                                        $this->ignoreErrors = true;
                                }
                                $result =& $this->stepValue( $owner );
@@ -965,7 +969,7 @@
                        case '?':
                                // Make the operator without the second value
                                $ternary = array(
-                                       PHPTAGS_STACK_COMMAND => '?',
+                                       PHPTAGS_STACK_COMMAND => 
PHPTAGS_T_TERNARY,
                                        PHPTAGS_STACK_PARAM => null,
                                        PHPTAGS_STACK_PARAM_2 => null,
                                        PHPTAGS_STACK_RESULT => null,
@@ -1096,7 +1100,7 @@
                                        PHPTAGS_STACK_DO_FALSE => false,
                                );
                                $result = array(
-                                       PHPTAGS_STACK_COMMAND => '?',
+                                       PHPTAGS_STACK_COMMAND => 
PHPTAGS_T_TERNARY,
                                        PHPTAGS_STACK_PARAM => null,
                                        PHPTAGS_STACK_PARAM_2 => $param2,
                                        PHPTAGS_STACK_RESULT => null,
@@ -1152,7 +1156,7 @@
                                        PHPTAGS_STACK_DO_FALSE => $stack_false,
                                );
                                $result = array(
-                                       PHPTAGS_STACK_COMMAND => '?',
+                                       PHPTAGS_STACK_COMMAND => 
PHPTAGS_T_TERNARY,
                                        PHPTAGS_STACK_PARAM => null,
                                        PHPTAGS_STACK_PARAM_2 => $param2,
                                        PHPTAGS_STACK_RESULT => null,
@@ -1466,8 +1470,12 @@
                        if ( $this->id === $end ) {
                                break;
                        }
-                       throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id, "',' or ';'" 
), $this->tokenLine, $this->place );
+                       throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id, ',', ';' ), 
$this->tokenLine, $this->place );
                }
+       }
+
+       private function stepSwitchConstruct( $throwEndTag ) {
+
        }
 
        private function stepForeachConstruct( $throwEndTag = true ) {
@@ -1486,7 +1494,7 @@
                        // PHP Parse error:  syntax error, unexpected $id
                        throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id ), 
$this->tokenLine, $this->place );
                }
-               if ( $arrayExpression[PHPTAGS_STACK_COMMAND] != 
PHPTAGS_T_VARIABLE && $arrayExpression[PHPTAGS_STACK_COMMAND] != 
PHPTAGS_T_ARRAY ) {
+               if ( $arrayExpression[PHPTAGS_STACK_COMMAND] !== 
PHPTAGS_T_VARIABLE && $arrayExpression[PHPTAGS_STACK_COMMAND] !== 
PHPTAGS_T_ARRAY ) {
                        // PHP Parse error:  syntax error, unexpected $id, 
expecting T_VARIABLE
                        throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( 
$arrayExpression[PHPTAGS_STACK_COMMAND], 'T_VARIABLE', 'T_ARRAY' ), 
$this->tokenLine, $this->place );
                }
@@ -1634,7 +1642,7 @@
                                $runtimeReturn = Runtime::run( array($command, 
$tmp),   array('PhpTags\\Compiler') );
                                if ( $runtimeReturn instanceof PhpTagsException 
) {
                                        if ( $this->ignoreErrors === null ) {
-                                               $this->stack[] = array( 
PHPTAGS_STACK_COMMAND => '@', PHPTAGS_STACK_PARAM => false );
+                                               $this->stack[] = array( 
PHPTAGS_STACK_COMMAND => PHPTAGS_T_IGNORE_ERROR, PHPTAGS_STACK_PARAM => false );
                                                $this->ignoreErrors = false;
                                        }
                                        return false;
@@ -1650,7 +1658,7 @@
                }
 
                if ( $this->ignoreErrors === null ) {
-                       $this->stack[] = array( PHPTAGS_STACK_COMMAND => '@', 
PHPTAGS_STACK_PARAM => false );
+                       $this->stack[] = array( PHPTAGS_STACK_COMMAND => 
PHPTAGS_T_IGNORE_ERROR, PHPTAGS_STACK_PARAM => false );
                        $this->ignoreErrors = false;
                }
                return false;
diff --git a/includes/PhpTagsException.php b/includes/PhpTagsException.php
index f8b9cd4..5a8e803 100644
--- a/includes/PhpTagsException.php
+++ b/includes/PhpTagsException.php
@@ -162,6 +162,9 @@
                        case self::FATAL_CALLED_MANY_EXPENSIVE_FUNCTION:
                                $message = "Too many expensive function calls, 
last is $arguments";
                                break;
+                       case self::FATAL_WRONG_BREAK_LEVELS:
+                               $message = "Cannot break/continue $arguments 
levels";
+                               break;
                        case self::NOTICE_GET_PROPERTY_OF_NON_OBJECT:
                                $message = 'Trying to get property of 
non-object';
                                break;
@@ -266,6 +269,7 @@
        const FATAL_CALL_FUNCTION_ON_NON_OBJECT = 4019; // PHP Fatal error:  
Call to a member function doo() on a non-object
        const FATAL_ACCESS_TO_UNDECLARED_STATIC_PROPERTY = 4020; // PHP Fatal 
error:  Access to undeclared static property: F::$rsrr
        const FATAL_UNEXPECTED_OBJECT_TYPE = 4021; // Fatal error: Unexpected 
object type stdClass. in
+       const FATAL_WRONG_BREAK_LEVELS = 4022; // PHP Fatal error:  Cannot 
break/continue 4 levels
 
        const FATAL_DENIED_FOR_NAMESPACE = 4500;
        const FATAL_CALLFUNCTION_INVALID_HOOK = 4501;
diff --git a/includes/Runtime.php b/includes/Runtime.php
index 2b997af..a1c500c 100644
--- a/includes/Runtime.php
+++ b/includes/Runtime.php
@@ -1,19 +1,33 @@
 <?php
 namespace PhpTags;
 
-define( 'PHPTAGS_STACK_RESULT', 'r' );
-define( 'PHPTAGS_STACK_COMMAND', 'c' );
-define( 'PHPTAGS_STACK_PARAM', 'p' );
-define( 'PHPTAGS_STACK_PARAM_2', 's' );
-define( 'PHPTAGS_STACK_PARAM_3', 'o' );
-define( 'PHPTAGS_STACK_INC_AFTER', 'i' );
-define( 'PHPTAGS_STACK_TOKEN_LINE', 'l' );
-define( 'PHPTAGS_STACK_DO_TRUE', 't' );
-define( 'PHPTAGS_STACK_DO_FALSE', 'f' );
-define( 'PHPTAGS_STACK_ARRAY_INDEX', 'a' );
-define( 'PHPTAGS_STACK_DEBUG', '#' );
-define( 'PHPTAGS_STACK_AIM', '*' );
-define( 'PHPTAGS_STACK_HOOK_TYPE', 'h' );
+//const PHPTAGS_STACK_RESULT = 'r';
+//const PHPTAGS_STACK_COMMAND = 'c';
+//const PHPTAGS_STACK_PARAM = 'p';
+//const PHPTAGS_STACK_PARAM_2 = 's';
+//const PHPTAGS_STACK_PARAM_3 = 'o';
+//const PHPTAGS_STACK_INC_AFTER = 'i';
+//const PHPTAGS_STACK_TOKEN_LINE = 'l';
+//const PHPTAGS_STACK_DO_TRUE = 't';
+//const PHPTAGS_STACK_DO_FALSE = 'f';
+//const PHPTAGS_STACK_ARRAY_INDEX = 'a';
+//const PHPTAGS_STACK_DEBUG = '#';
+//const PHPTAGS_STACK_AIM = '*';
+//const PHPTAGS_STACK_HOOK_TYPE = 'h';
+
+const PHPTAGS_STACK_COMMAND = 0;
+const PHPTAGS_STACK_RESULT = 1;
+const PHPTAGS_STACK_PARAM = 2;
+const PHPTAGS_STACK_PARAM_2 = 3;
+const PHPTAGS_STACK_PARAM_3 = 4;
+const PHPTAGS_STACK_INC_AFTER = 5;
+const PHPTAGS_STACK_TOKEN_LINE = 6;
+const PHPTAGS_STACK_DO_TRUE = 7;
+const PHPTAGS_STACK_DO_FALSE = 8;
+const PHPTAGS_STACK_ARRAY_INDEX = 9;
+const PHPTAGS_STACK_DEBUG = 10;
+const PHPTAGS_STACK_AIM = 11;
+const PHPTAGS_STACK_HOOK_TYPE = 12;
 
 define( 'PHPTAGS_HOOK_GET_CONSTANT', '_' );
 define( 'PHPTAGS_HOOK_FUNCTION', 'f' );
@@ -28,56 +42,223 @@
 define( 'PHPTAGS_OBJECT_DEFINITION', 0 );
 define( 'PHPTAGS_METHOD_CONSTRUCTOR', 1 );
 
-define( 'PHPTAGS_T_LOGICAL_OR', 263 );
-define( 'PHPTAGS_T_LOGICAL_XOR', 264 );
-define( 'PHPTAGS_T_LOGICAL_AND', 265 );
-define( 'PHPTAGS_T_PRINT', 266 );
-define( 'PHPTAGS_T_SR_EQUAL', 268 );
-define( 'PHPTAGS_T_SL_EQUAL', 269 );
-define( 'PHPTAGS_T_XOR_EQUAL', 270 );
-define( 'PHPTAGS_T_OR_EQUAL', 271 );
-define( 'PHPTAGS_T_AND_EQUAL', 272 );
-define( 'PHPTAGS_T_MOD_EQUAL', 273 );
-define( 'PHPTAGS_T_CONCAT_EQUAL', 274 );
-define( 'PHPTAGS_T_DIV_EQUAL', 275 );
-define( 'PHPTAGS_T_MUL_EQUAL', 276 );
-define( 'PHPTAGS_T_MINUS_EQUAL', 277 );
-define( 'PHPTAGS_T_PLUS_EQUAL', 278 );
-define( 'PHPTAGS_T_IS_NOT_IDENTICAL', 281 );
-define( 'PHPTAGS_T_IS_IDENTICAL', 282 );
-define( 'PHPTAGS_T_IS_NOT_EQUAL', 283 );
-define( 'PHPTAGS_T_IS_EQUAL', 284 );
-define( 'PHPTAGS_T_IS_GREATER_OR_EQUAL', 285 );
-define( 'PHPTAGS_T_IS_SMALLER_OR_EQUAL', 286 );
-define( 'PHPTAGS_T_SR', 287 );
-define( 'PHPTAGS_T_SL', 288 );
-define( 'PHPTAGS_T_UNSET_CAST', 290 );
-define( 'PHPTAGS_T_BOOL_CAST', 291 );
-define( 'PHPTAGS_T_ARRAY_CAST', 293 );
-define( 'PHPTAGS_T_STRING_CAST', 294 );
-define( 'PHPTAGS_T_DOUBLE_CAST', 295 );
-define( 'PHPTAGS_T_INT_CAST', 296 );
-define( 'PHPTAGS_T_DEC', 297 );
-define( 'PHPTAGS_T_INC', 298 );
-define( 'PHPTAGS_T_NEW', 300 );
-define( 'PHPTAGS_T_IF', 302 );
-define( 'PHPTAGS_T_HOOK', 308 );
-define( 'PHPTAGS_T_HOOK_CHECK_PARAM', 309 );
-define( 'PHPTAGS_T_VARIABLE', 310 );
-define( 'PHPTAGS_T_WHILE', 319 );
-define( 'PHPTAGS_T_FOREACH', 323 );
-define( 'PHPTAGS_T_AS', 327 );
-define( 'PHPTAGS_T_BREAK', 332 );
-define( 'PHPTAGS_T_CONTINUE', 333 );
-define( 'PHPTAGS_T_RETURN', 337 );
-define( 'PHPTAGS_T_GLOBAL', 344 );
-define( 'PHPTAGS_T_STATIC', 350 );
-define( 'PHPTAGS_T_UNSET', 352 );
-define( 'PHPTAGS_T_ISSET', 353 );
-define( 'PHPTAGS_T_EMPTY', 354 );
-define( 'PHPTAGS_T_LIST', 363 );
-define( 'PHPTAGS_T_ARRAY', 364 );
-define( 'PHPTAGS_T_COPY', 500 );
+/**
+ * operator: "
+ */
+const PHPTAGS_T_QUOTE = 0; // "
+/**
+ * operator: .
+ */
+const PHPTAGS_T_CONCAT = 1;
+/**
+ * operator: +
+ */
+const PHPTAGS_T_PLUS = 2;
+/**
+ * operator: -
+ */
+const PHPTAGS_T_MINUS = 3;
+/**
+ * operator: *
+ */
+const PHPTAGS_T_MUL = 4;
+/**
+ * operator: /
+ */
+const PHPTAGS_T_DIV = 5;
+/**
+ * operator: ==
+ */
+const PHPTAGS_T_IS_EQUAL = 6;
+/**
+ * get value from variable
+ */
+const PHPTAGS_T_VARIABLE = 7;
+/**
+ * operator: if
+ */
+const PHPTAGS_T_IF = 8;
+/**
+ * operator: =
+ */
+const PHPTAGS_T_EQUAL = 9;
+/**
+ * operator: .=
+ */
+const PHPTAGS_T_CONCAT_EQUAL = 10;
+/**
+ * operator: /=
+ */
+const PHPTAGS_T_DIV_EQUAL = 11;
+/**
+ * operator: *=
+ */
+const PHPTAGS_T_MUL_EQUAL = 12;
+/**
+ * operator: -=
+ */
+const PHPTAGS_T_MINUS_EQUAL = 13;
+/**
+ * operator: +=
+ */
+const PHPTAGS_T_PLUS_EQUAL = 14;
+/**
+ * operator: !==
+ */
+const PHPTAGS_T_IS_NOT_IDENTICAL = 15;
+/**
+ * operator: ===
+ */
+const PHPTAGS_T_IS_IDENTICAL = 16;
+/**
+ * operator: !=
+ */
+const PHPTAGS_T_IS_NOT_EQUAL = 17;
+/**
+ * operator: ^=
+ */
+const PHPTAGS_T_XOR_EQUAL = 18;
+/**
+ * operator: >=
+ */
+const PHPTAGS_T_IS_GREATER_OR_EQUAL = 19;
+/**
+ * operator: <=
+ */
+const PHPTAGS_T_IS_SMALLER_OR_EQUAL = 20;
+/**
+ * operator: >>
+ */
+const PHPTAGS_T_SR = 21;
+/**
+ * operator: <<
+ */
+const PHPTAGS_T_SL = 22;
+/**
+ * operator: (unset)
+ */
+const PHPTAGS_T_UNSET_CAST = 23;
+/**
+ * operator: (bool)
+ */
+const PHPTAGS_T_BOOL_CAST = 24;
+/**
+ * operator: (array)
+ */
+const PHPTAGS_T_ARRAY_CAST = 25;
+/**
+ * operator: (string)
+ */
+const PHPTAGS_T_STRING_CAST = 26;
+/**
+ * operator: (double)
+ */
+const PHPTAGS_T_DOUBLE_CAST = 27;
+/**
+ * operator: (int)
+ */
+const PHPTAGS_T_INT_CAST = 28;
+/**
+ * operator: --
+ */
+const PHPTAGS_T_DEC = 29;
+/**
+ * operator: ++
+ */
+const PHPTAGS_T_INC = 30;
+/**
+ * operator: new
+ */
+const PHPTAGS_T_NEW = 31;
+/**
+ * operator: &=
+ */
+const PHPTAGS_T_AND_EQUAL = 32;
+/**
+ * call phptags hook
+ */
+const PHPTAGS_T_HOOK = 33;
+/**
+ * check passed param to phptags hook
+ */
+const PHPTAGS_T_HOOK_CHECK_PARAM = 34;
+/**
+ * it copies value from variable to destination
+ */
+const PHPTAGS_T_COPY = 35;
+const PHPTAGS_T_WHILE = 36;
+const PHPTAGS_T_FOREACH = 37;
+const PHPTAGS_T_AS = 38;
+const PHPTAGS_T_BREAK = 39;
+const PHPTAGS_T_CONTINUE = 40;
+const PHPTAGS_T_RETURN = 41;
+const PHPTAGS_T_GLOBAL = 42;
+const PHPTAGS_T_STATIC = 43;
+const PHPTAGS_T_UNSET = 44;
+const PHPTAGS_T_ISSET = 45;
+const PHPTAGS_T_EMPTY = 46;
+const PHPTAGS_T_LIST = 47;
+const PHPTAGS_T_ARRAY = 48;
+const PHPTAGS_T_OR_EQUAL = 49;
+/**
+ * operators: echo, print
+ */
+const PHPTAGS_T_PRINT = 50;
+/**
+ * operator: ||
+ */
+const PHPTAGS_T_LOGICAL_OR = 51;
+/**
+ * operator: @
+ */
+const PHPTAGS_T_IGNORE_ERROR = 52; // @
+/**
+ * ternary operator: ?
+ */
+const PHPTAGS_T_TERNARY = 53; // ?
+/**
+ * operator: |
+ */
+const PHPTAGS_T_OR = 54; // |
+/**
+ * operator: ^
+ */
+const PHPTAGS_T_XOR = 55;
+/**
+ * operator: &
+ */
+const PHPTAGS_T_AND = 56;
+/**
+ * operator: >
+ */
+const PHPTAGS_T_IS_GREATER = 57;
+/**
+ * operator: <
+ */
+const PHPTAGS_T_IS_SMALLER = 58;
+/**
+ * operator: xor
+ */
+const PHPTAGS_T_LOGICAL_XOR = 59;
+const PHPTAGS_T_MOD_EQUAL = 60;
+/**
+ * operator: and
+ */
+const PHPTAGS_T_LOGICAL_AND = 61;
+/**
+ * operator: %
+ */
+const PHPTAGS_T_MOD = 62;
+const PHPTAGS_T_SL_EQUAL = 63;
+const PHPTAGS_T_SR_EQUAL = 64;
+/**
+ * operator: !
+ */
+const PHPTAGS_T_IS_NOT = 65;
+/**
+ * operator: ~
+ */
+const PHPTAGS_T_NOT = 66;
 
 /**
  * The runtime class of the extension PhpTags.
@@ -106,10 +287,80 @@
        private static $variables = array();
        private static $staticVariables = array();
        private static $globalVariables = array();
-       private static $exceptions = array();
+       private static $ignoreErrors = false;
        private static $scope;
        private static $parserDisabled = false;
        private static $errorCategoryAdded = false;
+
+       private static $operators = array(
+               PHPTAGS_T_QUOTE => 'doQuote',
+               PHPTAGS_T_CONCAT => 'doConcat',
+               PHPTAGS_T_PLUS => 'doPlus',
+               PHPTAGS_T_MINUS => 'doMinus',
+               PHPTAGS_T_MUL => 'doMul',
+               PHPTAGS_T_DIV => 'doDiv',
+               PHPTAGS_T_MOD => 'doMod',
+               PHPTAGS_T_AND => 'doAnd',
+               PHPTAGS_T_OR => 'doOr',
+               PHPTAGS_T_XOR => 'doXor',
+               PHPTAGS_T_SL => 'doShiftLeft',
+               PHPTAGS_T_SR => 'doShiftRight',
+               PHPTAGS_T_LOGICAL_AND => 'doLogicalAnd',
+               PHPTAGS_T_LOGICAL_XOR => 'doLogicalXor',
+               PHPTAGS_T_LOGICAL_OR => 'doLogicalOr',
+               PHPTAGS_T_IS_SMALLER => 'doIsSmaller',
+               PHPTAGS_T_IS_GREATER => 'doIsGreater',
+               PHPTAGS_T_IS_SMALLER_OR_EQUAL => 'doIsSmallerOrEqual',
+               PHPTAGS_T_IS_GREATER_OR_EQUAL => 'doIsGreaterOrEqual',
+               PHPTAGS_T_IS_EQUAL => 'doIsEqual',
+               PHPTAGS_T_IS_NOT_EQUAL => 'doIsNotEqual',
+               PHPTAGS_T_IS_IDENTICAL => 'doIsIdentical',
+               PHPTAGS_T_IS_NOT_IDENTICAL => 'doIsNotIdentical',
+               PHPTAGS_T_PRINT => 'doPrint',
+               PHPTAGS_T_NOT => 'doNot',
+               PHPTAGS_T_IS_NOT => 'doIsNot',
+               PHPTAGS_T_INT_CAST => 'doIntCast',
+               PHPTAGS_T_DOUBLE_CAST => 'doDoubleCast',
+               PHPTAGS_T_STRING_CAST => 'doStringCast',
+               PHPTAGS_T_ARRAY_CAST => 'doArrayCast',
+               PHPTAGS_T_BOOL_CAST => 'doBoolCast',
+               PHPTAGS_T_UNSET_CAST => 'doUnsetCast',
+               PHPTAGS_T_VARIABLE => 'doVariable',
+               PHPTAGS_T_TERNARY => 'doTernary',
+               PHPTAGS_T_IF => 'doIf',
+               PHPTAGS_T_FOREACH => 'doForeach',
+               PHPTAGS_T_WHILE => 'doWhile',
+               PHPTAGS_T_AS => 'doAs',
+               PHPTAGS_T_BREAK => 'doBreak',
+               PHPTAGS_T_CONTINUE => 'doContinue',
+               PHPTAGS_T_ARRAY => 'doArray',
+               PHPTAGS_T_STATIC => 'doStatic',
+               PHPTAGS_T_GLOBAL => 'doGlobal',
+               PHPTAGS_T_HOOK_CHECK_PARAM => 'doCheckingParam',
+               PHPTAGS_T_HOOK => 'doCallingHook',
+               PHPTAGS_T_NEW => 'doNewObject',
+               PHPTAGS_T_UNSET => 'doUnset',
+               PHPTAGS_T_ISSET => 'doIsSet',
+               PHPTAGS_T_EMPTY => 'doIsEmpty',
+               PHPTAGS_T_RETURN => 'doReturn',
+               PHPTAGS_T_COPY => 'doCopy',
+               PHPTAGS_T_IGNORE_ERROR => 'doIgnoreErrors',
+               PHPTAGS_T_LIST => 'doList',
+               PHPTAGS_T_INC => 'doIncrease',
+               PHPTAGS_T_DEC => 'doDecrease',
+               PHPTAGS_T_EQUAL => 'doSetVal',
+               PHPTAGS_T_CONCAT_EQUAL => 'doSetConcatVal',
+               PHPTAGS_T_PLUS_EQUAL => 'doSetPlusVal',
+               PHPTAGS_T_MINUS_EQUAL => 'doSetMinusVal',
+               PHPTAGS_T_MUL_EQUAL => 'doSetMulVal',
+               PHPTAGS_T_DIV_EQUAL => 'doSetDivVal',
+               PHPTAGS_T_MOD_EQUAL => 'doSetModVal',
+               PHPTAGS_T_AND_EQUAL => 'doSetAndVal',
+               PHPTAGS_T_OR_EQUAL => 'doSetOrVal',
+               PHPTAGS_T_XOR_EQUAL => 'doSetXorVal',
+               PHPTAGS_T_SL_EQUAL => 'doSetShiftLeftVal',
+               PHPTAGS_T_SR_EQUAL => 'doSetShiftRightVal',
+       );
 
        public static function reset() {
                global $wgPhpTagsMaxLoops;
@@ -126,629 +377,984 @@
                return self::run( Compiler::compile($code), $args, $scope );
        }
 
+       /**
+        * The output cache
+        * @var array
+        */
+       private static $return;
+       private static $running;
+       private static $runIndex;
+       private static $c;
+       private static $loopsOwner;
+       private static $memory;
+       private static $place;
+       private static $thisVariables;
+
+       private static function pushDown( $newCode, $newLoopsOwner, &$refReturn 
) {
+               self::$memory[] = array( &$refReturn, self::$running, 
self::$runIndex, self::$c, self::$loopsOwner );
+               self::$running = $newCode;
+               self::$runIndex = -1;
+               self::$c = count( $newCode );
+               self::$loopsOwner = $newLoopsOwner;
+       }
+
+       private static function popUp() {
+               list( self::$running[self::$runIndex][PHPTAGS_STACK_RESULT], 
self::$running, self::$runIndex, self::$c, self::$loopsOwner ) = array_pop( 
self::$memory );
+       }
+
+       /**
+        * PHPTAGS_T_QUOTE
+        * @param array $value
+        */
+       private static function doQuote ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = implode( 
$value[PHPTAGS_STACK_PARAM] );
+       }
+
+       /**
+        * PHPTAGS_T_CONCAT
+        * @param array $value
+        */
+       private static function doConcat ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] . 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_PLUS
+        * @param array $value
+        */
+       private static function doPlus ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] + 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_MINUS
+        * @param array $value
+        */
+       private static function doMinus ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] - 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_MUL
+        * @param array $value
+        */
+       private static function doMul ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] * 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_DIV
+        * @param array $value
+        */
+       private static function doDiv ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] / 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_MOD
+        * @param array $value
+        */
+       private static function doMod ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] % 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_AND
+        * @param array $value
+        */
+       private static function doAnd ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] & 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_OR
+        * @param array $value
+        */
+       private static function doOr ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] | 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_XOR
+        * @param array $value
+        */
+       private static function doXor ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] ^ 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_SL
+        * @param array $value
+        */
+       private static function doShiftLeft ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] << 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_SR
+        * @param array $value
+        */
+       private static function doShiftRight ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] >> 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_LOGICAL_AND
+        * @param array $value
+        */
+       private static function doLogicalAnd ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] && 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_LOGICAL_XOR
+        * @param array $value
+        */
+       private static function doLogicalXor ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] xor 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_LOGICAL_OR
+        * @param array $value
+        */
+       private static function doLogicalOr ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] || 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_IS_SMALLER
+        * @param array $value
+        */
+       private static function doIsSmaller ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] < 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_IS_GREATER
+        * @param array $value
+        */
+       private static function doIsGreater ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] > 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_IS_SMALLER_OR_EQUAL
+        * @param array $value
+        */
+       private static function doIsSmallerOrEqual ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] <= 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_IS_GREATER_OR_EQUAL
+        * @param array $value
+        */
+       private static function doIsGreaterOrEqual ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] >= 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_IS_EQUAL
+        * @param array $value
+        */
+       private static function doIsEqual ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] == 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_IS_NOT_EQUAL
+        * @param array $value
+        */
+       private static function doIsNotEqual ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] != 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_IS_IDENTICAL
+        * @param array $value
+        */
+       private static function doIsIdentical ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] === 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_IS_NOT_IDENTICAL
+        * @param array $value
+        */
+       private static function doIsNotIdentical ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] !== 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_PRINT outputs the value
+        * @param array $value
+        */
+       private static function doPrint ( $value ) {
+               if( $value[PHPTAGS_STACK_PARAM] instanceof GenericObject ) {
+                       self::$return[] = 
$value[PHPTAGS_STACK_PARAM]->toString();
+               } else {
+                       self::$return[] = $value[PHPTAGS_STACK_PARAM];
+               }
+       }
+
+       /**
+        * PHPTAGS_T_NOT
+        * @param array $value
+        */
+       private static function doNot ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = ~$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_IS_NOT
+        * @param array $value
+        */
+       private static function doIsNot ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = !$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_INT_CAST
+        * @param array $value
+        */
+       private static function doIntCast ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = 
(int)$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_DOUBLE_CAST
+        * @param array $value
+        */
+       private static function doDoubleCast ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = 
(double)$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_STRING_CAST
+        * @param array $value
+        */
+       private static function doStringCast ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = 
(string)$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_ARRAY_CAST
+        * @param array $value
+        */
+       private static function doArrayCast ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = 
(array)$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_BOOL_CAST
+        * @param array $value
+        */
+       private static function doBoolCast ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = 
(bool)$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_UNSET_CAST
+        * @param array $value
+        */
+       private static function doUnsetCast ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = 
(unset)$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_VARIABLE
+        * @param array $value
+        */
+       private static function doVariable ( $value ) {
+               $aim = $value[PHPTAGS_STACK_AIM];
+               if ( isset(self::$thisVariables[ $value[PHPTAGS_STACK_PARAM] ]) 
|| array_key_exists($value[PHPTAGS_STACK_PARAM], self::$thisVariables) ) {
+                       $value[PHPTAGS_STACK_PARAM_2][$aim] =& 
self::$thisVariables[ $value[PHPTAGS_STACK_PARAM] ];
+                       if ( isset($value[PHPTAGS_STACK_ARRAY_INDEX]) ) { // 
Example: $foo[1]
+                               foreach ( $value[PHPTAGS_STACK_ARRAY_INDEX] as 
$v ) {
+                                       if ( is_array( 
$value[PHPTAGS_STACK_PARAM_2][$aim] ) ) {
+                                               if ( 
isset($value[PHPTAGS_STACK_PARAM_2][$aim][$v]) || array_key_exists($v, 
$value[PHPTAGS_STACK_PARAM_2][$aim]) ) {
+                                                       
$value[PHPTAGS_STACK_PARAM_2][$aim] =& $value[PHPTAGS_STACK_PARAM_2][$aim][$v];
+                                               } else {
+                                                       // PHP Notice:  
Undefined offset: $1
+                                                       self::pushException( 
new PhpTagsException( PhpTagsException::NOTICE_UNDEFINED_INDEX, $v ) );
+                                                       unset( 
$value[PHPTAGS_STACK_PARAM_2][$aim] );
+                                                       
$value[PHPTAGS_STACK_PARAM_2][$aim] = null;
+                                               }
+                                       } else {
+                                               if ( isset( 
$value[PHPTAGS_STACK_PARAM_2][$aim][$v]) ) {
+                                                       unset( 
$value[PHPTAGS_STACK_PARAM_2][$aim] );
+                                                       
$value[PHPTAGS_STACK_PARAM_2][$aim] = $value[PHPTAGS_STACK_PARAM_2][$aim][$v];
+                                               } else {
+                                                       // PHP Notice:  
Uninitialized string offset: $1
+                                                       self::pushException( 
new PhpTagsException( PhpTagsException::NOTICE_UNINIT_STRING_OFFSET, (int)$v ) 
);
+                                                       unset( 
$value[PHPTAGS_STACK_PARAM_2][$aim] );
+                                                       
$value[PHPTAGS_STACK_PARAM_2][$aim] = null;
+                                               }
+                                       }
+                               }
+                       }
+               } else {
+                       unset( $value[PHPTAGS_STACK_PARAM_2][$aim] );
+                       $value[PHPTAGS_STACK_PARAM_2][$aim] = null;
+                       Runtime::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_UNDEFINED_VARIABLE, $value[PHPTAGS_STACK_PARAM] ) );
+               }
+       }
+
+       /**
+        * PHPTAGS_T_TERNARY
+        * @param array $value
+        */
+       private static function doTernary ( $value ) {
+               if( $value[PHPTAGS_STACK_PARAM] ) { // true ?
+                       if( 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_DO_TRUE] ) { // true ? 1+2 :
+                               self::pushDown( 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_DO_TRUE], '?', 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_PARAM] );
+                       }else{ // true ? 1 :
+                               $value[PHPTAGS_STACK_RESULT] = 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_PARAM];
+                       }
+               }else{ // false ?
+                       if( 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_DO_FALSE] ) { // false ? ... : 1+2
+                               self::pushDown( 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_DO_FALSE], '?', 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_PARAM_2] );
+                       }else{ // false ? ... : 1
+                               $value[PHPTAGS_STACK_RESULT] = 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_PARAM_2];
+                       }
+               }
+       }
+
+       /**
+        * PHPTAGS_T_IF
+        * @param array $value
+        */
+       private static function doIf ( $value ) {
+               $return = null;
+               if( $value[PHPTAGS_STACK_PARAM] ) { // Example: if( true )
+                       if( $value[PHPTAGS_STACK_DO_TRUE] ) { // Stack not 
empty: if(true);
+                               self::pushDown( $value[PHPTAGS_STACK_DO_TRUE], 
T_IF, $return );
+                       }
+               }else{ // Example: if( false )
+                       if( isset($value[PHPTAGS_STACK_DO_FALSE]) ) { // Stack 
not empty: if(false) ; else ;
+                               self::pushDown( $value[PHPTAGS_STACK_DO_FALSE], 
T_IF, $return );
+                       }
+               }
+       }
+
+       /**
+        * PHPTAGS_T_FOREACH
+        * @param array $value
+        */
+       private static function doForeach ( $value ) {
+               if ( !is_array($value[PHPTAGS_STACK_PARAM]) ) {
+                       self::pushException( new PhpTagsException( 
PhpTagsException::WARNING_INVALID_ARGUMENT_FOR_FOREACH, null ) );
+                       return;
+               }
+               reset( $value[PHPTAGS_STACK_PARAM] );
+               $null = null;
+               self::pushDown( $value[PHPTAGS_STACK_DO_TRUE], T_WHILE, $null );
+       }
+
+       /**
+        * PHPTAGS_T_WHILE
+        * @param array $value
+        */
+       private static function doWhile ( $value ) {
+               $null = null;
+               self::pushDown( $value[PHPTAGS_STACK_DO_TRUE], T_WHILE, $null );
+       }
+
+       /**
+        * PHPTAGS_T_AS
+        * @param array $value
+        */
+       private static function doAs ( $value ) {
+               if ( !is_array($value[PHPTAGS_STACK_RESULT]) ) {
+                       Runtime::pushException( new PhpTagsException( 
PhpTagsException::WARNING_INVALID_ARGUMENT_FOR_FOREACH, null ) );
+                       return;
+               }
+               if ( isset($value[PHPTAGS_STACK_PARAM_2]) ) { // T_DOUBLE_ARROW 
Example: while ( $foo as $key=>$value )
+                       if ( !list(self::$thisVariables[ 
$value[PHPTAGS_STACK_PARAM] ], self::$thisVariables[ 
$value[PHPTAGS_STACK_PARAM_2] ]) = each($value[PHPTAGS_STACK_RESULT]) ) {
+                               self::popUp();
+                       }
+               } else { // Example: while ( $foo as $value )
+                       if ( !list(,self::$thisVariables[ 
$value[PHPTAGS_STACK_PARAM] ]) = each($value[PHPTAGS_STACK_RESULT]) ) {
+                               self::popUp();
+                       }
+               }
+       }
+
+       /**
+        * PHPTAGS_T_BREAK
+        * @param array $value
+        */
+       private static function doBreak ( $value ) {
+               $loopsOwner =& self::$loopsOwner;
+               $memory =& self::$memory;
+               $originalBreak = $break = $value[PHPTAGS_STACK_RESULT];
+
+               for ( ; ; ) {
+                       if ( $loopsOwner === T_WHILE ) {
+                               --$break;
+                       }
+                       self::popUp();
+                       if ( $break === 0 ) {
+                               return;
+                       } elseif ( count( $memory ) === 0 ) {
+                               if ( $break > 1 ) {
+                                       throw new PhpTagsException( 
PhpTagsException::FATAL_WRONG_BREAK_LEVELS, $originalBreak );
+                               }
+                               return;
+                       }
+               }
+       }
+
+       /**
+        * PHPTAGS_T_CONTINUE
+        * @param array $value
+        */
+       private static function doContinue ( $value ) {
+               if( self::$loopsLimit-- <= 0 ) {
+                       throw new PhpTagsException( 
PhpTagsException::FATAL_LOOPS_LIMIT_REACHED, null, 
$value[PHPTAGS_STACK_TOKEN_LINE], $place );
+               }
+               $loopsOwner =& self::$loopsOwner;
+               $memory =& self::$memory;
+               $originalBreak = $break = $value[PHPTAGS_STACK_RESULT] - 1;
+
+               for ( ; ; ) {
+                       if ( $loopsOwner === T_WHILE ) {
+                               if ( $break > 0 ) {
+                                       --$break;
+                               } else {
+                                       break;
+                               }
+                       }
+                       self::popUp();
+                       if ( count( $memory ) === 0 && $break > 0 ) {
+                               throw new PhpTagsException( 
PhpTagsException::FATAL_WRONG_BREAK_LEVELS, $originalBreak );
+                       }
+               }
+               self::$runIndex = -1;
+       }
+
+       /**
+        * PHPTAGS_T_ARRAY inits new array
+        * @param array $value
+        */
+       private static function doArray ( $value ) {
+               $newArray = $value[PHPTAGS_STACK_PARAM][0];
+               $i = 1;
+               foreach ( $value[PHPTAGS_STACK_PARAM_2] as $t ) {
+                       list ( $k, $v ) = $t;
+                       $newArray[$k] = $v;
+                       if ( isset($value[PHPTAGS_STACK_PARAM][$i]) ) {
+                               foreach ( $value[PHPTAGS_STACK_PARAM][$i] as $n 
) {
+                                       $newArray[] = $n;
+                               }
+                       }
+                       ++$i;
+               }
+               $value[PHPTAGS_STACK_RESULT] = $newArray;
+       }
+
+       /**
+        * PHPTAGS_T_STATIC inits static variables
+        * @param array $value
+        */
+       private static function doStatic ( $value ) {
+               $name = $value[PHPTAGS_STACK_PARAM]; // variable name
+               if( !isset(self::$staticVariables[self::$place]) || 
!array_key_exists($name, self::$staticVariables[self::$place]) ) {
+                       self::$staticVariables[self::$place][$name] = 
$value[PHPTAGS_STACK_RESULT];
+                       if ( $value[PHPTAGS_STACK_DO_TRUE] ) {
+                               $null = null;
+                               self::pushDown( $value[PHPTAGS_STACK_DO_TRUE], 
T_STATIC, $null );
+                       }
+               }
+               self::$thisVariables[$name] =& 
self::$staticVariables[self::$place][$name];
+       }
+
+       /**
+        * PHPTAGS_T_GLOBAL inits global variables
+        * @param array $value
+        */
+       private static function doGlobal ( $value ) {
+               $gVars =& self::$globalVariables;
+               foreach( $value[PHPTAGS_STACK_PARAM] as $name ) { // variable 
names
+                       if( !array_key_exists($name, $gVars) ) {
+                               $gVars[$name] = null;
+                       }
+                       self::$thisVariables[$name] =& $gVars[$name];
+               }
+       }
+
+       /**
+        * PHPTAGS_T_HOOK_CHECK_PARAM checks param for hooks
+        * @param array $value
+        */
+       private static function doCheckingParam ( $value ) {
+               $i = $value[PHPTAGS_STACK_AIM];
+               $reference_info = Hooks::getReferenceInfo(
+                               $i, // ordinal number of the argument, zero is 
first
+                               $value[PHPTAGS_STACK_HOOK_TYPE],
+                               $value[PHPTAGS_STACK_PARAM], // name of 
function or method
+                               $value[PHPTAGS_STACK_PARAM_3] === false ? false 
: $value[PHPTAGS_STACK_PARAM_3][PHPTAGS_STACK_PARAM_3] // $object or false
+                       );
+
+               if ( $value[PHPTAGS_STACK_PARAM_2] === true && $reference_info 
=== false ) {
+                       // Param is variable and it needs to clone
+                       $t = $value[PHPTAGS_STACK_RESULT][$i];
+                       unset( $value[PHPTAGS_STACK_RESULT][$i] );
+                       $value[PHPTAGS_STACK_RESULT][$i] = $t;
+               } elseif ( $value[PHPTAGS_STACK_PARAM_2] === false && 
$reference_info === true ) {
+                       // Param is not variable and it's need reference
+                       throw new PhpTagsException( 
PhpTagsException::FATAL_VALUE_PASSED_BY_REFERENCE, null, 
$value[PHPTAGS_STACK_TOKEN_LINE], $place );
+               }
+       }
+
+       /**
+        * PHPTAGS_T_HOOK calls hook
+        * @param array $value
+        */
+       private static function doCallingHook ( $value ) {
+               $result = Hooks::callHook(
+                               $value[PHPTAGS_STACK_HOOK_TYPE],
+                               $value[PHPTAGS_STACK_PARAM_2], // arguments
+                               $value[PHPTAGS_STACK_PARAM], // name of 
function or method
+                               $value[PHPTAGS_STACK_PARAM_3] // $object or 
false
+                       );
+
+               if ( $result instanceof outPrint ) {
+                       $value[PHPTAGS_STACK_RESULT] = $result->returnValue;
+                       self::$return[] = $result;
+               } else {
+                       $value[PHPTAGS_STACK_RESULT] = $result;
+               }
+               if ( is_object($value[PHPTAGS_STACK_RESULT]) && 
!($value[PHPTAGS_STACK_RESULT] instanceof iRawOutput || 
$value[PHPTAGS_STACK_RESULT] instanceof GenericObject) ) {
+                       // @todo
+                       $value[PHPTAGS_STACK_RESULT] = null;
+                       Runtime::pushException( new PhpTagsException( 
PhpTagsException::WARNING_RETURNED_INVALID_VALUE, $value[PHPTAGS_STACK_PARAM] ) 
);
+               }
+       }
+
+       /**
+        * PHPTAGS_T_NEW creates new object
+        * @param array $value
+        */
+       private static function doNewObject ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = Hooks::createObject( 
$value[PHPTAGS_STACK_PARAM_2], $value[PHPTAGS_STACK_PARAM_3] );
+       }
+
+       /**
+        * PHPTAGS_T_UNSET unsets variables
+        * @param array $value
+        */
+       private static function doUnset ( $value ) {
+               $thisVariables =& self::$thisVariables;
+               foreach ( $value[PHPTAGS_STACK_PARAM] as $val ) {
+                       $name = $val[PHPTAGS_STACK_PARAM]; // Variable Name
+                       if ( isset($thisVariables[$name]) || 
array_key_exists($name, $thisVariables) ) { // defined variable
+                               if ( isset($val[PHPTAGS_STACK_ARRAY_INDEX]) ) { 
// There is array index. Example: unset($foo[0])
+                                       $ref =& $thisVariables[$name];
+                                       $tmp = array_pop( 
$val[PHPTAGS_STACK_ARRAY_INDEX] );
+                                       foreach ( 
$val[PHPTAGS_STACK_ARRAY_INDEX] as $v ) {
+                                               if ( is_string($ref) ) {
+                                                       throw new 
PhpTagsException( PhpTagsException::FATAL_CANNOT_UNSET_STRING_OFFSETS, null, 
$value[PHPTAGS_STACK_TOKEN_LINE], $place );
+                                               } elseif ( !isset($ref[$v]) ) { 
// undefined array index not for string
+                                                       continue 2;
+                                               }
+                                               $ref =& $ref[$v];
+                                       }
+                                       if ( is_array($ref) ) {
+                                               unset( $ref[$tmp] );
+                                       } else {
+                                               throw new PhpTagsException( 
PhpTagsException::FATAL_CANNOT_UNSET_STRING_OFFSETS, null, 
$value[PHPTAGS_STACK_TOKEN_LINE], $place );
+                                       }
+                               }else{ // There is no array index. Example: 
unset($foo)
+                                       unset( $thisVariables[$name] );
+                               }
+                       } elseif ( isset($val[PHPTAGS_STACK_ARRAY_INDEX]) ) { 
// undefined variable with array index. Example: unset($foo[1])
+                               self::pushException( new PhpTagsException( 
PHPTAGS_NOTICE_UNDEFINED_VARIABLE, $name ) );
+                       }
+               }
+       }
+
+       /**
+        * PHPTAGS_T_ISSET returns TRUE when variables are set
+        * @param array $value
+        */
+       private static function doIsSet ( $value ) {
+               $thisVariables =& self::$thisVariables;
+               foreach($value[PHPTAGS_STACK_PARAM] as $val) {
+                       if( !isset($thisVariables[ $val[PHPTAGS_STACK_PARAM] ]) 
) { // undefined variable or variable is null
+                               $value[PHPTAGS_STACK_RESULT] = false;
+                               return;
+                       } // true, variable is defined
+                       if( isset($val[PHPTAGS_STACK_ARRAY_INDEX]) ) { // 
Example: isset($foo[1])
+                               $ref =& $thisVariables[ 
$val[PHPTAGS_STACK_PARAM] ];
+                               $tmp = array_pop( 
$val[PHPTAGS_STACK_ARRAY_INDEX] );
+                               foreach( $val[PHPTAGS_STACK_ARRAY_INDEX] as $v 
) {
+                                       if( !isset($ref[$v]) ) { // undefined 
array index
+                                               $value[PHPTAGS_STACK_RESULT] = 
false;
+                                               return;
+                                       }
+                                       $ref =& $ref[$v];
+                               }
+                               // @todo ->>>>>>>>>>>> | 
************************************************************* | <<<<< it only 
for compatible with PHP 5.4 if used PHP 5.3 @see 
http://www.php.net/manual/en/function.isset.php Example #2 isset() on String 
Offsets
+                               if( !isset($ref[$tmp]) || (is_string($ref) && 
is_string($tmp ) && $tmp  != (string)(int)$tmp ) ) {
+                                       $value[PHPTAGS_STACK_RESULT] = false;
+                                       return;
+                               }
+                       } // true, variable is defined and have no array index
+               }
+               $value[PHPTAGS_STACK_RESULT] = true;
+       }
+
+       /**
+        * PHPTAGS_T_EMPTY returns TRUE when variables are empty
+        * @param array $value
+        */
+       private static function doIsEmpty ( $value ) {
+               $thisVariables =& self::$thisVariables;
+               foreach($value[PHPTAGS_STACK_PARAM] as $val) {
+                       if( !array_key_exists($val[PHPTAGS_STACK_PARAM], 
$thisVariables) ) { // undefined variable
+                               continue;
+                       }
+                       $ref =& $thisVariables[ $val[PHPTAGS_STACK_PARAM] ];
+                       if( isset($val[PHPTAGS_STACK_ARRAY_INDEX]) ) { // 
Example: empty($foo[1])
+                               $tmp = array_pop( 
$val[PHPTAGS_STACK_ARRAY_INDEX] );
+                               foreach( $val[PHPTAGS_STACK_ARRAY_INDEX] as $v 
) {
+                                       if( !isset($ref[$v]) ) { // undefined 
array index
+                                               continue 2;
+                                       }
+                                       $ref = &$ref[$v];
+                               }
+                               // @todo ->>>>>>>>>>>> | 
************************************************************* | <<<<< it only 
for compatible with PHP 5.4 if used PHP 5.3 @see 
http://www.php.net/manual/en/function.empty.php Example #2 empty() on String 
Offsets
+                               if( !empty($ref[$tmp]) && (is_array($ref) || 
!is_string( $tmp ) || $tmp  == (string)(int)$tmp ) ) {
+                                       $value[PHPTAGS_STACK_RESULT] = false;
+                                       return;
+                               }
+                       }elseif( !empty($ref) ) { // there is no array index 
and empty() returns false (PHP 5.5.0 supports expressions)
+                               $value[PHPTAGS_STACK_RESULT] = false;
+                               return;
+                       }
+               }
+               $value[PHPTAGS_STACK_RESULT] = true;
+       }
+
+       /**
+        * PHPTAGS_T_RETURN is designed for compiler only!
+        * @param array $value
+        */
+       private static function doReturn ( $value ) {
+               self::$return = self::$return ? new PhpTagsException() : 
$value[PHPTAGS_STACK_PARAM];
+       }
+
+       /**
+        * PHPTAGS_T_COPY copies value from variable to destination
+        * @param array $value
+        */
+       private static function doCopy ( $value ) {
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM];
+       }
+
+       /**
+        * PHPTAGS_T_IGNORE_ERROR
+        * @param array $value
+        */
+       private static function doIgnoreErrors ( $value ) {
+               self::$ignoreErrors = $value[PHPTAGS_STACK_PARAM];
+       }
+
+       /**
+        * PHPTAGS_T_LIST
+        * @param array $value
+        */
+       private static function doList ( $value ) {
+               self::fillList( $value[PHPTAGS_STACK_PARAM_2], 
$value[PHPTAGS_STACK_PARAM], self::$thisVariables );
+               $value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_INC
+        * @param array $value
+        */
+       private static function doIncrease ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               if ( $value[PHPTAGS_STACK_PARAM_2] ) { // $foo++
+                       $value[PHPTAGS_STACK_RESULT] = $ref++;
+               }else{ // ++$foo
+                       $value[PHPTAGS_STACK_RESULT] = ++$ref;
+               }
+       }
+
+       /**
+        * PHPTAGS_T_DEC
+        * @param array $value
+        */
+       private static function doDecrease ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               if ( $value[PHPTAGS_STACK_PARAM_2] ) { // $foo--
+                       $value[PHPTAGS_STACK_RESULT] = $ref--;
+               }else{ // --$foo
+                       $value[PHPTAGS_STACK_RESULT] = --$ref;
+               }
+       }
+
+       /**
+        * PHPTAGS_T_EQUAL
+        * @param array $value
+        */
+       private static function doSetVal ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               $value[PHPTAGS_STACK_RESULT] = $ref = 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_CONCAT_EQUAL
+        * @param array $value
+        */
+       private static function doSetConcatVal ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               $value[PHPTAGS_STACK_RESULT] = $ref .= 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_PLUS_EQUAL
+        * @param array $value
+        */
+       private static function doSetPlusVal ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               $value[PHPTAGS_STACK_RESULT] = $ref += 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_MINUS_EQUAL
+        * @param array $value
+        */
+       private static function doSetMinusVal ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               $value[PHPTAGS_STACK_RESULT] = $ref -= 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_MUL_EQUAL
+        * @param array $value
+        */
+       private static function doSetMulVal ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               $value[PHPTAGS_STACK_RESULT] = $ref *= 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_DIV_EQUAL
+        * @param array $value
+        */
+       private static function doSetDivVal ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               $value[PHPTAGS_STACK_RESULT] = $ref /= 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_MOD_EQUAL
+        * @param array $value
+        */
+       private static function doSetModVal ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               $value[PHPTAGS_STACK_RESULT] = $ref %= 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_AND_EQUAL
+        * @param array $value
+        */
+       private static function doSetAndVal ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               $value[PHPTAGS_STACK_RESULT] = $ref &= 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_OR_EQUAL
+        * @param array $value
+        */
+       private static function doSetOrVal ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               $value[PHPTAGS_STACK_RESULT] = $ref |= 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_XOR_EQUAL
+        * @param array $value
+        */
+       private static function doSetXorVal ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               $value[PHPTAGS_STACK_RESULT] = $ref ^= 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_SL_EQUAL
+        * @param array $value
+        */
+       private static function doSetShiftLeftVal ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               $value[PHPTAGS_STACK_RESULT] = $ref <<= 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       /**
+        * PHPTAGS_T_SR_EQUAL
+        * @param array $value
+        */
+       private static function doSetShiftRightVal ( $value ) {
+               $ref =& self::getVariableRef( $value );
+               $value[PHPTAGS_STACK_RESULT] = $ref <<= 
$value[PHPTAGS_STACK_PARAM_2];
+       }
+
+       private static function & getVariableRef( $value ) {
+               $thisVariables =& self::$thisVariables;
+               $variable = $value[PHPTAGS_STACK_PARAM];
+               $variableName = $variable[PHPTAGS_STACK_PARAM];
+               if( !(isset($thisVariables[$variableName]) || 
array_key_exists($variableName, $thisVariables)) ) { // Use undefined variable
+                       if( isset($value[PHPTAGS_STACK_ARRAY_INDEX]) ) { // 
Example: $foo[1]++
+                               $thisVariables[$variableName] = array();
+                       }else{
+                               $thisVariables[$variableName] = null;
+                       }
+                       if( $value[PHPTAGS_STACK_COMMAND] !== PHPTAGS_T_EQUAL ) 
{
+                               Runtime::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_UNDEFINED_VARIABLE, $variableName ) );
+                       }
+               }
+               $ref =& $thisVariables[$variableName];
+               if ( isset($variable[PHPTAGS_STACK_ARRAY_INDEX]) ) { // 
Example: $foo[1]++
+                       foreach ( $variable[PHPTAGS_STACK_ARRAY_INDEX] as $v ) {
+                               if ( $v === INF ) { // Example: $foo[]
+                                       $t = null;
+                                       $ref[] = &$t;
+                                       $ref = &$t;
+                                       unset( $t );
+                               } else {
+                                       if ( $ref === null ) {
+                                               if( 
$value[PHPTAGS_STACK_COMMAND] !== PHPTAGS_T_EQUAL ) {
+                                                       // PHP Notice:  
Undefined offset: $1
+                                                       Runtime::pushException( 
new PhpTagsException( PhpTagsException::NOTICE_UNDEFINED_OFFSET, 
$v[PHPTAGS_STACK_RESULT] ) );
+                                               }
+                                               $ref[$v] = null;
+                                               $ref =& $ref[$v];
+                                       } elseif ( is_array($ref) ) {
+                                               if ( !( isset($ref[$v]) || 
array_key_exists($v, $ref) ) ) {
+                                                       $ref[$v] = null;
+                                                       if( 
$value[PHPTAGS_STACK_COMMAND] !== PHPTAGS_T_EQUAL ) {
+                                                               // PHP Notice:  
Undefined offset: $1
+                                                               
Runtime::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_UNDEFINED_INDEX, $v ) );
+                                                       }
+                                               }
+                                               $ref =& $ref[$v];
+                                       } elseif ( is_string($ref) ) {
+                                               // PHP Fatal error:  Cannot use 
string offset as an array
+                                               throw new PhpTagsException( 
PhpTagsException::NOTICE_UNDEFINED_OFFSET, $v, 
$value[PHPTAGS_STACK_TOKEN_LINE], $place );
+                                       } else {
+                                               Runtime::pushException( new 
PhpTagsException( PhpTagsException::FATAL_STRING_OFFSET_AS_ARRAY, $v ) );
+                                               break 2;
+                                               // PHP Warning:  Cannot use a 
scalar value as an array
+                                       }
+                               }
+                       }
+               }
+               return $ref;
+       }
+
        public static function run( $code, array $args, $scope = '' ) {
                set_error_handler( '\\PhpTags\\ErrorHandler::onError' );
                try {
-                       if( !isset(self::$variables[$scope]) ) {
+                       self::$scope = $scope;
+                       self::$running = $code;
+                       self::$memory = array();
+                       self::$return = array();
+                       self::$loopsOwner = null;
+                       self::$place = isset($args[0]) ? $args[0] : ''; // Page 
name for static variables and error messages
+                       self::$c = count( $code );
+                       if( false === isset(self::$variables[$scope]) ) {
                                self::$variables[$scope] = array();
                        }
-                       self::$scope = $scope;
-                       $thisVariables =& self::$variables[$scope];
-                       $thisVariables['argv'] = $args;
-                       $thisVariables['argc'] = count($args);
-                       $thisVariables['GLOBALS'] = &self::$globalVariables;
-                       $exceptions =& self::$exceptions;
-                       $memory=array();
-                       $return = array();
-                       $break = 0; // used for T_BREAK
-                       $continue = false; // used for T_CONTINUE
-                       $loopsOwner = null;
-                       $place = isset($args[0]) ? $args[0] : ''; // Page name 
for static variables and error messages
+                       self::$thisVariables =& self::$variables[$scope];
+                       self::$thisVariables['argv'] = $args;
+                       self::$thisVariables['argc'] = count($args);
+                       self::$thisVariables['GLOBALS'] =& 
self::$globalVariables;
 
-                       $c = count( $code );
-                       $codeIndex=-1;
+                       $runCode =& self::$running;
+                       $runIndex =& self::$runIndex;
+                       $loopsOwner =& self::$loopsOwner;
+                       $memory =& self::$memory;
+                       $c =& self::$c;
+                       $operators = self::$operators;
 
+                       $runIndex = -1;
                        do {
-                               if ( $break ) {
-                                       if ( $loopsOwner == T_WHILE ) {
-                                               $break--;
-                                               continue;
-                                       }
-                                       break;
-                               } elseif ( $continue ) {
-                                       if ( $loopsOwner == T_WHILE ) {
-                                               $codeIndex = -1;
-                                               $continue = false;
-                                       } else {
-                                               continue;
-                                       }
+                               for ( ++$runIndex; $runIndex < $c; ++$runIndex 
) {
+                                       $value =& $runCode[$runIndex];
+                                       $call = $operators[ 
$value[PHPTAGS_STACK_COMMAND] ];
+                                       self::$call( $value );
                                }
-                               $codeIndex++;
-                               for ( ; $codeIndex < $c; $codeIndex++ ) {
-                                       $value =& $code[$codeIndex];
-                                       switch ( $value[PHPTAGS_STACK_COMMAND] 
) {
-                                               case '"': // Example: echo 
"abc$foo";
-                                                       
$value[PHPTAGS_STACK_RESULT] = implode( $value[PHPTAGS_STACK_PARAM] );
-                                                       break;
-                                               case '.':
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] . 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case '+':
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] + 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case '-':
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] - 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case '*':
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] * 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case '/':
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] / 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case '%':
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] % 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case '&':
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] & 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case '|':
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] | 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case '^':
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] ^ 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_SL:              
        // <<
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] << 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_SR:              
        // >>
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] >> 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_LOGICAL_AND:     
// and
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] && 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_LOGICAL_XOR:     
// xor
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] xor 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_LOGICAL_OR:      
// or
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] || 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case '<':
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] < 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case '>':
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] > 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case 
PHPTAGS_T_IS_SMALLER_OR_EQUAL:     // <=
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] <= 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case 
PHPTAGS_T_IS_GREATER_OR_EQUAL:     // >=
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] >= 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_IS_EQUAL:        
                // ==
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] == 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_IS_NOT_EQUAL:    
        // !=
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] != 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_IS_IDENTICAL:    
        // ===
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] === 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case 
PHPTAGS_T_IS_NOT_IDENTICAL:        // !==
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM] !== 
$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_PRINT:
-                                                       if( 
$value[PHPTAGS_STACK_PARAM] instanceof GenericObject ) {
-                                                               $return[] = 
$value[PHPTAGS_STACK_PARAM]->toString();
-                                                       } else {
-                                                               $return[] = 
$value[PHPTAGS_STACK_PARAM];
-                                                       }
-                                                       break;
-                                               case '~':
-                                                       
$value[PHPTAGS_STACK_RESULT] = ~$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case '!':
-                                                       
$value[PHPTAGS_STACK_RESULT] = !$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_INT_CAST:        
        // (int)
-                                                       
$value[PHPTAGS_STACK_RESULT] = (int)$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_DOUBLE_CAST:     
        // (double)
-                                                       
$value[PHPTAGS_STACK_RESULT] = (double)$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_STRING_CAST:     
        // (string)
-                                                       
$value[PHPTAGS_STACK_RESULT] = (string)$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_ARRAY_CAST:      
        // (array)
-                                                       
$value[PHPTAGS_STACK_RESULT] = (array)$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_BOOL_CAST:       
        // (bool)
-                                                       
$value[PHPTAGS_STACK_RESULT] = (bool)$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_UNSET_CAST:      
        // (unset)
-                                                       
$value[PHPTAGS_STACK_RESULT] = (unset)$value[PHPTAGS_STACK_PARAM_2];
-                                                       break;
-                                               case PHPTAGS_T_VARIABLE:
-                                                       $aim = 
$value[PHPTAGS_STACK_AIM];
-                                                       if ( 
isset($thisVariables[ $value[PHPTAGS_STACK_PARAM] ]) || 
array_key_exists($value[PHPTAGS_STACK_PARAM], $thisVariables) ) {
-                                                               
$value[PHPTAGS_STACK_PARAM_2][$aim] =& $thisVariables[ 
$value[PHPTAGS_STACK_PARAM] ];
-                                                               if ( 
isset($value[PHPTAGS_STACK_ARRAY_INDEX]) ) { // Example: $foo[1]
-                                                                       foreach 
( $value[PHPTAGS_STACK_ARRAY_INDEX] as $v ) {
-                                                                               
if ( is_array( $value[PHPTAGS_STACK_PARAM_2][$aim] ) ) {
-                                                                               
        if ( isset($value[PHPTAGS_STACK_PARAM_2][$aim][$v]) || 
array_key_exists($v, $value[PHPTAGS_STACK_PARAM_2][$aim]) ) {
-                                                                               
                $value[PHPTAGS_STACK_PARAM_2][$aim] =& 
$value[PHPTAGS_STACK_PARAM_2][$aim][$v];
-                                                                               
        } else {
-                                                                               
                // PHP Notice:  Undefined offset: $1
-                                                                               
                self::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_UNDEFINED_INDEX, $v ) );
-                                                                               
                unset( $value[PHPTAGS_STACK_PARAM_2][$aim] );
-                                                                               
                $value[PHPTAGS_STACK_PARAM_2][$aim] = null;
-                                                                               
        }
-                                                                               
} else {
-                                                                               
        if ( isset( $value[PHPTAGS_STACK_PARAM_2][$aim][$v]) ) {
-                                                                               
                unset( $value[PHPTAGS_STACK_PARAM_2][$aim] );
-                                                                               
                $value[PHPTAGS_STACK_PARAM_2][$aim] = 
$value[PHPTAGS_STACK_PARAM_2][$aim][$v];
-                                                                               
        } else {
-                                                                               
                // PHP Notice:  Uninitialized string offset: $1
-                                                                               
                self::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_UNINIT_STRING_OFFSET, (int)$v ) );
-                                                                               
                unset( $value[PHPTAGS_STACK_PARAM_2][$aim] );
-                                                                               
                $value[PHPTAGS_STACK_PARAM_2][$aim] = null;
-                                                                               
        }
-                                                                               
}
-                                                                       }
-                                                               }
-                                                       } else {
-                                                               unset( 
$value[PHPTAGS_STACK_PARAM_2][$aim] );
-                                                               
$value[PHPTAGS_STACK_PARAM_2][$aim] = null;
-                                                               
self::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_UNDEFINED_VARIABLE, $value[PHPTAGS_STACK_PARAM] ) );
-                                                       }
-                                                       break;
-                                               case '?':
-                                                       if( 
$value[PHPTAGS_STACK_PARAM] ) { // true ?
-                                                               if( 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_DO_TRUE] ) { // true ? 1+2 :
-                                                                       
$memory[] = array( &$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_PARAM], $code, 
$codeIndex, $c, $loopsOwner );
-                                                                       $code = 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_DO_TRUE];
-                                                                       
$codeIndex = -1;
-                                                                       $c = 
count($code);
-                                                                       
$loopsOwner = '?';
-                                                               }else{ // true 
? 1 :
-                                                                       
$value[PHPTAGS_STACK_RESULT] = 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_PARAM];
-                                                               }
-                                                       }else{ // false ?
-                                                               if( 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_DO_FALSE] ) { // false ? ... : 1+2
-                                                                       
$memory[] = array( &$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_PARAM_2], 
$code, $codeIndex, $c, $loopsOwner );
-                                                                       $code = 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_DO_FALSE];
-                                                                       
$codeIndex = -1;
-                                                                       $c = 
count($code);
-                                                                       
$loopsOwner = '?';
-                                                               }else{ // false 
? ... : 1
-                                                                       
$value[PHPTAGS_STACK_RESULT] = 
$value[PHPTAGS_STACK_PARAM_2][PHPTAGS_STACK_PARAM_2];
-                                                               }
-                                                       }
-                                                       break;
-                                               case PHPTAGS_T_IF:
-                                                       if( 
$value[PHPTAGS_STACK_PARAM] ) { // Example: if( true )
-                                                               if( 
$value[PHPTAGS_STACK_DO_TRUE] ) { // Stack not empty: if(true);
-                                                                       
$memory[] = array( null, $code, $codeIndex, $c, $loopsOwner );
-                                                                       $code = 
$value[PHPTAGS_STACK_DO_TRUE];
-                                                                       
$codeIndex = -1;
-                                                                       $c = 
count($code);
-                                                                       
$loopsOwner = T_IF;
-                                                               }
-                                                       }else{ // Example: if( 
false )
-                                                               if( 
isset($value[PHPTAGS_STACK_DO_FALSE]) ) { // Stack not empty: if(false) ; else ;
-                                                                       
$memory[] = array( null, $code, $codeIndex, $c, $loopsOwner );
-                                                                       $code = 
$value[PHPTAGS_STACK_DO_FALSE];
-                                                                       
$codeIndex = -1;
-                                                                       $c = 
count($code);
-                                                                       
$loopsOwner = T_IF;
-                                                               }
-                                                       }
-                                                       break;
-                                               case PHPTAGS_T_FOREACH:
-                                                       if ( 
!is_array($value[PHPTAGS_STACK_PARAM]) ) {
-                                                               
self::pushException( new PhpTagsException( 
PhpTagsException::WARNING_INVALID_ARGUMENT_FOR_FOREACH, null ) );
-                                                               break; // **** 
EXIT ****
-                                                       }
-                                                       reset( 
$value[PHPTAGS_STACK_PARAM] );
-                                                       // break is not 
necessary here
-                                               case PHPTAGS_T_WHILE: // PHP 
code "while($foo) { ... }" doing as T_WHILE { T_DO($foo) ... }. If $foo == 
false, T_DO doing as T_BREAK
-                                                       $memory[] = array( 
null, $code, $codeIndex, $c, $loopsOwner );
-                                                       $code = 
$value[PHPTAGS_STACK_DO_TRUE];
-                                                       $codeIndex = -1;
-                                                       $c = count($code);
-                                                       $loopsOwner = T_WHILE;
-                                                       break;
-                                               case PHPTAGS_T_AS:
-                                                       if ( 
!is_array($value[PHPTAGS_STACK_RESULT]) ) {
-                                                               
self::pushException( new PhpTagsException( 
PhpTagsException::WARNING_INVALID_ARGUMENT_FOR_FOREACH, null ) );
-                                                               break; // **** 
EXIT ****
-                                                       }
-                                                       if ( 
isset($value[PHPTAGS_STACK_PARAM_2]) ) { // T_DOUBLE_ARROW Example: while ( 
$foo as $key=>$value )
-                                                               if ( 
!list($thisVariables[ $value[PHPTAGS_STACK_PARAM] ], $thisVariables[ 
$value[PHPTAGS_STACK_PARAM_2] ]) = each($value[PHPTAGS_STACK_RESULT]) ) {
-                                                                       break 
2; // go to one level down
-                                                               }
-                                                       } else { // Example: 
while ( $foo as $value )
-                                                               if ( 
!list(,$thisVariables[ $value[PHPTAGS_STACK_PARAM] ]) = 
each($value[PHPTAGS_STACK_RESULT]) ) {
-                                                                       break 
2; // go to one level down
-                                                               }
-                                                       }
-                                                       break;
-                                               case PHPTAGS_T_BREAK:
-                                                       $break = 
$value[PHPTAGS_STACK_RESULT];
-                                                       if( $loopsOwner == 
T_WHILE ) {
-                                                               $break--;
-                                                       }
-                                                       break 2; // go to one 
level down
-                                               case PHPTAGS_T_CONTINUE:
-                                                       if( self::$loopsLimit-- 
<= 0 ) {
-                                                               throw new 
PhpTagsException( PhpTagsException::FATAL_LOOPS_LIMIT_REACHED, null, 
$value[PHPTAGS_STACK_TOKEN_LINE], $place );
-                                                       }
-                                                       $break = 
$value[PHPTAGS_STACK_RESULT]-1;
-                                                       if( $loopsOwner == 
T_WHILE && $break == 0 ) { // Example: while(true) continue;
-                                                               $codeIndex = -1;
-                                                               break;
-                                                       }
-                                                       $continue = true;
-                                                       break 2; // go to one 
level down
-                                               case PHPTAGS_T_ARRAY:           
        // array
-                                                       $tmp = 
$value[PHPTAGS_STACK_PARAM][0];
-                                                       $i = 1;
-                                                       foreach ( 
$value[PHPTAGS_STACK_PARAM_2] as $t ) {
-                                                               list ( $k, $v ) 
= $t;
-                                                               $tmp[$k] = $v;
-                                                               if ( 
isset($value[PHPTAGS_STACK_PARAM][$i]) ) {
-                                                                       foreach 
( $value[PHPTAGS_STACK_PARAM][$i] as $n ) {
-                                                                               
$tmp[] = $n;
-                                                                       }
-                                                               }
-                                                               $i++;
-                                                       }
-                                                       
$value[PHPTAGS_STACK_RESULT] = $tmp;
-                                                       break;
-                                               case PHPTAGS_T_STATIC:
-                                                       $vn = 
$value[PHPTAGS_STACK_PARAM]; // variable name
-                                                       if( 
!isset(self::$staticVariables[$place]) || !array_key_exists($vn, 
self::$staticVariables[$place]) ) {
-                                                               
self::$staticVariables[$place][$vn] = &$value[PHPTAGS_STACK_RESULT];
-                                                               if( 
$value[PHPTAGS_STACK_DO_TRUE] ) {
-                                                                       
//self::$staticVariables[$p][$vn] = null;
-                                                                       
$memory[] = array( null, $code, $codeIndex, $c, $loopsOwner );
-                                                                       $code = 
$value[PHPTAGS_STACK_DO_TRUE];
-                                                                       
$codeIndex = -1;
-                                                                       $c = 
count($code);
-                                                                       
$loopsOwner = T_STATIC;
-                                                               }
-                                                       }
-                                                       $thisVariables[$vn] = 
&self::$staticVariables[$place][$vn];
-                                                       break;
-                                               case PHPTAGS_T_GLOBAL:
-                                                       foreach( 
$value[PHPTAGS_STACK_PARAM] as $vn ) { // variable names
-                                                               if( 
!array_key_exists($vn, self::$globalVariables) ) {
-                                                                       
self::$globalVariables[$vn] = null;
-                                                               }
-                                                               
$thisVariables[$vn] = &self::$globalVariables[$vn];
-                                                       }
-                                                       break;
-                                               case PHPTAGS_T_HOOK_CHECK_PARAM:
-                                                       $i = 
$value[PHPTAGS_STACK_AIM];
-                                                       $reference_info = 
Hooks::getReferenceInfo(
-                                                                       $i, // 
ordinal number of the argument, zero is first
-                                                                       
$value[PHPTAGS_STACK_HOOK_TYPE],
-                                                                       
$value[PHPTAGS_STACK_PARAM], // name of function or method
-                                                                       
$value[PHPTAGS_STACK_PARAM_3] === false ? false : 
$value[PHPTAGS_STACK_PARAM_3][PHPTAGS_STACK_PARAM_3] // $object or false
-                                                               );
-
-                                                       if ( 
$value[PHPTAGS_STACK_PARAM_2] === true && $reference_info === false ) {
-                                                               // Param is 
variable and it needs to clone
-                                                               $t = 
$value[PHPTAGS_STACK_RESULT][$i];
-                                                               unset( 
$value[PHPTAGS_STACK_RESULT][$i] );
-                                                               
$value[PHPTAGS_STACK_RESULT][$i] = $t;
-                                                       } elseif ( 
$value[PHPTAGS_STACK_PARAM_2] === false && $reference_info === true ) {
-                                                               // Param is not 
variable and it's need reference
-                                                               throw new 
PhpTagsException( PhpTagsException::FATAL_VALUE_PASSED_BY_REFERENCE, null, 
$value[PHPTAGS_STACK_TOKEN_LINE], $place );
-                                                       }
-                                                       break;
-                                               case PHPTAGS_T_HOOK:
-                                                       $result = 
Hooks::callHook(
-                                                                       
$value[PHPTAGS_STACK_HOOK_TYPE],
-                                                                       
$value[PHPTAGS_STACK_PARAM_2], // arguments
-                                                                       
$value[PHPTAGS_STACK_PARAM], // name of function or method
-                                                                       
$value[PHPTAGS_STACK_PARAM_3] // $object or false
-                                                               );
-
-                                                       if ( $result instanceof 
outPrint ) {
-                                                               
$value[PHPTAGS_STACK_RESULT] = $result->returnValue;
-                                                               $return[] = 
$result;
-                                                       } else {
-                                                               
$value[PHPTAGS_STACK_RESULT] = $result;
-                                                       }
-                                                       if ( 
is_object($value[PHPTAGS_STACK_RESULT]) && !($value[PHPTAGS_STACK_RESULT] 
instanceof iRawOutput || $value[PHPTAGS_STACK_RESULT] instanceof GenericObject) 
) {
-                                                               // @todo
-                                                               
$value[PHPTAGS_STACK_RESULT] = null;
-                                                               
self::pushException( new PhpTagsException( 
PhpTagsException::WARNING_RETURNED_INVALID_VALUE, $value[PHPTAGS_STACK_PARAM] ) 
);
-                                                       }
-                                                       break;
-                                               case PHPTAGS_T_NEW:
-                                                       
$value[PHPTAGS_STACK_RESULT] = Hooks::createObject( 
$value[PHPTAGS_STACK_PARAM_2], $value[PHPTAGS_STACK_PARAM_3] );
-                                                       break;
-                                               case PHPTAGS_T_UNSET:
-                                                       foreach ( 
$value[PHPTAGS_STACK_PARAM] as $val ) {
-                                                               $vn = 
$val[PHPTAGS_STACK_PARAM]; // Variable Name
-                                                               if ( 
isset($thisVariables[$vn]) || array_key_exists($vn, $thisVariables) ) { // 
defined variable
-                                                                       if ( 
isset($val[PHPTAGS_STACK_ARRAY_INDEX]) ) { // There is array index. Example: 
unset($foo[0])
-                                                                               
$ref = &$thisVariables[$vn];
-                                                                               
$tmp = array_pop( $val[PHPTAGS_STACK_ARRAY_INDEX] );
-                                                                               
foreach ( $val[PHPTAGS_STACK_ARRAY_INDEX] as $v ) {
-                                                                               
        if ( is_string($ref) ) {
-                                                                               
                throw new PhpTagsException( 
PhpTagsException::FATAL_CANNOT_UNSET_STRING_OFFSETS, null, 
$value[PHPTAGS_STACK_TOKEN_LINE], $place );
-                                                                               
        } elseif ( !isset($ref[$v]) ) { // undefined array index not for string
-                                                                               
                continue 2;
-                                                                               
        }
-                                                                               
        $ref = &$ref[$v];
-                                                                               
}
-                                                                               
if ( is_array($ref) ) {
-                                                                               
        unset( $ref[$tmp] );
-                                                                               
} else {
-                                                                               
        throw new PhpTagsException( 
PhpTagsException::FATAL_CANNOT_UNSET_STRING_OFFSETS, null, 
$value[PHPTAGS_STACK_TOKEN_LINE], $place );
-                                                                               
}
-                                                                       }else{ 
// There is no array index. Example: unset($foo)
-                                                                               
unset( $thisVariables[$vn] );
-                                                                       }
-                                                               } elseif ( 
isset($val[PHPTAGS_STACK_ARRAY_INDEX]) ) { // undefined variable with array 
index. Example: unset($foo[1])
-                                                                       
self::pushException( new PhpTagsException( PHPTAGS_NOTICE_UNDEFINED_VARIABLE, 
$vn ) );
-                                                               }
-                                                       }
-                                                       break;
-                                               case PHPTAGS_T_ISSET:
-                                                       
foreach($value[PHPTAGS_STACK_PARAM] as $val) {
-                                                               if( 
!isset($thisVariables[ $val[PHPTAGS_STACK_PARAM] ]) ) { // undefined variable 
or variable is null
-                                                                       
$value[PHPTAGS_STACK_RESULT] = false;
-                                                                       break 2;
-                                                               } // true, 
variable is defined
-                                                               if( 
isset($val[PHPTAGS_STACK_ARRAY_INDEX]) ) { // Example: isset($foo[1])
-                                                                       $ref = 
&$thisVariables[ $val[PHPTAGS_STACK_PARAM] ];
-                                                                       $tmp = 
array_pop( $val[PHPTAGS_STACK_ARRAY_INDEX] );
-                                                                       
foreach( $val[PHPTAGS_STACK_ARRAY_INDEX] as $v ) {
-                                                                               
if( !isset($ref[$v]) ) { // undefined array index
-                                                                               
        $value[PHPTAGS_STACK_RESULT] = false;
-                                                                               
        break 3;
-                                                                               
}
-                                                                               
$ref = &$ref[$v];
-                                                                       }
-                                                                       // 
@todo ->>>>>>>>>>>> | 
************************************************************* | <<<<< it only 
for compatible with PHP 5.4 if used PHP 5.3 @see 
http://www.php.net/manual/en/function.isset.php Example #2 isset() on String 
Offsets
-                                                                       if( 
!isset($ref[$tmp]) || (is_string($ref) && is_string($tmp ) && $tmp  != 
(string)(int)$tmp ) ) {
-                                                                               
$value[PHPTAGS_STACK_RESULT] = false;
-                                                                               
break 2;
-                                                                       }
-                                                               } // true, 
variable is defined and have no array index
-                                                       }
-                                                       
$value[PHPTAGS_STACK_RESULT] = true;
-                                                       break;
-                                               case PHPTAGS_T_EMPTY:
-                                                       
foreach($value[PHPTAGS_STACK_PARAM] as $val) {
-                                                               if( 
!array_key_exists($val[PHPTAGS_STACK_PARAM], $thisVariables) ) { // undefined 
variable
-                                                                       
continue;
-                                                               }
-                                                               $ref = 
&$thisVariables[ $val[PHPTAGS_STACK_PARAM] ];
-                                                               if( 
isset($val[PHPTAGS_STACK_ARRAY_INDEX]) ) { // Example: empty($foo[1])
-                                                                       $tmp = 
array_pop( $val[PHPTAGS_STACK_ARRAY_INDEX] );
-                                                                       
foreach( $val[PHPTAGS_STACK_ARRAY_INDEX] as $v ) {
-                                                                               
if( !isset($ref[$v]) ) { // undefined array index
-                                                                               
        continue 2;
-                                                                               
}
-                                                                               
$ref = &$ref[$v];
-                                                                       }
-                                                                       // 
@todo ->>>>>>>>>>>> | 
************************************************************* | <<<<< it only 
for compatible with PHP 5.4 if used PHP 5.3 @see 
http://www.php.net/manual/en/function.empty.php Example #2 empty() on String 
Offsets
-                                                                       if( 
!empty($ref[$tmp]) && (is_array($ref) || !is_string( $tmp ) || $tmp  == 
(string)(int)$tmp ) ) {
-                                                                               
$value[PHPTAGS_STACK_RESULT] = false;
-                                                                               
break 2;
-                                                                       }
-                                                               }elseif( 
!empty($ref) ) { // there is no array index and empty() returns false (PHP 
5.5.0 supports expressions)
-                                                                       
$value[PHPTAGS_STACK_RESULT] = false;
-                                                                       break 2;
-                                                               }
-                                                       }
-                                                       
$value[PHPTAGS_STACK_RESULT] = true;
-                                                       break;
-                                               case PHPTAGS_T_RETURN:
-                                                       if ( $return ) {
-                                                               return new 
PhpTagsException();
-                                                       }
-                                                       return 
$value[PHPTAGS_STACK_PARAM];
-                                               case PHPTAGS_T_COPY:
-                                                       
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM];
-                                                       break;
-                                               case '@':
-                                                       if ( 
$value[PHPTAGS_STACK_PARAM] === true ) {
-                                                               $exceptions = 
false;
-                                                       } else {
-                                                               $exceptions = 
array();
-                                                       }
-                                                       break;
-                                               default: // ++, --, =, +=, -=, 
*=, etc...
-                                                       $variable = 
&$value[PHPTAGS_STACK_PARAM];
-                                                       $variableName = 
$variable[PHPTAGS_STACK_PARAM];
-                                                       if ( 
$variable[PHPTAGS_STACK_COMMAND] == PHPTAGS_T_LIST ) { // this is T_LIST. 
Example: list($foo, $bar) = $array;
-                                                               self::fillList( 
$value[PHPTAGS_STACK_PARAM_2], $variable, $thisVariables );
-                                                               
$value[PHPTAGS_STACK_RESULT] = $value[PHPTAGS_STACK_PARAM_2];
-                                                               unset( 
$variable );
-                                                               break; /**** 
EXIT ****/
-                                                       }
-                                                       if( 
!(isset($thisVariables[$variableName]) || array_key_exists($variableName, 
$thisVariables)) ) { // Use undefined variable
-                                                               if( 
isset($value[PHPTAGS_STACK_ARRAY_INDEX]) ) { // Example: $foo[1]++
-                                                                       
$thisVariables[$variableName] = array();
-                                                               }else{
-                                                                       
$thisVariables[$variableName] = null;
-                                                               }
-                                                               if( 
$value[PHPTAGS_STACK_COMMAND] != '=' ) {
-                                                                       
self::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_UNDEFINED_VARIABLE, $variableName ) );
-                                                               }
-                                                       }
-                                                       $ref = 
&$thisVariables[$variableName];
-                                                       if ( 
isset($variable[PHPTAGS_STACK_ARRAY_INDEX]) ) { // Example: $foo[1]++
-                                                               foreach ( 
$variable[PHPTAGS_STACK_ARRAY_INDEX] as $v ) {
-                                                                       if ( $v 
=== INF ) { // Example: $foo[]
-                                                                               
$t = null;
-                                                                               
$ref[] = &$t;
-                                                                               
$ref = &$t;
-                                                                               
unset( $t );
-                                                                       } else {
-                                                                               
if ( $ref === null ) {
-                                                                               
        if( $value[PHPTAGS_STACK_COMMAND] != '=' ) {
-                                                                               
                // PHP Notice:  Undefined offset: $1
-                                                                               
                self::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_UNDEFINED_OFFSET, $v[PHPTAGS_STACK_RESULT] ) );
-                                                                               
        }
-                                                                               
        $ref[$v] = null;
-                                                                               
        $ref = &$ref[$v];
-                                                                               
} elseif ( is_array($ref) ) {
-                                                                               
        if ( !( isset($ref[$v]) || array_key_exists($v, $ref) ) ) {
-                                                                               
                $ref[$v] = null;
-                                                                               
                if( $value[PHPTAGS_STACK_COMMAND] != '=' ) {
-                                                                               
                        // PHP Notice:  Undefined offset: $1
-                                                                               
                        self::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_UNDEFINED_INDEX, $v ) );
-                                                                               
                }
-                                                                               
        }
-                                                                               
        $ref = &$ref[$v];
-                                                                               
} elseif ( is_string($ref) ) {
-                                                                               
        // PHP Fatal error:  Cannot use string offset as an array
-                                                                               
        throw new PhpTagsException( PhpTagsException::NOTICE_UNDEFINED_OFFSET, 
$v, $value[PHPTAGS_STACK_TOKEN_LINE], $place );
-                                                                               
} else {
-                                                                               
        self::pushException( new PhpTagsException( 
PhpTagsException::FATAL_STRING_OFFSET_AS_ARRAY, $v ) );
-                                                                               
        unset( $variable );
-                                                                               
        break 2;
-                                                                               
        // PHP Warning:  Cannot use a scalar value as an array
-                                                                               
}
-                                                                       }
-                                                               }
-                                                       }
-                                                       switch ( 
$value[PHPTAGS_STACK_COMMAND] ) {
-                                                               case 
PHPTAGS_T_INC:
-                                                                       if ( 
$value[PHPTAGS_STACK_PARAM_2] ) { // $foo++
-                                                                               
$value[PHPTAGS_STACK_RESULT] = $ref++;
-                                                                       }else{ 
// ++$foo
-                                                                               
$value[PHPTAGS_STACK_RESULT] = ++$ref;
-                                                                       }
-                                                                       break;
-                                                               case 
PHPTAGS_T_DEC:
-                                                                       if ( 
$value[PHPTAGS_STACK_PARAM_2] ) { // $foo--
-                                                                               
$value[PHPTAGS_STACK_RESULT] = $ref--;
-                                                                       }else{ 
// --$foo
-                                                                               
$value[PHPTAGS_STACK_RESULT] = --$ref;
-                                                                       }
-                                                                       break;
-                                                               case '=':
-                                                                       
$value[PHPTAGS_STACK_RESULT] = $ref = $value[PHPTAGS_STACK_PARAM_2];
-                                                                       break;
-                                                               case 
PHPTAGS_T_CONCAT_EQUAL:    // .=
-                                                                       
$value[PHPTAGS_STACK_RESULT] = $ref .= $value[PHPTAGS_STACK_PARAM_2];
-                                                                       break;
-                                                               case 
PHPTAGS_T_PLUS_EQUAL:              // +=
-                                                                       
$value[PHPTAGS_STACK_RESULT] = $ref += $value[PHPTAGS_STACK_PARAM_2];
-                                                                       break;
-                                                               case 
PHPTAGS_T_MINUS_EQUAL:             // -=
-                                                                       
$value[PHPTAGS_STACK_RESULT] = $ref -= $value[PHPTAGS_STACK_PARAM_2];
-                                                                       break;
-                                                               case 
PHPTAGS_T_MUL_EQUAL:               // *=
-                                                                       
$value[PHPTAGS_STACK_RESULT] = $ref *= $value[PHPTAGS_STACK_PARAM_2];
-                                                                       break;
-                                                               case 
PHPTAGS_T_DIV_EQUAL:               // /=
-                                                                       
$value[PHPTAGS_STACK_RESULT] = $ref /= $value[PHPTAGS_STACK_PARAM_2];
-                                                                       break;
-                                                               case 
PHPTAGS_T_MOD_EQUAL:               // %=
-                                                                       
$value[PHPTAGS_STACK_RESULT] = $ref %= $value[PHPTAGS_STACK_PARAM_2];
-                                                                       break;
-                                                               case 
PHPTAGS_T_AND_EQUAL:               // &=
-                                                                       
$value[PHPTAGS_STACK_RESULT] = $ref &= $value[PHPTAGS_STACK_PARAM_2];
-                                                                       break;
-                                                               case 
PHPTAGS_T_OR_EQUAL:                // |=
-                                                                       
$value[PHPTAGS_STACK_RESULT] = $ref |= $value[PHPTAGS_STACK_PARAM_2];
-                                                                       break;
-                                                               case 
PHPTAGS_T_XOR_EQUAL:               // ^=
-                                                                       
$value[PHPTAGS_STACK_RESULT] = $ref ^= $value[PHPTAGS_STACK_PARAM_2];
-                                                                       break;
-                                                               case 
PHPTAGS_T_SL_EQUAL:                // <<=
-                                                                       
$value[PHPTAGS_STACK_RESULT] = $ref <<= $value[PHPTAGS_STACK_PARAM_2];
-                                                                       break;
-                                                               case 
PHPTAGS_T_SR_EQUAL:                // >>=
-                                                                       
$value[PHPTAGS_STACK_RESULT] = $ref >>= $value[PHPTAGS_STACK_PARAM_2];
-                                                                       break;
-                                                       }
-                                                       break;
-                                       }
-                                       if ( $exceptions ) {
-                                               foreach ( $exceptions as $exc ) 
{
-                                                       $exc->tokenLine = 
$value[PHPTAGS_STACK_TOKEN_LINE];
-                                                       $exc->place = $place;
-                                                       $return[] = (string) 
$exc;
-                                               }
-                                               $exceptions = array();
-                                               self::addRuntimeErrorCategory();
-                                       }
-                               }
-                       } while( list($code[$codeIndex][PHPTAGS_STACK_RESULT], 
$code, $codeIndex, $c, $loopsOwner) = array_pop($memory) );
+                       } while( 
list($runCode[$runIndex][PHPTAGS_STACK_RESULT], $runCode, $runIndex, $c, 
$loopsOwner) = array_pop($memory) );
                } catch ( PhpTagsException $e ) {
-                       $e->tokenLine = $value[PHPTAGS_STACK_TOKEN_LINE];
-                       $e->place = $place;
-                       if ( $exceptions ) {
-                               foreach ( $exceptions as $exc ) {
-                                       $exc->tokenLine = 
$value[PHPTAGS_STACK_TOKEN_LINE];
-                                       $exc->place = $place;
-                                       $return[] = (string) $exc;
-                               }
+                       if ( self::$ignoreErrors ) {
+                               self::$ignoreErrors = false;
+                       } else {
+                               $e->tokenLine = 
$value[PHPTAGS_STACK_TOKEN_LINE];
+                               $e->place = self::$place;
+                               self::addRuntimeErrorCategory();
+                               self::$return[] = (string) $e;
                        }
-                       $exceptions = array();
-                       self::addRuntimeErrorCategory();
-                       $return[] = (string) $e;
                        $value[PHPTAGS_STACK_RESULT] = null;
                } catch ( \Exception $e ) {
-                       $exceptions = array();
                        self::addRuntimeErrorCategory();
                        restore_error_handler();
                        throw $e;
                }
                restore_error_handler();
-               return $return;
+               return self::$return;
        }
 
-       private static function fillList( &$values, &$param, &$thisVariables ) {
+       static function fillList( &$values, &$parametrs, &$thisVariables ) {
                $return = array();
-               foreach ( $param[PHPTAGS_STACK_PARAM] as $key => $val ) {
-                       if( $val !== null ) { // skip emty params. Example: 
list(, $bar) = $array;
-                               if( $val[PHPTAGS_STACK_COMMAND] == 
PHPTAGS_T_LIST ) { // T_LIST inside other T_LIST. Example: list($a, list($b, 
$c)) = array(1, array(2, 3));
-                                       if ( is_array($values) && 
isset($values[$key]) ) {
-                                               $return[$key] = 
self::fillList($values[$key], $val, $thisVariables);
-                                       } else {
-                                               static $a=array();
-                                               $return[$key] = 
self::fillList($a, $val, $thisVariables);
-                                       }
-                                       continue;
-                               }
-                               $ref = &$thisVariables[ 
$val[PHPTAGS_STACK_PARAM] ];
-                               if ( isset($val[PHPTAGS_STACK_ARRAY_INDEX]) ) { 
// Example: list($foo[0], $foo[1]) = $array;
-                                       foreach ( 
$val[PHPTAGS_STACK_ARRAY_INDEX] as $v ) {
-                                               if (  $v === INF ) { // 
Example: $foo[]
-                                                       $t = null;
-                                                       $ref[] = &$t;
-                                                       $ref = &$t;
-                                                       unset( $t );
-                                               } else {
-                                                       if ( !isset($ref[$v]) ) 
{
-                                                               $ref[$v] = null;
-                                                       }
-                                                       $ref = &$ref[$v];
-                                               }
-                                       }
-                               }
-                               if ( is_array($values) ) {
-                                       if ( isset($values[$key]) ) {
-                                               $ref = $values[$key];
-                                       } else {
-                                               $ref = null;
-                                               // @todo E_NOTICE
-                                       }
-                               } else { // list() work with array only
-                                       $ref = null;
-                               }
-                               $return[$key] = $ref;
+
+               for ( $pkey = count( $parametrs ) - 1; $pkey >= 0; --$pkey ) {
+                       $param = $parametrs[$pkey];
+                       if ( $param === null ) { // skip emty params. Example: 
list(, $bar) = $array;
+                               continue;
                        }
+                       if( $param[PHPTAGS_STACK_COMMAND] == PHPTAGS_T_LIST ) { 
// T_LIST inside other T_LIST. Example: list($a, list($b, $c)) = array(1, 
array(2, 3));
+                               if ( is_array($values) && isset($values[$pkey]) 
) {
+                                       $return[$pkey] = 
self::fillList($values[$pkey], $param[PHPTAGS_STACK_PARAM], $thisVariables);
+                               } else {
+                                       static $emptyArray=array();
+                                       $return[$pkey] = 
self::fillList($emptyArray, $param[PHPTAGS_STACK_PARAM], $thisVariables);
+                               }
+                               continue;
+                       }
+                       // $param is variable
+                       $ref = &$thisVariables[ $param[PHPTAGS_STACK_PARAM] ];
+                       if ( isset($param[PHPTAGS_STACK_ARRAY_INDEX]) ) { // 
Example: list($foo[0], $foo[1]) = $array;
+                               foreach ( $param[PHPTAGS_STACK_ARRAY_INDEX] as 
$v ) {
+                                       if (  $v === INF ) { // Example: $foo[]
+                                               $t = null;
+                                               $ref[] = &$t;
+                                               $ref = &$t;
+                                               unset( $t );
+                                       } else {
+                                               if ( !isset($ref[$v]) ) {
+                                                       $ref[$v] = null;
+                                               }
+                                               $ref = &$ref[$v];
+                                       }
+                               }
+                       }
+                       if ( is_array($values) ) {
+                               if ( isset($values[$pkey]) || 
array_key_exists($pkey, $values) ) {
+                                       $ref = $values[$pkey];
+                               } else {
+                                       $ref = null;
+                                       Runtime::pushException( new 
PhpTagsException( PhpTagsException::NOTICE_UNDEFINED_OFFSET, $pkey ) );
+                               }
+                       } else { // list() work with array only
+                               $ref = null;
+                       }
+                       $return[$pkey] = $ref;
                }
        }
 
@@ -793,13 +1399,15 @@
        }
 
        public static function pushException( PhpTagsException $exc ) {
-               if ( self::$exceptions !== false ) {
-                       self::$exceptions[] = $exc;
+               if ( self::$ignoreErrors === false ) {
+                       $exc->tokenLine = 
self::$running[self::$runIndex][PHPTAGS_STACK_TOKEN_LINE];
+                       $exc->place = self::$place;
+                       self::$return[] = (string) $exc;
                }
        }
 
        public static function getExceptions() {
-               return self::$exceptions;
+               return false;
        }
 
        public static function getVariables() {

-- 
To view, visit https://gerrit.wikimedia.org/r/191858
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Idbfcca925f6668a6d1ec9810e6f8c1df75c31c58
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/PhpTags
Gerrit-Branch: master
Gerrit-Owner: Pastakhov <pastak...@yandex.ru>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to