updated the compiler to be more strict when it comes to the places where methods can be defined.

yet to fix test cases
This commit is contained in:
2025-09-12 23:12:49 +09:00
parent fe18991a4e
commit ef293d35d4
3 changed files with 51 additions and 15 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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)