From bdf527f298437590fe61d205a65c7c9a2d9b86bf Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sun, 9 Jan 2022 16:47:38 +0000 Subject: [PATCH] writing the compiler code for class variable handling --- lib/comp.c | 97 +++++++++++++++++++++++++++++++++++++++------------ lib/decode.c | 29 +++++++++++---- lib/exec.c | 69 ++++++++++++++++++++++++++++++++---- lib/hcl-prv.h | 28 +++++++++------ lib/hcl.h | 1 + 5 files changed, 178 insertions(+), 46 deletions(-) diff --git a/lib/comp.c b/lib/comp.c index 1a11eac..0112f64 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -31,7 +31,9 @@ enum VAR_NAMED, VAR_INDEXED, VAR_INST, - VAR_CLASS + VAR_CLASS_I, /* class variable in class initialization scope */ + VAR_CLASS_CM, /* class variable in class method scope */ + VAR_CLASS_IM, /* class variable in instance method scope */ }; enum @@ -210,12 +212,15 @@ static void kill_temporary_variable_at_offset (hcl_t* hcl, hcl_oow_t offset) hcl->c->tv.s.ptr[offset] = '('; /* HACK!! put a special character which can't form a variable name */ } -static int find_variable_backward (hcl_t* hcl, const hcl_oocs_t* name, hcl_var_info_t* vi) +static int find_variable_backward (hcl_t* hcl, const hcl_cnode_t* token, hcl_var_info_t* vi) { hcl_oow_t i, j; + const hcl_oocs_t* name; HCL_ASSERT (hcl, hcl->c->fnblk.depth >= 0); HCL_ASSERT (hcl, hcl->c->fnblk.info[hcl->c->fnblk.depth].tmprlen == hcl->c->tv.s.len); + + name = HCL_CNODE_GET_TOK(token); /* 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 */ @@ -229,25 +234,38 @@ static int find_variable_backward (hcl_t* hcl, const hcl_oocs_t* name, hcl_var_i if (fbi->clsblk_top >= 0) { - /* this function block has a class defined */ + /* this function block has a class defined. + * that is, it is in the class defintion scope. + * variable lookup must be limited to class scope */ hcl_clsblk_info_t* clsbi; - for (j = fbi->clsblk_top + 1; j > fbi->clsblk_base;) + #if 0 + for (j = fbi->clsblk_top + 1; j > fbi->clsblk_base; ) { clsbi = &hcl->c->clsblk.info[--j]; + #endif + clsbi = &hcl->c->clsblk.info[fbi->clsblk_top]; - if (i < hcl->c->fnblk.depth && clsbi->ivars_str) + if (clsbi->ivars_str) { haystack.ptr = clsbi->ivars_str; haystack.len = hcl_count_oocstr(clsbi->ivars_str); if (__find_word_in_string(&haystack, name, 1, &index) >= 0) { + if (i >= hcl->c->fnblk.depth) + { + /* instance variables are not accessible if not in class method scope. + * it is in class initialization scope */ + hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, HCL_CNODE_GET_LOC(token), name, "prohibited to access an instance variable"); + return -1; + } + vi->type = VAR_INST; vi->ctx_offset = 0; vi->index_in_ctx = index; HCL_INFO6 (hcl, "FOUND INST VAR [%.*js]...[%.*js]................ ===> ctx_offset %d index %d\n", haystack.len, haystack.ptr, name->len, name->ptr, (int)(vi->ctx_offset), (int)vi->index_in_ctx); - return 0; + return 1; } } @@ -257,14 +275,16 @@ HCL_INFO6 (hcl, "FOUND INST VAR [%.*js]...[%.*js]................ ===> ctx_offse haystack.len = hcl_count_oocstr(clsbi->cvars_str); if (__find_word_in_string(&haystack, name, 1, &index) >= 0) { - vi->type = VAR_CLASS; + /* TODO: VAR_CLASS_CM vs VAR_CLASS_IM, need to know if it's an instance method or a class method */ + vi->type = (i >= hcl->c->fnblk.depth? VAR_CLASS_I: VAR_CLASS_IM); vi->ctx_offset = 0; vi->index_in_ctx = index; HCL_INFO6 (hcl, "FOUND CLASS VAR [%.*js]...[%.*js]................ ===> ctx_offset %d index %d\n", haystack.len, haystack.ptr, name->len, name->ptr, (int)(vi->ctx_offset), (int)vi->index_in_ctx); - return 0; + return 1; } } + #if 0 } if (i == hcl->c->fnblk.depth) @@ -276,7 +296,9 @@ HCL_INFO2 (hcl, "CLASS NAMED VAR [%.*js]\n", name->len, name->ptr); vi->ctx_offset = 0; vi->index_in_ctx = 0; } - break; + #endif + + break; /* stop searching beyond class definition */ } if (HCL_LIKELY(i > 0)) @@ -310,12 +332,12 @@ HCL_INFO2 (hcl, "CLASS NAMED VAR [%.*js]\n", name->len, name->ptr); hcl->c->fnblk.info[i - 1].accessed_by_inner = 1; } - return 0; + return 1; } } HCL_INFO2 (hcl, "NOT FOUND => %.*js\n", name->len, name->ptr); - return -1; + return 0; /* not found */ } /* ========================================================================= */ @@ -494,9 +516,12 @@ static int emit_single_param_instruction (hcl_t* hcl, int cmd, hcl_oow_t param_1 case HCL_CODE_JUMP2_BACKWARD_IF_FALSE: case HCL_CODE_JUMP2_BACKWARD: - case HCL_CODE_PUSH_CLSVAR_X: - case HCL_CODE_STORE_INTO_CLSVAR_X: - case HCL_CODE_POP_INTO_CLSVAR_X: + case HCL_CODE_PUSH_CLSVAR_I_X: + case HCL_CODE_STORE_INTO_CLSVAR_I_X: + case HCL_CODE_POP_INTO_CLSVAR_I_X: + case HCL_CODE_PUSH_CLSVAR_M_X: + case HCL_CODE_STORE_INTO_CLSVAR_M_X: + case HCL_CODE_POP_INTO_CLSVAR_M_X: case HCL_CODE_TRY_ENTER: case HCL_CODE_TRY_ENTER2: @@ -760,7 +785,8 @@ static int emit_variable_access (hcl_t* hcl, int mode, const hcl_var_info_t* vi, { { HCL_CODE_PUSH_CTXTEMPVAR_0, HCL_CODE_POP_INTO_CTXTEMPVAR_0, HCL_CODE_STORE_INTO_CTXTEMPVAR_0 }, { HCL_CODE_PUSH_INSTVAR_0, HCL_CODE_POP_INTO_INSTVAR_0, HCL_CODE_STORE_INTO_INSTVAR_0 }, - { HCL_CODE_PUSH_CLSVAR_X, HCL_CODE_POP_INTO_CLSVAR_X, HCL_CODE_STORE_INTO_CLSVAR_X }, + { HCL_CODE_PUSH_CLSVAR_I_X, HCL_CODE_POP_INTO_CLSVAR_I_X, HCL_CODE_STORE_INTO_CLSVAR_I_X }, + { HCL_CODE_PUSH_CLSVAR_M_X, HCL_CODE_POP_INTO_CLSVAR_M_X, HCL_CODE_STORE_INTO_CLSVAR_M_X } }; switch (vi->type) @@ -769,12 +795,17 @@ static int emit_variable_access (hcl_t* hcl, int mode, const hcl_var_info_t* vi, return emit_double_param_instruction(hcl, inst_map[0][mode], vi->ctx_offset, vi->index_in_ctx, srcloc); case VAR_INST: + case VAR_CLASS_CM: HCL_ASSERT (hcl, vi->ctx_offset == 0); return emit_single_param_instruction(hcl, inst_map[1][mode], vi->index_in_ctx, srcloc); - case VAR_CLASS: + case VAR_CLASS_I: HCL_ASSERT (hcl, vi->ctx_offset == 0); return emit_single_param_instruction(hcl, inst_map[2][mode], vi->index_in_ctx, srcloc); + + case VAR_CLASS_IM: + HCL_ASSERT (hcl, vi->ctx_offset == 0); + return emit_single_param_instruction(hcl, inst_map[3][mode], vi->index_in_ctx, srcloc); } return -1; @@ -2221,8 +2252,12 @@ static HCL_INLINE int compile_class_p2 (hcl_t* hcl) */ hcl_cnode_t* class_name = cf->operand; hcl_var_info_t vi; + int x; - if (find_variable_backward(hcl, HCL_CNODE_GET_TOK(class_name), &vi) <= -1) + x = find_variable_backward(hcl, class_name, &vi); + if (x <= -1) return -1; + + if (x == 0) { SWITCH_TOP_CFRAME (hcl, COP_EMIT_SET, class_name); cf = GET_TOP_CFRAME(hcl); @@ -2230,7 +2265,6 @@ static HCL_INLINE int compile_class_p2 (hcl_t* hcl) } else { - //HCL_ASSERT (hcl, index <= HCL_SMOOI_MAX); SWITCH_TOP_CFRAME (hcl, COP_EMIT_SET, class_name); cf = GET_TOP_CFRAME(hcl); cf->u.set.vi = vi; @@ -2589,6 +2623,7 @@ static int compile_set (hcl_t* hcl, hcl_cnode_t* src) hcl_cframe_t* cf; hcl_cnode_t* cmd, * obj, * var, * val; hcl_var_info_t vi; + int x; HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(src)); HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_SET)); @@ -2643,7 +2678,10 @@ static int compile_set (hcl_t* hcl, hcl_cnode_t* src) SWITCH_TOP_CFRAME (hcl, COP_COMPILE_OBJECT, val); - if (find_variable_backward(hcl, HCL_CNODE_GET_TOK(var), &vi) <= -1) + x = find_variable_backward(hcl, var, &vi); + if (x <= -1) return -1; + + if (x == 0) { PUSH_SUBCFRAME (hcl, COP_EMIT_SET, var); /* set doesn't evaluate the variable name */ cf = GET_SUBCFRAME(hcl); @@ -2735,9 +2773,14 @@ static int compile_set_r (hcl_t* hcl, hcl_cnode_t* src) for (i = 0, obj = var_start; i < nvars; i++, obj = HCL_CNODE_CONS_CDR(obj)) { + int x; + var = HCL_CNODE_CONS_CAR(obj); - if (find_variable_backward(hcl, HCL_CNODE_GET_TOK(var), &vi) <= -1) + x = find_variable_backward(hcl, var, &vi); + if (x <= -1) return -1; + + if (x == 0) { PUSH_SUBCFRAME (hcl, COP_EMIT_SET, var); /* set_r doesn't evaluate the variable name */ cf = GET_SUBCFRAME(hcl); @@ -3380,6 +3423,7 @@ static int compile_cons_xlist_expression (hcl_t* hcl, hcl_cnode_t* obj, int nret static HCL_INLINE int compile_symbol (hcl_t* hcl, hcl_cnode_t* obj) { hcl_var_info_t vi; + int x; HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL(obj)); @@ -3390,7 +3434,10 @@ static HCL_INLINE int compile_symbol (hcl_t* hcl, hcl_cnode_t* obj) } /* check if a symbol is a local variable */ - if (find_variable_backward(hcl, HCL_CNODE_GET_TOK(obj), &vi) <= -1) + x = find_variable_backward(hcl, obj, &vi); + if (x <= -1) return -1; + + if (x == 0) { hcl_oop_t sym, cons; hcl_oow_t index; @@ -4526,8 +4573,12 @@ static HCL_INLINE int post_lambda (hcl_t* hcl) hcl_cnode_t* defun_name = cf->operand; hcl_oow_t index; hcl_var_info_t vi; - - if (find_variable_backward(hcl, HCL_CNODE_GET_TOK(defun_name), &vi) <= -1) + int x; + + x = find_variable_backward(hcl, defun_name, &vi); + if (x <= -1) return -1; + + if (x == 0) { SWITCH_TOP_CFRAME (hcl, COP_EMIT_SET, defun_name); cf = GET_TOP_CFRAME(hcl); diff --git a/lib/decode.c b/lib/decode.c index e3354cb..7c5641a 100644 --- a/lib/decode.c +++ b/lib/decode.c @@ -501,19 +501,36 @@ int hcl_decode (hcl_t* hcl, hcl_oow_t start, hcl_oow_t end) /* -------------------------------------------------------- */ - case HCL_CODE_PUSH_CLSVAR_X: + case HCL_CODE_PUSH_CLSVAR_I_X: FETCH_PARAM_CODE_TO (hcl, b1); - LOG_INST_1 (hcl, "push_clsvar %zu", b1); + LOG_INST_1 (hcl, "push_clsvar_i %zu", b1); break; - case HCL_CODE_STORE_INTO_CLSVAR_X: + case HCL_CODE_STORE_INTO_CLSVAR_I_X: FETCH_PARAM_CODE_TO (hcl, b1); - LOG_INST_1 (hcl, "store_into_clsvar %zu", b1); + LOG_INST_1 (hcl, "store_into_clsvar_i %zu", b1); break; - case HCL_CODE_POP_INTO_CLSVAR_X: + case HCL_CODE_POP_INTO_CLSVAR_I_X: FETCH_PARAM_CODE_TO (hcl, b1); - LOG_INST_1 (hcl, "pop_into_clsvar %zu", b1); + LOG_INST_1 (hcl, "pop_into_clsvar_i %zu", b1); + break; + + /* -------------------------------------------------------- */ + + case HCL_CODE_PUSH_CLSVAR_M_X: + FETCH_PARAM_CODE_TO (hcl, b1); + LOG_INST_1 (hcl, "push_clsvar_m %zu", b1); + break; + + case HCL_CODE_STORE_INTO_CLSVAR_M_X: + FETCH_PARAM_CODE_TO (hcl, b1); + LOG_INST_1 (hcl, "store_into_clsvar_m %zu", b1); + break; + + case HCL_CODE_POP_INTO_CLSVAR_M_X: + FETCH_PARAM_CODE_TO (hcl, b1); + LOG_INST_1 (hcl, "pop_into_clsvar_m %zu", b1); break; /* -------------------------------------------------------- */ diff --git a/lib/exec.c b/lib/exec.c index cc25eeb..2b66c8c 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -3629,21 +3629,21 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1) } #endif /* -------------------------------------------------------- */ - case HCL_CODE_PUSH_CLSVAR_X: + case HCL_CODE_PUSH_CLSVAR_I_X: { hcl_oop_class_t t; FETCH_PARAM_CODE_TO (hcl, b1); - LOG_INST_1 (hcl, "push_clsvar %zu", b1); + LOG_INST_1 (hcl, "push_clsvar_i %zu", b1); HCL_CLSTACK_FETCH_TOP_TO(hcl, t); - HCL_STACK_PUSH (hcl, t->cvar[b1]); /* TODO: consider the base size... */ + HCL_STACK_PUSH (hcl, t->cvar[b1]); break; } - case HCL_CODE_STORE_INTO_CLSVAR_X: + case HCL_CODE_STORE_INTO_CLSVAR_I_X: { hcl_oop_class_t t; FETCH_PARAM_CODE_TO (hcl, b1); - LOG_INST_1 (hcl, "store_into_clsvar %zu", b1); + LOG_INST_1 (hcl, "store_into_clsvar_i %zu", b1); if (HCL_CLSTACK_IS_EMPTY(hcl)) { hcl_seterrbfmt (hcl, HCL_ESTKUNDFLW, "empty class stack"); @@ -3655,11 +3655,11 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1) break; } - case HCL_CODE_POP_INTO_CLSVAR_X: + case HCL_CODE_POP_INTO_CLSVAR_I_X: { hcl_oop_class_t t; FETCH_PARAM_CODE_TO (hcl, b1); - LOG_INST_1 (hcl, "pop_into_clsvar %zu", b1); + LOG_INST_1 (hcl, "pop_into_clsvar_i %zu", b1); if (HCL_CLSTACK_IS_EMPTY(hcl)) { hcl_seterrbfmt (hcl, HCL_ESTKUNDFLW, "empty class stack"); @@ -3671,6 +3671,61 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1) HCL_STACK_POP (hcl); break; } + + /* -------------------------------------------------------- */ + + case HCL_CODE_PUSH_CLSVAR_M_X: + { + hcl_oop_class_t t; + FETCH_PARAM_CODE_TO (hcl, b1); + LOG_INST_1 (hcl, "push_clsvar_m %zu", b1); + /* TODO: finish implementing CLSVAR_M_X instructions ....*/ + t = (hcl_oop_oop_t)hcl->active_context->origin->receiver_or_base; + if (!HCL_IS_INSTANCE(hcl, t)) + { + hcl_seterrbfmt (hcl, HCL_ESTKUNDFLW, "non-instance receiver"); + supplement_errmsg (hcl, fetched_instruction_pointer); + goto oops; + } + t = HCL_OBJ_GET_CLASS(t); + HCL_STACK_PUSH (hcl, t->cvar[b1]); + break; + } + + case HCL_CODE_STORE_INTO_CLSVAR_M_X: + { + hcl_oop_class_t t; + FETCH_PARAM_CODE_TO (hcl, b1); + LOG_INST_1 (hcl, "store_into_clsvar_m %zu", b1); + t = (hcl_oop_oop_t)hcl->active_context->origin->receiver_or_base; + if (!HCL_IS_INSTANCE(hcl, t)) + { + hcl_seterrbfmt (hcl, HCL_ESTKUNDFLW, "non-instance receiver"); + supplement_errmsg (hcl, fetched_instruction_pointer); + goto oops; + } + t = HCL_OBJ_GET_CLASS(t); + t->cvar[b1] = HCL_STACK_GETTOP(hcl); + break; + } + + case HCL_CODE_POP_INTO_CLSVAR_M_X: + { + hcl_oop_class_t t; + FETCH_PARAM_CODE_TO (hcl, b1); + LOG_INST_1 (hcl, "pop_into_clsvar_m %zu", b1); + t = (hcl_oop_oop_t)hcl->active_context->origin->receiver_or_base; + if (!HCL_IS_INSTANCE(hcl, t)) + { + hcl_seterrbfmt (hcl, HCL_ESTKUNDFLW, "non-instance receiver"); + supplement_errmsg (hcl, fetched_instruction_pointer); + goto oops; + } + t = HCL_OBJ_GET_CLASS(t); + t->cvar[b1] = HCL_STACK_GETTOP(hcl); + HCL_STACK_POP (hcl); + break; + } /* -------------------------------------------------------- */ diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index 3077b97..cd7d6aa 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -672,12 +672,16 @@ SHORT INSTRUCTION CODE LONG INSTRUCTION C 116-119 0111 01XX YYYYYYYY SEND_MESSAGE_TO_SUPER 244 1111 0100 XXXXXXXX YYYYYYYY SEND_MESSAGE_TO_SUPER_X (bit 2 on) # XXX args, YYYYYYYY message -120 0111 1000 YYYYYYYY PUSH_CLSVAR_X -121 0111 1001 YYYYYYYY STORE_INTO_CLSVAR_X -122 0111 1010 YYYYYYYY POP_INTO_CLSVAR_X +120 0111 1000 YYYYYYYY PUSH_CLSVAR_I_X +121 0111 1001 YYYYYYYY STORE_INTO_CLSVAR_I_X +122 0111 1010 YYYYYYYY POP_INTO_CLSVAR_I_X -123 0111 1011 UNUSED -124-127 0111 11XX UNUSED +123 0111 1011 YYYYYYYY PUSH_CLSVAR_M_X +124 0111 1100 YYYYYYYY STORE_INTO_CLSVAR_M_X +125 0111 1101 YYYYYYYY POP_INTO_CLSVAR_M_X + +126 0111 1110 UNUSED +127 0111 1111 UNUSED ## ## "SHORT_CODE_0 | 0x80" becomes "LONG_CODE_X". @@ -831,11 +835,15 @@ enum hcl_bcode_t HCL_CODE_SEND_MESSAGE_TO_SUPER_2 = 0x76, /* 118 */ HCL_CODE_SEND_MESSAGE_TO_SUPER_3 = 0x77, /* 119 */ - HCL_CODE_PUSH_CLSVAR_X = 0x78, /* 120 */ - HCL_CODE_STORE_INTO_CLSVAR_X = 0x79, /* 121 */ - HCL_CODE_POP_INTO_CLSVAR_X = 0x7A, /* 122 */ - /* UNUSED 0x7B */ - /* UNUSED 0x7C - 0x7F */ + HCL_CODE_PUSH_CLSVAR_I_X = 0x78, /* 120 */ + HCL_CODE_STORE_INTO_CLSVAR_I_X = 0x79, /* 121 */ + HCL_CODE_POP_INTO_CLSVAR_I_X = 0x7A, /* 122 */ + + HCL_CODE_PUSH_CLSVAR_M_X = 0x7B, /* 123 */ + HCL_CODE_STORE_INTO_CLSVAR_M_X = 0x7C, /* 124 */ + HCL_CODE_POP_INTO_CLSVAR_M_X = 0x7D, /* 125 */ + + /* UNUSED 0x7E - 0x7F */ HCL_CODE_STORE_INTO_INSTVAR_X = 0x80, /* 128 */ diff --git a/lib/hcl.h b/lib/hcl.h index 5482e6d..187d83d 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -1859,6 +1859,7 @@ typedef enum hcl_concode_t hcl_concode_t; #define HCL_IS_FUNCTION(hcl,v) (HCL_OOP_IS_POINTER(v) && HCL_OBJ_GET_FLAGS_BRAND(v) == HCL_BRAND_FUNCTION) #define HCL_IS_BLOCK(hcl,v) (HCL_OOP_IS_POINTER(v) && HCL_OBJ_GET_FLAGS_BRAND(v) == HCL_BRAND_BLOCK) #define HCL_IS_CLASS(hcl,v) (HCL_OOP_IS_POINTER(v) && HCL_OBJ_GET_FLAGS_BRAND(v) == HCL_BRAND_CLASS) +#define HCL_IS_INSTANCE(hcl,v) (HCL_OOP_IS_POINTER(v) && HCL_OBJ_GET_FLAGS_BRAND(v) == HCL_BRAND_INSTANCE) #define HCL_IS_PROCESS(hcl,v) (HCL_OOP_IS_POINTER(v) && HCL_OBJ_GET_FLAGS_BRAND(v) == HCL_BRAND_PROCESS) #define HCL_IS_CONS(hcl,v) (HCL_OOP_IS_POINTER(v) && HCL_OBJ_GET_FLAGS_BRAND(v) == HCL_BRAND_CONS) #define HCL_IS_CONS_CONCODED(hcl,v,concode) (HCL_IS_CONS(hcl,v) && HCL_OBJ_GET_FLAGS_SYNCODE(v) == (concode))