diff --git a/examples/python/sys.php b/examples/python/sys.php deleted file mode 100644 index 295a00a5..00000000 --- a/examples/python/sys.php +++ /dev/null @@ -1,26 +0,0 @@ -full_version); -} - -function main() -{ - var_dump(sys::api_version); - var_dump(os::getpid()); - var_dump(os::environ->get("PATH")); -} - - - -$array["hello"] = $a; -$array["world"] = $b; - -$c = $array["world"]; - - diff --git a/src/Python/Translator.php b/src/Python/Translator.php deleted file mode 100644 index db1af2c9..00000000 --- a/src/Python/Translator.php +++ /dev/null @@ -1,979 +0,0 @@ -keywordsMap = array_flip($this->keywords); - $this->builtinTypes = array_flip($this->builtinTypes); - } - - public function prepare($root) - { - foreach ($root->body as $body) { - if ($body->_type == 'FunctionDef') { - $this->definedFunctions[$body->name] = 1; - } - } - } - - public function getLine($node): int - { - return $node->lineno; - } - - public function getType($node): string - { - return $node->_type; - } - - public function parseAttribute($attr) - { - switch ($attr->_type) { - case 'Name': - return '$' . $attr->id; - case 'Attribute': - return $this->parseAttribute($attr->value) . '->' . $attr->attr; - case 'Constant': - return 'PyCore::str("' . $attr->s . '")'; - case 'Call': - return $this->parseCall($attr); - case 'Subscript': - return $this->parseSubscript($attr); - case 'BinOp': - return $this->parseBinOp($attr); - default: - var_dump(__METHOD__, __LINE__); - abort($attr); - } - } - - public function parseFunc($fn) - { - switch ($fn->_type) { - case 'Name': - $id = $fn->id; - if (isset($this->keywordsMap[$id])) { - return 'PyCore::' . $id; - } elseif (isset($this->definedFunctions[$id])) { - return $id; - } elseif (isset($this->builtinTypes[$id])) { - return '$builtins->' . $id; - } else { - return '$' . $id; - } - // no break - case 'Attribute': - return $this->parseAttribute($fn->value) . '->' . $fn->attr; - default: - abort($fn); - } - } - - public function parseCall($call): string - { - $fn = $this->parseFunc($call->func); - if_empty_debug($fn, $call); - $args = $call->args; - $kwargs = $call->keywords; - - $args_list = []; - - foreach ($args as $arg) { - $args_list[] = $this->parseValue($arg); - } - - foreach ($kwargs as $arg) { - $name = $arg->arg; - $args_list[] = $name . ': ' . $this->parseValue($arg->value); - } - - if (empty($args_list)) { - return "$fn()"; - } else { - return "$fn(" . implode(', ', $args_list) . ")"; - } - } - - public static function valueToRepr($v, $python = false) - { - if (is_string($v)) { - $v = str_replace( - ["\\", "\n", "\r", "\t", "\v", "\x00", "\""], - ["\\\\", "\\n", "\\r", "\\t", "\\v", "\\x00", "\\\""], - $v - ); - return "\"$v\""; - } elseif ($v === []) { - return '[]'; - } elseif (is_numeric($v)) { - if ($python) { - if (is_infinite($v)) { - return "float('inf')"; - } elseif (is_nan($v)) { - return "float('nan')"; - } - } - return strval($v); - } elseif (is_bool($v)) { - return $python ? ($v ? 'True' : 'False') : ($v ? 'true' : 'false'); - } elseif (is_null($v)) { - return $python ? 'None' : 'null'; - } elseif (is_array($v)) { - return var_export($v, true); - } else { - return $python ? 'None' : 'null'; - } - } - - public function parseConstant($value): string - { - return self::valueToRepr($value->value); - } - - public function parseTuple($tuple) - { - $ids = []; - foreach ($tuple->dims as $dim) { - $ids[] = $this->parseTarget($dim); - } - return 'PyCore::tuple([' . implode(', ', $ids) . '])'; - } - - public function parseListComp($listComp) - { - $code = ''; - $this->indentLevel++; - $code .= $this->getIndent() . '$___ = [];' . PHP_EOL; - $recipient = '$___'; - $generators = $this->parseGenerators($listComp->generators, $recipient, $captures); - $code .= $this->getIndent() . $generators; - $code .= $this->getIndent() . 'return $___;' . PHP_EOL; - $this->indentLevel--; - $code .= $this->getIndent() . '})(' . implode(',', $captures) . ')'; - return '(function(' . implode(',', $captures) . ') {' . PHP_EOL . $code; - } - - public function parseValue($value) - { - switch ($value->_type) { - case 'Call': - return $this->parseCall($value); - case 'Constant': - return $this->parseConstant($value); - case 'Attribute': - return $this->parseAttribute($value); - case 'Name': - return $this->parseName($value); - case 'List': - return $this->parseList($value); - case 'Dict': - return $this->parseDict($value); - case 'Set': - return $this->parseSet($value); - case 'Tuple': - return $this->parseTuple($value); - case 'ListComp': - return $this->parseListComp($value); - case 'DictComp': - return $this->parseDictComp($value); - case 'BinOp': - return $this->parseBinOp($value); - case 'JoinedStr': - return $this->parseJoinedStr($value); - case 'Subscript': - return $this->parseSubscript($value); - case 'FormattedValue': - return $this->parseFormattedValue($value); - case 'UnaryOp': - return $this->parseTarget($value); - case 'BoolOp': - return $this->parseBoolOp($value); - case 'Compare': - return $this->parseTest($value); - case 'IfExp': - return $this->parseIfExp($value); - case 'Yield': - return $this->parseYield($value); - case 'Lambda': - return $this->parseLambda($value); - case 'GeneratorExp': - return $this->parseGeneratorExp($value); - default: - abort($value); - break; - } - } - - public function parseSlice($slice): string - { - if ($slice->_type == 'Constant') { - return $this->parseConstant($slice); - } elseif ($slice->_type === 'Tuple') { - return $this->parseTuple($slice); - } elseif ($slice->_type === 'Slice') { - $_args[] = $slice->lower ? $this->parseTarget($slice->lower) : 'null'; - $_args[] = $slice->upper ? $this->parseTarget($slice->upper) : 'null'; - $_args[] = $slice->step ? $this->parseTarget($slice->step) : 'null'; - return 'PyCore::slice(' . implode(', ', $_args) . ')'; - } else { - abort($slice); - } - } - - public function parseImportFrom($node): string - { - $module = $node->module; - $imports = []; - foreach ($node->names as $name) { - $type = $name->name; - $as = empty($name->asname) ? $type : $name->asname; - $imports[] = "\$$as = PyCore::import('$module')->$type"; - } - - return implode(';' . PHP_EOL, $imports); - } - - public function parseImport($node): string - { - $out = ''; - foreach ($node->names as $name) { - $module = $name->name; - $as = empty($name->asname) ? $module : $name->asname; - $out .= $this->getIndent() . "\$$as = PyCore::import('$module');\n"; - } - return $out; - } - - public function parseTarget($target) - { - switch ($target->_type) { - case 'Name': - return '$' . $target->id; - case 'UnaryOp': - $operand = $this->parseTarget($target->operand); - switch ($target->op->_type) { - case 'USub': - return '-' . $operand; - case 'Not': - return '!' . $operand; - default: - abort($target); - break; - } - break; - case 'Tuple': - return $this->parseTuple($target); - case 'Subscript': - return $this->parseSubscript($target); - case 'IfExp': - return $this->parseIfExp($target); - case 'Attribute': - return $this->parseAttribute($target); - case 'Constant': - return $this->parseConstant($target); - case 'List': - return $this->parseList($target); - case 'Set': - return $this->parseSet($target); - case 'Call': - return $this->parseCall($target); - case 'BinOp': - return $this->parseBinOp($target); - case 'Compare': - return $this->parseTest($target); - case 'Slice': - return $this->parseSlice($target); - case 'BoolOp': - return $this->parseBoolOp($target); - case 'ListComp': - return $this->parseListComp($target); - default: - abort($target); - break; - } - } - - public function parseIfExp($exp) - { - $test = $this->parseTest($exp->test); - $orelse = $this->parseValue($exp->orelse); - $body = $this->parseValue($exp->body); - return $test . ' ? ' . $body . ' : ' . $orelse; - } - - public function parseExpr($node) - { - switch ($node->_type) { - case 'Expr': - if (is_string($node->value->value)) { - return '/** ' . $node->value->value . ' */' . PHP_EOL; - } else { - return $this->parseValue($node->value) . ';'; - } - // no break - default: - return $this->parseValue($node->value) . ';'; - } - } - - public function parseArguments($args): string - { - $defaults = $args->defaults ?? []; - $names = []; - foreach ($args->args as $k => $arg) { - $tmp = '$' . $arg->arg; - if ($k >= count($args->args) - count($defaults)) { - $tmp .= ' = ' . $this->parseValue($defaults[$k - count($args->args) + count($defaults)]); - } - $names[] = $tmp; - } - if ($args->vararg) { - $names[] = '...$' . $args->vararg->arg; - } - return implode(', ', $names); - } - - public function parseReturn($node) - { - return 'return ' . $this->parseValue($node->value); - } - - public function parseTest($test) - { - $comparator = null; - $left = $test->left ? $this->parseValue($test->left) : ''; - if ($test->ops) { - $ops = $test->ops; - if (count($ops) != 1) { - abort($test); - } - $op = $ops[0]->_type; - $comparators = $test->comparators; - $comparator = $comparators[0]; - } elseif ($test->op) { - $op = $test->op->_type; - } else { - $op = ''; - } - - switch ($op) { - case 'Is': - case 'Eq': - return $left . ' == ' . $this->parseValue($comparator); - case 'NotEq': - return $left . ' != ' . $this->parseValue($comparator); - case 'In': - return $this->parseValue($comparator) . '->__contains__(' . $left . ')'; - case 'NotIn': - return '!' . $this->parseValue($comparator) . '->__contains__(' . $left . ')'; - case 'Gt': - return $left . ' > ' . $this->parseValue($comparator); - case 'Lt': - return $left . ' < ' . $this->parseValue($comparator); - case 'GtE': - return $left . ' >= ' . $this->parseValue($comparator); - case 'LtE': - return $left . ' <= ' . $this->parseValue($comparator); - case 'Not': - return '!' . $this->parseValue($test->operand); - case 'Or': - return $this->parseOr($test->values); - case 'And': - return $this->parseAnd($test->values); - default: - return $this->parseTarget($test); - } - } - - public function parseIf($node) - { - $expr = $this->parseTest($node->test); - $this->indentLevel++; - $body = $this->parseBody($node->body); - $orelse = empty($node->orelse) ? '' : $this->parseBody($node->orelse); - $this->indentLevel--; - return 'if (' . $expr . ') {' . - PHP_EOL . $body . - PHP_EOL . $this->getIndent() . '}' . - ($orelse ? ' else {' . PHP_EOL . $orelse . PHP_EOL . $this->getIndent() . '}' : '') . - PHP_EOL; - } - - public function parseIter($iter) - { - switch ($iter->_type) { - case 'Call': - return $this->parseCall($iter); - case 'List': - return $this->parseList($iter); - case 'Set': - return $this->parseSet($iter); - case 'Dict': - return $this->parseDict($iter); - case 'Name': - return $this->parseName($iter); - case 'Subscript': - return $this->parseSubscript($iter); - case 'Attribute': - return $this->parseAttribute($iter); - default: - abort($iter); - } - } - - public function parseSubscript($node) - { - if ($node->slice) { - $op = $node->ctx->_type; - $value = $this->parseValue($node->value); - if ($node->ctx->_type == 'Store') { - return $value. '[' . $this->parseSlice($node->slice) . '] = $__value'; - } elseif ($op == 'Del') { - return 'unset(' . $value . '[' . $this->parseSlice($node->slice) . '])'; - } else { - return $value . '[' . $this->parseSlice($node->slice) . ']'; - } - } else { - abort($node); - } - } - - public function parseFor($node) - { - $target = $this->parseTarget($node->target); - $iter = $this->parseIter($node->iter); - - $code = '$__iter = PyCore::iter(' . $iter . ');' . PHP_EOL; - $code .= $this->getIndent() . 'while($current = PyCore::next($__iter)) {' . PHP_EOL; - - $this->indentLevel++; - $code .= $this->getIndent() . $target . ' = $current;' . PHP_EOL; - $code .= $this->parseBody($node->body); - $this->indentLevel--; - - return $code . $this->getIndent() . PHP_EOL . $this->getIndent() . '}'; - } - - public function parseFunctionDef($node) - { - $name = $node->name; - $args = $this->parseArguments($node->args); - $fn = PHP_EOL . $this->getIndent() . 'function ' . $name . '(' . $args . ') {' . PHP_EOL; - $this->indentLevel++; - $fn .= $this->parseBody($node->body) . PHP_EOL; - ; - $this->indentLevel--; - $fn .= $this->getIndent() . '}' . PHP_EOL . PHP_EOL; - - return $fn; - } - - private function addLine($line, array &$lines) - { - if ($this->mode == 'cli' && STEP) { - echo $line . PHP_EOL; - } - $lines[] = $line; - } - - private function parseLine($node, &$lines) - { - switch ($node->_type) { - case 'ImportFrom': - $line = $this->parseImportFrom($node) . ';'; - break; - case 'Assign': - $target = $this->parseTarget($node->targets[0]); - $value = $this->parseValue($node->value); - if ($node->targets[0]->_type == 'Subscript') { - $this->addLine('$__value = ' . $value . ';', $lines); - $line = "$target;"; - } else { - $line = "$target = $value;"; - } - break; - case 'AugAssign': - $line = $this->parseAugAssign($node); - break; - case 'Import': - $line = $this->parseImport($node); - break; - case 'Expr': - $line = $this->parseExpr($node); - break; - case 'FunctionDef': - $line = $this->parseFunctionDef($node); - break; - case 'Return': - $line = $this->parseReturn($node) . ';'; - break; - case 'If': - $line = $this->parseIf($node); - break; - case 'For': - $line = $this->parseFor($node); - break; - case 'While': - $line = $this->parseWhile($node); - break; - case 'Try': - $line = $this->parseTry($node); - break; - case 'Raise': - $line = $this->parseRaise($node) . ';'; - break; - case 'Subscript': - $line = $this->parseSubscript($node) . ';'; - break; - case 'With': - $line = $this->parseWith($node); - break; - case 'Compare': - $line = $this->parseTest($node); - break; - case 'Delete': - $line = $this->parseDelete($node); - break; - case 'Continue': - $line = $this->parseContinue($node) . ';'; - break; - case 'Break': - $line = $this->parseBreak($node) . ';'; - break; - case 'Global': - $line = $this->parseGlobal($node) . ';'; - break; - case 'Pass': - $line = $this->parsePass($node) . ';'; - break; - case 'BinOp': - $line = $this->parseBinOp($node) . ';'; - break; - case 'IfExp': - $line = $this->parseIfExp($node) . ';'; - break; - case 'Tuple': - $line = $this->parseTuple($node) . ';'; - break; - case 'Lambda': - $line = $this->parseLambda($node) . ';'; - break; - case 'Call': - $line = $this->parseCall($node) . ';'; - break; - default: - abort($node); - $line = ''; - break; - } - $this->addLine($line, $lines); - } - - public function parseBody($tree): string - { - $lines = []; - foreach ($tree as $node) { - $this->parseLine($node, $lines); - } - foreach ($lines as &$line) { - $line = $this->getIndent() . $line; - } - return implode(PHP_EOL, $lines); - } - - public function convert($tree): void - { - $this->prepare($tree); - $output = 'parseBody($tree->body); - echo $output; - echo PHP_EOL; - } - - private function parseGenerators($generators, $recipient, &$captures) - { - $captures = []; - $code = ''; - - foreach ($generators as $k => $generator) { - $target = $this->parseTarget($generator->target); - if ($generator->iter->_type == 'Name') { - $name = '$' . $generator->iter->id; - $captures[] = $name; - } else { - $name = '$___iter'; - $code .= $this->getIndent() . '$___iter = ' . $this->parseIter($generator->iter) . ';' . PHP_EOL; - } - $code .= $this->getIndent() . 'foreach(' . $name . ' as $___i => ' . $target . ') {' . PHP_EOL; - $this->indentLevel++; - if (count($generators) === 1) { - $code .= $this->getIndent() . $recipient . '[] = ' . $target . ';' . PHP_EOL; - } else { - $code .= $this->getIndent() . $recipient . '[$___i][' . $k . '] = ' . $target . ';' . PHP_EOL; - } - $this->indentLevel--; - $code .= $this->getIndent() . '}' . PHP_EOL; - } - return $code; - } - - private function parseOp($op) - { - switch ($op) { - case 'Mod': - return '%'; - case 'Add': - return '+'; - case 'Sub': - return '-'; - case 'Mult': - return '*'; - case 'Div': - return '/'; - default: - return false; - } - } - - private function parseAugAssign($value): string - { - $op = $value->op->_type; - $left = $this->parseTarget($value->target); - $right = $this->parseValue($value->value); - $op_str = $this->parseOp($op); - if ($op_str) { - return $left . ' ' . $op_str . '= ' . $right . ';'; - } else { - return $left . ' = $operator->' . strtolower($op) . '(' . $left . ' , ' . $right . ');'; - } - } - - private function parseBinOp($value) - { - $op = $value->op->_type; - $left = $this->parseTarget($value->left); - $right = $this->parseValue($value->right); - $op_str = $this->parseOp($op); - if ($op_str) { - return $left . ' ' . $op_str . ' ' . $right; - } else { - return '$operator->' . strtolower($op) . '(' . $left . ' , ' . $right . ')'; - } - } - - private function parseJoinedStr($value) - { - $list = []; - foreach ($value->values as $v) { - $list[] = $this->parseValue($v); - } - return implode(' . ', $list); - } - - private function parseList($target) - { - $values = []; - foreach ($target->elts as $e) { - $values[] = $this->parseValue($e); - } - return 'new PyList([' . implode(', ', $values) . '])'; - } - - private function parseYield($value) - { - return 'yield ' . $this->parseValue($value->value) . ';'; - } - - private function parseWith(mixed $node): string - { - $items = $node->items; - $body = $node->body; - $code = ''; - $finally_code = ''; - - $parseItem = function ($call, $target) use (&$code, &$finally_code) { - $call = $this->parseCall($call); - $target = empty($target) ? '$__' : $this->parseTarget($target); - $code .= $target . '__object = ' . $call . ';' . PHP_EOL; - ; - $code .= $target . ' = ' . $target . '__object->__enter__();' . PHP_EOL; - $this->indentLevel++; - $finally_code .= $this->getIndent() . $target . '__object->__exit__(null, null, null);' . PHP_EOL; - $this->indentLevel--; - }; - - foreach ($items as $k => $item) { - if ($item->context_expr->_type == 'Tuple') { - $context_expr = $item->context_expr->dims; - $optional_vars = $item->optional_vars->dims; - foreach ($context_expr as $k2 => $dim) { - $parseItem($dim, $optional_vars[$k2]); - } - } else { - $parseItem($item->context_expr, $item->optional_vars); - } - } - - $code .= 'try {' . PHP_EOL; - $this->indentLevel++; - $code .= $this->parseBody($body); - $this->indentLevel--; - $code .= PHP_EOL . '} finally {' . PHP_EOL; - $code .= $finally_code; - $code .= '}' . PHP_EOL; - return $code; - } - - private function parseDict($dict) - { - $code = '[' . PHP_EOL; - foreach ($dict->values as $k => $v) { - if (empty($dict->keys[$k])) { - abort($v); - } - $key = $dict->keys[$k]; - $this->indentLevel++; - $code .= $this->getIndent() . $this->parseTarget($key) . ' => ' . $this->parseTarget($v) . ',' . PHP_EOL; - $this->indentLevel--; - } - return 'new PyDict(' . $code . '])'; - } - - - private function parseBoolOp($value) - { - switch ($value->op->_type) { - case 'And': - return $this->parseAnd($value->values); - case 'Or': - return $this->parseOr($value->values); - default: - abort($value); - break; - } - } - - private function parseAnd($values) - { - $targets = []; - foreach ($values as $v) { - $targets[] = $this->parseTarget($v); - } - return implode(' and ', $targets); - } - - private function parseOr($values) - { - $targets = []; - foreach ($values as $v) { - $targets[] = $this->parseTarget($v); - } - return implode(' or ', $targets); - } - - private function parseDelete(mixed $node) - { - $code = ''; - foreach ($node->targets as $target) { - $code .= $this->getIndent() . $this->parseSubscript($target) . ';' . PHP_EOL; - } - return $code; - } - - private function parseSet($target) - { - $values = []; - foreach ($target->elts as $e) { - $values[] = $this->parseValue($e); - } - return 'new PySet([' . implode(', ', $values) . '])'; - } - - private function parseWhile(mixed $node) - { - $test = $this->parseTest($node->test); - $code = 'while(' . $test . ') {' . PHP_EOL; - $this->indentLevel++; - $code .= $this->parseBody($node->body); - $this->indentLevel--; - return $code . $this->getIndent() . PHP_EOL . $this->getIndent() . '}'; - } - - private function parseTry(mixed $node) - { - $code = 'try {' . PHP_EOL; - $this->indentLevel++; - $code .= $this->parseBody($node->body); - $this->indentLevel--; - $code .= PHP_EOL . '}'; - - if ($node->handlers) { - $code .= ' catch(PyError $e) {' . PHP_EOL; - $this->indentLevel++; - foreach ($node->handlers as $k => $handler) { - if ($handler->type->_type == 'Name') { - $id = $handler->type->id; - $type = isset($this->builtinTypes[$id]) ? '$builtins->' . $id : '$' . $id; - } else { - $types = []; - foreach ($handler->type->dims as $dim) { - $id = $dim->id; - $types[] = isset($this->builtinTypes[$id]) ? '$builtins->' . $id : '$' . $id; - } - $type = 'new PyTuple([' . implode(', ', $types) . '])'; - } - $code .= ($k == 0 ? $this->getIndent() . 'if' : ' elseif') . ' (PyCore::isinstance($e, ' . $type . ')) {' . PHP_EOL; - $this->indentLevel++; - $code .= $this->parseBody($node->body); - $this->indentLevel--; - $code .= PHP_EOL . $this->getIndent() . '}'; - } - $code .= ' else {'; - $this->indentLevel++; - $code .= PHP_EOL . $this->getIndent() . 'throw $e;'; - $this->indentLevel--; - $code .= PHP_EOL . $this->getIndent() . '}' . PHP_EOL; - $this->indentLevel--; - $code .= $this->getIndent() . '}'; - } - - if ($node->finalbody) { - $code .= ' finally {' . PHP_EOL; - $this->indentLevel++; - $code .= $this->parseBody($node->finalbody); - $this->indentLevel--; - $code .= PHP_EOL . $this->getIndent() . '}'; - } - - return $code; - } - - private function parseRaise(mixed $node) - { - return 'throw ' . $this->parseCall($node->exc); - } - - private function parseName($value) - { - return '$' . $value->id; - } - - private function parseContinue(mixed $node) - { - return 'continue'; - } - - private function parseBreak(mixed $node) - { - return 'break'; - } - - private function parseGlobal(mixed $node) - { - $names = []; - foreach ($node->names as $name) { - $names[] = '$' . $name; - } - return 'global ' . implode(', ', $names); - } - - private function parsePass(mixed $node) - { - return 'return'; - } - - private function parseLambda($value) - { - $lines = []; - $args = $this->parseArguments($value->args); - $code = 'function (' . $args . ') {' . PHP_EOL; - $this->indentLevel++; - $this->parseLine($value->body, $lines); - $code .= $this->getIndent() . 'return ' . $lines[0] . PHP_EOL; - $this->indentLevel--; - $code .= $this->getIndent() . '}'; - return $code; - } - - private function parseFormattedValue($value) - { - $expr = $this->parseValue($value->value); - if ($value->format_spec and $value->format_spec->_type == 'JoinedStr') { - if (count($value->format_spec->values) != 1) { - abort($value); - } - $format = $value->format_spec->values[0]->value; - if ($format[0] == '.' and $format[-1] == 'f') { - return 'round(' . $expr . ', ' . substr($format, 1, strlen($format) - 2) . ')'; - } elseif (str_contains($format, '%')) { - return $expr . '->strftime("' . $format . '")'; - } else { - throw new \RuntimeException("Unsupported format: $format"); - } - } else { - return $expr; - } - } - - private function parseDictComp($node) - { - $code = ''; - $this->indentLevel++; - $code .= $this->getIndent() . '$___ = [];' . PHP_EOL; - $recipient = '$___'; - $generators = $this->parseGenerators($node->generators, $recipient, $captures); - $code .= $this->getIndent() . $generators; - $code .= $this->getIndent() . 'return $___;' . PHP_EOL; - $this->indentLevel--; - $code .= $this->getIndent() . '})(' . implode(',', $captures) . ')'; - return '(function(' . implode(',', $captures) . ') {' . PHP_EOL . $code; - } - - private function parseGeneratorExp($value) - { - abort($value); - } -}