public static function call(string $function, Arguments $arguments)
    {
        $mocks = self::$mocks;

        $mocks = array_filter($mocks, function (MockedFunction $mock) use ($function) {
            return $mock->getFunctionName() === $function;
        });

        # First try functions that expect the exact arguments, and have expectations that haven't been called yet
        foreach ($mocks as $mock) {
            if ($mock->matchArguments($arguments)) {
                if ($mock->canCall()) {
                    return $mock->call($arguments);
                }
            }
        }

        # Then try functions that expect any arguments, and have expectations that haven't been called yet
        foreach ($mocks as $mock) {
            if ($mock->canAcceptArguments($arguments)) {
                if ($mock->canCall()) {
                    return $mock->call($arguments);
                }
            }
        }

        # Now try functions that expect the exact arguments (so we can give an accurate error message)
        foreach ($mocks as $mock) {
            if ($mock->matchArguments($arguments)) {
                return $mock->call($arguments);
            }
        }

        # Finally try functions that expect any arguments (just so we can throw an error as there are no expectations left)
        foreach ($mocks as $mock) {
            if ($mock->canAcceptArguments($arguments)) {
                return $mock->call($arguments);
            }
        }

        throw new ExpectationException("Unexpected argument list for {$function}({$arguments})");
    }