作者:NumbDa
项目:zephi
/**
* @param array $expression
* @param Call $call
* @param CompilationContext $context
* @return bool|CompiledExpression|mixed
* @throws CompilerException
*/
public function optimize(array $expression, Call $call, CompilationContext $context)
{
if (!isset($expression['parameters'])) {
return false;
}
if (count($expression['parameters']) != 2) {
return false;
}
/**
* Process the expected symbol to be returned
*/
$call->processExpectedReturn($context);
$symbolVariable = $call->getSymbolVariable();
if ($symbolVariable->isNotVariableAndString()) {
throw new CompilerException("Returned values by functions can only be assigned to variant variables", $expression);
}
if ($expression['parameters'][0]['parameter']['type'] == 'string') {
$str = Utils::addSlashes($expression['parameters'][0]['parameter']['value']);
unset($expression['parameters'][0]);
}
if ($call->mustInitSymbolVariable()) {
$symbolVariable->initVariant($context);
}
$resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression);
$context->headersManager->add('kernel/string');
$symbolVariable->setDynamicTypes('string');
if (isset($str)) {
$context->codePrinter->output('zephir_fast_join_str(' . $symbolVariable->getName() . ', SL("' . $str . '"), ' . $resolvedParams[0] . ' TSRMLS_CC);');
return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
}
$context->codePrinter->output('zephir_fast_join(' . $symbolVariable->getName() . ', ' . $resolvedParams[0] . ', ' . $resolvedParams[1] . ' TSRMLS_CC);');
return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
}
作者:NumbDa
项目:zephi
/**
* @param CompilationContext $compilationContext
* @throws CompilerException
*/
public function compile(CompilationContext $compilationContext)
{
$compilationContext->headersManager->add('kernel/exception');
$codePrinter = $compilationContext->codePrinter;
$statement = $this->_statement;
$expr = $statement['expr'];
/**
* This optimizes throw new Exception("hello")
*/
if (!$compilationContext->insideTryCatch) {
if (isset($expr['class'])) {
if (isset($expr['parameters']) && count($expr['parameters']) == 1) {
if ($expr['parameters'][0]['parameter']['type'] == 'string') {
$className = Utils::getFullName($expr['class'], $compilationContext->classDefinition->getNamespace(), $compilationContext->aliasManager);
if ($compilationContext->compiler->isClass($className)) {
$classDefinition = $compilationContext->compiler->getClassDefinition($className);
$message = $expr['parameters'][0]['parameter']['value'];
$codePrinter->output('ZEPHIR_THROW_EXCEPTION_DEBUG_STR(' . $classDefinition->getClassEntry() . ', "' . Utils::addSlashes($message, true, Types::STRING) . '", "' . Compiler::getShortUserPath($statement['expr']['file']) . '", ' . $statement['expr']['line'] . ');');
$codePrinter->output('return;');
return;
} else {
if ($compilationContext->compiler->isInternalClass($className)) {
$classEntry = $compilationContext->classDefinition->getClassEntryByClassName($className, true);
if ($classEntry) {
$message = $expr['parameters'][0]['parameter']['value'];
$codePrinter->output('ZEPHIR_THROW_EXCEPTION_DEBUG_STR(' . $classEntry . ', "' . Utils::addSlashes($message, true, Types::STRING) . '", "' . Compiler::getShortUserPath($statement['expr']['file']) . '", ' . $statement['expr']['line'] . ');');
$codePrinter->output('return;');
return;
}
}
}
}
}
}
}
$throwExpr = new Expression($expr);
$resolvedExpr = $throwExpr->compile($compilationContext);
if ($resolvedExpr->getType() != 'variable') {
throw new CompilerException("Expression '" . $resolvedExpr->getType() . '" cannot be used as exception', $expr);
}
$variableVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $expr);
if ($variableVariable->getType() != 'variable') {
throw new CompilerException("Variable '" . $variableVariable->getType() . "' cannot be used as exception", $expr);
}
$codePrinter->output('zephir_throw_exception_debug(' . $variableVariable->getName() . ', "' . Compiler::getShortUserPath($statement['expr']['file']) . '", ' . $statement['expr']['line'] . ' TSRMLS_CC);');
if (!$compilationContext->insideTryCatch) {
$codePrinter->output('ZEPHIR_MM_RESTORE();');
$codePrinter->output('return;');
} else {
$codePrinter->output('goto try_end_' . $compilationContext->insideTryCatch . ';');
$codePrinter->outputBlankLine();
}
if ($variableVariable->isTemporal()) {
$variableVariable->setIdle(true);
}
}
作者:gvanbec
项目:zephi
/**
* @param array $expression
* @param Call $call
* @param CompilationContext $context
* @return bool|CompiledExpression|mixed
* @throws CompilerException
*/
public function optimize(array $expression, Call $call, CompilationContext $context)
{
if (!isset($expression['parameters'])) {
return false;
}
if (count($expression['parameters']) < 2) {
throw new CompilerException("'explode' require two parameter");
}
/**
* Process the expected symbol to be returned
*/
$call->processExpectedReturn($context);
$symbolVariable = $call->getSymbolVariable(true, $context);
if ($symbolVariable->isNotVariableAndString()) {
throw new CompilerException("Returned values by functions can only be assigned to variant variables", $expression);
}
/**
* Process limit
*/
$limit = 'LONG_MAX';
$limitOffset = 2;
if (count($expression['parameters']) == 3 && $expression['parameters'][2]['parameter']['type'] == 'int') {
$limit = $expression['parameters'][2]['parameter']['value'] . ' ';
unset($expression['parameters'][2]);
}
if ($expression['parameters'][0]['parameter']['type'] == 'string') {
$str = Utils::addSlashes($expression['parameters'][0]['parameter']['value']);
unset($expression['parameters'][0]);
if (count($expression['parameters']) == 2) {
$limitOffset = 1;
}
}
$resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression);
if (isset($resolvedParams[$limitOffset])) {
$context->headersManager->add('kernel/operators');
$limit = 'zephir_get_intval(' . $resolvedParams[$limitOffset] . ') ';
}
$context->headersManager->add('kernel/string');
$symbolVariable->setDynamicTypes('array');
if ($call->mustInitSymbolVariable()) {
$symbolVariable->initVariant($context);
}
$symbol = $context->backend->getVariableCode($symbolVariable);
if (isset($str)) {
$context->codePrinter->output('zephir_fast_explode_str(' . $symbol . ', SL("' . $str . '"), ' . $resolvedParams[0] . ', ' . $limit . ' TSRMLS_CC);');
return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
}
$context->codePrinter->output('zephir_fast_explode(' . $symbol . ', ' . $resolvedParams[0] . ', ' . $resolvedParams[1] . ', ' . $limit . ' TSRMLS_CC);');
return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
}
作者:chet0xhenr
项目:zephi
/**
* @param array $expression
* @param Call $call
* @param CompilationContext $context
* @return bool|CompiledExpression|mixed
*/
public function optimize(array $expression, Call $call, CompilationContext $context)
{
if (!isset($expression['parameters'])) {
return false;
}
if (count($expression['parameters']) != 2) {
return false;
}
if ($expression['parameters'][1]['parameter']['type'] == 'string') {
$str = Utils::addSlashes($expression['parameters'][1]['parameter']['value']);
unset($expression['parameters'][1]);
}
$resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression);
$context->headersManager->add('kernel/string');
if (isset($str)) {
return new CompiledExpression('bool', 'zephir_memnstr_str(' . $resolvedParams[0] . ', SL("' . $str . '"), "' . Compiler::getShortUserPath($expression['file']) . '", ' . $expression['line'] . ')', $expression);
}
return new CompiledExpression('bool', 'zephir_memnstr(' . $resolvedParams[0] . ', ' . $resolvedParams[1] . ', "' . Compiler::getShortUserPath($expression['file']) . '", ' . $expression['line'] . ')', $expression);
}
作者:chet0xhenr
项目:zephi
/**
* @param array $expression
* @param Call $call
* @param CompilationContext $context
* @return bool|CompiledExpression|mixed
*/
public function optimize(array $expression, Call $call, CompilationContext $context)
{
if (!isset($expression['parameters'])) {
return false;
}
if (count($expression['parameters']) != 2) {
return false;
}
if ($expression['parameters'][1]['parameter']['type'] == 'string') {
$str = Utils::addSlashes($expression['parameters'][1]['parameter']['value']);
unset($expression['parameters'][1]);
}
$context->headersManager->add('kernel/object');
$resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression);
if (isset($str)) {
return new CompiledExpression('bool', '(zephir_method_exists_ex(' . $resolvedParams[0] . ', SS("' . strtolower($str) . '") TSRMLS_CC) == SUCCESS)', $expression);
}
return new CompiledExpression('bool', '(zephir_method_exists(' . $resolvedParams[0] . ', ' . $resolvedParams[1] . ' TSRMLS_CC) == SUCCESS)', $expression);
}
作者:chet0xhenr
项目:zephi
/**
* @param array $expression
* @param Call $call
* @param CompilationContext $context
* @return bool|CompiledExpression|mixed
*/
public function optimize(array $expression, Call $call, CompilationContext $context)
{
if (!isset($expression['parameters'])) {
return false;
}
if (count($expression['parameters']) != 1) {
return false;
}
if ($expression['parameters'][0]['parameter']['type'] == 'string') {
$str = Utils::addSlashes($expression['parameters'][0]['parameter']['value']);
unset($expression['parameters'][0]);
}
$context->headersManager->add('kernel/object');
$resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression);
if (isset($str)) {
/* TODO: Solve this macro stuff better, move to backend */
$macro = $context->backend->isZE3() ? 'SL' : 'SS';
return new CompiledExpression('bool', '(zephir_function_exists_ex(' . $macro . '("' . strtolower($str) . '") TSRMLS_CC) == SUCCESS)', $expression);
}
return new CompiledExpression('bool', '(zephir_function_exists(' . $resolvedParams[0] . ' TSRMLS_CC) == SUCCESS)', $expression);
}
作者:Jvbzephi
项目:zephi
//.........这里部分代码省略.........
throw new CompilerException("Returning type: " . $resolvedExpr->getType() . " but this type is not compatible with return-type hints declared in the method", $statement['expr']);
}
break;
case 'bool':
if (!$currentMethod->areReturnTypesBoolCompatible()) {
throw new CompilerException("Returning type: " . $resolvedExpr->getType() . " but this type is not compatible with return-type hints declared in the method", $statement['expr']);
}
break;
case 'variable':
break;
}
break;
}
}
switch ($resolvedExpr->getType()) {
case 'null':
$codePrinter->output('RETURN_MM_NULL();');
break;
case 'int':
case 'uint':
case 'long':
case 'char':
case 'uchar':
$codePrinter->output('RETURN_MM_LONG(' . $resolvedExpr->getCode() . ');');
break;
case 'bool':
$codePrinter->output('RETURN_MM_BOOL(' . $resolvedExpr->getBooleanCode() . ');');
break;
case 'double':
$codePrinter->output('RETURN_MM_DOUBLE(' . $resolvedExpr->getCode() . ');');
break;
case 'string':
case 'istring':
$codePrinter->output('RETURN_MM_STRING("' . Utils::addSlashes($resolvedExpr->getCode()) . '", 1);');
break;
case 'array':
if ($resolvedExpr->getCode() != 'return_value') {
$codePrinter->output('RETURN_CTOR(' . $resolvedExpr->getCode() . ');');
} else {
$codePrinter->output('RETURN_MM();');
}
break;
case 'variable':
if (!isset($symbolVariable)) {
$symbolVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement['expr']);
}
switch ($symbolVariable->getType()) {
case 'int':
case 'uint':
case 'long':
case 'char':
case 'uchar':
$codePrinter->output('RETURN_MM_LONG(' . $symbolVariable->getName() . ');');
break;
case 'double':
$codePrinter->output('RETURN_MM_DOUBLE(' . $symbolVariable->getName() . ');');
break;
case 'string':
case 'array':
$codePrinter->output('RETURN_CTOR(' . $resolvedExpr->getCode() . ');');
break;
case 'bool':
$codePrinter->output('RETURN_MM_BOOL(' . $symbolVariable->getName() . ');');
break;
case 'variable':
if ($symbolVariable->getName() == 'this_ptr') {
作者:chet0xhenr
项目:zephi
/**
* Resolve parameters using zvals in the stack and without allocating memory for constants
*
* @param array $parameters
* @param CompilationContext $compilationContext
* @param array $expression
* @return array
*/
public function getReadOnlyResolvedParams($parameters, CompilationContext $compilationContext, array $expression)
{
$codePrinter = $compilationContext->codePrinter;
$exprParams = $this->getResolvedParamsAsExpr($parameters, $compilationContext, $expression, true);
$params = array();
$types = array();
$dynamicTypes = array();
foreach ($exprParams as $compiledExpression) {
$expression = $compiledExpression->getOriginal();
switch ($compiledExpression->getType()) {
case 'null':
$params[] = $compilationContext->backend->resolveValue('null', $compilationContext);
$types[] = 'null';
$dynamicTypes[] = 'null';
break;
case 'int':
case 'uint':
case 'long':
$parameterVariable = $compilationContext->backend->getScalarTempVariable('variable', $compilationContext, true);
$compilationContext->backend->assignLong($parameterVariable, $compiledExpression->getCode(), $compilationContext);
$this->_temporalVariables[] = $parameterVariable;
$params[] = '&' . $parameterVariable->getName();
$types[] = $parameterVariable->getType();
$dynamicTypes[] = $parameterVariable->getType();
break;
case 'char':
case 'uchar':
$parameterVariable = $compilationContext->backend->getScalarTempVariable('variable', $compilationContext, true);
$compilationContext->backend->assignLong($parameterVariable, '\'' . $compiledExpression->getCode() . '\'', $compilationContext);
$this->_temporalVariables[] = $parameterVariable;
$params[] = '&' . $parameterVariable->getName();
$types[] = $parameterVariable->getType();
$dynamicTypes[] = $parameterVariable->getType();
break;
case 'double':
$parameterVariable = $compilationContext->backend->getScalarTempVariable('variable', $compilationContext, true);
$codePrinter->output('ZVAL_DOUBLE(&' . $parameterVariable->getName() . ', ' . $compiledExpression->getCode() . ');');
$this->_temporalVariables[] = $parameterVariable;
$params[] = '&' . $parameterVariable->getName();
$types[] = $parameterVariable->getType();
$dynamicTypes[] = $parameterVariable->getType();
break;
case 'bool':
if ($compiledExpression->getCode() == 'true') {
$params[] = $compilationContext->backend->resolveValue('true', $compilationContext);
} else {
if ($compiledExpression->getCode() == 'false') {
$params[] = $compilationContext->backend->resolveValue('false', $compilationContext);
} else {
throw new Exception('?');
}
}
$types[] = 'bool';
$dynamicTypes[] = 'bool';
break;
case 'ulong':
case 'string':
case 'istring':
if ($compilationContext->backend->getName() == 'ZendEngine2') {
$parameterVariable = $compilationContext->symbolTable->getTempLocalVariableForWrite('variable', $compilationContext, $expression);
} else {
$parameterVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression);
}
$compilationContext->backend->assignString($parameterVariable, Utils::addSlashes($compiledExpression->getCode()), $compilationContext, true, false);
$this->_temporalVariables[] = $parameterVariable;
$params[] = '&' . $parameterVariable->getName();
$types[] = $parameterVariable->getType();
$dynamicTypes[] = $parameterVariable->getType();
break;
case 'array':
$parameterVariable = $compilationContext->symbolTable->getVariableForRead($compiledExpression->getCode(), $compilationContext, $expression);
$params[] = $compilationContext->backend->getVariableCode($parameterVariable);
$types[] = $parameterVariable->getType();
$dynamicTypes[] = $parameterVariable->getType();
break;
case 'variable':
$parameterVariable = $compilationContext->symbolTable->getVariableForRead($compiledExpression->getCode(), $compilationContext, $expression);
switch ($parameterVariable->getType()) {
case 'int':
case 'uint':
case 'long':
case 'ulong':
$parameterTempVariable = $compilationContext->backend->getScalarTempVariable('variable', $compilationContext, true);
$codePrinter->output('ZVAL_LONG(&' . $parameterTempVariable->getName() . ', ' . $compiledExpression->getCode() . ');');
$params[] = '&' . $parameterTempVariable->getName();
$types[] = $parameterTempVariable->getType();
$dynamicTypes[] = $parameterTempVariable->getType();
$this->_temporalVariables[] = $parameterTempVariable;
break;
case 'char':
case 'uchar':
$parameterTempVariable = $compilationContext->backend->getScalarTempVariable('variable', $compilationContext, true);
//.........这里部分代码省略.........
作者:chet0xhenr
项目:zephi
public function generateFunctionInformation()
{
$headerPrinter = new CodePrinter();
$entryPrinter = new CodePrinter();
/**
* Create argument info
*/
foreach ($this->functionDefinitions as $func) {
$funcName = $func->getInternalName();
$argInfoName = 'arginfo_' . strtolower($funcName);
$headerPrinter->output('PHP_FUNCTION(' . $funcName . ');');
$parameters = $func->getParameters();
if (count($parameters)) {
$headerPrinter->output('ZEND_BEGIN_ARG_INFO_EX(' . $argInfoName . ', 0, 0, ' . $func->getNumberOfRequiredParameters() . ')');
foreach ($parameters->getParameters() as $parameter) {
switch ($parameter['data-type']) {
case 'array':
$headerPrinter->output("\t" . 'ZEND_ARG_ARRAY_INFO(0, ' . $parameter['name'] . ', ' . (isset($parameter['default']) ? 1 : 0) . ')');
break;
case 'variable':
if (isset($parameter['cast'])) {
switch ($parameter['cast']['type']) {
case 'variable':
$value = $parameter['cast']['value'];
$headerPrinter->output("\t" . 'ZEND_ARG_OBJ_INFO(0, ' . $parameter['name'] . ', ' . Utils::escapeClassName($compilationContext->getFullName($value)) . ', ' . (isset($parameter['default']) ? 1 : 0) . ')');
break;
default:
throw new Exception('Unexpected exception');
}
} else {
$headerPrinter->output("\t" . 'ZEND_ARG_INFO(0, ' . $parameter['name'] . ')');
}
break;
default:
$headerPrinter->output("\t" . 'ZEND_ARG_INFO(0, ' . $parameter['name'] . ')');
break;
}
}
$headerPrinter->output('ZEND_END_ARG_INFO()');
$headerPrinter->outputBlankLine();
}
/** Generate FE's */
$paramData = count($parameters) ? $argInfoName : 'NULL';
if ($func->isGlobal()) {
$entryPrinter->output('ZEND_NAMED_FE(' . $func->getName() . ', ZEND_FN(' . $funcName . '), ' . $paramData . ')');
} else {
$entryPrinter->output('ZEND_NS_NAMED_FE("' . str_replace('\\', '\\\\', $func->getNamespace()) . '", ' . $func->getName() . ', ZEND_FN(' . $funcName . '), ' . $paramData . ')');
}
}
$entryPrinter->output('ZEND_FE_END');
return array($headerPrinter->getOutput(), $entryPrinter->getOutput());
}
作者:zhao590
项目:zephi
/**
* Tries to find specific an specialized optimizer for function calls
*
* @param string $funcName
* @param array $expression
* @param Call $call
* @param CompilationContext $compilationContext
*/
protected function optimize($funcName, array $expression, Call $call, CompilationContext $compilationContext)
{
$optimizer = false;
/**
* Check if the optimizer is already cached
*/
if (!isset(self::$_optimizers[$funcName])) {
$camelizeFunctionName = Utils::camelize($funcName);
/**
* Check every optimizer directory for an optimizer
*/
foreach (self::$_optimizerDirectories as $directory) {
$path = $directory . DIRECTORY_SEPARATOR . $camelizeFunctionName . 'Optimizer.php';
if (file_exists($path)) {
require_once $path;
$className = 'Zephir\\Optimizers\\FunctionCall\\' . $camelizeFunctionName . 'Optimizer';
if (!class_exists($className, false)) {
throw new \Exception('Class ' . $className . ' cannot be loaded');
}
$optimizer = new $className();
if (!$optimizer instanceof OptimizerAbstract) {
throw new \Exception('Class ' . $className . ' must be instance of OptimizerAbstract');
}
break;
}
}
self::$_optimizers[$funcName] = $optimizer;
} else {
$optimizer = self::$_optimizers[$funcName];
}
if ($optimizer) {
return $optimizer->optimize($expression, $call, $compilationContext);
}
return false;
}
作者:WalterSh
项目:zephi
//.........这里部分代码省略.........
}
break;
default:
throw new CompilerException("Default parameter value type: " . $parameter['default']['type'] . " cannot be assigned to variable(bool)", $parameter);
}
break;
case 'string':
$compilationContext->symbolTable->mustGrownStack(true);
$compilationContext->headersManager->add('kernel/memory');
switch ($parameter['default']['type']) {
case 'static-constant-access':
/**
* Now I can write code for easy use on Expression because code in this method don't write with codePrinter ;(
* @todo Rewrite all to codePrinter
*/
$symbolVariable = $compilationContext->symbolTable->getVariableForWrite($parameter['name'], $compilationContext, $parameter['default']);
$expression = new Expression($parameter['default']);
$expression->setExpectReturn(true, $symbolVariable);
$compiledExpression = $expression->compile($compilationContext);
if ($compiledExpression->getType() != 'string') {
throw new CompilerException("Default parameter value type: " . $compiledExpression->getType() . " cannot be assigned to variable(string)", $parameter);
}
$parameter['default']['type'] = $compiledExpression->getType();
$parameter['default']['value'] = $compiledExpression->getCode();
$compilationContext->codePrinter = $oldCodePrinter;
return $this->assignDefaultValue($parameter, $compilationContext);
break;
case 'null':
$compilationContext->backend->initVar($paramVariable, $compilationContext);
$compilationContext->backend->assignString($paramVariable, null, $compilationContext);
break;
case 'string':
$compilationContext->backend->initVar($paramVariable, $compilationContext);
$compilationContext->backend->assignString($paramVariable, Utils::addSlashes($parameter['default']['value'], true), $compilationContext);
break;
default:
throw new CompilerException("Default parameter value type: " . $parameter['default']['type'] . " cannot be assigned to variable(string)", $parameter);
}
break;
case 'array':
$compilationContext->symbolTable->mustGrownStack(true);
$compilationContext->headersManager->add('kernel/memory');
switch ($parameter['default']['type']) {
case 'null':
$compilationContext->backend->initVar($paramVariable, $compilationContext);
$compilationContext->backend->initArray($paramVariable, $compilationContext, null);
break;
case 'empty-array':
case 'array':
$compilationContext->backend->initVar($paramVariable, $compilationContext);
$compilationContext->backend->initArray($paramVariable, $compilationContext, null);
break;
default:
throw new CompilerException("Default parameter value type: " . $parameter['default']['type'] . " cannot be assigned to variable(array)", $parameter);
}
break;
case 'variable':
$symbolVariable = $compilationContext->symbolTable->getVariableForWrite($parameter['name'], $compilationContext, $parameter['default']);
switch ($parameter['default']['type']) {
case 'static-constant-access':
/**
* Now I can write code for easy use on Expression because code in this method don't write with codePrinter ;(
* @todo Rewrite all to codePrinter
*/
$expression = new Expression($parameter['default']);
$expression->setExpectReturn(true, $symbolVariable);
作者:chet0xhenr
项目:zephi
/**
* Throws an exception escaping the data
*
* @param CodePrinter $printer
* @param string $class
* @param string $message
* @param array $expression
*/
private function throwStringException(CodePrinter $printer, $class, $message, $expression)
{
$message = Utils::addSlashes($message);
$path = Compiler::getShortUserPath($expression['file']);
$printer->output(sprintf('ZEPHIR_THROW_EXCEPTION_DEBUG_STR(%s, "%s", "%s", %s);', $class, $message, $path, $expression['line']));
$printer->output('return;');
}
作者:edi
项目:zephi
/**
* Resolve parameters using zvals in the stack and without allocating memory for constants
*
* @param array $parameters
* @param CompilationContext $compilationContext
* @param array $expression
* @return array
*/
public function getReadOnlyResolvedParams($parameters, CompilationContext $compilationContext, array $expression)
{
$codePrinter = $compilationContext->codePrinter;
$exprParams = $this->getResolvedParamsAsExpr($parameters, $compilationContext, $expression, true);
$params = array();
$types = array();
$dynamicTypes = array();
foreach ($exprParams as $compiledExpression) {
$expression = $compiledExpression->getOriginal();
switch ($compiledExpression->getType()) {
case 'null':
$params[] = 'ZEPHIR_GLOBAL(global_null)';
$types[] = 'null';
$dynamicTypes[] = 'null';
break;
case 'int':
case 'uint':
case 'long':
$parameterVariable = $compilationContext->symbolTable->getTempLocalVariableForWrite('variable', $compilationContext, $expression);
$codePrinter->output('ZVAL_LONG(&' . $parameterVariable->getName() . ', ' . $compiledExpression->getCode() . ');');
$this->_temporalVariables[] = $parameterVariable;
$params[] = '&' . $parameterVariable->getName();
$types[] = $parameterVariable->getType();
$dynamicTypes[] = $parameterVariable->getType();
break;
case 'char':
case 'uchar':
$parameterVariable = $compilationContext->symbolTable->getTempLocalVariableForWrite('variable', $compilationContext, $expression);
$codePrinter->output('ZVAL_LONG(&' . $parameterVariable->getName() . ', \'' . $compiledExpression->getCode() . '\');');
$this->_temporalVariables[] = $parameterVariable;
$params[] = '&' . $parameterVariable->getName();
$types[] = $parameterVariable->getType();
$dynamicTypes[] = $parameterVariable->getType();
break;
case 'double':
$parameterVariable = $compilationContext->symbolTable->getTempLocalVariableForWrite('variable', $compilationContext, $expression);
$codePrinter->output('ZVAL_DOUBLE(&' . $parameterVariable->getName() . ', ' . $compiledExpression->getCode() . ');');
$this->_temporalVariables[] = $parameterVariable;
$params[] = '&' . $parameterVariable->getName();
$types[] = $parameterVariable->getType();
$dynamicTypes[] = $parameterVariable->getType();
break;
case 'bool':
if ($compiledExpression->getCode() == 'true') {
$params[] = 'ZEPHIR_GLOBAL(global_true)';
} else {
if ($compiledExpression->getCode() == 'false') {
$params[] = 'ZEPHIR_GLOBAL(global_false)';
} else {
throw new Exception('?');
}
}
$types[] = 'bool';
$dynamicTypes[] = 'bool';
break;
case 'ulong':
case 'string':
case 'istring':
$parameterVariable = $compilationContext->symbolTable->getTempLocalVariableForWrite('variable', $compilationContext, $expression);
$codePrinter->output('ZVAL_STRING(&' . $parameterVariable->getName() . ', "' . Utils::addSlashes($compiledExpression->getCode()) . '", 0);');
$this->_temporalVariables[] = $parameterVariable;
$params[] = '&' . $parameterVariable->getName();
$types[] = $parameterVariable->getType();
$dynamicTypes[] = $parameterVariable->getType();
break;
case 'array':
$parameterVariable = $compilationContext->symbolTable->getVariableForRead($compiledExpression->getCode(), $compilationContext, $expression);
$params[] = $parameterVariable->getName();
$types[] = $parameterVariable->getType();
$dynamicTypes[] = $parameterVariable->getType();
break;
case 'variable':
$parameterVariable = $compilationContext->symbolTable->getVariableForRead($compiledExpression->getCode(), $compilationContext, $expression);
switch ($parameterVariable->getType()) {
case 'int':
case 'uint':
case 'long':
case 'ulong':
$parameterTempVariable = $compilationContext->symbolTable->getTempLocalVariableForWrite('variable', $compilationContext, $expression);
$codePrinter->output('ZVAL_LONG(&' . $parameterTempVariable->getName() . ', ' . $compiledExpression->getCode() . ');');
$params[] = '&' . $parameterTempVariable->getName();
$types[] = $parameterVariable->getType();
$dynamicTypes[] = $parameterVariable->getType();
$this->_temporalVariables[] = $parameterTempVariable;
break;
case 'char':
case 'uchar':
$parameterTempVariable = $compilationContext->symbolTable->getTempLocalVariableForWrite('variable', $compilationContext, $expression);
$codePrinter->output('ZVAL_LONG(&' . $parameterTempVariable->getName() . ', ' . $compiledExpression->getCode() . ');');
$params[] = '&' . $parameterTempVariable->getName();
$types[] = $parameterVariable->getType();
$dynamicTypes[] = $parameterVariable->getType();
//.........这里部分代码省略.........
作者:chet0xhenr
项目:zephi
/**
* Resolves the access to a property in an object
*
* @param array $expression
* @param CompilationContext $compilationContext
* @return \CompiledExpression
*/
public function compile($expression, CompilationContext $compilationContext)
{
$codePrinter = $compilationContext->codePrinter;
$propertyAccess = $expression;
$expr = new Expression($propertyAccess['left']);
$exprVariable = $expr->compile($compilationContext);
switch ($exprVariable->getType()) {
case 'variable':
$variableVariable = $compilationContext->symbolTable->getVariableForRead($exprVariable->getCode(), $compilationContext, $expression);
switch ($variableVariable->getType()) {
case 'variable':
break;
default:
throw new CompilerException("Variable type: " . $variableVariable->getType() . " cannot be used as object", $propertyAccess['left']);
}
break;
default:
throw new CompilerException("Cannot use expression: " . $exprVariable->getType() . " as an object", $propertyAccess['left']);
}
switch ($propertyAccess['right']['type']) {
case 'variable':
$propertyVariable = $compilationContext->symbolTable->getVariableForRead($propertyAccess['right']['value'], $compilationContext, $expression);
break;
case 'string':
$propertyVariable = null;
break;
default:
throw new CompilerException("Variable type: " . $propertyAccess['right']['type'] . " cannot be used as object", $propertyAccess['left']);
}
/**
* Resolves the symbol that expects the value
*/
if ($this->_expecting) {
if ($this->_expectingVariable) {
$symbolVariable = $this->_expectingVariable;
if ($symbolVariable->getName() != 'return_value') {
$symbolVariable->observeVariant($compilationContext);
} else {
$symbolVariable = $compilationContext->symbolTable->getTempVariableForObserve('variable', $compilationContext, $expression);
}
} else {
$symbolVariable = $compilationContext->symbolTable->getTempVariableForObserve('variable', $compilationContext, $expression);
}
}
/**
* Variable that receives a property value must be polymorphic
*/
if ($symbolVariable && !$symbolVariable->isVariable()) {
throw new CompilerException("Cannot use variable: " . $symbolVariable->getType() . " to assign property value", $expression);
}
/**
* At this point, we don't know the exact dynamic type fetched from the property
*/
$symbolVariable->setDynamicTypes('undefined');
$compilationContext->headersManager->add('kernel/object');
$property = $propertyVariable ? $propertyVariable : Utils::addSlashes($expression['right']['value']);
$compilationContext->backend->fetchProperty($symbolVariable, $variableVariable, $property, false, $compilationContext, false);
return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
}
作者:NumbDa
项目:zephi
/**
* @param CompilationContext $compilationContext
* @throws CompilerException
*/
public function compile(CompilationContext $compilationContext)
{
foreach ($this->_statement['expressions'] as $echoExpr) {
$expr = new Expression($echoExpr);
$expr->setReadOnly(true);
$resolvedExpr = $expr->compile($compilationContext);
switch ($resolvedExpr->getType()) {
case 'int':
$compilationContext->codePrinter->output('php_printf("%d", ' . $resolvedExpr->getCode() . ');');
break;
case 'bool':
$compilationContext->codePrinter->output('php_printf("%s", ' . $resolvedExpr->getBooleanCode() . ' ? "1": "");');
break;
case 'double':
$compilationContext->codePrinter->output('php_printf("%f", ' . $resolvedExpr->getCode() . ');');
break;
case 'char':
case 'uchar':
$compilationContext->codePrinter->output('php_printf("%c", \'' . $resolvedExpr->getCode() . '\');');
break;
case 'long':
$compilationContext->codePrinter->output('php_printf("%ld", ' . $resolvedExpr->getCode() . ');');
break;
case 'string':
$compilationContext->codePrinter->output('php_printf("' . Utils::addSlashes($resolvedExpr->getCode()) . '");');
break;
case 'null':
break;
case 'variable':
$variable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $echoExpr);
switch ($variable->getType()) {
case 'int':
$compilationContext->codePrinter->output('php_printf("%d", ' . $variable->getName() . ');');
break;
case 'long':
$compilationContext->codePrinter->output('php_printf("%ld", ' . $variable->getName() . ');');
break;
case 'double':
$compilationContext->codePrinter->output('php_printf("%f", ' . $variable->getName() . ');');
break;
case 'uchar':
case 'char':
$compilationContext->codePrinter->output('php_printf("%c", ' . $variable->getName() . ');');
break;
case 'bool':
$compilationContext->codePrinter->output('php_printf("%s", ' . $variable->getName() . ' ? "1": "");');
break;
case 'string':
case 'variable':
$compilationContext->codePrinter->output('zend_print_zval(' . $variable->getName() . ', 0);');
break;
case 'null':
break;
default:
throw new CompilerException("Unknown type: " . $variable->getType(), $echoExpr);
}
break;
default:
throw new CompilerException("Unknown type: " . $resolvedExpr->getType(), $echoExpr);
}
}
}
作者:chet0xhenr
项目:zephi
//.........这里部分代码省略.........
$sparams = array();
$lparams = array();
for ($i = 0; $i < $len; $i++) {
$n = $i + 1;
$t = substr($key, $i, 1);
$sparams[] = 'op' . $n;
if ($t == 's') {
$params[] = 'const char *op' . $n . ', zend_uint op' . $n . '_len';
$lparams[] = 'op' . $n . ', sizeof(op' . $n . ')-1';
$lengths[] = 'op' . $n . '_len';
$svars[] = $n;
$avars[$n] = 's';
} else {
$params[] = 'zval *op' . $n;
$lparams[] = 'op' . $n;
$zvalCopy[] = 'op' . $n . '_copy';
$useCopy[] = 'use_copy' . $n . ' = 0';
$lengths[] = 'Z_STRLEN_P(op' . $n . ')';
$zvars[] = $n;
$avars[$n] = 'v';
}
}
$macros[] = '#define ZEPHIR_CONCAT_' . strtoupper($key) . '(result, ' . join(', ', $sparams) . ') \\' . PHP_EOL . "\t" . ' zephir_concat_' . $key . '(result, ' . join(', ', $lparams) . ', 0);';
$macros[] = '#define ZEPHIR_SCONCAT_' . strtoupper($key) . '(result, ' . join(', ', $sparams) . ') \\' . PHP_EOL . "\t" . ' zephir_concat_' . $key . '(result, ' . join(', ', $lparams) . ', 1);';
$macros[] = '';
$proto = 'void zephir_concat_' . $key . '(zval *result, ' . join(', ', $params) . ', int self_var)';
$proto = 'void zephir_concat_' . $key . '(zval *result, ' . join(', ', $params) . ', int self_var)';
$codeh .= '' . $proto . ';' . PHP_EOL;
$code .= $proto . '{' . PHP_EOL . PHP_EOL;
if (count($zvalCopy)) {
$code .= "\t" . 'zval result_copy, ' . join(', ', $zvalCopy) . ';' . PHP_EOL;
$code .= "\t" . 'int use_copy = 0, ' . join(', ', $useCopy) . ';' . PHP_EOL;
} else {
$code .= "\t" . 'zval result_copy;' . PHP_EOL;
$code .= "\t" . 'int use_copy = 0;' . PHP_EOL;
}
$code .= "\t" . 'uint offset = 0, length;' . PHP_EOL . PHP_EOL;
foreach ($zvars as $zvar) {
$code .= "\t" . 'if (Z_TYPE_P(op' . $zvar . ') != IS_STRING) {' . PHP_EOL;
$code .= "\t" . ' use_copy' . $zvar . ' = zend_make_printable_zval(op' . $zvar . ', &op' . $zvar . '_copy);' . PHP_EOL;
$code .= "\t" . ' if (use_copy' . $zvar . ') {' . PHP_EOL;
$code .= "\t" . ' op' . $zvar . ' = &op' . $zvar . '_copy;' . PHP_EOL;
$code .= "\t" . ' }' . PHP_EOL;
$code .= "\t" . '}' . PHP_EOL . PHP_EOL;
}
$code .= "\t" . 'length = ' . join(' + ', $lengths) . ';' . PHP_EOL;
$code .= "\t" . 'if (self_var) {' . PHP_EOL;
$code .= '' . PHP_EOL;
$code .= "\t\t" . 'if (Z_TYPE_P(result) != IS_STRING) {' . PHP_EOL;
$code .= "\t\t\t" . 'use_copy = zend_make_printable_zval(result, &result_copy);' . PHP_EOL;
$code .= "\t\t\t" . 'if (use_copy) {' . PHP_EOL;
$code .= "\t\t\t\t" . 'ZEPHIR_CPY_WRT_CTOR(result, (&result_copy));' . PHP_EOL;
$code .= "\t\t\t" . '}' . PHP_EOL;
$code .= "\t\t" . '}' . PHP_EOL . PHP_EOL;
$code .= "\t\t" . 'offset = Z_STRLEN_P(result);' . PHP_EOL;
$code .= "\t\t" . 'length += offset;' . PHP_EOL;
$code .= "\t\t" . 'Z_STR_P(result) = zend_string_realloc(Z_STR_P(result), length, 0);' . PHP_EOL;
$code .= '' . PHP_EOL;
$code .= "\t" . '} else {' . PHP_EOL;
$code .= "\t\t" . 'ZVAL_STR(result, zend_string_alloc(length, 0));' . PHP_EOL;
$code .= "\t" . '}' . PHP_EOL . PHP_EOL;
$position = '';
foreach ($avars as $n => $type) {
if ($type == 's') {
$code .= "\t" . 'memcpy(Z_STRVAL_P(result) + offset' . $position . ', op' . $n . ', op' . $n . '_len);' . PHP_EOL;
$position .= ' + op' . $n . '_len';
} else {
$code .= "\t" . 'memcpy(Z_STRVAL_P(result) + offset' . $position . ', Z_STRVAL_P(op' . $n . '), Z_STRLEN_P(op' . $n . '));' . PHP_EOL;
$position .= ' + Z_STRLEN_P(op' . $n . ')';
}
}
$code .= "\t" . 'Z_STRVAL_P(result)[length] = 0;' . PHP_EOL;
$code .= "\t" . 'zend_string_forget_hash_val(Z_STR_P(result));' . PHP_EOL;
foreach ($zvars as $zvar) {
$code .= "\t" . 'if (use_copy' . $zvar . ') {' . PHP_EOL;
$code .= "\t" . ' zval_dtor(op' . $zvar . ');' . PHP_EOL;
$code .= "\t" . '}' . PHP_EOL . PHP_EOL;
}
$code .= "\t" . 'if (use_copy) {' . PHP_EOL;
$code .= "\t" . ' zval_dtor(&result_copy);' . PHP_EOL;
$code .= "\t" . '}' . PHP_EOL . PHP_EOL;
$code .= "}" . PHP_EOL . PHP_EOL;
}
$code .= <<<EOF
void zephir_concat_function(zval *result, zval *op1, zval *op2) /* {{{ */
{
zval tmp;
/* Force separate zval, if op2=result will be reallocated */
if (unlikely(result == op2)) {
ZVAL_COPY_VALUE(&tmp, op2);
op2 = &tmp;
}
concat_function(result, op1, op2 TSRMLS_CC);
}
EOF;
$codeh .= "void zephir_concat_function(zval *result, zval *op1, zval *op2);\n#endif /* ZEPHIR_KERNEL_CONCAT_H */\n";
Utils::checkAndWriteIfNeeded($pcodeh . join(PHP_EOL, $macros) . PHP_EOL . PHP_EOL . $codeh, 'ext/kernel/concat.h');
Utils::checkAndWriteIfNeeded($code, 'ext/kernel/concat.c');
}
作者:NumbDa
项目:zephi
/**
* Compiles foo[] = {expr}
*
* @param $variable
* @param ZephirVariable $symbolVariable
* @param CompiledExpression $resolvedExpr
* @param CompilationContext $compilationContext
* @param $statement
* @throws CompilerException
*/
public function assign($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, $statement)
{
if (!$symbolVariable->isInitialized()) {
throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is not initialized", $statement);
}
if ($symbolVariable->isReadOnly()) {
throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is read only", $statement);
}
if ($symbolVariable->isLocalOnly()) {
throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is local only", $statement);
}
if ($symbolVariable->getType() != 'variable') {
throw new CompilerException("Cannot use variable type: '" . $symbolVariable->getType() . "' as array", $statement);
}
if ($symbolVariable->hasDifferentDynamicType(array('undefined', 'array'))) {
$compilationContext->logger->warning('Possible attempt to append elements on a non-array dynamic variable', 'non-array-append', $statement);
}
$codePrinter = $compilationContext->codePrinter;
$compilationContext->headersManager->add('kernel/array');
$type = $symbolVariable->getType();
switch ($type) {
case 'variable':
switch ($resolvedExpr->getType()) {
case 'null':
$codePrinter->output('zephir_array_append(&' . $variable . ', ZEPHIR_GLOBAL(global_null), PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
break;
case 'int':
case 'uint':
case 'long':
$symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
$codePrinter->output('ZVAL_LONG(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
$codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
$symbolVariable->setIdle(true);
break;
case 'double':
$symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
$codePrinter->output('ZVAL_DOUBLE(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
$codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
$symbolVariable->setIdle(true);
break;
case 'bool':
$symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
$codePrinter->output('ZVAL_BOOL(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getBooleanCode() . ');');
$codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
$symbolVariable->setIdle(true);
break;
case 'ulong':
case 'string':
$symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
$codePrinter->output('ZVAL_STRING(' . $symbolVariable->getName() . ', "' . Utils::addSlashes($resolvedExpr->getCode(), true) . '", 1);');
$codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
$symbolVariable->setIdle(true);
break;
case 'array':
$exprVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
$codePrinter->output('zephir_array_append(&' . $variable . ', ' . $exprVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
break;
case 'variable':
$exprVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
switch ($exprVariable->getType()) {
case 'int':
case 'uint':
case 'long':
$symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
$codePrinter->output('ZVAL_LONG(' . $symbolVariable->getName() . ', ' . $exprVariable->getName() . ');');
$codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
$symbolVariable->setIdle(true);
break;
case 'double':
$symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
$codePrinter->output('ZVAL_DOUBLE(' . $symbolVariable->getName() . ', ' . $exprVariable->getName() . ');');
$codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
$symbolVariable->setIdle(true);
break;
case 'bool':
$symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
$codePrinter->output('ZVAL_BOOL(' . $symbolVariable->getName() . ', ' . $exprVariable->getName() . ');');
$codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
$symbolVariable->setIdle(true);
break;
case 'variable':
case 'string':
case 'array':
$codePrinter->output('zephir_array_append(&' . $variable . ', ' . $exprVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
break;
default:
throw new CompilerException("Unknown type " . $exprVariable->getType(), $statement);
}
break;
default:
//.........这里部分代码省略.........
作者:NumbDa
项目:zephi
//.........这里部分代码省略.........
*/
$symbol->setIsInitialized(true, $compilationContext, $parameter);
/**
* Variables with class/type must be objects across the execution
*/
if (isset($parameter['cast'])) {
$symbol->setDynamicTypes('object');
$symbol->setClassTypes($compilationContext->getFullName($parameter['cast']['value']));
$classCastChecks[] = array($symbol, $parameter);
} else {
if (isset($parameter['data-type'])) {
if ($parameter['data-type'] == 'variable') {
$symbol->setDynamicTypes('undefined');
}
} else {
$symbol->setDynamicTypes('undefined');
}
}
}
$compilationContext->codePrinter->increaseLevel();
/**
* Checks that a class-hinted variable meets its declaration
*/
foreach ($classCastChecks as $classCastCheck) {
foreach ($classCastCheck[0]->getClassTypes() as $className) {
/**
* If the parameter is nullable check it must pass the 'instanceof' validation
*/
if (!isset($classCastCheck[1]['default'])) {
$evalExpr = new UnaryOperatorBuilder('not', new BinaryOperatorBuilder('instanceof', new VariableBuilder($classCastCheck[0]->getName()), new VariableBuilder('\\' . $className)));
} else {
$evalExpr = new BinaryOperatorBuilder('and', new BinaryOperatorBuilder('not-equals', new TypeOfOperatorBuilder(new VariableBuilder($classCastCheck[0]->getName())), new LiteralBuilder("string", "null")), new UnaryOperatorBuilder('not', new BinaryOperatorBuilder('instanceof', new VariableBuilder($classCastCheck[0]->getName()), new VariableBuilder('\\' . $className))));
}
$ifCheck = new IfStatementBuilder($evalExpr, new StatementsBlockBuilder(array(new ThrowStatementBuilder(new NewInstanceOperatorBuilder('\\InvalidArgumentException', array(new ParameterBuilder(new LiteralBuilder("string", "Parameter '" . $classCastCheck[0]->getName() . "' must be an instance of '" . Utils::escapeClassName($className) . "'"))))))));
$ifStatement = new IfStatement($ifCheck->get());
$ifStatement->compile($compilationContext);
}
}
$compilationContext->codePrinter->decreaseLevel();
}
/**
* Compile the block of statements if any
*/
if (is_object($this->_statements)) {
if ($this->hasModifier('static')) {
$compilationContext->staticContext = true;
} else {
$compilationContext->staticContext = false;
}
/**
* Compile the statements block as a 'root' branch
*/
$this->_statements->compile($compilationContext, false, Branch::TYPE_ROOT);
}
/**
* Initialize default values in dynamic variables
*/
$initVarCode = "";
foreach ($symbolTable->getVariables() as $variable) {
/**
* Initialize 'dynamic' variables with default values
*/
if ($variable->getType() == 'variable') {
if ($variable->getNumberUses() > 0) {
if ($variable->getName() != 'this_ptr' && $variable->getName() != 'return_value' && $variable->getName() != 'return_value_ptr') {
$defaultValue = $variable->getDefaultInitValue();
作者:Jvbzephi
项目:zephi
/**
* Resolves a PHP constant value into C-code
*
* @param array $expression
* @param CompilationContext $compilationContext
* @return CompiledExpression
* @throws \Zephir\CompilerException
*/
public function compile(array $expression, CompilationContext $compilationContext)
{
$isPhpConstant = false;
$isZephirConstant = false;
$constantName = $expression['value'];
$mergedConstants = array_merge($this->envConstans, $this->magickConstants, $this->resources);
if (!defined($expression['value']) && !in_array($constantName, $mergedConstants)) {
if (!$compilationContext->compiler->isConstant($constantName)) {
$compilationContext->logger->warning("Constant '" . $constantName . "' does not exist at compile time", 'nonexistent-constant', $expression);
} else {
$isZephirConstant = true;
}
} else {
if (strpos($constantName, 'VERSION') !== false) {
$isPhpConstant = false;
} else {
$isPhpConstant = true;
}
}
if ($isZephirConstant && !in_array($constantName, $this->resources)) {
$constant = $compilationContext->compiler->getConstant($constantName);
return new LiteralCompiledExpression($constant[0], $constant[1], $expression);
}
if ($isPhpConstant && !in_array($constantName, $mergedConstants)) {
$constantName = constant($constantName);
$type = strtolower(gettype($constantName));
switch ($type) {
case 'integer':
return new LiteralCompiledExpression('int', $constantName, $expression);
case 'double':
return new LiteralCompiledExpression('double', $constantName, $expression);
case 'string':
return new LiteralCompiledExpression('string', Utils::addSlashes($constantName, true, Types::STRING), $expression);
case 'object':
throw new CompilerException('?');
default:
return new LiteralCompiledExpression($type, $constantName, $expression);
}
}
if (in_array($constantName, $this->magickConstants)) {
switch ($constantName) {
case '__CLASS__':
return new CompiledExpression('string', $compilationContext->classDefinition->getCompleteName(), $expression);
//no break
//no break
case '__NAMESPACE__':
return new CompiledExpression('string', $compilationContext->classDefinition->getNamespace(), $expression);
//no break
//no break
case '__METHOD__':
return new CompiledExpression('string', $compilationContext->classDefinition->getName() . ':' . $compilationContext->currentMethod->getName(), $expression);
//no break
//no break
case '__FUNCTION__':
return new CompiledExpression('string', $compilationContext->currentMethod->getName(), $expression);
//no break
}
$compilationContext->logger->warning("Magic constant '" . $constantName . "' is not supported", 'not-supported-magic-constant', $expression);
return new LiteralCompiledExpression('null', null, $expression);
}
if ($this->_expecting && $this->_expectingVariable) {
$symbolVariable = $this->_expectingVariable;
$symbolVariable->setLocalOnly(false);
$symbolVariable->setMustInitNull(true);
$symbolVariable->initVariant($compilationContext);
} else {
$symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression);
}
if (!$symbolVariable->isVariable()) {
throw new CompilerException('Cannot use variable: ' . $symbolVariable->getType() . ' to assign property value', $expression);
}
$compilationContext->codePrinter->output('ZEPHIR_GET_CONSTANT(' . $symbolVariable->getName() . ', "' . $expression['value'] . '");');
return new CompiledExpression('variable', $symbolVariable->getName(), $expression);
}
作者:chet0xhenr
项目:zephi
/**
* Creates a new instance
*
* @param $expression
* @param CompilationContext $compilationContext
* @return CompiledExpression
* @throws CompilerException
*/
public function compile(array $expression, CompilationContext $compilationContext)
{
$codePrinter = $compilationContext->codePrinter;
/**
* Resolves the symbol that expects the value
*/
$this->_literalOnly = false;
$symbolVariable = $this->getExpectedNonLiteral($compilationContext, $expression);
if (!$symbolVariable->isVariable()) {
throw new CompilerException("Objects can only be instantiated into dynamic variables", $expression);
}
if ($symbolVariable->isLocalOnly()) {
throw new CompilerException("Cannot use non-heap variable to store new instance", $expression);
}
if ($symbolVariable->getName() != 'return_value') {
if ($symbolVariable->hasDifferentDynamicType(array('unknown', 'undefined', 'object', 'null'))) {
$compilationContext->logger->warning('Possible attempt to use non-object in "new" operator', 'non-valid-new', $expression);
}
}
/**
* Mark variables as dynamic objects
*/
$symbolVariable->setDynamicTypes('object');
$dynamic = false;
if ($expression['class'] == 'self' || $expression['class'] == 'static') {
$className = $compilationContext->classDefinition->getCompleteName();
} else {
$className = $expression['class'];
$dynamic = $expression['dynamic'];
if (!$dynamic) {
$className = $compilationContext->getFullName($expression['class']);
}
}
if (!$className) {
throw new CompilerException("A class name is required to instantiate the object", $expression);
}
/**
* stdclass doesn't have constructors
*/
$lowerClassName = strtolower($className);
$isStdClass = $lowerClassName === 'stdclass' || $lowerClassName === '\\stdclass';
if ($isStdClass) {
if (isset($expression['parameters']) && count($expression['parameters']) > 0) {
throw new CompilerException("stdclass does not receive parameters in its constructor", $expression);
}
$compilationContext->backend->initObject($symbolVariable, null, $compilationContext);
$symbolVariable->setClassTypes('stdclass');
} else {
$classDefinition = false;
if ($compilationContext->compiler->isClass($className)) {
$classDefinition = $compilationContext->compiler->getClassDefinition($className);
}
/**
* Classes inside the same extension
*/
if ($classDefinition) {
$compilationContext->backend->initObject($symbolVariable, $classDefinition->getClassEntry($compilationContext), $compilationContext);
$symbolVariable->setClassTypes($className);
$symbolVariable->setAssociatedClass($classDefinition);
} else {
/**
* Classes outside the extension
*/
if ($dynamic) {
$classNameVariable = $compilationContext->symbolTable->getVariableForRead($className, $compilationContext, $expression);
if ($classNameVariable->isNotVariableAndString()) {
throw new CompilerException("Only dynamic/string variables can be used in new operator. " . $classNameVariable->getName(), $expression);
}
/**
* Use a safe string version of the variable to avoid segfaults
*/
$compilationContext->headersManager->add('kernel/object');
$safeSymbolVariable = $compilationContext->symbolTable->getTempVariable('variable', $compilationContext, $expression);
$safeSymbolVariable->setMustInitNull(true);
$safeSymbolVariable->setIsInitialized(true, $compilationContext, $expression);
$safeSymbolVariable->increaseUses();
$compilationContext->codePrinter->output('zephir_fetch_safe_class(' . $safeSymbolVariable->getName() . ', ' . $classNameVariable->getName() . ');');
$safeSymbol = $compilationContext->backend->getVariableCode($safeSymbolVariable);
$classNameToFetch = 'Z_STRVAL_P(' . $safeSymbol . '), Z_STRLEN_P(' . $safeSymbol . ')';
$zendClassEntry = $compilationContext->cacheManager->getClassEntryCache()->get($classNameToFetch, true, $compilationContext);
$classEntry = $zendClassEntry->getName();
} else {
if (!class_exists($className, false)) {
$compilationContext->logger->warning('Class "' . $className . '" does not exist at compile time', "nonexistent-class", $expression);
$classNameToFetch = 'SL("' . Utils::escapeClassName($className) . '")';
$zendClassEntry = $compilationContext->cacheManager->getClassEntryCache()->get($classNameToFetch, false, $compilationContext);
$classEntry = $zendClassEntry->getName();
} else {
$reflectionClass = new \ReflectionClass($className);
if ($reflectionClass->isInterface()) {
throw new CompilerException('Interfaces cannot be instantiated', $expression);
} else {
//.........这里部分代码省略.........