annotate 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
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of Psy Shell.
Chris@0 5 *
Chris@0 6 * (c) 2012-2017 Justin Hileman
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Psy\ExecutionLoop;
Chris@0 13
Chris@0 14 use Psy\Configuration;
Chris@0 15 use Psy\Exception\BreakException;
Chris@0 16 use Psy\Exception\ErrorException;
Chris@0 17 use Psy\Exception\ThrowUpException;
Chris@0 18 use Psy\Exception\TypeErrorException;
Chris@0 19 use Psy\Shell;
Chris@0 20
Chris@0 21 /**
Chris@0 22 * The Psy Shell execution loop.
Chris@0 23 */
Chris@0 24 class Loop
Chris@0 25 {
Chris@0 26 const NOOP_INPUT = 'return null;';
Chris@0 27
Chris@0 28 /**
Chris@0 29 * Loop constructor.
Chris@0 30 *
Chris@0 31 * The non-forking loop doesn't have much use for Configuration, so we'll
Chris@0 32 * just ignore it.
Chris@0 33 *
Chris@0 34 * @param Configuration $config
Chris@0 35 */
Chris@0 36 public function __construct(Configuration $config)
Chris@0 37 {
Chris@0 38 // don't need this
Chris@0 39 }
Chris@0 40
Chris@0 41 /**
Chris@0 42 * Run the execution loop.
Chris@0 43 *
Chris@0 44 * @throws ThrowUpException if thrown by the `throw-up` command
Chris@0 45 *
Chris@0 46 * @param Shell $shell
Chris@0 47 */
Chris@0 48 public function run(Shell $shell)
Chris@0 49 {
Chris@0 50 $loop = function ($__psysh__) {
Chris@0 51 // Load user-defined includes
Chris@0 52 set_error_handler(array($__psysh__, 'handleError'));
Chris@0 53 try {
Chris@0 54 foreach ($__psysh__->getIncludes() as $__psysh_include__) {
Chris@0 55 include $__psysh_include__;
Chris@0 56 }
Chris@0 57 } catch (\Exception $_e) {
Chris@0 58 $__psysh__->writeException($_e);
Chris@0 59 }
Chris@0 60 restore_error_handler();
Chris@0 61 unset($__psysh_include__);
Chris@0 62
Chris@0 63 extract($__psysh__->getScopeVariables(false));
Chris@0 64
Chris@0 65 do {
Chris@0 66 $__psysh__->beforeLoop();
Chris@0 67 $__psysh__->setScopeVariables(get_defined_vars());
Chris@0 68
Chris@0 69 try {
Chris@0 70 // read a line, see if we should eval
Chris@0 71 $__psysh__->getInput();
Chris@0 72
Chris@0 73 // evaluate the current code buffer
Chris@0 74 ob_start(
Chris@0 75 array($__psysh__, 'writeStdout'),
Chris@0 76 version_compare(PHP_VERSION, '5.4', '>=') ? 1 : 2
Chris@0 77 );
Chris@0 78
Chris@0 79 // Let PsySH inject some magic variables back into the
Chris@0 80 // shell scope... things like $__class, and $__file set by
Chris@0 81 // reflection commands
Chris@0 82 extract($__psysh__->getSpecialScopeVariables(false));
Chris@0 83
Chris@0 84 // And unset any magic variables which are no longer needed
Chris@0 85 foreach ($__psysh__->getUnusedCommandScopeVariableNames() as $__psysh_var_name__) {
Chris@0 86 unset($$__psysh_var_name__, $__psysh_var_name__);
Chris@0 87 }
Chris@0 88
Chris@0 89 set_error_handler(array($__psysh__, 'handleError'));
Chris@0 90 $_ = eval($__psysh__->flushCode() ?: Loop::NOOP_INPUT);
Chris@0 91 restore_error_handler();
Chris@0 92
Chris@0 93 ob_end_flush();
Chris@0 94
Chris@0 95 $__psysh__->writeReturnValue($_);
Chris@0 96 } catch (BreakException $_e) {
Chris@0 97 restore_error_handler();
Chris@0 98 if (ob_get_level() > 0) {
Chris@0 99 ob_end_clean();
Chris@0 100 }
Chris@0 101 $__psysh__->writeException($_e);
Chris@0 102
Chris@0 103 return;
Chris@0 104 } catch (ThrowUpException $_e) {
Chris@0 105 restore_error_handler();
Chris@0 106 if (ob_get_level() > 0) {
Chris@0 107 ob_end_clean();
Chris@0 108 }
Chris@0 109 $__psysh__->writeException($_e);
Chris@0 110
Chris@0 111 throw $_e;
Chris@0 112 } catch (\TypeError $_e) {
Chris@0 113 restore_error_handler();
Chris@0 114 if (ob_get_level() > 0) {
Chris@0 115 ob_end_clean();
Chris@0 116 }
Chris@0 117 $__psysh__->writeException(TypeErrorException::fromTypeError($_e));
Chris@0 118 } catch (\Error $_e) {
Chris@0 119 restore_error_handler();
Chris@0 120 if (ob_get_level() > 0) {
Chris@0 121 ob_end_clean();
Chris@0 122 }
Chris@0 123 $__psysh__->writeException(ErrorException::fromError($_e));
Chris@0 124 } catch (\Exception $_e) {
Chris@0 125 restore_error_handler();
Chris@0 126 if (ob_get_level() > 0) {
Chris@0 127 ob_end_clean();
Chris@0 128 }
Chris@0 129 $__psysh__->writeException($_e);
Chris@0 130 }
Chris@0 131
Chris@0 132 $__psysh__->afterLoop();
Chris@0 133 } while (true);
Chris@0 134 };
Chris@0 135
Chris@0 136 // bind the closure to $this from the shell scope variables...
Chris@0 137 if (self::bindLoop()) {
Chris@0 138 $that = $shell->getBoundObject();
Chris@0 139 if (is_object($that)) {
Chris@0 140 $loop = $loop->bindTo($that, get_class($that));
Chris@0 141 } else {
Chris@0 142 $loop = $loop->bindTo(null, null);
Chris@0 143 }
Chris@0 144 }
Chris@0 145
Chris@0 146 $loop($shell);
Chris@0 147 }
Chris@0 148
Chris@0 149 /**
Chris@0 150 * A beforeLoop callback.
Chris@0 151 *
Chris@0 152 * This is executed at the start of each loop iteration. In the default
Chris@0 153 * (non-forking) loop implementation, this is a no-op.
Chris@0 154 */
Chris@0 155 public function beforeLoop()
Chris@0 156 {
Chris@0 157 // no-op
Chris@0 158 }
Chris@0 159
Chris@0 160 /**
Chris@0 161 * A afterLoop callback.
Chris@0 162 *
Chris@0 163 * This is executed at the end of each loop iteration. In the default
Chris@0 164 * (non-forking) loop implementation, this is a no-op.
Chris@0 165 */
Chris@0 166 public function afterLoop()
Chris@0 167 {
Chris@0 168 // no-op
Chris@0 169 }
Chris@0 170
Chris@0 171 /**
Chris@0 172 * Decide whether to bind the execution loop.
Chris@0 173 *
Chris@0 174 * @return bool
Chris@0 175 */
Chris@0 176 protected static function bindLoop()
Chris@0 177 {
Chris@0 178 // skip binding on HHVM <= 3.5.0
Chris@0 179 // see https://github.com/facebook/hhvm/issues/1203
Chris@0 180 if (defined('HHVM_VERSION')) {
Chris@0 181 return version_compare(HHVM_VERSION, '3.5.0', '>=');
Chris@0 182 }
Chris@0 183
Chris@0 184 return version_compare(PHP_VERSION, '5.4', '>=');
Chris@0 185 }
Chris@0 186 }