fixed an initial value handling bug and implemented getter and setter generation when a variable is set with #get and/or #set
This commit is contained in:
parent
34a5e0cab8
commit
307c43eb3e
@ -40,8 +40,8 @@ class TestObject(Object)
|
||||
|
||||
class B.TestObject(Object)
|
||||
{
|
||||
dcl(#class) Q, R.
|
||||
dcl(#classinst) a1, a2.
|
||||
var(#class) Q, R.
|
||||
var(#classinst) a1, a2.
|
||||
|
||||
method test000
|
||||
{
|
||||
|
316
moo/lib/comp.c
316
moo/lib/comp.c
@ -73,11 +73,25 @@ enum var_type_t
|
||||
};
|
||||
typedef enum var_type_t var_type_t;
|
||||
|
||||
enum varacc_type_t
|
||||
{
|
||||
VARACC_GETTER = (1 << 0),
|
||||
VARACC_SETTER = (1 << 1)
|
||||
};
|
||||
typedef enum varacc_type_t varacc_type_t;
|
||||
|
||||
struct var_info_t
|
||||
{
|
||||
var_type_t type;
|
||||
moo_ooi_t pos; /* not used for VAR_GLOBAL */
|
||||
moo_oop_class_t cls; /* useful if type is VAR_CLASS(class variable). note MOO_NULL indicates the self class. */
|
||||
|
||||
/* not used for VAR_GLOBAL */
|
||||
moo_ooi_t pos;
|
||||
|
||||
/* useful if type is VAR_CLASS(class variable).
|
||||
* note it may be set to MOO_NULL to indicate the self class when
|
||||
* the current class being compiled has not been instantiated. */
|
||||
moo_oop_class_t cls;
|
||||
|
||||
union
|
||||
{
|
||||
moo_oop_association_t gbl; /* used for VAR_GLOBAL only */
|
||||
@ -98,7 +112,6 @@ static struct voca_t
|
||||
{ 6, { '#','c','l','a','s','s' } },
|
||||
{ 10, { '#','c','l','a','s','s','i','n','s','t' } },
|
||||
{ 8, { 'c','o','n','t','i','n','u','e' } },
|
||||
{ 3, { 'd','c','l' } },
|
||||
{ 2, { 'd','o' } },
|
||||
{ 5, { '#','d','u','a','l' } },
|
||||
{ 4, { 'e','l','s','e' } },
|
||||
@ -110,6 +123,7 @@ static struct voca_t
|
||||
{ 5, { 'f','a','l','s','e' } },
|
||||
{ 6, { '#','f','i','n','a','l' } },
|
||||
{ 4, { 'f','r','o','m' } },
|
||||
{ 4, { '#','g','e','t' } },
|
||||
{ 9, { '#','h','a','l','f','w','o','r','d' } },
|
||||
{ 2, { 'i','f' } },
|
||||
{ 10, { '#','i','m','m','u','t','a','b','l','e' } },
|
||||
@ -128,6 +142,7 @@ static struct voca_t
|
||||
{ 10, { '#','p','r','i','m','i','t','i','v','e' } },
|
||||
{ 4, { 's','e','l','f' } },
|
||||
{ 6, { 's','e','l','f','n','s' } },
|
||||
{ 4, { '#','s','e','t' } },
|
||||
{ 5, { 's','u','p','e','r' } },
|
||||
{ 11, { 't','h','i','s','C','o','n','t','e','x','t' } },
|
||||
{ 11, { 't','h','i','s','P','r','o','c','e','s','s' } },
|
||||
@ -157,7 +172,6 @@ enum voca_id_t
|
||||
VOCA_CLASS_S,
|
||||
VOCA_CLASSINST_S,
|
||||
VOCA_CONTINUE,
|
||||
VOCA_DCL,
|
||||
VOCA_DO,
|
||||
VOCA_DUAL_S,
|
||||
VOCA_ELSE,
|
||||
@ -169,6 +183,7 @@ enum voca_id_t
|
||||
VOCA_FALSE,
|
||||
VOCA_FINAL_S,
|
||||
VOCA_FROM,
|
||||
VOCA_GET_S,
|
||||
VOCA_HALFWORD_S,
|
||||
VOCA_IF,
|
||||
VOCA_IMMUTABLE_S,
|
||||
@ -187,6 +202,7 @@ enum voca_id_t
|
||||
VOCA_PRIMITIVE_S,
|
||||
VOCA_SELF,
|
||||
VOCA_SELFNS,
|
||||
VOCA_SET_S,
|
||||
VOCA_SUPER,
|
||||
VOCA_THIS_CONTEXT,
|
||||
VOCA_THIS_PROCESS,
|
||||
@ -353,6 +369,7 @@ static int is_reserved_word (const moo_oocs_t* ucs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int is_restricted_word (const moo_oocs_t* ucs)
|
||||
{
|
||||
/* not fully reserved. but restricted in a certain context */
|
||||
@ -360,7 +377,6 @@ static int is_restricted_word (const moo_oocs_t* ucs)
|
||||
static int rw[] =
|
||||
{
|
||||
VOCA_CLASS,
|
||||
VOCA_DCL,
|
||||
VOCA_EXTEND,
|
||||
VOCA_FROM,
|
||||
VOCA_IMPORT,
|
||||
@ -378,6 +394,7 @@ static int is_restricted_word (const moo_oocs_t* ucs)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int begin_include (moo_t* moo);
|
||||
static int end_include (moo_t* moo);
|
||||
@ -488,6 +505,35 @@ static int find_word_in_string (const moo_oocs_t* haystack, const moo_oocs_t* na
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int fetch_word_from_string (const moo_oocs_t* haystack, moo_oow_t xindex, moo_oocs_t* str)
|
||||
{
|
||||
moo_ooch_t* t, * e, * ss;
|
||||
moo_oow_t index;
|
||||
|
||||
t = haystack->ptr;
|
||||
e = t + haystack->len;
|
||||
index = 0;
|
||||
|
||||
while (t < e)
|
||||
{
|
||||
while (t < e && is_spacechar(*t)) t++;
|
||||
|
||||
ss = t;
|
||||
while (t < e && !is_spacechar(*t)) t++;
|
||||
|
||||
if (xindex == index)
|
||||
{
|
||||
str->ptr = ss;
|
||||
str->len = t - ss;
|
||||
return 0;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define CHAR_TO_NUM(c,base) \
|
||||
((c >= '0' && c <= '9')? ((c - '0' < base)? (c - '0'): base): \
|
||||
(c >= 'A' && c <= 'Z')? ((c - 'A' + 10 < base)? (c - 'A' + 10): base): \
|
||||
@ -2598,7 +2644,7 @@ static MOO_INLINE int add_class_level_variable (moo_t* moo, var_type_t var_type,
|
||||
return n;
|
||||
}
|
||||
|
||||
static int set_class_level_variable_initv (moo_t* moo, var_type_t var_type, moo_oow_t var_index, moo_oop_t initv)
|
||||
static int set_class_level_variable_initv (moo_t* moo, var_type_t var_type, moo_oow_t var_index, moo_oop_t initv, int flags)
|
||||
{
|
||||
if (var_index >= moo->c->cls.var[var_type].initv_capa)
|
||||
{
|
||||
@ -2632,7 +2678,7 @@ static int set_class_level_variable_initv (moo_t* moo, var_type_t var_type, moo_
|
||||
}
|
||||
|
||||
moo->c->cls.var[var_type].initv[var_index].v = initv;
|
||||
moo->c->cls.var[var_type].initv[var_index].flags = 0; /* TODO: set flags properly */
|
||||
moo->c->cls.var[var_type].initv[var_index].flags = flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3158,8 +3204,8 @@ if super is variable-nonpointer, no instance variable is allowed.
|
||||
}
|
||||
|
||||
if (find_class_level_variable(moo, MOO_NULL, TOKEN_NAME(moo), &var) >= 0 ||
|
||||
moo_lookupdic (moo, (moo_oop_dic_t)moo->sysdic, TOKEN_NAME(moo)) || /* conflicts with a top global name */
|
||||
moo_lookupdic (moo, (moo_oop_dic_t)moo->c->cls.ns_oop, TOKEN_NAME(moo))) /* conflicts with a global name in the class'es name space */
|
||||
moo_lookupdic(moo, (moo_oop_dic_t)moo->sysdic, TOKEN_NAME(moo)) || /* conflicts with a top global name */
|
||||
moo_lookupdic(moo, (moo_oop_dic_t)moo->c->cls.ns_oop, TOKEN_NAME(moo))) /* conflicts with a global name in the class'es name space */
|
||||
{
|
||||
set_syntax_error (moo, MOO_SYNERR_VARNAMEDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo));
|
||||
return -1;
|
||||
@ -3189,6 +3235,7 @@ if super is variable-nonpointer, no instance variable is allowed.
|
||||
static int compile_class_level_variables (moo_t* moo)
|
||||
{
|
||||
var_type_t dcl_type = VAR_INSTANCE;
|
||||
int varacc_type = 0;
|
||||
|
||||
if (TOKEN_TYPE(moo) == MOO_IOTOK_LPAREN)
|
||||
{
|
||||
@ -3223,6 +3270,30 @@ static int compile_class_level_variables (moo_t* moo)
|
||||
dcl_type = VAR_CLASSINST;
|
||||
GET_TOKEN (moo);
|
||||
}
|
||||
else if (is_token_symbol(moo, VOCA_GET_S))
|
||||
{
|
||||
/* variable(#get) */
|
||||
if (varacc_type & VARACC_GETTER)
|
||||
{
|
||||
set_syntax_error (moo, MOO_SYNERR_MODIFIERDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo));
|
||||
return -1;
|
||||
}
|
||||
|
||||
varacc_type |= VARACC_GETTER;
|
||||
GET_TOKEN (moo);
|
||||
}
|
||||
else if (is_token_symbol(moo, VOCA_SET_S))
|
||||
{
|
||||
/* variable(#set) */
|
||||
if (varacc_type & VARACC_SETTER)
|
||||
{
|
||||
set_syntax_error (moo, MOO_SYNERR_MODIFIERDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo));
|
||||
return -1;
|
||||
}
|
||||
|
||||
varacc_type |= VARACC_SETTER;
|
||||
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 */
|
||||
@ -3275,8 +3346,8 @@ if super is variable-nonpointer, no instance variable is allowed.
|
||||
}
|
||||
|
||||
if (find_class_level_variable(moo, MOO_NULL, TOKEN_NAME(moo), &var) >= 0 ||
|
||||
moo_lookupdic (moo, (moo_oop_dic_t)moo->sysdic, TOKEN_NAME(moo)) || /* conflicts with a top global name */
|
||||
moo_lookupdic (moo, (moo_oop_dic_t)moo->c->cls.ns_oop, TOKEN_NAME(moo))) /* conflicts with a global name in the class'es name space */
|
||||
moo_lookupdic(moo, (moo_oop_dic_t)moo->sysdic, TOKEN_NAME(moo)) || /* conflicts with a top global name */
|
||||
moo_lookupdic(moo, (moo_oop_dic_t)moo->c->cls.ns_oop, TOKEN_NAME(moo))) /* conflicts with a global name in the class'es name space */
|
||||
{
|
||||
set_syntax_error (moo, MOO_SYNERR_VARNAMEDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo));
|
||||
return -1;
|
||||
@ -3302,10 +3373,16 @@ if super is variable-nonpointer, no instance variable is allowed.
|
||||
if (!lit) return -1;
|
||||
|
||||
/* set the initial value for the variable added above */
|
||||
if (set_class_level_variable_initv (moo, dcl_type, moo->c->cls.var[dcl_type].count - 1, lit) <= -1) return -1;
|
||||
if (set_class_level_variable_initv (moo, dcl_type, moo->c->cls.var[dcl_type].count - 1, lit, varacc_type) <= -1) return -1;
|
||||
|
||||
GET_TOKEN (moo);
|
||||
}
|
||||
else if (varacc_type)
|
||||
{
|
||||
/* this part is to remember the variable access type that indicates
|
||||
* whether to generate a getter method and a setter method */
|
||||
if (set_class_level_variable_initv (moo, dcl_type, moo->c->cls.var[dcl_type].count - 1, MOO_NULL, varacc_type) <= -1) return -1;
|
||||
}
|
||||
}
|
||||
else if (TOKEN_TYPE(moo) == MOO_IOTOK_COMMA || TOKEN_TYPE(moo) == MOO_IOTOK_EOF || TOKEN_TYPE(moo) == MOO_IOTOK_PERIOD)
|
||||
{
|
||||
@ -4087,6 +4164,7 @@ static MOO_INLINE int find_undotted_ident (moo_t* moo, const moo_oocs_t* name, c
|
||||
return 0;
|
||||
}
|
||||
|
||||
MOO_DEBUG0 (moo, "2222222222222222\n");
|
||||
/* find an undotted identifier in dictionaries */
|
||||
if (moo->c->cls.ns_oop)
|
||||
{
|
||||
@ -4709,6 +4787,11 @@ static int compile_expression_primary (moo_t* moo, const moo_oocs_t* ident, cons
|
||||
break;
|
||||
|
||||
case VAR_CLASS:
|
||||
/* get_variable_info must not set var.cls to MOO_NULL
|
||||
* because the class object pointer should be available
|
||||
* when a method definition is compiled */
|
||||
MOO_ASSERT (moo, var.cls != MOO_NULL);
|
||||
|
||||
if (add_literal(moo, (moo_oop_t)var.cls, &index) <= -1 ||
|
||||
emit_double_param_instruction(moo, BCODE_PUSH_OBJVAR_0, var.pos, index) <= -1) return -1;
|
||||
break;
|
||||
@ -6434,15 +6517,8 @@ static int __compile_method_definition (moo_t* moo)
|
||||
}
|
||||
|
||||
|
||||
static int compile_method_definition (moo_t* moo)
|
||||
static void reset_method_data (moo_t* moo)
|
||||
{
|
||||
int n;
|
||||
|
||||
/* clear data required to compile a method */
|
||||
MOO_ASSERT (moo, moo->c->balit.count == 0);
|
||||
MOO_ASSERT (moo, moo->c->arlit.count == 0);
|
||||
|
||||
moo->c->mth.active = 1;
|
||||
moo->c->mth.type = MOO_METHOD_INSTANCE;
|
||||
moo->c->mth.primitive = 0;
|
||||
moo->c->mth.lenient = 0;
|
||||
@ -6461,6 +6537,18 @@ static int compile_method_definition (moo_t* moo)
|
||||
moo->c->mth.pfnum = 0;
|
||||
moo->c->mth.blk_depth = 0;
|
||||
moo->c->mth.code.len = 0;
|
||||
}
|
||||
|
||||
static int compile_method_definition (moo_t* moo)
|
||||
{
|
||||
int n;
|
||||
|
||||
/* clear data required to compile a method */
|
||||
MOO_ASSERT (moo, moo->c->balit.count == 0);
|
||||
MOO_ASSERT (moo, moo->c->arlit.count == 0);
|
||||
|
||||
moo->c->mth.active = 1;
|
||||
reset_method_data (moo);
|
||||
|
||||
n = __compile_method_definition (moo);
|
||||
|
||||
@ -6469,9 +6557,164 @@ static int compile_method_definition (moo_t* moo)
|
||||
return n;
|
||||
}
|
||||
|
||||
static int make_getter_method (moo_t* moo, const moo_oocs_t* name, const var_info_t* var)
|
||||
{
|
||||
MOO_ASSERT (moo, moo->c->balit.count == 0);
|
||||
MOO_ASSERT (moo, moo->c->arlit.count == 0);
|
||||
|
||||
MOO_ASSERT (moo, moo->c->mth.name.len == 0);
|
||||
if (add_method_name_fragment(moo, name) <= -1) return -1;
|
||||
|
||||
switch (var->type)
|
||||
{
|
||||
case VAR_INSTANCE:
|
||||
MOO_ASSERT (moo, moo->c->mth.type == MOO_METHOD_INSTANCE);
|
||||
if (emit_single_param_instruction(moo, BCODE_PUSH_INSTVAR_0, var->pos) <= -1 ||
|
||||
emit_byte_instruction(moo, BCODE_RETURN_STACKTOP) <= -1) return -1;
|
||||
break;
|
||||
|
||||
case VAR_CLASSINST:
|
||||
MOO_ASSERT (moo, moo->c->mth.type == MOO_METHOD_CLASS);
|
||||
if (emit_single_param_instruction(moo, BCODE_PUSH_INSTVAR_0, var->pos) <= -1 ||
|
||||
emit_byte_instruction(moo, BCODE_RETURN_STACKTOP) <= -1) return -1;
|
||||
break;
|
||||
|
||||
case VAR_CLASS:
|
||||
{
|
||||
moo_oow_t index;
|
||||
MOO_ASSERT (moo, var->cls != MOO_NULL);
|
||||
MOO_ASSERT (moo, var->cls == moo->c->cls.self_oop);
|
||||
MOO_ASSERT (moo, moo->c->mth.type == MOO_METHOD_CLASS);
|
||||
|
||||
if (add_literal(moo, (moo_oop_t)var->cls, &index) <= -1 ||
|
||||
emit_double_param_instruction(moo, BCODE_PUSH_OBJVAR_0, var->pos, index) <= -1 ||
|
||||
emit_byte_instruction(moo, BCODE_RETURN_STACKTOP) <= -1) return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
MOO_DEBUG1 (moo, "internal error - invalid variable type in make_getter_method - %d\n", (int)var->type);
|
||||
moo_seterrnum (moo, MOO_EINTERN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return add_compiled_method (moo);
|
||||
}
|
||||
|
||||
|
||||
static int make_setter_method (moo_t* moo, const moo_oocs_t* name, const var_info_t* var)
|
||||
{
|
||||
static moo_ooch_t colon = ':';
|
||||
static moo_oocs_t colons = { &colon, 1 };
|
||||
|
||||
MOO_ASSERT (moo, moo->c->balit.count == 0);
|
||||
MOO_ASSERT (moo, moo->c->arlit.count == 0);
|
||||
|
||||
MOO_ASSERT (moo, moo->c->mth.name.len == 0);
|
||||
if (add_method_name_fragment(moo, name) <= -1 ||
|
||||
add_method_name_fragment(moo, &colons) <= -1) return -1;
|
||||
|
||||
switch (var->type)
|
||||
{
|
||||
case VAR_INSTANCE:
|
||||
MOO_ASSERT (moo, moo->c->mth.type == MOO_METHOD_INSTANCE);
|
||||
if (emit_single_param_instruction(moo, BCODE_PUSH_TEMPVAR_0, 0) <= -1 ||
|
||||
emit_single_param_instruction(moo, BCODE_POP_INTO_INSTVAR_0, var->pos) <= -1 ||
|
||||
emit_byte_instruction(moo, BCODE_RETURN_RECEIVER) <= -1) return -1;
|
||||
break;
|
||||
|
||||
case VAR_CLASSINST:
|
||||
MOO_ASSERT (moo, moo->c->mth.type == MOO_METHOD_CLASS);
|
||||
if (emit_single_param_instruction(moo, BCODE_PUSH_TEMPVAR_0, 0) <= -1 ||
|
||||
emit_single_param_instruction(moo, BCODE_POP_INTO_INSTVAR_0, var->pos) <= -1 ||
|
||||
emit_byte_instruction(moo, BCODE_RETURN_RECEIVER) <= -1) return -1;
|
||||
break;
|
||||
|
||||
case VAR_CLASS:
|
||||
{
|
||||
moo_oow_t index;
|
||||
MOO_ASSERT (moo, var->cls != MOO_NULL);
|
||||
MOO_ASSERT (moo, var->cls == moo->c->cls.self_oop);
|
||||
MOO_ASSERT (moo, moo->c->mth.type == MOO_METHOD_CLASS);
|
||||
|
||||
if (add_literal(moo, (moo_oop_t)var->cls, &index) <= -1 ||
|
||||
emit_single_param_instruction(moo, BCODE_PUSH_TEMPVAR_0, 0) <= -1 ||
|
||||
emit_double_param_instruction(moo, BCODE_POP_INTO_OBJVAR_0, var->pos, index) <= -1 ||
|
||||
emit_byte_instruction(moo, BCODE_RETURN_RECEIVER) <= -1) return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
MOO_DEBUG1 (moo, "internal error - invalid variable type in make_setter_method - %d\n", (int)var->type);
|
||||
moo_seterrnum (moo, MOO_EINTERN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return add_compiled_method (moo);
|
||||
}
|
||||
|
||||
static int make_getters_and_setters (moo_t* moo)
|
||||
{
|
||||
moo_oow_t i, var_type;
|
||||
moo_oocs_t var_name;
|
||||
moo_ioloc_t fake_loc;
|
||||
var_info_t var_info;
|
||||
int x;
|
||||
|
||||
fake_loc.line = 0;
|
||||
fake_loc.colm = 0;
|
||||
for (var_type = VAR_INSTANCE; var_type <= VAR_CLASS; var_type++)
|
||||
{
|
||||
for (i = 0; i < moo->c->cls.var[var_type].initv_count; i++)
|
||||
{
|
||||
if (!moo->c->cls.var[var_type].initv[i].flags) continue;
|
||||
|
||||
/* moo->c->mth.type needs to be set because get_variable_info()
|
||||
* uses it to validate variable's accessibility */
|
||||
reset_method_data (moo);
|
||||
moo->c->mth.type = (var_type == VAR_INSTANCE? MOO_METHOD_INSTANCE: MOO_METHOD_CLASS);
|
||||
|
||||
/* the following two function calls must not fail unless the compiler
|
||||
* is buggy. */
|
||||
|
||||
x = fetch_word_from_string (&moo->c->cls.var[var_type].str, i, &var_name);
|
||||
MOO_ASSERT (moo, x >= 0);
|
||||
x = get_variable_info (moo, &var_name, &fake_loc, 0, &var_info);
|
||||
MOO_ASSERT (moo, x >= 0);
|
||||
|
||||
MOO_ASSERT (moo, var_info.type == var_type);
|
||||
|
||||
if (moo->c->cls.var[var_type].initv[i].flags & VARACC_GETTER)
|
||||
{
|
||||
/* the method data has been reset above. */
|
||||
if (make_getter_method (moo, &var_name, &var_info) <= -1) return -1;
|
||||
}
|
||||
|
||||
if (moo->c->cls.var[var_type].initv[i].flags & VARACC_SETTER)
|
||||
{
|
||||
/* i set the method data here because make_getter_method()
|
||||
* pollutes it if triggered */
|
||||
reset_method_data (moo);
|
||||
moo->c->mth.type = (var_type == VAR_INSTANCE? MOO_METHOD_INSTANCE: MOO_METHOD_CLASS);
|
||||
|
||||
/* hack to simulate a parameter. note i don't manipulate tmprs or tmprs_capa
|
||||
* because there is no method body code to process. i simply generate a setter
|
||||
* method */
|
||||
moo->c->mth.tmpr_count = 1;
|
||||
moo->c->mth.tmpr_nargs = 1;
|
||||
|
||||
MOO_ASSERT (moo, var_info.type == var_type);
|
||||
if (make_setter_method (moo, &var_name, &var_info) <= -1) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int make_default_initial_values (moo_t* moo, var_type_t var_type)
|
||||
{
|
||||
moo_oow_t initv_count;
|
||||
moo_oow_t initv_count, super_initv_count;
|
||||
|
||||
MOO_ASSERT (moo, var_type == VAR_INSTANCE || var_type == VAR_CLASSINST);
|
||||
MOO_ASSERT (moo, VAR_INSTANCE == 0);
|
||||
@ -6480,11 +6723,18 @@ static int make_default_initial_values (moo_t* moo, var_type_t var_type)
|
||||
initv_count = moo->c->cls.var[var_type].initv_count;
|
||||
if (moo->c->cls.super_oop != moo->_nil && ((moo_oop_class_t)moo->c->cls.super_oop)->initv[var_type] != moo->_nil)
|
||||
{
|
||||
initv_count += MOO_OBJ_GET_SIZE(((moo_oop_class_t)moo->c->cls.super_oop)->initv[var_type]);
|
||||
super_initv_count = MOO_OBJ_GET_SIZE(((moo_oop_class_t)moo->c->cls.super_oop)->initv[var_type]);
|
||||
}
|
||||
else
|
||||
{
|
||||
super_initv_count = 0;
|
||||
|
||||
}
|
||||
initv_count += super_initv_count;
|
||||
|
||||
if (initv_count > 0)
|
||||
{
|
||||
moo_oow_t i, j = 0;
|
||||
moo_oow_t i, j;
|
||||
moo_oop_t tmp;
|
||||
|
||||
/* [NOTE]
|
||||
@ -6498,25 +6748,29 @@ static int make_default_initial_values (moo_t* moo, var_type_t var_type)
|
||||
tmp = moo_instantiate (moo, moo->_array, MOO_NULL, moo->c->cls.var[var_type].total_count);
|
||||
if (!tmp) return -1;
|
||||
|
||||
if (initv_count > moo->c->cls.var[var_type].initv_count)
|
||||
if (super_initv_count > 0)
|
||||
{
|
||||
/* handle default values defined in the superclass chain.
|
||||
* i merge them into a single array for convenience and
|
||||
* efficiency of object instantiation by moo_instantiate().
|
||||
* it can avoid looking up superclasses upon instantiaion */
|
||||
moo_oop_oop_t initv;
|
||||
moo_oow_t super_count;
|
||||
|
||||
j = 0;
|
||||
MOO_ASSERT (moo, moo->c->cls.super_oop != moo->_nil);
|
||||
super_count = initv_count - moo->c->cls.var[var_type].initv_count;
|
||||
initv = (moo_oop_oop_t)((moo_oop_class_t)moo->c->cls.super_oop)->initv[var_type];
|
||||
MOO_ASSERT (moo, MOO_CLASSOF(moo, initv) == moo->_array);
|
||||
for (i = 0; i < super_count; i++)
|
||||
for (i = 0; i < super_initv_count; i++)
|
||||
{
|
||||
if (initv->slot[i]) ((moo_oop_oop_t)tmp)->slot[j] = initv->slot[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* superclass chain have variables but no default values are defined */
|
||||
j = moo->c->cls.var[var_type].total_count - moo->c->cls.var[var_type].count;
|
||||
}
|
||||
|
||||
for (i = 0; i < moo->c->cls.var[var_type].initv_count; i++)
|
||||
{
|
||||
@ -6684,6 +6938,10 @@ static int make_defined_class (moo_t* moo)
|
||||
|
||||
/* TODO: update the subclasses field of the superclass if it's not nil */
|
||||
|
||||
|
||||
if (make_getters_and_setters (moo) <= -1) return -1;
|
||||
|
||||
|
||||
if (just_made)
|
||||
{
|
||||
/* register the class to the system dictionary. kernel classes have
|
||||
@ -7076,7 +7334,7 @@ static int __compile_class_definition (moo_t* moo, int extend)
|
||||
moo_oop_char_t pds;
|
||||
|
||||
/* when a class is extended, a new variable cannot be added */
|
||||
if (is_token_word(moo, VOCA_DCL) || is_token_word(moo, VOCA_VAR) || is_token_word(moo, VOCA_VARIABLE))
|
||||
if (is_token_word(moo, VOCA_VAR) || is_token_word(moo, VOCA_VARIABLE))
|
||||
{
|
||||
set_syntax_error (moo, MOO_SYNERR_VARDCLBANNED, TOKEN_LOC(moo), TOKEN_NAME(moo));
|
||||
return -1;
|
||||
@ -7156,7 +7414,7 @@ static int __compile_class_definition (moo_t* moo, int extend)
|
||||
GET_TOKEN (moo);
|
||||
if (compile_class_level_variables_vbar(moo, VAR_CLASS) <= -1) return -1;
|
||||
}
|
||||
else if (is_token_word(moo, VOCA_DCL) || is_token_word(moo, VOCA_VAR) || is_token_word(moo, VOCA_VARIABLE))
|
||||
else if (is_token_word(moo, VOCA_VAR) || is_token_word(moo, VOCA_VARIABLE))
|
||||
{
|
||||
/* variable declaration */
|
||||
GET_TOKEN (moo);
|
||||
|
Loading…
Reference in New Issue
Block a user