diff --git a/bin/main.c b/bin/main.c index a81fa77..b900953 100644 --- a/bin/main.c +++ b/bin/main.c @@ -455,24 +455,28 @@ static int handle_logopt (hcl_t* hcl, const hcl_bch_t* logstr) { "ic", 0, HCL_LOG_IC }, { "primitive", 0, HCL_LOG_PRIMITIVE }, + /* select a specific level */ { "fatal", 0, HCL_LOG_FATAL }, { "error", 0, HCL_LOG_ERROR }, { "warn", 0, HCL_LOG_WARN }, { "info", 0, HCL_LOG_INFO }, { "debug", 0, HCL_LOG_DEBUG }, + /* select a specific level or higher */ { "fatal+", 0, HCL_LOG_FATAL }, { "error+", 0, HCL_LOG_FATAL | HCL_LOG_ERROR }, { "warn+", 0, HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN }, { "info+", 0, HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO }, { "debug+", 0, HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO | HCL_LOG_DEBUG }, + /* select a specific level or lower */ { "fatal-", 0, HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO | HCL_LOG_DEBUG }, { "error-", 0, HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO | HCL_LOG_DEBUG }, { "warn-", 0, HCL_LOG_WARN | HCL_LOG_INFO | HCL_LOG_DEBUG }, { "info-", 0, HCL_LOG_INFO | HCL_LOG_DEBUG }, { "debug-", 0, HCL_LOG_DEBUG }, + /* exclude a specific level */ { "-fatal", 1, ~HCL_LOG_FATAL }, { "-error", 1, ~HCL_LOG_ERROR }, { "-warn", 1, ~HCL_LOG_WARN }, @@ -542,8 +546,8 @@ static int handle_dbgopt (hcl_t* hcl, const hcl_bch_t* str) cm = hcl_find_bchar_in_bcstr(flt, ','); len = cm? (cm - flt): hcl_count_bcstr(flt); - if (hcl_comp_bchars_bcstr (flt, len, "gc") == 0) dbgopt |= HCL_TRAIT_DEBUG_GC; - else if (hcl_comp_bchars_bcstr (flt, len, "bigint") == 0) dbgopt |= HCL_TRAIT_DEBUG_BIGINT; + if (hcl_comp_bchars_bcstr(flt, len, "gc") == 0) dbgopt |= HCL_TRAIT_DEBUG_GC; + else if (hcl_comp_bchars_bcstr(flt, len, "bigint") == 0) dbgopt |= HCL_TRAIT_DEBUG_BIGINT; else { fprintf (stderr, "ERROR: unknown debug option value - %.*s\n", (int)len, flt); @@ -806,7 +810,7 @@ int main (int argc, char* argv[]) #if defined(HCL_BUILD_DEBUG) if (dbgopt) { - if (handle_dbgopt (hcl, dbgopt) <= -1) goto oops; + if (handle_dbgopt(hcl, dbgopt) <= -1) goto oops; } #endif diff --git a/lib/comp.c b/lib/comp.c index 491f30e..defa895 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -35,6 +35,23 @@ enum #define TV_BUFFER_ALIGN 256 #define BLK_INFO_BUFFER_ALIGN 128 + +struct var_info_t +{ + int type; + + + /* ctx_offset 0 means the current context. + * 1 means current->home. + * 2 means current->home->home. + * index_in_ctx is a relative index within the context found. + */ + hcl_oow_t ctx_offset; /* context offset */ + hcl_oow_t index_in_ctx; /* index in the current scope */ +}; +typedef struct var_info_t var_info_t; + + /* -------------------------------------------- @@ -133,6 +150,7 @@ static int __find_word_in_string (const hcl_oocs_t* haystack, const hcl_oocs_t* { if (last) { + /* if last is true, find the last matching entry */ found = index; } else @@ -165,7 +183,6 @@ static int __find_word_in_string (const hcl_oocs_t* haystack, const hcl_oocs_t* return -1; /* not found */ } - static int add_temporary_variable (hcl_t* hcl, const hcl_oocs_t* name, hcl_oow_t dup_check_start) { hcl_oocs_t s; @@ -198,7 +215,6 @@ static void kill_temporary_variable_at_offset (hcl_t* hcl, hcl_oow_t offset) /* this is a hacky function. it's better to implement kill_temporary_variables() which uses word positions */ HCL_ASSERT (hcl, offset < hcl->c->tv.s.len); HCL_ASSERT (hcl, hcl->c->tv.s.ptr[offset] != ' '); - hcl->c->tv.s.ptr[offset] = '('; /* put a special character which can't form a variable name */ } @@ -208,6 +224,86 @@ 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); } + + + +#if 0 + HCL_ASSERT (hcl, hcl->c->fnblk.depth >= 0); + fbi = &hcl->c->fnblk.info[hcl->c->fnblk.depth]; + + /* if a temporary variable is accessed inside a block, + * use a special instruction to indicate it */ + HCL_ASSERT (hcl, index < fbi->tmprcnt); + for (i = hcl->c->fnblk.depth; i >= 0; i--) + { + hcl_oow_t parent_tmprcnt; + + parent_tmprcnt = (i > 0)? hcl->c->fnblk.info[i - 1].tmprcnt: 0; + if (index >= parent_tmprcnt) + { + hcl_oow_t ctx_offset, index_in_ctx; + ctx_offset = hcl->c->fnblk.depth - i; + index_in_ctx = index - parent_tmprcnt; + /* ctx_offset 0 means the current context. + * 1 means current->home. + * 2 means current->home->home. + * index_in_ctx is a relative index within the context found. + */ + if (emit_double_param_instruction(hcl, baseinst1, ctx_offset, index_in_ctx, srcloc) <= -1) return -1; + if (ctx_offset > 0) + { + fbi->access_outer = 1; /* the current function block accesses temporaries in an outer function block */ + hcl->c->fnblk.info[i].accessed_by_inner = 1; /* temporaries in an outer function block is accessed by the current function block */ + } + return 0; + } + } +#endif + +static int find_variable_backward (hcl_t* hcl, const hcl_oocs_t* name, var_info_t* vi) +{ + hcl_fnblk_info_t* fbi; + hcl_oow_t parent_tmprcnt, parent_tmprlen; + hcl_oow_t i, index; + hcl_oocs_t haystack; + + HCL_ASSERT (hcl, hcl->c->fnblk.info[hcl->c->fnblk.depth].tmprlen = hcl->c->tv.s.len); + + /* depth begins at -1. so it is the actual index. let the looping begin at depth + 1 + * to avoid an extra exit check without it */ + for (i = hcl->c->fnblk.depth + 1; i > 0; ) + { + fbi = &hcl->c->fnblk.info[--i]; + if (i > 0) + { + parent_tmprlen = hcl->c->fnblk.info[i - 1].tmprlen; + parent_tmprcnt = hcl->c->fnblk.info[i - 1].tmprcnt; + } + else + { + parent_tmprlen = 0; + parent_tmprcnt = 0; + } + + /* narrow the search scope to the current block */ + haystack.ptr = &hcl->c->tv.s.ptr[parent_tmprlen]; + haystack.len = fbi->tmprlen - parent_tmprlen; + + if (__find_word_in_string(&haystack, name, 1, &index) >= 0) + { + /* temporary variables or arguments */ + vi->type = VAR_INDEXED; + vi->ctx_offset = hcl->c->fnblk.depth - i; /* context offset */ + vi->index_in_ctx = index; +HCL_INFO4 (hcl, "FOUND ...[%.*js]................ ===> ctx_offset %d index %d\n", name->len, name->ptr, (int)(vi->ctx_offset), (int)vi->index_in_ctx); + return 0; + } + } + +HCL_INFO2 (hcl, "NOT FOUND => %.*js\n", name->len, name->ptr); + return -1; +} + /* ========================================================================= */ static int add_literal (hcl_t* hcl, hcl_oop_t obj, hcl_oow_t* index) @@ -661,10 +757,10 @@ static int emit_indexed_variable_access (hcl_t* hcl, hcl_oow_t index, hcl_oob_t ctx_offset = hcl->c->fnblk.depth - i; index_in_ctx = index - parent_tmprcnt; /* ctx_offset 0 means the current context. - * 1 means current->home. - * 2 means current->home->home. - * index_in_ctx is a relative index within the context found. - */ + * 1 means current->home. + * 2 means current->home->home. + * index_in_ctx is a relative index within the context found. + */ if (emit_double_param_instruction(hcl, baseinst1, ctx_offset, index_in_ctx, srcloc) <= -1) return -1; if (ctx_offset > 0) { @@ -1918,17 +2014,19 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl) hcl_cframe_t* cf; hcl_cnode_t* obj; hcl_oop_t tmp; - hcl_oow_t nivars, ncvars, saved_tv_wcount, tv_dup_start; + hcl_oow_t nivars, ncvars, saved_tv_wcount, tv_dup_check_start; cf = GET_TOP_CFRAME(hcl); obj = cf->operand; saved_tv_wcount = hcl->c->tv.wcount; - tv_dup_start = hcl->c->tv.s.len; + tv_dup_check_start = hcl->c->tv.s.len; -/* TODO: class variables */ +/* TODO: class variables */ nivars = ncvars = 0; - if (collect_vardcl(hcl, obj, &obj, tv_dup_start, &nivars, "instance") <= -1) goto oops; + /* use the temporary variable collection buffer for convenience when scanning + * instance variables and class variables */ + if (collect_vardcl(hcl, obj, &obj, tv_dup_check_start, &nivars, "instance") <= -1) goto oops; if (nivars > 0) { @@ -1938,7 +2036,7 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl) goto oops; } /* set starting point past the added space (+1 to index, -1 to length) */ - tmp = hcl_makestring(hcl, &hcl->c->tv.s.ptr[tv_dup_start + 1], hcl->c->tv.s.len - tv_dup_start - 1, 0); + tmp = hcl_makestring(hcl, &hcl->c->tv.s.ptr[tv_dup_check_start + 1], hcl->c->tv.s.len - tv_dup_check_start - 1, 0); if (HCL_UNLIKELY(!tmp)) goto oops; if (emit_push_literal(hcl, tmp, &cf->u._class.start_loc) <= -1) goto oops; } @@ -1956,8 +2054,13 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl) if (HCL_UNLIKELY(!tmp)) goto oops; if (emit_push_literal(hcl, tmp, &cf->u._class.start_loc) <= -1) goto oops; } - - if (push_clsblk(hcl, &cf->u._class.start_loc, nivars, ncvars, &hcl->c->tv.s.ptr[tv_dup_start + 1], HCL_NULL) <= -1) goto oops; + + if (push_clsblk(hcl, &cf->u._class.start_loc, nivars, ncvars, &hcl->c->tv.s.ptr[tv_dup_check_start + 1], HCL_NULL) <= -1) goto oops; + + /* discard the instance variables and class variables in the temporary variable collection buffe + * because they have been pushed to the class block structure */ + hcl->c->tv.s.len = tv_dup_check_start; + hcl->c->tv.wcount = saved_tv_wcount; /* class_enter nsuperclasses, nivars, ncvars */ if (emit_byte_instruction(hcl, HCL_CODE_CLASS_ENTER, &cf->u._class.start_loc) <= -1) goto oops; @@ -1970,7 +2073,7 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl) return 0; oops: - hcl->c->tv.s.len = tv_dup_start; + hcl->c->tv.s.len = tv_dup_check_start; hcl->c->tv.wcount = saved_tv_wcount; return -1; } @@ -2236,7 +2339,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), 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) { /* MAKE_FUNCTION tmpr_mask_1 tmpr_mask_2 lfbase lfsize */ @@ -3150,7 +3253,10 @@ static HCL_INLINE int compile_symbol (hcl_t* hcl, hcl_cnode_t* obj) hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNEDVARNAME, HCL_CNODE_GET_LOC(obj), HCL_CNODE_GET_TOK(obj), "special symbol not to be used as a variable name"); return -1; } - +{ +var_info_t vi; +find_variable_backward(hcl, HCL_CNODE_GET_TOK(obj), &vi); +} /* check if a symbol is a local variable */ if (find_temporary_variable_backward(hcl, HCL_CNODE_GET_TOK(obj), &index) <= -1) { diff --git a/lib/decode.c b/lib/decode.c index dd97ab9..4f4371b 100644 --- a/lib/decode.c +++ b/lib/decode.c @@ -28,25 +28,14 @@ #define DECODE_LOG_MASK (HCL_LOG_MNEMONIC | HCL_LOG_INFO) -#if defined(HCL_BUILD_RELEASE) - /* get rid of instruction logging regardless of the log mask - * in the release build */ -# define LOG_INST_0(hcl,fmt) -# define LOG_INST_1(hcl,fmt,a1) -# define LOG_INST_2(hcl,fmt,a1,a2) -# define LOG_INST_3(hcl,fmt,a1,a2,a3) -# define LOG_INST_4(hcl,fmt,a1,a2,a3,a4) -# define LOG_INST_5(hcl,fmt,a1,a2,a3,a4,a5) -# define LOG_INST_6(hcl,fmt,a1,a2,a3,a4,a5,a6) -#else -# define LOG_INST_0(hcl,fmt) HCL_LOG1(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer) -# define LOG_INST_1(hcl,fmt,a1) HCL_LOG2(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer, a1) -# define LOG_INST_2(hcl,fmt,a1,a2) HCL_LOG3(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2) -# define LOG_INST_3(hcl,fmt,a1,a2,a3) HCL_LOG4(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2, a3) -# define LOG_INST_4(hcl,fmt,a1,a2,a3,a4) HCL_LOG5(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2, a3, a4) -# define LOG_INST_5(hcl,fmt,a1,a2,a3,a4,a5) HCL_LOG6(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2, a3, a4, a5) -# define LOG_INST_6(hcl,fmt,a1,a2,a3,a4,a5,a6) HCL_LOG7(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2, a3, a4, a5, a6) -#endif +#define LOG_INST_0(hcl,fmt) HCL_LOG1(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer) +#define LOG_INST_1(hcl,fmt,a1) HCL_LOG2(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer, a1) +#define LOG_INST_2(hcl,fmt,a1,a2) HCL_LOG3(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2) +#define LOG_INST_3(hcl,fmt,a1,a2,a3) HCL_LOG4(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2, a3) +#define LOG_INST_4(hcl,fmt,a1,a2,a3,a4) HCL_LOG5(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2, a3, a4) +#define LOG_INST_5(hcl,fmt,a1,a2,a3,a4,a5) HCL_LOG6(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2, a3, a4, a5) +#define LOG_INST_6(hcl,fmt,a1,a2,a3,a4,a5,a6) HCL_LOG7(hcl, DECODE_LOG_MASK, " %06zd " fmt "\n", fetched_instruction_pointer, a1, a2, a3, a4, a5, a6) + #define FETCH_BYTE_CODE(hcl) (cdptr[ip++]) #define FETCH_BYTE_CODE_TO(hcl,v_ooi) (v_ooi = FETCH_BYTE_CODE(hcl)) @@ -682,6 +671,7 @@ int hcl_decode (hcl_t* hcl, hcl_oow_t start, hcl_oow_t end) } } + /* TODO: this needs changes... */ /* print literal frame contents */ for (ip = 0; ip < hcl->code.lit.len; ip++)