From 926510aa0907beb22a220bcde2a568ffb50fa364 Mon Sep 17 00:00:00 2001 From: Cinderella-Man Date: Thu, 5 Dec 2013 01:24:01 +0000 Subject: [PATCH 1/3] Fake empty function partly implemented --- Library/Operators/Other/CloneOperator.php | 2 +- Library/Operators/Other/EmptyOperator.php | 36 ++++++++++++++++++++++- parser/scanner.c | 2 +- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/Library/Operators/Other/CloneOperator.php b/Library/Operators/Other/CloneOperator.php index b9f87dedf07..976adc1a8f8 100644 --- a/Library/Operators/Other/CloneOperator.php +++ b/Library/Operators/Other/CloneOperator.php @@ -46,7 +46,7 @@ public function compile($expression, CompilationContext $compilationContext) $clonedVariable = $compilationContext->symbolTable->getVariableForRead($exprCompiledVariable->getCode(), $compilationContext, $expression); if ($clonedVariable->getType() != 'variable') { - throw new CompiledException("Variable type: " . $variable->getType() . " cannot be cloned"); + throw new CompiledException("Variable type: " . $exprVariable->getType() . " cannot be cloned"); } if ($clonedVariable->hasDifferentDynamicType(array('undefined', 'object', 'null'))) { diff --git a/Library/Operators/Other/EmptyOperator.php b/Library/Operators/Other/EmptyOperator.php index 1c737fc813d..6980947cdf2 100644 --- a/Library/Operators/Other/EmptyOperator.php +++ b/Library/Operators/Other/EmptyOperator.php @@ -33,10 +33,44 @@ class EmptyOperator extends BaseOperator */ public function compile($expression, CompilationContext $compilationContext) { - $compilationContext->headersManager->add('kernel/operators'); + if (isset($expression['left']['type']) + && $expression['left']['type'] == 'variable' + ) { + return $this->evaluateVariableExpression($expression, $compilationContext); + } + return new CompiledExpression('int', '(0 == 0)', $expression); } + /** + * Evaluates variable expressions like + * if empty $a + * if !empty $b + * + * it will create something around below lines: + * ZEPHIR_IS_EMPTY(var) + * + * @param array $expression + * @param \CompilationContext $compilationContext + * @return \CompiledExpression + */ + protected function evaluateVariableExpression( + $expression, + CompilationContext $compilationContext + ) { + + $variable = $compilationContext->symbolTable->getVariableForWrite( + $expression['left']['value'], + $compilationContext, + $expression['left'] + ); + + return new CompiledExpression( + 'bool', + 'ZEPHIR_IS_EMPTY(' . $variable->getName() . ')', + $expression + ); + } } \ No newline at end of file diff --git a/parser/scanner.c b/parser/scanner.c index 117c0c37efb..45431ce63cb 100644 --- a/parser/scanner.c +++ b/parser/scanner.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 on Mon Nov 25 11:46:04 2013 */ +/* Generated by re2c 0.13.5 on Wed Dec 4 23:31:37 2013 */ // 1 "scanner.re" /* From 4f0065437fc07cd6a576ff9856220b5ef8d9630b Mon Sep 17 00:00:00 2001 From: Cinderella-Man Date: Thu, 5 Dec 2013 01:55:02 +0000 Subject: [PATCH 2/3] Support for abstract classes --- Library/ClassDefinition.php | 9 +++++++-- parser/scanner.c | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Library/ClassDefinition.php b/Library/ClassDefinition.php index 8888c71fab6..d8af8d9bf1a 100644 --- a/Library/ClassDefinition.php +++ b/Library/ClassDefinition.php @@ -532,6 +532,11 @@ public function compile(CompilationContext $compilationContext) $namespace = $compilationContext->config->get('namespace'); + $abstractFlag = '0'; + if ($this->isAbstract()) { + $abstractFlag = 'ZEND_ACC_EXPLICIT_ABSTRACT_CLASS'; + } + /** * Register the class with extends + interfaces */ @@ -556,7 +561,7 @@ public function compile(CompilationContext $compilationContext) if ($this->getType() == 'class') { $codePrinter->output('ZEPHIR_REGISTER_CLASS_EX(' . $this->getNCNamespace() . ', ' . $this->getName() . ', ' . $namespace . ', ' . - strtolower($this->getSCName($namespace)) . ', ' . $classEntry . ', ' . $methodEntry . ', 0);'); + strtolower($this->getSCName($namespace)) . ', ' . $classEntry . ', ' . $methodEntry . ', ' . $abstractFlag . ');'); $codePrinter->outputBlankLine(); } else { $codePrinter->output('ZEPHIR_REGISTER_INTERFACE_EX(' . $this->getNCNamespace() . ', ' . $this->getName() . ', ' . $namespace . ', ' . @@ -566,7 +571,7 @@ public function compile(CompilationContext $compilationContext) } else { if ($this->getType() == 'class') { $codePrinter->output('ZEPHIR_REGISTER_CLASS(' . $this->getNCNamespace() . ', ' . $this->getName() . ', ' . $namespace . ', ' . - strtolower($this->getSCName($namespace)) . ', ' . $methodEntry . ', 0);'); + strtolower($this->getSCName($namespace)) . ', ' . $methodEntry . ', ' . $abstractFlag . ');'); } else { $codePrinter->output('ZEPHIR_REGISTER_INTERFACE(' . $this->getNCNamespace() . ', ' . $this->getName() . ', ' . $namespace . ', ' . strtolower($this->getSCName($namespace)) . ', ' . $methodEntry . ');'); diff --git a/parser/scanner.c b/parser/scanner.c index 45431ce63cb..e09edf0cba4 100644 --- a/parser/scanner.c +++ b/parser/scanner.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 on Wed Dec 4 23:31:37 2013 */ +/* Generated by re2c 0.13.5 on Thu Dec 5 01:52:37 2013 */ // 1 "scanner.re" /* From 43680be73892e634ab2129c467e37feffe8b17b4 Mon Sep 17 00:00:00 2001 From: Cinderella-Man Date: Tue, 17 Dec 2013 22:50:03 +0000 Subject: [PATCH 3/3] Updates and small unit test --- Library/Operators/Other/EmptyOperator.php | 27 +++++++++++++++-------- Library/SymbolTable.php | 4 ++-- test/flow.zep | 22 +++++++++++------- unit-tests/flow.php | 10 ++++++++- 4 files changed, 43 insertions(+), 20 deletions(-) diff --git a/Library/Operators/Other/EmptyOperator.php b/Library/Operators/Other/EmptyOperator.php index 6980947cdf2..458090044a4 100644 --- a/Library/Operators/Other/EmptyOperator.php +++ b/Library/Operators/Other/EmptyOperator.php @@ -35,13 +35,7 @@ public function compile($expression, CompilationContext $compilationContext) { $compilationContext->headersManager->add('kernel/operators'); - if (isset($expression['left']['type']) - && $expression['left']['type'] == 'variable' - ) { - return $this->evaluateVariableExpression($expression, $compilationContext); - } - - return new CompiledExpression('int', '(0 == 0)', $expression); + return $this->evaluateVariableExpression($expression, $compilationContext); } /** @@ -61,10 +55,25 @@ protected function evaluateVariableExpression( CompilationContext $compilationContext ) { + switch (true) { + case isset($expression['left']['left']['value']) + && isset($expression['left']['left']['type']) + && $expression['left']['left']['type'] == 'variable': + + $name = $expression['left']['left']['value']; + + break; + + default: + throw new Exception( + 'Empty syntax not supported' + ); + } + $variable = $compilationContext->symbolTable->getVariableForWrite( - $expression['left']['value'], + $name, $compilationContext, - $expression['left'] + $expression['left']['left'] ); return new CompiledExpression( diff --git a/Library/SymbolTable.php b/Library/SymbolTable.php index bc37e12c3c6..35e8b0a3f32 100644 --- a/Library/SymbolTable.php +++ b/Library/SymbolTable.php @@ -189,11 +189,11 @@ public function getVariableForRead($name, CompilationContext $compilationContext /** * Return a variable in the symbol table, it will be used for a write operation - * Some variables aren't writables themselves but their members do + * Some variables aren't writable themselves but their members do * * @param string $name - * @param array $statement * @param CompilationContext $compilationContext + * @param array $statement * @return \Variable */ public function getVariableForWrite($name, $compilationContext, $statement=null) diff --git a/test/flow.zep b/test/flow.zep index a966cb06ada..959c94d1c09 100644 --- a/test/flow.zep +++ b/test/flow.zep @@ -119,15 +119,15 @@ class Flow if b { let c = 1; if c { - return 1; + return 654; } else { - return 0; + return -1; } } else { - return 0; + return -2; } } else { - return 0; + return -3; } } @@ -142,7 +142,7 @@ class Flow if b { let c = 1; if c { - return 1; + return 987; } else { return 0; } @@ -158,7 +158,7 @@ class Flow { int a, b; let a = 1, b = 2; - if a + b { return 1; } + if a + b { return -12; } return 0; } @@ -166,7 +166,7 @@ class Flow { var a, b; let a = 1, b = 2; - if a + b { return 1; } + if a + b { return 74; } return 0; } @@ -174,10 +174,16 @@ class Flow { var a, b, c; let a = 1, b = 2, c = 3; - if a + b + c { return 1; } + if a + b + c { return 89; } return 0; } + public function testIf16(var a) + { + if empty(a) { return true; } + return false; + } + public function testLoop1() { var a; diff --git a/unit-tests/flow.php b/unit-tests/flow.php index 8f805dbd6e8..42f099261cf 100644 --- a/unit-tests/flow.php +++ b/unit-tests/flow.php @@ -11,7 +11,15 @@ assert($t->testIf7() === 1); assert($t->testIf8() === 0); assert($t->testIf9() === 1); -assert($t->testIf10() === 1); +assert($t->testIf10() === 654); +assert($t->testIf12() === 987); +assert($t->testIf13() === -12); +assert($t->testIf14() === 74); +assert($t->testIf15() === 89); +assert($t->testIf16(array()) === false); +assert($t->testIf16('') === true); +assert($t->testIf16(null) === true); +assert($t->testIf16(' ') === false); assert($t->testLoop1() === true); assert($t->testLoop2() === 5);