finished the initial variadic arguments handling work
This commit is contained in:
parent
bcaf4e5e1e
commit
45694df56b
@ -88,19 +88,29 @@ block context...
|
||||
^self.method
|
||||
}
|
||||
|
||||
#method varArgCount
|
||||
#method vargCount
|
||||
{
|
||||
^self basicSize - self class specNumInstVars - self.ntmprs
|
||||
}
|
||||
|
||||
#method vargAt: index
|
||||
{
|
||||
^self basicAt: (index + self class specNumInstVars + self.ntmprs)
|
||||
}
|
||||
}
|
||||
|
||||
#class(#pointer) BlockContext(Context)
|
||||
{
|
||||
#dcl nargs source home origin.
|
||||
|
||||
#method varArgCount
|
||||
#method vargCount
|
||||
{
|
||||
^self.home varArgCount
|
||||
^self.home vargCount
|
||||
}
|
||||
|
||||
#method vargAt: index
|
||||
{
|
||||
^self.home vargAt: index
|
||||
}
|
||||
|
||||
#method fork
|
||||
|
@ -146,10 +146,36 @@ procecure call is treated as if it is a unary message...
|
||||
'Beautiful life' dump.
|
||||
].
|
||||
|
||||
thisContext varArgCount dump.
|
||||
thisContext varArgCount (10, 20) dump.
|
||||
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.
|
||||
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
|
||||
|
@ -2573,12 +2573,11 @@ static int compile_unary_method_name (stix_t* stix)
|
||||
/* this is a procedural style method */
|
||||
STIX_ASSERT (stix->c->mth.tmpr_nargs == 0);
|
||||
|
||||
GET_TOKEN (stix);
|
||||
if (TOKEN_TYPE(stix) != STIX_IOTOK_RPAREN)
|
||||
{
|
||||
do
|
||||
{
|
||||
GET_TOKEN (stix);
|
||||
|
||||
if (TOKEN_TYPE(stix) != STIX_IOTOK_IDENT)
|
||||
{
|
||||
/* 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;
|
||||
stix->c->mth.tmpr_nargs++;
|
||||
|
||||
GET_TOKEN (stix);
|
||||
|
||||
if (TOKEN_TYPE(stix) == STIX_IOTOK_RPAREN) break;
|
||||
|
||||
if (TOKEN_TYPE(stix) != STIX_IOTOK_COMMA)
|
||||
@ -2604,12 +2603,13 @@ static int compile_unary_method_name (stix_t* stix)
|
||||
return -1;
|
||||
}
|
||||
|
||||
GET_TOKEN (stix);
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@ -4490,9 +4490,8 @@ static int add_compiled_method (stix_t* stix)
|
||||
preamble_index = 0;
|
||||
}
|
||||
|
||||
|
||||
if (stix->c->mth.parunary /*&& stix->c->mth.tmpr_nargs > 0*/)
|
||||
preamble_flags |= STIX_METHOD_PREAMBLE_FLAG_PARUNARY;
|
||||
if (stix->c->mth.variadic /*&& stix->c->mth.tmpr_nargs > 0*/)
|
||||
preamble_flags |= STIX_METHOD_PREAMBLE_FLAG_VARIADIC;
|
||||
|
||||
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.name.len = 0;
|
||||
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.tmpr_count = 0;
|
||||
stix->c->mth.tmpr_nargs = 0;
|
||||
|
@ -887,11 +887,11 @@ static stix_oop_process_t start_initial_process (stix_t* stix, stix_oop_context_
|
||||
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_ooi_t i;
|
||||
stix_ooi_t ntmprs, nargs;
|
||||
stix_ooi_t i, j;
|
||||
stix_ooi_t ntmprs, nargs, actual_ntmprs;
|
||||
|
||||
ntmprs = STIX_OOP_TO_SMOOI(mth->tmpr_count);
|
||||
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 (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);
|
||||
/* TODO: check if the method is pused some extra arguments... */
|
||||
ctx = (stix_oop_context_t)stix_instantiate (stix, stix->_method_context, STIX_NULL, ntmprs);
|
||||
ctx = (stix_oop_context_t)stix_instantiate (stix, stix->_method_context, STIX_NULL, actual_ntmprs);
|
||||
stix_poptmp (stix);
|
||||
if (!ctx) return -1;
|
||||
|
||||
@ -955,11 +963,30 @@ 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
|
||||
* the receiver. When the stack is empty, sp is -1.
|
||||
*/
|
||||
for (i = nargs; i > 0; )
|
||||
if (actual_nargs >= nargs)
|
||||
{
|
||||
/* copy argument */
|
||||
ctx->slot[--i] = STIX_STACK_GETTOP (stix);
|
||||
STIX_STACK_POP (stix);
|
||||
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);
|
||||
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 */
|
||||
ctx->receiver_or_source = STIX_STACK_GETTOP (stix);
|
||||
@ -1140,7 +1167,7 @@ TODO: overcome this problem
|
||||
STIX_ASSERT (stix->active_context == ctx);
|
||||
|
||||
/* 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 */
|
||||
#endif
|
||||
|
||||
preamble = STIX_OOP_TO_SMOOI(method->preamble);
|
||||
|
||||
/*STIX_ASSERT (STIX_OOP_TO_SMOOI(method->tmpr_nargs) == nargs);*/
|
||||
if (nargs != STIX_OOP_TO_SMOOI(method->tmpr_nargs))
|
||||
{
|
||||
/* TODO: throw exception??? */
|
||||
STIX_DEBUG1 (stix, "Argument count mismatch [%O]\n", method->name);
|
||||
stix->errnum = STIX_EINVAL;
|
||||
return -1;
|
||||
|
||||
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;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
preamble = STIX_OOP_TO_SMOOI(method->preamble);
|
||||
preamble_code = STIX_METHOD_GET_PREAMBLE_CODE(preamble);
|
||||
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 */
|
||||
if (activate_new_method (stix, method) <= -1) return -1;
|
||||
if (activate_new_method (stix, method, nargs) <= -1) return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2914,6 +2951,12 @@ static int start_method (stix_t* stix, stix_oop_method_t method, stix_oow_t narg
|
||||
|
||||
exec_handler:
|
||||
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);
|
||||
|
||||
stix_poptmp (stix);
|
||||
@ -2950,7 +2993,7 @@ static int start_method (stix_t* stix, stix_oop_method_t method, stix_oow_t narg
|
||||
}
|
||||
else
|
||||
{
|
||||
if (activate_new_method (stix, method) <= -1) return -1;
|
||||
if (activate_new_method (stix, method, nargs) <= -1) return -1;
|
||||
}
|
||||
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 ||
|
||||
preamble_code == STIX_METHOD_PREAMBLE_EXCEPTION ||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -544,7 +544,7 @@ struct stix_compiler_t
|
||||
stix_ioloc_t name_loc;
|
||||
|
||||
/* is the unary method followed by parameter list? */
|
||||
int parunary;
|
||||
int variadic;
|
||||
|
||||
/* single string containing a space separated list of temporaries */
|
||||
stix_oocs_t tmprs;
|
||||
|
@ -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 */
|
||||
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 */
|
||||
|
||||
@ -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_ooi_t arg_count = 0;
|
||||
stix_oocs_t cs;
|
||||
stix_ooi_t preamble_flags = 0;
|
||||
static stix_ooch_t dot[] = { '.', '\0' };
|
||||
|
||||
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++)
|
||||
{
|
||||
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... */
|
||||
/* 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] != ':')
|
||||
{
|
||||
oops_inval:
|
||||
STIX_DEBUG2 (stix, "Cannot generate primitive function method [%S] in [%O] - invalid name\n", mthname, cls->name);
|
||||
stix->errnum = STIX_EINVAL;
|
||||
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 */
|
||||
mth->owner = cls;
|
||||
mth->name = mnsym;
|
||||
/* TODO: premable flag -> VARIADIC, PARUNARY??? */
|
||||
mth->preamble = STIX_SMOOI_TO_OOP(STIX_METHOD_MAKE_PREAMBLE(STIX_METHOD_PREAMBLE_NAMED_PRIMITIVE, 0, 0));
|
||||
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, preamble_flags));
|
||||
mth->preamble_data[0] = 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_nargs = STIX_SMOOI_TO_OOP(arg_count);
|
||||
|
||||
|
||||
|
||||
/* TODO: emit BCODE_RETURN_NIL ? */
|
||||
|
||||
if (!stix_putatdic (stix, cls->mthdic[type], (stix_oop_t)mnsym, (stix_oop_t)mth))
|
||||
|
@ -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)
|
||||
|
||||
/* preamble flags */
|
||||
#define STIX_METHOD_PREAMBLE_FLAG_PARUNARY (1 << 0)
|
||||
#define STIX_METHOD_PREAMBLE_FLAG_VARIADIC (1 << 1)
|
||||
#define STIX_METHOD_PREAMBLE_FLAG_VARIADIC (1 << 0)
|
||||
|
||||
#define STIX_CONTEXT_NAMED_INSTVARS 8
|
||||
typedef struct stix_context_t stix_context_t;
|
||||
@ -1208,6 +1207,7 @@ STIX_EXPORT int stix_genpfmethod (
|
||||
stix_oop_t _class,
|
||||
stix_method_type_t type,
|
||||
const stix_ooch_t* mthname,
|
||||
int variadic,
|
||||
const stix_ooch_t* name
|
||||
);
|
||||
|
||||
|
@ -126,16 +126,17 @@ struct fnctab_t
|
||||
{
|
||||
const stix_bch_t* mthname;
|
||||
const stix_bch_t* pfname;
|
||||
int variadic;
|
||||
stix_pfimpl_t handler;
|
||||
};
|
||||
|
||||
static fnctab_t fnctab[] =
|
||||
{
|
||||
{ "_newInstSize", STIX_NULL, pf_newinstsize },
|
||||
{ "close", STIX_NULL, pf_close },
|
||||
{ "gets", STIX_NULL, pf_gets },
|
||||
{ "open:for:", STIX_NULL, pf_open },
|
||||
{ "puts", STIX_NULL, pf_puts }
|
||||
{ "_newInstSize", STIX_NULL, 0, pf_newinstsize },
|
||||
{ "close", STIX_NULL, 0, pf_close },
|
||||
{ "gets", STIX_NULL, 0, pf_gets },
|
||||
{ "open:for:", STIX_NULL, 0, pf_open },
|
||||
{ "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)
|
||||
{
|
||||
stix_pushtmp (stix, &_class);
|
||||
stix_genpfmethod (stix, mod, _class, STIX_METHOD_CLASS, voca_newInstSize, STIX_NULL);
|
||||
stix_genpfmethod (stix, mod, _class, STIX_METHOD_INSTANCE, voca_open_for, STIX_NULL);
|
||||
stix_genpfmethod (stix, mod, _class, STIX_METHOD_INSTANCE, voca_close, voca_close);
|
||||
stix_genpfmethod (stix, mod, _class, STIX_METHOD_CLASS, voca_newInstSize, 0, 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, 0, voca_close);
|
||||
stix_poptmp (stix);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user