diff --git a/lib/comp.c b/lib/comp.c index e0f8976..16bbc42 100644 --- a/lib/comp.c +++ b/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 (block_code_size == 0) - { - /* no body in lambda - (lambda (a b c)) */ -/* TODO: is this correct??? */ - if (emit_byte_instruction(hcl, HCL_CODE_PUSH_NIL, HCL_CNODE_GET_LOC(cf->operand)) <= -1) return -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??? */ + 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 (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) { diff --git a/lib/decode.c b/lib/decode.c index ea3e850..c47fca4 100644 --- a/lib/decode.c +++ b/lib/decode.c @@ -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 */ diff --git a/lib/exec.c b/lib/exec.c index 0fb6819..7f7540e 100644 --- a/lib/exec.c +++ b/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: diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index a57334d..8b29505 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -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 */ diff --git a/lib/hcl.h b/lib/hcl.h index ce91621..d76e137 100644 --- a/lib/hcl.h +++ b/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;