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; 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) static int is_in_class_method_scope (hak_t* hak)
{ {
hak_oow_t i; 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; ) for (i = hak->c->funblk.depth + 1; i > 0; )
{ {
hak_funblk_info_t* fbi; hak_funblk_info_t* fbi;
fbi = &hak->c->funblk.info[--i]; fbi = &hak->c->funblk.info[--i];
if (fbi->clsblk_top >= 0) if (fbi->clsblk_top >= 0)
{ {
if (i >= hak->c->funblk.depth) return 0; /* in class initialization scope */ 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 ( 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) 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; hak_oow_t new_depth;
@ -1179,6 +1185,7 @@ static int push_clsblk (
ci = &hak->c->clsblk.info[new_depth]; ci = &hak->c->clsblk.info[new_depth];
HAK_MEMSET(ci, 0, HAK_SIZEOF(*ci)); HAK_MEMSET(ci, 0, HAK_SIZEOF(*ci));
ci->def_llvl = llvl;
ci->class_name = class_name; ci->class_name = class_name;
ci->nivars = nivars; ci->nivars = nivars;
ci->ncvars = ncvars; ci->ncvars = ncvars;
@ -2940,6 +2947,7 @@ static int compile_class (hak_t* hak, hak_cnode_t* src)
cf = GET_TOP_CFRAME(hak); cf = GET_TOP_CFRAME(hak);
cf->u._class.nsuperclasses = 0; /* unsed for CLASS_P2 */ cf->u._class.nsuperclasses = 0; /* unsed for CLASS_P2 */
cf->u._class.indexed_type = indexed_type; 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.start_loc = *HAK_CNODE_GET_LOC(src); /* TODO: use *HAK_CNODE_GET_LOC(cmd) instead? */
cf->u._class.cmd_cnode = cmd; cf->u._class.cmd_cnode = cmd;
cf->u._class.class_name_cnode = class_name; /* duplicate with operand to COP_COMPILE_CLASS_P2 */ 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 = GET_TOP_CFRAME(hak);
cf->u._class.nsuperclasses = nsuperclasses; /* this needs to change if we support multiple superclasses... */ cf->u._class.nsuperclasses = nsuperclasses; /* this needs to change if we support multiple superclasses... */
cf->u._class.indexed_type = indexed_type; 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.start_loc = *HAK_CNODE_GET_LOC(src); /* TODO: use *HAK_CNODE_GET_LOC(cmd) instead? */
cf->u._class.cmd_cnode = cmd; cf->u._class.cmd_cnode = cmd;
cf->u._class.class_name_cnode = class_name; 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 (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, 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.ivar_start], vardcl.ivar_len,
&hak->c->tv.s.ptr[vardcl.cvar_start], vardcl.cvar_len) <= -1) goto oops; &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)) if (!fun_name && is_in_class_init_scope(hak))
{ {
/* TODO: it must allow as rvalue.. /* TODO: it must allow as rvalue..
@ -3465,7 +3494,7 @@ static int compile_fun (hak_t* hak, hak_cnode_t* src)
return -1; return -1;
} }
} }
else else /* !next */
{ {
/* nothing after 'fun' (e.g. fun ) */ /* nothing after 'fun' (e.g. fun ) */
hak_setsynerrbfmt( hak_setsynerrbfmt(
@ -3921,7 +3950,6 @@ static int compile_var (hak_t* hak, hak_cnode_t* src)
POP_CFRAME(hak); POP_CFRAME(hak);
return 0; return 0;
oops: oops:
return -1; 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_TYPE(x) ((x)->cn_type)
#define HAK_CNODE_GET_FLAGS(x) ((x)->cn_flags) #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_LOC(x) (&(x)->cn_loc)
#define HAK_CNODE_GET_TOK(x) (&(x)->cn_tok) #define HAK_CNODE_GET_TOK(x) (&(x)->cn_tok)
#define HAK_CNODE_GET_TOKPTR(x) ((x)->cn_tok.ptr) #define HAK_CNODE_GET_TOKPTR(x) ((x)->cn_tok.ptr)
@ -505,6 +506,7 @@ struct hak_cnode_t
int cn_flags; int cn_flags;
hak_loc_t cn_loc; hak_loc_t cn_loc;
hak_oocs_t cn_tok; hak_oocs_t cn_tok;
hak_oow_t cn_llvl; /* list level */
union union
{ {
@ -685,6 +687,7 @@ struct hak_cframe_t
{ {
hak_ooi_t nsuperclasses; hak_ooi_t nsuperclasses;
unsigned int indexed_type; unsigned int indexed_type;
hak_oow_t llvl; /* copied from cnode->cn_llvl */
hak_loc_t start_loc; hak_loc_t start_loc;
hak_cnode_t* cmd_cnode; hak_cnode_t* cmd_cnode;
hak_cnode_t* class_name_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 struct hak_clsblk_info_t
{ {
hak_oow_t def_llvl; /* defined list level */
hak_cnode_t* class_name; hak_cnode_t* class_name;
hak_oocsc_t ivars; hak_oocsc_t ivars;

View File

@ -1553,6 +1553,7 @@ static int feed_process_token (hak_t* hak)
int oldflagv; int oldflagv;
frd->expect_vlist_item = 0; frd->expect_vlist_item = 0;
frd->obj = leave_list(hak, &frd->list_loc, &frd->flagv, &oldflagv); 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->level--;
frd->flagv |= AT_BEGINNING; frd->flagv |= AT_BEGINNING;
list_loc = &frd->list_loc; list_loc = &frd->list_loc;
@ -1786,6 +1787,7 @@ static int feed_process_token (hak_t* hak)
#endif #endif
frd->obj = leave_list(hak, &frd->list_loc, &frd->flagv, &oldflagv); 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->level--;
frd->flagv |= AT_BEGINNING; /* the current one is over. move on the beginning for the next expression */ frd->flagv |= AT_BEGINNING; /* the current one is over. move on the beginning for the next expression */
list_loc = &frd->list_loc; 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 */ 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 #if 0
/* check if the element is read for a quoted list */ /* check if the element is read for a quoted list */
while (flagv & QUOTED) while (flagv & QUOTED)
@ -2539,7 +2543,7 @@ static int flx_dollared_ident (hak_t* hak, hak_ooci_t c)
} }
else else
{ {
hak_setsynerrbfmt ( hak_setsynerrbfmt(
hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), HAK_NULL, hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), HAK_NULL,
"invalid dollar-prefixed identifier character '%jc' after '%.*js'", c, "invalid dollar-prefixed identifier character '%jc' after '%.*js'", c,
TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak)); 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 else
{ {
hak_setsynerrbfmt ( hak_setsynerrbfmt(
hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), HAK_NULL, hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), HAK_NULL,
"invalid symbol character '%jc' after '%.*js'", c, "invalid symbol character '%jc' after '%.*js'", c,
TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak)); 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 else
{ {
hak_setsynerrbfmt ( hak_setsynerrbfmt(
hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), HAK_NULL, hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), HAK_NULL,
"invalid identifier character '%jc' after '%.*js'", c, "invalid identifier character '%jc' after '%.*js'", c,
TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak)); TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak));