<commit_before>from collections import namedtuple
from pycket import values
from pycket.cont import continuation
from pycket.error import SchemeException
from pycket.exposeprim import make_call_method
from pycket.small_list import inline_small_list
from pycket.values import from_list, w_void, w_null, w_false, w_true, W_Object, W_Fixnum, W_Symbol, W_Procedure, W_Prim
from rpython.rlib import jit

from collections import OrderedDict

#
# Structs are partially supported
# 
# Not implemented:
# 1) properties and super as an argument -- can't find module /Applications/Racket/collects/racket/private/kw.rkt
# 2) prefab -- '#s(sprout bean): need update in expand.rkt
# 3) methods overriding (including equal) -- generic-interfaces.rkt

# TODO: inspector currently does nothing
class W_StructInspector(W_Object):
    errorname = "struct-inspector"
    _immutable_fields_ = ["super"]

    @staticmethod 
    def make(inspector, issibling = False):
        super = inspector
        if issibling:
            super = inspector.super if inspector is not None else None
        return W_StructInspector(super)

    def __init__(self, super):
        self.super = super

current_inspector = W_StructInspector(None)

class W_StructType(W_Object):
    all_structs = {}
    errorname = "struct-type"
    _immutable_fields_ = ["id", "super", "init_field_cnt", "auto_field_cnt", "auto_v", "inspector", \
                          "immutables", "guard", "constr_name"]
    @staticmethod
    def make(name, super_type, init_field_cnt, auto_field_cnt, auto_v, props, inspector, proc_spec, immutables, guard, constr_name):
        struct_id = W_StructTypeDescriptor(name.value)
        W_StructType.all_structs[struct_id] = w_result = W_StructType(struct_id, super_type, init_field_cnt, auto_field_cnt, \
            auto_v, props, inspector, proc_spec, immutables, guard, constr_name)
        return w_result

    @staticmethod
    def lookup_struct_type(struct_id):
        return W_StructType.all_structs.get(struct_id, w_false)
    
    def __init__(self, struct_id, super_type, init_field_cnt, auto_field_cnt,
            auto_v, props, inspector, proc_spec, immutables, guard, constr_name):
        self.super = W_StructType.lookup_struct_type(super_type) if super_type is not w_false else None
        self.init_field_cnt = init_field_cnt.value
        self.auto_field_cnt = auto_field_cnt.value
        self.auto_v = auto_v
        self.props = []
        # for i in values.from_list(props):
        #     assert isinstance(i, values.W_Cons)
        #     self.props.append(i)
        self.inspector = inspector
        # self.proc_spec = proc_spec
        self.immutables = []
        for i in values.from_list(immutables):
            assert isinstance(i, values.W_Fixnum)
            self.immutables.append(i.value)
        self.guard = guard
        if isinstance(constr_name, W_Symbol):
            self.constr_name = constr_name.value
        else:
            self.constr_name = "make-" + struct_id.value

        self.auto_values = [self.auto_v] * self.auto_field_cnt
        self.isopaque = self.inspector is not w_false
        # self.mutable_fields = []

        self.desc = struct_id
        self.constr = W_StructConstructor(self.desc, self.super, self.init_field_cnt, self.auto_values, self.props,
                                          self.calculate_offset, self.isopaque, self.guard, self.constr_name)
        self.pred = W_StructPredicate(self.desc)
        self.acc = W_StructAccessor(self.desc)
        self.mut = W_StructMutator(self.desc)

    def constructor(self):
        return self.constr
    def set_mutable(self, field):
        pass
        # assert isinstance(field, W_Fixnum)
        # self.mutable_fields.append(field.value)

    # """
    # This method has to be called after initialization, otherwise self.mutable_fields will be empty
    # """
    def calculate_offset(self):
        result = OrderedDict()
        struct_type = self
        vals_offset = 0
        while True:
            vals_offset += struct_type.init_field_cnt + struct_type.auto_field_cnt
            struct_type = struct_type.super
            if isinstance(struct_type, W_StructType):
                result[struct_type.desc] = vals_offset
            else:
                break
        return result
    def make_struct_tuple(self):
        return [self.desc, self.constr, self.pred, self.acc, self.mut]

class W_RootStruct(W_Object):
    errorname = "root-struct"
    _immutable_fields_ = ["type", "super", "isopaque"]

    def __init__(self, struct_id, super, isopaque):
        self.type = struct_id
        self.super = super
        self.isopaque = isopaque

    @continuation
    def ref(self, struct_id, field, env, cont, _vals):
        raise NotImplementedError("base class")

    @continuation
    def set(self, struct_id, field, val, env, cont, _vals):
        raise NotImplementedError("base class")

    def vals(self):
        raise NotImplementedError("base class")

class W_Struct(W_RootStruct):
    errorname = "struct"
    _immutable_fields_ = ["values", "type", "super", "props", "isopaque"]
    def __init__(self, offset, struct_id, super, props, isopaque):
        W_RootStruct.__init__(self, struct_id, super, isopaque)
        self.offset = offset
        self.props = props

    def vals(self):
        return self._get_full_list()

    # Rather than reference functions, we store the continuations. This is
    # necessarray to get constant stack usage without adding extra preamble
    # continuations.
    @continuation
    def ref(self, struct_id, field, env, cont, _vals):
        from pycket.interpreter import return_value, jump
        # pos = self.offset[(struct_id, field)]
        # result = self._get_list(pos)
        # return return_value(result, env, cont)
        # import pdb; pdb.set_trace()
        if self.type == struct_id:
            result = self._get_list(field)
            return return_value(result, env, cont)
        elif self.type.value == struct_id.value:
            raise SchemeException("given value instantiates a different structure type with the same name")
        elif self.super is not None:
            # super = self.super
            # assert isinstance(super, W_Struct)
            # return jump(env, super.ref(struct_id, field, env, cont))
            result = self._get_list(field + self.offset[struct_id])
            return return_value(result, env, cont)
        else:
            assert False

    @continuation
    def set(self, struct_id, field, val, env, cont, _vals):
        from pycket.interpreter import return_value, jump
        # self._set_list(self.offset[(struct_id, field)], val)
        # return return_value(w_void, env, cont)

        type = jit.promote(self.type)
        if type == struct_id:<commit_msg>Mark struct continuations as immutable<commit_after>from collections import namedtuple
from pycket import values
from pycket.cont import continuation, label
from pycket.error import SchemeException
from pycket.exposeprim import make_call_method
from pycket.small_list import inline_small_list
from pycket.values import from_list, w_void, w_null, w_false, w_true, W_Object, W_Fixnum, W_Symbol, W_Procedure, W_Prim
from rpython.rlib import jit

from collections import OrderedDict

#
# Structs are partially supported
# 
# Not implemented:
# 1) properties and super as an argument -- can't find module /Applications/Racket/collects/racket/private/kw.rkt
# 2) prefab -- '#s(sprout bean): need update in expand.rkt
# 3) methods overriding (including equal) -- generic-interfaces.rkt

# TODO: inspector currently does nothing
class W_StructInspector(W_Object):
    errorname = "struct-inspector"
    _immutable_fields_ = ["super"]

    @staticmethod 
    def make(inspector, issibling = False):
        super = inspector
        if issibling:
            super = inspector.super if inspector is not None else None
        return W_StructInspector(super)

    def __init__(self, super):
        self.super = super

current_inspector = W_StructInspector(None)

class W_StructType(W_Object):
    all_structs = {}
    errorname = "struct-type"
    _immutable_fields_ = ["id", "super", "init_field_cnt", "auto_field_cnt", "auto_v", "inspector", \
                          "immutables", "guard", "constr_name"]
    @staticmethod
    def make(name, super_type, init_field_cnt, auto_field_cnt, auto_v, props, inspector, proc_spec, immutables, guard, constr_name):
        struct_id = W_StructTypeDescriptor(name.value)
        W_StructType.all_structs[struct_id] = w_result = W_StructType(struct_id, super_type, init_field_cnt, auto_field_cnt, \
            auto_v, props, inspector, proc_spec, immutables, guard, constr_name)
        return w_result

    @staticmethod
    def lookup_struct_type(struct_id):
        return W_StructType.all_structs.get(struct_id, w_false)
    
    def __init__(self, struct_id, super_type, init_field_cnt, auto_field_cnt,
            auto_v, props, inspector, proc_spec, immutables, guard, constr_name):
        self.super = W_StructType.lookup_struct_type(super_type) if super_type is not w_false else None
        self.init_field_cnt = init_field_cnt.value
        self.auto_field_cnt = auto_field_cnt.value
        self.auto_v = auto_v
        self.props = []
        # for i in values.from_list(props):
        #     assert isinstance(i, values.W_Cons)
        #     self.props.append(i)
        self.inspector = inspector
        # self.proc_spec = proc_spec
        self.immutables = []
        for i in values.from_list(immutables):
            assert isinstance(i, values.W_Fixnum)
            self.immutables.append(i.value)
        self.guard = guard
        if isinstance(constr_name, W_Symbol):
            self.constr_name = constr_name.value
        else:
            self.constr_name = "make-" + struct_id.value

        self.auto_values = [self.auto_v] * self.auto_field_cnt
        self.isopaque = self.inspector is not w_false
        # self.mutable_fields = []

        self.desc = struct_id
        self.constr = W_StructConstructor(self.desc, self.super, self.init_field_cnt, self.auto_values, self.props,
                                          self.calculate_offset, self.isopaque, self.guard, self.constr_name)
        self.pred = W_StructPredicate(self.desc)
        self.acc = W_StructAccessor(self.desc)
        self.mut = W_StructMutator(self.desc)

    def constructor(self):
        return self.constr
    def set_mutable(self, field):
        pass
        # assert isinstance(field, W_Fixnum)
        # self.mutable_fields.append(field.value)

    # """
    # This method has to be called after initialization, otherwise self.mutable_fields will be empty
    # """
    def calculate_offset(self):
        result = OrderedDict()
        struct_type = self
        vals_offset = 0
        while True:
            vals_offset += struct_type.init_field_cnt + struct_type.auto_field_cnt
            struct_type = struct_type.super
            if isinstance(struct_type, W_StructType):
                result[struct_type.desc] = vals_offset
            else:
                break
        return result
    def make_struct_tuple(self):
        return [self.desc, self.constr, self.pred, self.acc, self.mut]

class W_RootStruct(W_Object):
    errorname = "root-struct"
    _immutable_fields_ = ["type", "super", "isopaque", "ref", "set"]

    def __init__(self, struct_id, super, isopaque):
        self.type = struct_id
        self.super = super
        self.isopaque = isopaque

    @label
    def ref(self, struct_id, field, env, cont):
        raise NotImplementedError("base class")

    @label
    def set(self, struct_id, field, val, env, cont):
        raise NotImplementedError("base class")

    def vals(self):
        raise NotImplementedError("base class")

class W_Struct(W_RootStruct):
    errorname = "struct"
    _immutable_fields_ = ["values", "type", "super", "props", "isopaque"]
    def __init__(self, offset, struct_id, super, props, isopaque):
        W_RootStruct.__init__(self, struct_id, super, isopaque)
        self.offset = offset
        self.props = props

    def vals(self):
        return self._get_full_list()

    # Rather than reference functions, we store the continuations. This is
    # necessarray to get constant stack usage without adding extra preamble
    # continuations.
    @label
    def ref(self, struct_id, field, env, cont):
        from pycket.interpreter import return_value, jump
        # pos = self.offset[(struct_id, field)]
        # result = self._get_list(pos)
        # return return_value(result, env, cont)
        # import pdb; pdb.set_trace()
        if self.type == struct_id:
            result = self._get_list(field)
            return return_value(result, env, cont)
        elif self.type.value == struct_id.value:
            raise SchemeException("given value instantiates a different structure type with the same name")
        elif self.super is not None:
            # super = self.super
            # assert isinstance(super, W_Struct)
            # return jump(env, super.ref(struct_id, field, env, cont))
            result = self._get_list(field + self.offset[struct_id])
            return return_value(result, env, cont)
        else:
            assert False

    @label
    def set(self, struct_id, field, val, env, cont):
        from pycket.interpreter import return_value, jump
        # self._set_list(self.offset[(struct_id, field)], val)
        # return return_value(w_void, env, cont)

        type = jit.promote(self.type)
        if type == struct_id:
{'fraction_non_alphanumeric': 0.09139705882352941, 'fraction_numerical': 0.000588235294117647, 'mean_word_length': 2.8055400111919417, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7510174', 'n_tokens_mistral': 4171, 'n_tokens_neox': 4094, 'n_words': 1018}