22declare(strict_types=1);
 
   26use 
function array_map;
 
   28use 
function mb_strtoupper;
 
   29use 
function preg_match;
 
   43    private static $members = 
null;
 
   45    private static function verifyName(
string $name) : 
void{
 
   46        if(preg_match(
'/^(?!\d)[A-Za-z\d_]+$/u', $name) === 0){
 
   47            throw new \InvalidArgumentException(
"Invalid member name \"$name\", should only contain letters, numbers and underscores, and must not start with a number");
 
   56    private static function _registryRegister(
string $name, 
object $member) : 
void{
 
   57        if(self::$members === 
null){
 
   60        self::verifyName($name);
 
   61        $upperName = mb_strtoupper($name);
 
   62        if(isset(self::$members[$upperName])){
 
   63            throw new \InvalidArgumentException(
"\"$upperName\" is already reserved");
 
   65        self::$members[$upperName] = $member;
 
   73    abstract protected static function setup() : void;
 
   80    protected static function checkInit() : void{
 
   81        if(self::$members === null){
 
   90    private static function _registryFromString(
string $name) : object{
 
   92        if(self::$members === 
null){
 
   93            throw new AssumptionFailedError(self::class . 
"::checkInit() did not initialize self::\$members correctly");
 
   95        $upperName = mb_strtoupper($name);
 
   96        if(!isset(self::$members[$upperName])){
 
   97            throw new \InvalidArgumentException(
"No such registry member: " . self::class . 
"::" . $upperName);
 
   99        return self::preprocessMember(self::$members[$upperName]);
 
  102    protected static function preprocessMember(
object $member) : object{
 
  114        if(count($arguments) > 0){
 
  115            throw new \ArgumentCountError(
"Expected exactly 0 arguments, " . count($arguments) . 
" passed");
 
  119        if(self::$members !== 
null && isset(self::$members[$name])){
 
  120            return self::preprocessMember(self::$members[$name]);
 
  125            return self::_registryFromString($name);
 
  126        }
catch(\InvalidArgumentException $e){
 
  127            throw new \Error($e->getMessage(), 0, $e);
 
 
  135    private static function _registryGetAll() : array{
 
  137        return array_map(self::preprocessMember(...), self::$members ?? 
throw new AssumptionFailedError(self::class . 
"::checkInit() did not initialize self::\$members correctly"));
 
static __callStatic($name, $arguments)