Completed
Push — master ( 68be21...073c54 )
by Kévin
02:41
created

Compiler::compileToSource()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 33
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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