Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@
"bin": [
"bin/php-cfg"
]
}
}
2 changes: 1 addition & 1 deletion lib/PHPCfg/Op/Terminal/StaticVar.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class StaticVar extends Terminal

public ?Block $defaultBlock;

public ?Operand $defaultVar;
public ?Operand $defaultVar = null;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug fix not related to printer


public function __construct(Operand $var, ?Block $defaultBlock = null, ?Operand $defaultVar = null, array $attributes = [])
{
Expand Down
9 changes: 5 additions & 4 deletions lib/PHPCfg/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ protected function loadHandlers(): void
{
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(
__DIR__ . '/ParserHandler/',
RecursiveIteratorIterator::LEAVES_ONLY
)
__DIR__ . '/ParserHandler/'
),
RecursiveIteratorIterator::LEAVES_ONLY
);
$handlers = [];
foreach ($it as $file) {
Expand Down Expand Up @@ -310,7 +310,7 @@ public function parseExprNode($expr): ?Operand
if (isset($this->exprHandlers[$expr->getType()])) {
return $this->exprHandlers[$expr->getType()]->handleExpr($expr);
}
var_dump(array_keys($this->exprHandlers));

throw new RuntimeException('Unknown Expr Type ' . $expr->getType());
}

Expand Down Expand Up @@ -456,6 +456,7 @@ public function readVariableRecursive(string $name, Block $block): Operand

return $var;
}

$var = new Temporary(new Variable(new Literal($name)));
$phi = new Op\Phi($var, ['block' => $block]);
$this->ctx->addToIncompletePhis($block, $name, $phi);
Expand Down
1 change: 0 additions & 1 deletion lib/PHPCfg/ParserHandler/Batch/Scalar.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ public function handleExpr(Node\Expr $scalar): Operand
// TODO
return new Operand\Literal('__FUNCTION__');
default:
var_dump($scalar);
throw new RuntimeException('Unknown how to deal with scalar type ' . $scalar->getType());
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/PHPCfg/ParserHandler/Batch/Unary.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace PHPCfg\ParserHandler\Batch;

use PHPCfg\Assertion;
use PHPCfg\Op;
use PHPCfg\Operand;
use PHPCfg\ParserHandler;
Expand Down
18 changes: 8 additions & 10 deletions lib/PHPCfg/ParserHandler/Expr/ConstFetch.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,14 @@ class ConstFetch extends ParserHandler implements Expr
{
public function handleExpr(Node\Expr $expr): Operand
{
if ($expr->name->isUnqualified()) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug fix not related to printer

$lcname = strtolower($expr->name->toString());
switch ($lcname) {
case 'null':
return new Operand\Literal(null);
case 'true':
return new Operand\Literal(true);
case 'false':
return new Operand\Literal(false);
}
$lcname = strtolower($expr->name->toString());
switch ($lcname) {
case 'null':
return new Operand\NullOperand();
case 'true':
return new Operand\Literal(true);
case 'false':
return new Operand\Literal(false);
}

$nsName = null;
Expand Down
82 changes: 30 additions & 52 deletions lib/PHPCfg/Printer/Printer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace PHPCfg\Printer;

use FilesystemIterator;
use LogicException;
use PHPCfg\Block;
use PHPCfg\Func;
Expand Down Expand Up @@ -59,10 +60,13 @@ protected function loadRenderers(): void
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(
__DIR__ . '/Renderer/',
RecursiveIteratorIterator::LEAVES_ONLY
)
FilesystemIterator::SKIP_DOTS
),
RecursiveIteratorIterator::LEAVES_ONLY
);

$handlers = [];
$classes = [];
foreach ($it as $file) {
if (!$file->isFile() || $file->getExtension() !== 'php') {
continue;
Expand All @@ -75,14 +79,32 @@ protected function loadRenderers(): void
continue;
}

$classes[] = $class;
}

usort($classes, function ($a, $b) {
$aParts = substr_count($a, '\\');
$bParts = substr_count($b, '\\');

if ($aParts == $bParts) {
return 0;
}
return ($aParts < $bParts) ? 1 : -1;
});

foreach ($classes as $class) {
$obj = new $class($this);
$this->addRenderer($obj);
}
}

abstract public function printScript(Script $script): string;
abstract public function printScript(Script $script): mixed;

abstract public function printFunc(Func $func): mixed;

abstract public function printFunc(Func $func): string;
abstract public function renderOperand(Operand $var): mixed;

abstract public function renderOpLabel(array $desc): mixed;

protected function reset(): void
{
Expand All @@ -98,20 +120,6 @@ protected function getBlockId(Block $block): int
return $this->blocks[$block];
}

public function renderOperand(Operand $var): string
{
foreach ($this->renderers as $renderer) {
$result = $renderer->renderOperand($var);
if ($result !== null) {
$kind = $result['kind'];
$type = $result['type'];
unset($result['kind'], $result['type']);
return strtoupper($kind) . $type . '(' . trim(implode(" ", $result)) . ')';
}
}
return 'UNKNOWN';
}

public function renderOp(Op $op): array
{
foreach ($this->renderers as $renderer) {
Expand All @@ -121,17 +129,14 @@ public function renderOp(Op $op): array
$childblocks = $result['childblocks'];
return [
'op' => $op,
'kind' => $kind,
'label' => $this->renderOpLabel($result),
'childBlocks' => $childblocks,
];
}
}

return [
'op' => $op,
'label' => 'UNKNOWN',
'childBlocks' => $childBlocks,
];
throw new LogicException("Unknown op rendering: " . get_class($op));
}

protected function indent($str, $levels = 1): string
Expand All @@ -145,7 +150,7 @@ protected function indent($str, $levels = 1): string

public function enqueueBlock(Block $block): void
{
if (! $this->blocks->contains($block)) {
if (! $this->blocks->offsetExists($block)) {
$this->blocks[$block] = count($this->blocks) + 1;
$this->blockQueue->enqueue($block);
}
Expand All @@ -163,14 +168,7 @@ protected function render(Func $func)
$block = $this->blockQueue->dequeue();
$ops = [];
foreach ($block->phi as $phi) {
$result = $this->indent($this->renderOperand($phi->result) . ' = Phi(');
$result .= implode(', ', array_map([$this, 'renderOperand'], $phi->vars));
$result .= ')';
$renderedOps[$phi] = $ops[] = [
'op' => $phi,
'label' => $result,
'childBlocks' => [],
];
$renderedOps[$phi] = $ops[] = $this->renderOp($phi);
}
foreach ($block->children as $child) {
$renderedOps[$child] = $ops[] = $this->renderOp($child);
Expand Down Expand Up @@ -222,24 +220,4 @@ public function renderType(?Op\Type $type): string
}
throw new LogicException("Unknown type rendering: " . get_class($type));
}

public function renderOpLabel(array $desc): string
{
$result = "{$desc['kind']}";
unset($desc['kind'], $desc['childblocks']);
foreach ($desc as $name => $val) {
if (is_array($val)) {
foreach ($val as $v) {
if (is_array($v)) {
$result .= $this->indent("\n" . implode("\n", $v));
} else {
$result .= $this->indent("\n{$v}");
}
}
} else {
$result .= $this->indent("\n{$val}");
}
}
return $result;
}
}
55 changes: 25 additions & 30 deletions lib/PHPCfg/Printer/Renderer/GenericOp.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,46 +30,52 @@ public function reset(): void {}
public function renderOp(Op $op): ?array
{
$result = [
'attributes' => $this->renderAttributes($op->getAttributes()),
'attrGroups' => [],
'childblocks' => [],
'kind' => $op->getType(),
'types' => [],
'vars' => [],
'attributes' => $this->renderAttributes($op->getAttributes()),
'childblocks' => [],
];

if ($op instanceof Op\AttributableOp) {
$result['attrGroups'] = $this->renderAttrGroups($op);
}

if ($op instanceof Op\CallableOp) {
$func = $op->getFunc();
$result['vars'][] = "name: {$func->name}";
$result['vars']['name'] = $func->name;
}

if ($op instanceof Op\Stmt\Property || $op instanceof Op\Stmt\ClassMethod) {
$result['vars'][] = "flags: " . $this->renderFlags($op);
$result['vars']['flags'] = $this->renderFlags($op);
}


foreach ($op->getTypeNames() as $typeName => $type) {
if (is_array($type)) {
$result['types'][$typeName] = [];
foreach ($type as $key => $subType) {
if (! $subType) {
continue;
}
$result['types'][] = "{$typeName}[{$key}]: " . $this->printer->renderType($subType);
$result['types'][$typeName][$key] = $this->printer->renderType($subType);
}
} elseif ($type) {
$result['types'][] = "{$typeName}: " . $this->printer->renderType($type);
$result['types'][$typeName] = $this->printer->renderType($type);
}
}

foreach ($op->getVariableNames() as $varName => $vars) {
if (is_array($vars)) {
$result['vars'][$varName] = [];
foreach ($vars as $key => $var) {
if (! $var) {
continue;
}
$result['vars'][] = "{$varName}[{$key}]: " . $this->printer->renderOperand($var);
$result['vars'][$varName][$key] = $this->printer->renderOperand($var);
}
} elseif ($vars) {
$result['vars'][] = "{$varName}: " . $this->printer->renderOperand($vars);
$result['vars'][$varName] = $this->printer->renderOperand($vars);
}
}

Expand All @@ -91,12 +97,6 @@ public function renderOp(Op $op): ?array
}
}

if ($op instanceof Op\AttributableOp) {
$result['attrGroups'] = $this->renderAttrGroups($op);
}



return $result;
}

Expand All @@ -105,8 +105,6 @@ public function renderOperand(Operand $operand): ?array
return null;
}



protected function renderAttributes(array $attributes): array
{
if (!$this->printer->renderAttributes) {
Expand All @@ -115,38 +113,36 @@ protected function renderAttributes(array $attributes): array
$result = [];
foreach ($attributes as $key => $value) {
if (is_string($value) || is_numeric($value)) {
$result[] = "attribute['" . $key . "']: " . $value;
$result['attribute'][$key] = $value;
}
}
return $result;
}


protected function renderAttrGroups(Op\AttributableOp $op): array
{
$result = [];
$result['attrGroup'] = [];
foreach ($op->getAttributeGroups() as $indexGroup => $attrGroup) {
$result[$indexGroup] = [];
$result[$indexGroup][] = "attrGroup[$indexGroup]: ";
foreach ($this->renderAttributes($attrGroup->getAttributes()) as $attr) {
$result[$indexGroup][] = " {$attr}";
$result['attrGroup'][$indexGroup] = [];
foreach ($this->renderAttributes($attrGroup->getAttributes()) as $i => $attr) {
$result['attrGroup'][$indexGroup][$i] = $attr;
}
foreach ($attrGroup->attrs as $indexAttr => $attr) {
$result[$indexGroup][] = " attr[$indexAttr]: ";
foreach ($this->renderAttributes($attr->getAttributes()) as $rendered) {
$result[$indexGroup][] = " {$rendered}";
$result['attrGroup'][$indexGroup][$indexAttr] = [];
foreach ($this->renderAttributes($attr->getAttributes()) as $j => $rendered) {
$result['attrGroup'][$indexGroup][$indexAttr][$j] = $rendered;
}
$result[$indexGroup][] = " name: " . $this->printer->renderOperand($attr->name);
$result['attrGroup'][$indexGroup][$indexAttr]['name'] = $this->printer->renderOperand($attr->name);
foreach ($attr->args as $indexArg => $arg) {
$result[$indexGroup][] = " args[$indexArg]: " . $this->printer->renderOperand($arg);
$result['attrGroup'][$indexGroup][$indexAttr]['args'][$indexArg] = $this->printer->renderOperand($arg);
}
}
}

return $result;
}


protected function renderFlags(Op\Stmt $stmt): string
{
$result = '';
Expand Down Expand Up @@ -178,5 +174,4 @@ protected function renderFlags(Op\Stmt $stmt): string

return $result;
}

}
Loading
Loading