Compiler   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 81
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 0
loc 81
c 0
b 0
f 0
wmc 7
lcom 1
cbo 5
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 4 1
A __construct() 0 5 1
A compile() 0 16 2
A compileToSource() 0 35 2
A getRuleIdentifier() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace RulerZ\Compiler;
6
7
use RulerZ\Executor\Executor;
8
use RulerZ\Parser\Parser;
9
10
class Compiler
11
{
12
    /**
13
     * @var Parser
14
     */
15
    private $parser;
16
17
    /**
18
     * @var Evaluator
19
     */
20
    private $evaluator;
21
22
    public static function create($cacheDirectory = null): self
23
    {
24
        return new static(new FileEvaluator($cacheDirectory));
25
    }
26
27
    public function __construct(Evaluator $evaluator)
28
    {
29
        $this->parser = new Parser();
30
        $this->evaluator = $evaluator;
31
    }
32
33
    public function compile(string $rule, CompilationTarget $target, Context $context): Executor
34
    {
35
        $context['rule_identifier'] = $this->getRuleIdentifier($target, $context, $rule);
36
        $context['executor_classname'] = 'Executor_'.$context['rule_identifier'];
37
        $context['executor_fqcn'] = '\RulerZ\Compiled\Executor\\Executor_'.$context['rule_identifier'];
38
39
        if (!class_exists($context['executor_fqcn'], false)) {
40
            $compiler = function () use ($rule, $target, $context) {
41
                return $this->compileToSource($rule, $target, $context);
42
            };
43
44
            $this->evaluator->evaluate($context['rule_identifier'], $compiler);
45
        }
46
47
        return new $context['executor_fqcn']();
48
    }
49
50
    protected function compileToSource(string $rule, CompilationTarget $compilationTarget, Context $context): string
51
    {
52
        $ast = $this->parser->parse($rule);
53
        $executorModel = $compilationTarget->compile($ast, $context);
54
55
        $flattenedTraits = implode(PHP_EOL, array_map(function ($trait) {
56
            return "\t".'use \\'.ltrim($trait, '\\').';';
57
        }, $executorModel->getTraits()));
58
59
        $extraCode = '';
60
        foreach ($executorModel->getCompiledData() as $key => $value) {
61
            $extraCode .= sprintf('private $%s = %s;'.PHP_EOL, $key, var_export($value, true));
62
        }
63
64
        $commentedRule = str_replace(PHP_EOL, PHP_EOL.'    // ', $rule);
65
66
        return <<<EXECUTOR
67
namespace RulerZ\Compiled\Executor;
68
69
use RulerZ\Executor\Executor;
70
71
class {$context['executor_classname']} implements Executor
72
{
73
    $flattenedTraits
74
75
    $extraCode
76
77
    // $commentedRule
78
    protected function execute(\$target, array \$operators, array \$parameters)
79
    {
80
        return {$executorModel->getCompiledRule()};
81
    }
82
}
83
EXECUTOR;
84
    }
85
86
    protected function getRuleIdentifier(CompilationTarget $compilationTarget, Context $context, string $rule): string
87
    {
88
        return hash('crc32b', get_class($compilationTarget).$rule.$compilationTarget->getRuleIdentifierHint($rule, $context));
89
    }
90
}
91