Test Setup Failed
Push — master ( 1595cb...1df194 )
by Kirill
02:11
created

HashTable   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 14
eloc 25
dl 0
loc 105
rs 10
c 1
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A has() 0 11 4
A defined() 0 4 2
A get() 0 13 4
A addMany() 0 7 2
A add() 0 5 1
1
<?php
2
3
/**
4
 * This file is part of Railt package.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Railt\SDL\Backend;
13
14
use Phplrt\Source\Exception\NotAccessibleException;
15
use Railt\SDL\Backend\HashTable\ValueFactory;
16
use Railt\SDL\Exception\RuntimeErrorException;
17
use Railt\SDL\Frontend\Ast\Node;
18
use Railt\TypeSystem\Value\ValueInterface;
19
20
/**
21
 * Class HashTable
22
 */
23
final class HashTable implements HashTableInterface
24
{
25
    /**
26
     * @var array|ValueInterface[]
27
     */
28
    private array $variables = [];
29
30
    /**
31
     * @var ValueFactory
32
     */
33
    private ValueFactory $factory;
34
35
    /**
36
     * @var HashTableInterface|null
37
     */
38
    private ?HashTableInterface $parent;
39
40
    /**
41
     * HashTable constructor.
42
     *
43
     * @param ValueFactory $factory
44
     * @param array|ValueInterface[] $variables
45
     * @param HashTableInterface|null $parent
46
     */
47
    public function __construct(ValueFactory $factory, array $variables = [], HashTableInterface $parent = null)
48
    {
49
        $this->parent = $parent;
50
        $this->factory = $factory;
51
52
        $this->addMany($variables);
53
    }
54
55
    /**
56
     * @param string $name
57
     * @return bool
58
     */
59
    public function has(string $name): bool
60
    {
61
        if ($this->defined($name)) {
62
            return true;
63
        }
64
65
        if ($this->parent && $this->parent->has($name)) {
66
            return true;
67
        }
68
69
        return false;
70
    }
71
72
    /**
73
     * @param string $name
74
     * @return bool
75
     */
76
    private function defined(string $name): bool
77
    {
78
        return isset($this->variables[$name])
79
            || \array_key_exists($name, $this->variables);
80
    }
81
82
    /**
83
     * @param iterable $variables
84
     * @return $this
85
     */
86
    public function addMany(iterable $variables): self
87
    {
88
        foreach ($variables as $name => $value) {
89
            $this->add($name, $value);
90
        }
91
92
        return $this;
93
    }
94
95
    /**
96
     * @param string $name
97
     * @param mixed $value
98
     * @return $this
99
     */
100
    public function add(string $name, $value): self
101
    {
102
        $this->variables[$name] = $value;
103
104
        return $this;
105
    }
106
107
    /**
108
     * @param string $name
109
     * @param Node|null $ctx
110
     * @return ValueInterface
111
     * @throws NotAccessibleException
112
     * @throws RuntimeErrorException
113
     * @throws \RuntimeException
114
     */
115
    public function get(string $name, Node $ctx = null): ValueInterface
116
    {
117
        if ($this->defined($name)) {
118
            return $this->factory->make($this->variables[$name], $ctx);
119
        }
120
121
        if ($this->parent && $this->parent->has($name)) {
122
            return $this->parent->get($name, $ctx);
123
        }
124
125
        $error = \sprintf('Undefined variable $%s', $name);
126
127
        throw RuntimeErrorException::fromAst($error, $ctx);
128
    }
129
}
130