Completed
Push — master ( b2a65d...63a169 )
by Kirill
02:18
created

NumberValueBuilder::parseBin()   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 1
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\Builder\Value;
11
12
use Railt\Parser\Ast\LeafInterface;
13
use Railt\Parser\Ast\RuleInterface;
14
use Railt\SDL\Frontend\Builder\BaseBuilder;
15
use Railt\SDL\Frontend\Context\ContextInterface;
16
use Railt\SDL\Frontend\Parser;
17
use Railt\SDL\IR\SymbolTable\Value;
18
use Railt\SDL\IR\SymbolTable\ValueInterface;
19
use Railt\SDL\IR\Type;
20
21
/**
22
 * Class NumberValueBuilder
23
 */
24
class NumberValueBuilder extends BaseBuilder
25
{
26
    /**
27
     * @param RuleInterface $rule
28
     * @return bool
29
     */
30
    public function match(RuleInterface $rule): bool
31
    {
32
        return $rule->getName() === 'NumberValue';
33
    }
34
35
    /**
36
     * @param ContextInterface $ctx
37
     * @param RuleInterface $rule
38
     * @return ValueInterface
39
     */
40
    public function reduce(ContextInterface $ctx, RuleInterface $rule): ValueInterface
41
    {
42
        $value = $this->parse($rule);
43
44
        return new Value($value, \is_int($value) ? Type::int() : Type::float());
0 ignored issues
show
Bug introduced by
It seems like \is_int($value) ? \Railt...lt\SDL\IR\Type::float() can also be of type object<Railt\SDL\IR\Type...untimeTypeConstructors>; however, Railt\SDL\IR\SymbolTable\Value::__construct() does only seem to accept object<Railt\SDL\IR\Type\TypeInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
45
    }
46
47
    /**
48
     * @param RuleInterface $rule
49
     * @return float|int
50
     */
51
    private function parse(RuleInterface $rule)
52
    {
53
        /** @var LeafInterface $value */
54
        $value = $rule->getChild(0);
55
56
        switch (true) {
57
            case $this->isHex($value):
58
                return $this->parseHex($value->getValue(1));
59
60
            case $this->isBinary($value):
61
                return $this->parseBin($value->getValue(1));
62
63
            case $this->isExponential($value):
64
                return $this->parseExponential($value->getValue());
65
66
            case $this->isFloat($value):
67
                return $this->parseFloat($value->getValue());
68
69
            case $this->isInt($value):
70
                return $this->parseInt($value->getValue());
71
        }
72
73
        return (float)$value->getValue();
74
    }
75
76
    /**
77
     * @param LeafInterface $leaf
78
     * @return bool
79
     */
80
    private function isHex(LeafInterface $leaf): bool
81
    {
82
        return $leaf->getName() === Parser::T_HEX_NUMBER;
83
    }
84
85
    /**
86
     * @param string $value
87
     * @return int
88
     */
89
    private function parseHex(string $value): int
90
    {
91
        return \hexdec($value);
92
    }
93
94
    /**
95
     * @param LeafInterface $leaf
96
     * @return bool
97
     */
98
    private function isBinary(LeafInterface $leaf): bool
99
    {
100
        return $leaf->getName() === Parser::T_BIN_NUMBER;
101
    }
102
103
    /**
104
     * @param string $value
105
     * @return int
106
     */
107
    private function parseBin(string $value): int
108
    {
109
        return \bindec($value);
110
    }
111
112
    /**
113
     * @param LeafInterface $leaf
114
     * @return bool
115
     */
116
    private function isExponential(LeafInterface $leaf): bool
117
    {
118
        return \substr_count(\mb_strtolower($leaf->getValue()), 'e') !== 0;
119
    }
120
121
    /**
122
     * @param string $value
123
     * @return float
124
     */
125
    private function parseExponential(string $value): float
126
    {
127
        return (float)$value;
128
    }
129
130
    /**
131
     * @param LeafInterface $leaf
132
     * @return bool
133
     */
134
    private function isFloat(LeafInterface $leaf): bool
135
    {
136
        return \substr_count($leaf->getValue(), '.') !== 0;
137
    }
138
139
    /**
140
     * @param string $value
141
     * @return float
142
     */
143
    private function parseFloat(string $value): float
144
    {
145
        return (float)$value;
146
    }
147
148
    /**
149
     * @param LeafInterface $leaf
150
     * @return bool
151
     */
152
    private function isInt(LeafInterface $leaf): bool
153
    {
154
        return $leaf->getName() === Parser::T_NUMBER && \substr_count($leaf->getValue(), '.') === 0;
155
    }
156
157
    /**
158
     * @param string $value
159
     * @return int
160
     */
161
    private function parseInt(string $value): int
162
    {
163
        return $value >> 0;
164
    }
165
}
166