From 2ed62a5edb2de4540a32229765ebc82273fee020 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Sat, 1 Apr 2017 06:54:27 +0000 Subject: [PATCH] added a new method directive #liberal to indicate a method that accept a fully variadic number of arguments. the directive #liberal allows the caller to omit the named arguments as well. the directive #variadic requires the caller to provide at least the named arguments --- moo/kernel/test-014.moo | 17 +++++++++++++---- moo/lib/comp.c | 18 ++++++++++++------ moo/lib/exec.c | 24 +++++++++++++++--------- moo/lib/moo.h | 1 + 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/moo/kernel/test-014.moo b/moo/kernel/test-014.moo index 6ebc930..ff0d49e 100644 --- a/moo/kernel/test-014.moo +++ b/moo/kernel/test-014.moo @@ -145,6 +145,7 @@ class MyObject(TestObject) self varg_test (10, 20, 30, 40, 50) dump. self varg_test2 (10, 20, 30, 40, 50) dump. self varg_test3 (10, 20, 30, 40, 50) dump. + self varg_test3 (10, 20, 30, 40, 50, 60, 70, 80, 90, 100) dump. thisContext vargCount dump. thisContext vargCount dump. @@ -204,21 +205,29 @@ class MyObject(TestObject) } method(#class,#variadic) varg_test2(a,b,c) { - 0 to: (thisContext vargCount - 1) do: [:k | + 'varg_test2 start .....' dump. + a dump. + b dump. + c dump. + 'varg_test2 varg .....' dump. + 0 priorTo: (thisContext vargCount) do: [:k | (thisContext vargAt: k) dump. ]. + 'varg_test2 end .....' dump. ^a } - method(#class,#variadic) varg_test3(a,b,c,d,e,f) + method(#class,#liberal) varg_test3(a,b,c,d,e,f) { - 0 to: (thisContext vargCount - 1) do: [:k | + 'varg_test3 start .....' dump. + 0 priorTo: (thisContext vargCount) do: [:k | (thisContext vargAt: k) dump. ]. + 'varg_test3 end .....' dump. ## ^b * 100 ^f } - method(#class,#variadic) t001(a) + method(#class,#liberal) t001(a) { a isNil ifTrue: [^error(10)]. (a = 20) ifTrue: [^error]. diff --git a/moo/lib/comp.c b/moo/lib/comp.c index bfc6d25..2d0f518 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -103,6 +103,7 @@ static struct voca_t { 9, { '#','h','a','l','f','w','o','r','d' } }, { 2, { 'i','f' } }, { 8, { '#','i','n','c','l','u','d','e' } }, + { 8, { '#','l','i','b','e','r','a','l' } }, { 7, { '#','l','i','w','o','r','d' } }, { 6, { 'm','e','t','h','o','d' } }, { 3, { 'n','i','l' } }, @@ -150,6 +151,7 @@ enum voca_id_t VOCA_HALFWORD_S, VOCA_IF, VOCA_INCLUDE_S, + VOCA_LIBERAL_S, VOCA_LIWORD_S, VOCA_METHOD, VOCA_NIL, @@ -5752,8 +5754,8 @@ static int add_compiled_method (moo_t* moo) preamble_index = 0; } - if (moo->c->mth.variadic /*&& moo->c->mth.tmpr_nargs > 0*/) - preamble_flags |= MOO_METHOD_PREAMBLE_FLAG_VARIADIC; + /*if (moo->c->mth.variadic) */ + preamble_flags |= moo->c->mth.variadic; MOO_ASSERT (moo, MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(preamble_index)); @@ -5853,9 +5855,10 @@ static int compile_method_definition (moo_t* moo) GET_TOKEN (moo); } - else if (is_token_symbol(moo, VOCA_VARIADIC_S)) + else if (is_token_symbol(moo, VOCA_VARIADIC_S) || + is_token_symbol(moo, VOCA_LIBERAL_S)) { - /* method(#variadic) */ + /* method(#variadic) or method(#liberal) */ if (moo->c->mth.variadic) { /* #variadic duplicate modifier */ @@ -5863,7 +5866,10 @@ static int compile_method_definition (moo_t* moo) return -1; } - moo->c->mth.variadic = 1; + if (is_token_symbol(moo, VOCA_LIBERAL_S)) + moo->c->mth.variadic = MOO_METHOD_PREAMBLE_FLAG_LIBERAL; + else + moo->c->mth.variadic = MOO_METHOD_PREAMBLE_FLAG_VARIADIC; GET_TOKEN (moo); } @@ -6024,7 +6030,7 @@ static int compile_method_definition (moo_t* moo) GET_TOKEN (moo); if (compile_method_temporaries(moo) <= -1 || - compile_method_progma(moo) <= -1 || + compile_method_pragma(moo) <= -1 || compile_method_statements(moo) <= -1) return -1; if (TOKEN_TYPE(moo) != MOO_IOTOK_RBRACE) diff --git a/moo/lib/exec.c b/moo/lib/exec.c index d4da5de..591e49a 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -885,8 +885,8 @@ static MOO_INLINE int activate_new_method (moo_t* moo, moo_oop_method_t mth, moo if (actual_nargs > nargs) { /* more arguments than the method specification have been passed in. - * it must be a variadic unary method. othewise, the compiler is buggy */ - MOO_ASSERT (moo, MOO_METHOD_GET_PREAMBLE_FLAGS(MOO_OOP_TO_SMOOI(mth->preamble)) & MOO_METHOD_PREAMBLE_FLAG_VARIADIC); + * it must be a variadic or liberal unary method. othewise, the compiler is buggy */ + MOO_ASSERT (moo, MOO_METHOD_GET_PREAMBLE_FLAGS(MOO_OOP_TO_SMOOI(mth->preamble)) & (MOO_METHOD_PREAMBLE_FLAG_VARIADIC | MOO_METHOD_PREAMBLE_FLAG_LIBERAL)); actual_ntmprs = ntmprs + (actual_nargs - nargs); } else actual_ntmprs = ntmprs; @@ -3018,7 +3018,7 @@ moo_pfbase_t* moo_getpfnum (moo_t* moo, const moo_ooch_t* ptr, moo_oow_t len, mo /* ------------------------------------------------------------------------- */ 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 preamble, preamble_code, preamble_flags; moo_ooi_t /*sp,*/ stack_base; #if defined(MOO_DEBUG_VM_EXEC) @@ -3026,16 +3026,22 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) #endif preamble = MOO_OOP_TO_SMOOI(method->preamble); + preamble_flags = MOO_METHOD_GET_PREAMBLE_FLAGS(preamble); - if (nargs != MOO_OOP_TO_SMOOI(method->tmpr_nargs)) + if (preamble_flags & MOO_METHOD_PREAMBLE_FLAG_LIBERAL) { - - moo_ooi_t preamble_flags; - - preamble_flags = MOO_METHOD_GET_PREAMBLE_FLAGS(preamble); - if (!(preamble_flags & MOO_METHOD_PREAMBLE_FLAG_VARIADIC)) + /* do nothing - no argument check */ + } + else if (preamble_flags & MOO_METHOD_PREAMBLE_FLAG_VARIADIC) + { + if (nargs < MOO_OOP_TO_SMOOI(method->tmpr_nargs)) goto arg_count_mismatch; + } + else + { + if (nargs != MOO_OOP_TO_SMOOI(method->tmpr_nargs)) { /* TODO: better to throw a moo exception so that the caller can catch it??? */ + arg_count_mismatch: MOO_LOG3 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Fatal error - Argument count mismatch for a non-variadic method [%O] - %zd expected, %zu given\n", method->name, MOO_OOP_TO_SMOOI(method->tmpr_nargs), nargs); diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 08aedf2..1710956 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -596,6 +596,7 @@ struct moo_method_t /* preamble flags */ #define MOO_METHOD_PREAMBLE_FLAG_VARIADIC (1 << 0) +#define MOO_METHOD_PREAMBLE_FLAG_LIBERAL (1 << 1) /* NOTE: if you change the number of instance variables for moo_context_t, * you need to change the defintion of BlockContext and MethodContext.