diff --git a/moo/kernel/Apex.moo b/moo/kernel/Apex.moo index c7f5fa6..62b0030 100644 --- a/moo/kernel/Apex.moo +++ b/moo/kernel/Apex.moo @@ -328,13 +328,13 @@ class Apex(nil) ## ------------------------------------------------------- ## ------------------------------------------------------- - method(#class) perform() + method(#class,#variadic) perform() { self primitiveFailed } - method perform() + method(#variadic) perform() { self primitiveFailed @@ -540,85 +540,3 @@ extend Error } } -class System(Apex) -{ -} - -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. - ## System logNl: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'. - ## - method(#class) atLevel: level log: message - { - - ## do nothing upon logging failure - } - - method(#class) atLevel: level log: message and: message2 - { - - ## do nothing upon logging failure - } - - method(#class) atLevel: level log: message and: message2 and: message3 - { - - ## do nothing upon logging failure - } - - method(#class) atLevel: level logNl: message - { - ## the #_log primitive accepts an array. - ## so the following lines should work also. - ## | x | - ## x := Array new: 2. - ## x at: 0 put: message. - ## x at: 1 put: S'\n'. - ## ^self atLevel: level log: x. - - ^self atLevel: level log: message and: S'\n'. - } - - method(#class) atLevel: level logNl: message and: message2 - { - ^self atLevel: level log: message and: message2 and: S'\n'. - } - - method(#class) log: message - { - ^self atLevel: System.Log.INFO log: message. - } - - method(#class) log: message and: message2 - { - ^self atLevel: System.Log.INFO log: message and: message2. - } - - method(#class) logNl: message - { - ^self atLevel: System.Log.INFO logNl: message. - } - - method(#class) logNl: message and: message2 - { - ^self atLevel: System.Log.INFO logNl: message and: message2. - } -} - diff --git a/moo/kernel/Class.moo b/moo/kernel/Class.moo index b36bc61..6e4b20f 100644 --- a/moo/kernel/Class.moo +++ b/moo/kernel/Class.moo @@ -47,4 +47,9 @@ class(#pointer) Class(Apex) ]. ^false }*) + + method nsdic + { + ^self.nsdic + } } diff --git a/moo/kernel/Mill.moo b/moo/kernel/Mill.moo index bba6679..d39ed37 100644 --- a/moo/kernel/Mill.moo +++ b/moo/kernel/Mill.moo @@ -268,7 +268,11 @@ class MyObject(Object) method(#class) main { - |a i | + |a i| + + System _getUint8(1,2). + 'JJJJJJJJJJ' dump. + a := 100. ## PROBLEM: the following double loop will exhaust the stack @@ -318,16 +322,20 @@ class MyObject(Object) } }*) - System logNl: 'Sleeping start now....'. + + (* basicAt: 12 to access the nsdic field. use a proper method once it's defined in Class *) - (System basicAt: 12) keysAndValuesDo: [:k :v | + (System nsdic) keysAndValuesDo: [:k :v | k dump. v dump. '------------' dump. ]. - Processor sleepFor: 3. ## DEBUG VM... VM WAITING FOR 10 SECS instead of 3. + + (System at: #Processor) dump. + System logNl: 'Sleeping start now....'. + Processor sleepFor: 2. } (* diff --git a/moo/kernel/Moo.moo b/moo/kernel/Moo.moo index 8a921ba..eaf032e 100644 --- a/moo/kernel/Moo.moo +++ b/moo/kernel/Moo.moo @@ -2,6 +2,7 @@ #include 'Context.moo'. #include 'Except.moo'. #include 'Class.moo'. +#include 'System.moo'. #include 'Boolean.moo'. #include 'Magnitu.moo'. #include 'Collect.moo'. diff --git a/moo/kernel/Stdio.moo b/moo/kernel/Stdio.moo index 3cf652d..f42a93c 100644 --- a/moo/kernel/Stdio.moo +++ b/moo/kernel/Stdio.moo @@ -42,7 +42,7 @@ class Stdio(Object) from 'stdio' } *) - method format (fmt) + method(#variadic) format (fmt) { | a b c | 'THIS IS FORMAT' dump. diff --git a/moo/kernel/System.moo b/moo/kernel/System.moo new file mode 100644 index 0000000..9f5ba71 --- /dev/null +++ b/moo/kernel/System.moo @@ -0,0 +1,150 @@ +## TODO: consider if System can replace Apex itself. +## System, being the top class, seems to give very natural way of +## offering global system-level functions and interfaces. +## +## class System(nil) { ... } +## class Object(System) { .... } +## System at: # +## System logNl: 'xxxxx'. +## System getUint8(ptr,offset) + +class System(Apex) +{ +} + +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. + ## System logNl: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'. + ## + method(#class) atLevel: level log: message + { + + ## do nothing upon logging failure + } + + method(#class) atLevel: level log: message and: message2 + { + + ## do nothing upon logging failure + } + + method(#class) atLevel: level log: message and: message2 and: message3 + { + + ## do nothing upon logging failure + } + + method(#class) atLevel: level logNl: message + { + ## the #_log primitive accepts an array. + ## so the following lines should work also. + ## | x | + ## x := Array new: 2. + ## x at: 0 put: message. + ## x at: 1 put: S'\n'. + ## ^self atLevel: level log: x. + + ^self atLevel: level log: message and: S'\n'. + } + + method(#class) atLevel: level logNl: message and: message2 + { + ^self atLevel: level log: message and: message2 and: S'\n'. + } + + method(#class) log: message + { + ^self atLevel: System.Log.INFO log: message. + } + + method(#class) log: message and: message2 + { + ^self atLevel: System.Log.INFO log: message and: message2. + } + + method(#class) logNl: message + { + ^self atLevel: System.Log.INFO logNl: message. + } + + method(#class) logNl: message and: message2 + { + ^self atLevel: System.Log.INFO logNl: message and: message2. + } + + (* nsdic access *) + method(#class) at: key + { + ^self nsdic at: key + } + + method(#class) at: key put: value + { + ^self nsdic at: key put: value + } + + (* raw memory access *) + method(#class,#primitive) _getInt8 (rawptr, offset). ## + method(#class,#primitive) _getInt16 (rawptr, offset). + method(#class,#primitive) _getInt32 (rawptr, offset). + method(#class,#primitive) _getInt64 (rawptr, offset). + method(#class,#primitive) _getUint8 (rawptr, offset). ## + method(#class,#primitive) _getUint16 (rawptr, offset). + method(#class,#primitive) _getUint32 (rawptr, offset). + method(#class,#primitive) _getUint64 (rawptr, offset). + + (* + method(#class,#primitive) _putInt8 (rawptr, offset, value). + method(#class,#primitive) _putInt16 (rawptr, offset, value). + method(#class,#primitive) _putInt32 (rawptr, offset, value). + method(#class,#primitive) _putInt64 (rawptr, offset, value). + method(#class,#primitive) _putUint8 (rawptr, offset, value). + method(#class,#primitive) _putUint16 (rawptr, offset, value). + method(#class,#primitive) _putUint32 (rawptr, offset, value). + method(#class,#primitive) _putUint64 (rawptr, offset, value), + *) + + (* + method(#class) getUint8: rawptr at: offset + { + + } + + method(#class) getUint16: rawptr at: offset + { + + } + + method(#class) getUint32: rawptr at: offset + { + + } + + method(#class) getUint64: rawptr at: offset + { + + } + + method(#class) putUint8: value rawptr: rawptr at: offset + { + + }*) +} + diff --git a/moo/kernel/generr.moo b/moo/kernel/generr.moo index da81d6f..c3ceadc 100644 --- a/moo/kernel/generr.moo +++ b/moo/kernel/generr.moo @@ -81,6 +81,7 @@ class MyObject(Object) 'duplicate modifier' 'wrong method name' 'duplicate method name' + 'invalid variadic method definition' 'duplicate argument name' 'duplicate temporary variable name' 'duplicate variable name' diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 9bc57ee..7ddc7cc 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -116,6 +116,7 @@ static struct voca_t { 11, { 't','h','i','s','C','o','n','t','e','x','t' } }, { 11, { 't','h','i','s','P','r','o','c','e','s','s' } }, { 4, { 't','r','u','e' } }, + { 9, { '#','v','a','r','i','a','d','i','c' } }, { 5, { 'w','h','i','l','e' } }, { 5, { '#','w','o','r','d' } }, @@ -162,6 +163,7 @@ enum voca_id_t VOCA_THIS_CONTEXT, VOCA_THIS_PROCESS, VOCA_TRUE, + VOCA_VARIADIC_S, VOCA_WHILE, VOCA_WORD_S, @@ -3169,9 +3171,8 @@ static int compile_unary_method_name (moo_t* moo) while (1); } - /* indicate that the unary method name is followed by a parameter list */ - moo->c->mth.variadic = 1; GET_TOKEN (moo); + return 9999; /* to indicate the method definition is in a procedural style */ } return 0; @@ -3287,7 +3288,14 @@ static int compile_method_name (moo_t* moo) { set_syntax_error (moo, MOO_SYNERR_MTHNAMEDUPL, &moo->c->mth.name_loc, &moo->c->mth.name); return -1; - } + } + + /* compile_unary_method_name() returns 9999 if the name is followed by () */ + if (moo->c->mth.variadic && n != 9999) + { + set_syntax_error (moo, MOO_SYNERR_VARIADMTHINVAL, &moo->c->mth.name_loc, &moo->c->mth.name); + return -1; + } } MOO_ASSERT (moo, moo->c->mth.tmpr_nargs < MAX_CODE_NARGS); @@ -5799,22 +5807,29 @@ static int compile_method_definition (moo_t* moo) else if (is_token_symbol(moo, VOCA_PRIMITIVE_S)) { /* method(#primitive) */ - if (moo->c->cls.self_oop->modname == moo->_nil) - { - MOO_DEBUG2 (moo, "Disallowed #primitive method modifier in the class %.*js without 'from'\n", - MOO_OBJ_GET_SIZE(moo->c->cls.self_oop->name), - MOO_OBJ_GET_CHAR_SLOT(moo->c->cls.self_oop->name)); - set_syntax_error (moo, MOO_SYNERR_MODIFIERBANNED, TOKEN_LOC(moo), TOKEN_NAME(moo)); - return -1; - } - if (moo->c->mth.primitive) { + /* #primitive duplicate modifier */ set_syntax_error (moo, MOO_SYNERR_MODIFIERDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo)); return -1; } moo->c->mth.primitive = 1; + + GET_TOKEN (moo); + } + else if (is_token_symbol(moo, VOCA_VARIADIC_S)) + { + /* method(#variadic) */ + if (moo->c->mth.variadic) + { + /* #variadic duplicate modifier */ + set_syntax_error (moo, MOO_SYNERR_MODIFIERDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo)); + return -1; + } + + moo->c->mth.variadic = 1; + GET_TOKEN (moo); } else if (TOKEN_TYPE(moo) == MOO_IOTOK_COMMA || TOKEN_TYPE(moo) == MOO_IOTOK_EOF || TOKEN_TYPE(moo) == MOO_IOTOK_RPAREN) @@ -5853,9 +5868,6 @@ static int compile_method_definition (moo_t* moo) /* the primitive method must be of this form * method(#primitive) method_name. */ - moo_oow_t litidx, savedlen; - moo_oocs_t tmp; - if (TOKEN_TYPE(moo) != MOO_IOTOK_PERIOD) { /* . expected */ @@ -5863,32 +5875,73 @@ static int compile_method_definition (moo_t* moo) return -1; } + if (moo->c->cls.self_oop->modname == moo->_nil) + { + moo_oow_t savedlen; + moo_ooi_t pfnum; + + savedlen = moo->c->cls.modname.len; + + /* primitive identifer = classname_methodname + * let me compose the identifer into the back of the cls.modname buffer. + * i'll revert it when done */ + if (copy_string_to (moo, &moo->c->cls.name, &moo->c->cls.modname, &moo->c->cls.modname_capa, 1, '\0') <= -1 || + copy_string_to (moo, &moo->c->mth.name, &moo->c->cls.modname, &moo->c->cls.modname_capa, 1, '_') <= -1) + { + moo->c->cls.modname.len = savedlen; + return -1; + } + + pfnum = moo_getpfnum (moo, &moo->c->cls.modname.ptr[savedlen], moo->c->cls.modname.len - savedlen); + if (pfnum <= -1 || !MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(pfnum)) + { + MOO_DEBUG2 (moo, "Cannot find intrinsic primitive handler - %.*js\n", + moo->c->cls.modname.len - savedlen, &moo->c->cls.modname.ptr[savedlen]); + moo->c->cls.modname.len = savedlen; + set_syntax_error (moo, MOO_SYNERR_PFIDINVAL, &moo->c->mth.name_loc, &moo->c->mth.name); + return -1; + } + + moo->c->cls.modname.len = savedlen; + + moo->c->mth.pftype = PFTYPE_NUMBERED; + moo->c->mth.pfnum = pfnum; + } + else + { + moo_oow_t litidx, savedlen; + moo_oocs_t tmp; + + /* combine the module name and the method name delimited by a period + * when doing it, let me reuse the cls.modname buffer and restore it + * back once done */ + savedlen = moo->c->cls.modname.len; + + MOO_ASSERT (moo, MOO_CLASSOF(moo, moo->c->cls.self_oop->modname) == moo->_symbol); + tmp.ptr = MOO_OBJ_GET_CHAR_SLOT(moo->c->cls.self_oop->modname); + tmp.len = MOO_OBJ_GET_SIZE(moo->c->cls.self_oop->modname); + /* TODO: i can check if the primitive method is available at compile time by querying the module. * do the check depending on the compiler option */ - /* combine the module name and the method name delimited by a period - * when doing it, let me reuse the cls.modname buffer and restore it - * back once done */ - MOO_ASSERT (moo, MOO_CLASSOF(moo, moo->c->cls.self_oop->modname) == moo->_symbol); - savedlen = moo->c->cls.modname.len; - tmp.ptr = MOO_OBJ_GET_CHAR_SLOT(moo->c->cls.self_oop->modname); - tmp.len = MOO_OBJ_GET_SIZE(moo->c->cls.self_oop->modname); - if (copy_string_to (moo, &tmp, &moo->c->cls.modname, &moo->c->cls.modname_capa, 1, '\0') <= -1 || - copy_string_to (moo, &moo->c->mth.name, &moo->c->cls.modname, &moo->c->cls.modname_capa, 1, '.') <= -1 || - add_symbol_literal(moo, &moo->c->cls.modname, savedlen, &litidx) <= -1) - { + if (copy_string_to (moo, &tmp, &moo->c->cls.modname, &moo->c->cls.modname_capa, 1, '\0') <= -1 || + copy_string_to (moo, &moo->c->mth.name, &moo->c->cls.modname, &moo->c->cls.modname_capa, 1, '.') <= -1 || + add_symbol_literal(moo, &moo->c->cls.modname, savedlen, &litidx) <= -1) + { + moo->c->cls.modname.len = savedlen; + return -1; + } + moo->c->cls.modname.len = savedlen; - return -1; + + /* the symbol added must be the first literal to the current method. + * so this condition must be true. */ + MOO_ASSERT (moo, MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(litidx)); + + /* external named primitive containing a period. */ + moo->c->mth.pftype = PFTYPE_NAMED; + moo->c->mth.pfnum = litidx; } - moo->c->cls.modname.len = savedlen; - - /* the symbol added must be the first literal to the current method. - * so this condition must be true. */ - MOO_ASSERT (moo, MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(litidx)); - - /* external named primitive containing a period. */ - moo->c->mth.pftype = PFTYPE_NAMED; - moo->c->mth.pfnum = litidx; } else { diff --git a/moo/lib/err.c b/moo/lib/err.c index 690f0e9..d65076f 100644 --- a/moo/lib/err.c +++ b/moo/lib/err.c @@ -107,33 +107,33 @@ static moo_ooch_t synerrstr_35[] = {'d','i','s','a','l','l','o','w','e','d',' ', static moo_ooch_t synerrstr_36[] = {'d','u','p','l','i','c','a','t','e',' ','m','o','d','i','f','i','e','r','\0'}; static moo_ooch_t synerrstr_37[] = {'w','r','o','n','g',' ','m','e','t','h','o','d',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_38[] = {'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_39[] = {'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_40[] = {'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_41[] = {'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_42[] = {'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_43[] = {'u','n','d','e','c','l','a','r','e','d',' ','v','a','r','i','a','b','l','e','\0'}; -static moo_ooch_t synerrstr_44[] = {'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_45[] = {'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_46[] = {'a','m','b','i','g','u','o','u','s',' ','v','a','r','i','a','b','l','e','\0'}; -static moo_ooch_t synerrstr_47[] = {'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_48[] = {'t','o','o',' ','m','a','n','y',' ','t','e','m','p','o','r','a','r','i','e','s','\0'}; -static moo_ooch_t synerrstr_49[] = {'t','o','o',' ','m','a','n','y',' ','a','r','g','u','m','e','n','t','s','\0'}; -static moo_ooch_t synerrstr_50[] = {'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_51[] = {'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_52[] = {'t','o','o',' ','l','a','r','g','e',' ','b','l','o','c','k','\0'}; -static moo_ooch_t synerrstr_53[] = {'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_54[] = {'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_55[] = {'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_56[] = {'w','r','o','n','g',' ','m','o','d','u','l','e',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_57[] = {'#','i','n','c','l','u','d','e',' ','e','r','r','o','r','\0'}; -static moo_ooch_t synerrstr_58[] = {'w','r','o','n','g',' ','n','a','m','e','s','p','a','c','e',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_59[] = {'w','r','o','n','g',' ','p','o','o','l',' ','d','i','c','t','i','o','n','a','r','y',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_60[] = {'d','u','p','l','i','c','a','t','e',' ','p','o','o','l',' ','d','i','c','t','i','o','n','a','r','y',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_61[] = {'l','i','t','e','r','a','l',' ','e','x','p','e','c','t','e','d','\0'}; -static moo_ooch_t synerrstr_62[] = {'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_63[] = {'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_64[] = {'w','h','i','l','e',' ','e','x','p','e','c','t','e','d','\0'}; - +static moo_ooch_t synerrstr_39[] = {'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_40[] = {'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_41[] = {'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_42[] = {'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_43[] = {'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_44[] = {'u','n','d','e','c','l','a','r','e','d',' ','v','a','r','i','a','b','l','e','\0'}; +static moo_ooch_t synerrstr_45[] = {'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_46[] = {'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_47[] = {'a','m','b','i','g','u','o','u','s',' ','v','a','r','i','a','b','l','e','\0'}; +static moo_ooch_t synerrstr_48[] = {'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_49[] = {'t','o','o',' ','m','a','n','y',' ','t','e','m','p','o','r','a','r','i','e','s','\0'}; +static moo_ooch_t synerrstr_50[] = {'t','o','o',' ','m','a','n','y',' ','a','r','g','u','m','e','n','t','s','\0'}; +static moo_ooch_t synerrstr_51[] = {'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_52[] = {'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_53[] = {'t','o','o',' ','l','a','r','g','e',' ','b','l','o','c','k','\0'}; +static moo_ooch_t synerrstr_54[] = {'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_55[] = {'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_56[] = {'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_57[] = {'w','r','o','n','g',' ','m','o','d','u','l','e',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_58[] = {'#','i','n','c','l','u','d','e',' ','e','r','r','o','r','\0'}; +static moo_ooch_t synerrstr_59[] = {'w','r','o','n','g',' ','n','a','m','e','s','p','a','c','e',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_60[] = {'w','r','o','n','g',' ','p','o','o','l',' ','d','i','c','t','i','o','n','a','r','y',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_61[] = {'d','u','p','l','i','c','a','t','e',' ','p','o','o','l',' ','d','i','c','t','i','o','n','a','r','y',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_62[] = {'l','i','t','e','r','a','l',' ','e','x','p','e','c','t','e','d','\0'}; +static moo_ooch_t synerrstr_63[] = {'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_64[] = {'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_65[] = {'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, @@ -144,7 +144,7 @@ static moo_ooch_t* synerrstr[] = synerrstr_40, synerrstr_41, synerrstr_42, synerrstr_43, synerrstr_44, synerrstr_45, synerrstr_46, synerrstr_47, 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_64, synerrstr_65 }; #endif /* END: GENERATED WITH generr.moo */ diff --git a/moo/lib/exec.c b/moo/lib/exec.c index f32a1bd..ee308e8 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -1739,6 +1739,139 @@ static moo_pfrc_t pf_hash (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } + +static moo_pfrc_t _get_raw_int (moo_t* moo, moo_ooi_t nargs, int size) +{ + moo_uint8_t* rawptr; + moo_oow_t offset; + moo_ooi_t value; + moo_oop_t result; + + if (moo_inttooow (moo, MOO_STACK_GETARG(moo, nargs, 0), (moo_oow_t*)&rawptr) <= 0 || + moo_inttooow (moo, MOO_STACK_GETARG(moo, nargs, 1), &offset) <= 0) + { + moo->errnum = MOO_EINVAL; + return MOO_PF_FAILURE; + } + + switch (size) + { + case 1: + value = *(moo_int8_t*)&rawptr[offset]; + break; + + case 2: + value = *(moo_int16_t*)&rawptr[offset]; + break; + + case 4: + value = *(moo_int32_t*)&rawptr[offset]; + break; + + case 8: + value = *(moo_int64_t*)&rawptr[offset]; + break; + + default: + moo->errnum = MOO_EINVAL; + return MOO_PF_FAILURE; + } + + result = moo_ooitoint (moo, value); + if (!result) return MOO_PF_FAILURE; + + MOO_STACK_SETRET (moo, nargs, result); + return MOO_PF_SUCCESS; +} + +static moo_pfrc_t _get_raw_uint (moo_t* moo, moo_ooi_t nargs, int size) +{ + moo_uint8_t* rawptr; + moo_oow_t offset; + moo_oow_t value; + moo_oop_t result; + +MOO_DEBUG1 (moo, "get_raw_uint ..%d\n", size); + if (moo_inttooow (moo, MOO_STACK_GETARG(moo, nargs, 0), (moo_oow_t*)&rawptr) <= 0 || + moo_inttooow (moo, MOO_STACK_GETARG(moo, nargs, 1), &offset) <= 0) + { +MOO_DEBUG0 (moo, "get_raw_uint failure...\n"); + moo->errnum = MOO_EINVAL; + return MOO_PF_FAILURE; + } + + switch (size) + { + case 1: + value = *(moo_uint8_t*)&rawptr[offset]; + break; + + case 2: + value = *(moo_uint16_t*)&rawptr[offset]; + break; + + case 4: + value = *(moo_uint32_t*)&rawptr[offset]; + break; + + case 8: + value = *(moo_uint64_t*)&rawptr[offset]; + break; + + default: + moo->errnum = MOO_EINVAL; + return MOO_PF_FAILURE; + } + + result = moo_oowtoint (moo, value); + if (!result) return MOO_PF_FAILURE; + +MOO_DEBUG1 (moo, "get_raw_uint failure..%O.\n", result); + MOO_STACK_SETRET (moo, nargs, result); + return MOO_PF_SUCCESS; +} + + +static moo_pfrc_t pf_get_int8 (moo_t* moo, moo_ooi_t nargs) +{ + return _get_raw_int (moo, nargs, 1); +} + +static moo_pfrc_t pf_get_int16 (moo_t* moo, moo_ooi_t nargs) +{ + return _get_raw_int (moo, nargs, 2); +} + +static moo_pfrc_t pf_get_int32 (moo_t* moo, moo_ooi_t nargs) +{ + return _get_raw_int (moo, nargs, 4); +} + +static moo_pfrc_t pf_get_int64 (moo_t* moo, moo_ooi_t nargs) +{ + return _get_raw_int (moo, nargs, 8); +} + +static moo_pfrc_t pf_get_uint8 (moo_t* moo, moo_ooi_t nargs) +{ + return _get_raw_uint (moo, nargs, 1); +} + +static moo_pfrc_t pf_get_uint16 (moo_t* moo, moo_ooi_t nargs) +{ + return _get_raw_uint (moo, nargs, 2); +} + +static moo_pfrc_t pf_get_uint32 (moo_t* moo, moo_ooi_t nargs) +{ + return _get_raw_uint (moo, nargs, 4); +} + +static moo_pfrc_t pf_get_uint64 (moo_t* moo, moo_ooi_t nargs) +{ + return _get_raw_uint (moo, nargs, 8); +} + static moo_pfrc_t pf_responds_to (moo_t* moo, moo_ooi_t nargs) { moo_oop_t rcv, selector; @@ -1896,7 +2029,7 @@ static moo_pfrc_t __block_value (moo_t* moo, moo_oop_context_t rcv_blkctx, moo_o if (MOO_OOP_TO_SMOOI(rcv_blkctx->method_or_nargs) != actual_arg_count /* nargs */) { MOO_LOG4 (moo, MOO_LOG_PRIMITIVE | MOO_LOG_ERROR, - "Error(%hs) - wrong number of arguments to a block context %O - expecting %zd, got %zd\n", + "Error(%hs) - wrong number of arguments to a block context %O - %zd expected, %zd given\n", __PRIMITIVE_NAME__, rcv_blkctx, MOO_OOP_TO_SMOOI(rcv_blkctx->method_or_nargs), actual_arg_count); return MOO_PF_FAILURE; } @@ -2759,11 +2892,11 @@ static moo_pfrc_t pf_error_as_string (moo_t* moo, moo_ooi_t nargs) } -#define MAX_NARGS MOO_TYPE_MAX(moo_ooi_t) +#define MAX_NARGS MOO_TYPE_MAX(moo_oow_t) struct pf_t { - moo_ooi_t min_nargs; /* expected number of arguments */ - moo_ooi_t max_nargs; /* expected number of arguments */ + moo_oow_t min_nargs; /* expected number of arguments */ + moo_oow_t max_nargs; /* expected number of arguments */ moo_pfimpl_t handler; const char* name; /* the name is supposed to be 7-bit ascii only */ }; @@ -2791,6 +2924,26 @@ static pf_t pftab[] = { 0, 0, pf_hash, "_hash" }, + { 2, 2, pf_get_int8, "System__getInt8" }, + { 2, 2, pf_get_int16, "System__getInt16" }, + { 2, 2, pf_get_int32, "System__getInt32" }, + { 2, 2, pf_get_int64, "System__getInt64" }, + { 2, 2, pf_get_uint8, "System__getUint8" }, + { 2, 2, pf_get_uint16, "System__getUint16" }, + { 2, 2, pf_get_uint32, "System__getUint32" }, + { 2, 2, pf_get_uint64, "System__getUint64" }, + +/* + { 3, 3, pf_put_int8, "System__putInt8" }, + { 3, 3, pf_put_int16, "System__putInt16" }, + { 3, 3, pf_put_int32, "System__putInt32" }, + { 3, 3, pf_put_int64, "System__putInt64" }, + { 3, 3, pf_put_uint8, "System__putUint8" }, + { 3, 3, pf_put_uint16, "System__putUint16" }, + { 3, 3, pf_put_uint32, "System__putUint32" }, + { 3, 3, pf_put_uint64, "System__putUint64" }, +*/ + { 1, 1, pf_responds_to, "_responds_to" }, { 1, MAX_NARGS, pf_perform, "_perform" }, { 1, 1, pf_exceptionize_error, "_exceptionize_error" }, @@ -2799,7 +2952,6 @@ static pf_t pftab[] = { 0, MAX_NARGS, pf_block_value, "_block_value" }, { 0, MAX_NARGS, pf_block_new_process, "_block_new_process" }, - { 0, 0, pf_process_resume, "_process_resume" }, { 0, 0, pf_process_terminate, "_process_terminate" }, { 0, 0, pf_process_yield, "_process_yield" }, @@ -2852,10 +3004,7 @@ int moo_getpfnum (moo_t* moo, const moo_ooch_t* ptr, moo_oow_t len) /* TODO: have the pftable sorted alphabetically and do binary search */ for (i = 0; i < MOO_COUNTOF(pftab); i++) { - if (moo_compoocharsbcstr(ptr, len, pftab[i].name) == 0) - { - return i; - } + if (moo_compoocharsbcstr(ptr, len, pftab[i].name) == 0) return i; } moo->errnum = MOO_ENOENT; @@ -2866,6 +3015,7 @@ int moo_getpfnum (moo_t* moo, const moo_ooch_t* ptr, moo_oow_t len) static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) { moo_ooi_t preamble, preamble_code; + moo_ooi_t /*sp,*/ stack_base; #if defined(MOO_DEBUG_VM_EXEC) moo_ooi_t fetched_instruction_pointer = 0; /* set it to a fake value */ @@ -2982,24 +3132,36 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) { moo_ooi_t pfnum; + stack_base = moo->sp - nargs - 1; /* stack base before receiver and arguments */ + pfnum = MOO_METHOD_GET_PREAMBLE_INDEX(preamble); LOG_INST_1 (moo, "preamble_primitive %zd", pf_no); - if (pfnum >= 0 && pfnum < MOO_COUNTOF(pftab) && - (nargs >= pftab[pfnum].min_nargs && nargs <= pftab[pfnum].max_nargs)) + if (pfnum >= 0 && pfnum < MOO_COUNTOF(pftab)) { int n; + if ((nargs < pftab[pfnum].min_nargs || nargs > pftab[pfnum].max_nargs)) + { + MOO_DEBUG4 (moo, "Soft failure due to argument count mismatch for primitive function %hs - %zu-%zu expected, %zu given\n", + pftab[pfnum].name, pftab[pfnum].min_nargs, pftab[pfnum].max_nargs, nargs); + goto activate_primitive_method_body; + } + moo_pushtmp (moo, (moo_oop_t*)&method); n = pftab[pfnum].handler (moo, nargs); moo_poptmp (moo); if (n <= MOO_PF_HARD_FAILURE) return -1; if (n >= MOO_PF_SUCCESS) break; + + MOO_DEBUG2 (moo, "Soft failure indicated by primitive function %p - %hs\n", pftab[pfnum].handler, pftab[pfnum].name); + } + else + { + MOO_DEBUG1 (moo, "Cannot call primitive numbered %zd - invalid number\n", pfnum); } - /* soft primitive failure */ - if (activate_new_method (moo, method, nargs) <= -1) return -1; - break; + goto activate_primitive_method_body; } case MOO_METHOD_PREAMBLE_NAMED_PRIMITIVE: @@ -3008,10 +3170,8 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) moo_oop_t name; moo_pfimpl_t handler; moo_oow_t w; - moo_ooi_t /*sp,*/ sb; - /*sp = moo->sp;*/ - sb = moo->sp - nargs - 1; /* stack base before receiver and arguments */ + stack_base = moo->sp - nargs - 1; /* stack base before receiver and arguments */ #if !defined(NDEBUG) pf_name_index = MOO_METHOD_GET_PREAMBLE_INDEX(preamble); @@ -3072,6 +3232,7 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) MOO_DEBUG2 (moo, "Soft failure for non-existent primitive function - %.*js\n", MOO_OBJ_GET_SIZE(name), ((moo_oop_char_t)name)->slot); } + activate_primitive_method_body: #if defined(MOO_USE_METHOD_TRAILER) MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_TRAILER(method)); if (MOO_METHOD_GET_CODE_SIZE(method) == 0) /* this trailer size field not a small integer */ @@ -3079,11 +3240,10 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) if (method->code == moo->_nil) #endif { - /* no byte code to execute */ -/* TODO: what is the best tactics? emulate "self primitiveFailed"? */ - - /* force restore stack pointers */ - moo->sp = sb; + /* no byte code to execute - make it a hard failure */ +/* TODO: what is the best tactics? emulate "self primitiveFailed"? or should this be generated by the compiler */ + MOO_DEBUG0 (moo, "Empty primitive body\n"); + moo->sp = stack_base; /* force restore stack pointer */ MOO_STACK_PUSH (moo, moo->_nil); return -1; } @@ -3091,6 +3251,7 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) { if (activate_new_method (moo, method, nargs) <= -1) return -1; } + break; } diff --git a/moo/lib/main.c b/moo/lib/main.c index 3736742..4cd293b 100644 --- a/moo/lib/main.c +++ b/moo/lib/main.c @@ -1014,7 +1014,7 @@ static void vm_muxwait (moo_t* moo, const moo_ntime_t* dur, moo_vmprim_muxwait_c if (xtn->ev.len <= 0) { /* the event buffer is still empty */ - pthread_cond_wait (&xtn->ev.cnd2, &xtn->ev.mtx); + pthread_cond_timedwait (&xtn->ev.cnd2, &xtn->ev.mtx, &ts); } pthread_mutex_unlock (&xtn->ev.mtx); } @@ -1151,7 +1151,7 @@ static void vm_sleep (moo_t* moo, const moo_ntime_t* dur) #if defined(USE_THREAD) /* the sleep callback is called only if there is no IO semaphore - * waiting. so i can safely call vm_muxwait() wihtout a muxwait callback + * waiting. so i can safely call vm_muxwait() without a muxwait callback * when USE_THREAD is true */ vm_muxwait (moo, dur, MOO_NULL); #else diff --git a/moo/lib/moo.h b/moo/lib/moo.h index bd60c4a..b9fa16a 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -1229,6 +1229,7 @@ enum moo_synerrnum_t MOO_SYNERR_MODIFIERDUPL, /* duplicate modifier */ MOO_SYNERR_MTHNAME, /* wrong method name */ MOO_SYNERR_MTHNAMEDUPL, /* duplicate method name */ + MOO_SYNERR_VARIADMTHINVAL, /* invalid variadic method definition */ MOO_SYNERR_ARGNAMEDUPL, /* duplicate argument name */ MOO_SYNERR_TMPRNAMEDUPL, /* duplicate temporary variable name */ MOO_SYNERR_VARNAMEDUPL, /* duplicate variable name */