some more code to support multiple return values via return variables
This commit is contained in:
parent
faea7b60df
commit
550e39e21e
18
lib/comp.c
18
lib/comp.c
@ -3618,11 +3618,13 @@ static HCL_INLINE int emit_lambda (hcl_t* hcl)
|
||||
hcl_cframe_t* cf;
|
||||
hcl_oow_t block_code_size, lfsize;
|
||||
hcl_ooi_t jip;
|
||||
hcl_fnblk_info_t* fbi;
|
||||
|
||||
cf = GET_TOP_CFRAME(hcl);
|
||||
HCL_ASSERT (hcl, cf->opcode == COP_EMIT_LAMBDA);
|
||||
HCL_ASSERT (hcl, cf->operand != HCL_NULL);
|
||||
|
||||
fbi = &hcl->c->fnblk.info[hcl->c->fnblk.depth];
|
||||
jip = cf->u.lambda.jump_inst_pos;
|
||||
|
||||
if (hcl->option.trait & HCL_TRAIT_INTERACTIVE)
|
||||
@ -3631,16 +3633,30 @@ static HCL_INLINE int emit_lambda (hcl_t* hcl)
|
||||
/* HCL_CODE_LONG_PARAM_SIZE + 1 => size of the long JUMP_FORWARD instruction */
|
||||
block_code_size = hcl->code.bc.len - jip - (HCL_CODE_LONG_PARAM_SIZE + 1);
|
||||
|
||||
if (fbi->tmpr_nrvars > 0)
|
||||
{
|
||||
/* this function block defines one or more return variables */
|
||||
if (block_code_size > 0)
|
||||
{
|
||||
if (emit_byte_instruction(hcl, HCL_CODE_POP_STACKTOP, HCL_CNODE_GET_LOC(cf->operand)) <= -1) return -1;
|
||||
block_code_size++;
|
||||
}
|
||||
if (emit_byte_instruction(hcl, HCL_CODE_PUSH_RETURN_R, HCL_CNODE_GET_LOC(cf->operand)) <= -1) return -1;
|
||||
block_code_size++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (block_code_size == 0)
|
||||
{
|
||||
/* no body in lambda - (lambda (a b c)) */
|
||||
/* TODO: is this correct??? */
|
||||
/* TODO: is this correct??? */
|
||||
if (emit_byte_instruction(hcl, HCL_CODE_PUSH_NIL, HCL_CNODE_GET_LOC(cf->operand)) <= -1) return -1;
|
||||
block_code_size++;
|
||||
}
|
||||
|
||||
if (emit_byte_instruction(hcl, HCL_CODE_RETURN_FROM_BLOCK, HCL_CNODE_GET_LOC(cf->operand)) <= -1) return -1;
|
||||
block_code_size++;
|
||||
}
|
||||
|
||||
if (block_code_size > MAX_CODE_JUMP * 2)
|
||||
{
|
||||
|
@ -335,6 +335,10 @@ int hcl_decode (hcl_t* hcl, hcl_oow_t start, hcl_oow_t end)
|
||||
break;
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
case HCL_CODE_PUSH_RETURN_R:
|
||||
LOG_INST_0 (hcl, "push_return_r");
|
||||
break;
|
||||
|
||||
case HCL_CODE_CALL_R:
|
||||
FETCH_PARAM_CODE_TO (hcl, b1); /* nargs */
|
||||
FETCH_PARAM_CODE_TO (hcl, b2); /* nrvars */
|
||||
|
48
lib/exec.c
48
lib/exec.c
@ -363,7 +363,6 @@ static HCL_INLINE void fill_function_data (hcl_t* hcl, hcl_oop_function_t func,
|
||||
|
||||
/* initialize other fields */
|
||||
func->home = homectx;
|
||||
func->flags = HCL_SMOOI_TO_OOP(0);
|
||||
func->tmpr_mask = HCL_SMOOI_TO_OOP(tmpr_mask);
|
||||
}
|
||||
|
||||
@ -380,7 +379,6 @@ static HCL_INLINE void fill_block_data (hcl_t* hcl, hcl_oop_block_t blk, hcl_ooi
|
||||
|
||||
blk->home = homectx;
|
||||
blk->ip = HCL_SMOOI_TO_OOP(ip);
|
||||
blk->flags = HCL_SMOOI_TO_OOP(0);
|
||||
blk->tmpr_mask = HCL_SMOOI_TO_OOP(tmpr_mask);
|
||||
}
|
||||
|
||||
@ -1819,7 +1817,6 @@ static int prepare_new_context (hcl_t* hcl, hcl_oop_block_t rcv_blk, hcl_ooi_t n
|
||||
/* the receiver must be a block context */
|
||||
HCL_ASSERT (hcl, HCL_IS_BLOCK(hcl, rcv_blk));
|
||||
|
||||
flags = HCL_OOP_TO_SMOOI(rcv_blk->flags);
|
||||
tmpr_mask = HCL_OOP_TO_SMOOI(rcv_blk->tmpr_mask);
|
||||
|
||||
fblk_nrvars = GET_BLKTMPR_MASK_NRVARS(tmpr_mask);
|
||||
@ -1837,12 +1834,12 @@ static int prepare_new_context (hcl_t* hcl, hcl_oop_block_t rcv_blk, hcl_ooi_t n
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fblk_nrvars != req_nrvars)
|
||||
if (req_nrvars > fblk_nrvars)
|
||||
{
|
||||
HCL_LOG3 (hcl, HCL_LOG_IC | HCL_LOG_ERROR,
|
||||
"Error - wrong number of returns specified of a block %O - expected %zd, requested %zd\n",
|
||||
"Error - wrong number of returns specified of a block %O - max expected %zd, requested %zd\n",
|
||||
rcv_blk, fblk_nrvars, req_nrvars);
|
||||
hcl_seterrbfmt (hcl, HCL_ECALLRET, "wrong number of returns requested of function block - %zd expected, %zd requested", fblk_nrvars, req_nrvars);
|
||||
hcl_seterrbfmt (hcl, HCL_ECALLRET, "wrong number of returns requested of function block - %zd expected at most, %zd requested", fblk_nrvars, req_nrvars);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1860,7 +1857,7 @@ static int prepare_new_context (hcl_t* hcl, hcl_oop_block_t rcv_blk, hcl_ooi_t n
|
||||
}
|
||||
#else
|
||||
blkctx->ip = rcv_blk->ip;
|
||||
blkctx->flags = rcv_blk->flags;
|
||||
blkctx->req_nrets = HCL_SMOOI_TO_OOP(req_nrvars);
|
||||
blkctx->tmpr_mask = rcv_blk->tmpr_mask;
|
||||
blkctx->receiver_or_base = (hcl_oop_t)rcv_blk;
|
||||
blkctx->home = rcv_blk->home;
|
||||
@ -1965,7 +1962,7 @@ static int __activate_function (hcl_t* hcl, hcl_oop_function_t rcv_func, hcl_ooi
|
||||
if (HCL_UNLIKELY(!functx)) return -1;
|
||||
|
||||
functx->ip = HCL_SMOOI_TO_OOP(0);
|
||||
functx->flags = rcv_func->flags;
|
||||
functx->req_nrets = HCL_SMOOI_TO_OOP(1);
|
||||
functx->tmpr_mask = rcv_func->tmpr_mask;
|
||||
functx->receiver_or_base = (hcl_oop_t)rcv_func;
|
||||
functx->home = rcv_func->home;
|
||||
@ -2290,7 +2287,7 @@ static int start_initial_process_and_context (hcl_t* hcl, hcl_ooi_t initial_ip,
|
||||
hcl->sp = -1;
|
||||
|
||||
ctx->ip = HCL_SMOOI_TO_OOP(initial_ip);
|
||||
ctx->flags = HCL_SMOOI_TO_OOP(0);
|
||||
ctx->req_nrets = HCL_SMOOI_TO_OOP(1);
|
||||
ctx->tmpr_mask = HCL_SMOOI_TO_OOP(tmpr_mask);
|
||||
ctx->origin = ctx; /* the origin of the initial context is itself as this is created over the initial function */
|
||||
ctx->home = hcl->initial_function->home; /* this should be nil */
|
||||
@ -3117,6 +3114,37 @@ static int execute (hcl_t* hcl)
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
|
||||
case HCL_CODE_PUSH_RETURN_R:
|
||||
{
|
||||
hcl_oop_context_t ctx;
|
||||
hcl_oow_t i;
|
||||
hcl_ooi_t tmpr_mask, fixed_nargs;
|
||||
|
||||
LOG_INST_0 (hcl, "push_return_r");
|
||||
|
||||
HCL_ASSERT(hcl, HCL_IS_CONTEXT(hcl, hcl->active_context));
|
||||
|
||||
ctx = hcl->active_context;
|
||||
tmpr_mask = HCL_OOP_TO_SMOOI(ctx->tmpr_mask);
|
||||
fixed_nargs = GET_BLKTMPR_MASK_NARGS(tmpr_mask);
|
||||
|
||||
i = HCL_OOP_TO_SMOOI(ctx->req_nrets);
|
||||
|
||||
/* return variables are placed after the fixed arguments */
|
||||
while (i > 0)
|
||||
{
|
||||
--i;
|
||||
HCL_STACK_PUSH (hcl, ctx->slot[fixed_nargs + i]);
|
||||
}
|
||||
|
||||
/* same as HCL_CODE_RETURN_FROM_BLOCK */
|
||||
|
||||
hcl->last_retv = HCL_STACK_GETTOP(hcl); /* get the stack top */
|
||||
do_return_from_block (hcl);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case HCL_CODE_CALL_R:
|
||||
{
|
||||
hcl_oop_t rcv;
|
||||
@ -3165,7 +3193,7 @@ static int execute (hcl_t* hcl)
|
||||
break;
|
||||
|
||||
case HCL_BRAND_BLOCK:
|
||||
if (activate_block(hcl, b1, 0) <= -1) goto call_failed;
|
||||
if (activate_block(hcl, b1, 1) <= -1) goto call_failed;
|
||||
break;
|
||||
|
||||
case HCL_BRAND_PRIM:
|
||||
|
@ -831,13 +831,14 @@ enum hcl_bcode_t
|
||||
|
||||
HCL_CODE_CALL_X = 0xD4, /* 212 ## */
|
||||
HCL_CODE_CALL_R = 0xD5, /* 213 ## ##*/
|
||||
HCL_CODE_TRY_ENTER = 0xD6, /* 214 ## */
|
||||
HCL_CODE_TRY_ENTER2 = 0xD7, /* 215 ## */
|
||||
HCL_CODE_PUSH_RETURN_R = 0xD6, /* 214 */
|
||||
HCL_CODE_TRY_ENTER = 0xD7, /* 215 ## */
|
||||
|
||||
|
||||
HCL_CODE_STORE_INTO_CTXTEMPVAR_X = 0xD8, /* 216 ## */
|
||||
HCL_CODE_TRY_EXIT = 0xD9, /* 217 */
|
||||
HCL_CODE_THROW = 0xDA, /* 218 */
|
||||
/* UNUSED - 0xDB - 0xDB */
|
||||
HCL_CODE_TRY_ENTER2 = 0xD9, /* 217 ## */
|
||||
HCL_CODE_TRY_EXIT = 0xDA, /* 218 */
|
||||
HCL_CODE_THROW = 0xDB, /* 219 */
|
||||
|
||||
HCL_CODE_POP_INTO_CTXTEMPVAR_X = 0xDC, /* 220 ## */
|
||||
/* UNUSED - 0xDD - 0xDF */
|
||||
|
10
lib/hcl.h
10
lib/hcl.h
@ -549,11 +549,11 @@ struct hcl_fpdec_t
|
||||
#define HCL_FUNCTION_GET_CODE_BYTE(m) HCL_OBJ_GET_TRAILER_BYTE(m)
|
||||
#define HCL_FUNCTION_GET_CODE_SIZE(m) HCL_OBJ_GET_TRAILER_SIZE(m)
|
||||
|
||||
#define HCL_FUNCTION_NAMED_INSTVARS 4 /* this excludes literal frames and byte codes */
|
||||
#define HCL_FUNCTION_NAMED_INSTVARS 3 /* this excludes literal frames and byte codes */
|
||||
typedef struct hcl_function_t hcl_function_t;
|
||||
typedef struct hcl_function_t* hcl_oop_function_t;
|
||||
|
||||
#define HCL_BLOCK_NAMED_INSTVARS 4
|
||||
#define HCL_BLOCK_NAMED_INSTVARS 3
|
||||
typedef struct hcl_block_t hcl_block_t;
|
||||
typedef struct hcl_block_t* hcl_oop_block_t;
|
||||
|
||||
@ -567,7 +567,6 @@ struct hcl_function_t
|
||||
{
|
||||
HCL_OBJ_HEADER;
|
||||
|
||||
hcl_oop_t flags;
|
||||
hcl_oop_t tmpr_mask; /* smooi */
|
||||
hcl_oop_context_t home; /* home context. nil for the initial function */
|
||||
|
||||
@ -587,7 +586,6 @@ struct hcl_block_t
|
||||
{
|
||||
HCL_OBJ_HEADER;
|
||||
|
||||
hcl_oop_t flags;
|
||||
hcl_oop_t tmpr_mask; /* smooi */
|
||||
hcl_oop_context_t home; /* home context */
|
||||
hcl_oop_t ip; /* smooi. instruction pointer where the byte code begins in home->origin */
|
||||
@ -597,8 +595,8 @@ struct hcl_context_t
|
||||
{
|
||||
HCL_OBJ_HEADER;
|
||||
|
||||
/* SmallInteger, context flags */
|
||||
hcl_oop_t flags;
|
||||
/* SmallInteger */
|
||||
hcl_oop_t req_nrets;
|
||||
|
||||
/* SmallInteger. */
|
||||
hcl_oop_t tmpr_mask;
|
||||
|
Loading…
Reference in New Issue
Block a user