diff --git a/lib/comp.c b/lib/comp.c index 390b13a..abe88b5 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -189,29 +189,90 @@ static int find_temporary_variable_backward (hcl_t* hcl, const hcl_oocs_t* name, return __find_word_in_string(&hcl->c->tv.s, name, 1, index); } -static int store_temporary_variable_count_for_block (hcl_t* hcl, hcl_oow_t tmpr_count, hcl_oow_t tmpr_len, hcl_oow_t lfbase) +static int push_fnblk (hcl_t* hcl, hcl_cnode_t* cmd, hcl_oow_t tmpr_count, hcl_oow_t tmpr_len, hcl_oow_t lfbase) { - HCL_ASSERT (hcl, hcl->c->blk.depth >= 0); + HCL_ASSERT (hcl, hcl->c->fnblk.depth >= 0); - if (hcl->c->blk.depth >= hcl->c->blk.info_capa) + if (hcl->c->fnblk.depth == HCL_TYPE_MAX(hcl_ooi_t)) { - hcl_blk_info_t* tmp; - hcl_oow_t newcapa; - - newcapa = HCL_ALIGN(hcl->c->blk.depth + 1, BLK_INFO_BUFFER_ALIGN); - tmp = (hcl_blk_info_t*)hcl_reallocmem(hcl, hcl->c->blk.info, newcapa * HCL_SIZEOF(*tmp)); - if (HCL_UNLIKELY(!tmp)) return -1; - - hcl->c->blk.info_capa = newcapa; - hcl->c->blk.info = tmp; + if (cmd) + hcl_setsynerrbfmt (hcl, HCL_SYNERR_BLKDEPTH, HCL_CNODE_GET_LOC(src), HCL_NULL, "function block depth too deep in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); + else + hcl_setsynerrbfmt (hcl, HCL_SYNERR_BLKDEPTH, HCL_NULL, HCL_NULL, "function block depth too deep"); + return -1; } - hcl->c->blk.info[hcl->c->blk.depth].tmprlen = tmpr_len; - hcl->c->blk.info[hcl->c->blk.depth].tmprcnt = tmpr_count; - hcl->c->blk.info[hcl->c->blk.depth].lfbase = lfbase; + if (hcl->c->fnblk.depth >= hcl->c->fnblk.info_capa) + { + hcl_fnblk_info_t* tmp; + hcl_oow_t newcapa; + + newcapa = HCL_ALIGN(hcl->c->fnblk.depth + 1, BLK_INFO_BUFFER_ALIGN); + tmp = (hcl_fnblk_info_t*)hcl_reallocmem(hcl, hcl->c->fnblk.info, newcapa * HCL_SIZEOF(*tmp)); + if (HCL_UNLIKELY(!tmp)) return -1; + + hcl->c->fnblk.info_capa = newcapa; + hcl->c->fnblk.info = tmp; + } + + HCL_MEMSET (&hcl->c->fnblk.info[hcl->c->fnblk.depth], 0, HCL_SIZEOF(hcl->c->fnblk.info[hcl->c->fnblk.depth])); + + hcl->c->fnblk.info[hcl->c->fnblk.depth].tmprlen = tmpr_len; + hcl->c->fnblk.info[hcl->c->fnblk.depth].tmprcnt = tmpr_count; + hcl->c->fnblk.info[hcl->c->fnblk.depth].lfbase = lfbase; + + hcl->c->fnblk.info[hcl->c->fnblk.depth].cblk_base = hcl->c->cblk.depth; return 0; } +static void pop_fnblk (hcl_t* hcl) +{ + HCL_ASSERT (hcl, hcl->c->fnblk.depth >= 0); + hcl->c->fnblk.depth--; + if (hcl->c->fnblk.depth >= 0) + { + hcl->c->tv.s.len = hcl->c->fnblk.info[hcl->c->fnblk.depth].tmprlen; + hcl->c->tv.wcount = hcl->c->fnblk.info[hcl->c->fnblk.depth].tmprcnt; + + hcl->c->cblk.depth = hcl->c->fnblk.info[hcl->c->fnblk.depth].cblk_base; + } +} + +static int push_cblk (hcl_t* hcl, hcl_cnode_t* cmd, hcl_cblk_type_t type) +{ + if (hcl->c->cblk.depth == HCL_TYPE_MAX(hcl_ooi_t)) + { + hcl_setsynerrbfmt (hcl, HCL_SYNERR_BLKDEPTH, HCL_CNODE_GET_LOC(src), HCL_NULL, "control block depth too deep in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); + return -1; + } + + if (hcl->c->cblk.depth >= hcl->c->cblk.info_capa) + { + hcl_cblk_info_t* tmp; + hcl_oow_t newcapa; + + /* +2 to indicate +1 after increment */ + newcapa = HCL_ALIGN(hcl->c->cblk.depth + 2, BLK_INFO_BUFFER_ALIGN); + tmp = (hcl_cblk_info_t*)hcl_reallocmem(hcl, hcl->c->cblk.info, newcapa * HCL_SIZEOF(*tmp)); + if (HCL_UNLIKELY(!tmp)) return -1; + + hcl->c->cblk.info_capa = newcapa; + hcl->c->cblk.info = tmp; + } + + + hcl->c->cblk.depth++; + + HCL_MEMSET (&hcl->c->cblk.info[hcl->c->cblk.depth], 0, HCL_SIZEOF(hcl->c->fnblk.info[hcl->c->cblk.depth])); + hcl->c->cblk.info[hcl->c->cblk.depth]._type = type; + return 0; +} + +static void pop_cblk (hcl_t* hcl) +{ + HCL_ASSERT (hcl, hcl->c->cblk.depth >= 0); + hcl->c->cblk.depth--; +} /* ========================================================================= */ static int add_literal (hcl_t* hcl, hcl_oop_t obj, hcl_oow_t* index) @@ -219,7 +280,7 @@ static int add_literal (hcl_t* hcl, hcl_oop_t obj, hcl_oow_t* index) hcl_oow_t capa, i, lfbase = 0; - lfbase = (hcl->option.trait & HCL_TRAIT_INTERACTIVE)? hcl->c->blk.info[hcl->c->blk.depth].lfbase: 0; + lfbase = (hcl->option.trait & HCL_TRAIT_INTERACTIVE)? hcl->c->fnblk.info[hcl->c->fnblk.depth].lfbase: 0; /* TODO: speed up the following duplicate check loop */ for (i = lfbase; i < hcl->code.lit.len; i++) @@ -615,20 +676,20 @@ static HCL_INLINE void patch_long_param (hcl_t* hcl, hcl_ooi_t ip, hcl_oow_t par static int emit_indexed_variable_access (hcl_t* hcl, hcl_oow_t index, hcl_oob_t baseinst1, hcl_oob_t baseinst2, const hcl_ioloc_t* srcloc) { - if (hcl->c->blk.depth >= 0) + if (hcl->c->fnblk.depth >= 0) { hcl_oow_t i; /* if a temporary variable is accessed inside a block, * use a special instruction to indicate it */ - HCL_ASSERT (hcl, index < hcl->c->blk.info[hcl->c->blk.depth].tmprcnt); - for (i = hcl->c->blk.depth; i > 0; i--) /* excluded the top level -- TODO: change this code depending on global variable handling */ + HCL_ASSERT (hcl, index < hcl->c->fnblk.info[hcl->c->fnblk.depth].tmprcnt); + for (i = hcl->c->fnblk.depth; i > 0; i--) /* excluded the top level -- TODO: change this code depending on global variable handling */ { - if (index >= hcl->c->blk.info[i - 1].tmprcnt) + if (index >= hcl->c->fnblk.info[i - 1].tmprcnt) { hcl_oow_t ctx_offset, index_in_ctx; - ctx_offset = hcl->c->blk.depth - i; - index_in_ctx = index - hcl->c->blk.info[i - 1].tmprcnt; + ctx_offset = hcl->c->fnblk.depth - i; + index_in_ctx = index - hcl->c->fnblk.info[i - 1].tmprcnt; /* ctx_offset 0 means the current context. * 1 means current->home. * 2 means current->home->home. @@ -1571,13 +1632,15 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun) return -1; } - if (hcl->c->blk.depth == HCL_TYPE_MAX(hcl_ooi_t)) + if (push_fnblk(hcl) <= -1) return -1; + + if (hcl->c->fnblk.depth == HCL_TYPE_MAX(hcl_ooi_t)) { hcl_setsynerrbfmt (hcl, HCL_SYNERR_BLKDEPTH, HCL_CNODE_GET_LOC(src), HCL_NULL, "block depth too deep in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); return -1; } - hcl->c->blk.depth++; - if (store_temporary_variable_count_for_block(hcl, hcl->c->tv.wcount, hcl->c->tv.s.len, hcl->code.lit.len) <= -1) return -1; + hcl->c->fnblk.depth++; + if (store_temporary_variable_count_for_fnblk(hcl, hcl->c->tv.wcount, hcl->c->tv.s.len, hcl->code.lit.len) <= -1) return -1; if (hcl->option.trait & HCL_TRAIT_INTERACTIVE) @@ -1585,7 +1648,7 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun) /* make_function nargs ntmprs lfbase lfsize */ if (emit_double_param_instruction(hcl, HCL_CODE_MAKE_FUNCTION, nargs, ntmprs, HCL_CNODE_GET_LOC(cmd)) <= -1) return -1; lfbase_pos = hcl->code.bc.len; - if (emit_long_param(hcl, hcl->code.lit.len - hcl->c->blk.info[hcl->c->blk.depth - 1].lfbase) <= -1) return -1; /* literal frame base */ + if (emit_long_param(hcl, hcl->code.lit.len - hcl->c->fnblk.info[hcl->c->fnblk.depth - 1].lfbase) <= -1) return -1; /* literal frame base */ lfsize_pos = hcl->code.bc.len; /* literal frame size */ if (emit_long_param(hcl, 0) <= -1) return -1; } @@ -1779,13 +1842,15 @@ static int compile_try (hcl_t* hcl, hcl_cnode_t* src) /* TODO: allow local temporary variables?? */ - if (hcl->c->blk.depth == HCL_TYPE_MAX(hcl_ooi_t)) +#if 0 + if (hcl->c->fnblk.depth == HCL_TYPE_MAX(hcl_ooi_t)) { hcl_setsynerrbfmt (hcl, HCL_SYNERR_BLKDEPTH, HCL_CNODE_GET_LOC(src), HCL_NULL, "block depth too deep in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); return -1; } - hcl->c->blk.depth++; + hcl->c->fnblk.depth++; if (store_temporary_variable_count_for_block(hcl, hcl->c->tv.wcount, hcl->c->tv.s.len, hcl->code.lit.len) <= -1) return -1; +#endif /* TODO: HCL_TRAIT_INTERACTIVE??? */ if (emit_double_param_instruction(hcl, HCL_CODE_MAKE_BLOCK, 0, 0, HCL_CNODE_GET_LOC(cmd)) <= -1) return -1; @@ -1945,7 +2010,11 @@ static HCL_INLINE int post_catch (hcl_t* hcl) if (emit_byte_instruction(hcl, HCL_CODE_TRY_CATCH, HCL_CNODE_GET_LOC(cf->operand)) <= -1) return -1; - hcl->c->blk.depth--; +#if 0 + /*hcl->c->fnblk.depth--; */ + pop_cblk (hcl); +#endif + POP_CFRAME (hcl); return 0; } @@ -3335,7 +3404,7 @@ static HCL_INLINE int emit_lambda (hcl_t* hcl) jip = cf->u.lambda.jump_inst_pos; if (hcl->option.trait & HCL_TRAIT_INTERACTIVE) - lfsize = hcl->code.lit.len - hcl->c->blk.info[hcl->c->blk.depth].lfbase; + lfsize = hcl->code.lit.len - hcl->c->fnblk.info[hcl->c->fnblk.depth].lfbase; /* 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); @@ -3372,9 +3441,10 @@ static HCL_INLINE int post_lambda (hcl_t* hcl) cf = GET_TOP_CFRAME(hcl); HCL_ASSERT (hcl, cf->opcode == COP_POST_LAMBDA); - hcl->c->blk.depth--; - hcl->c->tv.s.len = hcl->c->blk.info[hcl->c->blk.depth].tmprlen; - hcl->c->tv.wcount = hcl->c->blk.info[hcl->c->blk.depth].tmprcnt; + /*hcl->c->fnblk.depth--; + hcl->c->tv.s.len = hcl->c->fnblk.info[hcl->c->fnblk.depth].tmprlen; + hcl->c->tv.wcount = hcl->c->fnblk.info[hcl->c->fnblk.depth].tmprcnt;*/ + pop_fnblk (hcl); if (cf->operand) { @@ -3514,11 +3584,11 @@ int hcl_compile (hcl_t* hcl, hcl_cnode_t* obj) HCL_ASSERT (hcl, hcl->c->tv.s.len == 0); HCL_ASSERT (hcl, hcl->c->tv.wcount == 0); - HCL_ASSERT (hcl, hcl->c->blk.depth == -1); + HCL_ASSERT (hcl, hcl->c->fnblk.depth == -1); /* TODO: in case i implement all global variables as block arguments at the top level...what should i do? */ - hcl->c->blk.depth++; /* this must be 0 here */ + /* * In the non-INTERACTIVE mode, the literal frame base doesn't matter. @@ -3550,7 +3620,12 @@ int hcl_compile (hcl_t* hcl, hcl_cnode_t* obj) * @0 (a) * @1 (set-a) */ - if (store_temporary_variable_count_for_block(hcl, hcl->c->tv.wcount, hcl->c->tv.s.len, 0) <= -1) return -1; +#if 0 + hcl->c->fnblk.depth++; /* this must be 0 here */ + if (store_temporary_variable_count_for_fnblk(hcl, hcl->c->tv.wcount, hcl->c->tv.s.len, 0) <= -1) return -1; +#else + if (push_fnblk(hcl, HCL_NULL, hcl->c->tv.wcount, hcl->c->tv.s.len, 0) <= -1) return -1; +#endif PUSH_CFRAME (hcl, COP_COMPILE_OBJECT, obj); @@ -3731,8 +3806,8 @@ int hcl_compile (hcl_t* hcl, hcl_cnode_t* obj) HCL_ASSERT (hcl, GET_TOP_CFRAME_INDEX(hcl) < 0); HCL_ASSERT (hcl, hcl->c->tv.s.len == 0); HCL_ASSERT (hcl, hcl->c->tv.wcount == 0); - HCL_ASSERT (hcl, hcl->c->blk.depth == 0); - hcl->c->blk.depth--; + HCL_ASSERT (hcl, hcl->c->fnblk.depth == 0); + pop_fnblk (hcl); /*hcl->c->fnblk.depth--;*/ hcl ->log.default_type_mask = log_default_type_mask; return 0; @@ -3748,6 +3823,6 @@ oops: hcl->c->tv.s.len = 0; hcl->c->tv.wcount = 0; - hcl->c->blk.depth = -1; + hcl->c->fnblk.depth = -1; return -1; } diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index f8454a6..2aecb54 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -363,13 +363,30 @@ struct hcl_cframe_t }; typedef struct hcl_cframe_t hcl_cframe_t; -struct hcl_blk_info_t +enum hcl_cblk_type_t +{ + HCL_CBLK_TYPE_LOOP, + HCL_CBLK_TYPE_TRY +}; +typedef enum hcl_cblk_type_t hcl_cblk_type_t; + +/* control block information */ +struct hcl_cblk_info_t +{ + hcl_cblk_type_t _type; +}; +typedef struct hcl_cblk_info_t hcl_cblk_info_t; + +/* function block information */ +struct hcl_fnblk_info_t { hcl_oow_t tmprlen; hcl_oow_t tmprcnt; hcl_oow_t lfbase; + + hcl_oow_t cblk_base; }; -typedef struct hcl_blk_info_t hcl_blk_info_t; +typedef struct hcl_fnblk_info_t hcl_fnblk_info_t; typedef struct hcl_rstl_t hcl_rstl_t; struct hcl_rstl_t /* reader stack for list reading */ @@ -445,10 +462,17 @@ struct hcl_compiler_t struct { - hcl_ooi_t depth; - hcl_blk_info_t* info; + hcl_ooi_t depth; /* signed because it starts with -1 */ + hcl_cblk_info_t* info; + hcl_oow_t info_capa; + } cblk; /* control block - loop, try-catch */ + + struct + { + hcl_ooi_t depth; /* signed because it starts with -1 */ + hcl_fnblk_info_t* info; hcl_oow_t info_capa; - } blk; /* lambda block */ + } fnblk; /* lambda/function block */ }; #endif