added the #dual modifier to method definition. a method defined with #dual is registered in both the instance side and the class side.

This commit is contained in:
hyunghwan.chung 2017-04-26 03:09:55 +00:00
parent 8298bad3e0
commit 04864659a8
3 changed files with 52 additions and 20 deletions

View File

@ -158,7 +158,7 @@ extend Apex
self primitiveFailed. self primitiveFailed.
} }
method basicAt: index method(#dual) basicAt: index
{ {
| perr | | perr |
@ -171,7 +171,7 @@ extend Apex
else { self primitiveFailed } else { self primitiveFailed }
} }
method basicAt: index put: anObject method(#dual) basicAt: index put: anObject
{ {
| perr | | perr |
@ -183,6 +183,7 @@ extend Apex
else { self primitiveFailed } else { self primitiveFailed }
} }
(*
method(#class) basicAt: index method(#class) basicAt: index
{ {
| perr | | perr |
@ -194,7 +195,7 @@ extend Apex
else { self primitiveFailed } else { self primitiveFailed }
} }
method(#class) basicAt: index put: anObject method(#dual) basicAt: index put: anObject
{ {
| perr | | perr |
<primitive: #_basic_at_put> <primitive: #_basic_at_put>
@ -203,7 +204,7 @@ extend Apex
if (perr == Error.Code.ERANGE) { self index: index outOfRange: (self basicSize) } if (perr == Error.Code.ERANGE) { self index: index outOfRange: (self basicSize) }
elsif (perr == Error.Code.EPERM) { self messageProhibited: #basicAt:put: } elsif (perr == Error.Code.EPERM) { self messageProhibited: #basicAt:put: }
else { self primitiveFailed } else { self primitiveFailed }
} }*)
(* ------------------------------------------------------------------ (* ------------------------------------------------------------------
* HASHING * HASHING

View File

@ -93,6 +93,7 @@ static struct voca_t
{ 8, { 'c','o','n','t','i','n','u','e' } }, { 8, { 'c','o','n','t','i','n','u','e' } },
{ 3, { 'd','c','l' } }, { 3, { 'd','c','l' } },
{ 2, { 'd','o' } }, { 2, { 'd','o' } },
{ 5, { '#','d','u','a','l' } },
{ 4, { 'e','l','s','e' } }, { 4, { 'e','l','s','e' } },
{ 5, { 'e','l','s','i','f' } }, { 5, { 'e','l','s','i','f' } },
{ 6, { 'e','n','s','u','r','e', } }, { 6, { 'e','n','s','u','r','e', } },
@ -147,6 +148,7 @@ enum voca_id_t
VOCA_CONTINUE, VOCA_CONTINUE,
VOCA_DCL, VOCA_DCL,
VOCA_DO, VOCA_DO,
VOCA_DUAL_S,
VOCA_ELSE, VOCA_ELSE,
VOCA_ELSIF, VOCA_ELSIF,
VOCA_ENSURE, VOCA_ENSURE,
@ -2786,8 +2788,17 @@ static int add_method_name_fragment (moo_t* moo, const moo_oocs_t* name)
static int method_exists (moo_t* moo, const moo_oocs_t* name) static int method_exists (moo_t* moo, const moo_oocs_t* name)
{ {
/* check if the current class contains a method of the given name */ /* check if the current class contains a method of the given name */
if (moo->c->mth.type == MOO_METHOD_DUAL)
{
return moo_lookupdic (moo, moo->c->cls.self_oop->mthdic[0], name) != MOO_NULL ||
moo_lookupdic (moo, moo->c->cls.self_oop->mthdic[1], name) != MOO_NULL;
}
else
{
MOO_ASSERT (moo, moo->c->mth.type < MOO_COUNTOF(moo->c->cls.self_oop->mthdic));
return moo_lookupdic (moo, moo->c->cls.self_oop->mthdic[moo->c->mth.type], name) != MOO_NULL; return moo_lookupdic (moo, moo->c->cls.self_oop->mthdic[moo->c->mth.type], name) != MOO_NULL;
} }
}
static int add_temporary_variable (moo_t* moo, const moo_oocs_t* name) static int add_temporary_variable (moo_t* moo, const moo_oocs_t* name)
{ {
@ -3830,17 +3841,17 @@ static int get_variable_info (moo_t* moo, const moo_oocs_t* name, const moo_iolo
switch (var->type) switch (var->type)
{ {
case VAR_INSTANCE: case VAR_INSTANCE:
if (moo->c->mth.type == MOO_METHOD_CLASS) if (moo->c->mth.type == MOO_METHOD_CLASS || moo->c->mth.type == MOO_METHOD_DUAL)
{ {
/* a class method cannot access an instance variable */ /* a class(or dual) method cannot access an instance variable */
set_syntax_error (moo, MOO_SYNERR_VARINACC, name_loc, name); set_syntax_error (moo, MOO_SYNERR_VARINACC, name_loc, name);
return -1; return -1;
} }
break; break;
case VAR_CLASSINST: case VAR_CLASSINST:
/* class instance variable can be accessed by only class methods */ /* class instance variable can be accessed by only pure class methods */
if (moo->c->mth.type == MOO_METHOD_INSTANCE) if (moo->c->mth.type == MOO_METHOD_INSTANCE || moo->c->mth.type == MOO_METHOD_DUAL)
{ {
/* an instance method cannot access a class-instance variable */ /* an instance method cannot access a class-instance variable */
set_syntax_error (moo, MOO_SYNERR_VARINACC, name_loc, name); set_syntax_error (moo, MOO_SYNERR_VARINACC, name_loc, name);
@ -6001,9 +6012,23 @@ need to write code to collect string.
moo_decode (moo, mth, &moo->c->cls.fqn); moo_decode (moo, mth, &moo->c->cls.fqn);
#endif #endif
moo_poptmps (moo, tmp_count); tmp_count = 0; if (moo->c->mth.type == MOO_METHOD_DUAL)
{
if (!moo_putatdic(moo, moo->c->cls.self_oop->mthdic[0], (moo_oop_t)name, (moo_oop_t)mth)) goto oops;
if (!moo_putatdic(moo, moo->c->cls.self_oop->mthdic[1], (moo_oop_t)name, (moo_oop_t)mth))
{
/* 'name' is a symbol created of moo->c->mth.name. so use it as a key for deletion */
moo_deletedic (moo, moo->c->cls.self_oop->mthdic[0], &moo->c->mth.name);
goto oops;
}
}
else
{
MOO_ASSERT (moo, moo->c->mth.type < MOO_COUNTOF(moo->c->cls.self_oop->mthdic));
if (!moo_putatdic(moo, moo->c->cls.self_oop->mthdic[moo->c->mth.type], (moo_oop_t)name, (moo_oop_t)mth)) goto oops; if (!moo_putatdic(moo, moo->c->cls.self_oop->mthdic[moo->c->mth.type], (moo_oop_t)name, (moo_oop_t)mth)) goto oops;
}
moo_poptmps (moo, tmp_count); tmp_count = 0;
return 0; return 0;
@ -6047,7 +6072,7 @@ static int compile_method_definition (moo_t* moo)
if (is_token_symbol(moo, VOCA_CLASS_S)) if (is_token_symbol(moo, VOCA_CLASS_S))
{ {
/* method(#class) */ /* method(#class) */
if (moo->c->mth.type == MOO_METHOD_CLASS) if (moo->c->mth.type == MOO_METHOD_CLASS || moo->c->mth.type == MOO_METHOD_DUAL)
{ {
set_syntax_error (moo, MOO_SYNERR_MODIFIERDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo)); set_syntax_error (moo, MOO_SYNERR_MODIFIERDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1; return -1;
@ -6056,6 +6081,18 @@ static int compile_method_definition (moo_t* moo)
moo->c->mth.type = MOO_METHOD_CLASS; moo->c->mth.type = MOO_METHOD_CLASS;
GET_TOKEN (moo); GET_TOKEN (moo);
} }
else if (is_token_symbol(moo, VOCA_DUAL_S))
{
/* method(#dual) */
if (moo->c->mth.type == MOO_METHOD_CLASS || moo->c->mth.type == MOO_METHOD_DUAL)
{
set_syntax_error (moo, MOO_SYNERR_MODIFIERDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1;
}
moo->c->mth.type = MOO_METHOD_DUAL;
GET_TOKEN (moo);
}
else if (is_token_symbol(moo, VOCA_PRIMITIVE_S)) else if (is_token_symbol(moo, VOCA_PRIMITIVE_S))
{ {
/* method(#primitive) */ /* method(#primitive) */
@ -6418,11 +6455,9 @@ static int make_defined_class (moo_t* moo)
if (!tmp) return -1; if (!tmp) return -1;
moo->c->cls.self_oop->mthdic[MOO_METHOD_CLASS] = (moo_oop_set_t)tmp; moo->c->cls.self_oop->mthdic[MOO_METHOD_CLASS] = (moo_oop_set_t)tmp;
MOO_DEBUG0 (moo, "!00000000000000000000\n");
/* store the default intial values for instance variables */ /* store the default intial values for instance variables */
if (make_default_initial_values (moo, VAR_INSTANCE) <= -1) return -1; if (make_default_initial_values (moo, VAR_INSTANCE) <= -1) return -1;
MOO_DEBUG0 (moo, "!111111111111111111111\n");
/* store the default intial values for class instance variables */ /* store the default intial values for class instance variables */
if (make_default_initial_values (moo, VAR_CLASSINST) <= -1) return -1; if (make_default_initial_values (moo, VAR_CLASSINST) <= -1) return -1;
if (moo->c->cls.self_oop->initv[VAR_CLASSINST] != moo->_nil) if (moo->c->cls.self_oop->initv[VAR_CLASSINST] != moo->_nil)
@ -6430,7 +6465,6 @@ MOO_DEBUG0 (moo, "!111111111111111111111\n");
moo_oow_t i, initv_count; moo_oow_t i, initv_count;
moo_oop_oop_t initv; moo_oop_oop_t initv;
MOO_DEBUG0 (moo, "!222222222222222222\n");
/* apply the default initial values for class instance variables to this class now */ /* apply the default initial values for class instance variables to this class now */
initv = (moo_oop_oop_t)moo->c->cls.self_oop->initv[VAR_CLASSINST]; initv = (moo_oop_oop_t)moo->c->cls.self_oop->initv[VAR_CLASSINST];
MOO_ASSERT (moo, MOO_CLASSOF(moo, initv) == moo->_array); MOO_ASSERT (moo, MOO_CLASSOF(moo, initv) == moo->_array);

View File

@ -171,14 +171,11 @@ typedef struct moo_obj_word_t* moo_oop_word_t;
#endif #endif
enum moo_method_type_t enum moo_method_type_t
{ {
MOO_METHOD_INSTANCE = 0, MOO_METHOD_INSTANCE = 0,
MOO_METHOD_CLASS = 1, MOO_METHOD_CLASS = 1,
MOO_METHOD_DUAL = 2
/* --------------------------- */
MOO_METHOD_TYPE_COUNT
}; };
typedef enum moo_method_type_t moo_method_type_t; typedef enum moo_method_type_t moo_method_type_t;
@ -511,7 +508,7 @@ struct moo_class_t
/* [0] - instance methods, MethodDictionary /* [0] - instance methods, MethodDictionary
* [1] - class methods, MethodDictionary */ * [1] - class methods, MethodDictionary */
moo_oop_set_t mthdic[MOO_METHOD_TYPE_COUNT]; moo_oop_set_t mthdic[2];
moo_oop_set_t nsdic; /* dictionary used for namespacing */ moo_oop_set_t nsdic; /* dictionary used for namespacing */
moo_oop_set_t cdic; /* constant dictionary */ moo_oop_set_t cdic; /* constant dictionary */