Advent of code 2015/7
Ajax Direct

Answer

Part 1 :
Part 2 :
function value($var, $wires)
{
    if (is_numeric($var)) return (int) $var;
    if (is_int($wires[$var] ?? null)) return $wires[$var];
    return null;
}

function compute($calc, $wires)
{
    if (is_numeric($calc)) return (int) $calc;
    if (count($calc) == 1) return !is_null($a = value($calc[0], $wires)) ? $a : $calc;
    if ($calc[0] == "NOT") return !is_null($a = value($calc[1], $wires)) ? 65535 - $a : $calc;

    $a = value($calc[0], $wires);
    $b = value($calc[2], $wires);
    if (is_null($a) || is_null($b)) return $calc;

    switch ($calc[1]) {
        case "AND":    return $a & $b;
        case "OR":     return $a | $b;
        case "LSHIFT": return $a << $b;
        case "RSHIFT": return $a >> $b;
    }
}

function solve($wires)
{
    while (!is_int($wires["a"])) {
        foreach ($wires as $letter=>&$calc) {
            if (is_int($calc)) continue;
            $wires[$letter] = compute($calc, $wires);
        }
    }
    return $wires["a"];
}

// =============================================================================
// > SOLUTIONS
// =============================================================================
$wires = [];
foreach ($input->lines as $line) {
    preg_match('/^([^-]+) -> ([a-z]+)$/', $line, $matches);
    $wires[$matches[2]] = explode(" ", $matches[1]);
}

$solution_1 = solve($wires);

$wires["b"] = $solution_1;
$solution_2 = solve($wires);