Inheritance: extends AdjacencyList, implements Gliph\Graph\MutableDirectedGraph
示例#1
0
 /**
  * @covers \Gliph\Traversal\DepthFirst::toposort
  * @expectedException Gliph\Exception\RuntimeException
  *   Thrown by the visitor after adding a cycle to the graph.
  */
 public function testToposort()
 {
     extract($this->v);
     $this->assertEquals(array($c, $d, $b, $a), DepthFirst::toposort($this->g, $a));
     $this->g->addDirectedEdge($d, $a);
     DepthFirst::toposort($this->g, $a);
 }
示例#2
0
 /**
  * @covers ::process
  */
 public function testExpansionFailure()
 {
     $graph = new DirectedAdjacencyList();
     $end = new End();
     $graph->ensureArc($end, $b = new JitBinaryOp(JitBinaryOp::PLUS, new Constant(1), new Variable(), new Variable()));
     $rule = new ConstBinaryOp();
     $this->assertFalse($rule->process($b, $graph));
 }
示例#3
0
 public static function dump(DirectedAdjacencyList $graph)
 {
     $edges = [];
     foreach ($graph->edges() as $edge) {
         $edges[] = $edge[0]->getName() . ' ' . $edge[1]->getName();
     }
     return $edges;
 }
示例#4
0
 /**
  * @covers ::process
  * @covers ::addRule
  */
 public function testOperation()
 {
     $graph = new DirectedAdjacencyList();
     $func = new Function_([], new Type(0), $graph);
     $graph->ensureVertex($func);
     $state = new GraphState($func);
     $resolver = new Optimizer();
     $resolver->addRule($r = $this->getMock(OptimizerRule::class));
     $r->expects($this->once())->method('process')->with($this->identicalTo($func))->will($this->returnValue(false));
     $resolver->process($state);
 }
示例#5
0
 /**
  * @covers ::__construct
  * @covers ::getGraph
  * @covers ::getFunction
  * @covers ::getDominator
  * @covers ::getPostDominator
  * @covers ::getInverseGraph
  */
 public function testBasicUsage()
 {
     $func = new JitFunction([], new Type(0), $graph = new DirectedAdjacencyList());
     $graph->ensureArc($func, new End());
     $state = new GraphState($func);
     $this->assertSame($func, $state->getFunction());
     $this->assertSame($graph, $state->getGraph());
     $this->assertInstanceOf(Dominator::class, $state->getDominator());
     $this->assertInstanceOf(Dominator::class, $state->getPostDominator());
     $this->assertInstanceOf(DirectedAdjacencyList::class, $state->getInverseGraph());
 }
示例#6
0
 /**
  * @covers ::generateText
  * @covers ::convertGraph
  */
 public function testGenerateText()
 {
     $a = new DummyVertex('a');
     $b = new DummyVertex('b');
     $c = new DummyVertex('c');
     $graph = new DirectedAdjacencyList();
     $graph->ensureArc($a, $b);
     $graph->ensureArc($b, $c);
     $graph->ensureArc($c, $b);
     $printer = new GraphPrinter();
     $this->assertContains('node_0', $printer->generateText($graph));
 }
示例#7
0
    /**
     * @covers ::generateFunction
     * @covers ::generate
     */
    public function testGenerateFunctionReversedJumpZ()
    {
        $generator = new Generator();
        $graph = new DirectedAdjacencyList();
        $long = new Type(Type::TYPE_LONG);
        $double = new Type(Type::TYPE_DOUBLE);
        $func = new Vertex\Function_([$a = new Variable($long), $b = new Variable($double)], $double, $graph);
        $noOp = new Vertex\NoOp();
        $jumpz = new Vertex\JumpZ($noOp, $a);
        $end = new Vertex\End();
        $graph->ensureArc($func, $jumpz);
        $graph->ensureArc($jumpz, $r1 = new Vertex\Return_(new Constant(1.5)));
        $graph->ensureArc($jumpz, $noOp);
        $graph->ensureArc($r1, $end);
        $graph->ensureArc($noOp, $r2 = new Vertex\Return_($b));
        $graph->ensureArc($r2, $end);
        $expected = <<<'EOF'
function test123 double
param $1 long
param $2 double
begin
jumpz $1 @1
const $3 double 1.5
return $3
label @1
return $2
end
EOF;
        $this->assertEquals($expected, $generator->generateFunction('test123', $func));
    }
示例#8
0
 /**
  * @covers ::isLiveVar
  */
 public function testIsLiveVarWithCycleAndLaterValue()
 {
     $graph = new DirectedAdjacencyList();
     $var = new Variable();
     $vertex = $this->getMock(Vertex::class);
     $graph->ensureVertex($vertex);
     $vertex->expects($this->once())->method('getVariables')->will($this->returnValue([]));
     $v1 = $this->getMock(Vertex::class);
     $v1->expects($this->once())->method('getVariables')->will($this->returnValue([$var]));
     $graph->ensureArc($vertex, $v1);
     $this->assertTrue(Helper::isLiveVar($var, $vertex, $graph));
 }
 /**
  * @expectedException Gliph\Exception\RuntimeException
  * @covers Gliph\Visitor\DepthFirstBasicVisitor::onBackEdge
  * @covers Gliph\Visitor\DepthFirstBasicVisitor::onInitializeVertex
  */
 public function testErrorOnCycle()
 {
     $this->g->addDirectedEdge($this->v['d'], $this->v['b']);
     DepthFirst::traverse($this->g, $this->vis);
 }
示例#10
0
 /**
  * @covers ::process
  * @covers ::implementSSA
  */
 public function testOperationLoopWithPhi()
 {
     $graph = new DirectedAdjacencyList();
     $a = new Variable();
     $func = new Function_([$a], new Type(0), $graph);
     $start = new NoOp();
     $noOp = new NoOp();
     $jumpz = new JumpZ($noOp, $a);
     $graph->ensureArc($func, $start);
     $graph->ensureArc($start, $jumpz);
     $graph->ensureArc($jumpz, $r = new Return_($a));
     $graph->ensureArc($r, new End());
     $graph->ensureArc($jumpz, $binary = new BinaryOp(BinaryOp::PLUS, $a, new Constant(2), $a));
     $graph->ensureArc($binary, $j = new Jump());
     $graph->ensureArc($j, $start);
     $state = new GraphState($func);
     $compiler = new SSACompiler();
     $compiler->process($state);
     $this->assertSame([$a], $func->getArguments());
     $i = 0;
     foreach ($graph->successorsOf($start) as $v) {
         $this->assertEquals(0, $i++, 'More then one adjacent node');
         $this->assertInstanceOf(Phi::class, $v);
         $this->assertContains($a, $v->getValues());
         $this->assertSame($r->getValue(), $v->getResult());
     }
 }
 /**
  * @covers \Gliph\Algorithm\ConnectedComponent::tarjan_scc()
  */
 public function testTarjanScc()
 {
     $a = new TestVertex('a');
     $b = new TestVertex('b');
     $c = new TestVertex('c');
     $d = new TestVertex('d');
     $e = new TestVertex('e');
     $f = new TestVertex('f');
     $g = new TestVertex('g');
     $h = new TestVertex('h');
     $graph = new DirectedAdjacencyList();
     $graph->addDirectedEdge($a, $d);
     $graph->addDirectedEdge($a, $b);
     $graph->addDirectedEdge($b, $c);
     $graph->addDirectedEdge($c, $d);
     $graph->addDirectedEdge($d, $a);
     $graph->addDirectedEdge($e, $d);
     $graph->addDirectedEdge($f, $g);
     $graph->addDirectedEdge($g, $h);
     $graph->addDirectedEdge($h, $f);
     $visitor = ConnectedComponent::tarjan_scc($graph);
     $expected_full = array(array($c, $b, $d, $a), array($e), array($h, $g, $f));
     $this->assertEquals($expected_full, $visitor->getComponents());
     $expected_full = array(array($c, $b, $d, $a), array($h, $g, $f));
     $this->assertEquals($expected_full, $visitor->getConnectedComponents());
 }
示例#12
0
 public function checkForCircularReference(array $phiNodes, GraphState $state)
 {
     $graph = new DirectedAdjacencyList();
     foreach ($phiNodes as $phi) {
         $result = $phi->getResult();
         foreach ($phi->getValues() as $value) {
             $graph->ensureArc($value, $result);
         }
     }
     $cycles = $graph->getCycles();
     foreach ($cycles as $cycle) {
         if ($this->areAllUnknown($cycle)) {
             // All are unknown, process!
             $types = array();
             foreach ($cycle as $component) {
                 foreach (Helper::getInboundNodes($component, $graph) as $node) {
                     if (in_array($node, $cycle, true)) {
                         continue;
                     }
                     $types[] = $node->getType()->getType();
                 }
             }
             $types = array_unique($types);
             $newType = 0;
             switch (count($types)) {
                 case 1:
                     if ($types[0] != Type::TYPE_UNKNOWN) {
                         $newType = $types[0];
                     }
                     break;
                 case 2:
                     if (in_array(Type::TYPE_NUMERIC, $types) && in_array(Type::TYPE_LONG, $types)) {
                         $newType = Type::TYPE_NUMERIC;
                     } elseif (in_array(Type::TYPE_NUMERIC, $types) && in_array(Type::TYPE_DOUBLE, $types)) {
                         $newType = Type::TYPE_DOUBLE;
                     }
                     break;
             }
             if ($newType) {
                 foreach ($cycle as $component) {
                     $component->setType(new Type($newType));
                 }
                 return true;
             }
         }
     }
     return false;
 }