From 70828ac11027e9b96376d229cab0b3def79af975 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Fri, 1 Dec 2023 21:49:28 +0900 Subject: [PATCH] updated the reader and the compiler to support self.var inside class definition --- lib/comp.c | 83 ++++++++++++++++++++++++++++++++++++------------------ lib/prim.c | 21 ++++++++++++++ lib/read.c | 21 ++++++++++---- 3 files changed, 93 insertions(+), 32 deletions(-) diff --git a/lib/comp.c b/lib/comp.c index 7f7ae5f..08dcaa4 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -256,17 +256,14 @@ static int is_in_class_method_scope (hcl_t* hcl) return 0; /* in plain function scope */ } -static int find_variable_backward (hcl_t* hcl, const hcl_cnode_t* token, hcl_var_info_t* vi) +static int find_variable_backward_with_word (hcl_t* hcl, const hcl_oocs_t* name, const hcl_loc_t* loc, int class_level_only, hcl_var_info_t* vi) { hcl_oow_t i; - 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 + /* depth begins at -1. so it is the actual index. let looping begin at depth + 1 * to avoid an extra exit check without it */ for (i = hcl->c->fnblk.depth + 1; i > 0; ) { @@ -302,7 +299,7 @@ static int find_variable_backward (hcl_t* hcl, const hcl_cnode_t* token, hcl_var { /* instance variables are accessible only in an instance method defintion scope. * it is in class initialization scope */ - hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, HCL_CNODE_GET_LOC(token), name, "prohibited access to an instance variable"); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, loc, name, "prohibited access to an instance variable"); return -1; } @@ -312,7 +309,7 @@ static int find_variable_backward (hcl_t* hcl, const hcl_cnode_t* token, hcl_var if (hcl->c->fnblk.info[--fi].fun_type == FUN_CM) { /* the function where this variable is defined is a class method or an plain function block within a class method*/ - hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, HCL_CNODE_GET_LOC(token), name, "prohibited access to an instance variable in a class method context"); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, loc, name, "prohibited access to an instance variable in a class method context"); return -1; } @@ -362,6 +359,8 @@ HCL_INFO2 (hcl, "CLASS NAMED VAR [%.*js]\n", name->len, name->ptr); break; /* stop searching beyond class definition */ } + if (class_level_only) continue; /* skip local variable declarations */ + if (HCL_LIKELY(i > 0)) { parent_tmprlen = hcl->c->fnblk.info[i - 1].tmprlen; @@ -401,6 +400,11 @@ HCL_INFO2 (hcl, "CLASS NAMED VAR [%.*js]\n", name->len, name->ptr); return 0; /* not found */ } +static int find_variable_backward_with_token (hcl_t* hcl, const hcl_cnode_t* token, hcl_var_info_t* vi) +{ + return find_variable_backward_with_word(hcl, HCL_CNODE_GET_TOK(token), HCL_CNODE_GET_LOC(token), 0, vi); +} + /* ========================================================================= */ static int check_block_expression_as_body (hcl_t* hcl, hcl_cnode_t* c, const hcl_cnode_t* ctx, int for_if) @@ -2610,7 +2614,7 @@ static HCL_INLINE int compile_class_p2 (hcl_t* hcl) hcl_var_info_t vi; int x; - x = find_variable_backward(hcl, class_name, &vi); + x = find_variable_backward_with_token(hcl, class_name, &vi); if (x <= -1) return -1; if (x == 0) @@ -3076,7 +3080,7 @@ static int compile_set (hcl_t* hcl, hcl_cnode_t* src) SWITCH_TOP_CFRAME (hcl, COP_COMPILE_OBJECT, val); - x = find_variable_backward(hcl, var, &vi); + x = find_variable_backward_with_token(hcl, var, &vi); if (x <= -1) return -1; if (x == 0) @@ -3175,7 +3179,7 @@ static int compile_set_r (hcl_t* hcl, hcl_cnode_t* src) var = HCL_CNODE_CONS_CAR(obj); - x = find_variable_backward(hcl, var, &vi); + x = find_variable_backward_with_token(hcl, var, &vi); if (x <= -1) return -1; if (x == 0) @@ -3365,9 +3369,9 @@ static HCL_INLINE int compile_catch (hcl_t* hcl) par_tmprcnt = 0; } - /* fill the variable information structure as if it's found by find_variable_backward(). + /* fill the variable information structure as if it's found by find_variable_backward_with_token(). * we know it's the last variable as add_temporary_variable() is called below. - * there is no need to call find_variable_backward() */ + * there is no need to call find_variable_backward_with_token() */ vi.type = VAR_INDEXED; vi.ctx_offset = 0; vi.index_in_ctx = hcl->c->tv.wcount - par_tmprcnt; @@ -3987,7 +3991,7 @@ static HCL_INLINE int compile_symbol (hcl_t* hcl, hcl_cnode_t* obj) } /* check if a symbol is a local variable */ - x = find_variable_backward(hcl, obj, &vi); + x = find_variable_backward_with_token(hcl, obj, &vi); if (x <= -1) return -1; if (x == 0) @@ -4022,32 +4026,54 @@ static HCL_INLINE int compile_symbol (hcl_t* hcl, hcl_cnode_t* obj) static HCL_INLINE int compile_dsymbol (hcl_t* hcl, hcl_cnode_t* obj) { - hcl_oop_t sym, cons; + hcl_oop_t cons; hcl_oow_t index; /* TODO: need a total revamp on the dotted symbols. * must differentiate module access and dictioary member access... * must implementate dictionary member access syntax... */ -#if 0 -the dot notation collides with car/cdr separator??? + /* the dot notation collides with car/cdr separator? no. dotted symbols don't contains space. + * the car cdr separator must be a single character */ { /* HACK FOR NOW */ const hcl_ooch_t* sep; + hcl_oocs_t name; + int x = 0; + hcl_var_info_t vi; - sep = hcl_find_oochar(HCL_CNODE_GET_TOKPTR(obj), HCL_CNODE_GET_TOKLEN(obj), '.'); + name = *HCL_CNODE_GET_TOK(obj); + + sep = hcl_find_oochar(name.ptr, name.len, '.'); HCL_ASSERT (hcl, sep != HCL_NULL); - if (hcl_comp_oochars_bcstr(HCL_CNODE_GET_TOKPTR(obj), sep - HCL_CNODE_GET_TOKPTR(obj), "self") == 0) + if (hcl_comp_oochars_bcstr(name.ptr, sep - name.ptr, "self") == 0) { /* instance variable? or instance method? */ HCL_DEBUG1 (hcl, ">>>> instance variable or method %js\n", sep + 1); + name.ptr = sep + 1; + name.len -= 5; + x = find_variable_backward_with_word(hcl, &name, HCL_CNODE_GET_LOC(obj), 1, &vi); + } + else if (hcl_comp_oochars_bcstr(name.ptr, sep - name.ptr, "super") == 0) + { + name.ptr = sep + 1; + name.len -= 6; + x = find_variable_backward_with_word(hcl, &name, HCL_CNODE_GET_LOC(obj), 1, &vi); /* TODO: arrange to skip the current class */ } - /* TODO: super? */ - } -#endif - sym = hcl_makesymbol(hcl, HCL_CNODE_GET_TOKPTR(obj), HCL_CNODE_GET_TOKLEN(obj)); - if (HCL_UNLIKELY(!sym)) return -1; - cons = (hcl_oop_t)hcl_getatsysdic(hcl, sym); + if (x <= -1) return -1; /* error */ + if (x >= 1) + { + /* found */ + HCL_ASSERT (hcl, vi.type != VAR_NAMED); + return emit_variable_access(hcl, VAR_ACCESS_PUSH, &vi, HCL_CNODE_GET_LOC(obj)); + } + +/* TODO: check if it's the method name??? NOT POSSIBLE??? */ + + /* if not found or not beginning with self/super, carry on with remaining resolution methods */ + } + + cons = (hcl_oop_t)hcl_lookupsysdicforsymbol_noseterr(hcl, HCL_CNODE_GET_TOK(obj)); if (!cons) { /* query the module for information if it is the first time @@ -4055,7 +4081,7 @@ HCL_DEBUG1 (hcl, ">>>> instance variable or method %js\n", sep + 1); hcl_pfbase_t* pfbase; hcl_mod_t* mod; - hcl_oop_t val; + hcl_oop_t sym, val; unsigned int kernel_bits; pfbase = hcl_querymod(hcl, HCL_CNODE_GET_TOKPTR(obj), HCL_CNODE_GET_TOKLEN(obj), &mod); @@ -4065,6 +4091,9 @@ HCL_DEBUG1 (hcl, ">>>> instance variable or method %js\n", sep + 1); return -1; } + sym = hcl_makesymbol(hcl, HCL_CNODE_GET_TOKPTR(obj), HCL_CNODE_GET_TOKLEN(obj)); + if (HCL_UNLIKELY(!sym)) return -1; + hcl_pushvolat (hcl, &sym); switch (pfbase->type) { @@ -5228,7 +5257,7 @@ static HCL_INLINE int post_lambda (hcl_t* hcl) if (is_in_class_init_scope(hcl)) { /* method definition */ - x = find_variable_backward(hcl, defun_name, &vi); + x = find_variable_backward_with_token(hcl, defun_name, &vi); if (x <= -1) return -1; if (x == 0) { @@ -5264,7 +5293,7 @@ static HCL_INLINE int post_lambda (hcl_t* hcl) } else { - x = find_variable_backward(hcl, defun_name, &vi); + x = find_variable_backward_with_token(hcl, defun_name, &vi); if (x <= -1) return -1; if (x == 0) { diff --git a/lib/prim.c b/lib/prim.c index 3b9ee5a..09b488d 100644 --- a/lib/prim.c +++ b/lib/prim.c @@ -408,6 +408,24 @@ static hcl_pfrc_t pf_is_lambda (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) return HCL_PF_SUCCESS; } +static hcl_pfrc_t pf_is_class (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) +{ + hcl_oop_t rv, x; + x = HCL_STACK_GETARG(hcl, nargs, 0); + rv = (HCL_IS_CLASS(hcl, x))? hcl->_true: hcl->_false; + HCL_STACK_SETRET (hcl, nargs, rv); + return HCL_PF_SUCCESS; +} + +static hcl_pfrc_t pf_is_object (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) +{ + hcl_oop_t rv, x; + x = HCL_STACK_GETARG(hcl, nargs, 0); + rv = (HCL_IS_INSTANCE(hcl, x))? hcl->_true: hcl->_false; + HCL_STACK_SETRET (hcl, nargs, rv); + return HCL_PF_SUCCESS; +} + /* ------------------------------------------------------------------------- */ static hcl_pfrc_t pf_not (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) @@ -918,6 +936,9 @@ static pf_t builtin_prims[] = { 1, 1, pf_is_bytearray, 10, { 'b','y','t','e','a','r','r','a','y','?' } }, { 1, 1, pf_is_dictionary, 11, { 'd','i','c','t','i','o','n','a','r','y','?' } }, { 1, 1, pf_is_lambda, 7, { 'l','a','m','b','d','a','?' } }, + { 1, 1, pf_is_lambda, 4, { 'f','u','n','?' } }, + { 1, 1, pf_is_class, 6, { 'c','l','a','s','s','?' } }, + { 1, 1, pf_is_object, 7, { 'o','b','j','e','c','t','?' } }, { 1, HCL_TYPE_MAX(hcl_oow_t), pf_number_add, 1, { '+' } }, diff --git a/lib/read.c b/lib/read.c index 3057242..c9f1b57 100644 --- a/lib/read.c +++ b/lib/read.c @@ -377,9 +377,9 @@ static HCL_INLINE int is_alnumchar (hcl_ooci_t c) static HCL_INLINE int is_delimchar (hcl_ooci_t c) { return c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || - c == ';' || c == '|' || c == ',' || c == '.' || c == ':' || c == ';' || + c == '|' || c == ',' || c == '.' || c == ':' || c == ';' || /* the first characters of tokens in delim_token_tab up to this point */ - c == '#' || c == '\"' || c == '\'' || is_spacechar(c) || c == HCL_UCI_EOF; + c == '#' || c == '\"' || c == '\'' || is_spacechar(c) || c == HCL_UCI_EOF; } static int copy_string_to (hcl_t* hcl, const hcl_oocs_t* src, hcl_oocs_t* dst, hcl_oow_t* dst_capa, int append, hcl_ooch_t add_delim) @@ -2162,8 +2162,16 @@ static int flx_plain_ident (hcl_t* hcl, hcl_ooci_t c) /* identifier */ tok_type = classify_ident_token(hcl, &seg); if (tok_type != HCL_TOK_IDENT) { - pi->non_ident_seg_count++; - pi->last_non_ident_type = tok_type; + if (pi->seg_count == 0 && (tok_type == HCL_TOK_SELF || tok_type == HCL_TOK_SUPER)) + { + /* allowed if it begins with self. or super. */ + /* nothing to do */ + } + else + { + pi->non_ident_seg_count++; + pi->last_non_ident_type = tok_type; + } } pi->seg_len = 0; /* the length of the segment to be worked on */ @@ -2192,7 +2200,10 @@ static int flx_plain_ident (hcl_t* hcl, hcl_ooci_t c) /* identifier */ } } - FEED_WRAP_UP (hcl, (pi->seg_count == 1? HCL_TOK_IDENT: HCL_TOK_IDENT_DOTTED)); + /* if single-segmented, perform classification(call classify_ident_token()) again + * bcause self and super as the first segment have not been marked as a non-identifier above */ + tok_type = (pi->seg_count == 1? classify_ident_token(hcl, TOKEN_NAME(hcl)): HCL_TOK_IDENT_DOTTED); + FEED_WRAP_UP (hcl, tok_type); goto not_consumed; } else