# Types which the user should never directly see
ERROR        = "<!error>"
RETURN_VALUE = "<!return value>"
FUNCTION     = "<!function>"

NEXT         = "<next>"
BREAK        = "<break>"

# Normal types
NUMBER  = "<number>"
BOOLEAN = "<boolean>"
STRING  = "<string>"
ARRAY   = "<array>"
NULL    = "<null>"
BLOCK   = "<block>"
TUPLE   = "<tuple>"

class InternalObject(object):
    def __eq__(self, other):
        return type(other) == type(self)
    
    def __ne__(self, other):
        return not self.__eq__(other)
    
    def __str__(self):
        return ""
    
    __repr__ = __str__
    
    
class Collection(InternalObject):
    def get_elements(self):
        return []
    
    
def compare(prop = "value"):
    return (lambda self, other: getattr(self, prop) == getattr(other, prop) if type(self) == type(other) else False)


class Error(InternalObject):
    """represents an error thrown in execution"""
    def __init__(self, msg):
        self.type = ERROR
        self.msg = msg
    
    __eq__ = compare("msg")
    
    def __str__(self):
        return "ERROR: %s" % self.msg
        

class ReturnValue(InternalObject):
    """represents a value to be returned from a function"""
    def __init__(self, value):
        self.type = RETURN_VALUE
        self.value = value
    
    __eq__ = compare()
            
    
    def __str__(self):
        return str(self.value)
        

class Number(InternalObject):
    """represents a number object"""
    def __init__(self, value):
        self.type = NUMBER
        self.value = float(value)
        
    __eq__ = compare()
            
    def __str__(self):
        return str(self.value)
        
    def is_integer(self):
        return float(int(self.value)) == self.value
        
    def is_positive(self):
        return self.value >= 0
        
        
class Boolean(InternalObject):
    """a boolean object"""
    def __init__(self, value):
        self.type = BOOLEAN
        self.value = value
        
    __eq__ = compare()
    
    def __str__(self):
        return str(self.value).lower()
        
        
class String(Collection):
    """a string object"""
    def __init__(self, value):
        self.type = STRING
        
        if type(value) == list:
            self.value = "".join(str(e) for e in value)
        else:
            self.value = value
        
    __eq__ = compare()
    
    def __str__(self):
        return "%s" % self.value
        
    def get_elements(self):
        return [String(ch) for ch in list(self.value)]
        
        
class Tuple(Collection):
    """a tuple object"""
    def __init__(self, value):
        self.type = TUPLE
        self.value = value
    
    __eq__ = compare()
    
    def __str__(self):
        return "(%s)" % "".join(str(e) + ", " for e in self.value)[:-2]
        
    def get_elements(self):
        return self.value
    
        
class Null(InternalObject):
    """the null object"""
    def __init__(self):
        self.type = NULL
        
    def __str__(self):
        return "null" 
        
        
class Array(Collection):
    """an array object"""
    def __init__(self, elements):
        self.type = ARRAY
        self.elements = elements
        
    __eq__ = compare("elements")
            
    def __str__(self):
        return "[%s]" % "".join(str(e) + ", " for e in self.elements)[:-2]
        
    def get_elements(self):
        return self.elements
        
        
class Function(InternalObject):
    """a function object"""
    def __init__(self, pattern, body, context):
        self.type = FUNCTION
        self.pattern = pattern # [id|param]
        self.body = body
        self.context = context
    
    def __str__(self):
        return "<function instance>"
        
        
class Block(InternalObject):
    """a block object"""
    def __init__(self, params, body):
        self.type = BLOCK
        self.params = params
        self.body = body
        
    def __str__(self):
        return "<block instance>"
        
        
class Next(InternalObject):
    """result of the next; statement"""
    def __init__(self):
        self.type = NEXT
        
    def __str__(self):
        return "<next>"
        
        
class Break(InternalObject):
    """result of the break; statement"""
    def __init__(self):
        self.type = BREAK
        
    def __str__(self):
        return "<break>"
@@ -2863,24 +2863,455 @@
  self.value%0A
+        %0A        %0Aclass Object(InternalObject):%0A    %22%22%22an object, similar to a dictionary in python%22%22%22%0A    def __init__(self, pairs):%0A        self.type = OBJECT%0A        self.pairs = pairs%0A        %0A    __eq__ = compare(%22pairs%22)%0A    %0A    def __str__(self):%0A        return %22%5B%25s%5D%22 %25 %22%22.join(%22%25s: %25s, %22 %25 (str(key), str(value)) for key, value in self.pairs.items())%0A        %0A    def get_elements(self):%0A        return self.pairs.keys()%0A
     %0A       

Implement the Object object