2016-12-27 19:58:58 +01:00
|
|
|
|
<?php
|
|
|
|
|
namespace Psalm;
|
|
|
|
|
|
|
|
|
|
class Clause
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* An array of strings of the form
|
|
|
|
|
* [
|
2017-10-22 17:57:41 +02:00
|
|
|
|
* '$a' => ['falsy'],
|
|
|
|
|
* '$b' => ['!falsy'],
|
2016-12-27 19:58:58 +01:00
|
|
|
|
* '$c' => ['!null'],
|
|
|
|
|
* '$d' => ['string', 'int']
|
|
|
|
|
* ]
|
|
|
|
|
*
|
|
|
|
|
* representing the formula
|
|
|
|
|
*
|
|
|
|
|
* !$a || $b || $c !== null || is_string($d) || is_int($d)
|
|
|
|
|
*
|
|
|
|
|
* @var array<string, array<string>>
|
|
|
|
|
*/
|
|
|
|
|
public $possibilities;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An array of things that are not true
|
|
|
|
|
* [
|
2017-10-22 17:57:41 +02:00
|
|
|
|
* '$a' => ['!falsy'],
|
|
|
|
|
* '$b' => ['falsy'],
|
2016-12-27 19:58:58 +01:00
|
|
|
|
* '$c' => ['null'],
|
|
|
|
|
* '$d' => ['!string', '!int']
|
|
|
|
|
* ]
|
|
|
|
|
* represents the formula
|
|
|
|
|
*
|
|
|
|
|
* $a && !$b && $c === null && !is_string($d) && !is_int($d)
|
|
|
|
|
*
|
|
|
|
|
* @var array<string, array<string>>|null
|
|
|
|
|
*/
|
|
|
|
|
public $impossibilities;
|
|
|
|
|
|
|
|
|
|
/** @var bool */
|
|
|
|
|
public $wedge;
|
|
|
|
|
|
|
|
|
|
/** @var bool */
|
|
|
|
|
public $reconcilable;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param array<string, array<string>> $possibilities
|
|
|
|
|
* @param bool $wedge
|
|
|
|
|
* @param bool $reconcilable
|
|
|
|
|
*/
|
|
|
|
|
public function __construct(array $possibilities, $wedge = false, $reconcilable = true)
|
|
|
|
|
{
|
|
|
|
|
$this->possibilities = $possibilities;
|
|
|
|
|
$this->wedge = $wedge;
|
|
|
|
|
$this->reconcilable = $reconcilable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param Clause $other_clause
|
2017-05-27 02:16:18 +02:00
|
|
|
|
*
|
2016-12-27 19:58:58 +01:00
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function contains(Clause $other_clause)
|
|
|
|
|
{
|
2017-03-20 04:26:45 +01:00
|
|
|
|
if (count($other_clause->possibilities) > count($this->possibilities)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-27 19:58:58 +01:00
|
|
|
|
foreach ($other_clause->possibilities as $var => $possible_types) {
|
|
|
|
|
if (!isset($this->possibilities[$var]) || count(array_diff($possible_types, $this->possibilities[$var]))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets a hash of the object – will be unique if we're unable to easily reconcile this with others
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public function getHash()
|
|
|
|
|
{
|
|
|
|
|
ksort($this->possibilities);
|
|
|
|
|
|
2017-02-02 06:45:23 +01:00
|
|
|
|
foreach ($this->possibilities as &$possible_types) {
|
2016-12-27 19:58:58 +01:00
|
|
|
|
sort($possible_types);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-18 16:18:04 +02:00
|
|
|
|
$possibility_string = json_encode($this->possibilities);
|
|
|
|
|
if (!$possibility_string) {
|
|
|
|
|
throw new \LogicException('Error converting possibilities to json');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return md5($possibility_string) .
|
2016-12-27 19:58:58 +01:00
|
|
|
|
($this->wedge || !$this->reconcilable ? spl_object_hash($this) : '');
|
|
|
|
|
}
|
|
|
|
|
}
|