From cd67f4b3374f86fe8d2a1bafa640453f648dc32c Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 6 Jul 2024 14:29:07 +0900 Subject: [PATCH] preparing to handle instance/class variables in a new style --- lib/comp.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/lib/comp.c b/lib/comp.c index b35e729..ac66354 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -1394,6 +1394,65 @@ static HCL_INLINE hcl_cframe_t* find_cframe_from_top (hcl_t* hcl, int opcode) /* ========================================================================= */ +static int collect_vardcl_for_class (hcl_t* hcl, hcl_cnode_t* obj, hcl_cnode_t** nextobj, hcl_oow_t tv_dup_check_start, hcl_oow_t* nvardcls, const hcl_bch_t* desc) +{ + hcl_oow_t ndcls = 0; + hcl_oow_t old_wcount = hcl->c->tv.wcount; + hcl_cnode_t* dcl; + hcl_cnode_t* var; + int coloned = 0; + + dcl = HCL_CNODE_CONS_CAR(obj); + HCL_ASSERT (hcl, HCL_CNODE_IS_CONS_CONCODED(dcl, HCL_CONCODE_XLIST)); + + do + { + var = HCL_CNODE_CONS_CAR(dcl); + + if (HCL_CNODE_IS_COLON(var)) + { + if (coloned) goto synerr_varname; + coloned = 1; + goto next; + } + + if (!HCL_CNODE_IS_SYMBOL_PLAIN(var)) + { + synerr_varname: + hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAME, HCL_CNODE_GET_LOC(var), HCL_CNODE_GET_TOK(var), "not variable name"); + return -1; + } + + + if (add_temporary_variable(hcl, HCL_CNODE_GET_TOK(var), tv_dup_check_start) <= -1) + { + if (hcl->errnum == HCL_EEXIST) + { + hcl_setsynerrbfmt (hcl, HCL_SYNERR_ARGNAMEDUP, HCL_CNODE_GET_LOC(var), HCL_CNODE_GET_TOK(var), "duplicate %hs variable", desc); + } + return -1; + } + ndcls++; + + next: + dcl = HCL_CNODE_CONS_CDR(dcl); + if (!dcl) break; + + if (!HCL_CNODE_IS_CONS(dcl)) + { + hcl_setsynerrbfmt (hcl, HCL_SYNERR_DOTBANNED, HCL_CNODE_GET_LOC(dcl), HCL_CNODE_GET_TOK(dcl), "redundant cdr in %hs variable list", desc); + return -1; + } + } + while (1); + + HCL_ASSERT (hcl, ndcls == hcl->c->tv.wcount - old_wcount); + *nextobj = HCL_CNODE_CONS_CDR(obj); + *nvardcls = ndcls; + + return 0; +} + static int collect_vardcl (hcl_t* hcl, hcl_cnode_t* obj, hcl_cnode_t** nextobj, hcl_oow_t tv_dup_check_start, hcl_oow_t* nvardcls, const hcl_bch_t* desc) { /* process a single variable declaration list */ @@ -2533,7 +2592,30 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl) ) */ tmp = HCL_CNODE_CONS_CAR(obj); - if (/*HCL_CNODE_IS_COLON(tmp)|| */ HCL_CNODE_IS_DBLCOLONS(tmp)) + if (HCL_CNODE_IS_CONS_CONCODED(tmp, HCL_CONCODE_XLIST)) + { + /* instance variables */ + hcl_oow_t checkpoint; + + checkpoint = hcl->c->tv.s.len; + + if (collect_vardcl_for_class(hcl, obj, &obj, tv_dup_check_start, &dclcount, "instance") <= -1) return -1; + nivars += dclcount; + + if (ivar_len <= 0) ivar_start = (cvar_len <= 0)? checkpoint: cvar_start; + ivar_len += hcl->c->tv.s.len - checkpoint; + + if (cvar_len > 0) + { + /* place the instance variables before the class variables + * if class variables "a b" has been collected before instance variables "cc dd ee" + * the rotation below manipulates the buffer to contain "cc dd ee a b". + */ + hcl_rotate_oochars (&hcl->c->tv.s.ptr[cvar_start], hcl->c->tv.s.len - cvar_start, -1, cvar_len); + cvar_start += hcl->c->tv.s.len - checkpoint; + } + } + else if (/*HCL_CNODE_IS_COLON(tmp)|| */ HCL_CNODE_IS_DBLCOLONS(tmp)) { /* class variables */ hcl_oow_t checkpoint; @@ -2555,6 +2637,7 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl) checkpoint = hcl->c->tv.s.len; if (collect_vardcl(hcl, obj, &obj, tv_dup_check_start, &dclcount, "class") <= -1) return -1; ncvars += dclcount; + if (cvar_len <= 0) cvar_start = checkpoint; cvar_len += hcl->c->tv.s.len - checkpoint; }