added moo_walkdic() for internal use

added incomplete interface implementation check
This commit is contained in:
hyunghwan.chung 2018-10-11 14:03:16 +00:00
parent 9656d87816
commit c6c3739572
5 changed files with 106 additions and 34 deletions

View File

@ -32,6 +32,10 @@ class X11(Object) [X11able,selfns.X11able3] from 'x11'
var event_loop_sem, event_loop_proc. var event_loop_sem, event_loop_proc.
var llevent_blocks. var llevent_blocks.
method(#dual) abc { ^nil }
method(#dual) def { ^nil }
method(#dual) abc3 { ^nil }
interface X11able3 interface X11able3
{ {
method(#dual) abc55. method(#dual) abc55.

View File

@ -224,8 +224,6 @@ static int is_normalized_integer (moo_t* moo, moo_oop_t oop)
MOO_INLINE static int is_bigint (moo_t* moo, moo_oop_t x) MOO_INLINE static int is_bigint (moo_t* moo, moo_oop_t x)
{ {
moo_oop_class_t c;
if (!MOO_OOP_IS_POINTER(x)) return 0; if (!MOO_OOP_IS_POINTER(x)) return 0;
/* TODO: is it better to introduce a special integer mark into the class itself */ /* TODO: is it better to introduce a special integer mark into the class itself */

View File

@ -3130,13 +3130,13 @@ static int method_exists (moo_t* moo, const moo_oocs_t* name)
{ {
if (moo->c->cunit->cunit_type == MOO_CUNIT_INTERFACE) if (moo->c->cunit->cunit_type == MOO_CUNIT_INTERFACE)
{ {
/* TODO: remove duplicate code */ /* TODO: remove duplicate code between interface and class */
moo_cunit_interface_t* ifce = (moo_cunit_interface_t*)moo->c->cunit; moo_cunit_interface_t* ifce = (moo_cunit_interface_t*)moo->c->cunit;
if (ifce->mth.type == MOO_METHOD_DUAL) if (ifce->mth.type == MOO_METHOD_DUAL)
{ {
return moo_lookupdic(moo, ifce->self_oop->mthdic[0], name) != MOO_NULL || return moo_lookupdic(moo, ifce->self_oop->mthdic[MOO_METHOD_INSTANCE], name) != MOO_NULL ||
moo_lookupdic(moo, ifce->self_oop->mthdic[1], name) != MOO_NULL; moo_lookupdic(moo, ifce->self_oop->mthdic[MOO_METHOD_CLASS], name) != MOO_NULL;
} }
else else
{ {
@ -3153,8 +3153,8 @@ static int method_exists (moo_t* moo, const moo_oocs_t* name)
moo_cunit_class_t* cc = (moo_cunit_class_t*)moo->c->cunit; moo_cunit_class_t* cc = (moo_cunit_class_t*)moo->c->cunit;
if (cc->mth.type == MOO_METHOD_DUAL) if (cc->mth.type == MOO_METHOD_DUAL)
{ {
return moo_lookupdic(moo, cc->self_oop->mthdic[0], name) != MOO_NULL || return moo_lookupdic(moo, cc->self_oop->mthdic[MOO_METHOD_INSTANCE], name) != MOO_NULL ||
moo_lookupdic(moo, cc->self_oop->mthdic[1], name) != MOO_NULL; moo_lookupdic(moo, cc->self_oop->mthdic[MOO_METHOD_CLASS], name) != MOO_NULL;
} }
else else
{ {
@ -6657,11 +6657,11 @@ need to write code to collect string.
if (cc->mth.type == MOO_METHOD_DUAL) if (cc->mth.type == MOO_METHOD_DUAL)
{ {
if (!moo_putatdic(moo, cc->self_oop->mthdic[0], (moo_oop_t)name, (moo_oop_t)mth)) goto oops; if (!moo_putatdic(moo, cc->self_oop->mthdic[MOO_METHOD_INSTANCE], (moo_oop_t)name, (moo_oop_t)mth)) goto oops;
if (!moo_putatdic(moo, cc->self_oop->mthdic[1], (moo_oop_t)name, (moo_oop_t)mth)) if (!moo_putatdic(moo, cc->self_oop->mthdic[MOO_METHOD_CLASS], (moo_oop_t)name, (moo_oop_t)mth))
{ {
/* 'name' is a symbol created of cc->mth.name. so use it as a key for deletion */ /* 'name' is a symbol created of cc->mth.name. so use it as a key for deletion */
moo_deletedic (moo, cc->self_oop->mthdic[0], &cc->mth.name); moo_deletedic (moo, cc->self_oop->mthdic[MOO_METHOD_INSTANCE], &cc->mth.name);
goto oops; goto oops;
} }
} }
@ -7820,10 +7820,52 @@ static int process_class_interfaces (moo_t* moo)
return 0; return 0;
} }
struct ciim_t
{
moo_oop_interface_t ifce;
moo_oop_class_t _class;
int mth_type;
};
typedef struct ciim_t ciim_t;
static int on_each_method (moo_t* moo, moo_oop_dic_t dic, moo_oop_association_t ass, void* ctx)
{
ciim_t* ciim = (ciim_t*)ctx;
moo_oocs_t name;
name.ptr = MOO_OBJ_GET_CHAR_SLOT(ass->key);
name.len = MOO_OBJ_GET_SIZE(ass->key);
ass = moo_lookupdic(moo, ciim->_class->mthdic[ciim->mth_type], &name);
if (!ass)
{/* TODO: change error code */
moo_setsynerrbfmt (moo, MOO_SYNERR_ARGFLOOD, MOO_NULL, MOO_NULL,
"%.*js not implementing %.*js>>%.*js",
MOO_OBJ_GET_SIZE(ciim->_class->name), MOO_OBJ_GET_CHAR_SLOT(ciim->_class->name),
MOO_OBJ_GET_SIZE(ciim->ifce->name), MOO_OBJ_GET_CHAR_SLOT(ciim->ifce->name),
name.len, name.ptr
);
return -1;
}
/* TODO: check preamble flags in signature */
return 0;
}
static int class_implements_interface (moo_t* moo, moo_oop_class_t _class, moo_oop_interface_t ifce) static int class_implements_interface (moo_t* moo, moo_oop_class_t _class, moo_oop_interface_t ifce)
{ {
ciim_t ciim;
return 0;
ciim.ifce = ifce;
ciim._class = _class;
ciim.mth_type = MOO_METHOD_INSTANCE;
if (moo_walkdic(moo, ifce->mthdic[MOO_METHOD_INSTANCE], on_each_method, &ciim) <= -1) return 0;
ciim.ifce = ifce;
ciim._class = _class;
ciim.mth_type = MOO_METHOD_CLASS;
if (moo_walkdic(moo, ifce->mthdic[MOO_METHOD_CLASS], on_each_method, &ciim) <= -1) return 0;
return 1;
} }
static int check_class_interface_conformance (moo_t* moo) static int check_class_interface_conformance (moo_t* moo)
@ -7833,15 +7875,7 @@ static int check_class_interface_conformance (moo_t* moo)
for (i = 0; i < cc->ifces.count; i++) for (i = 0; i < cc->ifces.count; i++)
{ {
moo_oop_interface_t ifce = (moo_oop_interface_t)cc->ifces.ptr[i]; if (!class_implements_interface(moo, cc->self_oop, (moo_oop_interface_t)cc->ifces.ptr[i])) return -1;
if (!class_implements_interface(moo, cc->self_oop, ifce))
{
moo_setsynerrbfmt (moo, MOO_SYNERR_ARGNAMEDUPL, &cc->fqn_loc, &cc->fqn,
"%.*js not implementing interface %.*js",
cc->fqn.len, cc->fqn.ptr,
MOO_OBJ_GET_SIZE(ifce->name), MOO_OBJ_GET_CHAR_SLOT(ifce->name));
return -1;
}
} }
return 0; return 0;
@ -8283,11 +8317,11 @@ static int add_method_signature (moo_t* moo)
if (ifce->mth.type == MOO_METHOD_DUAL) if (ifce->mth.type == MOO_METHOD_DUAL)
{ {
if (!moo_putatdic(moo, ifce->self_oop->mthdic[0], (moo_oop_t)name, (moo_oop_t)mth)) goto oops; if (!moo_putatdic(moo, ifce->self_oop->mthdic[MOO_METHOD_INSTANCE], (moo_oop_t)name, (moo_oop_t)mth)) goto oops;
if (!moo_putatdic(moo, ifce->self_oop->mthdic[1], (moo_oop_t)name, (moo_oop_t)mth)) if (!moo_putatdic(moo, ifce->self_oop->mthdic[MOO_METHOD_CLASS], (moo_oop_t)name, (moo_oop_t)mth))
{ {
/* 'name' is a symbol created of ifce->mth.name. so use it as a key for deletion */ /* 'name' is a symbol created of ifce->mth.name. so use it as a key for deletion */
moo_deletedic (moo, ifce->self_oop->mthdic[0], &ifce->mth.name); moo_deletedic (moo, ifce->self_oop->mthdic[MOO_METHOD_INSTANCE], &ifce->mth.name);
goto oops; goto oops;
} }
} }

View File

@ -62,7 +62,7 @@ static moo_oop_oop_t expand_bucket (moo_t* moo, moo_oop_oop_t oldbuc)
} }
moo_pushtmp (moo, (moo_oop_t*)&oldbuc); moo_pushtmp (moo, (moo_oop_t*)&oldbuc);
newbuc = (moo_oop_oop_t)moo_instantiate (moo, moo->_array, MOO_NULL, newsz); newbuc = (moo_oop_oop_t)moo_instantiate(moo, moo->_array, MOO_NULL, newsz);
moo_poptmp (moo); moo_poptmp (moo);
if (!newbuc) return MOO_NULL; if (!newbuc) return MOO_NULL;
@ -234,32 +234,32 @@ static moo_oop_association_t lookup (moo_t* moo, moo_oop_dic_t dic, const moo_oo
moo_oop_association_t moo_putatsysdic (moo_t* moo, moo_oop_t key, moo_oop_t value) moo_oop_association_t moo_putatsysdic (moo_t* moo, moo_oop_t key, moo_oop_t value)
{ {
MOO_ASSERT (moo, MOO_CLASSOF(moo,key) == moo->_symbol); MOO_ASSERT (moo, MOO_CLASSOF(moo,key) == moo->_symbol);
return find_or_upsert (moo, (moo_oop_dic_t)moo->sysdic, (moo_oop_char_t)key, value); return find_or_upsert(moo, (moo_oop_dic_t)moo->sysdic, (moo_oop_char_t)key, value);
} }
moo_oop_association_t moo_getatsysdic (moo_t* moo, moo_oop_t key) moo_oop_association_t moo_getatsysdic (moo_t* moo, moo_oop_t key)
{ {
MOO_ASSERT (moo, MOO_CLASSOF(moo,key) == moo->_symbol); MOO_ASSERT (moo, MOO_CLASSOF(moo,key) == moo->_symbol);
return find_or_upsert (moo, (moo_oop_dic_t)moo->sysdic, (moo_oop_char_t)key, MOO_NULL); return find_or_upsert(moo, (moo_oop_dic_t)moo->sysdic, (moo_oop_char_t)key, MOO_NULL);
} }
moo_oop_association_t moo_lookupsysdic (moo_t* moo, const moo_oocs_t* name) moo_oop_association_t moo_lookupsysdic (moo_t* moo, const moo_oocs_t* name)
{ {
return lookup (moo, (moo_oop_dic_t)moo->sysdic, name); return lookup(moo, (moo_oop_dic_t)moo->sysdic, name);
} }
moo_oop_association_t moo_putatdic (moo_t* moo, moo_oop_dic_t dic, moo_oop_t key, moo_oop_t value) moo_oop_association_t moo_putatdic (moo_t* moo, moo_oop_dic_t dic, moo_oop_t key, moo_oop_t value)
{ {
/*MOO_ASSERT (moo, MOO_CLASSOF(moo,key) == moo->_symbol);*/ /*MOO_ASSERT (moo, MOO_CLASSOF(moo,key) == moo->_symbol);*/
MOO_ASSERT (moo, MOO_OBJ_IS_CHAR_POINTER(key)); MOO_ASSERT (moo, MOO_OBJ_IS_CHAR_POINTER(key));
return find_or_upsert (moo, dic, (moo_oop_char_t)key, value); return find_or_upsert(moo, dic, (moo_oop_char_t)key, value);
} }
moo_oop_association_t moo_getatdic (moo_t* moo, moo_oop_dic_t dic, moo_oop_t key) moo_oop_association_t moo_getatdic (moo_t* moo, moo_oop_dic_t dic, moo_oop_t key)
{ {
/*MOO_ASSERT (moo, MOO_CLASSOF(moo,key) == moo->_symbol); */ /*MOO_ASSERT (moo, MOO_CLASSOF(moo,key) == moo->_symbol); */
MOO_ASSERT (moo, MOO_OBJ_IS_CHAR_POINTER(key)); MOO_ASSERT (moo, MOO_OBJ_IS_CHAR_POINTER(key));
return find_or_upsert (moo, dic, (moo_oop_char_t)key, MOO_NULL); return find_or_upsert(moo, dic, (moo_oop_char_t)key, MOO_NULL);
} }
moo_oop_association_t moo_lookupdic (moo_t* moo, moo_oop_dic_t dic, const moo_oocs_t* name) moo_oop_association_t moo_lookupdic (moo_t* moo, moo_oop_dic_t dic, const moo_oocs_t* name)
@ -334,6 +334,29 @@ found:
return 0; return 0;
} }
int moo_walkdic (moo_t* moo, moo_oop_dic_t dic, moo_dic_walker_t walker, void* ctx)
{
moo_oow_t index, count;
moo_oop_association_t ass;
count = MOO_OBJ_GET_SIZE(dic->bucket);
for (index = 0; index < count; index++)
{
ass = (moo_oop_association_t)dic->bucket->slot[index];
if ((moo_oop_t)ass != moo->_nil)
{
MOO_ASSERT (moo, MOO_CLASSOF(moo,ass) == moo->_association);
/*MOO_ASSERT (moo, MOO_CLASSOF(moo,ass->key) == moo->_symbol);*/
MOO_ASSERT (moo, MOO_OBJ_IS_CHAR_POINTER(ass->key));
if (walker(moo, dic, ass, ctx) <= -1) return -1;
}
}
return 0;
}
moo_oop_dic_t moo_makedic (moo_t* moo, moo_oop_class_t _class, moo_oow_t size) moo_oop_dic_t moo_makedic (moo_t* moo, moo_oop_class_t _class, moo_oow_t size)
{ {
moo_oop_dic_t dic; moo_oop_dic_t dic;
@ -342,11 +365,11 @@ moo_oop_dic_t moo_makedic (moo_t* moo, moo_oop_class_t _class, moo_oow_t size)
MOO_ASSERT (moo, MOO_CLASSOF(moo,_class) == moo->_class); MOO_ASSERT (moo, MOO_CLASSOF(moo,_class) == moo->_class);
MOO_ASSERT (moo, MOO_CLASS_SPEC_NAMED_INSTVARS(MOO_OOP_TO_SMOOI(_class->spec)) >= MOO_DIC_NAMED_INSTVARS); MOO_ASSERT (moo, MOO_CLASS_SPEC_NAMED_INSTVARS(MOO_OOP_TO_SMOOI(_class->spec)) >= MOO_DIC_NAMED_INSTVARS);
dic = (moo_oop_dic_t)moo_instantiate (moo, _class, MOO_NULL, 0); dic = (moo_oop_dic_t)moo_instantiate(moo, _class, MOO_NULL, 0);
if (!dic) return MOO_NULL; if (!dic) return MOO_NULL;
moo_pushtmp (moo, (moo_oop_t*)&dic); moo_pushtmp (moo, (moo_oop_t*)&dic);
tmp = moo_instantiate (moo, moo->_array, MOO_NULL, size); tmp = moo_instantiate(moo, moo->_array, MOO_NULL, size);
moo_poptmp (moo); moo_poptmp (moo);
if (!tmp) return MOO_NULL; if (!tmp) return MOO_NULL;
@ -363,6 +386,5 @@ moo_oop_nsdic_t moo_makensdic (moo_t* moo, moo_oop_class_t _class, moo_oow_t siz
{ {
MOO_ASSERT (moo, MOO_CLASSOF(moo,_class) == moo->_class); MOO_ASSERT (moo, MOO_CLASSOF(moo,_class) == moo->_class);
MOO_ASSERT (moo, MOO_CLASS_SPEC_NAMED_INSTVARS(MOO_OOP_TO_SMOOI(_class->spec)) >= MOO_NSDIC_NAMED_INSTVARS); MOO_ASSERT (moo, MOO_CLASS_SPEC_NAMED_INSTVARS(MOO_OOP_TO_SMOOI(_class->spec)) >= MOO_NSDIC_NAMED_INSTVARS);
return (moo_oop_nsdic_t)moo_makedic(moo, _class, size);
return (moo_oop_nsdic_t)moo_makedic (moo, _class, size);
} }

View File

@ -1049,6 +1049,13 @@ enum moo_bcode_t
(moo)->shuterr = shuterr; \ (moo)->shuterr = shuterr; \
} while(0) } while(0)
typedef int (*moo_dic_walker_t) (
moo_t* moo,
moo_oop_dic_t dic,
moo_oop_association_t ass,
void* ctx
);
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
@ -1234,6 +1241,13 @@ int moo_deletedic (
const moo_oocs_t* name const moo_oocs_t* name
); );
int moo_walkdic (
moo_t* moo,
moo_oop_dic_t dic,
moo_dic_walker_t walker,
void* ctx
);
moo_oop_dic_t moo_makedic ( moo_oop_dic_t moo_makedic (
moo_t* moo, moo_t* moo,
moo_oop_class_t _class, moo_oop_class_t _class,