Pastakhov has uploaded a new change for review.

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

Change subject: Update to master version 5.9 (v 5.9.0.26)
......................................................................

Update to master version 5.9 (v 5.9.0.26)

* Add params checking in Runtime class (v 5.9)
    * Runtime::VERSION = 11
    * remove ErrorHandler
* Commented out warning message about deprecated PHP entry point
* Fix Renderer::getFrame()
* Add extension.json file and move setup instructions to it (v 5.8.0)
* Fix string to number conversion in Compiler (v 5.7.2) Runtime 10
   Problem depends of conversion string by operator (int):
    Example:
    echo 'int ' . (int)420000000000000000000,
     "\nint string " . (int)"420000000000000000000",
     "\nstring+0 " . ("420000000000000000000" + 0);

    Output for 5.3.22 - 5.4.45, hhvm-3.6.1 - 3.12.0
    int 0
    int string 9223372036854775807
    string+0 4.2E+20

    Output for 5.5.0 - 7.0.3
    int -4275113695319687168
    int string 9223372036854775807
    string+0 4.2E+20

    Now it doing through operation string + 0
* Fix error messages when Hooks class is used recursively (v 5.7.1)
* Add heredoc, nowdoc. Fix 'OR', 'AND', '[]' operators (v 5.7.0 runtime 9)
    Also fix fatal error when PhpTags adds value to string:
    $string = 'foo';
    $string[] = 'bar';
* add outStrip class (v 5.6.0)
* Fix memory cache (v 5.5.0 Runtime 8)
    Now, function getBytecode() always return bytecode that never used early.
* Fix array constructor (v 5.4.0) Runtime release 7
    error when array constructor is:
    array( $foo, $bar ); it was as array( null, $bar );
* optimize class outPrint (v 5.3.0)
    * add function Renderer::insertNoWiki()
    * add funnction iRawOutput::getReturnValue()
    * add funnction iRawOutput::placeAsStripItem()
* Fix test initialization
* Fix debug messages
* Skip PhpTagsRuntimeFirstInit hook tests if PHPTAGS_TEST is not defined
* add debug mesaages to test files
* Update indentation to use tabs

Change-Id: I81b2c89a3a8a13ebf9f3ea1c14c3acbd91c0b2e7
---
M .gitignore
M PhpTags.hooks.php
M PhpTags.json
M PhpTags.php
A extension.json
M i18n/en.json
M i18n/it.json
A i18n/ko.json
M i18n/ru.json
M i18n/sv.json
M includes/Compiler.php
D includes/ErrorHandler.php
M includes/GenericObject.php
M includes/Hooks.php
M includes/JsonLoader.php
A includes/PhpTagsConstants.php
M includes/PhpTagsException.php
M includes/Renderer.php
M includes/Runtime.php
M includes/iRawOutput.php
M includes/outPrint.php
A includes/outStrip.php
M tests/phpunit/includes/!!!firstInit_Test.php
M tests/phpunit/includes/RuntimeTest.php
24 files changed, 1,504 insertions(+), 343 deletions(-)


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

diff --git a/.gitignore b/.gitignore
index 98b092a..afc53f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
 *~
 *.kate-swp
 .*.swp
+.directory
diff --git a/PhpTags.hooks.php b/PhpTags.hooks.php
index ea011d3..9e27ec9 100644
--- a/PhpTags.hooks.php
+++ b/PhpTags.hooks.php
@@ -60,14 +60,14 @@
 
        /**
         *
-        * @global int $wgPhpTagsCounter
+        * @global int $wgPhpTagsCallsCounter
         * @param Parser $parser
         * @param string $text
         * @return boolean
         */
        public static function onParserAfterTidy( $parser, &$text ) {
-               global $wgPhpTagsCounter;
-               if ( $wgPhpTagsCounter > 0 ) {
+               global $wgPhpTagsCallsCounter;
+               if ( $wgPhpTagsCallsCounter > 0 ) {
                        \PhpTags\Renderer::onParserAfterTidy( $parser, $text );
                }
                return true;
@@ -100,4 +100,14 @@
                return true;
        }
 
+       public static function onRegistration() {
+               global $wgPhpTagsLimitReport, $wgPhpTagsCallsCounter;
+
+               $wgPhpTagsLimitReport = false;
+               $wgPhpTagsCallsCounter = 0;
+
+               define ( 'PHPTAGS_HOOK_RELEASE', 8 );
+               define ( 'PHPTAGS_VERSION', '5.9.0.26' ); //@todo remove later, 
it only for backward compatibility
+       }
+
 }
diff --git a/PhpTags.json b/PhpTags.json
index 7adb405..1928822 100644
--- a/PhpTags.json
+++ b/PhpTags.json
@@ -2,18 +2,22 @@
        "constants": {
                "PHPTAGS_MAJOR_VERSION": {
                        "desc": "The current 'major' version of the PhpTags 
extension as an integer",
+                       "class": "PhpTagsConstants",
                        "type": "int"
                },
                "PHPTAGS_MINOR_VERSION": {
                        "desc": "The current 'minor' version of the PhpTags 
extension as an integer",
+                       "class": "PhpTagsConstants",
                        "type": "int"
                },
                "PHPTAGS_RELEASE_VERSION": {
                        "desc": "The current 'release' version of the PhpTags 
extension as an integer",
+                       "class": "PhpTagsConstants",
                        "type": "int"
                },
                "PHPTAGS_VERSION": {
                        "desc": "The current version of the PhpTags extension 
as a string",
+                       "class": "PhpTagsConstants",
                        "type": "string"
                }
        }
diff --git a/PhpTags.php b/PhpTags.php
index 3eb3698..d57d90e 100644
--- a/PhpTags.php
+++ b/PhpTags.php
@@ -1,104 +1,15 @@
 <?php
-/**
- * Main entry point for the PhpTags extension.
- *
- * @link https://www.mediawiki.org/wiki/Extension:PhpTags Documentation
- * @file PhpTags.php
- * @defgroup PhpTags
- * @ingroup Extensions
- * @author Pavel Astakhov <pastak...@yandex.ru>
- * @licence GNU General Public Licence 2.0 or later
- */
-
-// Check to see if we are being called as an extension or directly
-if ( !defined( 'MEDIAWIKI' ) ) {
-       die( 'This file is an extension to MediaWiki and thus not a valid entry 
point.' );
+if ( function_exists( 'wfLoadExtension' ) ) {
+       wfLoadExtension( 'PhpTags' );
+       // Keep i18n globals so mergeMessageFileList.php doesn't break
+       $wgMessagesDirs['PhpTags'] = __DIR__ . '/i18n';
+       $wgExtensionMessagesFiles['PhpTagsMagic'] = __DIR__ . 
'/PhpTags.i18n.magic.php';
+//     wfWarn(
+//             'Deprecated PHP entry point used for PhpTags extension. ' .
+//             'Please use wfLoadExtension instead, ' .
+//             'see https://www.mediawiki.org/wiki/Extension_registration for 
more details.'
+//     );
+       return;
+} else {
+       die( 'This version of the PhpTags extension requires MediaWiki 1.25+' );
 }
-
-const PHPTAGS_MAJOR_VERSION = 5;
-const PHPTAGS_MINOR_VERSION = 2;
-const PHPTAGS_RELEASE_VERSION = 0;
-define( 'PHPTAGS_VERSION', PHPTAGS_MAJOR_VERSION . '.' . PHPTAGS_MINOR_VERSION 
. '.' . PHPTAGS_RELEASE_VERSION );
-
-const PHPTAGS_HOOK_RELEASE = 8;
-const PHPTAGS_RUNTIME_RELEASE = 6;
-const PHPTAGS_JSONLOADER_RELEASE = 3;
-
-// Register this extension on Special:Version
-$wgExtensionCredits['parserhook'][] = array(
-       'path'                          => __FILE__,
-       'name'                          => 'PhpTags',
-       'version'                       => PHPTAGS_VERSION,
-       'url'                           => 
'https://www.mediawiki.org/wiki/Extension:PhpTags',
-       'author'                        => 
'[https://www.mediawiki.org/wiki/User:Pastakhov Pavel Astakhov]',
-       'descriptionmsg'        => 'phptags-desc',
-       'license-name'          => 'GPL-2.0+',
-);
-
-// Allow translations for this extension
-$wgMessagesDirs['PhpTags'] = __DIR__ . '/i18n';
-$wgExtensionMessagesFiles['PhpTagsMagic'] = __DIR__ . 
'/PhpTags.i18n.magic.php';
-
-//
-$wgPhpTagsLimitReport = false;
-$wgPhpTagsCounter = 0;
-
-// Preparing classes for autoloading
-$wgAutoloadClasses['PhpTagsHooks'] = __DIR__ . '/PhpTags.hooks.php';
-$wgAutoloadClasses['PhpTags\\Renderer'] = __DIR__ . '/includes/Renderer.php';
-$wgAutoloadClasses['PhpTags\\Timer'] = __DIR__ . '/includes/Renderer.php';
-$wgAutoloadClasses['PhpTags\\iRawOutput'] = __DIR__ . 
'/includes/iRawOutput.php';
-$wgAutoloadClasses['PhpTags\\outPrint'] = __DIR__ . '/includes/outPrint.php';
-$wgAutoloadClasses['PhpTags\\ErrorHandler'] = __DIR__ . 
'/includes/ErrorHandler.php';
-$wgAutoloadClasses['PhpTags\\PhpTagsException'] = __DIR__ . 
'/includes/PhpTagsException.php';
-$wgAutoloadClasses['PhpTags\\HookException'] = __DIR__ . 
'/includes/HookException.php';
-$wgAutoloadClasses['PhpTags\\Compiler'] = __DIR__ . '/includes/Compiler.php';
-$wgAutoloadClasses['PhpTags\\Runtime'] = __DIR__ . '/includes/Runtime.php';
-$wgAutoloadClasses['PhpTags\\GenericObject'] = __DIR__ . 
'/includes/GenericObject.php';
-$wgAutoloadClasses['PhpTags\\Hooks'] = __DIR__ . '/includes/Hooks.php';
-$wgAutoloadClasses['PhpTags\\JsonLoader'] = __DIR__ . 
'/includes/JsonLoader.php';
-$wgAutoloadClasses['PhpTagsObjects\\PhpTagsTestClass'] = __DIR__ . 
'/tests/phpunit/includes/PhpTagsTestClass.php';
-
-// Add tracking categories
-$wgTrackingCategories[] = 'phptags-compiler-error-category';
-$wgTrackingCategories[] = 'phptags-runtime-error-category';
-
-//
-$wgHooks['ParserFirstCallInit'][] = 'PhpTagsHooks::onParserFirstCallInit';
-$wgHooks['PhpTagsRuntimeFirstInit'][] = 
'PhpTagsHooks::onPhpTagsRuntimeFirstInit';
-$wgHooks['CodeMirrorGetAdditionalResources'][] = 
'PhpTagsHooks::onCodeMirrorGetAdditionalResources';
-$wgHooks['ParserLimitReport'][] = 'PhpTagsHooks::onParserLimitReport';
-$wgHooks['ParserAfterTidy'][] = 'PhpTagsHooks::onParserAfterTidy';
-$wgHooks['ExtensionTypes'][] = 'PhpTagsHooks::onExtensionTypes';
-$wgHooks['UnitTestsList'][] = 'PhpTagsHooks::onUnitTestsList';
-
-// add parser tests
-$wgParserTestFiles[] = __DIR__ . '/tests/parser/PhpTagsTests.txt';
-
-/**
- * You can specify the namespaces in which allowed to use this extension.
- *
- * Thus it is possible to give permission to use this extension only for a 
special user group, example:
- * define("NS_PHPTAGS", 1000);
- * define("NS_PHPTAGS_TALK", 1001);
- * $wgExtraNamespaces[NS_PHPTAGS] = "PhpTags";
- * $wgExtraNamespaces[NS_PHPTAGS_TALK] = "PhpTags_Talk";
- *
- * $wgPhpTagsNamespaces = array( NS_PHPTAGS => true );
- * $wgNamespaceProtection[NS_PHPTAGS] = array( 'phptags_editor' );
- * $wgGroupPermissions['sysop']['phptags_editor'] = true;
- *
- * @var mixed $wgPhpTagsNamespaces Array of namespaces in which allowed to use 
the extension PhpTags, and if boolean 'true' then it is unlimited namespaces
- */
-$wgPhpTagsNamespaces = true; // By default, this is unlimited namespaces
-
-/**
- * Maximum number of allowed loops
- */
-$wgPhpTagsMaxLoops = 1000;
-
-/**
- * Storage time of the compiled bytecode at cache
- * By default it is 30 days
- */
-$wgPhpTagsBytecodeExptime = 2592000;
diff --git a/extension.json b/extension.json
new file mode 100644
index 0000000..8ade0e0
--- /dev/null
+++ b/extension.json
@@ -0,0 +1,58 @@
+{
+       "name": "PhpTags",
+       "version": "5.9.0.26",
+       "author": "[https://www.mediawiki.org/wiki/User:Pastakhov Pavel 
Astakhov]",
+       "url": "https://www.mediawiki.org/wiki/Extension:PhpTags";,
+       "descriptionmsg": "phptags-desc",
+       "license-name": "GPL-2.0+",
+       "type": "phptags",
+       "MessagesDirs": {
+               "PhpTags": [
+                       "i18n"
+               ]
+       },
+       "ExtensionMessagesFiles": {
+               "PhpTagsMagic": "PhpTags.i18n.magic.php"
+       },
+       "AutoloadClasses": {
+               "PhpTagsHooks": "PhpTags.hooks.php",
+               "PhpTags\\Renderer": "includes/Renderer.php",
+               "PhpTags\\Timer": "includes/Renderer.php",
+               "PhpTags\\iRawOutput": "includes/iRawOutput.php",
+               "PhpTags\\outPrint": "includes/outPrint.php",
+               "PhpTags\\outStrip": "includes/outStrip.php",
+               "PhpTags\\PhpTagsException": "includes/PhpTagsException.php",
+               "PhpTags\\HookException": "includes/HookException.php",
+               "PhpTags\\Compiler": "includes/Compiler.php",
+               "PhpTags\\Runtime": "includes/Runtime.php",
+               "PhpTags\\GenericObject": "includes/GenericObject.php",
+               "PhpTags\\Hooks": "includes/Hooks.php",
+               "PhpTags\\JsonLoader": "includes/JsonLoader.php",
+               "PhpTagsObjects\\PhpTagsConstants": 
"includes/PhpTagsConstants.php",
+               "PhpTagsObjects\\PhpTagsTestClass": 
"tests/phpunit/includes/PhpTagsTestClass.php"
+       },
+       "Hooks": {
+               "ParserFirstCallInit": "PhpTagsHooks::onParserFirstCallInit",
+               "PhpTagsRuntimeFirstInit": 
"PhpTagsHooks::onPhpTagsRuntimeFirstInit",
+               "CodeMirrorGetAdditionalResources": 
"PhpTagsHooks::onCodeMirrorGetAdditionalResources",
+               "ParserLimitReport": "PhpTagsHooks::onParserLimitReport",
+               "ParserAfterTidy": "PhpTagsHooks::onParserAfterTidy",
+               "ExtensionTypes": "PhpTagsHooks::onExtensionTypes",
+               "UnitTestsList": "PhpTagsHooks::onUnitTestsList"
+       },
+       "ParserTestFiles": [
+               "tests/parser/PhpTagsTests.txt"
+       ],
+       "config": {
+               "TrackingCategories": [
+                       "phptags-compiler-error-category",
+                       "phptags-runtime-error-category"
+               ],
+               "PhpTagsNamespaces": true,
+               "PhpTagsMaxLoops": 1000,
+               "PhpTagsBytecodeExptime": 2592000
+       },
+       "callback": "PhpTagsHooks::onRegistration",
+       "manifest_version": 1
+}
+
diff --git a/i18n/en.json b/i18n/en.json
index 107412d..02dd57c 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -1,14 +1,14 @@
 {
-    "@metadata": {
-        "authors": [
-            "pastakhov"
-        ]
-    },
-    "phptags-compiler-error-category": "Pages with invalid PhpTags code",
-    "phptags-compiler-error-category-desc": "The PhpTags code has an error in 
it.",
-    "phptags-runtime-error-category": "Pages with PhpTags errors",
-    "phptags-runtime-error-category-desc": "There was an error when processing 
PhpTags code on the page.",
-    "phptags-desc": "Allows users to use the Magic expressions with PHP 
language syntax",
-    "phptags-disabled-for-namespace": "Extension PhpTags is disabled for the 
namespace \"$1\".",
-    "phptags-extension-type": "PhpTags extensions"
+       "@metadata": {
+               "authors": [
+                       "pastakhov"
+               ]
+       },
+       "phptags-compiler-error-category": "Pages with invalid PhpTags code",
+       "phptags-compiler-error-category-desc": "The PhpTags code has an error 
in it.",
+       "phptags-runtime-error-category": "Pages with PhpTags errors",
+       "phptags-runtime-error-category-desc": "There was an error when 
processing PhpTags code on the page.",
+       "phptags-desc": "Allows users to use the Magic expressions with PHP 
language syntax",
+       "phptags-disabled-for-namespace": "Extension PhpTags is disabled for 
the namespace \"$1\".",
+       "phptags-extension-type": "PhpTags extensions"
 }
diff --git a/i18n/it.json b/i18n/it.json
index 7b786a5..1b1f813 100644
--- a/i18n/it.json
+++ b/i18n/it.json
@@ -4,6 +4,11 @@
                        "Beta16"
                ]
        },
+       "phptags-compiler-error-category": "Pagine con codice PhpTags non 
valido",
+       "phptags-compiler-error-category-desc": "Il codice PhpTags contiene un 
errore.",
+       "phptags-runtime-error-category": "Pagine con errori PhpTags",
+       "phptags-runtime-error-category-desc": "Si è verificato un errore 
durante l'elaborazione del codice PhpTags nella pagina.",
        "phptags-desc": "Consente agli utenti di utilizzare le espressioni 
Magic con la sintassi del linguaggio PHP",
-       "phptags-disabled-for-namespace": "L'estensione PhpTags è disabilitata 
per il namespace \"$1\"."
+       "phptags-disabled-for-namespace": "L'estensione PhpTags è disabilitata 
per il namespace \"$1\".",
+       "phptags-extension-type": "Estensioni PhpTags"
 }
diff --git a/i18n/ko.json b/i18n/ko.json
new file mode 100644
index 0000000..df85032
--- /dev/null
+++ b/i18n/ko.json
@@ -0,0 +1,14 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Revi",
+                       "Ykhwong"
+               ]
+       },
+       "phptags-compiler-error-category": "잘못된 PhpTags 코드를 포함한 문서",
+       "phptags-compiler-error-category-desc": "PhpTags 코드에 문제가 있습니다.",
+       "phptags-runtime-error-category": "PhpTags 오류가 있는 문서",
+       "phptags-runtime-error-category-desc": "PhpTags 코드를 처리하던 중 오류가 발생했습니다.",
+       "phptags-disabled-for-namespace": "PhpTags 확장 기능이 \"$1\" 이름공간에서 활성화되지 
않았습니다.",
+       "phptags-extension-type": "PhpTags 확장 기능"
+}
diff --git a/i18n/ru.json b/i18n/ru.json
index efafaab..e6c05c3 100644
--- a/i18n/ru.json
+++ b/i18n/ru.json
@@ -4,6 +4,11 @@
                        "Okras"
                ]
        },
+       "phptags-compiler-error-category": "Страницы с неверным PhpTags-кодом",
+       "phptags-compiler-error-category-desc": "PhpTags-код, содержащий 
ошибку.",
+       "phptags-runtime-error-category": "Страницы с PhpTags-ошибками",
+       "phptags-runtime-error-category-desc": "Произошла ошибка при обработке 
кода PhpTags на этой странице.",
        "phptags-desc": "Позволяет пользователям использовать волшебные 
выражения в синтаксисе языка PHP",
-       "phptags-disabled-for-namespace": "Расширение PhpTags отключено для 
пространства имён «$1»."
+       "phptags-disabled-for-namespace": "Расширение PhpTags отключено для 
пространства имён «$1».",
+       "phptags-extension-type": "Расширения PhpTags"
 }
diff --git a/i18n/sv.json b/i18n/sv.json
index 6276cf9..e75551c 100644
--- a/i18n/sv.json
+++ b/i18n/sv.json
@@ -11,5 +11,6 @@
        "phptags-runtime-error-category": "Sidor med PhpTags-fel",
        "phptags-runtime-error-category-desc": "Det uppstod ett fel vid 
bearbetningen av PhpTags-koden på sidan.",
        "phptags-desc": "Tillåter användare att använda Magic-uttrycken med 
PHP-språksyntax",
-       "phptags-disabled-for-namespace": "Tillägget PhpTags är inaktiverat för 
namnrymden \"$1\"."
+       "phptags-disabled-for-namespace": "Tillägget PhpTags är inaktiverat för 
namnrymden \"$1\".",
+       "phptags-extension-type": "PhpTags-tillägg"
 }
diff --git a/includes/Compiler.php b/includes/Compiler.php
index ea7eb9a..d78f0f5 100644
--- a/includes/Compiler.php
+++ b/includes/Compiler.php
@@ -453,17 +453,12 @@
                                                $tmp = intval( $text, 8 );
                                        }
                                } else {
-                                       $tmp = (int)$text;
+                                       $tmp = $text + 0;
                                }
                                $result = array( Runtime::B_COMMAND=>null, 
Runtime::B_RESULT=>$tmp, Runtime::B_TOKEN_LINE=>$this->tokenLine, 
Runtime::B_DEBUG=>$text );
                                break;
                        case T_DNUMBER:
-                               $epos = stripos($text, 'e');
-                               if ( $epos === false ) {
-                                       $tmp = (float)$text;
-                               } else {
-                                       $tmp = (float)( substr($text, 0, $epos) 
* pow(10, substr($text, $epos+1)) );
-                               }
+                               $tmp = $text + 0;
                                $result = array( Runtime::B_COMMAND=>null, 
Runtime::B_RESULT=>$tmp, Runtime::B_TOKEN_LINE=>$this->tokenLine, 
Runtime::B_DEBUG=>$text );
                                break;
                        case T_CONSTANT_ENCAPSED_STRING:
@@ -534,11 +529,25 @@
                                }
                                $result = array( Runtime::B_COMMAND=>null, 
Runtime::B_RESULT=>$tmp, Runtime::B_TOKEN_LINE=>$this->tokenLine, 
Runtime::B_DEBUG=>$text );
                                break;
+                       case T_START_HEREDOC:
+                               if( substr( $text, 3, 1 ) === '\'' ) { // 
heredoc
+                                       $this->stepUP();
+                                       if ( $this->id !== 
T_ENCAPSED_AND_WHITESPACE ) {
+                                               throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id, 
"T_ENCAPSED_AND_WHITESPACE" ), $this->tokenLine, $this->place );
+                                       }
+                                       $result = array( 
Runtime::B_COMMAND=>null, Runtime::B_RESULT=>$this->text, 
Runtime::B_TOKEN_LINE=>$this->tokenLine, Runtime::B_DEBUG=>$text );
+                                       $this->stepUP();
+                                       if ( $this->id !== T_END_HEREDOC ) {
+                                               throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id, 
"T_ENCAPSED_AND_WHITESPACE" ), $this->tokenLine, $this->place );
+                                       }
+                                       break;
+                               } // nowdoc
+                               // break is not necessary here
                        case '"':
                                $this->stepUP();
                                $strings = array();
                                $i = 0;
-                               while ( $this->id != '"' ) {
+                               while ( $this->id !== '"' ) {
                                        if ( $this->id === T_CURLY_OPEN || 
$this->id === '}' ) {
                                                $this->stepUP();
                                        } else {
@@ -546,6 +555,8 @@
                                                if ( $val ) { // echo "abcd$foo
                                                        $strings[$i] = null;
                                                        
$this->addValueIntoStack( $val, $strings, $i );
+                                               } else if ( $this->id === 
T_END_HEREDOC ) {
+                                                       break;
                                                } else {
                                                        // PHP Parse error:  
syntax error, unexpected $id, expecting '"'
                                                        throw new 
PhpTagsException( PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( 
$this->id, "'\"'" ), $this->tokenLine, $this->place );
@@ -595,7 +606,7 @@
                                                // PHP Parse error:  syntax 
error, unexpected $id
                                                throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id ), 
$this->tokenLine, $this->place );
                                        }
-                                       if ( $owner === false && 
$variable[Runtime::B_COMMAND] === Runtime::T_VARIABLE ) {
+                                       if ( $owner === false && 
$variable[Runtime::B_COMMAND] === Runtime::T_VARIABLE ) { // $foo = <value> or 
$foo += <value>
                                                $return = array(
                                                        Runtime::B_COMMAND => 
self::$runtimeOperators[$id],
                                                        Runtime::B_PARAM_1 => 
$variable,
@@ -603,6 +614,7 @@
                                                        Runtime::B_RESULT => 
null,
                                                        Runtime::B_TOKEN_LINE 
=> $this->tokenLine,
                                                        Runtime::B_DEBUG => 
$text,
+                                                       Runtime::B_FLAGS => 
($cannotRead === true && $id !== '=') ? Runtime::F_DONT_CHECK_PARAM1 : 0,
                                                );
                                                $this->addValueIntoStack( $val, 
$return, Runtime::B_PARAM_2 );
                                                return $return; // *********** 
EXIT ***********
@@ -920,6 +932,8 @@
                                $result =& $this->stepValue( $owner );
                                $this->ignoreErrors = null;
                                return $result;
+                       case T_END_HEREDOC:
+                               return $result; // false
                }
                if ( $result !== false ) {
                        $this->stepUP();
@@ -954,6 +968,7 @@
                                        Runtime::B_RESULT => null,
                                        Runtime::B_TOKEN_LINE => 
$this->tokenLine,
                                        Runtime::B_DEBUG => $text,
+                                       Runtime::B_FLAGS => 0,
                                );
                                $didit = $this->addValueIntoStack( $value, 
$operator, Runtime::B_PARAM_1, false ); // Add the first value into the stack
 
@@ -1079,9 +1094,17 @@
                                        throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id ), 
$this->tokenLine, $this->place );
                                }
 
-                               $operator = array(
-                                       Runtime::B_COMMAND => 
self::$runtimeOperators[$id],
+                               $result = array(
+                                       Runtime::B_COMMAND => 
Runtime::T_TERNARY,
                                        Runtime::B_PARAM_1 => null,
+                                       Runtime::B_PARAM_2 => 
array(Runtime::B_DO_FALSE=>false, Runtime::B_PARAM_2=>false),
+                                       Runtime::B_RESULT => null,
+                                       Runtime::B_TOKEN_LINE => 
$this->tokenLine,
+                                       Runtime::B_DEBUG => $text,
+                               );
+
+                               $operator = array(
+                                       Runtime::B_COMMAND => 
Runtime::T_BOOL_CAST,
                                        Runtime::B_PARAM_2 => null,
                                        Runtime::B_RESULT => null,
                                        Runtime::B_TOKEN_LINE => 
$this->tokenLine,
@@ -1091,13 +1114,13 @@
                                $this->addValueIntoStack( $nextValue, 
$operator, Runtime::B_PARAM_2, true );
                                $stack_true = $this->stack ?: false;
                                $this->stack_pop_memory();
-                               $doit = $this->addValueIntoStack( $value, 
$operator, Runtime::B_PARAM_1, true );
+                               $done = $this->addValueIntoStack( $value, 
$result, Runtime::B_PARAM_1, true );
 
-                               if ( $stack_true === false && 
$operator[Runtime::B_PARAM_2] == false || $doit === true && 
$operator[Runtime::B_PARAM_1] == false ) {
+                               if ( $stack_true === false && 
$operator[Runtime::B_PARAM_2] == false || $done === true && 
$operator[Runtime::B_PARAM_1] == false ) {
                                        $result = array( Runtime::B_COMMAND => 
null,    Runtime::B_RESULT => false ); // it's always false
                                        break;
                                }
-                               if ( $stack_true === false && 
$operator[Runtime::B_PARAM_2] == true && $doit === true && 
$operator[Runtime::B_PARAM_1] == true ) {
+                               if ( $stack_true === false && 
$operator[Runtime::B_PARAM_2] == true && $done === true && 
$operator[Runtime::B_PARAM_1] == true ) {
                                        $result = array( Runtime::B_COMMAND => 
null,    Runtime::B_RESULT => true ); // it's always true
                                        break;
                                }
@@ -1108,22 +1131,8 @@
                                        $stack_true[] =& $operator;
                                }
 
-                               $param2 = array(
-                                       Runtime::B_RESULT => null,
-                                       Runtime::B_PARAM_1 => 
&$operator[Runtime::B_RESULT],
-                                       Runtime::B_DO_TRUE => $stack_true,
-                                       Runtime::B_PARAM_2 => false,
-                                       Runtime::B_DO_FALSE => false,
-                               );
-                               $result = array(
-                                       Runtime::B_COMMAND => 
Runtime::T_TERNARY,
-                                       Runtime::B_PARAM_1 => null,
-                                       Runtime::B_PARAM_2 => $param2,
-                                       Runtime::B_RESULT => null,
-                                       Runtime::B_TOKEN_LINE => 
$this->tokenLine,
-                                       Runtime::B_DEBUG => $text,
-                               );
-                               $this->addValueIntoStack( $value, $result, 
Runtime::B_PARAM_1, true );
+                               $result[Runtime::B_PARAM_2][Runtime::B_DO_TRUE] 
= $stack_true;
+                               $result[Runtime::B_PARAM_2][Runtime::B_PARAM_1] 
=& $operator[Runtime::B_RESULT];
                                break;
                        case T_BOOLEAN_OR:      // ||
                        case T_LOGICAL_OR:      // or
@@ -1135,9 +1144,17 @@
                                        throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id ), 
$this->tokenLine, $this->place );
                                }
 
-                               $operator = array(
-                                       Runtime::B_COMMAND => 
self::$runtimeOperators[$id],
+                               $result = array(
+                                       Runtime::B_COMMAND => 
Runtime::T_TERNARY,
                                        Runtime::B_PARAM_1 => null,
+                                       Runtime::B_PARAM_2 => 
array(Runtime::B_DO_TRUE=>false, Runtime::B_PARAM_1=>true),
+                                       Runtime::B_RESULT => null,
+                                       Runtime::B_TOKEN_LINE => 
$this->tokenLine,
+                                       Runtime::B_DEBUG => $text,
+                               );
+
+                               $operator = array(
+                                       Runtime::B_COMMAND => 
Runtime::T_BOOL_CAST,
                                        Runtime::B_PARAM_2 => null,
                                        Runtime::B_RESULT => null,
                                        Runtime::B_TOKEN_LINE => 
$this->tokenLine,
@@ -1147,13 +1164,13 @@
                                $this->addValueIntoStack( $nextValue, 
$operator, Runtime::B_PARAM_2, true );
                                $stack_false = $this->stack ?: false;
                                $this->stack_pop_memory();
-                               $doit = $this->addValueIntoStack( $value, 
$operator, Runtime::B_PARAM_1, true );
+                               $done = $this->addValueIntoStack( $value, 
$result, Runtime::B_PARAM_1, true );
 
-                               if ( $stack_false === false && 
$operator[Runtime::B_PARAM_2] == true || $doit === true && 
$operator[Runtime::B_PARAM_1] == true ) {
+                               if ( $stack_false === false && 
$operator[Runtime::B_PARAM_2] == true || $done === true && 
$operator[Runtime::B_PARAM_1] == true ) {
                                        $result = array( Runtime::B_COMMAND => 
null,    Runtime::B_RESULT => true ); // it's always true
                                        break;
                                }
-                               if ( $stack_false === false && 
$operator[Runtime::B_PARAM_2] == false && $doit === true && 
$operator[Runtime::B_PARAM_1] == false ) {
+                               if ( $stack_false === false && 
$operator[Runtime::B_PARAM_2] == false && $done === true && 
$operator[Runtime::B_PARAM_1] == false ) {
                                        $result = array( Runtime::B_COMMAND => 
null,    Runtime::B_RESULT => false ); // it's always false
                                        break;
                                }
@@ -1164,22 +1181,8 @@
                                        $stack_false[] =& $operator;
                                }
 
-                               $param2 = array(
-                                       Runtime::B_RESULT => null,
-                                       Runtime::B_PARAM_1 => true,
-                                       Runtime::B_DO_TRUE => false,
-                                       Runtime::B_PARAM_2 => 
&$operator[Runtime::B_RESULT],
-                                       Runtime::B_DO_FALSE => $stack_false,
-                               );
-                               $result = array(
-                                       Runtime::B_COMMAND => 
Runtime::T_TERNARY,
-                                       Runtime::B_PARAM_1 => null,
-                                       Runtime::B_PARAM_2 => $param2,
-                                       Runtime::B_RESULT => null,
-                                       Runtime::B_TOKEN_LINE => 
$this->tokenLine,
-                                       Runtime::B_DEBUG => $text,
-                               );
-                               $this->addValueIntoStack( $value, $result, 
Runtime::B_PARAM_1, true );
+                               
$result[Runtime::B_PARAM_2][Runtime::B_DO_FALSE] = $stack_false;
+                               $result[Runtime::B_PARAM_2][Runtime::B_PARAM_2] 
=& $operator[Runtime::B_RESULT];
                                break;
                }
                return $result;
@@ -1293,6 +1296,7 @@
                                                        $copy = array( 
Runtime::B_COMMAND=>Runtime::T_COPY, Runtime::B_PARAM_1=>null, 
Runtime::B_RESULT=>&$array[$i] );
                                                        
$this->addValueIntoStack( $value, $copy, Runtime::B_PARAM_1, false );
                                                        $this->stack[] =& $copy;
+                                                       unset( $copy );
                                                } else {
                                                        
$this->addValueIntoStack( $value, $array, $i );
                                                }
@@ -1347,7 +1351,7 @@
                if ( $result === false ) { // It is simple array and can be 
compiled, example: $foo = array( 1, 2, 3 );
                        $result = array( Runtime::B_COMMAND=>false, 
Runtime::B_RESULT=>&$array );
                } elseif ( $array ) {
-                       $result[Runtime::B_PARAM_1][] = &$array;
+                       $result[Runtime::B_PARAM_1][] =& $array;
                }
                return $result;
        }
diff --git a/includes/ErrorHandler.php b/includes/ErrorHandler.php
deleted file mode 100644
index d81cb55..0000000
--- a/includes/ErrorHandler.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-namespace PhpTags;
-
-/**
- * Description of ErrorHandler
- *
- * @author pastakhov
- */
-class ErrorHandler {
-
-       public static function onError( $errno, $errstr, $errfile, $errline, 
$errcontext, $object = false ) {
-               if ( $object === false ) { // @todo wfIsHHVM()
-                       return self::onPhpError( $errno, $errstr, $errfile );
-               }
-               return self::onHhvmError( $errno, $errstr, $errfile );
-       }
-
-       private static function onPhpError( $errno, $errstr, $errfile ) {
-               $backtrace = debug_backtrace();
-               if ( true === isset($backtrace[1]['file']) && strpos( 
$backtrace[1]['file'], 'PhpTags/includes/Runtime.php' ) !== false ) {
-                       if ( strpos( $errstr, 'Division by zero' ) !== false ) {
-                               Runtime::pushException( new PhpTagsException( 
PhpTagsException::WARNING_DIVISION_BY_ZERO, null ) );
-                               return true;
-                       }
-                       $matches = null;
-                       if ( preg_match('/^Object of class ([\\w:\\\\]+) could 
not be converted to (\\w+).*?/', $errstr, $matches) ) {
-                               return self::onRuntimeObjectConvertionError( 
$matches );
-                       }
-               }
-               return false;
-       }
-
-       private static function onRuntimeObjectConvertionError( $matches ) {
-               $object = Runtime::getCurrentOperator();
-               static $previousOperator = false;
-               if ( isset($object[Runtime::B_PARAM_1]) && 
is_a($object[Runtime::B_PARAM_1], $matches[1]) ) {
-                       if ( $previousOperator === $object && 
is_a($object[Runtime::B_PARAM_2], $matches[1]) ) {
-                               $matches[1] = 
$object[Runtime::B_PARAM_2]->getName();
-                       } else {
-                               $matches[1] = 
$object[Runtime::B_PARAM_1]->getName();
-                       }
-               } else {
-                       $matches[1] = $object[Runtime::B_PARAM_2]->getName();
-               }
-               Runtime::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array($matches[1], $matches[2]) ) );
-               $previousOperator = $object;
-               return true;
-       }
-
-       private static function onHhvmError( $errno, $errstr, $errfile ) {
-               $backtrace = debug_backtrace();
-               $matches = null;
-               if ( false !== strpos( $errfile, 'PhpTags/includes/Runtime.php' 
) ) {
-                       if ( strpos( $errstr, 'Division by zero' ) !== false ) {
-                               Runtime::pushException( new PhpTagsException( 
PhpTagsException::WARNING_DIVISION_BY_ZERO, null ) );
-                               return true;
-                       }
-                       $matches = null;
-                       if ( preg_match('/^Object of class ([\\w:\\\\]+) could 
not be converted to (\\w+).*?/', $errstr, $matches) ) {
-                               return self::onRuntimeObjectConvertionError( 
$matches );
-                       }
-               }
-               return false;
-       }
-
-}
diff --git a/includes/GenericObject.php b/includes/GenericObject.php
index e8136e9..aec9281 100644
--- a/includes/GenericObject.php
+++ b/includes/GenericObject.php
@@ -77,6 +77,19 @@
                return $this->value;
        }
 
+       /**
+        * Returns value for operator (array) and functions var_dump and etc...
+        * @since 5.9
+        * @return array
+        */
+       public function getDumpValue() {
+               return (array)('(' . Runtime::R_DUMP_OBJECT . ' <' . 
$this->getName() . '>)');
+       }
+
+       /**
+        * Returns object's name
+        * @return string
+        */
        public function getName() {
                return $this->objectName;
        }
@@ -115,7 +128,7 @@
                return \PhpTags\Hooks::getCallInfo( 
\PhpTags\Hooks::INFO_RETURNS_ON_FAILURE );
        }
 
-       // It doesn't allow illegal access to public properties inside phptag 
code by using foreach operator
+       // It doesn't allow illegal access to public properties inside phptag 
code through using foreach operator
        public function current() {}
        public function key() {}
        public function next() {}
diff --git a/includes/Hooks.php b/includes/Hooks.php
index ae165cf..74aca6a 100644
--- a/includes/Hooks.php
+++ b/includes/Hooks.php
@@ -105,7 +105,7 @@
                $key = wfMemcKey( 'phptags', 'loadJsonFiles' );
                $cached = $cache->get( $key );
                if ( $cached !== false &&
-                               $cached['JSONLOADER'] === 
PHPTAGS_JSONLOADER_RELEASE  &&
+                               $cached['JSONLOADER'] === JsonLoader::VERSION &&
                                $cached['jsonFiles'] === self::$jsonFiles &&
                                $cached['callbackConstants'] === 
self::$callbackConstants ) {
                        \wfDebugLog( 'PhpTags', __METHOD__ . '() using cache: 
yes' );
@@ -117,7 +117,7 @@
                        $data['constantValues'] += self::loadConstantValues();
                        $data['jsonFiles'] = self::$jsonFiles;
                        $data['callbackConstants'] = self::$callbackConstants;
-                       $data['JSONLOADER'] = PHPTAGS_JSONLOADER_RELEASE;
+                       $data['JSONLOADER'] = JsonLoader::VERSION;
                        $cache->set( $key, $data );
                }
                self::$jsonFiles = null;
@@ -406,13 +406,24 @@
        }
 
        /**
-        * @deprecated since version 5.2.0
+        *
         * @param type $name
         * @param type $object
         * @param type $value
         */
        public static function callSetObjectsProperty( $name, $object, $value ) 
{
-               return self::callSetObjectProperty( $value, strtolower( $name 
), $object );
+               $oldValue = self::$value;
+               self::$value = array(
+                       Runtime::B_HOOK_TYPE => Runtime::H_SET_OBJECT_PROPERTY,
+                       Runtime::B_METHOD => $name,
+                       Runtime::B_METHOD_KEY => null,
+                       Runtime::B_OBJECT => $object,
+               );
+
+               $return = self::callSetObjectProperty( $value, strtolower( 
$name ), $object );
+
+               self::$value = $oldValue;
+               return $return;
        }
 
        /**
@@ -422,7 +433,7 @@
         * @param \PhpTags\GenericObject $object
         * @return mixded
         */
-       public static function callSetObjectProperty( $value, $propertyKey, 
$object ) {
+       private static function callSetObjectProperty( $value, $propertyKey, 
$object ) {
                if ( false === $object instanceof GenericObject ) {
                        Runtime::pushException( new PhpTagsException( 
PhpTagsException::WARNING_ATTEMPT_TO_ASSIGN_PROPERTY ) );
                }
@@ -464,6 +475,7 @@
                        $objectKey = strtolower( $calledObjectName );
                }
 
+               $oldValue = self::$value;
                self::$value = array(
                        Runtime::B_HOOK_TYPE => Runtime::H_NEW_OBJECT,
                        Runtime::B_METHOD => '__construct',
@@ -492,6 +504,7 @@
                        }
                        throw new PhpTagsException( 
PhpTagsException::FATAL_OBJECT_NOT_CREATED, $message );
                }
+               self::$value = $oldValue;
                return $newObject;
        }
 
diff --git a/includes/JsonLoader.php b/includes/JsonLoader.php
index 5e4e2cf..81c630a 100644
--- a/includes/JsonLoader.php
+++ b/includes/JsonLoader.php
@@ -11,6 +11,8 @@
  */
 class JsonLoader {
 
+       const VERSION = 3;
+
        public static function load( $files ) {
                $objects = array();
                $functions = array();
diff --git a/includes/PhpTagsConstants.php b/includes/PhpTagsConstants.php
new file mode 100644
index 0000000..af8fcfe
--- /dev/null
+++ b/includes/PhpTagsConstants.php
@@ -0,0 +1,34 @@
+<?php
+namespace PhpTagsObjects;
+
+/**
+ *
+ *
+ * @file PhpTagsConstants.php
+ * @author Pavel Astakhov <pastak...@yandex.ru>
+ * @licence GNU General Public Licence 2.0 or later
+ */
+class PhpTagsConstants extends \PhpTags\GenericObject {
+
+       public static function getConstantValue( $constantName ) {
+               static $phptagsVersion = false;
+
+               if ( $phptagsVersion === false ) {
+                       $phptagsVersion = 
\ExtensionRegistry::getInstance()->getAllThings()['PhpTags']['version'];
+               }
+
+               switch ( $constantName ) {
+                       case 'PHPTAGS_VERSION':
+                               return $phptagsVersion;
+                       case 'PHPTAGS_MAJOR_VERSION':
+                               return (int)split( $phptagsVersion, '.' )[0];
+                       case 'PHPTAGS_MINOR_VERSION':
+                               $v = split( $phptagsVersion, '.' );
+                               return isset( $v[1] ) ? (int)$v[1] : 0;
+                       case 'PHPTAGS_RELEASE_VERSION':
+                               $v = split( $phptagsVersion, '.' );
+                               return isset( $v[2] ) ? (int)$v[2] : 0;
+               }
+               return parent::getConstantValue( $constantName );
+       }
+}
diff --git a/includes/PhpTagsException.php b/includes/PhpTagsException.php
index 180080c..e9e549d 100644
--- a/includes/PhpTagsException.php
+++ b/includes/PhpTagsException.php
@@ -191,6 +191,15 @@
                        case self::WARNING_ILLEGAL_OFFSET_TYPE:
                                $message = 'Illegal offset type';
                                break;
+                       case self::FATAL_CANNOT_USE_OBJECT_AS_ARRAY:
+                               $message = 'Cannot use object as array';
+                               break;
+                       case self::FATAL_UNSUPPORTED_OPERAND_TYPES:
+                               $message = 'Unsupported operand types';
+                               break;
+                       case self::FATAL_INTERNAL_ERROR:
+                               $message = 'Unexpected behavior of PhpTags 
(Internal Error):' . $arguments;
+                               break;
                        default:
                                $message = "Undefined error, code 
{$this->code}";
                                $this->code = self::EXCEPTION_FATAL * 1000;
@@ -281,11 +290,15 @@
        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_CANNOT_USE_OBJECT_AS_ARRAY = 4023; // Cannot use object of 
type %%%%%% as array
+       const FATAL_UNSUPPORTED_OPERAND_TYPES = 4024; // Unsupported operand 
types, example: [1] + 1
 
        const FATAL_DENIED_FOR_NAMESPACE = 4500;
        const FATAL_CALLFUNCTION_INVALID_HOOK = 4501;
        const FATAL_CALLCONSTANT_INVALID_HOOK = 4502;
 
+       const FATAL_INTERNAL_ERROR = 4999; // Unexpected behavior
+
        const EXCEPTION_CATCHABLE_FATAL = 5;
        const FATAL_OBJECT_COULD_NOT_BE_CONVERTED = 5001;  //PHP Catchable 
fatal error:  Object of class stdClass could not be converted to string
 
diff --git a/includes/Renderer.php b/includes/Renderer.php
index 7960aea..a994669 100644
--- a/includes/Renderer.php
+++ b/includes/Renderer.php
@@ -121,8 +121,8 @@
         * @return array
         */
        private static function getBytecode( $source, $parser, $frame, 
$frameTitle, $frameTitleText ) {
-               global $wgPhpTagsBytecodeExptime, $wgPhpTagsCounter;
-               $wgPhpTagsCounter++;
+               global $wgPhpTagsBytecodeExptime, $wgPhpTagsCallsCounter;
+               $wgPhpTagsCallsCounter++;
 
                static $parserTitle = false;
                if ( $parserTitle === false ) {
@@ -136,7 +136,7 @@
                if ( true === isset( self::$bytecodeCache[$revID][$md5Source] ) 
) {
                        \wfDebugLog( 'PhpTags', 'Memory hiting with key ' . 
$revID );
                        self::$memoryHit++;
-                       return self::$bytecodeCache[$revID][$md5Source];
+                       return unserialize( 
self::$bytecodeCache[$revID][$md5Source] );
                }
 
                if ( $wgPhpTagsBytecodeExptime > 0 && $revID > 0 && false === 
isset( self::$bytecodeLoaded[$revID] ) ) {
@@ -144,26 +144,26 @@
                        $key = \wfMemcKey( 'PhpTags', $revID );
                        $data = $cache->get( $key );
                        self::$bytecodeLoaded[$revID] = true;
-                       if ( $data !== false && $data[0] === 
PHPTAGS_RUNTIME_RELEASE ) {
+                       if ( $data !== false && $data[0] === Runtime::VERSION ) 
{
                                self::$bytecodeCache[$revID] = $data[1];
                                if ( true === isset( 
self::$bytecodeCache[$revID][$md5Source] ) ) {
                                        \wfDebugLog( 'PhpTags', 'Cache hiting 
with key ' . $revID );
                                        self::$cacheHit++;
-                                       return 
self::$bytecodeCache[$revID][$md5Source];
+                                       return unserialize( 
self::$bytecodeCache[$revID][$md5Source] );
                                }
                        }
                        \wfDebugLog( 'PhpTags', 'Cache missing with key ' . 
$revID );
                }
 
-               $bytecode = Compiler::compile( $source, $frameTitleText );
+               $bytecode = serialize( Compiler::compile( $source, 
$frameTitleText ) );
                self::$bytecodeCache[$revID][$md5Source] = $bytecode;
                if ( $revID > 0 ) { // Don't save bytecode of unsaved pages
-                       self::$bytecodeNeedsUpdate[$revID][$md5Source] = 
unserialize( serialize( $bytecode ) );
+                       self::$bytecodeNeedsUpdate[$revID][$md5Source] = 
$bytecode;
                }
 
                self::$compileHit++;
                Timer::addCompileTime( $parser );
-               return $bytecode;
+               return unserialize( $bytecode );
        }
 
        /**
@@ -180,7 +180,7 @@
                }
 
                if ( true === self::$needInitRuntime ) {
-                       \wfDebugLog( 'PhpTags', 'Run hook 
PhpTagsRuntimeFirstInit' );
+                       \wfDebug( 'PhpTags: Run hook PhpTagsRuntimeFirstInit' );
                        \Hooks::run( 'PhpTagsRuntimeFirstInit' );
                        Hooks::loadData();
                        Runtime::$loopsLimit = $wgPhpTagsMaxLoops;
@@ -197,7 +197,7 @@
                $cache = \wfGetCache( CACHE_ANYTHING );
                foreach ( self::$bytecodeNeedsUpdate as $revID => $data ) {
                        $key = wfMemcKey( 'PhpTags', $revID );
-                       $cache->set( $key, array(PHPTAGS_RUNTIME_RELEASE, 
$data), $wgPhpTagsBytecodeExptime );
+                       $cache->set( $key, array(Runtime::VERSION, $data), 
$wgPhpTagsBytecodeExptime );
                        \wfDebugLog( 'PhpTags', 'Save compiled bytecode to 
cache with key ' . $revID );
                }
                self::$bytecodeNeedsUpdate = array();
@@ -206,8 +206,8 @@
        public static function reset() {
                self::writeLimitReport();
 
-               global $wgPhpTagsCounter;
-               $wgPhpTagsCounter = 0;
+               global $wgPhpTagsCallsCounter;
+               $wgPhpTagsCallsCounter = 0;
                Runtime::reset();
                Timer::reset();
                self::$bytecodeCache = array();
@@ -240,7 +240,7 @@
        }
 
        public static function writeLimitReport() {
-               global $wgPhpTagsCounter, $wgPhpTagsLimitReport;
+               global $wgPhpTagsCallsCounter, $wgPhpTagsLimitReport;
 
                $time = Timer::getRunTime();
                $compileTime = Timer::getCompileTime();
@@ -252,7 +252,7 @@
 Total   : %.3f sec
 -----------------------------------------------------------
 ',
-                               $wgPhpTagsCounter,
+                               $wgPhpTagsCallsCounter,
                                $time - $compileTime,
                                $compileTime,
                                self::$compileHit,
@@ -343,6 +343,32 @@
                }
        }
 
+       /**
+        *
+        * @see Parser::insertStripItem()
+        * @param string $text
+        * @return string
+        */
+       public static function insertNoWiki( $text ) {
+               $parser = self::$parser;
+               if ( $parser === null ) { // skip in php unit tests
+                       return $text;
+               }
+               $rnd = 
"{$parser->mUniqPrefix}-phptags-{$parser->mMarkerIndex}-" . 
\Parser::MARKER_SUFFIX;
+               $parser->mMarkerIndex++;
+               $parser->mStripState->addNoWiki( $rnd, $text );
+               return $rnd;
+       }
+
+
+       public static function insertStripItem( $text ) {
+               $parser = self::$parser;
+               if ( $parser === null ) { // skip in php unit tests
+                       return $text;
+               }
+               return $parser->insertStripItem( $text );
+       }
+
 }
 
 class Timer {
diff --git a/includes/Runtime.php b/includes/Runtime.php
index eb3f4fe..2bf5210 100644
--- a/includes/Runtime.php
+++ b/includes/Runtime.php
@@ -11,6 +11,8 @@
  */
 class Runtime {
 
+       const VERSION = 11;
+
        ##### Bytecode array indexes #####
        const B_COMMAND = 0; // Token ID
        const B_RESULT = 1;
@@ -27,6 +29,9 @@
        const B_HOOK_TYPE = 12; // describes PhpTags hook type, constant, 
function etc (self::H_...)
        const B_METHOD = 13; // method or function name
        const B_METHOD_KEY = 14; // method or function name in lower case
+       const B_FLAGS = 15;
+
+       const F_DONT_CHECK_PARAM1 = 1;
 
        ##### Hook types #####
        const H_GET_CONSTANT = '_';
@@ -57,6 +62,9 @@
        const S_MEMORY = 5;
        const S_PLACE = 6;
        const S_VARIABLES = 7;
+
+       const R_ARRAY = 'Array';
+       const R_DUMP_OBJECT = 'object';
 
        private static $operators = array(
                self::T_QUOTE => 'doQuote',
@@ -161,7 +169,20 @@
         * @param array $value
         */
        private static function doQuote ( &$value ) {
-               $value[self::B_RESULT] = implode( $value[self::B_PARAM_1] );
+               $implode = array();
+               foreach ( $value[self::B_PARAM_1] as $v ) {
+                       if ( $v === null || is_scalar( $v ) ) {
+                               $implode[] = $v;
+                       } else if ( is_array( $v ) ) {
+                               self::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING ) );
+                               $implode[] = self::R_ARRAY;
+                       } else if ( $v instanceof GenericObject ) {
+                               $implode[] = $v->toString();
+                       } else {
+                               throw new PhpTagsException( 
PhpTagsException::FATAL_INTERNAL_ERROR, __LINE__ );
+                       }
+               }
+               $value[self::B_RESULT] = implode( $implode );
        }
 
        /**
@@ -169,7 +190,8 @@
         * @param array $value
         */
        private static function doConcat ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] . 
$value[self::B_PARAM_2];
+               $v = self::checkStringParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2], $value[self::B_FLAGS] );
+               $value[self::B_RESULT] = $v[0] . $v[1];
        }
 
        /**
@@ -177,7 +199,8 @@
         * @param array $value
         */
        private static function doPlus ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] + 
$value[self::B_PARAM_2];
+               $v = self::checkArrayParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] + $v[1];
        }
 
        /**
@@ -185,7 +208,8 @@
         * @param array $value
         */
        private static function doMinus ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] - 
$value[self::B_PARAM_2];
+               $v = self::checkScalarParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] - $v[1];
        }
 
        /**
@@ -193,7 +217,10 @@
         * @param array $value
         */
        private static function doMul ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] * 
$value[self::B_PARAM_2];
+               $v1 = $value[self::B_PARAM_1];
+               $v2 = $value[self::B_PARAM_2];
+               self::checkScalarParams( $v1, $v2 );
+               $value[self::B_RESULT] = $v1 * $v2;
        }
 
        /**
@@ -201,7 +228,15 @@
         * @param array $value
         */
        private static function doDiv ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] / 
$value[self::B_PARAM_2];
+               $v1 = $value[self::B_PARAM_1];
+               $v2 = $value[self::B_PARAM_2];
+               self::checkScalarParams( $v1, $v2 );
+               if ( $v2 == 0 ) {
+                       self::pushException( new PhpTagsException( 
PhpTagsException::WARNING_DIVISION_BY_ZERO ) );
+                       $value[self::B_RESULT] = false;
+               } else {
+                       $value[self::B_RESULT] = $v1 / $v2;
+               }
        }
 
        /**
@@ -209,7 +244,15 @@
         * @param array $value
         */
        private static function doMod ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] % 
$value[self::B_PARAM_2];
+               $v1 = $value[self::B_PARAM_1];
+               $v2 = $value[self::B_PARAM_2];
+               self::checkScalarParams( $v1, $v2 );
+               if ( $v2 == 0 ) {
+                       self::pushException( new PhpTagsException( 
PhpTagsException::WARNING_DIVISION_BY_ZERO ) );
+                       $value[self::B_RESULT] = false;
+               } else {
+                       $value[self::B_RESULT] = $v1 % $v2;
+               }
        }
 
        /**
@@ -217,7 +260,8 @@
         * @param array $value
         */
        private static function doAnd ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] & 
$value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] & $v[1];
        }
 
        /**
@@ -225,7 +269,8 @@
         * @param array $value
         */
        private static function doOr ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] | 
$value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] | $v[1];
        }
 
        /**
@@ -233,7 +278,8 @@
         * @param array $value
         */
        private static function doXor ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] ^ 
$value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] ^ $v[1];
        }
 
        /**
@@ -241,7 +287,8 @@
         * @param array $value
         */
        private static function doShiftLeft ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] << 
$value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] << $v[1];
        }
 
        /**
@@ -249,7 +296,8 @@
         * @param array $value
         */
        private static function doShiftRight ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] >> 
$value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] >> $v[1];
        }
 
        /**
@@ -281,7 +329,8 @@
         * @param array $value
         */
        private static function doIsSmaller ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] < 
$value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] < $v[1];
        }
 
        /**
@@ -289,7 +338,8 @@
         * @param array $value
         */
        private static function doIsGreater ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] > 
$value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] > $v[1];
        }
 
        /**
@@ -297,7 +347,8 @@
         * @param array $value
         */
        private static function doIsSmallerOrEqual ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] <= 
$value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] <= $v[1];
        }
 
        /**
@@ -305,7 +356,8 @@
         * @param array $value
         */
        private static function doIsGreaterOrEqual ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] >= 
$value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] >= $v[1];
        }
 
        /**
@@ -313,7 +365,8 @@
         * @param array $value
         */
        private static function doIsEqual ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] == 
$value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] == $v[1];
        }
 
        /**
@@ -321,7 +374,8 @@
         * @param array $value
         */
        private static function doIsNotEqual ( &$value ) {
-               $value[self::B_RESULT] = $value[self::B_PARAM_1] != 
$value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $value[self::B_PARAM_1], 
$value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $v[0] != $v[1];
        }
 
        /**
@@ -345,10 +399,16 @@
         * @param array $value
         */
        private static function doPrint ( &$value ) {
-               if( $value[self::B_PARAM_1] instanceof GenericObject ) {
-                       self::$stack[0][self::S_RETURN][] = 
$value[self::B_PARAM_1]->toString();
-               } else {
+               $v = $value[self::B_PARAM_1];
+               if ( is_scalar( $v ) || $v === null ) {
                        self::$stack[0][self::S_RETURN][] = 
$value[self::B_PARAM_1];
+               } else if( $v instanceof GenericObject ) {
+                       self::$stack[0][self::S_RETURN][] = 
$value[self::B_PARAM_1]->toString();
+               } else if ( is_array( $v ) ) {
+                       self::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING ) );
+                       self::$stack[0][self::S_RETURN][] = self::R_ARRAY;
+               } else { // Should never happen
+                       throw new PhpTagsException( 
PhpTagsException::FATAL_INTERNAL_ERROR, __LINE__ );
                }
        }
 
@@ -357,7 +417,12 @@
         * @param array $value
         */
        private static function doNot ( &$value ) {
-               $value[self::B_RESULT] = ~$value[self::B_PARAM_2];
+               $v = $value[self::B_PARAM_2];
+               if ( $v === null || is_scalar( $v ) ) {
+                       $value[self::B_RESULT] = ~$v;
+               } else {
+                       throw new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES );
+               }
        }
 
        /**
@@ -373,7 +438,9 @@
         * @param array $value
         */
        private static function doIntCast ( &$value ) {
-               $value[self::B_RESULT] = (int)$value[self::B_PARAM_2];
+               $tmp = null;
+               $v = self::checkObjectParams( $value[self::B_PARAM_2], $tmp );
+               $value[self::B_RESULT] = (int)$v[0];
        }
 
        /**
@@ -381,7 +448,9 @@
         * @param array $value
         */
        private static function doDoubleCast ( &$value ) {
-               $value[self::B_RESULT] = (double)$value[self::B_PARAM_2];
+               $tmp = null;
+               $v = self::checkObjectParams( $value[self::B_PARAM_2], $tmp, 
'double' );
+               $value[self::B_RESULT] = (double)$v[0];
        }
 
        /**
@@ -389,7 +458,10 @@
         * @param array $value
         */
        private static function doStringCast ( &$value ) {
-               $value[self::B_RESULT] = (string)$value[self::B_PARAM_2];
+               $tmp = null;
+               $flags = 0;
+               $v = self::checkStringParams( $value[self::B_PARAM_2], $tmp, 
$flags );
+               $value[self::B_RESULT] = (string)$v[0];
        }
 
        /**
@@ -397,7 +469,15 @@
         * @param array $value
         */
        private static function doArrayCast ( &$value ) {
-               $value[self::B_RESULT] = (array)$value[self::B_PARAM_2];
+               $v = $value[self::B_PARAM_2];
+               if ( is_object( $v ) ) {
+                       if ( $v instanceof GenericObject ) {
+                               $v = $v->getDumpValue();
+                       } else {
+                               throw new PhpTagsException( 
PhpTagsException::FATAL_INTERNAL_ERROR, __LINE__ );
+                       }
+               }
+               $value[self::B_RESULT] = (array)$v;
        }
 
        /**
@@ -413,7 +493,7 @@
         * @param array $value
         */
        private static function doUnsetCast ( &$value ) {
-               $value[self::B_RESULT] = (unset)$value[self::B_PARAM_2];
+               $value[self::B_RESULT] = null; //(unset)$value[self::B_PARAM_2];
        }
 
        /**
@@ -673,9 +753,9 @@
        private static function doCallingHook ( &$value ) {
                $result = Hooks::callHook( $value );
 
-               if ( $result instanceof outPrint ) {
-                       $value[self::B_RESULT] = $result->returnValue;
-                       self::$stack[0][self::S_RETURN][] = $result;
+               if ( $result instanceof iRawOutput ) {
+                       $value[self::B_RESULT] = $result->getReturnValue();
+                       self::$stack[0][self::S_RETURN][] = 
$result->placeAsStripItem();
                } else {
                        $value[self::B_RESULT] = $result;
                }
@@ -735,16 +815,16 @@
         */
        private static function doIsSet ( &$value ) {
                $variables =& self::$stack[0][self::S_VARIABLES];
-               foreach($value[self::B_PARAM_1] as $val) {
-                       if( !isset($variables[ $val[self::B_PARAM_1] ]) ) { // 
undefined variable or variable is null
+               foreach ( $value[self::B_PARAM_1] as $val ) {
+                       if ( !isset( $variables[ $val[self::B_PARAM_1] ] ) ) { 
// undefined variable or variable is null
                                $value[self::B_RESULT] = false;
                                return;
                        } // true, variable is defined
-                       if( isset($val[self::B_ARRAY_INDEX]) ) { // Example: 
isset($foo[1])
+                       if( isset( $val[self::B_ARRAY_INDEX] ) ) { // Example: 
isset($foo[1])
                                $ref =& $variables[ $val[self::B_PARAM_1] ];
                                $tmp = array_pop( $val[self::B_ARRAY_INDEX] );
                                foreach( $val[self::B_ARRAY_INDEX] as $v ) {
-                                       if( !isset($ref[$v]) ) { // undefined 
array index
+                                       if( !isset( $ref[$v] ) ) { // undefined 
array index
                                                $value[self::B_RESULT] = false;
                                                return;
                                        }
@@ -866,7 +946,8 @@
         */
        private static function doSetConcatVal ( &$value ) {
                $ref =& self::getVariableRef( $value );
-               $value[self::B_RESULT] = $ref .= $value[self::B_PARAM_2];
+               $v = self::checkStringParams( $ref, $value[self::B_PARAM_2], 
$value[self::B_FLAGS] );
+               $value[self::B_RESULT] = $ref = $v[0] . $v[1];
        }
 
        /**
@@ -875,7 +956,8 @@
         */
        private static function doSetPlusVal ( &$value ) {
                $ref =& self::getVariableRef( $value );
-               $value[self::B_RESULT] = $ref += $value[self::B_PARAM_2];
+               $v = self::checkArrayParams( $ref, $value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $ref = $v[0] + $v[1];
        }
 
        /**
@@ -884,7 +966,8 @@
         */
        private static function doSetMinusVal ( &$value ) {
                $ref =& self::getVariableRef( $value );
-               $value[self::B_RESULT] = $ref -= $value[self::B_PARAM_2];
+               $v = self::checkScalarParams( $ref, $value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $ref = $v[0] - $v[1];
        }
 
        /**
@@ -893,7 +976,8 @@
         */
        private static function doSetMulVal ( &$value ) {
                $ref =& self::getVariableRef( $value );
-               $value[self::B_RESULT] = $ref *= $value[self::B_PARAM_2];
+               $v = self::checkScalarParams( $ref, $value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $ref = $v[0] * $v[1];
        }
 
        /**
@@ -902,7 +986,13 @@
         */
        private static function doSetDivVal ( &$value ) {
                $ref =& self::getVariableRef( $value );
-               $value[self::B_RESULT] = $ref /= $value[self::B_PARAM_2];
+               $v = self::checkScalarParams( $ref, $value[self::B_PARAM_2] );
+               if ( $v[1] == 0 ) {
+                       self::pushException( new PhpTagsException( 
PhpTagsException::WARNING_DIVISION_BY_ZERO ) );
+                       $value[self::B_RESULT] = $ref = false;
+               } else {
+                       $value[self::B_RESULT] = $ref = $v[0] / $v[1];
+               }
        }
 
        /**
@@ -911,7 +1001,13 @@
         */
        private static function doSetModVal ( &$value ) {
                $ref =& self::getVariableRef( $value );
-               $value[self::B_RESULT] = $ref %= $value[self::B_PARAM_2];
+               $v = self::checkScalarParams( $ref, $value[self::B_PARAM_2] );
+               if ( $v[1] == 0 ) {
+                       self::pushException( new PhpTagsException( 
PhpTagsException::WARNING_DIVISION_BY_ZERO ) );
+                       $value[self::B_RESULT] = $ref = false;
+               } else {
+                       $value[self::B_RESULT] = $ref = $v[0] % $v[1];
+               }
        }
 
        /**
@@ -920,7 +1016,8 @@
         */
        private static function doSetAndVal ( &$value ) {
                $ref =& self::getVariableRef( $value );
-               $value[self::B_RESULT] = $ref &= $value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $ref, $value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $ref = $v[0] & $v[1];
        }
 
        /**
@@ -929,7 +1026,8 @@
         */
        private static function doSetOrVal ( &$value ) {
                $ref =& self::getVariableRef( $value );
-               $value[self::B_RESULT] = $ref |= $value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $ref, $value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $ref = $v[0] | $v[1];
        }
 
        /**
@@ -938,7 +1036,8 @@
         */
        private static function doSetXorVal ( &$value ) {
                $ref =& self::getVariableRef( $value );
-               $value[self::B_RESULT] = $ref ^= $value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $ref, $value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $ref = $v[0] ^ $v[1];
        }
 
        /**
@@ -947,7 +1046,8 @@
         */
        private static function doSetShiftLeftVal ( &$value ) {
                $ref =& self::getVariableRef( $value );
-               $value[self::B_RESULT] = $ref <<= $value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $ref, $value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $ref = $v[0] << $v[1];
        }
 
        /**
@@ -956,7 +1056,86 @@
         */
        private static function doSetShiftRightVal ( &$value ) {
                $ref =& self::getVariableRef( $value );
-               $value[self::B_RESULT] = $ref <<= $value[self::B_PARAM_2];
+               $v = self::checkObjectParams( $ref, $value[self::B_PARAM_2] );
+               $value[self::B_RESULT] = $ref = $v[0] >> $v[1];
+       }
+
+       private static function checkStringParams( &$v1, &$v2, &$flags ) {
+               $return = array( $v1, $v2 );
+
+               if ( $v1 !== null && !is_scalar( $v1 ) ) {
+                       if ( is_array( $v1 ) ) {
+                               if ( !($flags & self::F_DONT_CHECK_PARAM1) ) {
+                                       self::pushException( new 
PhpTagsException( PhpTagsException::NOTICE_ARRAY_TO_STRING ) );
+                                       $return[0] = self::R_ARRAY;
+                               }
+                       } else if ( $v1 instanceof GenericObject ) {
+                               $return[0] = $v1->toString();
+                       } else {
+                               throw new PhpTagsException( 
PhpTagsException::FATAL_INTERNAL_ERROR, __LINE__ );
+                       }
+               }
+               if ( $v2 !== null && !is_scalar( $v2 ) ) {
+                       if ( is_array( $v2 ) ) {
+                               self::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING ) );
+                               $return[1] = self::R_ARRAY;
+                       } else if ( $v2 instanceof GenericObject ) {
+                               $return[1] = $v2->toString();
+                       } else {
+                               throw new PhpTagsException( 
PhpTagsException::FATAL_INTERNAL_ERROR, __LINE__ );
+                       }
+               }
+
+               return $return;
+       }
+
+       private static function checkArrayParams( &$v1, &$v2 ) {
+               if ( !($v1 === null || is_scalar( $v1 )) || !($v2 === null || 
is_scalar( $v2 )) ) {
+                       $return = self::checkObjectParams( $v1, $v2 );
+                       if ( is_array( $v1 ) xor is_array( $v2 ) ) { // [1] + 1 
or 1 + [1]
+                               throw new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES );
+                       }
+               } else {
+                       $return = array( $v1, $v2 );
+               }
+
+               return $return;
+       }
+
+       private static function checkScalarParams( &$v1, &$v2 ) {
+               if ( !($v1 === null || is_scalar( $v1 )) || !($v2 === null || 
is_scalar( $v2 )) ) {
+                       $return = self::checkObjectParams( $v1, $v2 );
+                       if ( is_array( $v1 ) || is_array( $v2 ) ) { // [1] + 1 
or 1 + [1]
+                               throw new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES );
+                       }
+               } else {
+                       $return = array( $v1, $v2 );
+               }
+
+               return $return;
+       }
+
+       private static function checkObjectParams( &$v1, &$v2, $to = 'int' ) {
+               $return = array( $v1, $v2 );
+
+               if ( is_object( $v1 ) ) {
+                       if ( $v1 instanceof GenericObject ) {
+                               self::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array($v1->getName(), $to) ) );
+                               $return[0] = 1;
+                       } else {
+                               throw new PhpTagsException( 
PhpTagsException::FATAL_INTERNAL_ERROR, __LINE__ );
+                       }
+               }
+               if ( is_object( $v2 ) ) {
+                       if ( $v2 instanceof GenericObject ) {
+                               self::pushException( new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array($v2->getName(), $to) ) );
+                               $return[1] = 1;
+                       } else {
+                               throw new PhpTagsException( 
PhpTagsException::FATAL_INTERNAL_ERROR, __LINE__ );
+                       }
+               }
+
+               return $return;
        }
 
        private static function & getVariableRef( $value ) {
@@ -972,6 +1151,18 @@
                $ref =& $variables[$variableName];
                if ( isset($var[self::B_ARRAY_INDEX]) ) { // Example: $foo[1]++
                        foreach ( $var[self::B_ARRAY_INDEX] as $v ) {
+                               if ( $ref === true || $ref === false ) {
+                                       if ( $v === INF ) { // Example: $foo[]
+                                               $ref = array();
+                                       }
+                               } else if ( is_scalar( $ref ) ) {
+                                       self::pushException( new 
PhpTagsException( PhpTagsException::WARNING_SCALAR_VALUE_AS_ARRAY, null ) );
+                                       unset( $ref );
+                                       $ref = null;
+                                       break;
+                               } else if ( is_object( $ref ) ) {
+                                       throw new PhpTagsException( 
PhpTagsException::FATAL_CANNOT_USE_OBJECT_AS_ARRAY, $ref );
+                               }
                                if ( $v === INF ) { // Example: $foo[]
                                        $t = null;
                                        $ref[] = &$t;
@@ -985,7 +1176,7 @@
                                                }
                                                $ref[$v] = null;
                                                $ref =& $ref[$v];
-                                       } elseif ( is_array($ref) ) {
+                                       } else {
                                                if ( !( isset($ref[$v]) || 
array_key_exists($v, $ref) ) ) {
                                                        $ref[$v] = null;
                                                        if( 
$value[self::B_COMMAND] !== self::T_EQUAL ) {
@@ -994,12 +1185,6 @@
                                                        }
                                                }
                                                $ref =& $ref[$v];
-                                       } else { // scalar
-                                               // PHP Warning:  Cannot use a 
scalar value as an array
-                                               self::pushException( new 
PhpTagsException( PhpTagsException::WARNING_SCALAR_VALUE_AS_ARRAY, null ) );
-                                               unset( $ref );
-                                               $ref = null;
-                                               break;
                                        }
                                }
                        }
@@ -1008,7 +1193,6 @@
        }
 
        public static function run( $code, array $args, $scope = '' ) {
-               set_error_handler( '\\PhpTags\\ErrorHandler::onError' );
                try {
                        if( false === isset( self::$variables[$scope] ) ) {
                                self::$variables[$scope] = array();
@@ -1054,17 +1238,15 @@
                        self::$ignoreErrors = false;
                } catch ( \Exception $e ) {
                        Renderer::addRuntimeErrorCategory();
-                       restore_error_handler();
                        self::$ignoreErrors = false;
                        array_shift( self::$stack );
                        throw $e;
                }
-               restore_error_handler();
                array_shift( self::$stack );
                return $stack[self::S_RETURN];
        }
 
-       static function fillList( &$values, &$parametrs, $offset = false ) {
+       private static function fillList( &$values, &$parametrs, $offset = 
false ) {
                $return = array();
 
                for ( $pkey = count( $parametrs ) - 1; $pkey >= 0; --$pkey ) {
diff --git a/includes/iRawOutput.php b/includes/iRawOutput.php
index 33813cb..6e3abc0 100644
--- a/includes/iRawOutput.php
+++ b/includes/iRawOutput.php
@@ -9,5 +9,11 @@
  * @licence GNU General Public Licence 2.0 or later
  */
 interface iRawOutput {
+
        public function __toString();
-}
\ No newline at end of file
+
+       public function getReturnValue();
+
+       public function placeAsStripItem();
+
+}
diff --git a/includes/outPrint.php b/includes/outPrint.php
index 22f4540..4d41582 100644
--- a/includes/outPrint.php
+++ b/includes/outPrint.php
@@ -9,28 +9,41 @@
  * @licence GNU General Public Licence 2.0 or later
  */
 class outPrint implements iRawOutput {
-       public $returnValue=null;
-       private $contents;
-       private $raw;
+       private $returnValue;
+       private $content;
        private $element;
        private $attribs;
 
-       public function __construct( $returnValue, $contents, $raw=false, 
$element='pre', $attribs = array() ) {
+       /**
+        *
+        * @param mixed $returnValue
+        * @param string $content
+        * @param bool $raw
+        * @param string|false $element
+        * @param array $attribs
+        * @param array $sheath
+        */
+       public function __construct( $returnValue, $content, $raw=false, 
$element='pre', $attribs = array() ) {
                $this->returnValue = $returnValue;
-               $this->raw = $raw;
-               $this->contents = (string)$contents;
+               $this->content = $raw ? (string)$content : strtr( $content, 
array('&'=>'&amp;', '<'=>'&lt;') );
                $this->element = $element;
                $this->attribs = $attribs;
        }
 
        public function __toString() {
-               if( $this->element !== false ){
-                       if( $this->raw ) {
-                               return \Html::rawElement( $this->element, 
array(), $this->contents ) . "\n";
-                       }else{
-                               return \Html::element( $this->element, array(), 
$this->contents ) . "\n";
-                       }
+               if ( $this->element ) {
+                       return \Html::rawElement( $this->element, 
$this->attribs, $this->content );
                }
-               return $this->raw ? "{$this->contents}\n" : strtr( 
$this->contents, array('&'=>'&amp;', '<'=>'&lt;') ) . "\n";
+               return $this->content;
        }
+
+       public function getReturnValue() {
+               return $this->returnValue;
+       }
+
+       public function placeAsStripItem() {
+               $this->content = Renderer::insertNoWiki( $this->content );
+               return Renderer::insertStripItem( $this );
+       }
+
 }
diff --git a/includes/outStrip.php b/includes/outStrip.php
new file mode 100644
index 0000000..387e80f
--- /dev/null
+++ b/includes/outStrip.php
@@ -0,0 +1,41 @@
+<?php
+namespace PhpTags;
+/**
+ * The outStrip class of the extension PHP Tags.
+ *
+ * @file outPrint.php
+ * @ingroup PhpTags
+ * @author Pavel Astakhov <pastak...@yandex.ru>
+ * @licence GNU General Public Licence 2.0 or later
+ */
+class outStrip implements iRawOutput {
+       private $returnValue;
+       private $strip;
+
+       /**
+        *
+        * @param mixed $returnValue
+        * @param string $strip
+        * @param bool $raw
+        * @param string|false $element
+        * @param array $attribs
+        * @param array $sheath
+        */
+       public function __construct( $returnValue, $strip ) {
+               $this->returnValue = $returnValue;
+               $this->strip = $strip;
+       }
+
+       public function __toString() {
+               return $this->strip;
+       }
+
+       public function getReturnValue() {
+               return $this->returnValue;
+       }
+
+       public function placeAsStripItem() {
+               return $this->strip;
+       }
+
+}
diff --git "a/tests/phpunit/includes/\041\041\041firstInit_Test.php" 
"b/tests/phpunit/includes/\041\041\041firstInit_Test.php"
index f2c021b..3815e37 100644
--- "a/tests/phpunit/includes/\041\041\041firstInit_Test.php"
+++ "b/tests/phpunit/includes/\041\041\041firstInit_Test.php"
@@ -1,20 +1,24 @@
 <?php
-\PhpTags\Hooks::addJsonFile( __DIR__ . '/PhpTags_test.json' );
-const PHPTAGS_TEST = 'Test';
-const PHPTAGS_TEST_BANNED = 'Test';
-\Hooks::register( 'PhpTagsBeforeCallRuntimeHook', function ( $hookType, 
$objectName, $methodName, $values ) {
-       if ( $hookType === \PhpTags\Runtime::H_GET_CONSTANT || $hookType === 
\PhpTags\Runtime::H_GET_OBJECT_CONSTANT ) {
-               $methodName = strtolower( $methodName );
-       }
-       if ( substr( $methodName, -6 ) === 'banned' ) {
-               $hookTypeString = \PhpTags\Hooks::getCallInfo( 
\PhpTags\Hooks::INFO_HOOK_TYPE_STRING );
-               \PhpTags\Runtime::pushException( new \PhpTags\HookException( 
"Sorry, you cannot use this $hookTypeString" ) );
-               return false;
-       }
-       return true;
-} );
 
 if ( \PhpTags\Renderer::$needInitRuntime ) {
+       wfDebug( 'PHPTags: test initialization ' . __FILE__ );
+
+       \PhpTags\Hooks::addJsonFile( __DIR__ . '/PhpTags_test.json' );
+       define( 'PHPTAGS_TEST', 'Test' );
+       define( 'PHPTAGS_TEST_BANNED', 'Test' );
+       \Hooks::register( 'PhpTagsBeforeCallRuntimeHook', function ( $hookType, 
$objectName, $methodName, $values ) {
+               if ( $hookType === \PhpTags\Runtime::H_GET_CONSTANT || 
$hookType === \PhpTags\Runtime::H_GET_OBJECT_CONSTANT ) {
+                       $methodName = strtolower( $methodName );
+               }
+               if ( substr( $methodName, -6 ) === 'banned' ) {
+                       $hookTypeString = \PhpTags\Hooks::getCallInfo( 
\PhpTags\Hooks::INFO_HOOK_TYPE_STRING );
+                       \PhpTags\Runtime::pushException( new 
\PhpTags\HookException( "Sorry, you cannot use this $hookTypeString" ) );
+                       return false;
+               }
+               return true;
+       } );
+
+       wfDebug( 'PHPTags: run hook PhpTagsRuntimeFirstInit ' . __FILE__ );
        \Hooks::run( 'PhpTagsRuntimeFirstInit' );
        \PhpTags\Hooks::loadData();
        \PhpTags\Runtime::$loopsLimit = 1000;
diff --git a/tests/phpunit/includes/RuntimeTest.php 
b/tests/phpunit/includes/RuntimeTest.php
index ed08b5d..e5fb022 100644
--- a/tests/phpunit/includes/RuntimeTest.php
+++ b/tests/phpunit/includes/RuntimeTest.php
@@ -53,6 +53,131 @@
                        );
        }
 
+       public function testRun_echo_heredoc_1() {
+               $this->assertEquals(
+                               Runtime::runSource('
+echo <<<EOT
+Example of string
+spanning multiple lines
+using heredoc syntax.
+EOT;
+'),
+                               array('Example of string
+spanning multiple lines
+using heredoc syntax.
+')
+                       );
+       }
+       public function testRun_echo_heredoc_2() {
+               $this->assertEquals(
+                               Runtime::runSource('
+echo <<<EOT
+Example of string
+spanning multiple lines
+using "heredoc" syntax.
+EOT;
+'),
+                               array('Example of string
+spanning multiple lines
+using "heredoc" syntax.
+')
+                       );
+       }
+       public function testRun_echo_heredoc_3() {
+               $this->assertEquals(
+                               Runtime::runSource('
+echo <<<EOT
+Example of string
+spanning multiple\n lines\n
+using "heredoc" syntax.
+EOT;
+'),
+                               array('Example of string
+spanning multiple
+ lines
+
+using "heredoc" syntax.
+')
+                       );
+       }
+       public function testRun_echo_heredoc_4() {
+               $this->assertEquals(
+                               Runtime::runSource('
+$foo = "BAR";
+echo <<<"EOT"
+Example of string $foo
+spanning multiple lines
+using heredoc syntax.
+EOT;
+'),
+                               array('Example of string BAR
+spanning multiple lines
+using heredoc syntax.
+')
+                       );
+       }
+       public function testRun_echo_nowdoc_1() {
+               $this->assertEquals(
+                               Runtime::runSource('
+echo <<<\'EOT\'
+Example of string
+spanning multiple lines
+using nowdoc syntax.
+EOT;
+'),
+                               array('Example of string
+spanning multiple lines
+using nowdoc syntax.
+')
+                       );
+       }
+       public function testRun_echo_nowdoc_2() {
+               $this->assertEquals(
+                               Runtime::runSource('
+echo <<<\'EOT\'
+Example of string
+spanning multiple lines
+using "nowdoc" syntax.
+EOT;
+'),
+                               array('Example of string
+spanning multiple lines
+using "nowdoc" syntax.
+')
+                       );
+       }
+       public function testRun_echo_nowdoc_3() {
+               $this->assertEquals(
+                               Runtime::runSource('
+echo <<<\'EOT\'
+Example of string
+spanning multiple\n lines\n
+using "nowdoc" syntax.
+EOT;
+'),
+                               array('Example of string
+spanning multiple\n lines\n
+using "nowdoc" syntax.
+')
+                       );
+       }
+       public function testRun_echo_nowdoc_4() {
+               $this->assertEquals(
+                               Runtime::runSource('
+$foo = "BAR";
+echo <<<\'EOT\'
+Example of string $foo
+spanning multiple lines
+using nowdoc syntax.
+EOT;
+'),
+                               array('Example of string $foo
+spanning multiple lines
+using nowdoc syntax.
+')
+                       );
+       }
+
        public function testRun_echo_union_1() {
                $this->assertEquals(
                                Runtime::runSource('echo "String" . "Union";'),
@@ -977,6 +1102,328 @@
                $this->assertEquals(
                                Runtime::runSource('$foo=1; $bar=2; $foo+=$bar; 
echo $foo,$bar;'),
                                array('3', '2')
+                       );
+       }
+       public function testRun_echo_assignment_7() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar="4"; 
$foo = $foo . $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       Runtime::R_ARRAY . 4,
+                                       '4',
+                               )
+                       );
+       }
+       public function testRun_echo_assignment_8() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo="4"; $bar=["rrr"]; 
$foo = $foo . $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       4 . Runtime::R_ARRAY,
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       Runtime::R_ARRAY,
+                               )
+                       );
+       }
+       public function testRun_echo_assignment_9() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar=["rrr"]; 
$foo = $foo . $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       Runtime::R_ARRAY . Runtime::R_ARRAY,
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       Runtime::R_ARRAY,
+                               )
+                       );
+       }
+       public function testRun_echo_assignment_10() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo="4"; $bar=["rrr"]; 
$foo .= $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       4 . Runtime::R_ARRAY,
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       Runtime::R_ARRAY,
+                               )
+                       );
+       }
+       public function testRun_echo_assignment_11() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo .= $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       Runtime::R_ARRAY . 'rrr',
+                                       'rrr',
+                               )
+                       );
+       }
+       public function testRun_echo_assignment_12() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar=["rrr"]; 
$foo .= $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       Runtime::R_ARRAY . Runtime::R_ARRAY,
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       Runtime::R_ARRAY,
+                               )
+                       );
+       }
+       public function testRun_echo_assignment_13() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar="4"; 
$foo=$foo+$bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_echo_assignment_14() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar="4"; 
$foo+=$bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_echo_assignment_15() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo="rrr"; $bar=["4"]; 
$foo+=$bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_echo_assignment_16() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar=["4"]; 
$foo+=$bar; echo $foo[0];', array('test'), 77777 ),
+                               array( 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_17() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar=["4"]; 
$foo = $foo + $bar; echo $foo[0];', array('test'), 77777 ),
+                               array( 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_18() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar="4"; 
$foo=$foo-$bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_echo_assignment_19() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar="4"; 
$foo-=$bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_echo_assignment_20() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar="4"; 
$foo=$foo*$bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_echo_assignment_21() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar="4"; 
$foo*=$bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_echo_assignment_22() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar="4"; 
$foo=$foo/$bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_echo_assignment_23() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar="4"; 
$foo/=$bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_echo_assignment_24() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo="rrr"; $bar=["4"]; 
$foo=$foo%$bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_echo_assignment_25() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo="rrr"; $bar=["4"]; 
$foo%=$bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_echo_assignment_26() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo = ($foo and $bar); echo $foo,$bar;', array('test'), 77777 ),
+                               array( '1', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_27() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo = ($foo or $bar); echo $foo,$bar;', array('test'), 77777 ),
+                               array( '1', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_28() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo = ($foo Xor $bar); echo $foo,$bar;', array('test'), 77777 ),
+                               array( '', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_29() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo = ($foo & $bar); echo $foo,$bar;', array('test'), 77777 ),
+                               array( '0', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_30() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo = ($foo | $bar); echo $foo,$bar;', array('test'), 77777 ),
+                               array( '1', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_31() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo = ($foo ^ $bar); echo $foo,$bar;', array('test'), 77777 ),
+                               array( '1', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_32() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo |= $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( '1', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_33() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo ^= $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( '1', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_34() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo &= $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( '0', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_35() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo = ($foo >> $bar); echo $foo,$bar;', array('test'), 77777 ),
+                               array( '1', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_36() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo="rrr"; $bar=["rrr"]; 
$foo = ($foo << $bar); echo $foo,$bar[0];', array('test'), 77777 ),
+                               array( '0', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_37() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo >>= $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( '1', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_38() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo="rrr"; $bar=["rrr"]; 
$foo <<= $bar; echo $foo,$bar[0];', array('test'), 77777 ),
+                               array( '0', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_39() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo = $foo > $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( '1', 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_40() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo="rrr"; $bar=["rrr"]; 
$foo = $foo < $bar; echo $foo,$bar[0];', array('test'), 77777 ),
+                               array( true, 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_41() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["4"]; $bar="rrr"; 
$foo = $foo == $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array( false, 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_42() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo="rrr"; $bar=["rrr"]; 
$foo = $foo != $bar; echo $foo,$bar[0];', array('test'), 77777 ),
+                               array( true, 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_43() {
+               $this->assertEquals(
+                               Runtime::runSource( '$bar=["rrr"]; $foo = 
~$bar; echo $foo,$bar[0];', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_echo_assignment_44() {
+               $this->assertEquals(
+                               Runtime::runSource( '$bar=["rrr"]; $foo = 
!$bar; echo $foo === false;', array('test'), 77777 ),
+                               array( true )
+                       );
+       }
+       public function testRun_echo_assignment_45() {
+               $this->assertEquals(
+                               Runtime::runSource( '$bar=["rrr"]; 
$foo=(int)$bar; echo $foo === 1;', array('test'), 77777 ),
+                               array( true )
+                       );
+       }
+       public function testRun_echo_assignment_46() {
+               $this->assertEquals(
+                               Runtime::runSource( '$bar=["rrr"]; 
$foo=(double)$bar; echo $foo === (double)1;', array('test'), 77777 ),
+                               array( true )
+                       );
+       }
+       public function testRun_echo_assignment_47() {
+               $this->assertEquals(
+                               Runtime::runSource( '$bar=["rrr"]; 
$foo=(string)$bar; echo $foo;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       Runtime::R_ARRAY,
+                               )
+                       );
+       }
+       public function testRun_echo_assignment_48() {
+               $this->assertEquals(
+                               Runtime::runSource( '$bar=["rrr"]; 
$foo=(array)$bar; echo $foo[0];', array('test'), 77777 ),
+                               array( 'rrr' )
+                       );
+       }
+       public function testRun_echo_assignment_49() {
+               $this->assertEquals(
+                               Runtime::runSource( '$bar=["rrr"]; 
$foo=(bool)$bar; echo $foo === true;', array('test'), 77777 ),
+                               array( true )
+                       );
+       }
+       public function testRun_echo_assignment_50() {
+               $this->assertEquals(
+                               Runtime::runSource( '$bar=["rrr"]; 
$foo=(unset)$bar; echo $foo === null;', array('test'), 77777 ),
+                               array( true )
+                       );
+       }
+
+       public function testRun_array_increase_test_1() {
+               $this->assertEquals(
+                               Runtime::runSource( '$bar=["rrr"]; $bar++; echo 
$bar[0];', array('test'), 77777 ),
+                               array( 'rrr' )
+                       );
+       }
+       public function testRun_array_increase_test_2() {
+               $this->assertEquals(
+                               Runtime::runSource( '$bar=["rrr"]; ++$bar; echo 
$bar[0];', array('test'), 77777 ),
+                               array( 'rrr' )
+                       );
+       }
+       public function testRun_array_increase_test_3() {
+               $this->assertEquals(
+                               Runtime::runSource( '$bar=["rrr"]; --$bar; echo 
$bar[0];', array('test'), 77777 ),
+                               array( 'rrr' )
+                       );
+       }
+       public function testRun_array_increase_test_4() {
+               $this->assertEquals(
+                               Runtime::runSource( '$bar=["rrr"]; $bar--; echo 
$bar[0];', array('test'), 77777 ),
+                               array( 'rrr' )
                        );
        }
 
@@ -2045,10 +2492,50 @@
                                Runtime::runSource('$foo=array(1); echo 
(string)++$foo[0];'),
                                array('2')
                        );
-       }public function testRun_echo_array_right_increment_2() {
+       }
+       public function testRun_echo_array_right_increment_2() {
                $this->assertEquals(
                                Runtime::runSource('$foo=array(1); echo 
(string)++$foo[0], $foo[0];'),
                                array('2', 2)
+                       );
+       }
+       public function testRun_echo_array_constructor_1() {
+               $this->assertEquals(
+                               Runtime::runSource('
+$b = array( "a", "b", "c" );
+$a = array( $b[0], $b[1], $b[2] );
+echo "(" . $b[0] . $b[1] . $b[2] .")--";
+echo "(" . $a[0] . $a[1] . $a[2] .")";'),
+                               array('(abc)--', '(abc)')
+                       );
+       }
+       public function testRun_echo_array_exception_1() {
+               $this->assertEquals(
+                               Runtime::runSource( '$t = 5; $t[] = 4; echo 
$t;', array('test') ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::WARNING_SCALAR_VALUE_AS_ARRAY, null, 1, 'test' ),
+                                       '5',
+                               )
+                       );
+       }
+       public function testRun_echo_array_exception_2() {
+               $this->assertEquals(
+                               Runtime::runSource( '$t = "5"; $t[] = 4; echo 
$t;', array('test') ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::WARNING_SCALAR_VALUE_AS_ARRAY, null, 1, 'test' ),
+                                       '5',
+                               )
+                       );
+       }
+       public function testRun_echo_array_no_exception_3() {
+               $this->assertEquals(
+                               Runtime::runSource( '$t = null; $t[] = 4; echo 
$t[0];', array('test') ),
+                               array( '4' )
+                       );
+       }public function testRun_echo_array_no_exception_4() {
+               $this->assertEquals(
+                               Runtime::runSource( '$t = false; $t[] = 4; echo 
$t[0];', array('test') ),
+                               array( '4' )
                        );
        }
 
@@ -2746,6 +3233,30 @@
                                array('false')
                        );
        }
+       public function testRun_echo_isset_boolean_and_1() {
+               $this->assertEquals(
+                               Runtime::runSource( '
+       $g = ["a" => 0]; $x = "a";
+       if ( isset( $g[$x] ) && $x !== "kf" ) {
+               echo "TRUE";
+       } else {
+           echo "FALSE";
+       }'),
+                               array( 'TRUE' )
+                       );
+       }
+       public function testRun_echo_isset_boolean_or_1() {
+               $this->assertEquals(
+                               Runtime::runSource( '
+       $g = ["a" => 0]; $x = "a";
+       if ( isset( $g[$x] ) || $x === "kf" ) {
+               echo "TRUE";
+       } else {
+           echo "FALSE";
+       }'),
+                               array( 'TRUE' )
+                       );
+       }
 
        public function testRun_echo_unset_1() {
                $this->assertEquals(
@@ -2963,6 +3474,10 @@
                                Runtime::runSource('echo PHPTAGS_VERSION;'),
                                array(PHPTAGS_VERSION)
                        );
+               $this->assertEquals(
+                               Runtime::runSource('echo PHPTAGS_VERSION;'),
+                               
array(\ExtensionRegistry::getInstance()->getAllThings()['PhpTags']['version'])
+                       );
        }
 
        public function testRun_echo_exception_1() {
@@ -3049,14 +3564,33 @@
        public function testRun_echo_exception_11() {
                $this->assertEquals( array( false ), Runtime::runSource( 'echo 
@(5/0);', array('Test') ) );
        }
+       public function testRun_echo_exception_12() {
+               $this->assertEquals(
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::WARNING_DIVISION_BY_ZERO, null, 1, 'Test' ),
+                                       false,
+                               ),
+                               Runtime::runSource( 'echo 5%0;', array('Test') )
+                       );
+       }
 
        public function testRun_constant_test() {
+               wfDebug( 'PHPTags: this message must be after PHPTags test 
initialization. ' . __METHOD__ );
+               if ( !defined( 'PHPTAGS_TEST' ) ) {
+                       wfDebug( 'PHPTags: constant PHPTAGS_TEST is not 
defined, skip PhpTagsRuntimeFirstInit hook tests. ' . __METHOD__ );
+                       return;
+               }
+
                $this->assertEquals(
                                Runtime::runSource( 'echo PHPTAGS_TEST;' ),
                                array( 'Test' )
                        );
        }
        public function testRun_constant_test_banned() {
+               if ( !defined( 'PHPTAGS_TEST' ) ) {
+                       return;
+               }
+
                $result = Runtime::runSource( 'echo PHPTAGS_TEST_BANNED;', 
array('Test ban') );
 
                $exc1 = new \PhpTags\HookException( 'Sorry, you cannot use this 
constant' );
@@ -3069,12 +3603,20 @@
                $this->assertEquals( $result, array( (string)$exc1, 
(string)$exc2, false ) );
        }
        public function testRun_constant_class_test() {
+               if ( !defined( 'PHPTAGS_TEST' ) ) {
+                       return;
+               }
+
                $this->assertEquals(
                                Runtime::runSource( 'echo 
PHPTAGS_TEST_IN_CLASS;' ),
                                array( 'I am constant PHPTAGS_TEST_IN_CLASS' )
                        );
        }
        public function testRun_constant_class_banned_test() {
+               if ( !defined( 'PHPTAGS_TEST' ) ) {
+                       return;
+               }
+
                $result = Runtime::runSource( 'echo 
PHPTAGS_TEST_IN_CLASS_BANNED;', array('Test ban') );
 
                $exc1 = new \PhpTags\HookException( 'Sorry, you cannot use this 
constant' );
@@ -3087,12 +3629,20 @@
                $this->assertEquals( $result, array( (string)$exc1, 
(string)$exc2, false ) );
        }
        public function testRun_object_constant_test() {
+               if ( !defined( 'PHPTAGS_TEST' ) ) {
+                       return;
+               }
+
                $this->assertEquals(
                                Runtime::runSource( 'echo 
PhpTagsTest::OBJ_TEST;' ),
                                array( 'c_OBJ_TEST' )
                        );
        }
        public function testRun_object_constant_banned_test() {
+               if ( !defined( 'PHPTAGS_TEST' ) ) {
+                       return;
+               }
+
                $result = Runtime::runSource( 'echo 
PhpTagsTest::OBJ_TEST_BANNED;', array('Test ban') );
 
                $exc1 = new \PhpTags\HookException( 'Sorry, you cannot use this 
object constant' );
@@ -3105,12 +3655,20 @@
                $this->assertEquals( $result, array( (string)$exc1, 
(string)$exc2, false ) );
        }
        public function testRun_function_test() {
+               if ( !defined( 'PHPTAGS_TEST' ) ) {
+                       return;
+               }
+
                $this->assertEquals(
                                Runtime::runSource( 'echo 
PhpTagsTestfunction();' ),
                                array( 'f_phptagstestfunction' )
                        );
        }
        public function testRun_function_banned_test() {
+               if ( !defined( 'PHPTAGS_TEST' ) ) {
+                       return;
+               }
+
                $result = Runtime::runSource( 'echo 
PhpTagsTestfunction_BANNED();', array('Test ban') );
 
                $exc1 = new \PhpTags\HookException( 'Sorry, you cannot use this 
function' );
@@ -3123,12 +3681,20 @@
                $this->assertEquals( $result, array( (string)$exc1, 
(string)$exc2, false ) );
        }
        public function testRun_object_method_test() {
+               if ( !defined( 'PHPTAGS_TEST' ) ) {
+                       return;
+               }
+
                $this->assertEquals(
                                Runtime::runSource( '$obj = new PhpTagsTest(); 
echo $obj->myMETHOD();' ),
                                array( 'm_mymethod' )
                        );
        }
        public function testRun_object_method_banned_test() {
+               if ( !defined( 'PHPTAGS_TEST' ) ) {
+                       return;
+               }
+
                $result = Runtime::runSource( '$obj = new PhpTagsTest(); echo 
$obj->myMETHOD_BaNnEd();', array('Test ban') );
 
                $exc1 = new \PhpTags\HookException( 'Sorry, you cannot use this 
method' );
@@ -3141,12 +3707,20 @@
                $this->assertEquals( $result, array( (string)$exc1, 
(string)$exc2, false ) );
        }
        public function testRun_static_method_test() {
+               if ( !defined( 'PHPTAGS_TEST' ) ) {
+                       return;
+               }
+
                $this->assertEquals(
                                Runtime::runSource( 'echo 
PhpTagsTest::mystaticMETHOD();' ),
                                array( 's_mystaticmethod' )
                        );
        }
        public function testRun_static_method_banned_test() {
+               if ( !defined( 'PHPTAGS_TEST' ) ) {
+                       return;
+               }
+
                $result = Runtime::runSource( 'echo 
PhpTagsTest::mystaticMETHOD_BaNnEd();', array('Test ban') );
 
                $exc1 = new \PhpTags\HookException( 'Sorry, you cannot use this 
static method' );
@@ -3159,4 +3733,297 @@
                $this->assertEquals( $result, array( (string)$exc1, 
(string)$exc2, false ) );
        }
 
+       public function testRun_object_operation_test_1() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar=new 
PhpTagsTest(); $foo = $foo . $bar; echo $foo[0],$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       (string) new PhpTagsException( 
PhpTagsException::FATAL_OBJECT_COULD_NOT_BE_CONVERTED, array('PhpTagsTest', 
'string'), 1, 'test' ),
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_2() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["rrr"]; $bar=new 
PhpTagsTest(); $foo = $foo + $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ),
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_3() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=["rrr"]; $foo += $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ),
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_4() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=5; $foo = $bar + $foo; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       6,
+                                       5,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_5() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=5; $foo = $bar - $foo; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       4,
+                                       5,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_6() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=5; $foo -= $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       -4,
+                                       5,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_7() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=5; $foo = $foo > $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       false,
+                                       5,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_8() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=5; $foo = $foo < $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       true,
+                                       5,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_9() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=5; $foo = $bar <= $foo; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       false,
+                                       5,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_10() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=5; $foo = $bar >= $foo; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       true,
+                                       5,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_11() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=5; $foo = $bar == $foo; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       false,
+                                       5,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_12() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=5; $foo = $bar != $foo; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       true,
+                                       5,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_13() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=5; $foo = $bar === $foo; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       false,
+                                       5,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_14() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=5; $foo = $bar !== $foo; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       true,
+                                       5,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_15() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=8; $foo = $bar | $foo; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       9,
+                                       8,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_16() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=8; $foo |= $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       9,
+                                       8,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_17() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=8; $foo = $bar >> $foo; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       4,
+                                       8,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_18() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=8; $foo <<= $bar; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       256,
+                                       8,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_19() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=8; $foo = $bar && $foo; echo $foo,$bar;', array('test'), 77777 ),
+                               array(
+                                       true,
+                                       8,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_20() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar= ~$foo; echo $foo,$bar;', array('test'), 77777 ),
+                               array( (string) new PhpTagsException( 
PhpTagsException::FATAL_UNSUPPORTED_OPERAND_TYPES, null, 1, 'test' ) )
+                       );
+       }
+       public function testRun_object_operation_test_21() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar= !$foo; echo $bar === false;', array('test'), 77777 ),
+                               array( true     )
+                       );
+       }
+       public function testRun_object_operation_test_22() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=(int)$foo; echo $bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'int'), 1, 
'test' ),
+                                       1,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_23() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=(double)$foo; echo $bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_OBJECT_CONVERTED, array('PhpTagsTest', 'double'), 1, 
'test' ),
+                                       1,
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_24() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=(string)$foo; echo $bar;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::FATAL_OBJECT_COULD_NOT_BE_CONVERTED, array('PhpTagsTest', 
'string'), 1, 'test' ),
+                               )
+                       );
+       }
+       public function testRun_object_operation_test_25() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=(array)$foo; echo $bar[0];', array('test'), 77777 ),
+                               array( '(object <PhpTagsTest>)' )
+                       );
+       }
+       public function testRun_object_operation_test_26() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=(bool)$foo; echo $bar === true;', array('test'), 77777 ),
+                               array( true )
+                       );
+       }
+       public function testRun_object_operation_test_27() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$bar=(unset)$foo; echo $bar === null;', array('test'), 77777 ),
+                               array( true )
+                       );
+       }
+
+       public function testRun_object_increase_test_1() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$foo++; echo $foo;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::FATAL_OBJECT_COULD_NOT_BE_CONVERTED, array('PhpTagsTest', 
'string'), 1, 'test' ),
+                               )
+                       );
+       }
+       public function testRun_object_increase_test_2() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
++$foo; echo $foo;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::FATAL_OBJECT_COULD_NOT_BE_CONVERTED, array('PhpTagsTest', 
'string'), 1, 'test' ),
+                               )
+                       );
+       }
+       public function testRun_object_increase_test_3() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
--$foo; echo $foo;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::FATAL_OBJECT_COULD_NOT_BE_CONVERTED, array('PhpTagsTest', 
'string'), 1, 'test' ),
+                               )
+                       );
+       }
+       public function testRun_object_increase_test_4() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
$foo--; echo $foo;', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::FATAL_OBJECT_COULD_NOT_BE_CONVERTED, array('PhpTagsTest', 
'string'), 1, 'test' ),
+                               )
+                       );
+       }
+
+       public function testRun_array_quote_test_1() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=["bar"]; echo 
"$foo";', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::NOTICE_ARRAY_TO_STRING, null, 1, 'test' ),
+                                       Runtime::R_ARRAY,
+                               )
+                       );
+       }
+       public function testRun_object_quote_test_1() {
+               $this->assertEquals(
+                               Runtime::runSource( '$foo=new PhpTagsTest(); 
echo "$foo";', array('test'), 77777 ),
+                               array(
+                                       (string) new PhpTagsException( 
PhpTagsException::FATAL_OBJECT_COULD_NOT_BE_CONVERTED, array('PhpTagsTest', 
'string'), 1, 'test' ),
+                               )
+                       );
+       }
+
+
 }

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I81b2c89a3a8a13ebf9f3ea1c14c3acbd91c0b2e7
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/PhpTags
Gerrit-Branch: REL1_26
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