updated compile_fun() to check attribute list after having found class_name, fun_name, arg_list
This commit is contained in:
parent
506b8fd9d7
commit
bcaae10bef
110
lib/comp.c
110
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;
|
||||
|
@ -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'
|
||||
|
||||
---
|
||||
|
@ -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'
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user