From 277dc64ac41d5d9b6ac5ba605d8c673778fc1b78 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Sat, 12 Oct 2019 04:21:23 +0000 Subject: [PATCH] implemented interface method duplication check in the compiler --- moo/kernel/Class.moo | 7 +++---- moo/lib/comp.c | 30 ++++++++++++++++++-------- moo/lib/exec.c | 4 ++-- moo/lib/moo.c | 4 ++-- moo/lib/moo.h | 50 +++++++++++++++++++++++++++++++++++--------- 5 files changed, 68 insertions(+), 27 deletions(-) diff --git a/moo/kernel/Class.moo b/moo/kernel/Class.moo index 675652f..ad1b115 100644 --- a/moo/kernel/Class.moo +++ b/moo/kernel/Class.moo @@ -10,9 +10,9 @@ interface ClassInterface // class(#pointer,#limited,#uncopyable) Class(Apex) [ClassInterface] { - var spec, selfspec, superclass, subclasses, name, modname. + var name, instmthdic, classmthdic, nsup, nsdic. + var spec, selfspec, superclass, subclasses, modname. var instvars, classinstvars, classvars, pooldics. - var instmthdic, classmthdic, nsup, nsdic. var trsize, trgc, initv, initv_ci. method(#class) initialize { ^self } @@ -46,6 +46,5 @@ class(#pointer,#limited,#uncopyable) Class(Apex) [ClassInterface] class(#pointer,#limited,#uncopyable) Interface(Apex) { - var name. - var instmthdic, classmthdic, nsup, nsdic. + var name, instmthdic, classmthdic, nsup, nsdic. } diff --git a/moo/lib/comp.c b/moo/lib/comp.c index f16c514..829295f 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -9079,17 +9079,29 @@ static int ciim_on_each_method (moo_t* moo, moo_oop_dic_t dic, moo_oop_associati mth = moo_findmethodinclasschain(moo, ciim->_class, ciim->mth_type, &name); if (!mth) { - /* TODO: take methods from interface..*/ if (MOO_CLASSOF(moo, ass->value) == moo->_method) { + moo_oow_t i; + moo_oop_method_t im; + mth = (moo_oop_method_t)ass->value; -#if 0 - if (!moo_putatdic(moo, ciim->_class->mthdic[ciim->mth_type], (moo_oop_t)mth->name, (moo_oop_t)mth)) + for (i = 0; i < ciim->cc->ifce_mths[ciim->mth_type].count; i++) { -/* TODO: error handling. GC safety, etc */ - } -#else - /* TODO: check duplication */ + im = (moo_oop_method_t)ciim->cc->ifce_mths[ciim->mth_type].ptr[i]; + if (mth->name == im->name) + { + /* duplicate interface method name found */ + moo_setsynerrbfmt (moo, MOO_SYNERR_MTHNAMEDUPL, MOO_NULL, MOO_NULL, + "%.*js defined in multiple interfaces for %.*js - %.*js, %.*js", + name.len, name.ptr, + MOO_OBJ_GET_SIZE(ciim->_class->name), MOO_OBJ_GET_CHAR_SLOT(ciim->_class->name), + MOO_OBJ_GET_SIZE(im->owner->name), MOO_OBJ_GET_CHAR_SLOT(im->owner->name), + MOO_OBJ_GET_SIZE(ciim->ifce->name), MOO_OBJ_GET_CHAR_SLOT(ciim->ifce->name) + ); + return -1; + } + } + if (add_oop_to_oopbuf(moo, &ciim->cc->ifce_mths[ciim->mth_type], (moo_oop_t)mth) <= -1) { const moo_ooch_t* oldmsg = moo_backuperrmsg(moo); @@ -9101,8 +9113,7 @@ static int ciim_on_each_method (moo_t* moo, moo_oop_dic_t dic, moo_oop_associati ); return -1; } -#endif - + return 0; } @@ -9213,6 +9224,7 @@ static int check_class_interface_conformance (moo_t* moo) if (!class_implements_interface(moo, cc->self_oop, (moo_oop_interface_t)cc->ifces.ptr[i])) return -1; } + MOO_STATIC_ASSERT (MOO_METHOD_INSTANCE == 0 && MOO_METHOD_CLASS == 1); for (j = MOO_METHOD_INSTANCE; j <= MOO_METHOD_CLASS; j++) { for (i = 0; i < cc->ifce_mths[j].count; i++) diff --git a/moo/lib/exec.c b/moo/lib/exec.c index b30db19..6b30c6a 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -1847,8 +1847,8 @@ moo_oop_method_t moo_findmethod (moo_t* moo, moo_oop_t receiver, moo_oop_char_t if (in_super) { - MOO_ASSERT (moo, moo->active_method); - MOO_ASSERT (moo, moo->active_method->owner); + MOO_ASSERT (moo, moo->active_method != MOO_NULL); + MOO_ASSERT (moo, moo->active_method->owner != MOO_NULL); /* if 'super' is allowed in the interface method, the owner field * can be an interface. super must not be allowed in the interface diff --git a/moo/lib/moo.c b/moo/lib/moo.c index 7bad723..aaa5fc7 100644 --- a/moo/lib/moo.c +++ b/moo/lib/moo.c @@ -873,8 +873,8 @@ int moo_genpfmethod (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class, moo_met mth->literal_frame[0] = (moo_oop_t)pfidsym; /* premable should contain the index to the literal frame which is always 0 */ - mth->owner = _class; - mth->name = mnsym; + MOO_STORE_OOP (moo, (moo_oop_t*)&mth->owner, (moo_oop_t)_class); + MOO_STORE_OOP (moo, (moo_oop_t*)&mth->name, (moo_oop_t)mnsym); if (variadic) preamble_flags |= MOO_METHOD_PREAMBLE_FLAG_VARIADIC; mth->preamble = MOO_SMOOI_TO_OOP(MOO_METHOD_MAKE_PREAMBLE(MOO_METHOD_PREAMBLE_NAMED_PRIMITIVE, 0, preamble_flags)); mth->preamble_data[0] = MOO_SMPTR_TO_OOP(0); diff --git a/moo/lib/moo.h b/moo/lib/moo.h index cd9d1d1..6d0a5db 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -470,6 +470,10 @@ struct moo_dic_t typedef struct moo_nsdic_t moo_nsdic_t; typedef struct moo_nsdic_t* moo_oop_nsdic_t; +#define MOO_METHOWNER_NAMED_INSTVARS 5 +typedef struct moo_methowner_t moo_methowner_t; +typedef struct moo_methowner_t* moo_oop_methowner_t; + #define MOO_INTERFACE_NAMED_INSTVARS 5 typedef struct moo_interface_t moo_interface_t; typedef struct moo_interface_t* moo_oop_interface_t; @@ -489,29 +493,62 @@ struct moo_nsdic_t moo_oop_t nsup; /* a class if it belongs to the class. another nsdic if it doesn't */ }; -struct moo_interface_t +struct moo_methowner_t { + /* a method can be owned by a class or an interface. + * this structure defines common fields between a class and an interface and + * is for internal VM use only. */ MOO_OBJ_HEADER; + + /* === the following five fields must be placed in class and interface === */ moo_oop_char_t name; /* [0] - instance methods, MethodDictionary * [1] - class methods, MethodDictionary */ moo_oop_dic_t mthdic[2]; + moo_oop_nsdic_t nsup; /* pointer to the upper namespace */ moo_oop_nsdic_t nsdic; /* dictionary used for namespacing - may be nil when there are no subitems underneath */ + /* ======================================================================== */ +}; + +struct moo_interface_t +{ + MOO_OBJ_HEADER; + + /* === the following five fields must be in sync with moo_methowner_t === */ + moo_oop_char_t name; + + /* [0] - instance methods, MethodDictionary + * [1] - class methods, MethodDictionary */ + moo_oop_dic_t mthdic[2]; + + moo_oop_nsdic_t nsup; /* pointer to the upper namespace */ + moo_oop_nsdic_t nsdic; /* dictionary used for namespacing - may be nil when there are no subitems underneath */ + /* ===================================================================== */ }; struct moo_class_t { MOO_OBJ_HEADER; + /* === the following five fields must be in sync with moo_methowner_t === */ + moo_oop_char_t name; /* Symbol */ + + /* [0] - instance methods, MethodDictionary + * [1] - class methods, MethodDictionary */ + moo_oop_dic_t mthdic[2]; + + moo_oop_nsdic_t nsup; /* pointer to the upper namespace */ + moo_oop_nsdic_t nsdic; /* dictionary used for namespacing - may be nil when there are no subitems underneath */ + /* ===================================================================== */ + moo_oop_t spec; /* SmallInteger. instance specification */ moo_oop_t selfspec; /* SmallInteger. specification of the class object itself */ moo_oop_t superclass; /* Another class */ moo_oop_t subclasses; /* Array of subclasses */ - moo_oop_char_t name; /* Symbol */ moo_oop_t modname; /* Symbol if importing a module. nil if not. */ /* == NEVER CHANGE THIS ORDER OF 3 ITEMS BELOW == */ @@ -522,13 +559,6 @@ struct moo_class_t moo_oop_char_t pooldics; /* String - pool dictionaries imported */ - /* [0] - instance methods, MethodDictionary - * [1] - class methods, MethodDictionary */ - moo_oop_dic_t mthdic[2]; - - moo_oop_nsdic_t nsup; /* pointer to the upper namespace */ - moo_oop_nsdic_t nsdic; /* dictionary used for namespacing - may be nil when there are no subitems underneath */ - moo_oop_t trsize; /* trailer size for new instances */ moo_oop_t trgc; /* trailer gc callback */ @@ -571,7 +601,7 @@ struct moo_method_t { MOO_OBJ_HEADER; - moo_oop_class_t owner; /* Class */ + moo_oop_methowner_t owner; /* Class or Interface */ moo_oop_char_t name; /* Symbol, method name */