From bcaae10bef16331c586a229b734ca66a4dcef5ec Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Wed, 2 Oct 2024 19:14:10 +0900 Subject: [PATCH] updated compile_fun() to check attribute list after having found class_name, fun_name, arg_list --- lib/comp.c | 110 +++++++++++++++++++++++++++++++++--------------- t/feed-5001.err | 17 -------- t/var-5004.err | 34 +++++++++++++++ 3 files changed, 111 insertions(+), 50 deletions(-) diff --git a/lib/comp.c b/lib/comp.c index d61417e..b2a2790 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -2817,7 +2817,9 @@ static HCL_INLINE int compile_class_p2 (hcl_t* hcl) /* ========================================================================= */ -static int check_fun_attr_list (hcl_t* hcl, hcl_cnode_t* attr_list, unsigned int* fun_type) +static int check_fun_attr_list ( + hcl_t* hcl, hcl_cnode_t* attr_list, unsigned int* fun_type, + hcl_cnode_t* cmd, hcl_cnode_t* class_name, hcl_cnode_t* fun_name) { unsigned int ft; @@ -2827,7 +2829,37 @@ static int check_fun_attr_list (hcl_t* hcl, hcl_cnode_t* attr_list, unsigned int HCL_ASSERT (hcl, HCL_CNODE_IS_CONS_CONCODED(attr_list, HCL_CONCODE_XLIST) || HCL_CNODE_IS_ELIST_CONCODED(attr_list, HCL_CONCODE_XLIST)); - if (HCL_CNODE_IS_CONS(attr_list)) + if (HCL_CNODE_IS_ELIST_CONCODED(attr_list, HCL_CONCODE_XLIST)) + { + /* don't allow empty attribute list */ + if (class_name && fun_name) + { + hcl_setsynerrbfmt ( + hcl, HCL_SYNERR_FUN, HCL_CNODE_GET_LOC(attr_list), HCL_NULL, + "empty attribute list for '%.*js:%.*js' for '%.*js'", + HCL_CNODE_GET_TOKLEN(class_name), HCL_CNODE_GET_TOKPTR(class_name), + HCL_CNODE_GET_TOKLEN(fun_name), HCL_CNODE_GET_TOKPTR(fun_name), + HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); + } + else if (fun_name) + { + hcl_setsynerrbfmt ( + hcl, HCL_SYNERR_FUN, HCL_CNODE_GET_LOC(attr_list), HCL_NULL, + "empty attribute list for '%.*js' for '%.*js'", + HCL_CNODE_GET_TOKLEN(fun_name), HCL_CNODE_GET_TOKPTR(fun_name), + HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); + } + else + { + hcl_setsynerrbfmt ( + hcl, HCL_SYNERR_FUN, HCL_CNODE_GET_LOC(attr_list), HCL_NULL, + "empty attribute list after unamed function for '%.*js'", + HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); + } + return -1; + } + + if (HCL_CNODE_IS_CONS_CONCODED(attr_list, HCL_CONCODE_XLIST)) { hcl_cnode_t* c, * a; const hcl_ooch_t* tokptr; @@ -2892,6 +2924,7 @@ static int compile_fun (hcl_t* hcl, hcl_cnode_t* src) hcl_oow_t saved_tv_wcount, tv_dup_start; hcl_cnode_t* fun_name; hcl_cnode_t* class_name; + hcl_cnode_t* attr_list; hcl_cnode_t* arg_list; hcl_cnode_t* fun_body; hcl_cframe_t* cf; @@ -2904,6 +2937,7 @@ static int compile_fun (hcl_t* hcl, hcl_cnode_t* src) next = HCL_CNODE_CONS_CDR(src); fun_name = HCL_NULL; class_name = HCL_NULL; + attr_list = HCL_NULL; arg_list = HCL_NULL; fun_body = HCL_NULL; fun_type = FUN_PLAIN; @@ -2914,12 +2948,10 @@ static int compile_fun (hcl_t* hcl, hcl_cnode_t* src) if (next) { hcl_cnode_t* tmp; - hcl_cnode_t* attr_list; /* the reader ensures that the cdr field of a cons cell points to the next cell. * and only the field of the last cons cell is NULL. */ HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(next)); - attr_list = HCL_NULL; /* fun (arg..) * fun name (arg..) @@ -2977,9 +3009,6 @@ static int compile_fun (hcl_t* hcl, hcl_cnode_t* src) return -1; } fun_name = tmp; - fun_type = FUN_IM; - if (attr_list && check_fun_attr_list(hcl, attr_list, &fun_type) <= -1) return -1; - fun_type |= 0x100; /* indicate that the function was defined in 'fun class:name()' style */ next = HCL_CNODE_CONS_CDR(next); if (!next) @@ -3005,32 +3034,6 @@ static int compile_fun (hcl_t* hcl, hcl_cnode_t* src) return -1; } } - else - { - /* no 'class:' part after 'fun' */ - if (is_in_class_init_scope(hcl)) - { - /* TODO:THIS IS ALSO WRONG. - * class X { - * a := (fun x(){}) ## this context is also class_init_scope. so the check above isn't good enough - * } */ - fun_type = FUN_IM; - if (attr_list && check_fun_attr_list(hcl, attr_list, &fun_type) <= -1) return -1; - } - else - { - /* as of now, the plain function doesn't support attribute list. - * this can change in the future. */ - if (attr_list) - { - hcl_setsynerrbfmt ( - hcl, HCL_SYNERR_FUN, HCL_CNODE_GET_LOC(attr_list), HCL_NULL, - "unsupported attribute list for plain function '%.*js'", - HCL_CNODE_GET_TOKLEN(fun_name), HCL_CNODE_GET_TOKPTR(fun_name)); - return -1; - } - } - } } if (HCL_CNODE_IS_CONS_CONCODED(tmp, HCL_CONCODE_XLIST) || @@ -3157,6 +3160,47 @@ static int compile_fun (hcl_t* hcl, hcl_cnode_t* src) return -1; } + if (attr_list) + { + if (is_in_class_init_scope(hcl) || class_name) + { +/* TODO: */ + /* TODO: THIS IS ALSO WRONG. + * class X { + * a := (fun x(){}) ## this context is also class_init_scope. so the check above isn't good enough + * } */ + fun_type = FUN_IM; + if (check_fun_attr_list(hcl, attr_list, &fun_type, cmd, class_name, fun_name) <= -1) return -1; + if (class_name) fun_type |= 0x100; /* defined in `fun class:xxx` style outside class */ + } + else + { + if (fun_name) + { + hcl_setsynerrbfmt ( + hcl, HCL_SYNERR_FUN, HCL_CNODE_GET_LOC(attr_list), HCL_NULL, + "unsupported attribute list for plain function '%.*js'", + HCL_CNODE_GET_TOKLEN(fun_name), HCL_CNODE_GET_TOKPTR(fun_name)); + } + else + { + hcl_setsynerrbfmt ( + hcl, HCL_SYNERR_FUN, HCL_CNODE_GET_LOC(attr_list), HCL_NULL, + "unsupported attribute list for unamed function for '%.*js'", + HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); + } + return -1; + } + } + else + { + if (is_in_class_init_scope(hcl) || class_name) + { + fun_type = FUN_IM; + if (class_name) fun_type |= 0x100; + } + } + /* process the argument list */ va = 0; nargs = 0; diff --git a/t/feed-5001.err b/t/feed-5001.err index f75ad4a..0ad782f 100644 --- a/t/feed-5001.err +++ b/t/feed-5001.err @@ -134,23 +134,6 @@ printf if; ##ERROR: syntax error - 'if' prohibited in this context --- -fun :: fun1() { ##ERROR: syntax error - invalid function name '::' for 'fun' - return 10; -}; - ---- - -fun fun fun1() { ##ERROR: syntax error - invalid function name 'fun' for 'fun' - return 10; -}; - ---- - -fun(#ci) fun1() { ##ERROR: syntax error - unsupported attribute list for plain function 'fun1' -} - ---- - (10 + 20 30) ##ERROR: syntax error - redundant operand '30' --- diff --git a/t/var-5004.err b/t/var-5004.err index 6db00fe..25f6d1e 100644 --- a/t/var-5004.err +++ b/t/var-5004.err @@ -64,3 +64,37 @@ fun x (... a) { ##ERROR: syntax error - unexpected token 'a' after '...' for 'fu fun x (... : a) { ##ERROR: syntax error - : disallowed } + +--- + +fun :: fun1() { ##ERROR: syntax error - invalid function name '::' for 'fun' + return 10; +}; + +--- + +fun fun fun1() { ##ERROR: syntax error - invalid function name 'fun' for 'fun' + return 10; +}; + +--- + +fun(#ci) fun1() { ##ERROR: syntax error - unsupported attribute list for plain function 'fun1' +} + +--- + +fun() () { ##ERROR: syntax error - unsupported attribute list for unamed function for 'fun' +} + +--- + +fun() X:y() { ##ERROR: syntax error - empty attribute list for 'X:y' for 'fun' +} + +--- + +class X { + fun() y() { ##ERROR: syntax error - empty attribute list for 'y' for 'fun' + } +}