Pastakhov has uploaded a new change for review.

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


Change subject: Refactoring (version 0.2.0)
......................................................................

Refactoring (version 0.2.0)

Patch Set 1: Refactoring and add class Variable

Change-Id: I7a479b05548e9a9f096f3d1375fb6feaafab8c2d
---
M Foxway.php
M includes/Debug.php
M includes/Interpreter.php
M includes/Runtime.php
M includes/RuntimeDebug.php
A includes/Variable.php
M tests/phpunit/includes/InterpreterTest.php
7 files changed, 331 insertions(+), 293 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Foxway 
refs/changes/17/62217/1

diff --git a/Foxway.php b/Foxway.php
index 3e60e4b..5dec562 100644
--- a/Foxway.php
+++ b/Foxway.php
@@ -15,7 +15,7 @@
        die( 'This file is an extension to MediaWiki and thus not a valid entry 
point.' );
 }
 
-define( 'Foxway_VERSION' , '0.1.0' );
+define( 'Foxway_VERSION' , '0.2.0' );
 
 // Register this extension on Special:Version
 $wgExtensionCredits['parserhook'][] = array(
@@ -57,6 +57,7 @@
 $wgAutoloadClasses['Foxway\\Interpreter']              = $dir . 
'/includes/Interpreter.php';
 $wgAutoloadClasses['Foxway\\Runtime']                  = $dir . 
'/includes/Runtime.php';
 $wgAutoloadClasses['Foxway\\RuntimeDebug']             = $dir . 
'/includes/RuntimeDebug.php';
+$wgAutoloadClasses['Foxway\\Variable']                 = $dir . 
'/includes/Variable.php';
 
 // Resources
 $wgResourceModules['ext.Foxway.Debug'] = array(
diff --git a/includes/Debug.php b/includes/Debug.php
index 33dea04..bea0441 100644
--- a/includes/Debug.php
+++ b/includes/Debug.php
@@ -38,12 +38,14 @@
     }
 
        private static function getHTMLbyToken( $token ) {
-               if ( is_string($token) ) {
+               if ( is_array($token) ) {
+                       list($id, $t) = $token;
+                       $text = strtr( $t, array('&'=>'&amp;', '<'=>'&lt;') );
+                       $tokenName = token_name($id);
+               } else {
                        $id = $token;
                        $text = strtr( $id, array('&'=>'&amp;', '<'=>'&lt;') );
-               } else {
-                       list($id, $text) = $token;
-                       $text = strtr( $text, array('&'=>'&amp;', '<'=>'&lt;') 
);
+                       $tokenName = false;
                }
 
                $class = false;
@@ -76,6 +78,7 @@
                        case T_IF:
                        case T_ELSE:
                        case T_ELSEIF:
+                       case T_ARRAY:
                                $class = 'foxway_construct';
                                break;
                        case T_VARIABLE:
@@ -95,11 +98,15 @@
                                return '';
                }
 
+               $attribs = array();
                if( $class !== false ) {
-                       return \Html::rawElement( 'span', 
array('class'=>$class, 'title'=>token_name($id)), $text );
+                       $attribs['class'] = $class;
                }
-               if( is_array($token) ) {
-                       return \Html::rawElement( 'span', 
array('title'=>token_name($id)), $text );
+               if( $tokenName ) {
+                       $attribs['title'] = $tokenName;
+               }
+               if( count($attribs) > 0 ) {
+                       return \Html::rawElement( 'span', $attribs, $text );
                }
                return $text;
        }
diff --git a/includes/Interpreter.php b/includes/Interpreter.php
index 19b70a2..0aaf205 100644
--- a/includes/Interpreter.php
+++ b/includes/Interpreter.php
@@ -224,12 +224,13 @@
                                        $runtime->addParam( (float)$text );
                                        break;
                                case T_ENCAPSED_AND_WHITESPACE: // " $a"
+                                       $runtime->addParam( 
self::process_slashes($text, false) );
                                        if( $expectQuotesClose ) {
                                                $runtime->addOperator('.');
                                        }
-                                       $runtime->addParam( 
self::process_slashes($text, false) );
                                        break;
                                case T_VARIABLE:
+                                       $runtime->addVariableAsParam( $text );
                                        if( $expected && in_array(T_VARIABLE, 
$expected) ) {
                                                if( $expectCurlyClose ) {
                                                        $expected = array( '}' 
);
@@ -286,7 +287,6 @@
                                                        ',',
                                                        );
                                        }
-                                       $runtime->addParam( "\0$text" );
                                        break;
                                case T_STRING:
                                        if( strcasecmp($text, 'true') == 0 ) {
@@ -325,7 +325,7 @@
                                        switch ($command) {
                                                case T_ECHO:
                                                        $commandsEmbedded--;
-                                                       $return[] = $result;
+                                                       $return = 
array_merge($return, $result);
                                                        break;
                                                case T_IF:
                                                        $commandsEmbedded--;
@@ -405,7 +405,6 @@
                                case '"':
                                        if( $expectQuotesClose === false ) {
                                                $runtime->addOperator('"(');
-                                               $runtime->addParam('');
                                                $expectQuotesClose = true;
                                                $expected = 
array(T_ENCAPSED_AND_WHITESPACE, T_CURLY_OPEN, T_VARIABLE, '"');
                                                break;
diff --git a/includes/Runtime.php b/includes/Runtime.php
index 01786df..bc148db 100644
--- a/includes/Runtime.php
+++ b/includes/Runtime.php
@@ -46,6 +46,11 @@
                array(T_LOGICAL_OR), // or
                array(','),
        );
+       private $countPrecedences;
+
+       public function __construct() {
+               $this->countPrecedences = count(self::$operatorsPrecedence)-1;
+       }
 
        public function getOperators() {
                static $operators = array();
@@ -91,10 +96,12 @@
        }
 
        public function addCommand( $name ) {
-               if( $this->lastCommand ) {
-                       $this->pushStack();
-               }
+               $this->pushStack();
                $this->lastCommand = $name;
+       }
+
+       public function addVariableAsParam( $name ) {
+               $this->addParam( new Variable($name, self::$variables) );
        }
 
        public function addParam( $param ) {
@@ -104,7 +111,6 @@
                        $this->lastOperator = false;
                }
                $this->lastParam = $param;
-               $this->doMath(0);
        }
 
        protected function parenthesesOpen() {
@@ -118,6 +124,10 @@
 
        protected function parenthesesClose() {
                $this->doMath();
+               if( count($this->listParams) ) {
+                       $this->listParams[] = $this->lastParam;
+                       $this->lastParam = $this->listParams;
+               }
                $this->popStack();
                if( !is_null($this->lastCommand) && $this->lastCommand != 
T_ECHO ) {
                        return $this->lastCommand;
@@ -125,26 +135,59 @@
        }
 
        public function addOperator( $operator ) {
+               if( $this->lastParam instanceof Variable ) {
+                       $lastParam = &$this->lastParam->getReference();
+               }else{
+                       $lastParam = &$this->lastParam;
+               }
+
                switch ($operator) {
+                       case ',':
+                               $this->doMath();
+                               $this->listParams[] = $this->lastParam 
instanceof Variable ? $this->lastParam->getReference() : $this->lastParam;
+                               $this->lastParam = null;
+                               break;
+                       case '?':
+                               $this->doMath( 
$this->getOperatorPrecedence('?') );
+                               return $this->lastParam instanceof Variable ? 
$this->lastParam->getReference() : $this->lastParam;
+                               break;
                        case '"(':
                        case '(':
                                $this->parenthesesOpen();
                                break;
                        case '")':
+                               $this->lastOperator = false;
+                               // break is not necessary here
                        case ')':
                                $this->parenthesesClose();
-                               if( $this->lastCommand && $this->lastCommand != 
T_ECHO ) {
-                                       if( substr($this->lastParam, 0, 2) == 
"\0$" ) {
-                                               $variableLastParam = 
substr($this->lastParam, 2);
-                                               if( 
!isset(self::$variables[$variableLastParam]) ) {
-                                                       //TODO
-                                                       return array( 
$this->lastCommand, null);
-                                               } else {
-                                                       return array( 
$this->lastCommand, self::$variables[$variableLastParam]);
+                               if( $this->lastCommand == T_IF ) {
+                                       return array( T_IF, $this->lastParam 
instanceof Variable ? $this->lastParam->getReference() : $this->lastParam );
+                               }elseif($this->lastCommand ) {
+                                       $this->doCommand();
+                               }
+                               break;
+                       case '[':
+                               $this->addCommand($this->lastParam);
+                               break;
+                       case ']':
+                               $this->doMath();
+                               if( substr($this->lastCommand, 0, 2) == "\0$" ) 
{
+                                       $variable = substr($this->lastCommand, 
2);
+                                       \MWDebug::log('$variable = ' . 
var_export($variable,true));
+                                       \MWDebug::log('variables = ' . 
var_export(self::$variables,true));
+                                       if( isset(self::$variables[$variable]) 
) {
+                                               $value = 
&self::$variables[$variable];
+                                               if( !is_array($value) || isset( 
$value[$this->lastParam]) ) {
+                                                       $this->lastParam = 
$value[$this->lastParam];
+                                                       $this->popStack();
+                                                       
\MWDebug::log('$this->lastParam = ' . var_export($this->lastParam,true));
+                                                       break;
                                                }
                                        }
-                                       return array( $this->lastCommand, 
$this->lastParam);
                                }
+                               $this->lastParam = null;
+                               $this->popStack();
+                               \MWDebug::log('$this->lastParam = ' . 
var_export($this->lastParam,true));
                                break;
                        default:
                                $precedence = $this->getOperatorPrecedence( 
$operator );
@@ -160,45 +203,15 @@
                                                case T_STRING_CAST:
                                                case T_ARRAY_CAST:
                                                case T_BOOL_CAST:
+                                               case T_INC:
+                                               case T_DEC:
                                                        if( 
!isset($this->mathMemory[0]) ) {
                                                                
$this->mathMemory[0] = array();
                                                        }
                                                        $this->mathMemory[0][] 
= $operator;
-                                                       break;
-                                               case T_INC: // TODO
-                                                       if( $this->lastOperator 
|| is_null($this->lastParam) ) {
-                                                               if( 
!isset($this->mathMemory[0]) ) {
-                                                                       
$this->mathMemory[0] = array();
-                                                               }
-                                                               
$this->mathMemory[0][] = $operator;
-                                                       } else {
-                                                               
$variableLastParam = false;
-                                                               if( 
substr($this->lastParam, 0, 2) == "\0$" ) {
-                                                                       
$variableLastParam = substr($this->lastParam, 2);
-                                                                       if( 
!isset(self::$variables[$variableLastParam]) ) {
-                                                                               
self::$variables[$variableLastParam] = null;
-                                                                       }
-                                                                       
$this->lastParam = self::$variables[$variableLastParam];
-                                                                       
self::$variables[$variableLastParam]++;
-                                                               }
-                                                       }
-                                                       break;
-                                               case T_DEC: // TODO
-                                                       if( $this->lastOperator 
|| is_null($this->lastParam) ) {
-                                                               if( 
!isset($this->mathMemory[0]) ) {
-                                                                       
$this->mathMemory[0] = array();
-                                                               }
-                                                               
$this->mathMemory[0][] = $operator;
-                                                       } else {
-                                                               
$variableLastParam = false;
-                                                               if( 
substr($this->lastParam, 0, 2) == "\0$" ) {
-                                                                       
$variableLastParam = substr($this->lastParam, 2);
-                                                                       if( 
!isset(self::$variables[$variableLastParam]) ) {
-                                                                               
self::$variables[$variableLastParam] = null;
-                                                                       }
-                                                                       
$this->lastParam = self::$variables[$variableLastParam];
-                                                                       
self::$variables[$variableLastParam]--;
-                                                               }
+                                                       if( $this->lastParam 
instanceof Variable && !$this->lastOperator ) {
+                                                               
$this->lastOperator = $operator;
+                                                               
$this->doMath(0);
                                                        }
                                                        break;
                                                default:
@@ -212,24 +225,18 @@
                                }
                                break;
                }
-               if( substr($this->lastParam, 0, 2) == "\0$" ) {
-                       $variableLastParam = substr($this->lastParam, 2);
-                       if( !isset(self::$variables[$variableLastParam]) ) {
-                               //TODO
-                               return null;
-                       } else {
-                               return self::$variables[$variableLastParam];
-                       }
-               }
-               return $this->lastParam;
        }
 
-       protected function doMath( $precedence = 17 ) { //17 = 
count($operatorsPrecedence)-1
+       protected function doMath( $precedence = false ) {
+
                if( isset($this->mathMemory[0]) ) {
                        while( $mathZerroMemory = 
array_pop($this->mathMemory[0]) ) {
                                $this->doOperation($mathZerroMemory);
                        }
                        unset($this->mathMemory[0]);
+               }
+               if($precedence === false){
+                       $precedence = $this->countPrecedences;
                }
                for($n = 1; $n <= $precedence; $n++) {
                        if( isset($this->mathMemory[$n]) ) {
@@ -240,163 +247,142 @@
        }
 
        protected function doOperation($operator, $param = null) {
-               $variableParam = false;
-               if( substr($param, 0, 2) == "\0$" ) {
-                       $variableParam = substr($param, 2);
-                       if( !isset(self::$variables[$variableParam]) ) {
-                               self::$variables[$variableParam] = null;
-                               // TODO show warning
-                       }
-                       $param = self::$variables[$variableParam];
+               if( $param instanceof Variable ) {
+                       $param = &$param->getReference();
                }
-
-               $variableLastParam = false;
-               if( substr($this->lastParam, 0, 2) == "\0$" ) {
-                       $variableLastParam = substr($this->lastParam, 2);
-                       if( !isset(self::$variables[$variableLastParam]) ) {
-                               self::$variables[$variableLastParam] = null;
-                               // TODO show warning
-                       }
-                       $this->lastParam = self::$variables[$variableLastParam];
+               if( $this->lastParam instanceof Variable ) {
+                       $lastParam = &$this->lastParam->getReference();
+               }else{
+                       $lastParam = &$this->lastParam;
                }
 
                switch ($operator) {
                        case '=':
-                               self::$variables[$variableParam] = 
$this->lastParam;
+                               $this->lastParam = $param = $lastParam;
                                break;
                        case T_CONCAT_EQUAL:// .=
-                               self::$variables[$variableParam] .= 
$this->lastParam;
-                               $this->lastParam = 
self::$variables[$variableParam];
+                               $this->lastParam = $param .= $lastParam;
                                break;
                        case T_PLUS_EQUAL:// +=
-                               self::$variables[$variableParam] += 
$this->lastParam;
-                               $this->lastParam = 
self::$variables[$variableParam];
+                               $this->lastParam = $param += $lastParam;
                                break;
                        case T_MINUS_EQUAL:// -=
-                               self::$variables[$variableParam] -= 
$this->lastParam;
-                               $this->lastParam = 
self::$variables[$variableParam];
+                               $this->lastParam = $param -= $lastParam;
                                break;
                        case T_MUL_EQUAL: // *=
-                               self::$variables[$variableParam] *= 
$this->lastParam;
-                               $this->lastParam = 
self::$variables[$variableParam];
+                               $this->lastParam = $param *= $lastParam;
                                break;
                        case T_DIV_EQUAL: // /=
-                               self::$variables[$variableParam] /= 
$this->lastParam;
-                               $this->lastParam = 
self::$variables[$variableParam];
+                               $this->lastParam = $param /= $lastParam;
                                break;
                        case T_MOD_EQUAL: // %=
-                               self::$variables[$variableParam] %= 
$this->lastParam;
-                               $this->lastParam = 
self::$variables[$variableParam];
+                               $this->lastParam = $param %= $lastParam;
                                break;
                        case T_AND_EQUAL:// &=
-                               self::$variables[$variableParam] &= 
$this->lastParam;
-                               $this->lastParam = 
self::$variables[$variableParam];
+                               $this->lastParam = $param &= $lastParam;
                                break;
                        case T_OR_EQUAL:// |=
-                               self::$variables[$variableParam] |= 
$this->lastParam;
-                               $this->lastParam = 
self::$variables[$variableParam];
+                               $this->lastParam = $param |= $lastParam;
                                break;
                        case T_XOR_EQUAL:// ^=
-                               self::$variables[$variableParam] ^= 
$this->lastParam;
-                               $this->lastParam = 
self::$variables[$variableParam];
+                               $this->lastParam = $param ^= $lastParam;
                                break;
                        case T_SL_EQUAL:// <<=
-                               self::$variables[$variableParam] <<= 
$this->lastParam;
-                               $this->lastParam = 
self::$variables[$variableParam];
+                               $this->lastParam = $param <<= $lastParam;
                                break;
                        case T_SR_EQUAL:// >>=
-                               self::$variables[$variableParam] >>= 
$this->lastParam;
-                               $this->lastParam = 
self::$variables[$variableParam];
+                               $this->lastParam = $param >>= $lastParam;
                                break;
-                       case T_INC: // ++$variable
-                               $this->lastParam = 
++self::$variables[$variableLastParam];
-                               break;
-                       case T_DEC: // --$variable
-                               $this->lastParam = 
--self::$variables[$variableLastParam];
-                               break;
-                       case ',':
-                               $this->listParams[] = $param;
-                               break;
-                       case '.':
-                               $this->lastParam = $param . $this->lastParam;
-                               break;
-                       case '+':
-                               $this->lastParam += $param;
-                               break;
-                       case '-':
-                               if( is_null($param) ) { // Negation
-                                       $this->lastParam = -$this->lastParam;
-                               } else { // Subtraction
-                                       $this->lastParam = $param - 
$this->lastParam;
+                       case T_INC: // ++
+                               if( $this->lastOperator) {
+                                       $this->lastOperator = false;
+                                       $this->lastParam = $lastParam++;
+                               } else {
+                                       $this->lastParam = ++$lastParam;
                                }
                                break;
+                       case T_DEC: // --
+                               if( $this->lastOperator) {
+                                       $this->lastOperator = false;
+                                       $this->lastParam = $lastParam--;
+                               } else {
+                                       $this->lastParam = --$lastParam;
+                               }
+                               break;
+                       case '.':
+                               $this->lastParam = $param . $lastParam;
+                               break;
+                       case '+':
+                               $this->lastParam = $param + $lastParam;
+                               break;
+                       case '-':
+                               $this->lastParam = $param - $lastParam;
+                               break;
                        case '*':
-                               $this->lastParam *= $param;
+                               $this->lastParam = $param * $lastParam;
                                break;
                        case '/':
-                               $this->lastParam = $param / $this->lastParam;
+                               $this->lastParam = $param / $lastParam;
                                break;
                        case '%':
-                               $this->lastParam = $param % $this->lastParam;
+                               $this->lastParam = $param % $lastParam;
                                break;
                        case '&':
-                               $this->lastParam &= $param;
+                               $this->lastParam = $param & $lastParam;
                                break;
                        case '|':
-                               $this->lastParam = $param | $this->lastParam;
+                               $this->lastParam = $param | $lastParam;
                                break;
                        case '^':
-                               $this->lastParam = $param ^ $this->lastParam;
+                               $this->lastParam = $param ^ $lastParam;
                                break;
                        case T_SL: // <<
-                               $this->lastParam = $param << $this->lastParam;
+                               $this->lastParam = $param << $lastParam;
                                break;
                        case T_SR: // >>
-                               $this->lastParam = $param >> $this->lastParam;
+                               $this->lastParam = $param >> $lastParam;
                                break;
                        case '~':
-                               $this->lastParam = ~$this->lastParam;
+                               $this->lastParam = ~$lastParam;
                                break;
                        case T_INT_CAST:
-                               $this->lastParam = (integer) $this->lastParam;
+                               $this->lastParam = (integer) $lastParam;
                                break;
                        case T_DOUBLE_CAST:
-                               $this->lastParam = (float) $this->lastParam;
+                               $this->lastParam = (float) $lastParam;
                                break;
                        case T_STRING_CAST:
-                               $this->lastParam = (string) $this->lastParam;
+                               $this->lastParam = (string) $lastParam;
                                break;
                        case T_ARRAY_CAST:
-                               $this->lastParam = (array) $this->lastParam;
+                               $this->lastParam = (array) $lastParam;
                                break;
                        case T_BOOL_CAST:
-                               $this->lastParam = (bool) $this->lastParam;
+                               $this->lastParam = (bool) $lastParam;
                                break;
                        case '<':
-                               $this->lastParam = $param < $this->lastParam;
+                               $this->lastParam = $param < $lastParam;
                                break;
                        case '>':
-                               $this->lastParam = $param > $this->lastParam;
+                               $this->lastParam = $param > $lastParam;
                                break;
                        case T_IS_SMALLER_OR_EQUAL: // <=
-                               $this->lastParam = $param <= $this->lastParam;
+                               $this->lastParam = $param <= $lastParam;
                                break;
                        case T_IS_GREATER_OR_EQUAL: // >=
-                               $this->lastParam = $param >= $this->lastParam;
+                               $this->lastParam = $param >= $lastParam;
                                break;
                        case T_IS_EQUAL: // ==
-                               $this->lastParam = $param == $this->lastParam;
+                               $this->lastParam = $param == $lastParam;
                                break;
                        case T_IS_NOT_EQUAL: // !=
-                               $this->lastParam = $param != $this->lastParam;
+                               $this->lastParam = $param != $lastParam;
                                break;
                        case T_IS_IDENTICAL: // ===
-                               $this->lastParam = $param === $this->lastParam;
+                               $this->lastParam = $param === $lastParam;
                                break;
                        case T_IS_NOT_IDENTICAL: // !==
-                               $this->lastParam = $param !== $this->lastParam;
-                               break;
-                       case '?':
+                               $this->lastParam = $param !== $lastParam;
                                break;
                        default:
                                \MWDebug::log( __METHOD__ . " unknown operator 
'$operator'" );
@@ -406,14 +392,13 @@
 
        // Remember the child class RuntimeDebug
        public function getCommandResult( ) {
-               $this->doMath();
-               $this->doOperation(',', $this->lastParam);
+               $this->addOperator(',');
                $return = null;
 
                // Remember the child class RuntimeDebug
                switch ($this->lastCommand) {
                        case T_ECHO:
-                               $return = array( $this->lastCommand, 
implode('', $this->listParams) );
+                               $return = array( $this->lastCommand, 
$this->listParams );
                                break;
                        case false:
                                break; // exsample: $foo = 'foobar';
@@ -423,8 +408,19 @@
                                \MWDebug::log($return);
                }
                $this->popStack();
-               $this->lastParam = null;
+               //$this->lastParam = null;
                return $return;
        }
 
-}
+       private function doCommand() {
+               switch ($this->lastCommand) {
+                       case T_ARRAY:
+                               \MWDebug::log( var_export($this->lastParam, 
true));
+                               $this->lastCommand = false;
+                               break;
+                       default:
+                               break;
+               }
+       }
+
+}
\ No newline at end of file
diff --git a/includes/RuntimeDebug.php b/includes/RuntimeDebug.php
index 957c041..6e9ee33 100644
--- a/includes/RuntimeDebug.php
+++ b/includes/RuntimeDebug.php
@@ -11,6 +11,24 @@
 class RuntimeDebug extends Runtime {
 
        private $debug = array();
+       private $listParamsDebug = array();
+       private $savedListParams;
+       private $stackDebug = array();
+
+       protected function pushStack() {
+               parent::pushStack();
+               $this->stackDebug[] = $this->listParamsDebug;
+       }
+
+       protected function popStack() {
+               parent::popStack();
+               $this->savedListParams = $this->listParamsDebug;
+               if( count($this->stackDebug) == 0 ) {
+                       $this->listParamsDebug = array();
+               } else {
+                       $this->listParamsDebug = array_pop($this->stackDebug);
+               }
+       }
 
        public function getDebug() {
                $return = implode('<br>', $this->debug);
@@ -19,106 +37,46 @@
        }
 
        protected function doOperation($operator, $param = null) {
-               if( $operator == ',' || $operator == '?' ) {
-                       return parent::doOperation($operator, $param);
-               }
-
-               if( substr($param, 0, 2) == "\0$" ) {
-                       $variableParam = substr($param, 2);
-                       $undefined = '';
-                       if( !isset(self::$variables[$variableParam]) ) {
-                               $undefined = \Html::element('span', 
array('class'=>'foxway_undefined'), "Undefined ");
-                               $thisparam = null;
-                       }else{
-                               $thisparam = self::$variables[$variableParam];
-                       }
-                       $thisparam = $undefined . \Html::element('span', 
array('class'=>'foxway_variable'), "\$$variableParam") .
-                                       '(' . self::getHTMLForValue($thisparam) 
. ')';
-               } else {
-                       $thisparam = self::getHTMLForValue($param);
-               }
-
-               if( substr($this->lastParam, 0, 2) == "\0$" ) {
-                       $variableLastParam = substr($this->lastParam, 2);
-                       $undefined = '';
-                       if( !isset(self::$variables[$variableLastParam]) ) {
-                               $undefined = \Html::element('span', 
array('class'=>'foxway_undefined'), "Undefined ");
-                               $lastParam = null;
-                       } else {
-                               $lastParam = 
self::$variables[$variableLastParam];
-                       }
-                       $lastParam = $undefined . \Html::element('span', 
array('class'=>'foxway_variable'), "\$$variableLastParam") .
-                                       '(' . self::getHTMLForValue($lastParam) 
. ')';
-               } else {
-                       $lastParam = self::getHTMLForValue($this->lastParam);
-               }
-
                if( $operator == '=' ){
-                       $return = \Html::element('span', 
array('class'=>'foxway_variable'), "\$$variableParam") . 
'&nbsp;<b>=></b>&nbsp;=&nbsp;';
+                       $return = \Html::element('span', 
array('class'=>'foxway_variable'), $param->name) .
+                                       '&nbsp;<b>=></b>&nbsp;=&nbsp;';
                } else {
-                       if( $variableParam || $variableLastParam ) {
-                               $return = ($variableParam ? 
\Html::element('span', array('class'=>'foxway_variable'), "\$$variableParam") : 
self::getHTMLForValue($thisparam)) .
-                                               
self::getHTMLForOperator($operator) .
-                                               ($variableLastParam ? 
\Html::element('span', array('class'=>'foxway_variable'), 
"\$$variableLastParam") : self::getHTMLForValue($lastParam)) .
-                                               " <b>=></b> ";
-                       }
-                       $return = $thisparam . 
self::getHTMLForOperator($operator) . $lastParam . '&nbsp;<b>=></b>&nbsp;';
+                       $return = self::getHTMLForValue($param) .
+                                       self::getHTMLForOperator($operator) .
+                                       self::getHTMLForValue($this->lastParam) 
.
+                                       '&nbsp;<b>=></b>&nbsp;';
                }
 
                parent::doOperation($operator, $param);
 
-               $this->debug[] = $return . 
self::getHTMLForValue($this->lastParam);
+               $this->debug[] = $return . self::getHTMLForValue( 
$this->lastParam /*instanceof Variable ? $this->lastParam->value : 
$this->lastParam*/ );
        }
 
        public function addOperator($operator) {
+               if( $operator == ',' ) {
+                       $this->doMath();
+                       $this->listParamsDebug[] = 
self::getHTMLForValue($this->lastParam);
+               }
+/*
                if( ($operator == T_INC || $operator == T_DEC) && 
(!$this->lastOperator && !is_null($this->lastParam)) ) {
-                       $variableLastParam = substr($this->lastParam, 2);
-                       $variable = '';
-                       $value = null;
-                       if( !isset(self::$variables[$variableLastParam]) ) {
-                               $variable = \Html::element('span', 
array('class'=>'foxway_undefined'), 'Undefined ');
-                       }else{
-                               $value = self::$variables[$variableLastParam];
-                       }
-                       $this->debug[] = $variable . \Html::element('span', 
array('class'=>'foxway_variable'), "\$$variableLastParam") .
-                                       '(' . self::getHTMLForValue($value) . 
')' .
+                       $lastParam = $this->lastParam;
+                       $value = $lastParam->value;
+                       $this->debug[] = self::getHTMLForValue($value) .
                                        ($operator == T_INC ? '++' : '--') .
                                        '&nbsp;<b>=></b>&nbsp;' .
                                        '(' . self::getHTMLForValue($operator 
== T_INC ? $value+1 : $value-1) . ')&nbsp' . self::getHTMLForValue($value);
-               }
+               }*/
 
                $return = parent::addOperator($operator);
+               $value = $this->lastParam;
 
                if( $operator == '?' ) {
-
-                       if( substr($this->lastParam, 0, 2) == "\0$" ) {
-                               $variableLastParam = substr($this->lastParam, 
2);
-                               $variable = '';
-                               if( 
!isset(self::$variables[$variableLastParam]) ) {
-                                       $variable = \Html::element('span', 
array('class'=>'foxway_undefined'), 'Undefined ');
-                               }
-                               $variable .= \Html::element('span', 
array('class'=>'foxway_variable'), "\$$variableLastParam");
-                               $variable .= '(' . 
self::getHTMLForValue($return) . ')';
-                       }else{
-                               $variable = self::getHTMLForValue($return);
-                       }
-                       $this->debug[] = $variable . 
"&nbsp;?&nbsp;<b>=></b>&nbsp;" . self::getHTMLForValue($return?true:false);
+                       $this->debug[] = self::getHTMLForValue($value) . 
"&nbsp;?&nbsp;<b>=></b>&nbsp;" . self::getHTMLForValue($return?true:false);
                }elseif( $operator == ')' && is_array($return) ) {
                        list($command, $result) = $return;
                        switch ($command) {
                                case T_IF:
-                                       if( substr($this->lastParam, 0, 2) == 
"\0$" ) {
-                                               $variableLastParam = 
substr($this->lastParam, 2);
-                                               $variable = '';
-                                               if( 
!isset(self::$variables[$variableLastParam]) ) {
-                                                       $variable = 
\Html::element('span', array('class'=>'foxway_undefined'), 'Undefined ');
-                                               }
-                                               $variable .= 
\Html::element('span', array('class'=>'foxway_variable'), 
"\$$variableLastParam");
-                                               $variable .= '(' . 
self::getHTMLForValue($result) . ')';
-                                       }else{
-                                               $variable = 
self::getHTMLForValue($result);
-                                       }
-                                       $t = self::getHTMLForCommand($command) 
. "(&nbsp;" . $variable . "&nbsp;)&nbsp;<b>=></b>&nbsp;";
+                                       $t = self::getHTMLForCommand($command) 
. "(&nbsp;" . self::getHTMLForValue($value) . "&nbsp;)&nbsp;<b>=></b>&nbsp;";
                                        if( $result ) {
                                                $t .= 
self::getHTMLForValue(true);
                                        } else {
@@ -127,69 +85,63 @@
                                        $this->debug[] = $t;
                                        break;
                                default:
-                                       $this->debug[] = 
self::getHTMLForCommand($command) . "( " . self::getHTMLForValue($result) . " 
)";
+                                       $this->debug[] = 
self::getHTMLForCommand($command) . "( " . self::getHTMLForValue($value) . " )";
                                        break;
                        }
                }
                return $return;
        }
 
-       // This is a modified copy of the parent
        public function getCommandResult( ) {
-               $this->doMath();
-               $this->doOperation(',', $this->lastParam);
-               $return = null;
+               $lastCommand = $this->lastCommand;
+               $return = parent::getCommandResult();
 
-               // Remember the child class RuntimeDebug
-               switch ($this->lastCommand) {
+               switch ($lastCommand) {
                        case T_ECHO:
-                               $return = array( $this->lastCommand, 
implode('', $this->listParams) );
-                               $this->debug[] = 
self::getHTMLForCommand($this->lastCommand) . '&nbsp;' . 
$this->getHTMLForListParams() . ';';
-                               $this->debug[] = $return[1];
+                               $this->debug[] = 
self::getHTMLForCommand($lastCommand) . '&nbsp;' . implode(', ', 
$this->savedListParams) . ';';
+                               $this->debug[] = implode('', $return[1]);
                                break;
-                       case false:
-                               break; // exsample: $foo = 'foobar';
-                       default:
-                               // TODO
-                               $return = 'Error! Unknown command "' . 
htmlspecialchars($this->lastCommand) . '" in ' . __METHOD__;
-                               $this->debug[] = $return;
-                               \MWDebug::log($return);
+                       default :
+                               $this->debug[] = is_array($return) ? $return[1] 
: $return ;
                }
-               $this->popStack();
-               $this->lastParam = null;
+
+
                return $return;
        }
 
-       private function getHTMLForListParams() {
-               $return = array();
-               foreach ($this->listParams as $value) {
-                       $return[] = self::getHTMLForValue($value);
-               }
-               return implode(',&nbsp;', $return);
-       }
-
        private static function getHTMLForValue($param) {
+               $value = $param instanceof Variable ? $param->value : $param;
                $class = false;
-               if( $param === true ) {
+               if( $value === true ) {
                        $class = 'foxway_construct';
-                       $param = 'true';
-               }elseif( $param === false ) {
+                       $value = 'true';
+               }elseif( $value === false ) {
                        $class = 'foxway_construct';
-                       $param = 'false';
-               }elseif( $param === null ) {
+                       $value = 'false';
+               }elseif( $value === null ) {
                        $class = 'foxway_construct';
-                       $param = 'null';
-               }elseif( is_string($param) ) {
+                       $value = 'null';
+               }elseif( is_string($value) ) {
                        $class = 'foxway_string';
-                       $param = "'$param'";
-               }elseif( is_numeric($param) ) {
+                       $value = "'$value'";
+               }elseif( is_numeric($value) ) {
                        $class = 'foxway_number';
+               }  elseif( is_array($value) ) {
+                       if( count($value) <= 3 ) {
+                               return var_export($value, true);
+                       }
+               }
+               if( $class ) {
+                       $value = \Html::element('span', array('class'=>$class), 
$value);
+               } else {
+                       $value = strtr( $value, array('&'=>'&amp;', 
'<'=>'&lt;') );
                }
 
-               if( $class ) {
-                       return \Html::element('span', array('class'=>$class), 
$param);
+               if( $param instanceof Variable ) {
+                       return ($param->isDefined ? '' : \Html::element( 
'span', array('class'=>'foxway_undefined'), "Undefined " )) .
+                                       \Html::element( 'span', 
array('class'=>'foxway_variable'), $param->name ) . "($value)";
                }
-               return strtr( $param, array('&'=>'&amp;', '<'=>'&lt;') );
+               return $value;
        }
 
        private static function getHTMLForCommand($command) {
diff --git a/includes/Variable.php b/includes/Variable.php
new file mode 100644
index 0000000..3c2170e
--- /dev/null
+++ b/includes/Variable.php
@@ -0,0 +1,46 @@
+<?php
+namespace Foxway;
+/**
+ * Variable class for Runtime of Foxway extension.
+ *
+ * @file Variable.php
+ * @ingroup Foxway
+ * @author Pavel Astakhov <[email protected]>
+ * @licence GNU General Public Licence 2.0 or later
+ * @property-read string $name Name of variable
+ * @property-read mixed $value Value of variable
+ * @property-read boolean $isDefined Returns true if variable is defined
+ */
+class Variable {
+       private $name;
+       private $variablesArray;
+
+       public function __construct( $name, &$variablesArray ) {
+               $this->name = $name;
+               $this->variablesArray = &$variablesArray;
+       }
+
+       public function &getReference() {
+               $name = $this->name;
+               if( !isset($this->variablesArray[$name]) ) {
+                       $this->variablesArray[$name] = null;
+               }
+               return $this->variablesArray[$name];
+       }
+
+       public function __get($name) {
+               switch ($name) {
+                       case 'name':
+                               return $this->name;
+                               break;
+                       case 'value':
+                               if( isset($this->variablesArray[$this->name]) ) 
{
+                                       return 
$this->variablesArray[$this->name];
+                               }
+                               break;
+                       case 'isDefined':
+                               return 
isset($this->variablesArray[$this->name]);
+                               break;
+               }
+       }
+}
diff --git a/tests/phpunit/includes/InterpreterTest.php 
b/tests/phpunit/includes/InterpreterTest.php
index 0e135df..caf4268 100644
--- a/tests/phpunit/includes/InterpreterTest.php
+++ b/tests/phpunit/includes/InterpreterTest.php
@@ -37,13 +37,13 @@
        public function testRun_echo_parameters_1() {
                $this->assertEquals(
                                Interpreter::run('echo 
"Parameter1","Parameter2" , "Parameter3";'),
-                               array('Parameter1Parameter2Parameter3')
+                               array('Parameter1', 'Parameter2', 'Parameter3')
                                );
        }
        public function testRun_echo_parameters_2() {
                $this->assertEquals(
                                Interpreter::run('echo \'This \', \'string \', 
\'was \', \'made \', \'with multiple parameters.\';'),
-                               array('This string was made with multiple 
parameters.')
+                               array('This ', 'string ', 'was ', 'made ', 
'with multiple parameters.')
                                );
        }
 
@@ -98,7 +98,7 @@
        public function testRun_echo_variables_6() {
                $this->assertEquals(
                                Interpreter::run('echo $foo,$bar;'),
-                               array('foobarbarbaz')
+                               array('foobar', 'barbaz')
                                );
        }
        public function testRun_echo_variables_7() {
@@ -128,7 +128,7 @@
        public function testRun_echo_variables_11() {
                $this->assertEquals(
                                Interpreter::run('echo "This ", \'string \', 
"was $foo ", \'with multiple parameters.\';'),
-                               array('This string was foobar with multiple 
parameters.')
+                               array('This ', 'string ', 'was foobar ', 'with 
multiple parameters.')
                                );
        }
 
@@ -155,7 +155,7 @@
        public function testRun_echo_math_1() {
                $this->assertEquals(
                                Interpreter::run('echo \'5 + 5 * 10 = \', 5 + 5 
* 10;'),
-                               array('5 + 5 * 10 = 55')
+                               array('5 + 5 * 10 = ', '55')
                                );
        }
        public function testRun_echo_math_2() {
@@ -192,7 +192,7 @@
        public function testRun_echo_math_params() {
                $this->assertEquals(
                                Interpreter::run('echo \'10 + 5 * 5 = \', 10 + 
5 * 5, "\n\n";'),
-                               array("10 + 5 * 5 = 35\n\n")
+                               array('10 + 5 * 5 = ', '35', "\n\n")
                                );
        }
 
@@ -202,15 +202,15 @@
 $foo = 100;
 $bar = \'5\';
 echo "\$foo * \$bar = $foo * $bar = ", $foo * $bar, "\n\n";'),
-                               array("\$foo * \$bar = 100 * 5 = 500\n\n")
+                               array('$foo * $bar = 100 * 5 = ', '500', "\n\n")
                                );
                $this->assertEquals(
                                Interpreter::run('echo "\$foo / \$bar = $foo / 
$bar = ", $foo / $bar, "\n\n";'),
-                               array("\$foo / \$bar = 100 / 5 = 20\n\n")
+                               array('$foo / $bar = 100 / 5 = ', '20', "\n\n")
                                );
                $this->assertEquals(
                                Interpreter::run('echo "-\$foo / -\$bar = 
{-$foo} / {-$bar} = ", -$foo / -$bar, "\n\n";'),
-                               array("-\$foo / -\$bar = {-100} / {-5} = 
20\n\n")
+                               array('-$foo / -$bar = {-100} / {-5} = ', '20', 
"\n\n")
                                );
        }
 
@@ -345,7 +345,7 @@
        public function testRun_echo_math_Increment_1() {
                $this->assertEquals(
                                Interpreter::run('$a = 10; echo $a++, $a, 
++$a;'),
-                               array('101112')
+                               array('10', '11', '12')
                                );
        }
        public function testRun_echo_math_Increment_2() {
@@ -361,13 +361,13 @@
 $a++;
 ++$a;
 echo "$a, ", $a++ + -5, ", " . ++$a, ", $a.";'),
-                               array('12, 7, 14, 14.')
+                               array('12, ', '7', ', 14', ', 14.')
                                );
        }
        public function testRun_echo_math_Decrement_1() {
                $this->assertEquals(
                                Interpreter::run('$a = 10; echo $a--, $a, 
--$a;'),
-                               array('1098')
+                               array('10', '9', '8')
                                );
        }
        public function testRun_echo_math_Decrement_2() {
@@ -377,7 +377,7 @@
 $a--;
 --$a;
 echo "$a, ", $a-- + -5, ", " . --$a, ", $a.";'),
-                               array('8, 3, 6, 6.')
+                               array('8, ', '3', ', 6', ', 6.')
                                );
        }
 
@@ -424,13 +424,13 @@
        public function testRun_echo_parentheses_7() {
                $this->assertEquals(
                                Interpreter::run('echo("hello "), $foo;'),
-                               array('hello foo')
+                               array('hello ', 'foo')
                                );
        }
        public function testRun_echo_parentheses_8() {
                $this->assertEquals(
                                Interpreter::run('echo ($foo), (" is "), 
$foo;'),
-                               array('foo is foo')
+                               array('foo', ' is ', 'foo')
                                );
        }
 
@@ -827,4 +827,41 @@
                                );
        }
 
+       public function testRun_echo_assignment_1() {
+               $this->assertEquals(
+                               Interpreter::run('echo $foo = 1;'),
+                               array('1')
+                               );
+       }
+       public function testRun_echo_assignment_2() {
+               $this->assertEquals(
+                               Interpreter::run('echo $foo = 1 + 2;'),
+                               array('3')
+                               );
+       }
+       public function testRun_echo_assignment_3() {
+               $this->assertEquals(
+                               Interpreter::run('$foo=1; echo $foo += 2;'),
+                               array('3')
+                               );
+       }
+       public function testRun_echo_assignment_4() {
+               $this->assertEquals(
+                               Interpreter::run('$foo=1; echo $foo += 2 + 3;'),
+                               array('6')
+                               );
+       }/*
+       public function testRun_echo_assignment_5() {
+               $this->assertEquals(
+                               Interpreter::run('echo $bar = $foo = 1, $foo, 
$bar;'),
+                               array('1', '1', '1')
+                               );
+       }*/
+       public function testRun_echo_assignment_6() {
+               $this->assertEquals(
+                               Interpreter::run('$foo=1; $bar=2; $foo+=$bar; 
echo $foo,$bar;'),
+                               array('3', '2')
+                               );
+       }
+
 }

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I7a479b05548e9a9f096f3d1375fb6feaafab8c2d
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Foxway
Gerrit-Branch: master
Gerrit-Owner: Pastakhov <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to