added some interface implementation code
This commit is contained in:
parent
cde05be1a1
commit
90ed6d91e3
250
moo/lib/comp.c
250
moo/lib/comp.c
@ -51,8 +51,7 @@
|
|||||||
enum class_type_t
|
enum class_type_t
|
||||||
{
|
{
|
||||||
CLASS_TYPE_NORMAL = 0,
|
CLASS_TYPE_NORMAL = 0,
|
||||||
CLASS_TYPE_EXTEND,
|
CLASS_TYPE_EXTEND
|
||||||
CLASS_TYPE_INTERFACE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class_mod_t
|
enum class_mod_t
|
||||||
@ -2796,6 +2795,13 @@ static MOO_INLINE int set_pooldic_fqn (moo_t* moo, moo_cunit_pooldic_t* pd, cons
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MOO_INLINE int set_interface_fqn (moo_t* moo, moo_cunit_interface_t* ifce, const moo_oocs_t* name)
|
||||||
|
{
|
||||||
|
if (copy_string_to(moo, name, &ifce->fqn, &ifce->fqn_capa, 0, '\0') <= -1) return -1;
|
||||||
|
ifce->name = ifce->fqn;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static MOO_INLINE int add_class_level_variable (moo_t* moo, var_type_t var_type, const moo_oocs_t* name, const moo_ioloc_t* loc)
|
static MOO_INLINE int add_class_level_variable (moo_t* moo, var_type_t var_type, const moo_oocs_t* name, const moo_ioloc_t* loc)
|
||||||
{
|
{
|
||||||
moo_cunit_class_t* cc = (moo_cunit_class_t*)moo->c->cunit;
|
moo_cunit_class_t* cc = (moo_cunit_class_t*)moo->c->cunit;
|
||||||
@ -7661,7 +7667,7 @@ static int __compile_class_definition (moo_t* moo, int class_type)
|
|||||||
if (cc->cunit_parent && cc->cunit_parent->cunit_type == MOO_CUNIT_CLASS && TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED)
|
if (cc->cunit_parent && cc->cunit_parent->cunit_type == MOO_CUNIT_CLASS && TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED)
|
||||||
{
|
{
|
||||||
/* the name of a nested class cannot be multi-segmented */
|
/* the name of a nested class cannot be multi-segmented */
|
||||||
moo_setsynerrbfmt (moo, MOO_SYNERR_IDENT, TOKEN_LOC(moo), TOKEN_NAME(moo), "undotted identifier expected");
|
moo_setsynerrbfmt (moo, MOO_SYNERR_IDENT, TOKEN_LOC(moo), TOKEN_NAME(moo), "undotted class name expected");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7702,24 +7708,7 @@ static int __compile_class_definition (moo_t* moo, int class_type)
|
|||||||
}
|
}
|
||||||
GET_TOKEN (moo);
|
GET_TOKEN (moo);
|
||||||
|
|
||||||
if (class_type == CLASS_TYPE_INTERFACE)
|
if (class_type == CLASS_TYPE_EXTEND)
|
||||||
{
|
|
||||||
MOO_ASSERT (moo, cc->flags == 0);
|
|
||||||
|
|
||||||
MOO_INFO2 (moo, "Defining an interface %.*js\n", cc->fqn.len, cc->fqn.ptr);
|
|
||||||
|
|
||||||
ass = moo_lookupdic(moo, (moo_oop_dic_t)cc->ns_oop, &cc->name);
|
|
||||||
if (ass)
|
|
||||||
{
|
|
||||||
// The interface name already exists. An interface cannot be defined with an existing name
|
|
||||||
moo_setsynerr (moo, MOO_SYNERR_CLASSDUPL, &cc->fqn_loc, &cc->name); /* TODO: change the error code to MOO_SYNERR_IFCEDUPL? */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* an interface doesn't inherit anything */
|
|
||||||
cc->super_oop = moo->_nil;
|
|
||||||
}
|
|
||||||
else if (class_type == CLASS_TYPE_EXTEND)
|
|
||||||
{
|
{
|
||||||
/* extending class */
|
/* extending class */
|
||||||
MOO_ASSERT (moo, cc->flags == 0);
|
MOO_ASSERT (moo, cc->flags == 0);
|
||||||
@ -7956,21 +7945,7 @@ static int __compile_class_definition (moo_t* moo, int class_type)
|
|||||||
|
|
||||||
GET_TOKEN (moo);
|
GET_TOKEN (moo);
|
||||||
|
|
||||||
if (class_type == CLASS_TYPE_INTERFACE)
|
if (class_type == CLASS_TYPE_EXTEND)
|
||||||
{
|
|
||||||
/* an interface cannot have variables */
|
|
||||||
if (is_token_word(moo, VOCA_VAR) || is_token_word(moo, VOCA_VARIABLE) ||
|
|
||||||
is_token_binary_selector(moo, VOCA_VBAR) ||
|
|
||||||
is_token_binary_selector(moo, VOCA_VBAR_PLUS) ||
|
|
||||||
is_token_binary_selector(moo, VOCA_VBAR_ASTER))
|
|
||||||
{
|
|
||||||
moo_setsynerr (moo, MOO_SYNERR_VARDCLBANNED, TOKEN_LOC(moo), TOKEN_NAME(moo));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (make_defined_interface(moo) <= -1) return -1;
|
|
||||||
}
|
|
||||||
else if (class_type == CLASS_TYPE_EXTEND)
|
|
||||||
{
|
{
|
||||||
moo_oop_char_t pds;
|
moo_oop_char_t pds;
|
||||||
|
|
||||||
@ -8171,7 +8146,164 @@ static int compile_class_definition (moo_t* moo, int class_type)
|
|||||||
|
|
||||||
static int __compile_interface_definition (moo_t* moo)
|
static int __compile_interface_definition (moo_t* moo)
|
||||||
{
|
{
|
||||||
|
moo_cunit_interface_t* ifce = (moo_cunit_interface_t*)moo->c->cunit;
|
||||||
|
moo_oop_association_t ass;
|
||||||
|
|
||||||
|
if (TOKEN_TYPE(moo) != MOO_IOTOK_IDENT &&
|
||||||
|
TOKEN_TYPE(moo) != MOO_IOTOK_IDENT_DOTTED)
|
||||||
|
{
|
||||||
|
/* interface name expected. */
|
||||||
|
moo_setsynerr (moo, MOO_SYNERR_IDENT, TOKEN_LOC(moo), TOKEN_NAME(moo));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ifce->cunit_parent && ifce->cunit_parent->cunit_type == MOO_CUNIT_CLASS && TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED)
|
||||||
|
{
|
||||||
|
/* the name of a nested class cannot be multi-segmented */
|
||||||
|
moo_setsynerrbfmt (moo, MOO_SYNERR_IDENT, TOKEN_LOC(moo), TOKEN_NAME(moo), "undotted interface name expected");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT && is_restricted_word(TOKEN_NAME(moo)))
|
||||||
|
{
|
||||||
|
/* wrong class name */
|
||||||
|
moo_setsynerr (moo, MOO_SYNERR_CLASSNAMEINVAL, TOKEN_LOC(moo), TOKEN_NAME(moo));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* [NOTE] TOKEN_NAME(moo) doesn't contain the full name if it's nested
|
||||||
|
* inside a class. it is merely a name that appeared in the source
|
||||||
|
* code.
|
||||||
|
* TODO: compose the full name by traversing the namespace chain. */
|
||||||
|
if (set_interface_fqn(moo, ifce, TOKEN_NAME(moo)) <= -1) return -1;
|
||||||
|
ifce->fqn_loc = moo->c->tok.loc;
|
||||||
|
|
||||||
|
if (ifce->cunit_parent && ifce->cunit_parent->cunit_type == MOO_CUNIT_CLASS)
|
||||||
|
{
|
||||||
|
/* nested inside a class */
|
||||||
|
moo_cunit_interface_t* c = (moo_cunit_interface_t*)ifce->cunit_parent;
|
||||||
|
if ((moo_oop_t)c->self_oop->nsdic == moo->_nil)
|
||||||
|
{
|
||||||
|
/* attach a new namespace dictionary to the nsdic field of the class */
|
||||||
|
if (!attach_nsdic_to_class(moo, c->self_oop)) return -1;
|
||||||
|
}
|
||||||
|
ifce->ns_oop = c->self_oop->nsdic; /* TODO: if c->nsdic is nil, create one? */
|
||||||
|
}
|
||||||
|
else if (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED)
|
||||||
|
{
|
||||||
|
if (preprocess_dotted_name(moo, 0, MOO_NULL, &ifce->fqn, &ifce->fqn_loc, &ifce->name, &ifce->ns_oop) <= -1) return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ifce->ns_oop = moo->sysdic;
|
||||||
|
}
|
||||||
|
GET_TOKEN (moo);
|
||||||
|
|
||||||
|
MOO_INFO2 (moo, "Defining an interface %.*js\n", ifce->fqn.len, ifce->fqn.ptr);
|
||||||
|
|
||||||
|
ass = moo_lookupdic(moo, (moo_oop_dic_t)ifce->ns_oop, &ifce->name);
|
||||||
|
if (ass)
|
||||||
|
{
|
||||||
|
// The interface name already exists. An interface cannot be defined with an existing name
|
||||||
|
moo_setsynerr (moo, MOO_SYNERR_CLASSDUPL, &ifce->fqn_loc, &ifce->name); /* TODO: change the error code to MOO_SYNERR_IFCEDUPL? */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* an interface doesn't inherit anything */
|
||||||
|
ifce->super_oop = moo->_nil;
|
||||||
|
|
||||||
|
if (TOKEN_TYPE(moo) != MOO_IOTOK_LBRACE)
|
||||||
|
{
|
||||||
|
moo_setsynerr (moo, MOO_SYNERR_LBRACE, TOKEN_LOC(moo), TOKEN_NAME(moo));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
MOO_ASSERT (moo, ifce->super_oop != MOO_NULL);
|
||||||
|
if (ifce->super_oop != moo->_nil)
|
||||||
|
{
|
||||||
|
/* adjust the instance variable count and the class instance variable
|
||||||
|
* count to include that of a superclass */
|
||||||
|
moo_oop_class_t c;
|
||||||
|
moo_oow_t spec, self_spec;
|
||||||
|
|
||||||
|
c = (moo_oop_class_t)ifce->super_oop;
|
||||||
|
spec = MOO_OOP_TO_SMOOI(c->spec);
|
||||||
|
self_spec = MOO_OOP_TO_SMOOI(c->selfspec);
|
||||||
|
|
||||||
|
/* [NOTE] class variables are not inherited.
|
||||||
|
* so no data about them are not transferred over */
|
||||||
|
|
||||||
|
if ((ifce->flags & CLASS_INDEXED) && ifce->indexed_type != MOO_OBJ_TYPE_OOP)
|
||||||
|
{
|
||||||
|
/* the class defined is a non-pointer object. */
|
||||||
|
if (MOO_CLASS_SPEC_INDEXED_TYPE(spec) == MOO_OBJ_TYPE_OOP && MOO_CLASS_SPEC_NAMED_INSTVARS(spec) > 0)
|
||||||
|
{
|
||||||
|
/* a non-pointer object cannot inherit from a pointer object with instance variables */
|
||||||
|
moo_setsynerrbfmt (moo, MOO_SYNERR_INHERITBANNED, &ifce->fqn_loc, &ifce->fqn,
|
||||||
|
"the non-pointer class %.*js cannot inherit from a pointer class defined with instance variables",
|
||||||
|
ifce->fqn.len, ifce->fqn.ptr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: I don't mandate that the parent and the child be of the same type.
|
||||||
|
* Say, for a parent class(#byte(4)), a child can be defined to be
|
||||||
|
* class(#word(4)). */
|
||||||
|
|
||||||
|
if (ifce->non_pointer_instsize < MOO_CLASS_SPEC_NAMED_INSTVARS(spec))
|
||||||
|
{
|
||||||
|
moo_setsynerrbfmt (moo, MOO_SYNERR_NPINSTSIZEINVAL, &type_loc, MOO_NULL,
|
||||||
|
"the instance size(%zu) for the non-pointer class %.*js must not be less than the size(%zu) defined in the superclass ",
|
||||||
|
ifce->non_pointer_instsize, ifce->fqn.len, ifce->fqn.ptr, (moo_oow_t)MOO_CLASS_SPEC_NAMED_INSTVARS(spec));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* the class defined is a pointer object or a variable-pointer object */
|
||||||
|
MOO_ASSERT (moo, ifce->non_pointer_instsize == 0); /* no such thing as class(#pointer(N)). so it must be 0 */
|
||||||
|
ifce->var[VAR_INSTANCE].total_count = MOO_CLASS_SPEC_NAMED_INSTVARS(spec);
|
||||||
|
}
|
||||||
|
ifce->var[VAR_CLASSINST].total_count = MOO_CLASS_SELFSPEC_CLASSINSTVARS(self_spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
GET_TOKEN (moo);
|
||||||
|
|
||||||
|
/* an interface cannot have variables */
|
||||||
|
if (is_token_word(moo, VOCA_VAR) || is_token_word(moo, VOCA_VARIABLE) ||
|
||||||
|
is_token_binary_selector(moo, VOCA_VBAR) ||
|
||||||
|
is_token_binary_selector(moo, VOCA_VBAR_PLUS) ||
|
||||||
|
is_token_binary_selector(moo, VOCA_VBAR_ASTER))
|
||||||
|
{
|
||||||
|
moo_setsynerr (moo, MOO_SYNERR_VARDCLBANNED, TOKEN_LOC(moo), TOKEN_NAME(moo));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (make_defined_interface(moo) <= -1) return -1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (is_token_word(moo, VOCA_METHOD))
|
||||||
|
{
|
||||||
|
/* method definition in class definition */
|
||||||
|
GET_TOKEN (moo);
|
||||||
|
if (compile_method_definition(moo) <= -1) return -1;
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
while (1);
|
||||||
|
|
||||||
|
if (TOKEN_TYPE(moo) != MOO_IOTOK_RBRACE)
|
||||||
|
{
|
||||||
|
moo_setsynerr (moo, MOO_SYNERR_RBRACE, TOKEN_LOC(moo), TOKEN_NAME(moo));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
GET_TOKEN (moo);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int compile_interface_definition (moo_t* moo)
|
static int compile_interface_definition (moo_t* moo)
|
||||||
@ -8327,7 +8459,7 @@ static int __compile_pooldic_definition (moo_t* moo)
|
|||||||
if (pd->cunit_parent && pd->cunit_parent->cunit_type == MOO_CUNIT_CLASS && TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED)
|
if (pd->cunit_parent && pd->cunit_parent->cunit_type == MOO_CUNIT_CLASS && TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED)
|
||||||
{
|
{
|
||||||
/* the pool dictionary nested inside a class cannot be multi-segmented */
|
/* the pool dictionary nested inside a class cannot be multi-segmented */
|
||||||
moo_setsynerrbfmt (moo, MOO_SYNERR_IDENT, TOKEN_LOC(moo), TOKEN_NAME(moo), "undotted identifier expected");
|
moo_setsynerrbfmt (moo, MOO_SYNERR_IDENT, TOKEN_LOC(moo), TOKEN_NAME(moo), "undotted pooldic name expected");
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8639,6 +8771,23 @@ static void gc_cunit_chain (moo_t* moo)
|
|||||||
{
|
{
|
||||||
switch (cunit->cunit_type)
|
switch (cunit->cunit_type)
|
||||||
{
|
{
|
||||||
|
case MOO_CUNIT_POOLDIC:
|
||||||
|
{
|
||||||
|
moo_cunit_pooldic_t* pd;
|
||||||
|
pd = (moo_cunit_pooldic_t*)cunit;
|
||||||
|
if (pd->pd_oop)
|
||||||
|
{
|
||||||
|
register moo_oop_t x = moo_moveoop(moo, (moo_oop_t)pd->pd_oop);
|
||||||
|
pd->pd_oop = (moo_oop_dic_t)x;
|
||||||
|
}
|
||||||
|
if (pd->ns_oop)
|
||||||
|
{
|
||||||
|
register moo_oop_t x = moo_moveoop(moo, (moo_oop_t)pd->ns_oop);
|
||||||
|
pd->ns_oop = (moo_oop_nsdic_t)x;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MOO_CUNIT_CLASS:
|
case MOO_CUNIT_CLASS:
|
||||||
{
|
{
|
||||||
moo_oow_t i, j;
|
moo_oow_t i, j;
|
||||||
@ -8687,20 +8836,29 @@ static void gc_cunit_chain (moo_t* moo)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MOO_CUNIT_POOLDIC:
|
case MOO_CUNIT_INTERFACE:
|
||||||
{
|
{
|
||||||
moo_cunit_pooldic_t* pd;
|
moo_cunit_interface_t* ifce;
|
||||||
pd = (moo_cunit_pooldic_t*)cunit;
|
ifce = (moo_cunit_interface_t*)cunit;
|
||||||
if (pd->pd_oop)
|
|
||||||
|
if (ifce->self_oop)
|
||||||
|
ifce->self_oop = (moo_oop_class_t)moo_moveoop(moo, (moo_oop_t)ifce->self_oop);
|
||||||
|
|
||||||
|
if (ifce->super_oop)
|
||||||
|
ifce->super_oop = moo_moveoop(moo, ifce->super_oop);
|
||||||
|
|
||||||
|
if (ifce->ns_oop)
|
||||||
{
|
{
|
||||||
register moo_oop_t x = moo_moveoop(moo, (moo_oop_t)pd->pd_oop);
|
register moo_oop_t x = moo_moveoop(moo, (moo_oop_t)ifce->ns_oop);
|
||||||
pd->pd_oop = (moo_oop_dic_t)x;
|
ifce->ns_oop = (moo_oop_nsdic_t)x;
|
||||||
}
|
}
|
||||||
if (pd->ns_oop)
|
|
||||||
|
if (ifce->superns_oop)
|
||||||
{
|
{
|
||||||
register moo_oop_t x = moo_moveoop(moo, (moo_oop_t)pd->ns_oop);
|
register moo_oop_t x = moo_moveoop(moo, (moo_oop_t)ifce->superns_oop);
|
||||||
pd->ns_oop = (moo_oop_nsdic_t)x;
|
ifce->superns_oop = (moo_oop_nsdic_t)x;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user