Mercurial > hg > isophonics-drupal-site
diff vendor/psy/psysh/src/Psy/ExecutionLoop/Loop.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/src/Psy/ExecutionLoop/Loop.php Wed Nov 29 16:09:58 2017 +0000 @@ -0,0 +1,186 @@ +<?php + +/* + * This file is part of Psy Shell. + * + * (c) 2012-2017 Justin Hileman + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Psy\ExecutionLoop; + +use Psy\Configuration; +use Psy\Exception\BreakException; +use Psy\Exception\ErrorException; +use Psy\Exception\ThrowUpException; +use Psy\Exception\TypeErrorException; +use Psy\Shell; + +/** + * The Psy Shell execution loop. + */ +class Loop +{ + const NOOP_INPUT = 'return null;'; + + /** + * Loop constructor. + * + * The non-forking loop doesn't have much use for Configuration, so we'll + * just ignore it. + * + * @param Configuration $config + */ + public function __construct(Configuration $config) + { + // don't need this + } + + /** + * Run the execution loop. + * + * @throws ThrowUpException if thrown by the `throw-up` command + * + * @param Shell $shell + */ + public function run(Shell $shell) + { + $loop = function ($__psysh__) { + // Load user-defined includes + set_error_handler(array($__psysh__, 'handleError')); + try { + foreach ($__psysh__->getIncludes() as $__psysh_include__) { + include $__psysh_include__; + } + } catch (\Exception $_e) { + $__psysh__->writeException($_e); + } + restore_error_handler(); + unset($__psysh_include__); + + extract($__psysh__->getScopeVariables(false)); + + do { + $__psysh__->beforeLoop(); + $__psysh__->setScopeVariables(get_defined_vars()); + + try { + // read a line, see if we should eval + $__psysh__->getInput(); + + // evaluate the current code buffer + ob_start( + array($__psysh__, 'writeStdout'), + version_compare(PHP_VERSION, '5.4', '>=') ? 1 : 2 + ); + + // Let PsySH inject some magic variables back into the + // shell scope... things like $__class, and $__file set by + // reflection commands + extract($__psysh__->getSpecialScopeVariables(false)); + + // And unset any magic variables which are no longer needed + foreach ($__psysh__->getUnusedCommandScopeVariableNames() as $__psysh_var_name__) { + unset($$__psysh_var_name__, $__psysh_var_name__); + } + + set_error_handler(array($__psysh__, 'handleError')); + $_ = eval($__psysh__->flushCode() ?: Loop::NOOP_INPUT); + restore_error_handler(); + + ob_end_flush(); + + $__psysh__->writeReturnValue($_); + } catch (BreakException $_e) { + restore_error_handler(); + if (ob_get_level() > 0) { + ob_end_clean(); + } + $__psysh__->writeException($_e); + + return; + } catch (ThrowUpException $_e) { + restore_error_handler(); + if (ob_get_level() > 0) { + ob_end_clean(); + } + $__psysh__->writeException($_e); + + throw $_e; + } catch (\TypeError $_e) { + restore_error_handler(); + if (ob_get_level() > 0) { + ob_end_clean(); + } + $__psysh__->writeException(TypeErrorException::fromTypeError($_e)); + } catch (\Error $_e) { + restore_error_handler(); + if (ob_get_level() > 0) { + ob_end_clean(); + } + $__psysh__->writeException(ErrorException::fromError($_e)); + } catch (\Exception $_e) { + restore_error_handler(); + if (ob_get_level() > 0) { + ob_end_clean(); + } + $__psysh__->writeException($_e); + } + + $__psysh__->afterLoop(); + } while (true); + }; + + // bind the closure to $this from the shell scope variables... + if (self::bindLoop()) { + $that = $shell->getBoundObject(); + if (is_object($that)) { + $loop = $loop->bindTo($that, get_class($that)); + } else { + $loop = $loop->bindTo(null, null); + } + } + + $loop($shell); + } + + /** + * A beforeLoop callback. + * + * This is executed at the start of each loop iteration. In the default + * (non-forking) loop implementation, this is a no-op. + */ + public function beforeLoop() + { + // no-op + } + + /** + * A afterLoop callback. + * + * This is executed at the end of each loop iteration. In the default + * (non-forking) loop implementation, this is a no-op. + */ + public function afterLoop() + { + // no-op + } + + /** + * Decide whether to bind the execution loop. + * + * @return bool + */ + protected static function bindLoop() + { + // skip binding on HHVM <= 3.5.0 + // see https://github.com/facebook/hhvm/issues/1203 + if (defined('HHVM_VERSION')) { + return version_compare(HHVM_VERSION, '3.5.0', '>='); + } + + return version_compare(PHP_VERSION, '5.4', '>='); + } +}