enhancing the compiler to support the variable argument list with the ellipsis
This commit is contained in:
parent
44d2c067e1
commit
01719d0056
@ -67,6 +67,11 @@ hcl_cnode_t* hcl_makecnodefalse (hcl_t* hcl, const hcl_ioloc_t* loc, const hcl_
|
||||
return make_cnode(hcl, HCL_CNODE_FALSE, loc, tok);
|
||||
}
|
||||
|
||||
hcl_cnode_t* hcl_makecnodeellipsis (hcl_t* hcl, const hcl_ioloc_t* loc, const hcl_oocs_t* tok)
|
||||
{
|
||||
return make_cnode(hcl, HCL_CNODE_ELLIPSIS, loc, tok);
|
||||
}
|
||||
|
||||
hcl_cnode_t* hcl_makecnodecharlit (hcl_t* hcl, const hcl_ioloc_t* loc, const hcl_oocs_t* tok, const hcl_ooch_t v)
|
||||
{
|
||||
hcl_cnode_t* c = make_cnode(hcl, HCL_CNODE_CHARLIT, loc, tok);
|
||||
|
20
lib/comp.c
20
lib/comp.c
@ -751,7 +751,7 @@ static void pop_fnblk (hcl_t* hcl)
|
||||
{
|
||||
hcl_oow_t tmpr_mask;
|
||||
|
||||
/* patch the temporary mask parameter for the MAKE_BLOCK or MAKE_FUNCTION instruction */
|
||||
/* patch the temporaries mask parameter for the MAKE_BLOCK or MAKE_FUNCTION instruction */
|
||||
HCL_ASSERT (hcl, hcl->code.bc.ptr[fbi->make_inst_pos] == HCL_CODE_MAKE_BLOCK ||
|
||||
hcl->code.bc.ptr[fbi->make_inst_pos] == HCL_CODE_MAKE_FUNCTION);
|
||||
|
||||
@ -759,6 +759,8 @@ static void pop_fnblk (hcl_t* hcl)
|
||||
* the number of arguments, return variables and local variables */
|
||||
HCL_ASSERT (hcl, fbi->tmprcnt - hcl->c->tv.wcount == fbi->tmpr_nargs + fbi->tmpr_nrvars + fbi->tmpr_nlvars);
|
||||
|
||||
/* the temporaries mask is a bit-mask that encodes the counts of different temporary variables.
|
||||
* and it's split to two intruction parameters when used with MAKE_BLOCK and MAKE_FUNCTION */
|
||||
tmpr_mask = ENCODE_BLKTMPR_MASK(fbi->tmpr_va, fbi->tmpr_nargs, fbi->tmpr_nrvars, fbi->tmpr_nlvars);
|
||||
patch_double_long_params_with_oow (hcl, fbi->make_inst_pos + 1, tmpr_mask);
|
||||
}
|
||||
@ -1641,7 +1643,7 @@ static int collect_local_vardcl (hcl_t* hcl, hcl_cnode_t* obj, hcl_cnode_t** nex
|
||||
static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
|
||||
{
|
||||
hcl_cnode_t* cmd, * obj, * args;
|
||||
hcl_oow_t nargs, nrvars, nlvars;
|
||||
hcl_oow_t va, nargs, nrvars, nlvars;
|
||||
hcl_ooi_t jump_inst_pos, lfbase_pos, lfsize_pos;
|
||||
hcl_oow_t saved_tv_wcount, tv_dup_start;
|
||||
hcl_cnode_t* defun_name;
|
||||
@ -1701,6 +1703,7 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
|
||||
}
|
||||
|
||||
/* process the argument list */
|
||||
va = 0;
|
||||
args = HCL_CNODE_CONS_CAR(obj);
|
||||
HCL_ASSERT (hcl, args != HCL_NULL);
|
||||
if (HCL_CNODE_IS_ELIST_CONCODED(args, HCL_CONCODE_XLIST))
|
||||
@ -1723,9 +1726,10 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
|
||||
do
|
||||
{
|
||||
arg = HCL_CNODE_CONS_CAR(dcl);
|
||||
if (HCL_CNODE_IS_CONS(arg))
|
||||
if (HCL_CNODE_IS_ELLIPSIS(arg))
|
||||
{
|
||||
|
||||
va = 1;
|
||||
break;
|
||||
}
|
||||
else if (!HCL_CNODE_IS_SYMBOL(arg))
|
||||
{
|
||||
@ -1792,7 +1796,7 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
|
||||
|
||||
HCL_ASSERT (hcl, nargs + nrvars + nlvars == hcl->c->tv.wcount - saved_tv_wcount);
|
||||
|
||||
if (push_fnblk(hcl, HCL_CNODE_GET_LOC(src), 0, nargs, nrvars, nlvars, hcl->c->tv.wcount, hcl->c->tv.s.len, hcl->code.bc.len, hcl->code.lit.len) <= -1) return -1;
|
||||
if (push_fnblk(hcl, HCL_CNODE_GET_LOC(src), va, nargs, nrvars, nlvars, hcl->c->tv.wcount, hcl->c->tv.s.len, hcl->code.bc.len, hcl->code.lit.len) <= -1) return -1;
|
||||
|
||||
if (hcl->option.trait & HCL_TRAIT_INTERACTIVE)
|
||||
{
|
||||
@ -2880,7 +2884,7 @@ redo:
|
||||
goto done;
|
||||
|
||||
case HCL_CONCODE_VLIST:
|
||||
hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARDCLBANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "variable declaration disallowed");
|
||||
hcl_setsynerrbfmt (hcl, HCL_SYNERR_ELLIPSISBANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "variable declaration disallowed");
|
||||
return -1;
|
||||
|
||||
default:
|
||||
@ -2896,6 +2900,10 @@ redo:
|
||||
oprnd = oprnd->u.shell.obj;
|
||||
goto redo;
|
||||
|
||||
case HCL_CNODE_ELLIPSIS:
|
||||
hcl_setsynerrbfmt (hcl, HCL_SYNERR_INTERN, HCL_CNODE_GET_LOC(oprnd), HCL_CNODE_GET_TOK(oprnd), "ellipsis disallowed in this context", HCL_CNODE_GET_TYPE(oprnd));
|
||||
return -1;
|
||||
|
||||
default:
|
||||
hcl_setsynerrbfmt (hcl, HCL_SYNERR_INTERN, HCL_CNODE_GET_LOC(oprnd), HCL_CNODE_GET_TOK(oprnd), "internal error - unexpected object type %d", HCL_CNODE_GET_TYPE(oprnd));
|
||||
return -1;
|
||||
|
@ -125,6 +125,7 @@ static char* synerrstr[] =
|
||||
"no separator between array/dictionary elements",
|
||||
"#include error",
|
||||
|
||||
"... disallowed",
|
||||
"loop body too big",
|
||||
"if body too big",
|
||||
"lambda block too big",
|
||||
|
@ -148,6 +148,7 @@ enum hcl_iotok_type_t
|
||||
HCL_IOTOK_IDENT,
|
||||
HCL_IOTOK_IDENT_DOTTED,
|
||||
HCL_IOTOK_DOT,
|
||||
HCL_IOTOK_ELLIPSIS,
|
||||
HCL_IOTOK_COLON,
|
||||
HCL_IOTOK_COMMA,
|
||||
HCL_IOTOK_LPAREN,
|
||||
@ -195,6 +196,7 @@ enum hcl_cnode_type_t
|
||||
HCL_CNODE_NIL,
|
||||
HCL_CNODE_TRUE,
|
||||
HCL_CNODE_FALSE,
|
||||
HCL_CNODE_ELLIPSIS,
|
||||
|
||||
HCL_CNODE_CONS,
|
||||
HCL_CNODE_ELIST, /* empty list */
|
||||
@ -208,6 +210,8 @@ typedef enum hcl_cnode_type_t hcl_cnode_type_t;
|
||||
#define HCL_CNODE_GET_TOKPTR(x) ((x)->cn_tok.ptr)
|
||||
#define HCL_CNODE_GET_TOKLEN(x) ((x)->cn_tok.len)
|
||||
|
||||
#define HCL_CNODE_IS_ELLIPSIS(x) ((x)->cn_type == HCL_CNODE_ELLIPSIS)
|
||||
|
||||
#define HCL_CNODE_IS_SYMBOL(x) ((x)->cn_type == HCL_CNODE_SYMBOL)
|
||||
#define HCL_CNODE_IS_SYMBOL_SYNCODED(x, code) ((x)->cn_type == HCL_CNODE_SYMBOL && (x)->u.symbol.syncode == (code))
|
||||
#define HCL_CNODE_SYMBOL_SYNCODE(x) ((x)->u.symbol.syncode)
|
||||
@ -220,7 +224,6 @@ typedef enum hcl_cnode_type_t hcl_cnode_type_t;
|
||||
#define HCL_CNODE_CONS_CAR(x) ((x)->u.cons.car)
|
||||
#define HCL_CNODE_CONS_CDR(x) ((x)->u.cons.cdr)
|
||||
|
||||
|
||||
#define HCL_CNODE_IS_ELIST(x) ((x)->cn_type == HCL_CNODE_ELIST)
|
||||
#define HCL_CNODE_IS_ELIST_CONCODED(x, code) ((x)->cn_type == HCL_CNODE_ELIST && (x)->u.elist.concode == (code))
|
||||
#define HCL_CNODE_ELIST_CONCODE(x) ((x)->u.elist.concode)
|
||||
@ -1404,6 +1407,7 @@ int hcl_emitbyteinstruction (
|
||||
hcl_cnode_t* hcl_makecnodenil (hcl_t* hcl, const hcl_ioloc_t* loc, const hcl_oocs_t* tok);
|
||||
hcl_cnode_t* hcl_makecnodetrue (hcl_t* hcl, const hcl_ioloc_t* loc, const hcl_oocs_t* tok);
|
||||
hcl_cnode_t* hcl_makecnodefalse (hcl_t* hcl, const hcl_ioloc_t* loc, const hcl_oocs_t* tok);
|
||||
hcl_cnode_t* hcl_makecnodeellipsis (hcl_t* hcl, const hcl_ioloc_t* loc, const hcl_oocs_t* tok);
|
||||
hcl_cnode_t* hcl_makecnodecharlit (hcl_t* hcl, const hcl_ioloc_t* loc, const hcl_oocs_t* tok, const hcl_ooch_t v);
|
||||
hcl_cnode_t* hcl_makecnodesymbol (hcl_t* hcl, const hcl_ioloc_t* loc, const hcl_oocs_t* tok);
|
||||
hcl_cnode_t* hcl_makecnodedsymbol (hcl_t* hcl, const hcl_ioloc_t* loc, const hcl_oocs_t* tok);
|
||||
|
@ -131,6 +131,7 @@ enum hcl_synerrnum_t
|
||||
HCL_SYNERR_NOSEP, /* no seperator between array/dictionary elements */
|
||||
HCL_SYNERR_INCLUDE, /* #include error */
|
||||
|
||||
HCL_SYNERR_ELLIPSISBANNED, /* ... disallowed */
|
||||
HCL_SYNERR_LOOPFLOOD, /* loop body too big */
|
||||
HCL_SYNERR_IFFLOOD, /* if body too big */
|
||||
HCL_SYNERR_BLKFLOOD, /* lambda block too big */
|
||||
|
34
lib/read.c
34
lib/read.c
@ -1078,6 +1078,35 @@ retry:
|
||||
break;
|
||||
|
||||
case '.':
|
||||
oldc = c;
|
||||
GET_CHAR_TO (hcl, c);
|
||||
if(c == '.')
|
||||
{
|
||||
hcl_iolxc_t sd;
|
||||
hcl_ooci_t oldc2;
|
||||
|
||||
sd = hcl->c->lxc; /* back up '#' */
|
||||
|
||||
oldc2 = c;
|
||||
GET_CHAR_TO (hcl, c);
|
||||
if (c == '.')
|
||||
{
|
||||
SET_TOKEN_TYPE (hcl, HCL_IOTOK_ELLIPSIS);
|
||||
ADD_TOKEN_CHAR (hcl, oldc);
|
||||
ADD_TOKEN_CHAR (hcl, oldc2);
|
||||
ADD_TOKEN_CHAR (hcl, c);
|
||||
break;
|
||||
}
|
||||
|
||||
unget_char (hcl, &hcl->c->lxc);
|
||||
unget_char (hcl, &sd);
|
||||
}
|
||||
else
|
||||
{
|
||||
unget_char (hcl, &hcl->c->lxc);
|
||||
}
|
||||
c = oldc;
|
||||
|
||||
SET_TOKEN_TYPE (hcl, HCL_IOTOK_DOT);
|
||||
ADD_TOKEN_CHAR (hcl, c);
|
||||
break;
|
||||
@ -1910,6 +1939,10 @@ static hcl_cnode_t* read_object (hcl_t* hcl)
|
||||
obj = hcl_makecnodefalse(hcl, TOKEN_LOC(hcl), TOKEN_NAME(hcl));
|
||||
break;
|
||||
|
||||
case HCL_IOTOK_ELLIPSIS:
|
||||
obj = hcl_makecnodeellipsis(hcl, TOKEN_LOC(hcl), TOKEN_NAME(hcl));
|
||||
break;
|
||||
|
||||
case HCL_IOTOK_SMPTRLIT:
|
||||
{
|
||||
hcl_oow_t i;
|
||||
@ -1987,6 +2020,7 @@ static hcl_cnode_t* read_object (hcl_t* hcl)
|
||||
case HCL_IOTOK_IDENT_DOTTED:
|
||||
obj = hcl_makecnodedsymbol(hcl, TOKEN_LOC(hcl), TOKEN_NAME(hcl));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (!obj) goto oops;
|
||||
|
Loading…
Reference in New Issue
Block a user