implemented interface method duplication check in the compiler

This commit is contained in:
hyunghwan.chung 2019-10-12 04:21:23 +00:00
parent 5be193b3fe
commit 277dc64ac4
5 changed files with 68 additions and 27 deletions

View File

@ -10,9 +10,9 @@ interface ClassInterface
// //
class(#pointer,#limited,#uncopyable) Class(Apex) [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 instvars, classinstvars, classvars, pooldics.
var instmthdic, classmthdic, nsup, nsdic.
var trsize, trgc, initv, initv_ci. var trsize, trgc, initv, initv_ci.
method(#class) initialize { ^self } method(#class) initialize { ^self }
@ -46,6 +46,5 @@ class(#pointer,#limited,#uncopyable) Class(Apex) [ClassInterface]
class(#pointer,#limited,#uncopyable) Interface(Apex) class(#pointer,#limited,#uncopyable) Interface(Apex)
{ {
var name. var name, instmthdic, classmthdic, nsup, nsdic.
var instmthdic, classmthdic, nsup, nsdic.
} }

View File

@ -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); mth = moo_findmethodinclasschain(moo, ciim->_class, ciim->mth_type, &name);
if (!mth) if (!mth)
{ {
/* TODO: take methods from interface..*/
if (MOO_CLASSOF(moo, ass->value) == moo->_method) if (MOO_CLASSOF(moo, ass->value) == moo->_method)
{ {
moo_oow_t i;
moo_oop_method_t im;
mth = (moo_oop_method_t)ass->value; mth = (moo_oop_method_t)ass->value;
#if 0 for (i = 0; i < ciim->cc->ifce_mths[ciim->mth_type].count; i++)
if (!moo_putatdic(moo, ciim->_class->mthdic[ciim->mth_type], (moo_oop_t)mth->name, (moo_oop_t)mth))
{ {
/* TODO: error handling. GC safety, etc */ im = (moo_oop_method_t)ciim->cc->ifce_mths[ciim->mth_type].ptr[i];
} if (mth->name == im->name)
#else {
/* TODO: check duplication */ /* 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) 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); 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; return -1;
} }
#endif
return 0; 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; 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 (j = MOO_METHOD_INSTANCE; j <= MOO_METHOD_CLASS; j++)
{ {
for (i = 0; i < cc->ifce_mths[j].count; i++) for (i = 0; i < cc->ifce_mths[j].count; i++)

View File

@ -1847,8 +1847,8 @@ moo_oop_method_t moo_findmethod (moo_t* moo, moo_oop_t receiver, moo_oop_char_t
if (in_super) if (in_super)
{ {
MOO_ASSERT (moo, moo->active_method); MOO_ASSERT (moo, moo->active_method != MOO_NULL);
MOO_ASSERT (moo, moo->active_method->owner); MOO_ASSERT (moo, moo->active_method->owner != MOO_NULL);
/* if 'super' is allowed in the interface method, the owner field /* if 'super' is allowed in the interface method, the owner field
* can be an interface. super must not be allowed in the interface * can be an interface. super must not be allowed in the interface

View File

@ -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; mth->literal_frame[0] = (moo_oop_t)pfidsym;
/* premable should contain the index to the literal frame which is always 0 */ /* premable should contain the index to the literal frame which is always 0 */
mth->owner = _class; MOO_STORE_OOP (moo, (moo_oop_t*)&mth->owner, (moo_oop_t)_class);
mth->name = mnsym; MOO_STORE_OOP (moo, (moo_oop_t*)&mth->name, (moo_oop_t)mnsym);
if (variadic) preamble_flags |= MOO_METHOD_PREAMBLE_FLAG_VARIADIC; 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 = 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); mth->preamble_data[0] = MOO_SMPTR_TO_OOP(0);

View File

@ -470,6 +470,10 @@ struct moo_dic_t
typedef struct moo_nsdic_t moo_nsdic_t; typedef struct moo_nsdic_t moo_nsdic_t;
typedef struct moo_nsdic_t* moo_oop_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 #define MOO_INTERFACE_NAMED_INSTVARS 5
typedef struct moo_interface_t moo_interface_t; typedef struct moo_interface_t moo_interface_t;
typedef struct moo_interface_t* moo_oop_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 */ 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; MOO_OBJ_HEADER;
/* === the following five fields must be placed in class and interface === */
moo_oop_char_t name; moo_oop_char_t name;
/* [0] - instance methods, MethodDictionary /* [0] - instance methods, MethodDictionary
* [1] - class methods, MethodDictionary */ * [1] - class methods, MethodDictionary */
moo_oop_dic_t mthdic[2]; moo_oop_dic_t mthdic[2];
moo_oop_nsdic_t nsup; /* pointer to the upper namespace */ 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_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 struct moo_class_t
{ {
MOO_OBJ_HEADER; 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 spec; /* SmallInteger. instance specification */
moo_oop_t selfspec; /* SmallInteger. specification of the class object itself */ moo_oop_t selfspec; /* SmallInteger. specification of the class object itself */
moo_oop_t superclass; /* Another class */ moo_oop_t superclass; /* Another class */
moo_oop_t subclasses; /* Array of subclasses */ 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. */ moo_oop_t modname; /* Symbol if importing a module. nil if not. */
/* == NEVER CHANGE THIS ORDER OF 3 ITEMS BELOW == */ /* == 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 */ 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 trsize; /* trailer size for new instances */
moo_oop_t trgc; /* trailer gc callback */ moo_oop_t trgc; /* trailer gc callback */
@ -571,7 +601,7 @@ struct moo_method_t
{ {
MOO_OBJ_HEADER; 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 */ moo_oop_char_t name; /* Symbol, method name */