finished the initial variadic arguments handling work

This commit is contained in:
hyunghwan.chung 2016-12-14 07:18:01 +00:00
parent bcaf4e5e1e
commit 45694df56b
8 changed files with 134 additions and 51 deletions

View File

@ -88,19 +88,29 @@ block context...
^self.method ^self.method
} }
#method varArgCount #method vargCount
{ {
^self basicSize - self class specNumInstVars - self.ntmprs ^self basicSize - self class specNumInstVars - self.ntmprs
} }
#method vargAt: index
{
^self basicAt: (index + self class specNumInstVars + self.ntmprs)
}
} }
#class(#pointer) BlockContext(Context) #class(#pointer) BlockContext(Context)
{ {
#dcl nargs source home origin. #dcl nargs source home origin.
#method varArgCount #method vargCount
{ {
^self.home varArgCount ^self.home vargCount
}
#method vargAt: index
{
^self.home vargAt: index
} }
#method fork #method fork

View File

@ -146,10 +146,36 @@ procecure call is treated as if it is a unary message...
'Beautiful life' dump. 'Beautiful life' dump.
]. ].
thisContext varArgCount dump. self varg_test (10, 20, 30, 40, 50) dump.
thisContext varArgCount (10, 20) dump. self varg_test2 (10, 20, 30, 40, 50) dump.
self varg_test3 (10, 20, 30, 40, 50) dump.
thisContext vargCount dump.
thisContext vargCount dump.
} }
#method(#class) varg_test()
{
0 to: (thisContext vargCount - 1) do: [:k |
(thisContext vargAt: k) dump.
].
^999
}
#method(#class) varg_test2(a,b,c)
{
0 to: (thisContext vargCount - 1) do: [:k |
(thisContext vargAt: k) dump.
].
^a
}
#method(#class) varg_test3(a,b,c,d,e,f)
{
0 to: (thisContext vargCount - 1) do: [:k |
(thisContext vargAt: k) dump.
].
## ^b * 100
^f
}
} }
#extend MyObject #extend MyObject

View File

@ -2573,12 +2573,11 @@ static int compile_unary_method_name (stix_t* stix)
/* this is a procedural style method */ /* this is a procedural style method */
STIX_ASSERT (stix->c->mth.tmpr_nargs == 0); STIX_ASSERT (stix->c->mth.tmpr_nargs == 0);
GET_TOKEN (stix);
if (TOKEN_TYPE(stix) != STIX_IOTOK_RPAREN) if (TOKEN_TYPE(stix) != STIX_IOTOK_RPAREN)
{ {
do do
{ {
GET_TOKEN (stix);
if (TOKEN_TYPE(stix) != STIX_IOTOK_IDENT) if (TOKEN_TYPE(stix) != STIX_IOTOK_IDENT)
{ {
/* wrong argument name. identifier is expected */ /* wrong argument name. identifier is expected */
@ -2594,8 +2593,8 @@ static int compile_unary_method_name (stix_t* stix)
if (add_temporary_variable(stix, TOKEN_NAME(stix)) <= -1) return -1; if (add_temporary_variable(stix, TOKEN_NAME(stix)) <= -1) return -1;
stix->c->mth.tmpr_nargs++; stix->c->mth.tmpr_nargs++;
GET_TOKEN (stix); GET_TOKEN (stix);
if (TOKEN_TYPE(stix) == STIX_IOTOK_RPAREN) break; if (TOKEN_TYPE(stix) == STIX_IOTOK_RPAREN) break;
if (TOKEN_TYPE(stix) != STIX_IOTOK_COMMA) if (TOKEN_TYPE(stix) != STIX_IOTOK_COMMA)
@ -2604,12 +2603,13 @@ static int compile_unary_method_name (stix_t* stix)
return -1; return -1;
} }
GET_TOKEN (stix);
} }
while (1); while (1);
} }
/* indicate that the unary method name is followed by a parameter list */ /* indicate that the unary method name is followed by a parameter list */
stix->c->mth.parunary = 1; stix->c->mth.variadic = 1;
GET_TOKEN (stix); GET_TOKEN (stix);
} }
@ -4490,9 +4490,8 @@ static int add_compiled_method (stix_t* stix)
preamble_index = 0; preamble_index = 0;
} }
if (stix->c->mth.variadic /*&& stix->c->mth.tmpr_nargs > 0*/)
if (stix->c->mth.parunary /*&& stix->c->mth.tmpr_nargs > 0*/) preamble_flags |= STIX_METHOD_PREAMBLE_FLAG_VARIADIC;
preamble_flags |= STIX_METHOD_PREAMBLE_FLAG_PARUNARY;
STIX_ASSERT (STIX_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(preamble_index)); STIX_ASSERT (STIX_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(preamble_index));
@ -4544,7 +4543,7 @@ static int compile_method_definition (stix_t* stix)
stix->c->mth.kwsels.len = 0; stix->c->mth.kwsels.len = 0;
stix->c->mth.name.len = 0; stix->c->mth.name.len = 0;
STIX_MEMSET (&stix->c->mth.name_loc, 0, STIX_SIZEOF(stix->c->mth.name_loc)); STIX_MEMSET (&stix->c->mth.name_loc, 0, STIX_SIZEOF(stix->c->mth.name_loc));
stix->c->mth.parunary = 0; stix->c->mth.variadic = 0;
stix->c->mth.tmprs.len = 0; stix->c->mth.tmprs.len = 0;
stix->c->mth.tmpr_count = 0; stix->c->mth.tmpr_count = 0;
stix->c->mth.tmpr_nargs = 0; stix->c->mth.tmpr_nargs = 0;

View File

@ -887,11 +887,11 @@ static stix_oop_process_t start_initial_process (stix_t* stix, stix_oop_context_
return proc; return proc;
} }
static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth) static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth, stix_ooi_t actual_nargs)
{ {
stix_oop_context_t ctx; stix_oop_context_t ctx;
stix_ooi_t i; stix_ooi_t i, j;
stix_ooi_t ntmprs, nargs; stix_ooi_t ntmprs, nargs, actual_ntmprs;
ntmprs = STIX_OOP_TO_SMOOI(mth->tmpr_count); ntmprs = STIX_OOP_TO_SMOOI(mth->tmpr_count);
nargs = STIX_OOP_TO_SMOOI(mth->tmpr_nargs); nargs = STIX_OOP_TO_SMOOI(mth->tmpr_nargs);
@ -899,9 +899,17 @@ static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth)
STIX_ASSERT (ntmprs >= 0); STIX_ASSERT (ntmprs >= 0);
STIX_ASSERT (nargs <= ntmprs); STIX_ASSERT (nargs <= ntmprs);
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 */
STIX_ASSERT (STIX_METHOD_GET_PREAMBLE_FLAGS(STIX_OOP_TO_SMOOI(mth->preamble)) & STIX_METHOD_PREAMBLE_FLAG_VARIADIC);
actual_ntmprs = ntmprs + (actual_nargs - nargs);
}
else actual_ntmprs = ntmprs;
stix_pushtmp (stix, (stix_oop_t*)&mth); stix_pushtmp (stix, (stix_oop_t*)&mth);
/* TODO: check if the method is pused some extra arguments... */ ctx = (stix_oop_context_t)stix_instantiate (stix, stix->_method_context, STIX_NULL, actual_ntmprs);
ctx = (stix_oop_context_t)stix_instantiate (stix, stix->_method_context, STIX_NULL, ntmprs);
stix_poptmp (stix); stix_poptmp (stix);
if (!ctx) return -1; if (!ctx) return -1;
@ -955,12 +963,31 @@ static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth)
* Since the number of arguments is 3, stack[sp - 3] points to * Since the number of arguments is 3, stack[sp - 3] points to
* the receiver. When the stack is empty, sp is -1. * the receiver. When the stack is empty, sp is -1.
*/ */
for (i = nargs; i > 0; ) if (actual_nargs >= nargs)
{ {
/* copy argument */ for (i = actual_nargs, j = ntmprs + (actual_nargs - nargs); i > nargs; i--)
{
/* place variadic arguments after local temporaries */
ctx->slot[--j] = STIX_STACK_GETTOP (stix);
STIX_STACK_POP (stix);
}
STIX_ASSERT (i == nargs);
while (i > 0)
{
/* place normal argument before local temporaries */
ctx->slot[--i] = STIX_STACK_GETTOP (stix); ctx->slot[--i] = STIX_STACK_GETTOP (stix);
STIX_STACK_POP (stix); STIX_STACK_POP (stix);
} }
}
else
{
for (i = actual_nargs; i > 0; )
{
/* place normal argument before local temporaries */
ctx->slot[--i] = STIX_STACK_GETTOP (stix);
STIX_STACK_POP (stix);
}
}
/* copy receiver */ /* copy receiver */
ctx->receiver_or_source = STIX_STACK_GETTOP (stix); ctx->receiver_or_source = STIX_STACK_GETTOP (stix);
STIX_STACK_POP (stix); STIX_STACK_POP (stix);
@ -1140,7 +1167,7 @@ TODO: overcome this problem
STIX_ASSERT (stix->active_context == ctx); STIX_ASSERT (stix->active_context == ctx);
/* emulate the message sending */ /* emulate the message sending */
return activate_new_method (stix, mth); return activate_new_method (stix, mth, 0);
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@ -2765,16 +2792,26 @@ static int start_method (stix_t* stix, stix_oop_method_t method, stix_oow_t narg
stix_ooi_t fetched_instruction_pointer = 0; /* set it to a fake value */ stix_ooi_t fetched_instruction_pointer = 0; /* set it to a fake value */
#endif #endif
preamble = STIX_OOP_TO_SMOOI(method->preamble);
/*STIX_ASSERT (STIX_OOP_TO_SMOOI(method->tmpr_nargs) == nargs);*/ /*STIX_ASSERT (STIX_OOP_TO_SMOOI(method->tmpr_nargs) == nargs);*/
if (nargs != STIX_OOP_TO_SMOOI(method->tmpr_nargs)) if (nargs != STIX_OOP_TO_SMOOI(method->tmpr_nargs))
{ {
/* TODO: throw exception??? */
STIX_DEBUG1 (stix, "Argument count mismatch [%O]\n", method->name); stix_ooi_t preamble_flags;
preamble_flags = STIX_METHOD_GET_PREAMBLE_FLAGS(preamble);
if (!(preamble_flags & STIX_METHOD_PREAMBLE_FLAG_VARIADIC))
{
/* TODO: better to throw a stix exception so that the caller can catch it??? */
STIX_LOG3 (stix, STIX_LOG_IC | STIX_LOG_FATAL,
"Fatal error - Argument count mismatch for a non-variadic method [%O] - %zd expected, %zu given\n",
method->name, STIX_OOP_TO_SMOOI(method->tmpr_nargs), nargs);
stix->errnum = STIX_EINVAL; stix->errnum = STIX_EINVAL;
return -1; return -1;
} }
}
preamble = STIX_OOP_TO_SMOOI(method->preamble);
preamble_code = STIX_METHOD_GET_PREAMBLE_CODE(preamble); preamble_code = STIX_METHOD_GET_PREAMBLE_CODE(preamble);
switch (preamble_code) switch (preamble_code)
{ {
@ -2868,7 +2905,7 @@ static int start_method (stix_t* stix, stix_oop_method_t method, stix_oow_t narg
} }
/* soft primitive failure */ /* soft primitive failure */
if (activate_new_method (stix, method) <= -1) return -1; if (activate_new_method (stix, method, nargs) <= -1) return -1;
break; break;
} }
@ -2914,6 +2951,12 @@ static int start_method (stix_t* stix, stix_oop_method_t method, stix_oow_t narg
exec_handler: exec_handler:
stix_pushtmp (stix, (stix_oop_t*)&method); stix_pushtmp (stix, (stix_oop_t*)&method);
/* the primitive handler is executed without activating the method itself.
* one major difference between the primitive function and the normal method
* invocation is that the primitive function handler should access arguments
* directly in the stack unlik a normal activated method context where the
* arguments are copied to the back. */
n = handler (stix, nargs); n = handler (stix, nargs);
stix_poptmp (stix); stix_poptmp (stix);
@ -2950,7 +2993,7 @@ static int start_method (stix_t* stix, stix_oop_method_t method, stix_oow_t narg
} }
else else
{ {
if (activate_new_method (stix, method) <= -1) return -1; if (activate_new_method (stix, method, nargs) <= -1) return -1;
} }
break; break;
} }
@ -2959,7 +3002,7 @@ static int start_method (stix_t* stix, stix_oop_method_t method, stix_oow_t narg
STIX_ASSERT (preamble_code == STIX_METHOD_PREAMBLE_NONE || STIX_ASSERT (preamble_code == STIX_METHOD_PREAMBLE_NONE ||
preamble_code == STIX_METHOD_PREAMBLE_EXCEPTION || preamble_code == STIX_METHOD_PREAMBLE_EXCEPTION ||
preamble_code == STIX_METHOD_PREAMBLE_ENSURE); preamble_code == STIX_METHOD_PREAMBLE_ENSURE);
if (activate_new_method (stix, method) <= -1) return -1; if (activate_new_method (stix, method, nargs) <= -1) return -1;
break; break;
} }

View File

@ -544,7 +544,7 @@ struct stix_compiler_t
stix_ioloc_t name_loc; stix_ioloc_t name_loc;
/* is the unary method followed by parameter list? */ /* is the unary method followed by parameter list? */
int parunary; int variadic;
/* single string containing a space separated list of temporaries */ /* single string containing a space separated list of temporaries */
stix_oocs_t tmprs; stix_oocs_t tmprs;

View File

@ -696,7 +696,7 @@ stix_pfimpl_t stix_querymod (stix_t* stix, const stix_ooch_t* pfid, stix_oow_t p
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* add a new primitive method */ /* add a new primitive method */
int stix_genpfmethod (stix_t* stix, stix_mod_t* mod, stix_oop_t _class, stix_method_type_t type, const stix_ooch_t* mthname, const stix_ooch_t* pfname) int stix_genpfmethod (stix_t* stix, stix_mod_t* mod, stix_oop_t _class, stix_method_type_t type, const stix_ooch_t* mthname, int variadic, const stix_ooch_t* pfname)
{ {
/* NOTE: this function is a subset of add_compiled_method() in comp.c */ /* NOTE: this function is a subset of add_compiled_method() in comp.c */
@ -706,6 +706,7 @@ int stix_genpfmethod (stix_t* stix, stix_mod_t* mod, stix_oop_t _class, stix_met
stix_oow_t tmp_count = 0, i; stix_oow_t tmp_count = 0, i;
stix_ooi_t arg_count = 0; stix_ooi_t arg_count = 0;
stix_oocs_t cs; stix_oocs_t cs;
stix_ooi_t preamble_flags = 0;
static stix_ooch_t dot[] = { '.', '\0' }; static stix_ooch_t dot[] = { '.', '\0' };
STIX_ASSERT (STIX_CLASSOF(stix, _class) == stix->_class); STIX_ASSERT (STIX_CLASSOF(stix, _class) == stix->_class);
@ -718,12 +719,17 @@ int stix_genpfmethod (stix_t* stix, stix_mod_t* mod, stix_oop_t _class, stix_met
for (i = 0; mthname[i]; i++) for (i = 0; mthname[i]; i++)
{ {
if (mthname[i] == ':') arg_count++; if (mthname[i] == ':')
{
if (variadic) goto oops_inval;
arg_count++;
}
} }
/* TODO: check if name is a valid method name - more checks... */ /* TODO: check if name is a valid method name - more checks... */
/* TOOD: if the method name is a binary selector, it can still have an argument.. so the check below is invalid... */ /* TOOD: if the method name is a binary selector, it can still have an argument.. so the check below is invalid... */
if (arg_count > 0 && mthname[i - 1] != ':') if (arg_count > 0 && mthname[i - 1] != ':')
{ {
oops_inval:
STIX_DEBUG2 (stix, "Cannot generate primitive function method [%S] in [%O] - invalid name\n", mthname, cls->name); STIX_DEBUG2 (stix, "Cannot generate primitive function method [%S] in [%O] - invalid name\n", mthname, cls->name);
stix->errnum = STIX_EINVAL; stix->errnum = STIX_EINVAL;
goto oops; goto oops;
@ -777,15 +783,13 @@ int stix_genpfmethod (stix_t* stix, stix_mod_t* mod, stix_oop_t _class, stix_met
/* premable should contain the index to the literal frame which is always 0 */ /* premable should contain the index to the literal frame which is always 0 */
mth->owner = cls; mth->owner = cls;
mth->name = mnsym; mth->name = mnsym;
/* TODO: premable flag -> VARIADIC, PARUNARY??? */ if (variadic) preamble_flags |= STIX_METHOD_PREAMBLE_FLAG_VARIADIC;
mth->preamble = STIX_SMOOI_TO_OOP(STIX_METHOD_MAKE_PREAMBLE(STIX_METHOD_PREAMBLE_NAMED_PRIMITIVE, 0, 0)); mth->preamble = STIX_SMOOI_TO_OOP(STIX_METHOD_MAKE_PREAMBLE(STIX_METHOD_PREAMBLE_NAMED_PRIMITIVE, 0, preamble_flags));
mth->preamble_data[0] = STIX_SMOOI_TO_OOP(0); mth->preamble_data[0] = STIX_SMOOI_TO_OOP(0);
mth->preamble_data[1] = STIX_SMOOI_TO_OOP(0); mth->preamble_data[1] = STIX_SMOOI_TO_OOP(0);
mth->tmpr_count = STIX_SMOOI_TO_OOP(arg_count); mth->tmpr_count = STIX_SMOOI_TO_OOP(arg_count);
mth->tmpr_nargs = STIX_SMOOI_TO_OOP(arg_count); mth->tmpr_nargs = STIX_SMOOI_TO_OOP(arg_count);
/* TODO: emit BCODE_RETURN_NIL ? */ /* TODO: emit BCODE_RETURN_NIL ? */
if (!stix_putatdic (stix, cls->mthdic[type], (stix_oop_t)mnsym, (stix_oop_t)mth)) if (!stix_putatdic (stix, cls->mthdic[type], (stix_oop_t)mnsym, (stix_oop_t)mth))

View File

@ -545,8 +545,7 @@ struct stix_method_t
#define STIX_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(num) ((num) >= STIX_METHOD_PREAMBLE_INDEX_MIN && (num) <= STIX_METHOD_PREAMBLE_INDEX_MAX) #define STIX_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(num) ((num) >= STIX_METHOD_PREAMBLE_INDEX_MIN && (num) <= STIX_METHOD_PREAMBLE_INDEX_MAX)
/* preamble flags */ /* preamble flags */
#define STIX_METHOD_PREAMBLE_FLAG_PARUNARY (1 << 0) #define STIX_METHOD_PREAMBLE_FLAG_VARIADIC (1 << 0)
#define STIX_METHOD_PREAMBLE_FLAG_VARIADIC (1 << 1)
#define STIX_CONTEXT_NAMED_INSTVARS 8 #define STIX_CONTEXT_NAMED_INSTVARS 8
typedef struct stix_context_t stix_context_t; typedef struct stix_context_t stix_context_t;
@ -1208,6 +1207,7 @@ STIX_EXPORT int stix_genpfmethod (
stix_oop_t _class, stix_oop_t _class,
stix_method_type_t type, stix_method_type_t type,
const stix_ooch_t* mthname, const stix_ooch_t* mthname,
int variadic,
const stix_ooch_t* name const stix_ooch_t* name
); );

View File

@ -126,16 +126,17 @@ struct fnctab_t
{ {
const stix_bch_t* mthname; const stix_bch_t* mthname;
const stix_bch_t* pfname; const stix_bch_t* pfname;
int variadic;
stix_pfimpl_t handler; stix_pfimpl_t handler;
}; };
static fnctab_t fnctab[] = static fnctab_t fnctab[] =
{ {
{ "_newInstSize", STIX_NULL, pf_newinstsize }, { "_newInstSize", STIX_NULL, 0, pf_newinstsize },
{ "close", STIX_NULL, pf_close }, { "close", STIX_NULL, 0, pf_close },
{ "gets", STIX_NULL, pf_gets }, { "gets", STIX_NULL, 0, pf_gets },
{ "open:for:", STIX_NULL, pf_open }, { "open:for:", STIX_NULL, 0, pf_open },
{ "puts", STIX_NULL, pf_puts } { "puts", STIX_NULL, 1, pf_puts }
}; };
@ -149,9 +150,9 @@ static stix_ooch_t voca_newInstSize[] = { '_','n','e','w','I','n','s','t','S','i
static int import (stix_t* stix, stix_mod_t* mod, stix_oop_t _class) static int import (stix_t* stix, stix_mod_t* mod, stix_oop_t _class)
{ {
stix_pushtmp (stix, &_class); stix_pushtmp (stix, &_class);
stix_genpfmethod (stix, mod, _class, STIX_METHOD_CLASS, voca_newInstSize, STIX_NULL); stix_genpfmethod (stix, mod, _class, STIX_METHOD_CLASS, voca_newInstSize, 0, STIX_NULL);
stix_genpfmethod (stix, mod, _class, STIX_METHOD_INSTANCE, voca_open_for, STIX_NULL); stix_genpfmethod (stix, mod, _class, STIX_METHOD_INSTANCE, voca_open_for, 0, STIX_NULL);
stix_genpfmethod (stix, mod, _class, STIX_METHOD_INSTANCE, voca_close, voca_close); stix_genpfmethod (stix, mod, _class, STIX_METHOD_INSTANCE, voca_close, 0, voca_close);
stix_poptmp (stix); stix_poptmp (stix);
return 0; return 0;
} }