# Path: supplement/objects.py
# def create_object(owner, obj, node=None):
#     node = node or ('undefined', None)
#     obj_type = type(obj)
# 
#     if node[0] == 'imported':
#         newobj = ImportedObject(node)
# 
#     elif obj_type == ModuleType:
#         return owner.project.get_module(obj.__name__)
# 
#     elif obj_type == ClassType or issubclass(obj_type, type):
#         newobj = ClassObject(node, obj)
# 
#     elif obj_type == FunctionType or obj_type == BuiltinFunctionType or obj_type == MethodDescriptor:
#         newobj = FunctionObject(node, obj)
# 
#     else:
#         newobj = InstanceObject(node, obj)
# 
#     newobj.project = owner.project
#     newobj.filename = owner.filename
# 
#     return newobj
# 
# class FakeInstanceObject(Object):
#     def __init__(self, class_obj):
#         self._class = class_obj
# 
#     def get_names(self):
#         return set(self._class.get_names()).union(set(self._class.get_assigned_attributes()))
# 
#     def __getitem__(self, name):
#         attrs = self._class.get_assigned_attributes()
#         if name in attrs:
#             return wrap_in_method(self, attrs[name].get_object())
# 
#         if name in self._class.get_names():
#             return wrap_in_method(self, self._class[name])
# 
#         raise KeyError(name)
# 
# Path: supplement/common.py
# class Value(GetObjectDelegate):
#     def __init__(self, scope, value):
#         self.scope = scope
#         self.value = value
# 
#     def get_object(self):
#         try:
#             return self._object
#         except AttributeError:
#             pass
# 
#         self._object = self.scope.eval(self.value, False)
#         return self._object
# 
# class UnknownObject(Object): pass
# 
# class Object(object):
#     def get_location(self):
#         raise NotImplementedError()
#         return None, None
# 
#     def get_names(self):
#         return set()
# 
#     def __contains__(self, name):
#         return name in self.get_names()
# 
#     def __getitem__(self, name):
#         return UnknownObject()
# 
#     def op_call(self, *args):
#         return UnknownObject()
# 
#     def op_getitem(self, idx):
#         return UnknownObject()
# 
#     def op_setitem(self, idx, value):
#         logging.getLogger(__name__).info('Try to set item on unknown object %s', self)
# 
#     def is_descriptor(self):
#         return False
# 
#     def get_assigned_attributes(self):
#         return {}
# 
#     def get_docstring(self):
#         return None
# 
#     def get_signature(self):
#         return None
# 
#     def get_scope(self):
#         return None
# 
#     def op_common_item(self):
#         return UnknownObject()
# 
# def create_object_from_seq_item(scope, expr):
#     seq = scope.eval(expr, False)
#     return seq.op_common_item()
# 
# def get_indexes_for_target(target, result, idx):
#     if isinstance(target, (ast.Tuple, ast.List)):
#         idx.append(0)
#         for r in target.elts:
#             get_indexes_for_target(r, result, idx)
#         idx.pop()
# 
#     else:
#         result.append((target, idx[:]))
#         if idx:
#             idx[-1] += 1
# 
#     return result
# 
# Path: supplement/names.py
# class RecursiveCallException(Exception):
#     def __init__(self, obj):
#         self.object = obj
# 
#     def is_called_by(self, obj):
#         return obj is self.object


import ast
import logging
from .objects import create_object, FakeInstanceObject
from .common import Value, UnknownObject, Object, create_object_from_seq_item, get_indexes_for_target
from .names import RecursiveCallException
        from .scope import InnerScope
        from .names import PostponedName, AssignedName
                from .tree import dump_tree

class Indexable(Object):
    def __init__(self, scope, obj, nodes):
        self.values = [Value(scope, r) for r in nodes]
        self.object = obj

    def op_getitem(self, idx):
        idx = idx.get_value()
        try:
            value = self.values[idx]
        except IndexError:
            return UnknownObject()

        return value.get_object()

    def op_common_item(self):
        try:
            value = self.values[0]
        except IndexError:
            return UnknownObject()

        return value.get_object()

    def get_names(self):
        return self.object.get_names()

    def __getitem__(self, name):
        return self.object[name]



# Path: supplement/objects.py
# def create_object(owner, obj, node=None):
#     node = node or ('undefined', None)
#     obj_type = type(obj)
# 
#     if node[0] == 'imported':
#         newobj = ImportedObject(node)
# 
#     elif obj_type == ModuleType:
#         return owner.project.get_module(obj.__name__)
# 
#     elif obj_type == ClassType or issubclass(obj_type, type):
#         newobj = ClassObject(node, obj)
# 
#     elif obj_type == FunctionType or obj_type == BuiltinFunctionType or obj_type == MethodDescriptor:
#         newobj = FunctionObject(node, obj)
# 
#     else:
#         newobj = InstanceObject(node, obj)
# 
#     newobj.project = owner.project
#     newobj.filename = owner.filename
# 
#     return newobj
# 
# class FakeInstanceObject(Object):
#     def __init__(self, class_obj):
#         self._class = class_obj
# 
#     def get_names(self):
#         return set(self._class.get_names()).union(set(self._class.get_assigned_attributes()))
# 
#     def __getitem__(self, name):
#         attrs = self._class.get_assigned_attributes()
#         if name in attrs:
#             return wrap_in_method(self, attrs[name].get_object())
# 
#         if name in self._class.get_names():
#             return wrap_in_method(self, self._class[name])
# 
#         raise KeyError(name)
# 
# Path: supplement/common.py
# class Value(GetObjectDelegate):
#     def __init__(self, scope, value):
#         self.scope = scope
#         self.value = value
# 
#     def get_object(self):
#         try:
#             return self._object
#         except AttributeError:
#             pass
# 
#         self._object = self.scope.eval(self.value, False)
#         return self._object
# 
# class UnknownObject(Object): pass
# 
# class Object(object):
#     def get_location(self):
#         raise NotImplementedError()
#         return None, None
# 
#     def get_names(self):
#         return set()
# 
#     def __contains__(self, name):
#         return name in self.get_names()
# 
#     def __getitem__(self, name):
#         return UnknownObject()
# 
#     def op_call(self, *args):
#         return UnknownObject()
# 
#     def op_getitem(self, idx):
#         return UnknownObject()
# 
#     def op_setitem(self, idx, value):
#         logging.getLogger(__name__).info('Try to set item on unknown object %s', self)
# 
#     def is_descriptor(self):
#         return False
# 
#     def get_assigned_attributes(self):
#         return {}
# 
#     def get_docstring(self):
#         return None
# 
#     def get_signature(self):
#         return None
# 
#     def get_scope(self):
#         return None
# 
#     def op_common_item(self):
#         return UnknownObject()
# 
# def create_object_from_seq_item(scope, expr):
#     seq = scope.eval(expr, False)
#     return seq.op_common_item()
# 
# def get_indexes_for_target(target, result, idx):
#     if isinstance(target, (ast.Tuple, ast.List)):
#         idx.append(0)
#         for r in target.elts:
#             get_indexes_for_target(r, result, idx)
#         idx.pop()
# 
#     else:
#         result.append((target, idx[:]))
#         if idx:
#             idx[-1] += 1
# 
#     return result
# 
# Path: supplement/names.py
# class RecursiveCallException(Exception):
#     def __init__(self, obj):
#         self.object = obj
# 
#     def is_called_by(self, obj):
#         return obj is self.object


# Path: supplement/evaluator.py
import ast
import logging
from .objects import create_object, FakeInstanceObject
from .common import Value, UnknownObject, Object, create_object_from_seq_item, get_indexes_for_target
from .names import RecursiveCallException
        from .scope import InnerScope
        from .names import PostponedName, AssignedName
                from .tree import dump_tree


class Indexable(Object):
    def __init__(self, scope, obj, nodes):
        self.values = [Value(scope, r) for r in nodes]
        self.object = obj

    def op_getitem(self, idx):
        idx = idx.get_value()
        try:
            value = self.values[idx]
        except IndexError:
            return UnknownObject()

        return value.get_object()

    def op_common_item(self):
        try:
            value = self.values[0]
        except IndexError:
            return UnknownObject()

        return value.get_object()

    def get_names(self):
        return self.object.get_names()

    def __getitem__(self, name):
        return self.object[name]



class Dict(Object):