diff --git a/moo/kernel/X11.moo b/moo/kernel/X11.moo index e4a0c6b..53efb82 100644 --- a/moo/kernel/X11.moo +++ b/moo/kernel/X11.moo @@ -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. diff --git a/moo/lib/bigint.c b/moo/lib/bigint.c index 452eb6d..735686a 100644 --- a/moo/lib/bigint.c +++ b/moo/lib/bigint.c @@ -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 */ diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 268e6c2..36c1c86 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -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; } } diff --git a/moo/lib/dic.c b/moo/lib/dic.c index 4da0e88..22c9de6 100644 --- a/moo/lib/dic.c +++ b/moo/lib/dic.c @@ -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); } diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 13af13f..0a00ade 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -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,