From ef293d35d48a2f6decc6dede0b9f54a028f41fc8 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Fri, 12 Sep 2025 23:12:49 +0900 Subject: [PATCH] updated the compiler to be more strict when it comes to the places where methods can be defined. yet to fix test cases --- lib/comp.c | 52 +++++++++++++++++++++++++++++++++++++++------------ lib/hak-prv.h | 4 ++++ lib/read.c | 10 +++++++--- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/lib/comp.c b/lib/comp.c index c70cfe7..ab8ac7a 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -337,6 +337,14 @@ static int is_in_class_init_scope (hak_t* hak) return fbi->clsblk_top >= 0; } +static int is_in_class_init_scope_but_not_at_llvl (hak_t* hak, hak_oow_t llvl) +{ + hak_funblk_info_t* fbi; + HAK_ASSERT(hak, hak->c->funblk.depth >= 0); + fbi = &hak->c->funblk.info[hak->c->funblk.depth]; + return fbi->clsblk_top >= 0 && hak->c->clsblk.info[fbi->clsblk_top].def_llvl != llvl; +} + static int is_in_class_method_scope (hak_t* hak) { hak_oow_t i; @@ -345,9 +353,7 @@ static int is_in_class_method_scope (hak_t* hak) for (i = hak->c->funblk.depth + 1; i > 0; ) { hak_funblk_info_t* fbi; - fbi = &hak->c->funblk.info[--i]; - if (fbi->clsblk_top >= 0) { if (i >= hak->c->funblk.depth) return 0; /* in class initialization scope */ @@ -1143,7 +1149,7 @@ static void pop_ctlblk (hak_t* hak) } static int push_clsblk ( - hak_t* hak, const hak_loc_t* errloc, hak_cnode_t* class_name, hak_oow_t nivars, hak_oow_t ncvars, + hak_t* hak, const hak_loc_t* errloc, hak_oow_t llvl, hak_cnode_t* class_name, hak_oow_t nivars, hak_oow_t ncvars, const hak_ooch_t* ivars_str, hak_oow_t ivars_strlen, const hak_ooch_t* cvars_str, hak_oow_t cvars_strlen) { hak_oow_t new_depth; @@ -1179,6 +1185,7 @@ static int push_clsblk ( ci = &hak->c->clsblk.info[new_depth]; HAK_MEMSET(ci, 0, HAK_SIZEOF(*ci)); + ci->def_llvl = llvl; ci->class_name = class_name; ci->nivars = nivars; ci->ncvars = ncvars; @@ -2940,6 +2947,7 @@ static int compile_class (hak_t* hak, hak_cnode_t* src) cf = GET_TOP_CFRAME(hak); cf->u._class.nsuperclasses = 0; /* unsed for CLASS_P2 */ cf->u._class.indexed_type = indexed_type; + cf->u._class.llvl = HAK_CNODE_GET_LLVL(src); cf->u._class.start_loc = *HAK_CNODE_GET_LOC(src); /* TODO: use *HAK_CNODE_GET_LOC(cmd) instead? */ cf->u._class.cmd_cnode = cmd; cf->u._class.class_name_cnode = class_name; /* duplicate with operand to COP_COMPILE_CLASS_P2 */ @@ -2948,6 +2956,7 @@ static int compile_class (hak_t* hak, hak_cnode_t* src) cf = GET_TOP_CFRAME(hak); cf->u._class.nsuperclasses = nsuperclasses; /* this needs to change if we support multiple superclasses... */ cf->u._class.indexed_type = indexed_type; + cf->u._class.llvl = HAK_CNODE_GET_LLVL(src); cf->u._class.start_loc = *HAK_CNODE_GET_LOC(src); /* TODO: use *HAK_CNODE_GET_LOC(cmd) instead? */ cf->u._class.cmd_cnode = cmd; cf->u._class.class_name_cnode = class_name; @@ -2993,7 +3002,7 @@ static HAK_INLINE int compile_class_p1 (hak_t* hak) if (check_block_expression_as_body(hak, obj, cf->u._class.cmd_cnode, FOR_CLASS) <= -1) return -1; - if (push_clsblk(hak, &cf->u._class.start_loc, + if (push_clsblk(hak, &cf->u._class.start_loc, cf->u._class.llvl, cf->u._class.class_name_cnode, vardcl.nivars, vardcl.ncvars, &hak->c->tv.s.ptr[vardcl.ivar_start], vardcl.ivar_len, &hak->c->tv.s.ptr[vardcl.cvar_start], vardcl.cvar_len) <= -1) goto oops; @@ -3423,6 +3432,26 @@ static int compile_fun (hak_t* hak, hak_cnode_t* src) } } + if (src->cn_llvl >= 2 && is_in_class_init_scope_but_not_at_llvl(hak, src->cn_llvl - 2)) + { + if (fun_name) + { + hak_setsynerrbfmt( + hak, HAK_SYNERR_FUN, HAK_CNODE_GET_LOC(cmd), HAK_NULL, + "function '%.*js' defined with '%.*js' prohibited in class initialziation context", + HAK_CNODE_GET_TOKLEN(fun_name), HAK_CNODE_GET_TOKPTR(fun_name), + HAK_CNODE_GET_TOKLEN(cmd), HAK_CNODE_GET_TOKPTR(cmd)); + } + else + { + hak_setsynerrbfmt( + hak, HAK_SYNERR_FUN, HAK_CNODE_GET_LOC(cmd), HAK_NULL, + "unnamed function defined with '%.*js' prohibited in class initialziation context", + HAK_CNODE_GET_TOKLEN(cmd), HAK_CNODE_GET_TOKPTR(cmd)); + } + return -1; + } + if (!fun_name && is_in_class_init_scope(hak)) { /* TODO: it must allow as rvalue.. @@ -3465,7 +3494,7 @@ static int compile_fun (hak_t* hak, hak_cnode_t* src) return -1; } } - else + else /* !next */ { /* nothing after 'fun' (e.g. fun ) */ hak_setsynerrbfmt( @@ -3921,7 +3950,6 @@ static int compile_var (hak_t* hak, hak_cnode_t* src) POP_CFRAME(hak); return 0; - oops: return -1; } @@ -5802,12 +5830,12 @@ static int compile_object_list (hak_t* hak) cf = GET_TOP_CFRAME(hak); HAK_ASSERT(hak, cf->opcode == COP_COMPILE_ARGUMENT_LIST || - cf->opcode == COP_COMPILE_OBJECT_LIST || - cf->opcode == COP_COMPILE_OBJECT_LIST_TAIL || - cf->opcode == COP_COMPILE_IF_OBJECT_LIST || - cf->opcode == COP_COMPILE_IF_OBJECT_LIST_TAIL || - cf->opcode == COP_COMPILE_TRY_OBJECT_LIST || - cf->opcode == COP_COMPILE_TRY_OBJECT_LIST_TAIL); + cf->opcode == COP_COMPILE_OBJECT_LIST || + cf->opcode == COP_COMPILE_OBJECT_LIST_TAIL || + cf->opcode == COP_COMPILE_IF_OBJECT_LIST || + cf->opcode == COP_COMPILE_IF_OBJECT_LIST_TAIL || + cf->opcode == COP_COMPILE_TRY_OBJECT_LIST || + cf->opcode == COP_COMPILE_TRY_OBJECT_LIST_TAIL); cop = cf->opcode; oprnd = cf->operand; diff --git a/lib/hak-prv.h b/lib/hak-prv.h index 31045ba..37bd998 100644 --- a/lib/hak-prv.h +++ b/lib/hak-prv.h @@ -460,6 +460,7 @@ typedef enum hak_cnode_flag_t hak_cnode_flag_t; #define HAK_CNODE_GET_TYPE(x) ((x)->cn_type) #define HAK_CNODE_GET_FLAGS(x) ((x)->cn_flags) +#define HAK_CNODE_GET_LLVL(x) ((x)->cn_llvl) #define HAK_CNODE_GET_LOC(x) (&(x)->cn_loc) #define HAK_CNODE_GET_TOK(x) (&(x)->cn_tok) #define HAK_CNODE_GET_TOKPTR(x) ((x)->cn_tok.ptr) @@ -505,6 +506,7 @@ struct hak_cnode_t int cn_flags; hak_loc_t cn_loc; hak_oocs_t cn_tok; + hak_oow_t cn_llvl; /* list level */ union { @@ -685,6 +687,7 @@ struct hak_cframe_t { hak_ooi_t nsuperclasses; unsigned int indexed_type; + hak_oow_t llvl; /* copied from cnode->cn_llvl */ hak_loc_t start_loc; hak_cnode_t* cmd_cnode; hak_cnode_t* class_name_cnode; @@ -738,6 +741,7 @@ typedef struct hak_funblk_info_t hak_funblk_info_t; struct hak_clsblk_info_t { + hak_oow_t def_llvl; /* defined list level */ hak_cnode_t* class_name; hak_oocsc_t ivars; diff --git a/lib/read.c b/lib/read.c index e355813..282ef3c 100644 --- a/lib/read.c +++ b/lib/read.c @@ -1553,6 +1553,7 @@ static int feed_process_token (hak_t* hak) int oldflagv; frd->expect_vlist_item = 0; frd->obj = leave_list(hak, &frd->list_loc, &frd->flagv, &oldflagv); + if (HAK_LIKELY(frd->obj)) frd->obj->cn_llvl = frd->level; frd->level--; frd->flagv |= AT_BEGINNING; list_loc = &frd->list_loc; @@ -1786,6 +1787,7 @@ static int feed_process_token (hak_t* hak) #endif frd->obj = leave_list(hak, &frd->list_loc, &frd->flagv, &oldflagv); + if (HAK_LIKELY(frd->obj)) frd->obj->cn_llvl = frd->level; /* list level */ frd->level--; frd->flagv |= AT_BEGINNING; /* the current one is over. move on the beginning for the next expression */ list_loc = &frd->list_loc; @@ -2027,6 +2029,8 @@ static int feed_process_token (hak_t* hak) if (!frd->obj) goto oops; /* TODO: this doesn't have to be checked if jump has been made to auto_xlist... so restructure the flow */ + frd->obj->cn_llvl = frd->level; /* list level */ + #if 0 /* check if the element is read for a quoted list */ while (flagv & QUOTED) @@ -2539,7 +2543,7 @@ static int flx_dollared_ident (hak_t* hak, hak_ooci_t c) } else { - hak_setsynerrbfmt ( + hak_setsynerrbfmt( hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), HAK_NULL, "invalid dollar-prefixed identifier character '%jc' after '%.*js'", c, TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak)); @@ -2853,7 +2857,7 @@ static int flx_hmarked_ident (hak_t* hak, hak_ooci_t c) } else { - hak_setsynerrbfmt ( + hak_setsynerrbfmt( hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), HAK_NULL, "invalid symbol character '%jc' after '%.*js'", c, TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak)); @@ -2963,7 +2967,7 @@ static int flx_plain_ident (hak_t* hak, hak_ooci_t c) /* identifier */ } else { - hak_setsynerrbfmt ( + hak_setsynerrbfmt( hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), HAK_NULL, "invalid identifier character '%jc' after '%.*js'", c, TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak));