added moo_walkdic() for internal use
added incomplete interface implementation check
This commit is contained in:
parent
9656d87816
commit
c6c3739572
@ -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.
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
{
|
||||
|
||||
return 0;
|
||||
ciim_t ciim;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
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);
|
||||
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_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_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)
|
||||
{
|
||||
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_ASSERT (moo, MOO_CLASSOF(moo,key) == moo->_symbol);*/
|
||||
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_ASSERT (moo, MOO_CLASSOF(moo,key) == moo->_symbol); */
|
||||
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)
|
||||
@ -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;
|
||||
@ -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_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;
|
||||
|
||||
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);
|
||||
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_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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user