Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 28 additions & 28 deletions src/TrinaryLogic.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,30 +39,36 @@
final class TrinaryLogic
{

private const YES = 1;
private const MAYBE = 0;
private const NO = -1;
private const YES = 3;
private const MAYBE = 1;
private const NO = 0;

/** @var self[] */
private static array $registry = [];

private static self $YES;

private static self $MAYBE;

private static self $NO;

private function __construct(private int $value)
{
}

public static function createYes(): self
{
return self::$registry[self::YES] ??= new self(self::YES);
return self::$YES ??= (self::$registry[self::YES] ??= new self(self::YES));
}

public static function createNo(): self
{
return self::$registry[self::NO] ??= new self(self::NO);
return self::$NO ??= (self::$registry[self::NO] ??= new self(self::NO));
}

public static function createMaybe(): self
{
return self::$registry[self::MAYBE] ??= new self(self::MAYBE);
return self::$MAYBE ??= (self::$registry[self::MAYBE] ??= new self(self::MAYBE));
}

public static function createFromBoolean(bool $value): self
Expand All @@ -73,8 +79,7 @@ public static function createFromBoolean(bool $value): self

private static function create(int $value): self
{
self::$registry[$value] ??= new self($value);
return self::$registry[$value];
return self::$registry[$value] ??= new self($value);
}

/**
Expand Down Expand Up @@ -113,17 +118,13 @@ public function toBooleanType(): BooleanType
return new ConstantBooleanType($this->value === self::YES);
}

public function and(self ...$operands): self
public function and(?self $operand = null, self ...$rest): self
{
$min = $this->value;
foreach ($operands as $operand) {
if ($operand->value >= $min) {
continue;
}

$min = $operand->value;
$min = $this->value & ($operand !== null ? $operand->value : self::YES);
foreach ($rest as $restOperand) {
$min &= $restOperand->value;
}
return self::create($min);
return self::$registry[$min] ??= new self($min);
}

/**
Expand Down Expand Up @@ -153,17 +154,13 @@ public function lazyAnd(
return $this->and(...$results);
}

public function or(self ...$operands): self
public function or(?self $operand = null, self ...$rest): self
{
$max = $this->value;
foreach ($operands as $operand) {
if ($operand->value < $max) {
continue;
}

$max = $operand->value;
$max = $this->value | ($operand !== null ? $operand->value : self::NO);
foreach ($rest as $restOperand) {
$max |= $restOperand->value;
}
return self::create($max);
return self::$registry[$max] ??= new self($max);
}

/**
Expand Down Expand Up @@ -247,7 +244,7 @@ public static function maxMin(self ...$operands): self
throw new ShouldNotHappenException();
}
$operandValues = array_column($operands, 'value');
return self::create(max($operandValues) > 0 ? 1 : min($operandValues));
return self::create(max($operandValues) > self::MAYBE ? self::YES : min($operandValues));
}

/**
Expand Down Expand Up @@ -275,7 +272,10 @@ public static function lazyMaxMin(

public function negate(): self
{
return self::create(-$this->value);
// 0b11 >> 0 == 0b11 (3)
// 0b11 >> 1 == 0b01 (1)
// 0b11 >> 3 == 0b00 (0)
return self::create(3 >> $this->value);
}

public function equals(self $other): bool
Expand Down
Loading