From aeb02213b4f0228b803c85f44fda3df8bfc0ba7b Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Sat, 1 Apr 2017 04:58:02 +0000 Subject: [PATCH] changed moo_getpfnum(). added argument count checks when processing primitive method pragmas --- moo/kernel/Apex.moo | 39 ++++----- moo/kernel/Magnitu.moo | 11 +-- moo/kernel/Process.moo | 16 +--- moo/lib/comp.c | 44 +++++++--- moo/lib/exec.c | 184 +++++++++++++++++++++-------------------- moo/lib/moo-prv.h | 5 +- 6 files changed, 149 insertions(+), 150 deletions(-) diff --git a/moo/kernel/Apex.moo b/moo/kernel/Apex.moo index 62b0030..faead9c 100644 --- a/moo/kernel/Apex.moo +++ b/moo/kernel/Apex.moo @@ -328,13 +328,13 @@ class Apex(nil) ## ------------------------------------------------------- ## ------------------------------------------------------- - method(#class,#variadic) perform() + method(#class,#variadic) perform(selector) { self primitiveFailed } - - method(#variadic) perform() + + method(#variadic) perform(selector) { self primitiveFailed @@ -481,14 +481,14 @@ class Error(Apex) pooldic Error.Code { - EGENERIC := error(0). - ENOIMPL := error(1). - ESYSERR := error(2). - EINTERN := error(3). - ESYSMEM := error(4). - EOOMEM := error(5). - EINVAL := error(6). - ENOENT := error(7). + EGENERIC := error(1). + ENOIMPL := error(2). + ESYSERR := error(3). + EINTERN := error(4). + ESYSMEM := error(5). + EOOMEM := error(6). + EINVAL := error(7). + ENOENT := error(8). (* add more items... *) } @@ -524,19 +524,8 @@ extend Error ^false } - method asInteger - { - - } - - method asCharacter - { - - } - - method asString - { - - } + method(#primitive) asInteger. + method(#primitive) asCharacter. + method(#primitive) asString. } diff --git a/moo/kernel/Magnitu.moo b/moo/kernel/Magnitu.moo index 880e233..c3936e4 100644 --- a/moo/kernel/Magnitu.moo +++ b/moo/kernel/Magnitu.moo @@ -304,15 +304,8 @@ class SmallInteger(Integer) ## ^0 ## } - method asError - { - - } - - method asCharacter - { - - } + method(#primitive) asCharacter. + method(#primitive) asError. } class(#liword) LargeInteger(Integer) diff --git a/moo/kernel/Process.moo b/moo/kernel/Process.moo index 638d761..8692362 100644 --- a/moo/kernel/Process.moo +++ b/moo/kernel/Process.moo @@ -124,18 +124,10 @@ class Semaphore(Object) ## ================================================================== - method signal - { - - self primitiveFailed. - } - - method wait - { - - self primitiveFailed. - } + method(#primitive) signal. + method(#primitive) wait. +(* method waitWithTimeout: seconds { @@ -147,7 +139,7 @@ class Semaphore(Object) self primitiveFailed } - +*) method critical: aBlock { self wait. diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 4004e0f..bfc6d25 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -3351,10 +3351,10 @@ static int compile_method_temporaries (moo_t* moo) return 0; } -static int compile_method_primitive (moo_t* moo) +static int compile_method_pragma (moo_t* moo) { /* - * method-primitive := "<" "primitive:" integer ">" | + * method-pragma := "<" "primitive:" integer ">" | * "<" "primitive:" symbol ">" | * "<" "exception" ">" | * "<" "ensure" ">" @@ -3400,22 +3400,22 @@ static int compile_method_primitive (moo_t* moo) { const moo_ooch_t* tptr; moo_oow_t tlen; + moo_pfbase_t* pfbase; tptr = TOKEN_NAME_PTR(moo) + 1; tlen = TOKEN_NAME_LEN(moo) - 1; /* attempt get a primitive function number by name */ - pfnum = moo_getpfnum (moo, tptr, tlen); - if (pfnum <= -1) + pfbase = moo_getpfnum (moo, tptr, tlen, &pfnum); + if (!pfbase) { /* a built-in primitive function is not found * check if it is a primitive function identifier */ moo_oow_t lit_idx; - moo_pfbase_t* pfbase; if (!moo_rfindoochar (tptr, tlen, '.')) { - /* wrong primitive functio identifier */ + /* wrong primitive function identifier */ set_syntax_error (moo, MOO_SYNERR_PFIDINVAL, TOKEN_LOC(moo), TOKEN_NAME(moo)); return -1; } @@ -3433,7 +3433,7 @@ static int compile_method_primitive (moo_t* moo) if (moo->c->mth.tmpr_nargs < pfbase->minargs || moo->c->mth.tmpr_nargs > pfbase->maxargs) { - MOO_DEBUG5 (moo, "Unsupported argument count in primitive method definition of %.*js - %zd-%zd expected, %zd specified\n", + MOO_DEBUG5 (moo, "Unsupported argument count in primitive method pragma of %.*js - %zd-%zd expected, %zd specified\n", tlen, tptr, pfbase->minargs, pfbase->maxargs, moo->c->mth.tmpr_nargs); set_syntax_error (moo, MOO_SYNERR_PFARGDEFINVAL, &moo->c->mth.name_loc, &moo->c->mth.name); return -1; @@ -3455,7 +3455,14 @@ static int compile_method_primitive (moo_t* moo) } else { - /* TODO: check argument count for this primitive ... */ + if (moo->c->mth.tmpr_nargs < pfbase->minargs || moo->c->mth.tmpr_nargs > pfbase->maxargs) + { + MOO_DEBUG5 (moo, "Unsupported argument count in primitive method pragma of %.*js - %zd-%zd expected, %zd specified\n", + tlen, tptr, pfbase->minargs, pfbase->maxargs, moo->c->mth.tmpr_nargs); + set_syntax_error (moo, MOO_SYNERR_PFARGDEFINVAL, &moo->c->mth.name_loc, &moo->c->mth.name); + return -1; + } + moo->c->mth.pftype = PFTYPE_NUMBERED; moo->c->mth.pfnum = pfnum; } @@ -5910,6 +5917,7 @@ static int compile_method_definition (moo_t* moo) moo_oow_t savedlen; moo_ooi_t pfnum; + moo_pfbase_t* pfbase; savedlen = moo->c->cls.modname.len; @@ -5923,8 +5931,8 @@ static int compile_method_definition (moo_t* moo) 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)) + pfbase = moo_getpfnum (moo, &moo->c->cls.modname.ptr[savedlen], moo->c->cls.modname.len - savedlen, &pfnum); + if (!pfbase) { MOO_DEBUG2 (moo, "Cannot find intrinsic primitive function - %.*js\n", moo->c->cls.modname.len - savedlen, &moo->c->cls.modname.ptr[savedlen]); @@ -5933,9 +5941,19 @@ static int compile_method_definition (moo_t* moo) return -1; } -/* TODO: check argumetns... */ + if (moo->c->mth.tmpr_nargs < pfbase->minargs || moo->c->mth.tmpr_nargs > pfbase->maxargs) + { + MOO_DEBUG5 (moo, "Unsupported argument count in primitive method definition of %.*js - %zd-%zd expected, %zd specified\n", + moo->c->cls.modname.len - savedlen, &moo->c->cls.modname.ptr[savedlen], + pfbase->minargs, pfbase->maxargs, moo->c->mth.tmpr_nargs); + set_syntax_error (moo, MOO_SYNERR_PFARGDEFINVAL, &moo->c->mth.name_loc, &moo->c->mth.name); + moo->c->cls.modname.len = savedlen; + return -1; + } + moo->c->cls.modname.len = savedlen; + MOO_ASSERT (moo, MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(pfnum)); moo->c->mth.pftype = PFTYPE_NUMBERED; moo->c->mth.pfnum = pfnum; } @@ -6006,7 +6024,7 @@ static int compile_method_definition (moo_t* moo) GET_TOKEN (moo); if (compile_method_temporaries(moo) <= -1 || - compile_method_primitive(moo) <= -1 || + compile_method_progma(moo) <= -1 || compile_method_statements(moo) <= -1) return -1; if (TOKEN_TYPE(moo) != MOO_IOTOK_RBRACE) @@ -6157,7 +6175,7 @@ static int __compile_class_definition (moo_t* moo, int extend) * * method-definition := method method-modifier? method-actual-definition * method-modifier := "(" (#class | #instance)? ")" - * method-actual-definition := method-name "{" method-tempraries? method-primitive? method-statements* "}" + * method-actual-definition := method-name "{" method-tempraries? method-pragma? method-statements* "}" * * NOTE: when extending a class, class-module-import and variable-definition are not allowed. */ diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 4e0202f..d4da5de 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -1901,6 +1901,8 @@ static moo_pfrc_t pf_perform (moo_t* moo, moo_ooi_t nargs) moo_oop_t /*rcv,*/ selector; moo_oow_t ssp, esp, i; + MOO_ASSERT (moo, nargs >= 1); /* at least, a selector must be specified */ + /*rcv = MOO_STACK_GETRCV(moo, nargs);*/ selector = MOO_STACK_GETARG(moo, nargs, 0); @@ -2886,127 +2888,131 @@ static moo_pfrc_t pf_error_as_string (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } - -#define MAX_NARGS MOO_TYPE_MAX(moo_oow_t) +#define MA MOO_TYPE_MAX(moo_oow_t) struct pf_t { - 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 */ + moo_pfbase_t pfbase; }; typedef struct pf_t pf_t; static pf_t pftab[] = { - { 0, MAX_NARGS, pf_dump, "_dump" }, - { 2, MAX_NARGS, pf_log, "_log" }, + { "_dump", { pf_dump, 0, MA } }, + { "_log", { pf_log, 2, MA } }, - { 1, 1, pf_identical, "_identical" }, - { 1, 1, pf_not_identical, "_not_identical" }, - { 1, 1, pf_equal, "_equal" }, - { 1, 1, pf_not_equal, "_not_equal" }, - { 0, 0, pf_class, "_class" }, + { "_identical", { pf_identical, 1, 1 } }, + { "_not_identical", { pf_not_identical, 1, 1 } }, + { "_equal", { pf_equal, 1, 1 } }, + { "_not_equal", { pf_not_equal, 1, 1 } }, + { "_class", { pf_class, 0, 0 } }, - { 0, 1, pf_basic_new, "_basic_new" }, - { 0, 1, pf_ngc_new, "_ngc_new" }, - { 0, 0, pf_ngc_dispose, "_ngc_dispose" }, - { 0, 0, pf_shallow_copy, "_shallow_copy" }, + { "_basic_new", { pf_basic_new, 0, 1 } }, + { "_ngc_new", { pf_ngc_new, 0, 1 } }, + { "_ngc_dispose", { pf_ngc_dispose, 0, 0 } }, + { "_shallow_copy", { pf_shallow_copy, 0, 0 } }, - { 0, 0, pf_basic_size, "_basic_size" }, - { 1, 1, pf_basic_at, "_basic_at" }, - { 2, 2, pf_basic_at_put, "_basic_at_put" }, + { "_basic_size", { pf_basic_size, 0, 0 } }, + { "_basic_at", { pf_basic_at, 1, 1 } }, + { "_basic_at_put", { pf_basic_at_put, 2, 2 } }, - { 0, 0, pf_hash, "_hash" }, + { "_hash", { pf_hash, 0, 0 } }, - { 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" }, + { "System__getInt8", { pf_get_int8, 2, 2 } }, + { "System__getInt16", { pf_get_int16, 2, 2 } }, + { "System__getInt32", { pf_get_int32, 2, 2 } }, + { "System__getInt64", { pf_get_int64, 2, 2 } }, + { "System__getUint8", { pf_get_uint8, 2, 2 } }, + { "System__getUint16", { pf_get_uint16, 2, 2 } }, + { "System__getUint32", { pf_get_uint32, 2, 2 } }, + { "System__getUint64", { pf_get_uint64, 2, 2 } }, /* - { 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" }, + { "System__putInt8", { pf_put_int8, 3, 3 } }, + { "System__putInt16", { pf_put_int16, 3, 3 } }, + { "System__putInt32", { pf_put_int32, 3, 3 } }, + { "System__putInt64", { pf_put_int64, 3, 3 } }, + { "System__putUint8", { pf_put_uint8, 3, 3 } }, + { "System__putUint16", { pf_put_uint16, 3, 3 } }, + { "System__putUint32", { pf_put_uint32, 3, 3 } }, + { "System__putUint64", { pf_put_uint64, 3, 3 } }, */ - { 1, 1, pf_responds_to, "_responds_to" }, - { 1, MAX_NARGS, pf_perform, "_perform" }, - { 1, 1, pf_exceptionize_error, "_exceptionize_error" }, + { "_responds_to", { pf_responds_to, 1, 1 } }, + { "_perform", { pf_perform, 1, MA } }, + { "_exceptionize_error", { pf_exceptionize_error, 1, 1 } }, - { 1, 1, pf_context_goto, "_context_goto" }, - { 0, MAX_NARGS, pf_block_value, "_block_value" }, - { 0, MAX_NARGS, pf_block_new_process, "_block_new_process" }, + { "_context_goto", { pf_context_goto, 1, 1 } }, + { "_block_value", { pf_block_value, 0, MA } }, + { "_block_new_process", { pf_block_new_process, 0, 1 } }, - { 0, 0, pf_process_resume, "_process_resume" }, - { 0, 0, pf_process_terminate, "_process_terminate" }, - { 0, 0, pf_process_yield, "_process_yield" }, - { 0, 0, pf_process_suspend, "_process_suspend" }, - { 0, 0, pf_semaphore_signal, "_semaphore_signal" }, - { 0, 0, pf_semaphore_wait, "_semaphore_wait" }, + { "_process_resume", { pf_process_resume, 0, 0 } }, + { "_process_terminate", { pf_process_terminate, 0, 0 } }, + { "_process_yield", { pf_process_yield, 0, 0 } }, + { "_process_suspend", { pf_process_suspend, 0, 0 } }, - { 1, 1, pf_processor_schedule, "_processor_schedule" }, - { 2, 3, pf_processor_add_timed_semaphore, "_processor_add_timed_semaphore" }, - { 2, 2, pf_processor_add_input_semaphore, "_processor_add_input_semaphore" }, - { 2, 2, pf_processor_add_output_semaphore, "_processor_add_output_semaphore" }, - { 2, 2, pf_processor_add_inoutput_semaphore, "_processor_add_inoutput_semaphore" }, - { 1, 1, pf_processor_remove_semaphore, "_processor_remove_semaphore" }, - { 2, 2, pf_processor_return_to, "_processor_return_to" }, + { "Semaphore_signal", { pf_semaphore_signal, 0, 0 } }, + { "Semaphore_wait", { pf_semaphore_wait, 0, 0 } }, - { 1, 1, pf_integer_add, "_integer_add" }, - { 1, 1, pf_integer_sub, "_integer_sub" }, - { 1, 1, pf_integer_mul, "_integer_mul" }, - { 1, 1, pf_integer_quo, "_integer_quo" }, - { 1, 1, pf_integer_rem, "_integer_rem" }, - { 1, 1, pf_integer_quo2, "_integer_quo2" }, - { 1, 1, pf_integer_rem2, "_integer_rem2" }, - { 0, 0, pf_integer_negated, "_integer_negated" }, - { 1, 1, pf_integer_bitat, "_integer_bitat" }, - { 1, 1, pf_integer_bitand, "_integer_bitand" }, - { 1, 1, pf_integer_bitor, "_integer_bitor" }, - { 1, 1, pf_integer_bitxor, "_integer_bitxor" }, - { 0, 0, pf_integer_bitinv, "_integer_bitinv" }, - { 1, 1, pf_integer_bitshift, "_integer_bitshift" }, - { 1, 1, pf_integer_eq, "_integer_eq" }, - { 1, 1, pf_integer_ne, "_integer_ne" }, - { 1, 1, pf_integer_lt, "_integer_lt" }, - { 1, 1, pf_integer_gt, "_integer_gt" }, - { 1, 1, pf_integer_le, "_integer_le" }, - { 1, 1, pf_integer_ge, "_integer_ge" }, - { 1, 1, pf_integer_inttostr, "_integer_inttostr" }, + { "_processor_schedule", { pf_processor_schedule, 1, 1 } }, + { "_processor_add_timed_semaphore", { pf_processor_add_timed_semaphore, 2, 3 } }, + { "_processor_add_input_semaphore", { pf_processor_add_input_semaphore, 2, 2 } }, + { "_processor_add_output_semaphore", { pf_processor_add_output_semaphore, 2, 2 } }, + { "_processor_add_inoutput_semaphore", { pf_processor_add_inoutput_semaphore, 2, 2 } }, + { "_processor_remove_semaphore", { pf_processor_remove_semaphore, 1, 1 } }, + { "_processor_return_to", { pf_processor_return_to, 2, 2 } }, - { 0, 0, pf_smooi_as_character, "_smooi_as_character" }, - { 0, 0, pf_smooi_as_error, "_smooi_as_error" }, + { "_integer_add", { pf_integer_add, 1, 1 } }, + { "_integer_sub", { pf_integer_sub, 1, 1 } }, + { "_integer_mul", { pf_integer_mul, 1, 1 } }, + { "_integer_quo", { pf_integer_quo, 1, 1 } }, + { "_integer_rem", { pf_integer_rem, 1, 1 } }, + { "_integer_quo2", { pf_integer_quo2, 1, 1 } }, + { "_integer_rem2", { pf_integer_rem2, 1, 1 } }, + { "_integer_negated", { pf_integer_negated, 0, 0 } }, + { "_integer_bitat", { pf_integer_bitat, 1, 1 } }, + { "_integer_bitand", { pf_integer_bitand, 1, 1 } }, + { "_integer_bitor", { pf_integer_bitor, 1, 1 } }, + { "_integer_bitxor", { pf_integer_bitxor, 1, 1 } }, + { "_integer_bitinv", { pf_integer_bitinv, 0, 0 } }, + { "_integer_bitshift", { pf_integer_bitshift, 1, 1 } }, + { "_integer_eq", { pf_integer_eq, 1, 1 } }, + { "_integer_ne", { pf_integer_ne, 1, 1 } }, + { "_integer_lt", { pf_integer_lt, 1, 1 } }, + { "_integer_gt", { pf_integer_gt, 1, 1 } }, + { "_integer_le", { pf_integer_le, 1, 1 } }, + { "_integer_ge", { pf_integer_ge, 1, 1 } }, + { "_integer_inttostr", { pf_integer_inttostr, 1, 1 } }, - { 0, 0, pf_error_as_character, "_error_as_character" }, - { 0, 0, pf_error_as_integer, "_error_as_integer" }, - { 0, 0, pf_error_as_string, "_error_as_string" } + { "Error_asCharacter", { pf_error_as_character, 0, 0 } }, + { "Error_asInteger", { pf_error_as_integer, 0, 0 } }, + { "Error_asString", { pf_error_as_string, 0, 0 } }, + + { "SmallInteger_asCharacter", { pf_smooi_as_character, 0, 0 } }, + { "SmallInteger_asError", { pf_smooi_as_error, 0, 0 } } }; -int moo_getpfnum (moo_t* moo, const moo_ooch_t* ptr, moo_oow_t len) +moo_pfbase_t* moo_getpfnum (moo_t* moo, const moo_ooch_t* ptr, moo_oow_t len, moo_ooi_t* pfnum) { - int i; + moo_ooi_t i; /* TODO: have the pftable sorted alphabetically and do binary search */ +/* TODO: sort pftab and utilize moo_findpfbase? */ for (i = 0; i < MOO_COUNTOF(pftab); i++) { /* moo_compoocharsbcstr() is not aware of multibyte encoding. * so the names above should be composed of the single byte * characters only */ - if (moo_compoocharsbcstr(ptr, len, pftab[i].name) == 0) return i; + if (moo_compoocharsbcstr(ptr, len, pftab[i].name) == 0) + { + MOO_ASSERT (moo, MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(i)); /* this must never be so big */ + *pfnum = i; + return &pftab[i].pfbase; + } } moo->errnum = MOO_ENOENT; - return -1; + return MOO_NULL; } /* ------------------------------------------------------------------------- */ @@ -3139,20 +3145,20 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) { int n; - if ((nargs < pftab[pfnum].min_nargs || nargs > pftab[pfnum].max_nargs)) + if ((nargs < pftab[pfnum].pfbase.minargs || nargs > pftab[pfnum].pfbase.maxargs)) { 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); + pftab[pfnum].name, pftab[pfnum].pfbase.minargs, pftab[pfnum].pfbase.maxargs, nargs); goto activate_primitive_method_body; } moo_pushtmp (moo, (moo_oop_t*)&method); - n = pftab[pfnum].handler (moo, nargs); + n = pftab[pfnum].pfbase.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); + MOO_DEBUG2 (moo, "Soft failure indicated by primitive function %p - %hs\n", pftab[pfnum].pfbase.handler, pftab[pfnum].name); } else { diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 7c5db8f..1b242e9 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -1168,10 +1168,11 @@ moo_oop_t moo_inttostr ( /* exec.c */ /* ========================================================================= */ -int moo_getpfnum ( +moo_pfbase_t* moo_getpfnum ( moo_t* moo, const moo_ooch_t* ptr, - moo_oow_t len + moo_oow_t len, + moo_ooi_t* pfnum );