# Path: nolang/error.py
# class AppError(Exception):
#     def __init__(self, w_exception):
#         self.w_exception = w_exception
#         self.traceback = None
# 
#     def record_position(self, frame, bytecode, index):
#         self.traceback = TracebackElem(frame, index, bytecode, self.traceback)
# 
#     def match(self, space, w_expected):
#         return space.issubclass(space.type(self.w_exception), w_expected)
# 
#     def __repr__(self):
#         return '<AppError %r>' % (self.w_exception,)
#     __str__ = __repr__
# 
# Path: nolang/objects/root.py
# class W_Root(object):
#     cls_w_type = None
# 
#     def int_w(self, space):
#         raise space.apperr(space.w_typeerror, 'expected integer')
# 
#     def utf8_w(self, space):
#         raise space.apperr(space.w_typeerror, 'expected string')
# 
#     def buffer_w(self, space):
#         raise space.apperr(space.w_typeerror, 'expected buffer')
# 
#     def listview(self, space):
#         raise space.apperr(space.w_typeerror, 'expected list')
# 
#     def dictview(self, space):
#         raise space.apperr(space.w_typeerror, 'expected dict')
# 
#     def hash(self, space):
#         raise space.apperr(space.w_typeerror, 'unhashable type')
# 
#     def iter(self, space):
#         raise space.apperr(space.w_typeerror, 'uniterable type')
# 
#     def iter_next(self, space):
#         raise space.apperr(space.w_typeerror, 'object not an iterator')
# 
#     def getattr(self, space, attrname):
#         return space.w_NotImplemented
# 
#     def bind(self, space, w_obj):
#         return self
# 
#     def gettype(self, space):
#         return self.cls_w_type
# 
#     def str(self, space):
#         raise space.apperr(space.w_typeerror,
#             'object cannot be converted to str')
# 
#     def len(self, space):
#         raise space.apperr(space.w_typeerror, 'unsized type')
# 
#     def is_true(self, space):
#         return True
# 
#     def lt(self, space, w_obj):
#         raise space.apperr(space.w_typeerror, 'object not comparable')
# 
#     def eq(self, space, w_other):
#         if self is w_other:
#             return True
#         if space.type(self) is not space.type(w_other):
#             raise NotImplementedOp
#         return False
# 
#     def add(self, space, w_other):
#         raise space.apperr(space.w_typeerror, 'no implementation for `+`')
# 
#     def sub(self, space, w_other):
#         raise space.apperr(space.w_typeerror, 'no implementation for `-`')
# 
#     def mul(self, space, w_other):
#         raise space.apperr(space.w_typeerror, 'no implementation for `*`')
# 
#     def truediv(self, space, w_other):
#         raise space.apperr(space.w_typeerror, 'no implementation for `/`')
# 
#     def call(self, space, interpreter, args, kwargs):
#         raise space.apperr(space.w_typeerror, 'object is not callable')
# 
#     def freeze(self, space):
#         if self.is_frozen(space):
#             return
#         raise space.apperr(space.w_freezeerror, 'object not freezable')
# 
#     def thaw(self, space):
#         raise space.apperr(space.w_freezeerror, 'object does not know '
#             'how to thaw, this should be an internal error')
# 
#     def is_frozen(self, space):
#         return False
# 
# class NotImplementedOp(Exception):
#     pass
# 
# Path: nolang/builtins/spec.py
# class TypeSpec(object):
#     def __init__(self, name, constructor, methods=None, properties=None,
#                  parent_name=None, is_subclassable=False):
#         self.constructor = constructor
#         self.name = name
#         if methods is None:
#             methods = {}
#         self.methods = methods
#         if properties is None:
#             properties = {}
#         self.properties = properties
#         self.parent_name = parent_name
#         self.is_subclassable = is_subclassable
# 
# def unwrap_spec(**spec):
#     def wrapper(func):
#         func.unwrap_spec = spec
#         return func
#     return wrapper


from rpython.rlib.objectmodel import compute_hash
from nolang.error import AppError
from nolang.objects.root import W_Root, NotImplementedOp
from nolang.builtins.spec import TypeSpec, unwrap_spec
    def str(self, space):
        return self.utf8_w(space)

    def len(self, space):
        if self.lgt == -1:
            # XXX compute it better once utf8 lands
            self.lgt = len(self.utf8val.decode('utf-8'))
        return self.lgt

    def hash(self, space):
        return compute_hash(self.utf8val)

    def eq(self, space, w_other):
        try:
            other = space.utf8_w(w_other)
        except AppError as ae:
            if space.type(ae.w_exception) is space.w_typeerror:
                raise NotImplementedOp
            raise
        return self.utf8val == other

    def is_frozen(self, space):
        return True


@unwrap_spec(value='utf8')
def new_str(space, value):
    return space.newtext(value)



# Path: nolang/error.py
# class AppError(Exception):
#     def __init__(self, w_exception):
#         self.w_exception = w_exception
#         self.traceback = None
# 
#     def record_position(self, frame, bytecode, index):
#         self.traceback = TracebackElem(frame, index, bytecode, self.traceback)
# 
#     def match(self, space, w_expected):
#         return space.issubclass(space.type(self.w_exception), w_expected)
# 
#     def __repr__(self):
#         return '<AppError %r>' % (self.w_exception,)
#     __str__ = __repr__
# 
# Path: nolang/objects/root.py
# class W_Root(object):
#     cls_w_type = None
# 
#     def int_w(self, space):
#         raise space.apperr(space.w_typeerror, 'expected integer')
# 
#     def utf8_w(self, space):
#         raise space.apperr(space.w_typeerror, 'expected string')
# 
#     def buffer_w(self, space):
#         raise space.apperr(space.w_typeerror, 'expected buffer')
# 
#     def listview(self, space):
#         raise space.apperr(space.w_typeerror, 'expected list')
# 
#     def dictview(self, space):
#         raise space.apperr(space.w_typeerror, 'expected dict')
# 
#     def hash(self, space):
#         raise space.apperr(space.w_typeerror, 'unhashable type')
# 
#     def iter(self, space):
#         raise space.apperr(space.w_typeerror, 'uniterable type')
# 
#     def iter_next(self, space):
#         raise space.apperr(space.w_typeerror, 'object not an iterator')
# 
#     def getattr(self, space, attrname):
#         return space.w_NotImplemented
# 
#     def bind(self, space, w_obj):
#         return self
# 
#     def gettype(self, space):
#         return self.cls_w_type
# 
#     def str(self, space):
#         raise space.apperr(space.w_typeerror,
#             'object cannot be converted to str')
# 
#     def len(self, space):
#         raise space.apperr(space.w_typeerror, 'unsized type')
# 
#     def is_true(self, space):
#         return True
# 
#     def lt(self, space, w_obj):
#         raise space.apperr(space.w_typeerror, 'object not comparable')
# 
#     def eq(self, space, w_other):
#         if self is w_other:
#             return True
#         if space.type(self) is not space.type(w_other):
#             raise NotImplementedOp
#         return False
# 
#     def add(self, space, w_other):
#         raise space.apperr(space.w_typeerror, 'no implementation for `+`')
# 
#     def sub(self, space, w_other):
#         raise space.apperr(space.w_typeerror, 'no implementation for `-`')
# 
#     def mul(self, space, w_other):
#         raise space.apperr(space.w_typeerror, 'no implementation for `*`')
# 
#     def truediv(self, space, w_other):
#         raise space.apperr(space.w_typeerror, 'no implementation for `/`')
# 
#     def call(self, space, interpreter, args, kwargs):
#         raise space.apperr(space.w_typeerror, 'object is not callable')
# 
#     def freeze(self, space):
#         if self.is_frozen(space):
#             return
#         raise space.apperr(space.w_freezeerror, 'object not freezable')
# 
#     def thaw(self, space):
#         raise space.apperr(space.w_freezeerror, 'object does not know '
#             'how to thaw, this should be an internal error')
# 
#     def is_frozen(self, space):
#         return False
# 
# class NotImplementedOp(Exception):
#     pass
# 
# Path: nolang/builtins/spec.py
# class TypeSpec(object):
#     def __init__(self, name, constructor, methods=None, properties=None,
#                  parent_name=None, is_subclassable=False):
#         self.constructor = constructor
#         self.name = name
#         if methods is None:
#             methods = {}
#         self.methods = methods
#         if properties is None:
#             properties = {}
#         self.properties = properties
#         self.parent_name = parent_name
#         self.is_subclassable = is_subclassable
# 
# def unwrap_spec(**spec):
#     def wrapper(func):
#         func.unwrap_spec = spec
#         return func
#     return wrapper


# Path: nolang/objects/unicode.py
from rpython.rlib.objectmodel import compute_hash
from nolang.error import AppError
from nolang.objects.root import W_Root, NotImplementedOp
from nolang.builtins.spec import TypeSpec, unwrap_spec

    def str(self, space):
        return self.utf8_w(space)

    def len(self, space):
        if self.lgt == -1:
            # XXX compute it better once utf8 lands
            self.lgt = len(self.utf8val.decode('utf-8'))
        return self.lgt

    def hash(self, space):
        return compute_hash(self.utf8val)

    def eq(self, space, w_other):
        try:
            other = space.utf8_w(w_other)
        except AppError as ae:
            if space.type(ae.w_exception) is space.w_typeerror:
                raise NotImplementedOp
            raise
        return self.utf8val == other

    def is_frozen(self, space):
        return True


@unwrap_spec(value='utf8')
def new_str(space, value):
    return space.newtext(value)



W_StrObject.spec = TypeSpec('Str', new_str)