| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 | <?phpnamespace JmesPath;/** * Provides CLI debugging information for the AST and Compiler runtimes. */class DebugRuntime{    private $runtime;    private $out;    private $lexer;    private $parser;    public function __construct(callable $runtime, $output = null)    {        $this->runtime = $runtime;        $this->out = $output ?: STDOUT;        $this->lexer = new Lexer();        $this->parser = new Parser($this->lexer);    }    public function __invoke($expression, $data)    {        if ($this->runtime instanceof CompilerRuntime) {            return $this->debugCompiled($expression, $data);        }        return $this->debugInterpreted($expression, $data);    }    private function debugInterpreted($expression, $data)    {        return $this->debugCallback(            function () use ($expression, $data) {                $runtime = $this->runtime;                return $runtime($expression, $data);            },            $expression,            $data        );    }    private function debugCompiled($expression, $data)    {        $result = $this->debugCallback(            function () use ($expression, $data) {                $runtime = $this->runtime;                return $runtime($expression, $data);            },            $expression,            $data        );        $this->dumpCompiledCode($expression);        return $result;    }    private function dumpTokens($expression)    {        $lexer = new Lexer();        fwrite($this->out, "Tokens\n======\n\n");        $tokens = $lexer->tokenize($expression);        foreach ($tokens as $t) {            fprintf(                $this->out,                "%3d  %-13s  %s\n", $t['pos'], $t['type'],                json_encode($t['value'])            );        }        fwrite($this->out, "\n");    }    private function dumpAst($expression)    {        $parser = new Parser();        $ast = $parser->parse($expression);        fwrite($this->out, "AST\n========\n\n");        fwrite($this->out, json_encode($ast, JSON_PRETTY_PRINT) . "\n");    }    private function dumpCompiledCode($expression)    {        fwrite($this->out, "Code\n========\n\n");        $dir = sys_get_temp_dir();        $hash = md5($expression);        $functionName = "jmespath_{$hash}";        $filename = "{$dir}/{$functionName}.php";        fwrite($this->out, "File: {$filename}\n\n");        fprintf($this->out, file_get_contents($filename));    }    private function debugCallback(callable $debugFn, $expression, $data)    {        fprintf($this->out, "Expression\n==========\n\n%s\n\n", $expression);        $this->dumpTokens($expression);        $this->dumpAst($expression);        fprintf($this->out, "\nData\n====\n\n%s\n\n", json_encode($data, JSON_PRETTY_PRINT));        $startTime = microtime(true);        $result = $debugFn();        $total = microtime(true) - $startTime;        fprintf($this->out, "\nResult\n======\n\n%s\n\n", json_encode($result, JSON_PRETTY_PRINT));        fwrite($this->out, "Time\n====\n\n");        fprintf($this->out, "Total time:     %f ms\n\n", $total);        return $result;    }}
 |