From 9ad9299dea59b165436360d1917f7062bfd8a13a Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Mon, 8 Oct 2018 06:51:31 +0000 Subject: [PATCH] allowed class and class extension nesting inside a class --- moo/kernel/Apex.moo | 22 +++++++++++++++-- moo/kernel/Socket.moo | 26 ++++++++++---------- moo/kernel/System.moo | 31 +++++++++++------------- moo/kernel/X11.moo | 55 +++++++++++++++++++++++++------------------ moo/lib/comp.c | 50 ++++++++++++++++++++++++++++++++++----- moo/lib/err.c | 28 ++++++++++++++++++++-- moo/lib/moo-prv.h | 1 + moo/lib/moo-utl.h | 20 ++++++++++++++-- moo/lib/moo.c | 8 +++---- moo/lib/moo.h | 8 +++++++ moo/lib/utl.c | 17 +++++++++---- 11 files changed, 193 insertions(+), 73 deletions(-) diff --git a/moo/kernel/Apex.moo b/moo/kernel/Apex.moo index ee0fb5a..f5476f9 100644 --- a/moo/kernel/Apex.moo +++ b/moo/kernel/Apex.moo @@ -4,8 +4,26 @@ class Apex(nil) class(#limited) Error(Apex) { + pooldic Code + { + ENOERR := #\E0. + EGENERIC := #\E1. + ENOIMPL := #\E2. + ESYSERR := #\E3. + EINTERN := #\E4. + ESYSMEM := #\E5. + EOOMEM := #\E6. + EINVAL := #\E7. + ENOENT := #\E8. + EPERM := #\E12. + ERANGE := #\E20. + + ELIMIT := #\E9999. + ## add more items... + } } +(* pooldic Error.Code { ENOERR := #\E0. @@ -21,8 +39,8 @@ pooldic Error.Code ERANGE := #\E20. ELIMIT := #\E9999. -(* add more items... *) -} +## add more items... +} *) (*pooldic Error.Code2 { diff --git a/moo/kernel/Socket.moo b/moo/kernel/Socket.moo index 5d9fc5d..8d18d8e 100644 --- a/moo/kernel/Socket.moo +++ b/moo/kernel/Socket.moo @@ -231,6 +231,19 @@ class Socket(Object) from 'sck' ## the internal representation used by various modules. (e.g. sck) var(#get) handle := -1. + ## TODO: generate these family and type from the C header + pooldic Family + { + INET := 2. + INET6 := 10. + } + + pooldic Type + { + STREAM := 1. + DGRAM := 2. + } + method(#primitive) open(family, type, proto). ## map the open primitive again with a different name for strict internal use only. ## this method is supposed to be used to handle an accepted socket in server sockets. @@ -284,19 +297,6 @@ class Socket(Object) from 'sck' } } -(* TODO: generate these family and type from the C header *) -pooldic Socket.Family -{ - INET := 2. - INET6 := 10. -} - -pooldic Socket.Type -{ - STREAM := 1. - DGRAM := 2. -} - class SyncSocket(Socket) { var iosem, tmoutsem, sg. diff --git a/moo/kernel/System.moo b/moo/kernel/System.moo index dd85da5..52008c4 100644 --- a/moo/kernel/System.moo +++ b/moo/kernel/System.moo @@ -12,6 +12,20 @@ class System(Apex) { var(#class) asyncsg. + pooldic Log + { + ## ----------------------------------------------------------- + ## defines log levels + ## these items must follow defintions in moo.h + ## ----------------------------------------------------------- + + DEBUG := 1. + INFO := 2. + WARN := 4. + ERROR := 8. + FATAL := 16. + } + method(#class) addAsyncSemaphore: sem { ^self.asyncsg addSemaphore: sem @@ -124,24 +138,7 @@ class System(Apex) s signalAfterSecs: secs nanosecs: nanosecs. s wait. } -} -pooldic System.Log -{ - ## ----------------------------------------------------------- - ## defines log levels - ## these items must follow defintions in moo.h - ## ----------------------------------------------------------- - - DEBUG := 1. - INFO := 2. - WARN := 4. - ERROR := 8. - FATAL := 16. -} - -extend System -{ ## the following methods may not look suitable to be placed ## inside a system dictionary. but they are here for quick and dirty ## output production from the moo code. diff --git a/moo/kernel/X11.moo b/moo/kernel/X11.moo index 99bdba3..ce78ce1 100644 --- a/moo/kernel/X11.moo +++ b/moo/kernel/X11.moo @@ -15,6 +15,38 @@ class X11(Object) from 'x11' var event_loop_sem, event_loop_proc. var llevent_blocks. + class Exception(System.Exception) + { + } + + class Point(Object) + { + var(#get,#set) x := 0, y := 0. + } + + class Dimension(Object) + { + var(#get,#set) width := 0, height := 0. + } + + class Rectangle(Object) + { + var(#get,#set) + x := 0, + y := 0, + width := 0, + height := 0. + } + + extend Point + { + method print + { + x dump. + y dump. + } + } + method(#primitive,#liberal) _open_display(name). method(#primitive) _close_display. method(#primitive) _get_fd. @@ -47,29 +79,6 @@ class X11(Object) from 'x11' } } -class X11.Exception(System.Exception) -{ -} - -class X11.Point(Object) -{ - var(#get,#set) x := 0, y := 0. -} - -class X11.Dimension(Object) -{ - var(#get,#set) width := 0, height := 0. -} - -class X11.Rectangle(Object) -{ - var(#get,#set) - x := 0, - y := 0, - width := 0, - height := 0. -} - ## --------------------------------------------------------------------------- ## Event ## --------------------------------------------------------------------------- diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 51cefe3..32293da 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -247,6 +247,7 @@ enum voca_id_t }; typedef enum voca_id_t voca_id_t; +static int compile_class_definition (moo_t* moo, int class_type); static int compile_pooldic_definition (moo_t* moo); static int compile_block_statement (moo_t* moo); static int compile_method_statement (moo_t* moo); @@ -7656,8 +7657,15 @@ static int __compile_class_definition (moo_t* moo, int class_type) return -1; } + 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 */ + moo_setsynerrbfmt (moo, MOO_SYNERR_IDENT, TOKEN_LOC(moo), TOKEN_NAME(moo), "undotted identifier expected"); + return -1; + } + #if 0 - if (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT && is_restricted_word (TOKEN_NAME(moo))) + 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)); @@ -7665,10 +7673,25 @@ static int __compile_class_definition (moo_t* moo, int class_type) } #endif - /* copy the class name */ + + /* [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_class_fqn(moo, cc, TOKEN_NAME(moo)) <= -1) return -1; cc->fqn_loc = moo->c->tok.loc; - if (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED) + + if (cc->cunit_parent && cc->cunit_parent->cunit_type == MOO_CUNIT_CLASS) + { + moo_cunit_class_t* c = (moo_cunit_class_t*)cc->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; + } + cc->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, (class_type == CLASS_TYPE_EXTEND? PDN_DONT_ADD_NS: 0), MOO_NULL, &cc->fqn, &cc->fqn_loc, &cc->name, &cc->ns_oop) <= -1) return -1; } @@ -7724,8 +7747,7 @@ static int __compile_class_definition (moo_t* moo, int class_type) cc->super_oop = cc->self_oop->superclass; - MOO_ASSERT (moo, cc->super_oop == moo->_nil || - MOO_CLASSOF(moo, cc->super_oop) == moo->_class); + MOO_ASSERT (moo, cc->super_oop == moo->_nil || MOO_CLASSOF(moo, cc->super_oop) == moo->_class); } else { @@ -8096,6 +8118,18 @@ static int __compile_class_definition (moo_t* moo, int class_type) GET_TOKEN (moo); if (compile_pooldic_definition(moo) <= -1) return -1; } + else if (is_token_word(moo, VOCA_CLASS)) + { + /* class definition nested inside another class definition */ + GET_TOKEN (moo); + if (compile_class_definition(moo, CLASS_TYPE_NORMAL) <= -1) return -1; + } + else if (is_token_word(moo, VOCA_EXTEND)) + { + /* class extension nested inside another class definition */ + GET_TOKEN (moo); + if (compile_class_definition(moo, CLASS_TYPE_EXTEND) <= -1) return -1; + } else break; } while (1); @@ -8263,10 +8297,14 @@ 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) { /* the pool dictionary nested inside a class cannot be multi-segmented */ - moo_setsynerr (moo, MOO_SYNERR_IDENT, TOKEN_LOC(moo), TOKEN_NAME(moo)); + moo_setsynerrbfmt (moo, MOO_SYNERR_IDENT, TOKEN_LOC(moo), TOKEN_NAME(moo), "undotted identifier expected"); goto oops; } + /* [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_pooldic_fqn(moo, pd, TOKEN_NAME(moo)) <= -1) goto oops; pd->fqn_loc = moo->c->tok.loc; diff --git a/moo/lib/err.c b/moo/lib/err.c index 21202c4..5e50c50 100644 --- a/moo/lib/err.c +++ b/moo/lib/err.c @@ -405,7 +405,19 @@ void moo_setsynerrbfmt (moo_t* moo, moo_synerrnum_t num, const moo_ioloc_t* loc, if (tgt) { - moo->c->synerr.tgt = *tgt; + if (tgt->len >= MOO_COUNTOF(moo->c->synerr_tgtbuf) && + moo_copyoocharstosbuf(moo, tgt->ptr, tgt->len, MOO_SBUF_ID_SYNERR) >= 0) + { + moo->c->synerr.tgt.ptr = moo->sbuf[MOO_SBUF_ID_SYNERR].ptr; + moo->c->synerr.tgt.len = moo->sbuf[MOO_SBUF_ID_SYNERR].len; + } + else + { + moo->c->synerr.tgt.ptr = moo->c->synerr_tgtbuf; + moo->c->synerr.tgt.len = (tgt->len < MOO_COUNTOF(moo->c->synerr_tgtbuf))? tgt->len: (MOO_COUNTOF(moo->c->synerr_tgtbuf) - 1); + moo->c->synerr.tgt.ptr[moo->c->synerr.tgt.len] = '\0'; + moo_copy_oochars (moo->c->synerr.tgt.ptr, tgt->ptr, moo->c->synerr.tgt.len); + } } else { @@ -456,7 +468,19 @@ void moo_setsynerrufmt (moo_t* moo, moo_synerrnum_t num, const moo_ioloc_t* loc, if (tgt) { - moo->c->synerr.tgt = *tgt; + if (tgt->len >= MOO_COUNTOF(moo->c->synerr_tgtbuf) && + moo_copyoocharstosbuf(moo, tgt->ptr, tgt->len, MOO_SBUF_ID_SYNERR) >= 0) + { + moo->c->synerr.tgt.ptr = moo->sbuf[MOO_SBUF_ID_SYNERR].ptr; + moo->c->synerr.tgt.len = moo->sbuf[MOO_SBUF_ID_SYNERR].len; + } + else + { + moo->c->synerr.tgt.ptr = moo->c->synerr_tgtbuf; + moo->c->synerr.tgt.len = (tgt->len < MOO_COUNTOF(moo->c->synerr_tgtbuf))? tgt->len: (MOO_COUNTOF(moo->c->synerr_tgtbuf) - 1); + moo->c->synerr.tgt.ptr[moo->c->synerr.tgt.len] = '\0'; + moo_copy_oochars (moo->c->synerr.tgt.ptr, tgt->ptr, moo->c->synerr.tgt.len); + } } else { diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 865155b..24beab1 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -666,6 +666,7 @@ struct moo_compiler_t /* syntax error information */ moo_synerr_t synerr; + moo_ooch_t synerr_tgtbuf[256]; /* temporary space used when dealing with an illegal character */ moo_ooch_t ilchr; diff --git a/moo/lib/moo-utl.h b/moo/lib/moo-utl.h index 997cfbb..edcf956 100644 --- a/moo/lib/moo-utl.h +++ b/moo/lib/moo-utl.h @@ -336,15 +336,31 @@ MOO_EXPORT moo_oow_t moo_count_bcstr ( MOO_EXPORT int moo_copyoocstrtosbuf ( moo_t* moo, const moo_ooch_t* str, - int id + int id ); MOO_EXPORT int moo_concatoocstrtosbuf ( moo_t* moo, const moo_ooch_t* str, - int id + int id ); + +MOO_EXPORT int moo_copyoocharstosbuf ( + moo_t* moo, + const moo_ooch_t* ptr, + moo_oow_t len, + int id +); + +MOO_EXPORT int moo_concatoocharstosbuf ( + moo_t* moo, + const moo_ooch_t* ptr, + moo_oow_t len, + int id +); + + #if defined(MOO_OOCH_IS_UCH) # define moo_conv_oocs_to_bcs_with_cmgr(oocs,oocslen,bcs,bcslen,cmgr) moo_conv_ucs_to_bcs_with_cmgr(oocs,oocslen,bcs,bcslen,cmgr) # define moo_conv_oochars_to_bchars_with_cmgr(oocs,oocslen,bcs,bcslen,cmgr) moo_conv_uchars_to_bchars_with_cmgr(oocs,oocslen,bcs,bcslen,cmgr) diff --git a/moo/lib/moo.c b/moo/lib/moo.c index 3148683..2ddaeb4 100644 --- a/moo/lib/moo.c +++ b/moo/lib/moo.c @@ -837,15 +837,15 @@ int moo_genpfmethod (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class, moo_met /* compose a full primitive function identifier to VM's string buffer. * pfid => mod->name + '.' + pfname */ - if (moo_copyoocstrtosbuf(moo, mod->name, 0) <= -1 || - moo_concatoocstrtosbuf(moo, dot, 0) <= -1 || - moo_concatoocstrtosbuf(moo, pfname, 0) <= -1) + if (moo_copyoocstrtosbuf(moo, mod->name, MOO_SBUF_TMP) <= -1 || + moo_concatoocstrtosbuf(moo, dot, MOO_SBUF_TMP) <= -1 || + moo_concatoocstrtosbuf(moo, pfname, MOO_SBUF_TMP) <= -1) { MOO_DEBUG2 (moo, "Cannot generate primitive function method [%js] in [%O] - VM memory shortage\n", mthname, _class->name); return -1; } - pfidsym = (moo_oop_char_t)moo_makesymbol (moo, moo->sbuf[0].ptr, moo->sbuf[0].len); + pfidsym = (moo_oop_char_t)moo_makesymbol(moo, moo->sbuf[MOO_SBUF_TMP].ptr, moo->sbuf[MOO_SBUF_TMP].len); if (!pfidsym) { MOO_DEBUG2 (moo, "Cannot generate primitive function method [%js] in [%O] - symbol instantiation failure\n", mthname, _class->name); diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 8032d0b..2404fa6 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -1327,6 +1327,14 @@ typedef struct moo_compiler_t moo_compiler_t; #define MOO_ERRMSG_CAPA (2048) +enum moo_sbuf_id_t +{ + MOO_SBUF_ID_TMP = 0, + MOO_SBUF_ID_SYNERR = 1 + /* more? */ +}; + + struct moo_t { moo_mmgr_t* mmgr; diff --git a/moo/lib/utl.c b/moo/lib/utl.c index 42e2fe1..de07132 100644 --- a/moo/lib/utl.c +++ b/moo/lib/utl.c @@ -352,12 +352,15 @@ moo_bch_t* moo_find_bchar_in_bcstr (const moo_bch_t* ptr, moo_bch_t c) /* ----------------------------------------------------------------------- */ int moo_concatoocstrtosbuf (moo_t* moo, const moo_ooch_t* str, int id) +{ + return moo_concatoocharstosbuf(moo, str, moo_count_oocstr(str), id); +} + +int moo_concatoocharstosbuf (moo_t* moo, const moo_ooch_t* ptr, moo_oow_t len, int id) { moo_sbuf_t* p; - moo_oow_t len; p = &moo->sbuf[id]; - len = moo_count_oocstr (str); if (len > p->capa - p->len) { @@ -374,7 +377,7 @@ int moo_concatoocstrtosbuf (moo_t* moo, const moo_ooch_t* str, int id) p->capa = newcapa; } - moo_copy_oochars (&p->ptr[p->len], str, len); + moo_copy_oochars (&p->ptr[p->len], ptr, len); p->len += len; p->ptr[p->len] = '\0'; @@ -384,7 +387,13 @@ int moo_concatoocstrtosbuf (moo_t* moo, const moo_ooch_t* str, int id) int moo_copyoocstrtosbuf (moo_t* moo, const moo_ooch_t* str, int id) { moo->sbuf[id].len = 0;; - return moo_concatoocstrtosbuf (moo, str, id); + return moo_concatoocstrtosbuf(moo, str, id); +} + +int moo_copyoocharstosbuf (moo_t* moo, const moo_ooch_t* ptr, moo_oow_t len, int id) +{ + moo->sbuf[id].len = 0;; + return moo_concatoocharstosbuf(moo, ptr, len, id); } /* ----------------------------------------------------------------------- */