Skip to content

Commit c8beb58

Browse files
committed
Add debug comments
1 parent 68e44a1 commit c8beb58

File tree

4 files changed

+126
-36
lines changed

4 files changed

+126
-36
lines changed

src/Internal/Runtime/SourceExecutor.php

Lines changed: 118 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
use FFI\Preprocessor\Internal\Lexer;
2323
use FFI\Preprocessor\Io\Directory\Repository as DirectoriesRepository;
2424
use FFI\Preprocessor\Io\Source\Repository as SourcesRepository;
25+
use FFI\Preprocessor\Option;
2526
use FFI\Preprocessor\Preprocessor;
27+
use JetBrains\PhpStorm\ExpectedValues;
2628
use Phplrt\Contracts\Exception\RuntimeExceptionInterface;
2729
use Phplrt\Contracts\Lexer\TokenInterface;
2830
use Phplrt\Contracts\Source\FileInterface;
@@ -35,6 +37,8 @@
3537
/**
3638
* @internal SourceExecutor is an internal library class, please do not use it in your code.
3739
* @psalm-internal FFI\Preprocessor\Internal
40+
*
41+
* @psalm-import-type OptionEnum from Option
3842
*/
3943
final class SourceExecutor
4044
{
@@ -68,12 +72,15 @@ final class SourceExecutor
6872
* @param DirectoriesRepository $directories
6973
* @param SourcesRepository $sources
7074
* @param LoggerInterface $logger
75+
* @param int-mask-of<OptionEnum> $options
7176
*/
7277
public function __construct(
7378
private DirectivesRepository $directives,
7479
private DirectoriesRepository $directories,
7580
private SourcesRepository $sources,
7681
private LoggerInterface $logger,
82+
#[ExpectedValues(flagsFromClass: Option::class)]
83+
private int $options,
7784
) {
7885
$this->lexer = new Lexer();
7986
$this->stack = new OutputStack();
@@ -98,11 +105,11 @@ public function execute(ReadableInterface $source): \Traversable
98105
try {
99106
switch ($token->getName()) {
100107
case Lexer::T_ERROR:
101-
$this->doError($token, $source);
108+
yield from $this->doError($token, $source);
102109
break;
103110

104111
case Lexer::T_WARNING:
105-
$this->doWarning($token, $source);
112+
yield from $this->doWarning($token, $source);
106113
break;
107114

108115
case Lexer::T_QUOTED_INCLUDE:
@@ -111,39 +118,39 @@ public function execute(ReadableInterface $source): \Traversable
111118
break;
112119

113120
case Lexer::T_IFDEF:
114-
$this->doIfDefined($token);
121+
yield from $this->doIfDefined($token, $source);
115122
break;
116123

117124
case Lexer::T_IFNDEF:
118-
$this->doIfNotDefined($token);
125+
yield from $this->doIfNotDefined($token, $source);
119126
break;
120127

121128
case Lexer::T_ENDIF:
122-
$this->doEndIf();
129+
yield from $this->doEndIf($token, $source);
123130
break;
124131

125132
case Lexer::T_IF:
126-
$this->doIf($token);
133+
yield from $this->doIf($token, $source);
127134
break;
128135

129136
case Lexer::T_ELSE_IF:
130-
$this->doElseIf($token, $source);
137+
yield from $this->doElseIf($token, $source);
131138
break;
132139

133140
case Lexer::T_ELSE:
134-
$this->doElse();
141+
yield from $this->doElse($token, $source);
135142
break;
136143

137144
case Lexer::T_OBJECT_MACRO:
138-
$this->doObjectLikeDirective($token);
145+
yield from $this->doObjectLikeDirective($token, $source);
139146
break;
140147

141148
case Lexer::T_FUNCTION_MACRO:
142-
$this->doFunctionLikeDirective($token);
149+
yield from $this->doFunctionLikeDirective($token, $source);
143150
break;
144151

145152
case Lexer::T_UNDEF:
146-
$this->doRemoveDefine($token);
153+
yield from $this->doRemoveDefine($token, $source);
147154
break;
148155

149156
case Lexer::T_SOURCE:
@@ -163,6 +170,39 @@ public function execute(ReadableInterface $source): \Traversable
163170
}
164171
}
165172

173+
/**
174+
* @param ReadableInterface $source
175+
* @param TokenInterface $token
176+
* @param array<string> $comments
177+
* @return iterable<string>
178+
*/
179+
private function debug(ReadableInterface $source, TokenInterface $token, array $comments = []): iterable
180+
{
181+
if (Option::contains($this->options, Option::KEEP_DEBUG_COMMENTS)) {
182+
$map = static fn(string $line): string => "// $line\n";
183+
$line = Position::fromOffset($source, $token->getOffset())
184+
->getLine();
185+
return [
186+
'// ' . $this->sourceToString($source) . ':' . $line . "\n",
187+
...\array_map($map, $comments)
188+
];
189+
}
190+
191+
return [];
192+
}
193+
194+
/**
195+
* @param ReadableInterface $source
196+
* @return string
197+
*/
198+
private function sourceToString(ReadableInterface $source): string
199+
{
200+
return $source instanceof FileInterface
201+
? $source->getPathname()
202+
: '{' . $source->getHash() . '}'
203+
;
204+
}
205+
166206
/**
167207
* @param ReadableInterface $source
168208
* @return string
@@ -177,11 +217,12 @@ private function read(ReadableInterface $source): string
177217
/**
178218
* @param Composite $tok
179219
* @param ReadableInterface $src
220+
* @return iterable<string>
180221
*/
181-
private function doError(Composite $tok, ReadableInterface $src): void
222+
private function doError(Composite $tok, ReadableInterface $src): iterable
182223
{
183224
if (! $this->stack->isEnabled()) {
184-
return;
225+
return [];
185226
}
186227

187228
$message = $this->escape(\trim($tok[0]->getValue()));
@@ -190,6 +231,8 @@ private function doError(Composite $tok, ReadableInterface $src): void
190231
'position' => Position::fromOffset($tok->getOffset()),
191232
'source' => $src,
192233
]);
234+
235+
return $this->debug($src, $tok, ['error ' . $message]);
193236
}
194237

195238
/**
@@ -228,11 +271,12 @@ private function escape(string $body): string
228271
/**
229272
* @param Composite $tok
230273
* @param ReadableInterface $src
274+
* @return iterable<string>
231275
*/
232-
private function doWarning(Composite $tok, ReadableInterface $src): void
276+
private function doWarning(Composite $tok, ReadableInterface $src): iterable
233277
{
234278
if (! $this->stack->isEnabled()) {
235-
return;
279+
return [];
236280
}
237281

238282
$message = $this->escape(\trim($tok[0]->getValue()));
@@ -241,6 +285,8 @@ private function doWarning(Composite $tok, ReadableInterface $src): void
241285
'position' => Position::fromOffset($tok->getOffset()),
242286
'source' => $src,
243287
]);
288+
289+
return $this->debug($src, $tok, ['warning ' . $message]);
244290
}
245291

246292
/**
@@ -267,6 +313,7 @@ private function doInclude(Composite $token, ReadableInterface $src): iterable
267313
throw NotReadableException::fromSource($e->getMessage(), $src, $token[0]);
268314
}
269315

316+
yield from $this->debug($src, $token, ['include ' . $this->sourceToString($inclusion)]);
270317
yield from $this->execute($inclusion);
271318
}
272319

@@ -306,66 +353,82 @@ private function lookup(ReadableInterface $source, string $file, bool $withLocal
306353

307354
/**
308355
* @param Composite $token
356+
* @param ReadableInterface $source
357+
* @return iterable<string>
309358
*/
310-
private function doIfDefined(Composite $token): void
359+
private function doIfDefined(Composite $token, ReadableInterface $source): iterable
311360
{
312361
if (! $this->stack->isEnabled()) {
313362
$this->stack->push(false);
314363

315-
return;
364+
return [];
316365
}
317366

318367
$body = $this->escape($token[0]->getValue());
319368

320369
$defined = $this->directives->defined($body);
321370

322371
$this->stack->push($defined);
372+
373+
return $this->debug($source, $token, ['if defined ' . $body]);
323374
}
324375

325376
/**
326377
* @param Composite $token
378+
* @param ReadableInterface $source
379+
* @return iterable<string>
327380
*/
328-
private function doIfNotDefined(Composite $token): void
381+
private function doIfNotDefined(Composite $token, ReadableInterface $source): iterable
329382
{
330383
if (! $this->stack->isEnabled()) {
331384
$this->stack->push(false);
332385

333-
return;
386+
return [];
334387
}
335388

336389
$body = $this->escape($token[0]->getValue());
337390

338391
$defined = $this->directives->defined($body);
339392

340393
$this->stack->push(! $defined);
394+
395+
return $this->debug($source, $token, ['if not defined ' . $body]);
341396
}
342397

343398
/**
344-
* @return void
399+
* @param TokenInterface $token
400+
* @param ReadableInterface $source
401+
* @return iterable<string>
345402
*/
346-
private function doEndIf(): void
403+
private function doEndIf(TokenInterface $token, ReadableInterface $source): iterable
347404
{
348405
try {
349406
$this->stack->pop();
350407
} catch (\LogicException $e) {
351408
throw new \LogicException('#endif directive without #if');
352409
}
410+
411+
return $this->debug($source, $token, ['endif']);
353412
}
354413

355414
/**
356415
* @param Composite $token
416+
* @param ReadableInterface $source
417+
* @return iterable<string>
357418
* @throws RuntimeExceptionInterface
358419
* @throws \Throwable
359420
*/
360-
private function doIf(Composite $token): void
421+
private function doIf(Composite $token, ReadableInterface $source): iterable
361422
{
362423
if (! $this->stack->isEnabled()) {
363424
$this->stack->push(false);
364425

365-
return;
426+
return [];
366427
}
367428

368429
$this->stack->push($this->eval($token));
430+
431+
return $this->debug($source, $token, ['if ' . $token[0]->getValue()]);
369432
}
370433

371434
/**
@@ -398,23 +461,29 @@ private function replace(string $body, int $ctx): string
398461
/**
399462
* @param Composite $token
400463
* @param ReadableInterface $source
464+
* @return iterable<string>
465+
* @throws RuntimeExceptionInterface
401466
* @throws \Throwable
402467
*/
403-
private function doElseIf(Composite $token, ReadableInterface $source): void
468+
private function doElseIf(Composite $token, ReadableInterface $source): iterable
404469
{
405470
if (! $this->stack->isCompleted() && $this->eval($token)) {
406471
$this->stack->complete();
407472

408-
return;
473+
return [];
409474
}
410475

411476
$this->stack->update(false, $this->stack->isCompleted());
477+
478+
return $this->debug($source, $token, ['else if ' . $token->getValue()]);
412479
}
413480

414481
/**
415-
* @return void
482+
* @param TokenInterface $token
483+
* @param ReadableInterface $source
484+
* @return iterable<string>
416485
*/
417-
private function doElse(): void
486+
private function doElse(TokenInterface $token, ReadableInterface $source): iterable
418487
{
419488
try {
420489
if (! $this->stack->isCompleted()) {
@@ -425,15 +494,19 @@ private function doElse(): void
425494
} catch (\LogicException $e) {
426495
throw new \LogicException('#else directive without #if');
427496
}
497+
498+
return $this->debug($source, $token, ['else']);
428499
}
429500

430501
/**
431502
* @param Composite $token
503+
* @param ReadableInterface $source
504+
* @return iterable<string>
432505
*/
433-
private function doObjectLikeDirective(Composite $token): void
506+
private function doObjectLikeDirective(Composite $token, ReadableInterface $source): iterable
434507
{
435508
if (! $this->stack->isEnabled()) {
436-
return;
509+
return [];
437510
}
438511

439512
// Name
@@ -444,15 +517,19 @@ private function doObjectLikeDirective(Composite $token): void
444517
$value = $this->replace($value, DirectiveExecutor::CTX_EXPRESSION);
445518

446519
$this->directives->define($name, new ObjectLikeDirective($value));
520+
521+
return $this->debug($source, $token, ['define ' . $name . ' = ' . ($value ?: '""')]);
447522
}
448523

449524
/**
450525
* @param Composite $token
526+
* @param ReadableInterface $source
527+
* @return iterable<string>
451528
*/
452-
private function doFunctionLikeDirective(Composite $token): void
529+
private function doFunctionLikeDirective(Composite $token, ReadableInterface $source): iterable
453530
{
454531
if (! $this->stack->isEnabled()) {
455-
return;
532+
return [];
456533
}
457534

458535
// Name
@@ -466,22 +543,30 @@ private function doFunctionLikeDirective(Composite $token): void
466543
$value = $this->replace($value, DirectiveExecutor::CTX_EXPRESSION);
467544

468545
$this->directives->define($name, new FunctionLikeDirective($args, $value));
546+
547+
return $this->debug($source, $token, [
548+
'define ' . $name . '(' . $token[1]->getValue() . ') = ' . ($value ?: '""')
549+
]);
469550
}
470551

471552
/**
472553
* @param Composite $token
554+
* @param ReadableInterface $source
555+
* @return iterable<string>
473556
*/
474-
private function doRemoveDefine(Composite $token): void
557+
private function doRemoveDefine(Composite $token, ReadableInterface $source): iterable
475558
{
476559
if (! $this->stack->isEnabled()) {
477-
return;
560+
return [];
478561
}
479562

480563
$body = $this->escape($token[0]->getValue());
481564

482565
$name = $this->replace($body, DirectiveExecutor::CTX_SOURCE);
483566

484567
$this->directives->undef($name);
568+
569+
return $this->debug($source, $token, ['undef ' . $name]);
485570
}
486571

487572
/**

0 commit comments

Comments
 (0)