Hoa central
Variable.php
Go to the documentation of this file.
1 <?php
2 
38 
39 use Hoa\Core;
40 use Hoa\Math;
41 use Hoa\Praspel;
42 use Hoa\Realdom;
43 use Hoa\Visitor;
44 
53 class Variable
54  implements Visitor\Element,
56 {
62  protected $_name = null;
63 
69  protected $_local = false;
70 
76  protected $_clause = null;
77 
83  protected $_value = null;
84 
90  protected $_domains = null;
91 
97  protected $_refDomains = null;
98 
104  protected $_alias = null;
105 
111  protected $_constraints = [];
112 
119  protected $_tmpConstraintsType = null;
120 
127  protected $_tmpConstraintsIndex = null;
128 
129 
130 
140  public function __construct(
141  $name,
142  $local,
143  Praspel\Model\Clause $clause = null
144  ) {
145  if (('\old' === substr($name, 0, 4) ||
146  '\result' === $name) &&
147  !($clause instanceof Praspel\Model\Ensures)) {
148  throw new Praspel\Exception\Model(
149  '\old(…) and \result are only allowed in @ensures, ' .
150  'given %s in @%s.',
151  0,
152  [$name, $clause->getName()]
153  );
154  }
155 
156  $this->_name = $name;
157  $this->_local = $local;
158  $this->_clause = $clause;
159  $this->_refDomains = &$this->_domains;
160 
161  return;
162  }
163 
170  public function setValue($value)
171  {
172  $old = $this->_value;
173  $this->_value = $value;
174 
175  return $old;
176  }
177 
183  public function &getValue()
184  {
185  return $this->_value;
186  }
187 
197  public function __set($name, $value)
198  {
199  if ('in' !== $name) {
200  $this->$name = $value;
201 
202  return;
203  }
204 
205  $onDomains = $this->_domains === $this->_refDomains;
206 
207  if (true === $onDomains &&
208  !empty($this->_domains)) {
209  throw new Praspel\Exception\Model(
210  'Variable $%s has already declared domains.',
211  1,
212  $this->getName()
213  );
214  }
215 
216  if (!($value instanceof Realdom\Disjunction)) {
217  $value = realdom()->const($value);
218  }
219 
220  $this->_refDomains = $value;
221 
222  if (false === $onDomains) {
223  $this->_domains->propagateConstraints(
224  $this->_tmpConstraintsType,
225  $this->_tmpConstraintsIndex
226  );
227 
228  $this->_tmpConstraintsType = null;
229  $this->_tmpConstraintsIndex = null;
230  }
231 
232  unset($this->_refDomains);
233  $this->_refDomains = &$this->_domains;
234 
235  $this->_domains->setHolder($this);
236 
237  foreach ($this->_domains as $domain) {
238  $domain->setConstraints($this->_constraints);
239  }
240 
241  return;
242  }
243 
244  /*
245  * Call the predicate() method on realistic domains.
246  *
247  * @access public
248  * @param mixed $q Sampled value.
249  * @return boolean
250  */
251  public function predicate($q = null)
252  {
253  if (null === $q) {
254  $q = $this->getValue();
255  }
256 
257  return $this->getDomains()->predicate($q);
258  }
259 
267  public function sample(Math\Sampler $sampler = null)
268  {
269  return $this->getDomains()->sample($sampler);
270  }
271 
277  public function reset()
278  {
279  return $this->getDomains()->reset();
280  }
281 
288  public function key($scalar)
289  {
290  if (!isset($this->_constraints['key'])) {
291  $this->_constraints['key'] = [];
292  }
293 
294  unset($this->_refDomains);
295  $handle = &$this->_constraints['key'][];
296  $handle[0] = realdom()->const($scalar);
297  $this->_refDomains = &$handle[1];
298 
299  end($this->_constraints['key']);
300  $this->_tmpConstraintsType = 'key';
301  $this->_tmpConstraintsIndex = key($this->_constraints['key']);
302 
303  return $this;
304  }
305 
312  public function contains($scalar)
313  {
314  if (!isset($this->_constraints['contains'])) {
315  $this->_constraints['contains'] = [];
316  }
317 
318  $this->_constraints['contains'][] = realdom()->const($scalar);
319 
320  return $this;
321  }
322 
329  public function is()
330  {
331  if (!isset($this->_constraints['is'])) {
332  $this->_constraints['is'] = [];
333  }
334 
335  $this->_constraints['is'] = array_merge(
336  $this->_constraints['is'],
337  func_get_args()
338  );
339 
340  return $this;
341  }
342 
350  public function domainof($variable)
351  {
352  $variables = $this->getClause()->getLocalVariables();
353 
354  if (!isset($variables[$variable])) {
355  throw new Praspel\Exception\Model(
356  'Variable $%s does not exist, cannot alias domains to $%s.',
357  2,
358  [$variable, $this->getName()]
359  );
360  }
361 
362  if (!empty($this->_domains)) {
363  throw new Praspel\Exception\Model(
364  'Variable $%s already has domains, cannot alias new domains ' .
365  'from $%s.',
366  3,
367  [$this->getName(), $variable]
368  );
369  }
370 
371  $this->_alias = $variable;
372  $this->_domains = &$variables[$variable]->getDomains();
373 
374  return $this;
375  }
376 
382  public function &getDomains()
383  {
384  return $this->_domains;
385  }
386 
392  public function &getHeld()
393  {
394  return $this->getDomains();
395  }
396 
402  public function getName()
403  {
404  return $this->_name;
405  }
406 
412  public function isLocal()
413  {
414  return $this->_local;
415  }
416 
422  public function getConstraints()
423  {
424  return $this->_constraints;
425  }
426 
432  public function getAlias()
433  {
434  return $this->_alias;
435  }
436 
442  public function getClause()
443  {
444  return $this->_clause;
445  }
446 
455  public function accept(
456  Visitor\Visit $visitor,
457  &$handle = null,
458  $eldnah = null
459  ) {
460  return $visitor->visit($this, $handle, $eldnah);
461  }
462 }
463 
467 Core\Consistency::flexEntity('Hoa\Praspel\Model\Variable\Variable');
sample(Math\Sampler $sampler=null)
Definition: Variable.php:267
accept(Visitor\Visit $visitor, &$handle=null, $eldnah=null)
Definition: Variable.php:455
__construct($name, $local, Praspel\Model\Clause $clause=null)
Definition: Variable.php:140