<commit_before>
import sys
from spyvm import model, constants
from spyvm.util.version import VersionMixin
from rpython.rlib import objectmodel, jit
from rpython.rlib.objectmodel import import_from_mixin
import rstrategies as rstrat

"""
A note on terminology:
A normal smalltalk objects contains references to other objects. These pointers
are the *storage* of the object. In RSqueak, each W_PointersObject passes
handling of its storage to a *strategy* object (subclass of AbstractStrategy).
Most objects are handled by a subclass of SingletonStorageStrategy. These classes
implement the actual "storage strategy" concept ("Storage Strategies for Collections
in Dynamically Typed Languages", Bolcz et al., 2013). To support these singleton
strategies, W_PointersObject have a _storage field for arbitrary usage by their
strategy.
Strategies including the "ShadowMixin" are called *shadows*. Shadows are not
singletons and are bound to a single W_PointersObject and store additional state
required to implement the language semantics. ShadowMixin is used by ContextPartShadow
(storage_context.py) and AbstractGenericStrategy, which is extended by various classes
in storage_classes.py.
"""

class AbstractStrategy(object):
    """Subclasses of this handle the information contained in Smalltalk objects.
    The common API allows to store and fetch elements from object slots.
    Every object has some kind of storage representation attached.
    Some subclasses (those with *Shadow in their name) contain additional information,
    required by the VM. These 'shadows' not only manage the memory of their Smalltalk objects,
    but are also the VM-internal representation of these objects.
    """
    _attrs_ = ['space']
    _immutable_fields_ = ['space']
    provides_getname = False
    repr_classname = "AbstractStrategy"
    __metaclass__ = rstrat.StrategyMetaclass
    import_from_mixin(rstrat.AbstractStrategy)

    def __init__(self, space, w_self, size):
        self.space = space
    def getname(self):
        raise NotImplementedError("Abstract class")
    def __repr__(self):
        if self.provides_getname:
            return "<%s %s>" % (self.repr_classname, self.getname())
        else:
            return "<%s>" % self.repr_classname
    def strategy_factory(self):
        return self.space.strategy_factory
    def convert_storage_from_AllNilStrategy(self, w_self, all_nil_storage):
        # Fields are initialized to nil
        self.initialize_storage(w_self, all_nil_storage.size(w_self))
    def insert(self, w_self, index0, list_w):
        raise NotImplementedError("Smalltalk objects are fixed size")
    def delete(self, w_self, start, end):
        raise NotImplementedError("Smalltalk objects are fixed size")
    def is_shadow(self):
        return False
    def handles_become(self):
        """Only shadows are non-singletons and actually handle become"""
        return self.is_shadow()
    def become(self, w_other):
        raise NotImplementedError("This strategy doesn't handle become.")
    def onesided_become(self, w_other):
        # This is only needed in ShadowMixin, but has to be pulled up here because
        # both AbstractGenericShadow and ContextPartShadow use it.
        raise NotImplementedError("This strategy doesn't handle become.")

# ========== Storage classes implementing storage strategies ==========

class SingletonStorageStrategy(AbstractStrategy):
    """
    Singleton strategies handle 'simple' object storage in normal objects, without
    additional VM-internal information.
    Depending on the data inside an object, different optimizing strategies are used.
    """
    repr_classname = "SingletonStorageStrategy"
    _attrs_ = []
    import_from_mixin(rstrat.UnsafeIndexingMixin)

    def default_value(self):
        return self.space.w_nil

@rstrat.strategy()
class ListStrategy(SingletonStorageStrategy):
    _attrs_ = []
    repr_classname = "ListStrategy"
    import_from_mixin(rstrat.GenericStrategy)

class WeakListStrategy(SingletonStorageStrategy):
    repr_classname = "WeakListStrategy"
    import_from_mixin(rstrat.WeakGenericStrategy)

@rstrat.strategy(generalize=[ListStrategy])
class SmallIntegerOrNilStrategy(SingletonStorageStrategy):
    repr_classname = "SmallIntegerOrNilStrategy"
    import_from_mixin(rstrat.TaggingStrategy)
    contained_type = model.W_SmallInteger
    def wrap(self, val): return self.space.wrap_int(val)
    def unwrap(self, w_val): return self.space.unwrap_int(w_val)
    def wrapped_tagged_value(self): return self.space.w_nil
    def unwrapped_tagged_value(self): return constants.MAXINT

@rstrat.strategy(generalize=[ListStrategy])
class FloatOrNilStrategy(SingletonStorageStrategy):
    repr_classname = "FloatOrNilStrategy"
    import_from_mixin(rstrat.TaggingStrategy)
    contained_type = model.W_Float
    tag_float = sys.float_info.max
    def wrap(self, val): return self.space.wrap_float(val)
    def unwrap(self, w_val): return self.space.unwrap_float(w_val)
    def wrapped_tagged_value(self): return self.space.w_nil
    def unwrapped_tagged_value(self): return self.tag_float

@rstrat.strategy(generalize=[
    SmallIntegerOrNilStrategy,
    FloatOrNilStrategy,
    ListStrategy])
class AllNilStrategy(SingletonStorageStrategy):<commit_msg>add a strategy for characters (e.g. used by String instances)<commit_after>
import sys
from spyvm import model, constants
from spyvm.util.version import VersionMixin
from rpython.rlib import objectmodel, jit
from rpython.rlib.objectmodel import import_from_mixin
import rstrategies as rstrat

"""
A note on terminology:
A normal smalltalk objects contains references to other objects. These pointers
are the *storage* of the object. In RSqueak, each W_PointersObject passes
handling of its storage to a *strategy* object (subclass of AbstractStrategy).
Most objects are handled by a subclass of SingletonStorageStrategy. These classes
implement the actual "storage strategy" concept ("Storage Strategies for Collections
in Dynamically Typed Languages", Bolcz et al., 2013). To support these singleton
strategies, W_PointersObject have a _storage field for arbitrary usage by their
strategy.
Strategies including the "ShadowMixin" are called *shadows*. Shadows are not
singletons and are bound to a single W_PointersObject and store additional state
required to implement the language semantics. ShadowMixin is used by ContextPartShadow
(storage_context.py) and AbstractGenericStrategy, which is extended by various classes
in storage_classes.py.
"""

class AbstractStrategy(object):
    """Subclasses of this handle the information contained in Smalltalk objects.
    The common API allows to store and fetch elements from object slots.
    Every object has some kind of storage representation attached.
    Some subclasses (those with *Shadow in their name) contain additional information,
    required by the VM. These 'shadows' not only manage the memory of their Smalltalk objects,
    but are also the VM-internal representation of these objects.
    """
    _attrs_ = ['space']
    _immutable_fields_ = ['space']
    provides_getname = False
    repr_classname = "AbstractStrategy"
    __metaclass__ = rstrat.StrategyMetaclass
    import_from_mixin(rstrat.AbstractStrategy)

    def __init__(self, space, w_self, size):
        self.space = space
    def getname(self):
        raise NotImplementedError("Abstract class")
    def __repr__(self):
        if self.provides_getname:
            return "<%s %s>" % (self.repr_classname, self.getname())
        else:
            return "<%s>" % self.repr_classname
    def strategy_factory(self):
        return self.space.strategy_factory
    def convert_storage_from_AllNilStrategy(self, w_self, all_nil_storage):
        # Fields are initialized to nil
        self.initialize_storage(w_self, all_nil_storage.size(w_self))
    def insert(self, w_self, index0, list_w):
        raise NotImplementedError("Smalltalk objects are fixed size")
    def delete(self, w_self, start, end):
        raise NotImplementedError("Smalltalk objects are fixed size")
    def is_shadow(self):
        return False
    def handles_become(self):
        """Only shadows are non-singletons and actually handle become"""
        return self.is_shadow()
    def become(self, w_other):
        raise NotImplementedError("This strategy doesn't handle become.")
    def onesided_become(self, w_other):
        # This is only needed in ShadowMixin, but has to be pulled up here because
        # both AbstractGenericShadow and ContextPartShadow use it.
        raise NotImplementedError("This strategy doesn't handle become.")

# ========== Storage classes implementing storage strategies ==========

class SingletonStorageStrategy(AbstractStrategy):
    """
    Singleton strategies handle 'simple' object storage in normal objects, without
    additional VM-internal information.
    Depending on the data inside an object, different optimizing strategies are used.
    """
    repr_classname = "SingletonStorageStrategy"
    _attrs_ = []
    import_from_mixin(rstrat.UnsafeIndexingMixin)

    def default_value(self):
        return self.space.w_nil

@rstrat.strategy()
class ListStrategy(SingletonStorageStrategy):
    _attrs_ = []
    repr_classname = "ListStrategy"
    import_from_mixin(rstrat.GenericStrategy)

class WeakListStrategy(SingletonStorageStrategy):
    repr_classname = "WeakListStrategy"
    import_from_mixin(rstrat.WeakGenericStrategy)

@rstrat.strategy(generalize=[ListStrategy])
class SmallIntegerOrNilStrategy(SingletonStorageStrategy):
    repr_classname = "SmallIntegerOrNilStrategy"
    import_from_mixin(rstrat.TaggingStrategy)
    contained_type = model.W_SmallInteger
    def wrap(self, val): return self.space.wrap_int(val)
    def unwrap(self, w_val): return self.space.unwrap_int(w_val)
    def wrapped_tagged_value(self): return self.space.w_nil
    def unwrapped_tagged_value(self): return constants.MAXINT

@rstrat.strategy(generalize=[ListStrategy])
class CharacterOrNilStrategy(SingletonStorageStrategy):
    repr_classname = "CharacterOrNilStrategy"
    import_from_mixin(rstrat.TaggingStrategy)
    contained_type = model.W_Character
    def wrap(self, val): return self.space.wrap_char(chr(val))
    def unwrap(self, w_val): return ord(self.space.unwrap_char(w_val))
    def wrapped_tagged_value(self): return self.space.w_nil
    def unwrapped_tagged_value(self): return constants.MAXINT

@rstrat.strategy(generalize=[ListStrategy])
class FloatOrNilStrategy(SingletonStorageStrategy):
    repr_classname = "FloatOrNilStrategy"
    import_from_mixin(rstrat.TaggingStrategy)
    contained_type = model.W_Float
    tag_float = sys.float_info.max
    def wrap(self, val): return self.space.wrap_float(val)
    def unwrap(self, w_val): return self.space.unwrap_float(w_val)
    def wrapped_tagged_value(self): return self.space.w_nil
    def unwrapped_tagged_value(self): return self.tag_float

@rstrat.strategy(generalize=[
    SmallIntegerOrNilStrategy,
    FloatOrNilStrategy,
    ListStrategy])
class AllNilStrategy(SingletonStorageStrategy):
{'fraction_non_alphanumeric': 0.07491886043995673, 'fraction_numerical': 0.0009015506671474937, 'mean_word_length': 4.582788122798188, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7439588', 'n_tokens_mistral': 3143, 'n_tokens_neox': 3077, 'n_words': 950}