Test Failed
Push — master ( 2d53c5...8b1ae1 )
by Kirill
02:39
created

Opcode::getOperands()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\SDL\Frontend\IR;
11
12
use Railt\Io\Readable;
13
use Railt\Reflection\Contracts\TypeInterface;
14
use Railt\SDL\Frontend\AST\Value\ValueInterface;
15
16
/**
17
 * Class Opcode
18
 */
19
class Opcode implements OpcodeInterface
20
{
21
    /**
22
     * @var array|string[]|null
23
     */
24
    protected static $opcodes;
25
26
    /**
27
     * @var int
28
     */
29
    protected $operation;
30
31
    /**
32
     * @var array
33
     */
34
    protected $operands;
35
36
    /**
37
     * Opcode constructor.
38
     * @param int $operation
39
     * @param mixed ...$operands
40
     */
41
    public function __construct(int $operation, ...$operands)
42
    {
43
        $this->operation = $operation;
44
        $this->operands = $operands;
45
    }
46
47
    /**
48
     * @return int
49
     */
50
    public function getOperation(): int
51
    {
52
        return $this->operation;
53
    }
54
55
    /**
56
     * @return array
57
     */
58
    public function getOperands(): array
59
    {
60
        return $this->operands;
61
    }
62
63
    /**
64
     * @param int $id
65
     * @param Readable $readable
66
     * @param int $offset
67
     * @return JoinableOpcode
68
     */
69
    public function join(int $id, Readable $readable, int $offset = 0): JoinableOpcode
70
    {
71
        return new JoinableOpcode($this, $id, $readable, $offset);
72
    }
73
74
    /**
75
     * @param mixed $value
76
     * @return string
77
     */
78
    protected function operandToString($value): string
79
    {
80
        switch (true) {
81
            case $value instanceof ValueInterface:
82
                return $value->toString();
83
84
            case $value instanceof TypeInterface:
85
                return '$' . $value->getName();
86
87
            case $value instanceof JoinableOpcode:
88
                return '!' . $value->getId();
89
90
            case $value instanceof OpcodeInterface:
91
                return $value->getName();
92
93
            case $value instanceof Readable:
94
                return 'file:' . $value->getPathname();
95
96
            case \is_bool($value):
97
                return '(php:bool)' . ($value ? 'true' : 'false');
98
99
            case $value === null:
100
                return '(php:null)null';
101
102
            case \is_scalar($value):
103
                $type = \gettype($value);
104
                $minified = \preg_replace('/\s+/', ' ', (string)$value);
105
                return '(php:' . $type . ')"' . \addcslashes($minified, '"') . '"';
106
107
            case \is_object($value):
108
                return \get_class($value) . '#' . \spl_object_hash($value);
109
        }
110
111
        return '';
112
    }
113
114
    /**
115
     * @return string
116
     */
117
    public function __toString(): string
118
    {
119
        $operands = \array_map(function ($value): string {
120
            return $this->operandToString($value);
121
        }, $this->operands);
122
123
        return \sprintf('%-20s %-20s', $this->getName(), '{' . \implode(', ', $operands) . '}');
124
    }
125
126
    /**
127
     * @return string
128
     */
129
    public function getName(): string
130
    {
131
        return static::getOperationName($this->operation);
132
    }
133
134
    /**
135
     * @param int $operation
136
     * @return string
137
     */
138
    public static function getOperationName(int $operation): string
139
    {
140
        if (static::$opcodes === null) {
141
            static::$opcodes = [];
142
143
            try {
144
                $reflection = new \ReflectionClass(static::class);
145
                foreach ($reflection->getConstants() as $name => $value) {
146
                    static::$opcodes[$value] = $name;
147
                }
148
            } catch (\ReflectionException $e) {
149
                return 'RL_NOP';
150
            }
151
        }
152
153
        return static::$opcodes[$operation] ?? static::$opcodes[static::RL_NOP];
154
    }
155
}
156