introduced a new class modifier #immutable to indicate that an instantiated object cannot be modified using basicAt:put:
This commit is contained in:
parent
1dff630fdd
commit
63519c1ca3
@ -116,7 +116,7 @@ class(#character) String(Array)
|
|||||||
|
|
||||||
## -------------------------------------------------------------------------------
|
## -------------------------------------------------------------------------------
|
||||||
|
|
||||||
class(#character,#final,#limited) Symbol(String)
|
class(#character,#final,#limited,#immutable) Symbol(String)
|
||||||
{
|
{
|
||||||
method asString
|
method asString
|
||||||
{
|
{
|
||||||
|
@ -291,7 +291,7 @@ class Number(Magnitude)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Integer(Number)
|
class(#limited) Integer(Number)
|
||||||
{
|
{
|
||||||
method timesRepeat: aBlock
|
method timesRepeat: aBlock
|
||||||
{
|
{
|
||||||
@ -310,17 +310,17 @@ class SmallInteger(Integer)
|
|||||||
method(#primitive) asError.
|
method(#primitive) asError.
|
||||||
}
|
}
|
||||||
|
|
||||||
class(#liword) LargeInteger(Integer)
|
class(#liword,#limited) LargeInteger(Integer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
class(#liword) LargePositiveInteger(LargeInteger)
|
class(#liword,#immutable) LargePositiveInteger(LargeInteger)
|
||||||
{
|
{
|
||||||
method abs { ^self }
|
method abs { ^self }
|
||||||
method sign { ^1 }
|
method sign { ^1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
class(#liword) LargeNegativeInteger(LargeInteger)
|
class(#liword,#immutable) LargeNegativeInteger(LargeInteger)
|
||||||
{
|
{
|
||||||
method abs { ^self negated }
|
method abs { ^self negated }
|
||||||
method sign { ^-1 }
|
method sign { ^-1 }
|
||||||
|
@ -52,7 +52,8 @@ enum class_mod_t
|
|||||||
{
|
{
|
||||||
CLASS_FINAL = (1 << 0),
|
CLASS_FINAL = (1 << 0),
|
||||||
CLASS_LIMITED = (1 << 1),
|
CLASS_LIMITED = (1 << 1),
|
||||||
CLASS_INDEXED = (1 << 2)
|
CLASS_INDEXED = (1 << 2),
|
||||||
|
CLASS_IMMUTABLE = (1 << 3)
|
||||||
};
|
};
|
||||||
|
|
||||||
enum var_type_t
|
enum var_type_t
|
||||||
@ -107,6 +108,7 @@ static struct voca_t
|
|||||||
{ 4, { 'f','r','o','m' } },
|
{ 4, { 'f','r','o','m' } },
|
||||||
{ 9, { '#','h','a','l','f','w','o','r','d' } },
|
{ 9, { '#','h','a','l','f','w','o','r','d' } },
|
||||||
{ 2, { 'i','f' } },
|
{ 2, { 'i','f' } },
|
||||||
|
{ 10, { '#','i','m','m','u','t','a','b','l','e' } },
|
||||||
{ 6, { 'i','m','p','o','r','t' } },
|
{ 6, { 'i','m','p','o','r','t' } },
|
||||||
{ 8, { '#','i','n','c','l','u','d','e' } },
|
{ 8, { '#','i','n','c','l','u','d','e' } },
|
||||||
{ 8, { '#','l','i','b','e','r','a','l' } },
|
{ 8, { '#','l','i','b','e','r','a','l' } },
|
||||||
@ -165,6 +167,7 @@ enum voca_id_t
|
|||||||
VOCA_FROM,
|
VOCA_FROM,
|
||||||
VOCA_HALFWORD_S,
|
VOCA_HALFWORD_S,
|
||||||
VOCA_IF,
|
VOCA_IF,
|
||||||
|
VOCA_IMMUTABLE_S,
|
||||||
VOCA_IMPORT,
|
VOCA_IMPORT,
|
||||||
VOCA_INCLUDE_S,
|
VOCA_INCLUDE_S,
|
||||||
VOCA_LIBERAL_S,
|
VOCA_LIBERAL_S,
|
||||||
@ -6407,9 +6410,10 @@ static int make_defined_class (moo_t* moo)
|
|||||||
moo_oow_t spec, self_spec;
|
moo_oow_t spec, self_spec;
|
||||||
int just_made = 0, flags;
|
int just_made = 0, flags;
|
||||||
|
|
||||||
spec = MOO_CLASS_SPEC_MAKE (moo->c->cls.var[VAR_INSTANCE].total_count,
|
flags = 0;
|
||||||
((moo->c->cls.flags & CLASS_INDEXED)? 1: 0),
|
if (moo->c->cls.flags & CLASS_INDEXED) flags |= MOO_CLASS_SPEC_FLAG_INDEXED;
|
||||||
moo->c->cls.indexed_type);
|
if (moo->c->cls.flags & CLASS_IMMUTABLE) flags |= MOO_CLASS_SPEC_FLAG_IMMUTABLE;
|
||||||
|
spec = MOO_CLASS_SPEC_MAKE (moo->c->cls.var[VAR_INSTANCE].total_count, flags, moo->c->cls.indexed_type);
|
||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
if (moo->c->cls.flags & CLASS_FINAL) flags |= MOO_CLASS_SELFSPEC_FLAG_FINAL;
|
if (moo->c->cls.flags & CLASS_FINAL) flags |= MOO_CLASS_SELFSPEC_FLAG_FINAL;
|
||||||
@ -6656,6 +6660,16 @@ static int __compile_class_definition (moo_t* moo, int extend)
|
|||||||
moo->c->cls.flags |= CLASS_LIMITED;
|
moo->c->cls.flags |= CLASS_LIMITED;
|
||||||
GET_TOKEN(moo);
|
GET_TOKEN(moo);
|
||||||
}
|
}
|
||||||
|
else if (is_token_symbol(moo, VOCA_IMMUTABLE_S))
|
||||||
|
{
|
||||||
|
if (moo->c->cls.flags & CLASS_IMMUTABLE)
|
||||||
|
{
|
||||||
|
set_syntax_error (moo, MOO_SYNERR_MODIFIERDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
moo->c->cls.flags |= CLASS_IMMUTABLE;
|
||||||
|
GET_TOKEN(moo);
|
||||||
|
}
|
||||||
else if (TOKEN_TYPE(moo) == MOO_IOTOK_COMMA || TOKEN_TYPE(moo) == MOO_IOTOK_EOF || TOKEN_TYPE(moo) == MOO_IOTOK_RPAREN)
|
else if (TOKEN_TYPE(moo) == MOO_IOTOK_COMMA || TOKEN_TYPE(moo) == MOO_IOTOK_EOF || TOKEN_TYPE(moo) == MOO_IOTOK_RPAREN)
|
||||||
{
|
{
|
||||||
/* no modifier is present */
|
/* no modifier is present */
|
||||||
|
@ -1648,7 +1648,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
|
|||||||
|
|
||||||
if (MOO_OBJ_GET_FLAGS_RDONLY(rcv))
|
if (MOO_OBJ_GET_FLAGS_RDONLY(rcv))
|
||||||
{
|
{
|
||||||
/* TODO: better error handlign */
|
/* TODO: better error handling */
|
||||||
moo->errnum = MOO_EPERM;
|
moo->errnum = MOO_EPERM;
|
||||||
return MOO_PF_FAILURE;
|
return MOO_PF_FAILURE;
|
||||||
}
|
}
|
||||||
@ -1669,15 +1669,6 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
|
|||||||
return MOO_PF_FAILURE;
|
return MOO_PF_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MOO_OBJ_GET_CLASS(rcv) == moo->_symbol)
|
|
||||||
{
|
|
||||||
/* TODO: disallow change of some key kernel objects???? */
|
|
||||||
/* TODO: is it better to introduct a read-only mark in the object header instead of this class check??? */
|
|
||||||
/* read-only object */ /* TODO: DEVISE A WAY TO PASS a proper error from the primitive handler to MOO */
|
|
||||||
moo->errnum = MOO_EINVAL;
|
|
||||||
return MOO_PF_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (MOO_OBJ_GET_FLAGS_TYPE(rcv))
|
switch (MOO_OBJ_GET_FLAGS_TYPE(rcv))
|
||||||
{
|
{
|
||||||
case MOO_OBJ_TYPE_BYTE:
|
case MOO_OBJ_TYPE_BYTE:
|
||||||
|
20
moo/lib/gc.c
20
moo/lib/gc.c
@ -174,14 +174,14 @@ static int ignite_1 (moo_t* moo)
|
|||||||
moo->_apex = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
moo->_apex = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_undefined_object = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
moo->_undefined_object = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_object = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
moo->_object = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_string = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 1, MOO_OBJ_TYPE_CHAR));
|
moo->_string = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_CHAR));
|
||||||
|
|
||||||
moo->_symbol = alloc_kernel_class (moo,
|
moo->_symbol = alloc_kernel_class (moo,
|
||||||
MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED,
|
MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED,
|
||||||
0, MOO_CLASS_SPEC_MAKE(0, 1, MOO_OBJ_TYPE_CHAR));
|
0, MOO_CLASS_SPEC_MAKE(0, MOO_CLASS_SPEC_FLAG_INDEXED | MOO_CLASS_SPEC_FLAG_IMMUTABLE, MOO_OBJ_TYPE_CHAR));
|
||||||
|
|
||||||
moo->_array = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 1, MOO_OBJ_TYPE_OOP));
|
moo->_array = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_byte_array = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 1, MOO_OBJ_TYPE_BYTE));
|
moo->_byte_array = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_BYTE));
|
||||||
moo->_symbol_set = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SET_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
moo->_symbol_set = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SET_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_dictionary = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SET_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
moo->_dictionary = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SET_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_system_dictionary = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SET_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
moo->_system_dictionary = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SET_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
||||||
@ -189,15 +189,15 @@ static int ignite_1 (moo_t* moo)
|
|||||||
moo->_namespace = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SET_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
moo->_namespace = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SET_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_pool_dictionary = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SET_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
moo->_pool_dictionary = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SET_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_method_dictionary = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SET_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
moo->_method_dictionary = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SET_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_method = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_METHOD_NAMED_INSTVARS, 1, MOO_OBJ_TYPE_OOP));
|
moo->_method = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_METHOD_NAMED_INSTVARS, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_association = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_ASSOCIATION_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
moo->_association = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_ASSOCIATION_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
||||||
|
|
||||||
moo->_method_context = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_CONTEXT_NAMED_INSTVARS, 1, MOO_OBJ_TYPE_OOP));
|
moo->_method_context = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_CONTEXT_NAMED_INSTVARS, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_block_context = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_CONTEXT_NAMED_INSTVARS, 1, MOO_OBJ_TYPE_OOP));
|
moo->_block_context = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_CONTEXT_NAMED_INSTVARS, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_OOP));
|
||||||
|
|
||||||
moo->_process = alloc_kernel_class (moo,
|
moo->_process = alloc_kernel_class (moo,
|
||||||
MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED,
|
MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED,
|
||||||
0, MOO_CLASS_SPEC_MAKE(MOO_PROCESS_NAMED_INSTVARS, 1, MOO_OBJ_TYPE_OOP));
|
0, MOO_CLASS_SPEC_MAKE(MOO_PROCESS_NAMED_INSTVARS, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_OOP));
|
||||||
|
|
||||||
moo->_semaphore = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SEMAPHORE_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
moo->_semaphore = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(MOO_SEMAPHORE_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_process_scheduler = alloc_kernel_class (moo,
|
moo->_process_scheduler = alloc_kernel_class (moo,
|
||||||
@ -212,8 +212,8 @@ static int ignite_1 (moo_t* moo)
|
|||||||
* Does this make sense? */
|
* Does this make sense? */
|
||||||
moo->_character = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
moo->_character = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_small_integer = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
moo->_small_integer = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_large_positive_integer = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 1, MOO_OBJ_TYPE_LIWORD));
|
moo->_large_positive_integer = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, MOO_CLASS_SPEC_FLAG_INDEXED | MOO_CLASS_SPEC_FLAG_IMMUTABLE, MOO_OBJ_TYPE_LIWORD));
|
||||||
moo->_large_negative_integer = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 1, MOO_OBJ_TYPE_LIWORD));
|
moo->_large_negative_integer = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, MOO_CLASS_SPEC_FLAG_INDEXED | MOO_CLASS_SPEC_FLAG_IMMUTABLE, MOO_OBJ_TYPE_LIWORD));
|
||||||
|
|
||||||
moo->_small_pointer = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
moo->_small_pointer = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
||||||
moo->_system = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
moo->_system = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP));
|
||||||
|
@ -151,26 +151,32 @@
|
|||||||
* The MOO_CLASS_SPEC_MAKE() macro creates a class spec value.
|
* The MOO_CLASS_SPEC_MAKE() macro creates a class spec value.
|
||||||
* _class->spec = MOO_SMOOI_TO_OOP(MOO_CLASS_SPEC_MAKE(0, 1, MOO_OBJ_TYPE_CHAR));
|
* _class->spec = MOO_SMOOI_TO_OOP(MOO_CLASS_SPEC_MAKE(0, 1, MOO_OBJ_TYPE_CHAR));
|
||||||
*/
|
*/
|
||||||
#define MOO_CLASS_SPEC_MAKE(named_instvar,is_indexed,indexed_type) ( \
|
#define MOO_CLASS_SPEC_MAKE(named_instvar,flags,indexed_type) ( \
|
||||||
(((moo_oow_t)(named_instvar)) << (MOO_OBJ_FLAGS_TYPE_BITS + 1)) | \
|
(((moo_oow_t)(named_instvar)) << (MOO_OBJ_FLAGS_TYPE_BITS + 2)) | \
|
||||||
(((moo_oow_t)(indexed_type)) << 1) | (((moo_oow_t)is_indexed) & 1) )
|
(((moo_oow_t)(indexed_type)) << 2) | (((moo_oow_t)flags) & 3) )
|
||||||
|
|
||||||
/* what is the number of named instance variables?
|
/* what is the number of named instance variables?
|
||||||
* MOO_CLASS_SPEC_NAMED_INSTVARS(MOO_OOP_TO_SMOOI(_class->spec))
|
* MOO_CLASS_SPEC_NAMED_INSTVARS(MOO_OOP_TO_SMOOI(_class->spec))
|
||||||
*/
|
*/
|
||||||
#define MOO_CLASS_SPEC_NAMED_INSTVARS(spec) \
|
#define MOO_CLASS_SPEC_NAMED_INSTVARS(spec) \
|
||||||
(((moo_oow_t)(spec)) >> (MOO_OBJ_FLAGS_TYPE_BITS + 1))
|
(((moo_oow_t)(spec)) >> (MOO_OBJ_FLAGS_TYPE_BITS + 2))
|
||||||
|
|
||||||
/* is it a user-indexable class?
|
/* is it a user-indexable class?
|
||||||
* all objects can be indexed with basicAt:.
|
* all objects can be indexed with basicAt:.
|
||||||
* this indicates if an object can be instantiated with a dynamic size
|
* this indicates if an object can be instantiated with a dynamic size
|
||||||
* (new: size) and and can be indexed with at:.
|
* (new: size) and and can be indexed with at:.
|
||||||
*/
|
*/
|
||||||
#define MOO_CLASS_SPEC_IS_INDEXED(spec) (((moo_oow_t)(spec)) & 1)
|
#define MOO_CLASS_SPEC_FLAGS(spec) (((moo_oow_t)(spec)) & 3)
|
||||||
|
|
||||||
/* if so, what is the indexing type? character? pointer? etc? */
|
/* if so, what is the indexing type? character? pointer? etc? */
|
||||||
#define MOO_CLASS_SPEC_INDEXED_TYPE(spec) \
|
#define MOO_CLASS_SPEC_INDEXED_TYPE(spec) \
|
||||||
((((moo_oow_t)(spec)) >> 1) & MOO_LBMASK(moo_oow_t, MOO_OBJ_FLAGS_TYPE_BITS))
|
((((moo_oow_t)(spec)) >> 2) & MOO_LBMASK(moo_oow_t, MOO_OBJ_FLAGS_TYPE_BITS))
|
||||||
|
|
||||||
|
#define MOO_CLASS_SPEC_FLAG_INDEXED (1 << 0)
|
||||||
|
#define MOO_CLASS_SPEC_FLAG_IMMUTABLE (1 << 1)
|
||||||
|
|
||||||
|
#define MOO_CLASS_SPEC_IS_INDEXED(spec) (MOO_CLASS_SPEC_FLAGS(spec) & MOO_CLASS_SPEC_FLAG_INDEXED)
|
||||||
|
#define MOO_CLASS_SPEC_IS_IMMUTABLE(spec) (MOO_CLASS_SPEC_FLAGS(spec) & MOO_CLASS_SPEC_FLAG_IMMUTABLE)
|
||||||
|
|
||||||
/* What is the maximum number of named instance variables?
|
/* What is the maximum number of named instance variables?
|
||||||
* This limit is set so because the number must be encoded into the spec field
|
* This limit is set so because the number must be encoded into the spec field
|
||||||
@ -180,7 +186,7 @@
|
|||||||
* type of the spec field in the class object.
|
* type of the spec field in the class object.
|
||||||
*/
|
*/
|
||||||
#define MOO_MAX_NAMED_INSTVARS \
|
#define MOO_MAX_NAMED_INSTVARS \
|
||||||
MOO_BITS_MAX(moo_oow_t, MOO_SMOOI_ABS_BITS - (MOO_OBJ_FLAGS_TYPE_BITS + 1))
|
MOO_BITS_MAX(moo_oow_t, MOO_SMOOI_ABS_BITS - (MOO_OBJ_FLAGS_TYPE_BITS + 2))
|
||||||
|
|
||||||
/* Given the number of named instance variables, what is the maximum number
|
/* Given the number of named instance variables, what is the maximum number
|
||||||
* of indexed instance variables? The number of indexed instance variables
|
* of indexed instance variables? The number of indexed instance variables
|
||||||
|
@ -155,22 +155,22 @@ static MOO_INLINE moo_oop_t alloc_numeric_array (moo_t* moo, const void* ptr, mo
|
|||||||
return hdr;
|
return hdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
moo_oop_t moo_alloccharobj (moo_t* moo, const moo_ooch_t* ptr, moo_oow_t len)
|
MOO_INLINE moo_oop_t moo_alloccharobj (moo_t* moo, const moo_ooch_t* ptr, moo_oow_t len)
|
||||||
{
|
{
|
||||||
return alloc_numeric_array (moo, ptr, len, MOO_OBJ_TYPE_CHAR, MOO_SIZEOF(moo_ooch_t), 1);
|
return alloc_numeric_array (moo, ptr, len, MOO_OBJ_TYPE_CHAR, MOO_SIZEOF(moo_ooch_t), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
moo_oop_t moo_allocbyteobj (moo_t* moo, const moo_oob_t* ptr, moo_oow_t len)
|
MOO_INLINE moo_oop_t moo_allocbyteobj (moo_t* moo, const moo_oob_t* ptr, moo_oow_t len)
|
||||||
{
|
{
|
||||||
return alloc_numeric_array (moo, ptr, len, MOO_OBJ_TYPE_BYTE, MOO_SIZEOF(moo_oob_t), 0);
|
return alloc_numeric_array (moo, ptr, len, MOO_OBJ_TYPE_BYTE, MOO_SIZEOF(moo_oob_t), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
moo_oop_t moo_allochalfwordobj (moo_t* moo, const moo_oohw_t* ptr, moo_oow_t len)
|
MOO_INLINE moo_oop_t moo_allochalfwordobj (moo_t* moo, const moo_oohw_t* ptr, moo_oow_t len)
|
||||||
{
|
{
|
||||||
return alloc_numeric_array (moo, ptr, len, MOO_OBJ_TYPE_HALFWORD, MOO_SIZEOF(moo_oohw_t), 0);
|
return alloc_numeric_array (moo, ptr, len, MOO_OBJ_TYPE_HALFWORD, MOO_SIZEOF(moo_oohw_t), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
moo_oop_t moo_allocwordobj (moo_t* moo, const moo_oow_t* ptr, moo_oow_t len)
|
MOO_INLINE moo_oop_t moo_allocwordobj (moo_t* moo, const moo_oow_t* ptr, moo_oow_t len)
|
||||||
{
|
{
|
||||||
return alloc_numeric_array (moo, ptr, len, MOO_OBJ_TYPE_WORD, MOO_SIZEOF(moo_oow_t), 0);
|
return alloc_numeric_array (moo, ptr, len, MOO_OBJ_TYPE_WORD, MOO_SIZEOF(moo_oow_t), 0);
|
||||||
}
|
}
|
||||||
@ -332,60 +332,11 @@ moo_oop_t moo_instantiate (moo_t* moo, moo_oop_class_t _class, const void* vptr,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oop) MOO_OBJ_SET_CLASS (oop, (moo_oop_t)_class);
|
if (oop)
|
||||||
moo_poptmps (moo, tmp_count);
|
|
||||||
return oop;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: ... */
|
|
||||||
moo_oop_t moo_instantiate2 (moo_t* moo, moo_oop_class_t _class, const void* vptr, moo_oow_t vlen, int ngc)
|
|
||||||
{
|
|
||||||
moo_oop_t oop;
|
|
||||||
moo_obj_type_t type;
|
|
||||||
moo_oow_t alloclen;
|
|
||||||
moo_oow_t tmp_count = 0;
|
|
||||||
|
|
||||||
MOO_ASSERT (moo, moo->_nil != MOO_NULL);
|
|
||||||
|
|
||||||
if (decode_spec (moo, _class, vlen, &type, &alloclen) <= -1)
|
|
||||||
{
|
{
|
||||||
moo->errnum = MOO_EINVAL;
|
MOO_OBJ_SET_CLASS (oop, (moo_oop_t)_class);
|
||||||
return MOO_NULL;
|
if (MOO_CLASS_SPEC_IS_IMMUTABLE(MOO_OOP_TO_SMOOI(_class->spec))) MOO_OBJ_SET_FLAGS_RDONLY (oop, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
moo_pushtmp (moo, (moo_oop_t*)&_class); tmp_count++;
|
|
||||||
|
|
||||||
/* TODO: support NGC */
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case MOO_OBJ_TYPE_OOP:
|
|
||||||
/* [NOTE] vptr is not used for GC unsafety. read comment in moo_instantiate() */
|
|
||||||
oop = moo_allocoopobj (moo, alloclen);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MOO_OBJ_TYPE_CHAR:
|
|
||||||
oop = moo_alloccharobj (moo, vptr, alloclen);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MOO_OBJ_TYPE_BYTE:
|
|
||||||
oop = moo_allocbyteobj (moo, vptr, alloclen);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MOO_OBJ_TYPE_HALFWORD:
|
|
||||||
oop = moo_allochalfwordobj (moo, vptr, alloclen);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MOO_OBJ_TYPE_WORD:
|
|
||||||
oop = moo_allocwordobj (moo, vptr, alloclen);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
moo->errnum = MOO_EINTERN;
|
|
||||||
oop = MOO_NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oop) MOO_OBJ_SET_CLASS (oop, _class);
|
|
||||||
moo_poptmps (moo, tmp_count);
|
moo_poptmps (moo, tmp_count);
|
||||||
return oop;
|
return oop;
|
||||||
}
|
}
|
||||||
@ -411,6 +362,26 @@ moo_oop_t moo_instantiatewithtrailer (moo_t* moo, moo_oop_class_t _class, moo_oo
|
|||||||
{
|
{
|
||||||
case MOO_OBJ_TYPE_OOP:
|
case MOO_OBJ_TYPE_OOP:
|
||||||
oop = moo_allocoopobjwithtrailer(moo, alloclen, trptr, trlen);
|
oop = moo_allocoopobjwithtrailer(moo, alloclen, trptr, trlen);
|
||||||
|
if (oop)
|
||||||
|
{
|
||||||
|
/* initialize named instance variables with default values */
|
||||||
|
if (_class->initv[0] != moo->_nil)
|
||||||
|
{
|
||||||
|
moo_oow_t i = MOO_OBJ_GET_SIZE(_class->initv[0]);
|
||||||
|
|
||||||
|
/* [NOTE] i don't deep-copy initial values.
|
||||||
|
* if you change the contents of compound values like arrays,
|
||||||
|
* it affects subsequent instantiation of the class.
|
||||||
|
* it's important that the compiler should mark compound initial
|
||||||
|
* values read-only. */
|
||||||
|
while (i > 0)
|
||||||
|
{
|
||||||
|
--i;
|
||||||
|
((moo_oop_oop_t)oop)->slot[i] = ((moo_oop_oop_t)_class->initv[0])->slot[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -424,7 +395,11 @@ moo_oop_t moo_instantiatewithtrailer (moo_t* moo, moo_oop_class_t _class, moo_oo
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oop) MOO_OBJ_SET_CLASS (oop, _class);
|
if (oop)
|
||||||
|
{
|
||||||
|
MOO_OBJ_SET_CLASS (oop, _class);
|
||||||
|
if (MOO_CLASS_SPEC_IS_IMMUTABLE(MOO_OOP_TO_SMOOI(_class->spec))) MOO_OBJ_SET_FLAGS_RDONLY (oop, 1);
|
||||||
|
}
|
||||||
moo_poptmps (moo, tmp_count);
|
moo_poptmps (moo, tmp_count);
|
||||||
return oop;
|
return oop;
|
||||||
}
|
}
|
||||||
|
@ -158,9 +158,6 @@ static moo_oop_t find_or_make_symbol (moo_t* moo, const moo_ooch_t* ptr, moo_oow
|
|||||||
MOO_ASSERT (moo, tally < MOO_SMOOI_MAX);
|
MOO_ASSERT (moo, tally < MOO_SMOOI_MAX);
|
||||||
moo->symtab->tally = MOO_SMOOI_TO_OOP(tally + 1);
|
moo->symtab->tally = MOO_SMOOI_TO_OOP(tally + 1);
|
||||||
moo->symtab->bucket->slot[index] = (moo_oop_t)symbol;
|
moo->symtab->bucket->slot[index] = (moo_oop_t)symbol;
|
||||||
|
|
||||||
/* set RDONLY on a symbol */
|
|
||||||
MOO_OBJ_SET_FLAGS_RDONLY (symbol, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (moo_oop_t)symbol;
|
return (moo_oop_t)symbol;
|
||||||
|
Loading…
Reference in New Issue
Block a user