22import rpython .rlib .jit as jit
33from rpython .rlib .rarithmetic import r_uint
44from pixie .vm .code import as_var
5+ from pixie .vm .numbers import Integer , Float
56from pixie .vm .keyword import Keyword
67import pixie .vm .rt as rt
78
@@ -46,12 +47,15 @@ def type(self):
4647 return self ._custom_type
4748
4849 def set_field (self , name , val ):
49- self ._custom_type .set_mutable (name )
5050 idx = self ._custom_type .get_slot_idx (name )
5151 if idx == - 1 :
5252 runtime_error (u"Invalid field named " + rt .name (rt .str (name )) + u" on type " + rt .name (rt .str (self .type ())))
5353
54- self ._fields [idx ] = val
54+ old_val = self ._fields [idx ]
55+ if isinstance (old_val , AbstractMutableCell ):
56+ old_val .set_mutable_cell_value (self ._custom_type , self ._fields , name , idx , val )
57+ else :
58+ self ._fields [idx ] = val
5559 return self
5660
5761 @jit .elidable_promote ()
@@ -65,9 +69,14 @@ def get_field(self, name):
6569 runtime_error (u"Invalid field named " + rt .name (rt .str (name )) + u" on type " + rt .name (rt .str (self .type ())))
6670
6771 if self ._custom_type .is_mutable (name ):
68- return self ._fields [idx ]
72+ value = self ._fields [idx ]
73+ else :
74+ value = self .get_field_immutable (idx )
75+
76+ if isinstance (value , AbstractMutableCell ):
77+ return value .get_mutable_cell_value ()
6978 else :
70- return self . get_field_immutable ( idx )
79+ return value
7180
7281 def set_field_by_idx (self , idx , val ):
7382 affirm (isinstance (idx , r_uint ), u"idx must be a r_uint" )
@@ -98,7 +107,13 @@ def _new__args(args):
98107 affirm (cnt - 1 != tp .get_num_slots (), u"Wrong number of initializer fields to custom type" )
99108 arr = [None ] * cnt
100109 for x in range (cnt ):
101- arr [x ] = args [x + 1 ]
110+ val = args [x + 1 ]
111+ if isinstance (val , Integer ):
112+ val = IntegerMutableCell (val .int_val ())
113+ elif isinstance (val , Float ):
114+ val = FloatMutableCell (val .float_val ())
115+
116+ arr [x ] = val
102117 return CustomTypeInstance (tp , arr )
103118
104119@as_var ("set-field!" )
@@ -114,3 +129,49 @@ def get_field(inst, field):
114129 affirm (isinstance (field , Keyword ), u"Field must be a keyword" )
115130 return inst .get_field (field )
116131
132+
133+
134+ class AbstractMutableCell (Object ):
135+ _type = Type (u"pixie.stdlib.AbstractMutableCell" )
136+ def type (self ):
137+ return self ._type
138+
139+ def set_mutable_cell_value (self , ct , fields , nm , idx , value ):
140+ pass
141+
142+ def get_mutable_cell_value (self ):
143+ pass
144+
145+ class IntegerMutableCell (AbstractMutableCell ):
146+ def __init__ (self , int_val ):
147+ self ._mutable_integer_val = int_val
148+
149+ def set_mutable_cell_value (self , ct , fields , nm , idx , value ):
150+ if not isinstance (value , Integer ):
151+ ct .set_mutable (nm )
152+ if isinstance (value , Float ):
153+ fields [idx ] = FloatMutableCell (value .float_val ())
154+ else :
155+ fields [idx ] = value
156+ else :
157+ self ._mutable_integer_val = value .int_val ()
158+
159+ def get_mutable_cell_value (self ):
160+ return rt .wrap (self ._mutable_integer_val )
161+
162+ class FloatMutableCell (AbstractMutableCell ):
163+ def __init__ (self , float_val ):
164+ self ._mutable_float_val = float_val
165+
166+ def set_mutable_cell_value (self , ct , fields , nm , idx , value ):
167+ if not isinstance (value , Float ):
168+ ct .set_mutable (nm )
169+ if isinstance (value , Integer ):
170+ fields [idx ] = IntegerMutableCell (value .int_val ())
171+ else :
172+ fields [idx ] = value
173+ else :
174+ self ._mutable_float_val = value .float_val ()
175+
176+ def get_mutable_cell_value (self ):
177+ return rt .wrap (self ._mutable_float_val )
0 commit comments