From 63519c1ca3c3701e7323d9134baa3fa3fb9b55c4 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Sun, 7 May 2017 05:18:21 +0000 Subject: [PATCH] introduced a new class modifier #immutable to indicate that an instantiated object cannot be modified using basicAt:put: --- moo/kernel/Collect.moo | 2 +- moo/kernel/Magnitu.moo | 8 ++-- moo/lib/comp.c | 30 ++++++++++---- moo/lib/exec.c | 11 +----- moo/lib/gc.c | 20 +++++----- moo/lib/moo-prv.h | 20 ++++++---- moo/lib/obj.c | 89 +++++++++++++++--------------------------- moo/lib/sym.c | 3 -- 8 files changed, 83 insertions(+), 100 deletions(-) diff --git a/moo/kernel/Collect.moo b/moo/kernel/Collect.moo index e16be02..932ecd7 100644 --- a/moo/kernel/Collect.moo +++ b/moo/kernel/Collect.moo @@ -116,7 +116,7 @@ class(#character) String(Array) ## ------------------------------------------------------------------------------- -class(#character,#final,#limited) Symbol(String) +class(#character,#final,#limited,#immutable) Symbol(String) { method asString { diff --git a/moo/kernel/Magnitu.moo b/moo/kernel/Magnitu.moo index 075e4da..b6ef0bd 100644 --- a/moo/kernel/Magnitu.moo +++ b/moo/kernel/Magnitu.moo @@ -291,7 +291,7 @@ class Number(Magnitude) } } -class Integer(Number) +class(#limited) Integer(Number) { method timesRepeat: aBlock { @@ -310,17 +310,17 @@ class SmallInteger(Integer) 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 sign { ^1 } } -class(#liword) LargeNegativeInteger(LargeInteger) +class(#liword,#immutable) LargeNegativeInteger(LargeInteger) { method abs { ^self negated } method sign { ^-1 } diff --git a/moo/lib/comp.c b/moo/lib/comp.c index d379980..217bf83 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -50,9 +50,10 @@ enum class_mod_t { - CLASS_FINAL = (1 << 0), - CLASS_LIMITED = (1 << 1), - CLASS_INDEXED = (1 << 2) + CLASS_FINAL = (1 << 0), + CLASS_LIMITED = (1 << 1), + CLASS_INDEXED = (1 << 2), + CLASS_IMMUTABLE = (1 << 3) }; enum var_type_t @@ -107,6 +108,7 @@ static struct voca_t { 4, { 'f','r','o','m' } }, { 9, { '#','h','a','l','f','w','o','r','d' } }, { 2, { 'i','f' } }, + { 10, { '#','i','m','m','u','t','a','b','l','e' } }, { 6, { 'i','m','p','o','r','t' } }, { 8, { '#','i','n','c','l','u','d','e' } }, { 8, { '#','l','i','b','e','r','a','l' } }, @@ -165,6 +167,7 @@ enum voca_id_t VOCA_FROM, VOCA_HALFWORD_S, VOCA_IF, + VOCA_IMMUTABLE_S, VOCA_IMPORT, VOCA_INCLUDE_S, VOCA_LIBERAL_S, @@ -6407,9 +6410,10 @@ static int make_defined_class (moo_t* moo) moo_oow_t spec, self_spec; int just_made = 0, flags; - spec = MOO_CLASS_SPEC_MAKE (moo->c->cls.var[VAR_INSTANCE].total_count, - ((moo->c->cls.flags & CLASS_INDEXED)? 1: 0), - moo->c->cls.indexed_type); + flags = 0; + if (moo->c->cls.flags & CLASS_INDEXED) flags |= MOO_CLASS_SPEC_FLAG_INDEXED; + 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; 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; 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) { - /* no modifier is present */ + /* no modifier is present */ set_syntax_error (moo, MOO_SYNERR_MODIFIER, TOKEN_LOC(moo), TOKEN_NAME(moo)); return -1; } else { - /* invalid modifier */ + /* invalid modifier */ set_syntax_error (moo, MOO_SYNERR_MODIFIERINVAL, TOKEN_LOC(moo), TOKEN_NAME(moo)); return -1; } diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 73f2d11..b6c598f 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -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)) { -/* TODO: better error handlign */ +/* TODO: better error handling */ moo->errnum = MOO_EPERM; 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; } - 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)) { case MOO_OBJ_TYPE_BYTE: diff --git a/moo/lib/gc.c b/moo/lib/gc.c index 6b1a394..91db74d 100644 --- a/moo/lib/gc.c +++ b/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->_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->_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_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->_byte_array = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 1, MOO_OBJ_TYPE_BYTE)); + 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, 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->_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->_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 = 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->_method_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, 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, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_OOP)); moo->_process = alloc_kernel_class (moo, 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->_process_scheduler = alloc_kernel_class (moo, @@ -212,8 +212,8 @@ static int ignite_1 (moo_t* moo) * Does this make sense? */ 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->_large_positive_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, 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, 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->_system = alloc_kernel_class (moo, 0, 0, MOO_CLASS_SPEC_MAKE(0, 0, MOO_OBJ_TYPE_OOP)); diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index cb8edcb..c4936d8 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -151,26 +151,32 @@ * 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)); */ -#define MOO_CLASS_SPEC_MAKE(named_instvar,is_indexed,indexed_type) ( \ - (((moo_oow_t)(named_instvar)) << (MOO_OBJ_FLAGS_TYPE_BITS + 1)) | \ - (((moo_oow_t)(indexed_type)) << 1) | (((moo_oow_t)is_indexed) & 1) ) +#define MOO_CLASS_SPEC_MAKE(named_instvar,flags,indexed_type) ( \ + (((moo_oow_t)(named_instvar)) << (MOO_OBJ_FLAGS_TYPE_BITS + 2)) | \ + (((moo_oow_t)(indexed_type)) << 2) | (((moo_oow_t)flags) & 3) ) /* what is the number of named instance variables? * MOO_CLASS_SPEC_NAMED_INSTVARS(MOO_OOP_TO_SMOOI(_class->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? * all objects can be indexed with basicAt:. * this indicates if an object can be instantiated with a dynamic size * (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? */ #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? * 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. */ #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 * of indexed instance variables? The number of indexed instance variables diff --git a/moo/lib/obj.c b/moo/lib/obj.c index f2faa13..f0bfc56 100644 --- a/moo/lib/obj.c +++ b/moo/lib/obj.c @@ -155,22 +155,22 @@ static MOO_INLINE moo_oop_t alloc_numeric_array (moo_t* moo, const void* ptr, mo 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); } -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); } -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); } -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); } @@ -332,60 +332,11 @@ moo_oop_t moo_instantiate (moo_t* moo, moo_oop_class_t _class, const void* vptr, break; } - if (oop) MOO_OBJ_SET_CLASS (oop, (moo_oop_t)_class); - 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) + if (oop) { - moo->errnum = MOO_EINVAL; - return MOO_NULL; + MOO_OBJ_SET_CLASS (oop, (moo_oop_t)_class); + 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); 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: 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; default: @@ -424,7 +395,11 @@ moo_oop_t moo_instantiatewithtrailer (moo_t* moo, moo_oop_class_t _class, moo_oo 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); return oop; } diff --git a/moo/lib/sym.c b/moo/lib/sym.c index e8863bb..2cac124 100644 --- a/moo/lib/sym.c +++ b/moo/lib/sym.c @@ -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->symtab->tally = MOO_SMOOI_TO_OOP(tally + 1); 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;