introduced a new class modifier #immutable to indicate that an instantiated object cannot be modified using basicAt:put:

This commit is contained in:
hyunghwan.chung 2017-05-07 05:18:21 +00:00
parent 1dff630fdd
commit 63519c1ca3
8 changed files with 83 additions and 100 deletions

View File

@ -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
{ {

View File

@ -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 }

View File

@ -50,9 +50,10 @@
enum class_mod_t 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,15 +6660,25 @@ 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 */
set_syntax_error (moo, MOO_SYNERR_MODIFIER, TOKEN_LOC(moo), TOKEN_NAME(moo)); set_syntax_error (moo, MOO_SYNERR_MODIFIER, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1; return -1;
} }
else else
{ {
/* invalid modifier */ /* invalid modifier */
set_syntax_error (moo, MOO_SYNERR_MODIFIERINVAL, TOKEN_LOC(moo), TOKEN_NAME(moo)); set_syntax_error (moo, MOO_SYNERR_MODIFIERINVAL, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1; return -1;
} }

View File

@ -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:

View File

@ -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));

View File

@ -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

View File

@ -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;
} }

View File

@ -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;