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 llevent_blocks.
method(#dual) abc { ^nil }
method(#dual) def { ^nil }
method(#dual) abc3 { ^nil }
interface X11able3
{
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_oop_class_t c;
if (!MOO_OOP_IS_POINTER(x)) return 0;
/* 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)
{
/* TODO: remove duplicate code */
/* TODO: remove duplicate code between interface and class */
moo_cunit_interface_t* ifce = (moo_cunit_interface_t*)moo->c->cunit;
if (ifce->mth.type == MOO_METHOD_DUAL)
{
return moo_lookupdic(moo, ifce->self_oop->mthdic[0], name) != MOO_NULL ||
moo_lookupdic(moo, ifce->self_oop->mthdic[1], name) != MOO_NULL;
return moo_lookupdic(moo, ifce->self_oop->mthdic[MOO_METHOD_INSTANCE], name) != MOO_NULL ||
moo_lookupdic(moo, ifce->self_oop->mthdic[MOO_METHOD_CLASS], name) != MOO_NULL;
}
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;
if (cc->mth.type == MOO_METHOD_DUAL)
{
return moo_lookupdic(moo, cc->self_oop->mthdic[0], name) != MOO_NULL ||
moo_lookupdic(moo, cc->self_oop->mthdic[1], name) != MOO_NULL;
return moo_lookupdic(moo, cc->self_oop->mthdic[MOO_METHOD_INSTANCE], name) != MOO_NULL ||
moo_lookupdic(moo, cc->self_oop->mthdic[MOO_METHOD_CLASS], name) != MOO_NULL;
}
else
{
@ -6657,11 +6657,11 @@ need to write code to collect string.
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[1], (moo_oop_t)name, (moo_oop_t)mth))
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[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 */
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;
}
}
@ -7820,10 +7820,52 @@ static int process_class_interfaces (moo_t* moo)
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)
{
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)
@ -7833,15 +7875,7 @@ static int check_class_interface_conformance (moo_t* moo)
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, 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;
}
if (!class_implements_interface(moo, cc->self_oop, (moo_oop_interface_t)cc->ifces.ptr[i])) return -1;
}
return 0;
@ -8283,11 +8317,11 @@ static int add_method_signature (moo_t* moo)
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[1], (moo_oop_t)name, (moo_oop_t)mth))
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[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 */
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;
}
}

View File

@ -334,6 +334,29 @@ found:
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 dic;
@ -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_CLASS_SPEC_NAMED_INSTVARS(MOO_OOP_TO_SMOOI(_class->spec)) >= MOO_NSDIC_NAMED_INSTVARS);
return (moo_oop_nsdic_t)moo_makedic(moo, _class, size);
}

View File

@ -1049,6 +1049,13 @@ enum moo_bcode_t
(moo)->shuterr = shuterr; \
} 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)
extern "C" {
#endif
@ -1234,6 +1241,13 @@ int moo_deletedic (
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_t* moo,
moo_oop_class_t _class,