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