/** * Creates a closure * * @param array $expression * @param CompilationContext $compilationContext * @return CompiledExpression * @throws \Zephir\CompilerException */ public function compile(array $expression, CompilationContext $compilationContext) { $classDefinition = new ClassDefinition($compilationContext->config->get('namespace'), self::$id . '__closure'); $classDefinition->setIsFinal(true); $compilerFile = new CompilerFileAnonymous($classDefinition, $compilationContext->config, $compilationContext->logger); $compilationContext->compiler->addClassDefinition($compilerFile, $classDefinition); /** * Builds parameters using the only parameter available */ $parameters = new ClassMethodParameters(array(array('type' => 'parameter', 'name' => $expression['left']['value'], 'const' => 0, 'data-type' => 'variable', 'mandatory' => 0, 'reference' => 0, 'file' => $expression['left']['file'], 'line' => $expression['left']['line'], 'char' => $expression['left']['char']))); $statementBlock = new StatementsBlockBuilder(array(new ReturnStatementBuilder(new RawExpressionBuilder($expression['right'])))); $block = $statementBlock->get(); $classMethod = new ClassMethod($classDefinition, array('public', 'final'), '__invoke', $parameters, new StatementsBlock($block), null, null, $expression); $classDefinition->addMethod($classMethod, $block); $compilationContext->headersManager->add('kernel/object'); if ($this->expecting) { if ($this->expectingVariable) { $symbolVariable = $this->expectingVariable; } else { $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression); } } else { $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression); } $symbolVariable->initVariant($compilationContext); $compilationContext->codePrinter->output('zephir_create_closure_ex(' . $symbolVariable->getName() . ', NULL, ' . $classDefinition->getClassEntry() . ', SS("__invoke") TSRMLS_CC);'); self::$id++; return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression); }
private function initializeArray($compilationContext) { $classDefinition = $this->classDefinition; $parentClassDefinition = $classDefinition->getExtendsClassDefinition(); if (!$this->isStatic()) { $constructParentMethod = $parentClassDefinition ? $parentClassDefinition->getInitMethod() : null; $constructMethod = $classDefinition->getInitMethod(); } else { $constructParentMethod = $parentClassDefinition ? $parentClassDefinition->getStaticInitMethod() : null; $constructMethod = $classDefinition->getStaticInitMethod(); } if ($constructMethod) { $statementsBlock = $constructMethod->getStatementsBlock(); if ($statementsBlock) { $statements = $statementsBlock->getStatements(); $letStatement = $this->getLetStatement()->get(); $needLetStatementAdded = true; foreach ($statements as $statement) { if ($statement === $letStatement) { $needLetStatementAdded = false; break; } } $this->removeInitializationStatements($statements); if ($needLetStatementAdded) { $newStatements = array(); /** * Start from let statement */ $newStatements[] = $letStatement; foreach ($statements as $statement) { $newStatements[] = $statement; } $statementsBlock->setStatements($newStatements); $constructMethod->setStatementsBlock($statementsBlock); $classDefinition->updateMethod($constructMethod); } } else { $statementsBlockBuilder = new StatementsBlockBuilder(array($this->getLetStatement()), false); $constructMethod->setStatementsBlock(new StatementsBlock($statementsBlockBuilder->get())); $classDefinition->updateMethod($constructMethod); } } else { $statements = array(); if ($constructParentMethod) { $statements = $constructParentMethod->getStatementsBlock()->getStatements(); } $this->removeInitializationStatements($statements); $statements[] = $this->getLetStatement()->get(); $statementsBlock = new StatementsBlock($statements); if ($this->isStatic()) { $classDefinition->addStaticInitMethod($statementsBlock); } else { $classDefinition->addInitMethod($statementsBlock); } } }
/** * Produce the code to register a property * * @param CompilationContext $compilationContext * @throws CompilerException */ public function compile(CompilationContext $compilationContext) { switch ($this->defaultValue['type']) { case 'long': case 'int': case 'string': case 'double': case 'bool': $this->declareProperty($compilationContext, $this->defaultValue['type'], $this->defaultValue['value']); break; case 'array': case 'empty-array': $classDefinition = $this->classDefinition; if ($this->isStatic()) { $methodName = 'zephir_init_static_properties'; $visibility = array('internal'); } else { $methodName = 'zephir_init_properties'; $visibility = array('internal'); /* Make sure a constructor exists, so that properties are initialized */ $method = $classDefinition->getMethod('__construct'); if (!$method || $method->getClassDefinition() != $classDefinition) { $classDefinition->setIsGeneratedConstructor(true); $classDefinition->getEventsManager()->dispatch('setMethod', array(new ClassMethod($classDefinition, array('public'), '__construct', null, null), null)); } } $constructParentMethod = null; $constructMethod = $classDefinition->getMethod($methodName); /** * Make sure we do not steal the construct method of the parent, * but initialize our own with the inherited statements to ensure * valid property initialization */ if ($constructMethod && $constructMethod->getClassDefinition() != $classDefinition) { $constructParentMethod = $constructMethod; $constructMethod = null; } if ($constructMethod) { $statementsBlock = $constructMethod->getStatementsBlock(); if ($statementsBlock) { $statements = $statementsBlock->getStatements(); $letStatement = $this->getLetStatement()->get(); $needLetStatementAdded = true; foreach ($statements as $statement) { if ($statement === $letStatement) { $needLetStatementAdded = false; break; } } if ($needLetStatementAdded) { $newStatements = array(); /** * Start from let statement */ $newStatements[] = $letStatement; foreach ($statements as $statement) { $newStatements[] = $statement; } $statementsBlock->setStatements($newStatements); $constructMethod->setStatementsBlock($statementsBlock); $classDefinition->getEventsManager()->dispatch('setMethod', array($constructMethod)); } } else { $statementsBlockBuilder = new StatementsBlockBuilder(array($this->getLetStatement()), false); $constructMethod->setStatementsBlock(new StatementsBlock($statementsBlockBuilder->get())); $classDefinition->getEventsManager()->dispatch('setMethod', array($constructMethod)); } } else { $statements = array(); if ($constructParentMethod) { $statements = $constructParentMethod->getStatementsBlock()->getStatements(); } $statements[] = $this->getLetStatement()->get(); $statementsBlock = new StatementsBlock($statements); $classDefinition->getEventsManager()->dispatch('setMethod', array(new ClassMethod($classDefinition, $visibility, $methodName, null, $statementsBlock), null)); return false; } //continue //continue case 'null': $this->declareProperty($compilationContext, $this->defaultValue['type'], null); break; case 'static-constant-access': $expression = new Expression($this->defaultValue); $compiledExpression = $expression->compile($compilationContext); $this->declareProperty($compilationContext, $compiledExpression->getType(), $compiledExpression->getCode()); break; default: throw new CompilerException('Unknown default type: ' . $this->defaultValue['type'], $this->original); } }
/** * Produce the code to register a property * * @param CompilationContext $compilationContext * @throws CompilerException */ public function compile(CompilationContext $compilationContext) { switch ($this->_defaultValue['type']) { case 'long': case 'int': case 'string': case 'double': case 'bool': $this->declareProperty($compilationContext, $this->_defaultValue['type'], $this->_defaultValue['value']); break; case 'array': case 'empty-array': if ($this->isStatic()) { throw new CompilerException('Cannot define static property with default value: ' . $this->_defaultValue['type'], $this->_original); } $constructMethod = $compilationContext->classDefinition->getMethod('__construct'); if ($constructMethod) { $statementsBlock = $constructMethod->getStatementsBlock(); if ($statementsBlock) { $statements = $statementsBlock->getStatements(); $letStatement = $this->getLetStatement()->get(); $needLetStatementAdded = true; foreach ($statements as $statement) { if ($statement === $letStatement) { $needLetStatementAdded = false; break; } } if ($needLetStatementAdded) { $statements[] = $letStatement; $statementsBlock->setStatements($statements); $constructMethod->setStatementsBlock($statementsBlock); $compilationContext->classDefinition->getEventsManager()->dispatch('setMethod', array($constructMethod)); } } else { $statementsBlockBuilder = new StatementsBlockBuilder(array($this->getLetStatement()), false); $constructMethod->setStatementsBlock(new StatementsBlock($statementsBlockBuilder->get())); $compilationContext->classDefinition->getEventsManager()->dispatch('setMethod', array($constructMethod)); } } else { $statementsBlock = new StatementsBlock(array($this->getLetStatement()->get())); $compilationContext->classDefinition->getEventsManager()->dispatch('setMethod', array(new ClassMethod($compilationContext->classDefinition, array('public'), '__construct', null, $statementsBlock), null)); return false; } //continue //continue case 'null': $this->declareProperty($compilationContext, $this->_defaultValue['type'], null); break; case 'static-constant-access': $expression = new Expression($this->_defaultValue); $compiledExpression = $expression->compile($compilationContext); $this->declareProperty($compilationContext, $compiledExpression->getType(), $compiledExpression->getCode()); break; default: throw new CompilerException('Unknown default type: ' . $this->_defaultValue['type'], $this->_original); } }