From 18b270529cb550de0997f7d7f5dd172661de7408 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Fri, 12 Oct 2018 09:09:45 +0000 Subject: [PATCH] added moo_findmethodinclasschain() added MOO_SYNERR_CLASSNCIFCE finished implementing interface conformance check primitively --- moo/kernel/Class.moo | 8 ++- moo/kernel/X11.moo | 8 +-- moo/kernel/generr.moo | 1 + moo/lib/comp.c | 66 +++++++++++++++----- moo/lib/err.c | 87 +++++++++++++------------- moo/lib/exec.c | 141 +++++++++++++++++++++++++----------------- moo/lib/gc.c | 2 +- moo/lib/moo-prv.h | 15 +++++ moo/lib/moo.h | 5 ++ moo/lib/pf-basic.c | 2 +- 10 files changed, 210 insertions(+), 125 deletions(-) diff --git a/moo/kernel/Class.moo b/moo/kernel/Class.moo index 7a2c726..c3dbbb2 100644 --- a/moo/kernel/Class.moo +++ b/moo/kernel/Class.moo @@ -1,8 +1,14 @@ +interface ClassInterface +{ + method name. + method superclass. +} + ## ## the Class object should be a variable-pointer object because ## it needs to accomodate class instance variables. ## -class(#pointer,#limited) Class(Apex) +class(#pointer,#limited) Class(Apex) [ClassInterface] { var spec, selfspec, superclass, subclasses, name, modname. var instvars, classinstvars, classvars, pooldics. diff --git a/moo/kernel/X11.moo b/moo/kernel/X11.moo index 53efb82..8f4c59f 100644 --- a/moo/kernel/X11.moo +++ b/moo/kernel/X11.moo @@ -3,7 +3,7 @@ interface X11able { method(#dual) abc. - method(#dual) def. + method(#dual,#liberal) def(x, y). } interface X11able2 { @@ -13,7 +13,7 @@ interface X11able2 interface X11able3 { - method(#dual) abc3. + method(#dual) class. } @@ -33,8 +33,8 @@ class X11(Object) [X11able,selfns.X11able3] from 'x11' var llevent_blocks. method(#dual) abc { ^nil } -method(#dual) def { ^nil } -method(#dual) abc3 { ^nil } +method(#dual,#liberal) def(x, z) { ^nil } +###method(#dual) abc3 { ^nil } interface X11able3 { diff --git a/moo/kernel/generr.moo b/moo/kernel/generr.moo index 41a2c9f..4578eb0 100644 --- a/moo/kernel/generr.moo +++ b/moo/kernel/generr.moo @@ -80,6 +80,7 @@ class MyObject(Object) 'duplicate name' 'undefined name' 'contradictory class definition' + 'class not conforming to interface' 'invalid non-pointer instance size' 'prohibited inheritance' 'variable declaration not allowed' diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 2e4d373..0e67caa 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -4253,7 +4253,7 @@ static MOO_INLINE int find_dotted_ident (moo_t* moo, const moo_oocs_t* name, con MOO_ASSERT (moo, moo->c->cunit->cunit_type == MOO_CUNIT_CLASS); /* called inside a class definition */ - if (cc->super_oop) + if (cc->in_class_body) { /* [NOTE] * cls.ns_oop is set when the class name is enountered. @@ -4262,6 +4262,7 @@ static MOO_INLINE int find_dotted_ident (moo_t* moo, const moo_oocs_t* name, con * on the other hand, cls.ns_oop is not MOO_NULL as long as * cls.super_oop is not MOO_NULL. */ + MOO_ASSERT (moo, cc->super_oop != MOO_NULL); MOO_ASSERT (moo, cc->ns_oop != MOO_NULL); /* cc->self_oop may still be MOO_NULL if the class has not been instantiated */ @@ -4371,11 +4372,11 @@ static MOO_INLINE int find_undotted_ident (moo_t* moo, const moo_oocs_t* name, c } } - if (cc->super_oop) + if (cc->in_class_body) { /* called inside a class definition */ /* read a comment in find_dotted_ident() for the reason behind - * the if condition above. */ + * the 'if' condition above. */ MOO_ASSERT (moo, cc->super_oop != MOO_NULL); MOO_ASSERT (moo, cc->ns_oop != MOO_NULL); @@ -4384,7 +4385,7 @@ static MOO_INLINE int find_undotted_ident (moo_t* moo, const moo_oocs_t* name, c { /* if the current class being compiled has not been instantiated, * no validation nor adjustment of the var->pos field is performed */ - return cc->self_oop? validate_class_level_variable (moo, var, name, name_loc): 0; + return cc->self_oop? validate_class_level_variable(moo, var, name, name_loc): 0; } } @@ -7310,7 +7311,7 @@ static int make_defined_class (moo_t* moo) /* this is an internally created class object being defined. */ MOO_ASSERT (moo, MOO_CLASSOF(moo, cc->self_oop) == moo->_class); - MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_KERNEL(cc->self_oop) == 1); + MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_KERNEL(cc->self_oop) == MOO_OBJ_FLAGS_KERNEL_IMMATURE); if (spec != MOO_OOP_TO_SMOOI(cc->self_oop->spec) || self_spec != MOO_OOP_TO_SMOOI(cc->self_oop->selfspec)) @@ -7341,7 +7342,7 @@ static int make_defined_class (moo_t* moo) * if superclass is byte variable, the current class cannot be word variable or something else. * TODO: TODO: TODO: */ - MOO_OBJ_SET_FLAGS_KERNEL (cc->self_oop, 2); + MOO_OBJ_SET_FLAGS_KERNEL (cc->self_oop, MOO_OBJ_FLAGS_KERNEL_MATURE); cc->self_oop->superclass = cc->super_oop; @@ -7680,7 +7681,8 @@ static int process_class_superclass (moo_t* moo) if (get_variable_info(moo, &cc->superfqn, &cc->superfqn_loc, superfqn_is_dotted, &var) <= -1) return -1; if (var.type != VAR_GLOBAL) goto unknown_superclass; - if (MOO_CLASSOF(moo, var.u.gbl->value) == moo->_class && MOO_OBJ_GET_FLAGS_KERNEL(var.u.gbl->value) != 1) + if (MOO_CLASSOF(moo, var.u.gbl->value) == moo->_class && + MOO_OBJ_GET_FLAGS_KERNEL(var.u.gbl->value) != MOO_OBJ_FLAGS_KERNEL_IMMATURE) { /* the value found must be a class and it must not be an incomplete internal class object. * 0(non-kernel object) @@ -7830,17 +7832,21 @@ struct ciim_t }; 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) +static int ciim_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; + moo_oop_method_t mth; + moo_oop_methsig_t sig; 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, + + /* [IMPORT] the method lookup logic should be the same as moo_findmethod() in exec.c */ + mth = moo_findmethodinclasschain(moo, ciim->_class, ciim->mth_type, &name); + if (!mth) + { + moo_setsynerrbfmt (moo, MOO_SYNERR_CLASSNCIFCE, 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), @@ -7849,7 +7855,31 @@ static int on_each_method (moo_t* moo, moo_oop_dic_t dic, moo_oop_association_t return -1; } -/* TODO: check preamble flags in signature */ + sig = (moo_oop_methsig_t)ass->value; + if (MOO_METHOD_GET_PREAMBLE_FLAGS(MOO_OOP_TO_SMOOI(mth->preamble)) != MOO_METHOD_GET_PREAMBLE_FLAGS(MOO_OOP_TO_SMOOI(sig->preamble))) + { + moo_setsynerrbfmt (moo, MOO_SYNERR_CLASSNCIFCE, MOO_NULL, MOO_NULL, + "%.*js>>%.*js modifiers conficting with %.*js>>%.*js", + MOO_OBJ_GET_SIZE(ciim->_class->name), MOO_OBJ_GET_CHAR_SLOT(ciim->_class->name), + name.len, name.ptr, + MOO_OBJ_GET_SIZE(ciim->ifce->name), MOO_OBJ_GET_CHAR_SLOT(ciim->ifce->name), + name.len, name.ptr + ); + return -1; + } + + if (mth->tmpr_nargs != sig->tmpr_nargs) /* don't need MOO_OOP_TO_SMOOI */ + { + moo_setsynerrbfmt (moo, MOO_SYNERR_CLASSNCIFCE, MOO_NULL, MOO_NULL, + "%.*js>>%.*js parameters conflicting with %.*js>>%.*js", + MOO_OBJ_GET_SIZE(ciim->_class->name), MOO_OBJ_GET_CHAR_SLOT(ciim->_class->name), + name.len, name.ptr, + MOO_OBJ_GET_SIZE(ciim->ifce->name), MOO_OBJ_GET_CHAR_SLOT(ciim->ifce->name), + name.len, name.ptr + ); + return -1; + } + return 0; } @@ -7860,12 +7890,12 @@ static int class_implements_interface (moo_t* moo, moo_oop_class_t _class, moo_o 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; + if (moo_walkdic(moo, ifce->mthdic[MOO_METHOD_INSTANCE], ciim_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; + if (moo_walkdic(moo, ifce->mthdic[MOO_METHOD_CLASS], ciim_on_each_method, &ciim) <= -1) return 0; return 1; } @@ -7975,7 +8005,7 @@ static int __compile_class_definition (moo_t* moo, int class_type) ass = moo_lookupdic(moo, (moo_oop_dic_t)cc->ns_oop, &cc->name); if (ass && MOO_CLASSOF(moo, ass->value) == moo->_class && - MOO_OBJ_GET_FLAGS_KERNEL(ass->value) != 1) + MOO_OBJ_GET_FLAGS_KERNEL(ass->value) != MOO_OBJ_FLAGS_KERNEL_IMMATURE) { /* the value must be a class object. * and it must be either a user-defined(0) or completed kernel built-in(2). @@ -7999,7 +8029,8 @@ static int __compile_class_definition (moo_t* moo, int class_type) ass = moo_lookupdic(moo, (moo_oop_dic_t)cc->ns_oop, &cc->name); if (ass) { - if (MOO_CLASSOF(moo, ass->value) != moo->_class || MOO_OBJ_GET_FLAGS_KERNEL(ass->value) > 1) + if (MOO_CLASSOF(moo, ass->value) != moo->_class || + MOO_OBJ_GET_FLAGS_KERNEL(ass->value) == MOO_OBJ_FLAGS_KERNEL_MATURE) { /* the object found with the name is not a class object * or the the class object found is a fully defined kernel @@ -8030,6 +8061,7 @@ static int __compile_class_definition (moo_t* moo, int class_type) } } + cc->in_class_body = 1; if (TOKEN_TYPE(moo) != MOO_IOTOK_LBRACE) { moo_setsynerr (moo, MOO_SYNERR_LBRACE, TOKEN_LOC(moo), TOKEN_NAME(moo)); diff --git a/moo/lib/err.c b/moo/lib/err.c index fe744eb..630a724 100644 --- a/moo/lib/err.c +++ b/moo/lib/err.c @@ -107,49 +107,50 @@ static moo_ooch_t synerrstr_27[] = {'p','r','i','m','i','t','i','v','e',':',' ', static moo_ooch_t synerrstr_28[] = {'w','r','o','n','g',' ','d','i','r','e','c','t','i','v','e','\0'}; static moo_ooch_t synerrstr_29[] = {'w','r','o','n','g',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_30[] = {'d','u','p','l','i','c','a','t','e',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_31[] = {'u','n','d','e','f','i','n','e','d',' ','n','a','a','e','\0'}; +static moo_ooch_t synerrstr_31[] = {'u','n','d','e','f','i','n','e','d',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_32[] = {'c','o','n','t','r','a','d','i','c','t','o','r','y',' ','c','l','a','s','s',' ','d','e','f','i','n','i','t','i','o','n','\0'}; -static moo_ooch_t synerrstr_33[] = {'i','n','v','a','l','i','d',' ','n','o','n','-','p','o','i','n','t','e','r',' ','i','n','s','t','a','n','c','e',' ','s','i','z','e','\0'}; -static moo_ooch_t synerrstr_34[] = {'p','r','o','h','i','b','i','t','e','d',' ','i','n','h','e','r','i','t','a','n','c','e','\0'}; -static moo_ooch_t synerrstr_35[] = {'v','a','r','i','a','b','l','e',' ','d','e','c','l','a','r','a','t','i','o','n',' ','n','o','t',' ','a','l','l','o','w','e','d','\0'}; -static moo_ooch_t synerrstr_36[] = {'m','o','d','i','f','i','e','r',' ','e','x','p','e','c','t','e','d','\0'}; -static moo_ooch_t synerrstr_37[] = {'w','r','o','n','g',' ','m','o','d','i','f','i','e','r','\0'}; -static moo_ooch_t synerrstr_38[] = {'d','i','s','a','l','l','o','w','e','d',' ','m','o','d','i','f','i','e','r','\0'}; -static moo_ooch_t synerrstr_39[] = {'d','u','p','l','i','c','a','t','e',' ','m','o','d','i','f','i','e','r','\0'}; -static moo_ooch_t synerrstr_40[] = {'m','e','t','h','o','d',' ','n','a','m','e',' ','e','x','p','e','c','t','e','d','\0'}; -static moo_ooch_t synerrstr_41[] = {'d','u','p','l','i','c','a','t','e',' ','m','e','t','h','o','d',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_42[] = {'i','n','v','a','l','i','d',' ','v','a','r','i','a','d','i','c',' ','m','e','t','h','o','d',' ','d','e','f','i','n','i','t','i','o','n','\0'}; -static moo_ooch_t synerrstr_43[] = {'v','a','r','i','a','b','l','e',' ','n','a','m','e',' ','e','x','p','e','c','t','e','d','\0'}; -static moo_ooch_t synerrstr_44[] = {'d','u','p','l','i','c','a','t','e',' ','a','r','g','u','m','e','n','t',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_45[] = {'d','u','p','l','i','c','a','t','e',' ','t','e','m','p','o','r','a','r','y',' ','v','a','r','i','a','b','l','e',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_46[] = {'d','u','p','l','i','c','a','t','e',' ','v','a','r','i','a','b','l','e',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_47[] = {'d','u','p','l','i','c','a','t','e',' ','b','l','o','c','k',' ','a','r','g','u','m','e','n','t',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_48[] = {'u','n','d','e','c','l','a','r','e','d',' ','v','a','r','i','a','b','l','e','\0'}; -static moo_ooch_t synerrstr_49[] = {'u','n','u','s','a','b','l','e',' ','v','a','r','i','a','b','l','e',' ','i','n',' ','c','o','m','p','i','l','e','d',' ','c','o','d','e','\0'}; -static moo_ooch_t synerrstr_50[] = {'i','n','a','c','c','e','s','s','i','b','l','e',' ','v','a','r','i','a','b','l','e','\0'}; -static moo_ooch_t synerrstr_51[] = {'a','m','b','i','g','u','o','u','s',' ','v','a','r','i','a','b','l','e','\0'}; -static moo_ooch_t synerrstr_52[] = {'t','o','o',' ','m','a','n','y',' ','i','n','s','t','a','n','c','e','/','c','l','a','s','s',' ','v','a','r','i','a','b','l','e','s','\0'}; -static moo_ooch_t synerrstr_53[] = {'i','n','a','c','c','e','s','s','i','b','l','e',' ','s','e','l','f','\0'}; -static moo_ooch_t synerrstr_54[] = {'w','r','o','n','g',' ','e','x','p','r','e','s','s','i','o','n',' ','p','r','i','m','a','r','y','\0'}; -static moo_ooch_t synerrstr_55[] = {'t','o','o',' ','m','a','n','y',' ','t','e','m','p','o','r','a','r','i','e','s','\0'}; -static moo_ooch_t synerrstr_56[] = {'t','o','o',' ','m','a','n','y',' ','a','r','g','u','m','e','n','t','s','\0'}; -static moo_ooch_t synerrstr_57[] = {'t','o','o',' ','m','a','n','y',' ','b','l','o','c','k',' ','t','e','m','p','o','r','a','r','i','e','s','\0'}; -static moo_ooch_t synerrstr_58[] = {'t','o','o',' ','m','a','n','y',' ','b','l','o','c','k',' ','a','r','g','u','m','e','n','t','s','\0'}; -static moo_ooch_t synerrstr_59[] = {'t','o','o',' ','l','a','r','g','e',' ','b','l','o','c','k','\0'}; -static moo_ooch_t synerrstr_60[] = {'t','o','o',' ','l','a','r','g','e',' ','a','r','r','a','y',' ','e','x','p','r','e','s','s','i','o','n','\0'}; -static moo_ooch_t synerrstr_61[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','n','u','m','b','e','r','\0'}; -static moo_ooch_t synerrstr_62[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','i','d','e','n','t','i','f','i','e','r','\0'}; -static moo_ooch_t synerrstr_63[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','a','r','g','u','m','e','n','t',' ','d','e','f','i','n','i','t','i','o','n','\0'}; -static moo_ooch_t synerrstr_64[] = {'f','a','i','l','e','d',' ','t','o',' ','i','m','p','o','r','t',' ','m','o','d','u','l','e','\0'}; -static moo_ooch_t synerrstr_65[] = {'#','i','n','c','l','u','d','e',' ','e','r','r','o','r','\0'}; -static moo_ooch_t synerrstr_66[] = {'w','r','o','n','g',' ','p','r','a','g','m','a',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_67[] = {'w','r','o','n','g',' ','n','a','m','e','s','p','a','c','e',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_68[] = {'w','r','o','n','g',' ','p','o','o','l','d','i','c','i','m','p','o','r','t',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_69[] = {'d','u','p','l','i','c','a','t','e',' ','p','o','o','l','d','i','c','i','m','p','o','r','t',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_70[] = {'l','i','t','e','r','a','l',' ','e','x','p','e','c','t','e','d','\0'}; -static moo_ooch_t synerrstr_71[] = {'b','r','e','a','k',' ','o','r',' ','c','o','n','t','i','n','u','e',' ','n','o','t',' ','w','i','t','h','i','n',' ','a',' ','l','o','o','p','\0'}; -static moo_ooch_t synerrstr_72[] = {'b','r','e','a','k',' ','o','r',' ','c','o','n','t','i','n','u','e',' ','w','i','t','h','i','n',' ','a',' ','b','l','o','c','k','\0'}; -static moo_ooch_t synerrstr_73[] = {'w','h','i','l','e',' ','e','x','p','e','c','t','e','d','\0'}; +static moo_ooch_t synerrstr_33[] = {'c','l','a','s','s',' ','n','o','t',' ','c','o','n','f','o','r','m','i','n','g',' ','t','o',' ','i','n','t','e','r','f','a','c','e','\0'}; +static moo_ooch_t synerrstr_34[] = {'i','n','v','a','l','i','d',' ','n','o','n','-','p','o','i','n','t','e','r',' ','i','n','s','t','a','n','c','e',' ','s','i','z','e','\0'}; +static moo_ooch_t synerrstr_35[] = {'p','r','o','h','i','b','i','t','e','d',' ','i','n','h','e','r','i','t','a','n','c','e','\0'}; +static moo_ooch_t synerrstr_36[] = {'v','a','r','i','a','b','l','e',' ','d','e','c','l','a','r','a','t','i','o','n',' ','n','o','t',' ','a','l','l','o','w','e','d','\0'}; +static moo_ooch_t synerrstr_37[] = {'m','o','d','i','f','i','e','r',' ','e','x','p','e','c','t','e','d','\0'}; +static moo_ooch_t synerrstr_38[] = {'w','r','o','n','g',' ','m','o','d','i','f','i','e','r','\0'}; +static moo_ooch_t synerrstr_39[] = {'d','i','s','a','l','l','o','w','e','d',' ','m','o','d','i','f','i','e','r','\0'}; +static moo_ooch_t synerrstr_40[] = {'d','u','p','l','i','c','a','t','e',' ','m','o','d','i','f','i','e','r','\0'}; +static moo_ooch_t synerrstr_41[] = {'m','e','t','h','o','d',' ','n','a','m','e',' ','e','x','p','e','c','t','e','d','\0'}; +static moo_ooch_t synerrstr_42[] = {'d','u','p','l','i','c','a','t','e',' ','m','e','t','h','o','d',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_43[] = {'i','n','v','a','l','i','d',' ','v','a','r','i','a','d','i','c',' ','m','e','t','h','o','d',' ','d','e','f','i','n','i','t','i','o','n','\0'}; +static moo_ooch_t synerrstr_44[] = {'v','a','r','i','a','b','l','e',' ','n','a','m','e',' ','e','x','p','e','c','t','e','d','\0'}; +static moo_ooch_t synerrstr_45[] = {'d','u','p','l','i','c','a','t','e',' ','a','r','g','u','m','e','n','t',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_46[] = {'d','u','p','l','i','c','a','t','e',' ','t','e','m','p','o','r','a','r','y',' ','v','a','r','i','a','b','l','e',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_47[] = {'d','u','p','l','i','c','a','t','e',' ','v','a','r','i','a','b','l','e',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_48[] = {'d','u','p','l','i','c','a','t','e',' ','b','l','o','c','k',' ','a','r','g','u','m','e','n','t',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_49[] = {'u','n','d','e','c','l','a','r','e','d',' ','v','a','r','i','a','b','l','e','\0'}; +static moo_ooch_t synerrstr_50[] = {'u','n','u','s','a','b','l','e',' ','v','a','r','i','a','b','l','e',' ','i','n',' ','c','o','m','p','i','l','e','d',' ','c','o','d','e','\0'}; +static moo_ooch_t synerrstr_51[] = {'i','n','a','c','c','e','s','s','i','b','l','e',' ','v','a','r','i','a','b','l','e','\0'}; +static moo_ooch_t synerrstr_52[] = {'a','m','b','i','g','u','o','u','s',' ','v','a','r','i','a','b','l','e','\0'}; +static moo_ooch_t synerrstr_53[] = {'t','o','o',' ','m','a','n','y',' ','i','n','s','t','a','n','c','e','/','c','l','a','s','s',' ','v','a','r','i','a','b','l','e','s','\0'}; +static moo_ooch_t synerrstr_54[] = {'i','n','a','c','c','e','s','s','i','b','l','e',' ','s','e','l','f','\0'}; +static moo_ooch_t synerrstr_55[] = {'w','r','o','n','g',' ','e','x','p','r','e','s','s','i','o','n',' ','p','r','i','m','a','r','y','\0'}; +static moo_ooch_t synerrstr_56[] = {'t','o','o',' ','m','a','n','y',' ','t','e','m','p','o','r','a','r','i','e','s','\0'}; +static moo_ooch_t synerrstr_57[] = {'t','o','o',' ','m','a','n','y',' ','a','r','g','u','m','e','n','t','s','\0'}; +static moo_ooch_t synerrstr_58[] = {'t','o','o',' ','m','a','n','y',' ','b','l','o','c','k',' ','t','e','m','p','o','r','a','r','i','e','s','\0'}; +static moo_ooch_t synerrstr_59[] = {'t','o','o',' ','m','a','n','y',' ','b','l','o','c','k',' ','a','r','g','u','m','e','n','t','s','\0'}; +static moo_ooch_t synerrstr_60[] = {'t','o','o',' ','l','a','r','g','e',' ','b','l','o','c','k','\0'}; +static moo_ooch_t synerrstr_61[] = {'t','o','o',' ','l','a','r','g','e',' ','a','r','r','a','y',' ','e','x','p','r','e','s','s','i','o','n','\0'}; +static moo_ooch_t synerrstr_62[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','n','u','m','b','e','r','\0'}; +static moo_ooch_t synerrstr_63[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','i','d','e','n','t','i','f','i','e','r','\0'}; +static moo_ooch_t synerrstr_64[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','a','r','g','u','m','e','n','t',' ','d','e','f','i','n','i','t','i','o','n','\0'}; +static moo_ooch_t synerrstr_65[] = {'f','a','i','l','e','d',' ','t','o',' ','i','m','p','o','r','t',' ','m','o','d','u','l','e','\0'}; +static moo_ooch_t synerrstr_66[] = {'#','i','n','c','l','u','d','e',' ','e','r','r','o','r','\0'}; +static moo_ooch_t synerrstr_67[] = {'w','r','o','n','g',' ','p','r','a','g','m','a',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_68[] = {'w','r','o','n','g',' ','n','a','m','e','s','p','a','c','e',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_69[] = {'w','r','o','n','g',' ','p','o','o','l','d','i','c','i','m','p','o','r','t',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_70[] = {'d','u','p','l','i','c','a','t','e',' ','p','o','o','l','d','i','c','i','m','p','o','r','t',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_71[] = {'l','i','t','e','r','a','l',' ','e','x','p','e','c','t','e','d','\0'}; +static moo_ooch_t synerrstr_72[] = {'b','r','e','a','k',' ','o','r',' ','c','o','n','t','i','n','u','e',' ','n','o','t',' ','w','i','t','h','i','n',' ','a',' ','l','o','o','p','\0'}; +static moo_ooch_t synerrstr_73[] = {'b','r','e','a','k',' ','o','r',' ','c','o','n','t','i','n','u','e',' ','w','i','t','h','i','n',' ','a',' ','b','l','o','c','k','\0'}; +static moo_ooch_t synerrstr_74[] = {'w','h','i','l','e',' ','e','x','p','e','c','t','e','d','\0'}; static moo_ooch_t* synerrstr[] = { synerrstr_0, synerrstr_1, synerrstr_2, synerrstr_3, synerrstr_4, synerrstr_5, synerrstr_6, synerrstr_7, @@ -161,7 +162,7 @@ static moo_ooch_t* synerrstr[] = synerrstr_48, synerrstr_49, synerrstr_50, synerrstr_51, synerrstr_52, synerrstr_53, synerrstr_54, synerrstr_55, synerrstr_56, synerrstr_57, synerrstr_58, synerrstr_59, synerrstr_60, synerrstr_61, synerrstr_62, synerrstr_63, synerrstr_64, synerrstr_65, synerrstr_66, synerrstr_67, synerrstr_68, synerrstr_69, synerrstr_70, synerrstr_71, - synerrstr_72, synerrstr_73 + synerrstr_72, synerrstr_73, synerrstr_74 }; #endif /* END: GENERATED WITH generr.moo */ diff --git a/moo/lib/exec.c b/moo/lib/exec.c index d2fa5dd..12f4955 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -1620,82 +1620,107 @@ static MOO_INLINE int activate_new_method (moo_t* moo, moo_oop_method_t mth, moo return 0; } +MOO_INLINE moo_oop_method_t find_method_in_class (moo_t* moo, moo_oop_class_t _class, int mth_type, const moo_oocs_t* name) +{ + moo_oop_association_t ass; + moo_oop_dic_t mthdic; + + mthdic = _class->mthdic[mth_type]; + + /* if a kernel class is not defined in the bootstrapping code, + * the method dictionary is still nil. you must define all the initial + * kernel classes properly before you can use this function */ + MOO_ASSERT (moo, (moo_oop_t)mthdic != moo->_nil); + MOO_ASSERT (moo, MOO_CLASSOF(moo, mthdic) == moo->_method_dictionary); + + ass = (moo_oop_association_t)moo_lookupdic(moo, mthdic, name); + if (ass) + { + /* found the method */ + MOO_ASSERT (moo, MOO_CLASSOF(moo, ass->value) == moo->_method); + return (moo_oop_method_t)ass->value; + } + + /* NOTE: moo_seterrXXX() is not called here */ + return MOO_NULL; +} + +MOO_INLINE moo_oop_method_t find_method_in_class_chain (moo_t* moo, moo_oop_class_t _class, int mth_type, const moo_oocs_t* name) +{ + moo_oop_method_t mth; + + do + { + mth = find_method_in_class(moo, _class, mth_type, name); + if (mth) return mth; + _class = (moo_oop_class_t)_class->superclass; + } + while ((moo_oop_t)_class != moo->_nil); + + /* NOTE: moo_seterrXXX() is not called here */ + return MOO_NULL; +} + +moo_oop_method_t moo_findmethodinclass (moo_t* moo, moo_oop_class_t _class, int mth_type, const moo_oocs_t* name) +{ + moo_oop_method_t mth; + mth = find_method_in_class(moo, _class, mth_type, name); + if (!mth) moo_seterrnum (moo, MOO_ENOENT); + return mth; +} + +moo_oop_method_t moo_findmethodinclasschain (moo_t* moo, moo_oop_class_t _class, int mth_type, const moo_oocs_t* name) +{ + moo_oop_method_t mth; + mth = find_method_in_class_chain(moo, _class, mth_type, name); + if (!mth) moo_seterrnum (moo, MOO_ENOENT); + return mth; +} + moo_oop_method_t moo_findmethod (moo_t* moo, moo_oop_t receiver, const moo_oocs_t* message, int super) { - moo_oop_class_t cls; - moo_oop_association_t ass; - moo_oop_t c; - moo_oop_dic_t mthdic; - int dic_no; -/* TODO: implement method lookup cache */ + moo_oop_class_t _class; + moo_oop_class_t c; + int mth_type; + moo_oop_method_t mth; - cls = MOO_CLASSOF(moo, receiver); - if (cls == moo->_class) + _class = MOO_CLASSOF(moo, receiver); + if (_class == moo->_class) { /* receiver is a class object (an instance of Class) */ - c = receiver; - dic_no = MOO_METHOD_CLASS; + c = (moo_oop_class_t)receiver; + mth_type = MOO_METHOD_CLASS; } else { /* receiver is not a class object. so take its class */ - c = (moo_oop_t)cls; - dic_no = MOO_METHOD_INSTANCE; + c = _class; + mth_type = MOO_METHOD_INSTANCE; } - - MOO_ASSERT (moo, c != moo->_nil); + MOO_ASSERT (moo, (moo_oop_t)c != moo->_nil); if (super) { - /* - moo_oop_method_t m; - MOO_ASSERT (moo, MOO_CLASSOF(moo, moo->active_context->origin) == moo->_method_context); - m = (moo_oop_method_t)moo->active_context->origin->method_or_nargs; - c = ((moo_oop_class_t)m->owner)->superclass; - */ MOO_ASSERT (moo, moo->active_method); MOO_ASSERT (moo, moo->active_method->owner); - c = ((moo_oop_class_t)moo->active_method->owner)->superclass; - if (c == moo->_nil) goto not_found; /* reached the top of the hierarchy */ + c = (moo_oop_class_t)((moo_oop_class_t)moo->active_method->owner)->superclass; + if ((moo_oop_t)c == moo->_nil) goto not_found; + // c is nil if it reached the top of the hierarch. + // otherwise c points to a class object } - do - { - mthdic = ((moo_oop_class_t)c)->mthdic[dic_no]; - /* if a kernel class is not defined in the bootstrapping code, - * the method dictionary is still nil. the initial kernel classes - * must all be defined properly */ - MOO_ASSERT (moo, (moo_oop_t)mthdic != moo->_nil); - - MOO_ASSERT (moo, MOO_CLASSOF(moo, mthdic) == moo->_method_dictionary); - - ass = (moo_oop_association_t)moo_lookupdic (moo, mthdic, message); - if (ass) - { - /* found the method */ - MOO_ASSERT (moo, MOO_CLASSOF(moo, ass->value) == moo->_method); - return (moo_oop_method_t)ass->value; - } - c = ((moo_oop_class_t)c)->superclass; - } - while (c != moo->_nil); + /* [IMPORT] the method lookup logic should be the same as ciim_on_each_method() in comp.c */ + mth = find_method_in_class_chain(moo, c, mth_type, message); + if (mth) return mth; not_found: - if (cls == moo->_class) + if (_class == moo->_class) { /* the object is an instance of Class. find the method * in an instance method dictionary of Class also */ - mthdic = ((moo_oop_class_t)cls)->mthdic[MOO_METHOD_INSTANCE]; - MOO_ASSERT (moo, (moo_oop_t)mthdic != moo->_nil); - MOO_ASSERT (moo, MOO_CLASSOF(moo, mthdic) == moo->_method_dictionary); - - ass = (moo_oop_association_t)moo_lookupdic (moo, mthdic, message); - if (ass) - { - MOO_ASSERT (moo, MOO_CLASSOF(moo, ass->value) == moo->_method); - return (moo_oop_method_t)ass->value; - } + mth = find_method_in_class(moo, _class, MOO_METHOD_INSTANCE, message); + if (mth) return mth; } MOO_LOG3 (moo, MOO_LOG_DEBUG, "Method '%.*js' not found in %O\n", message->len, message->ptr, receiver); @@ -1727,14 +1752,14 @@ static int start_initial_process_and_context (moo_t* moo, const moo_oocs_t* objn #if defined(INVOKE_DIRECTLY) - ass = moo_lookupsysdic (moo, objname); + ass = moo_lookupsysdic(moo, objname); if (!ass || MOO_CLASSOF(moo, ass->value) != moo->_class) { MOO_LOG2 (moo, MOO_LOG_DEBUG, "Cannot find a class '%.*js'", objname->len, objname->ptr); return -1; } - mth = moo_findmethod (moo, ass->value, mthname, 0); + mth = moo_findmethod(moo, ass->value, mthname, 0); if (!mth) { MOO_LOG4 (moo, MOO_LOG_DEBUG, "Cannot find a method %.*js>>%.*js", objname->len, objname->ptr, mthname->len, mthname->ptr); @@ -1758,7 +1783,7 @@ TODO: overcome this problem - accept parameters.... startup.ptr = str_startup; startup.len = 7; - mth = moo_findmethod (moo, (moo_oop_t)moo->_system, &startup, 0); + mth = moo_findmethod(moo, (moo_oop_t)moo->_system, &startup, 0); if (!mth) { MOO_LOG0 (moo, MOO_LOG_DEBUG, "Cannot find the startup method in the system class"); @@ -4016,7 +4041,7 @@ static int send_message (moo_t* moo, moo_oop_char_t selector, int to_super, moo_ mthname.ptr = fbm; mthname.len = 18; - method = moo_findmethod (moo, receiver, &mthname, 0); + method = moo_findmethod(moo, receiver, &mthname, 0); if (!method) { /* this must not happen as long as doesNotUnderstand: is implemented under Apex. @@ -4053,7 +4078,7 @@ static int send_message_with_str (moo_t* moo, const moo_ooch_t* nameptr, moo_oow mthname.ptr = (moo_ooch_t*)nameptr; mthname.len = namelen; - method = moo_findmethod (moo, receiver, &mthname, to_super); + method = moo_findmethod(moo, receiver, &mthname, to_super); if (!method) { MOO_LOG4 (moo, MOO_LOG_IC | MOO_LOG_FATAL, diff --git a/moo/lib/gc.c b/moo/lib/gc.c index 88a1415..5934acd 100644 --- a/moo/lib/gc.c +++ b/moo/lib/gc.c @@ -409,7 +409,7 @@ static moo_oop_class_t alloc_kernel_class (moo_t* moo, int class_flags, moo_oow_ c = (moo_oop_class_t)moo_allocoopobj (moo, MOO_CLASS_NAMED_INSTVARS + num_classvars); if (!c) return MOO_NULL; - MOO_OBJ_SET_FLAGS_KERNEL (c, 1); + MOO_OBJ_SET_FLAGS_KERNEL (c, MOO_OBJ_FLAGS_KERNEL_IMMATURE); MOO_OBJ_SET_CLASS (c, (moo_oop_t)moo->_class); c->spec = MOO_SMOOI_TO_OOP(spec); c->selfspec = MOO_SMOOI_TO_OOP(MOO_CLASS_SELFSPEC_MAKE(num_classvars, 0, class_flags)); diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 0a00ade..177a053 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -607,6 +607,7 @@ struct moo_cunit_class_t moo_ioloc_t modname_loc; moo_oopbuf_t ifces; + int in_class_body; /* set to non-zero after '{' has been encountered */ /* instance variable, class variable, class instance variable, constant * var[0] - named instance variables @@ -1426,6 +1427,20 @@ moo_oop_method_t moo_findmethod ( int super ); +moo_oop_method_t moo_findmethodinclass ( + moo_t* moo, + moo_oop_class_t _class, + int mth_type, + const moo_oocs_t* name +); + +moo_oop_method_t moo_findmethodinclasschain ( + moo_t* moo, + moo_oop_class_t _class, + int mth_type, + const moo_oocs_t* name +); + /* ========================================================================= */ /* moo.c */ /* ========================================================================= */ diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 12bdeb6..71003b4 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -446,6 +446,10 @@ typedef enum moo_gcfin_t moo_gcfin_t; (((moo_oow_t)(r)) << MOO_OBJ_FLAGS_TRAILER_SHIFT) \ ) +#define MOO_OBJ_FLAGS_KERNEL_USER 0 +#define MOO_OBJ_FLAGS_KERNEL_IMMATURE 1 +#define MOO_OBJ_FLAGS_KERNEL_MATURE 2 + #define MOO_OBJ_HEADER \ moo_oow_t _flags; \ moo_oow_t _size; \ @@ -1684,6 +1688,7 @@ enum moo_synerrnum_t MOO_SYNERR_NAMEDUPL, /* duplicate name */ MOO_SYNERR_NAMEUNDEF, /* undefined name */ MOO_SYNERR_CLASSCONTRA, /* contradictory class */ + MOO_SYNERR_CLASSNCIFCE, /* class not conforming to interface */ MOO_SYNERR_NPINSTSIZEINVAL, /* invalid non-pointer instance size */ MOO_SYNERR_INHERITBANNED, /* prohibited inheritance */ MOO_SYNERR_VARDCLBANNED, /* variable declaration not allowed */ diff --git a/moo/lib/pf-basic.c b/moo/lib/pf-basic.c index 5b8b8d3..8b78b69 100644 --- a/moo/lib/pf-basic.c +++ b/moo/lib/pf-basic.c @@ -795,7 +795,7 @@ moo_pfrc_t moo_pf_responds_to (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) mthname.ptr = MOO_OBJ_GET_CHAR_SLOT(selector); mthname.len = MOO_OBJ_GET_SIZE(selector); - if (moo_findmethod (moo, rcv, &mthname, 0)) + if (moo_findmethod(moo, rcv, &mthname, 0)) { MOO_STACK_SETRET (moo, nargs, moo->_true); }