def lookup_by_path(path, opts = {})
      path = path.to_s
      namespace = opts[:namespace]
      inheritance = opts[:inheritance] || false
      proxy_fallback = opts[:proxy_fallback] || false
      type = opts[:type]

      if namespace.is_a?(CodeObjects::Proxy)
        return proxy_fallback ? CodeObjects::Proxy.new(namespace, path, type) : nil
      end

      if namespace == :root || !namespace
        namespace = @registry.root
      else
        namespace = namespace.parent until namespace.is_a?(CodeObjects::NamespaceObject)
      end
      orignamespace = namespace

      if path =~ /\A#{default_separator}/
        path = $'
        namespace = @registry.root
        orignamespace = @registry.root
      end

      resolved = nil
      lexical_lookup = 0
      while namespace && !resolved
        resolved = lookup_path_direct(namespace, path, type)
        resolved ||= lookup_path_inherited(namespace, path, type) if inheritance
        break if resolved
        namespace = namespace.parent
        lexical_lookup += 1
      end

      # method objects cannot be resolved through lexical lookup by more than 1 ns
      if lexical_lookup > 1 && resolved.is_a?(CodeObjects::MethodObject)
        resolved = nil
      end

      if proxy_fallback
        resolved ||= CodeObjects::Proxy.new(orignamespace, path, type)
      end

      resolved
    end
def lookup_by_path(path, opts = {})
      path = path.to_s
      namespace = opts[:namespace]
      inheritance = opts[:inheritance] || false
      proxy_fallback = opts[:proxy_fallback] || false
      type = opts[:type]

      if namespace.is_a?(CodeObjects::Proxy)
        return proxy_fallback ? CodeObjects::Proxy.new(namespace, path, type) : nil
      end

      if namespace == :root || !namespace
        namespace = @registry.root
      else
        namespace = namespace.parent until namespace.is_a?(CodeObjects::NamespaceObject)
      end
      orignamespace = namespace

      if path =~ /\A#{default_separator}/
        path = $'
        namespace = @registry.root
        orignamespace = @registry.root
      end

      resolved = nil
      lexical_lookup = 0
      while namespace && !resolved
        resolved = lookup_path_direct(namespace, path, type)
        resolved ||= lookup_path_inherited(namespace, path, type) if inheritance
        break if resolved
        namespace = namespace.parent
        lexical_lookup += 1
      end

      # method objects cannot be resolved through lexical lookup by more than 1 ns
      if lexical_lookup > 1 && resolved.is_a?(CodeObjects::MethodObject)
        resolved = nil
      end

      if proxy_fallback
        resolved ||= CodeObjects::Proxy.new(orignamespace, path, type)
      end

      resolved
    end
Creates a new resolver object for a registry.

 @param registry [Registry] only set this if customizing the registry
   object
 Performs a lookup on a given path in the registry. Resolution will occur
 in a similar way to standard Ruby identifier resolution, doing lexical
 lookup, as well as (optionally) through the inheritance chain. A proxy
 object can be returned if the lookup fails for future resolution. The
 proxy will be type hinted with the +type+ used in the original lookup.

 @option opts namespace [CodeObjects::Base, :root, nil] (nil) the namespace
   object to start searching from. If root or nil is provided, {Registry.root}
   is assumed.
 @option opts inheritance [Boolean] (false) whether to perform lookups through
   the inheritance chain (includes mixins)
 @option opts proxy_fallback [Boolean] (false) when true, a proxy is returned
   if no match is found
 @option opts type [Symbol] (nil) an optional type hint for the resolver
   to consider when performing a lookup. If a type is provided and the
   resolved object's type does not match the hint, the object is discarded.
 @return [CodeObjects::Base, CodeObjects::Proxy, nil] the first object
   that matches the path lookup. If proxy_fallback is provided, a proxy
   object will be returned in the event of no match, otherwise nil will
   be returned.
 @example A lookup from root
   resolver.lookup_by_path("A::B::C")
 @example A lookup from the A::B namespace
   resolver.lookup_by_path("C", namespace: P("A::B"))
 @example A lookup on a method through the inheritance tree
   resolver.lookup_by_math("A::B#foo", inheritance: true)