public function ref(...$argv): Reference
	{
		$type = $argv[0];

		// Clone if Reference is given
		if ($type instanceof Reference) {
			if (count($argv) != 1) {
				throw new InvalidArgumentException('The first argument is a Reference and more than one argument given.');
			}
			return clone $type;
		}

		// Get arguments
		if (is_array($type)) {
			if (count($argv) != 1) {
				throw new InvalidArgumentException('The first argument is an array and more than one argument given.');
			}
		}

		// Decode arguments to machine type and machine-specific ID
		foreach ($this->backends as $b => $backend) {
			$id = array_slice($argv, 1);
			if ($backend->inferMachineType($argv, $type, $id)) {
				// Create reference
				$m = $backend->getMachine($this, $type);
				if ($m === null) {
					throw new RuntimeException('Cannot create machine: '.$type);
				}
				$ref = $m->ref($id);

				// Emit events
				if ($this->debug_logger) {
					$this->debug_logger->afterReferenceCreated($backend, $ref);
				}
				if ($this->after_reference_created) {
					$this->after_reference_created->emit($ref);
				}

				return $ref;
			}
		}

		throw new InvalidReferenceException('Cannot infer machine type: '.$type);
	}