adding code to support class attribute list. work in progress
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
hyung-hwan 2024-10-05 00:05:52 +09:00
parent f4d223f646
commit 3f350dd38a
8 changed files with 190 additions and 43 deletions

View File

@ -2464,6 +2464,132 @@ static HCL_INLINE int compile_else (hcl_t* hcl)
/* ========================================================================= */
static int check_class_attr_list (hcl_t* hcl, hcl_cnode_t* attr_list, unsigned int* indexed_type, hcl_cnode_t* cmd, hcl_cnode_t* class_name)
{
static struct
{
const hcl_bch_t* name;
unsigned int flag;
} flag_tab[] = {
{ "v", HCL_CLASS_SPEC_FLAG_INDEXED },
{ "var", HCL_CLASS_SPEC_FLAG_INDEXED },
{ "variable", HCL_CLASS_SPEC_FLAG_INDEXED },
{ "immutable", HCL_CLASS_SPEC_FLAG_IMMUTABLE },
{ "uncopyable", HCL_CLASS_SPEC_FLAG_UNCOPYABLE },
};
static struct
{
const hcl_bch_t* name;
hcl_obj_type_t indexed_type;
} type_tab[] = {
{ "b", HCL_OBJ_TYPE_BYTE },
{ "byte", HCL_OBJ_TYPE_BYTE },
{ "c", HCL_OBJ_TYPE_CHAR },
{ "char", HCL_OBJ_TYPE_CHAR },
{ "character", HCL_OBJ_TYPE_CHAR },
{ "halfword", HCL_OBJ_TYPE_HALFWORD },
{ "hw", HCL_OBJ_TYPE_HALFWORD },
{ "w", HCL_OBJ_TYPE_WORD },
{ "word", HCL_OBJ_TYPE_WORD }
/* TODO: uint32 uint16 .. etc */
};
hcl_obj_type_t ct;
ct = HCL_OBJ_TYPE_OOP;
HCL_ASSERT (hcl, attr_list != HCL_NULL);
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_ELIST_CONCODED(attr_list, HCL_CONCODE_XLIST))
{
/* don't allow empty attribute list */
if (class_name)
{
hcl_setsynerrbfmt (
hcl, HCL_SYNERR_FUN, HCL_CNODE_GET_LOC(attr_list), HCL_NULL,
"empty attribute list on '%.*js' for '%.*js'",
HCL_CNODE_GET_TOKLEN(class_name), HCL_CNODE_GET_TOKPTR(class_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 on unamed class 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;
hcl_oow_t toklen, i;
c = attr_list;
while (c)
{
a = HCL_CNODE_CONS_CAR(c);
tokptr = HCL_CNODE_GET_TOKPTR(a);
toklen = HCL_CNODE_GET_TOKLEN(a);
if (!HCL_CNODE_IS_TYPED(a, HCL_CNODE_SYMLIT))
{
hcl_setsynerrbfmt (
hcl, HCL_SYNERR_FUN, HCL_CNODE_GET_LOC(a), HCL_NULL,
"invalid class attribute name '%.*js'", toklen, tokptr);
return -1;
}
for (i = 0; i < HCL_COUNTOF(flag_tab); i++)
{
if (hcl_comp_oochars_bcstr(tokptr, toklen, flag_tab[i].name) == 0)
{
if ((ct >> 8) & flag_tab[i].flag)
{
conflict:
hcl_setsynerrbfmt (
hcl, HCL_SYNERR_FUN, HCL_CNODE_GET_LOC(a), HCL_NULL,
"conflicting or duplicate class attribute name '%.*js'", toklen, tokptr);
return -1;
}
ct |= (flag_tab[i].flag << 8);
break;
}
}
if (i >= HCL_COUNTOF(flag_tab))
{
for (i = 0; i < HCL_COUNTOF(type_tab); i++)
{
if (hcl_comp_oochars_bcstr(tokptr, toklen, type_tab[i].name) == 0)
{
if (ct & 0x7F) goto conflict;
ct = type_tab[i].indexed_type;
break;
}
}
if (i >= HCL_COUNTOF(type_tab))
{
hcl_setsynerrbfmt (
hcl, HCL_SYNERR_FUN, HCL_CNODE_GET_LOC(a), HCL_NULL,
"unrecognized class attribute name '%.*js'", toklen, tokptr);
return -1;
}
}
c = HCL_CNODE_CONS_CDR(c);
}
}
*indexed_type = ct;
return 0;
}
/*
(class A
[ x y ] ## instance variables
@ -2495,29 +2621,42 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src)
{
hcl_cframe_t* cf;
hcl_cnode_t* cmd, * obj, * tmp;
hcl_cnode_t* attr_list;
hcl_cnode_t* class_name, * superclass;
int nsuperclasses;
unsigned int indexed_type;
cmd = HCL_CNODE_CONS_CAR(src);
obj = HCL_CNODE_CONS_CDR(src);
attr_list = HCL_NULL;
class_name = HCL_NULL;
indexed_type = HCL_OBJ_TYPE_OOP;
HCL_ASSERT (hcl, HCL_CNODE_IS_TYPED(cmd, HCL_CNODE_CLASS));
/* TODO: attribute lsit */
if (obj /*&& HCL_CNODE_IS_CONS(obj)*/)
if (obj)
{
HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(obj));
tmp = HCL_CNODE_CONS_CAR(obj);
if (HCL_CNODE_IS_ELIST_CONCODED(tmp, HCL_CONCODE_XLIST) || HCL_CNODE_IS_CONS_CONCODED(tmp, HCL_CONCODE_XLIST))
{
attr_list = tmp;
obj = HCL_CNODE_CONS_CAR(obj) ;
}
}
if (obj)
{
HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(obj));
if (HCL_CNODE_IS_FOR_DATA_SIMPLE(tmp) || HCL_CNODE_IS_FOR_LANG(tmp))
{
if (!HCL_CNODE_IS_SYMBOL_IDENT(tmp))
{
hcl_setsynerrbfmt (
hcl, HCL_SYNERR_VARNAME, HCL_CNODE_GET_LOC(tmp), HCL_NULL,
hcl, HCL_SYNERR_CLASS, HCL_CNODE_GET_LOC(tmp), HCL_NULL,
"invalid class name '%.*js' for '%.*js'",
HCL_CNODE_GET_TOKLEN(tmp), HCL_CNODE_GET_TOKPTR(tmp),
HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
@ -2534,19 +2673,23 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src)
if (class_name)
{
hcl_setsynerrbfmt (
hcl, HCL_SYNERR_BLOCK, HCL_CNODE_GET_LOC(src), HCL_NULL,
"no class body defined for '%.*js'",
HCL_CNODE_GET_TOKLEN(class_name), HCL_CNODE_GET_TOKPTR(class_name));
hcl, HCL_SYNERR_CLASS, HCL_CNODE_GET_LOC(src), HCL_NULL,
"incomplete definition of '%.*js' for '%.*js'",
HCL_CNODE_GET_TOKLEN(class_name), HCL_CNODE_GET_TOKPTR(class_name),
HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
}
else
{
hcl_setsynerrbfmt (
hcl, HCL_SYNERR_BLOCK, HCL_CNODE_GET_LOC(src), HCL_NULL,
"no class body defined for unnamed class");
hcl, HCL_SYNERR_CLASS, HCL_CNODE_GET_LOC(src), HCL_NULL,
"incomplete defintion of unnamed class for '%.*js'",
HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
}
return -1;
}
if (attr_list && check_class_attr_list(hcl, attr_list, &indexed_type, cmd, class_name) <= -1) return -1;
tmp = HCL_CNODE_CONS_CAR(obj);
if (HCL_CNODE_IS_COLON(tmp)) /* check for superclass marker */
{
@ -2557,7 +2700,7 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src)
if (!obj || !HCL_CNODE_IS_CONS(obj))
{
hcl_setsynerrbfmt (
hcl, HCL_SYNERR_EOX, HCL_CNODE_GET_LOC(marker), HCL_NULL,
hcl, HCL_SYNERR_CLASS, HCL_CNODE_GET_LOC(marker), HCL_NULL,
"no expression or declaration after %.*js",
HCL_CNODE_GET_TOKLEN(marker), HCL_CNODE_GET_TOKPTR(marker));
return -1;
@ -2570,7 +2713,7 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src)
if (HCL_CNODE_IS_FOR_DATA_SIMPLE(superclass) || HCL_CNODE_IS_FOR_LANG(superclass))
{
hcl_setsynerrbfmt (
hcl, HCL_SYNERR_NAME, HCL_CNODE_GET_LOC(marker), HCL_NULL,
hcl, HCL_SYNERR_CLASS, HCL_CNODE_GET_LOC(marker), HCL_NULL,
"invalid superclass name '%.*js' after '%.*js' for '%.*js'",
HCL_CNODE_GET_TOKLEN(superclass), HCL_CNODE_GET_TOKPTR(superclass),
HCL_CNODE_GET_TOKLEN(marker), HCL_CNODE_GET_TOKPTR(marker),
@ -2579,7 +2722,7 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src)
else
{
hcl_setsynerrbfmt (
hcl, HCL_SYNERR_NAME, HCL_CNODE_GET_LOC(marker), HCL_NULL,
hcl, HCL_SYNERR_CLASS, HCL_CNODE_GET_LOC(marker), HCL_NULL,
"no valid superclass name after '%.*js' for '%.*js'",
HCL_CNODE_GET_TOKLEN(marker), HCL_CNODE_GET_TOKPTR(marker),
HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
@ -2631,12 +2774,14 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src)
PUSH_CFRAME (hcl, COP_COMPILE_CLASS_P2, class_name); /* 3 - use class name for assignment */
cf = GET_TOP_CFRAME(hcl);
cf->u._class.nsuperclasses = 0; /* unsed for CLASS_P2 */
cf->u._class.indexed_type = indexed_type;
cf->u._class.start_loc = *HCL_CNODE_GET_LOC(src); /* TODO: use *HCL_CNODE_GET_LOC(cmd) instead? */
cf->u._class.cmd_cnode = cmd;
PUSH_CFRAME (hcl, COP_COMPILE_CLASS_P1, obj); /* 2 - variables declaraions and actual body */
cf = GET_TOP_CFRAME(hcl);
cf->u._class.nsuperclasses = nsuperclasses; /* this needs to change if we support multiple superclasses... */
cf->u._class.indexed_type = indexed_type;
cf->u._class.start_loc = *HCL_CNODE_GET_LOC(src); /* TODO: use *HCL_CNODE_GET_LOC(cmd) instead? */
cf->u._class.cmd_cnode = cmd;
@ -2723,6 +2868,7 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl)
/* class_enter nsuperclasses, nivars, ncvars */
if (emit_byte_instruction(hcl, HCL_CODE_CLASS_ENTER, &cf->u._class.start_loc) <= -1) goto oops;
if (emit_byte_instruction(hcl, (hcl_oob_t)cf->u._class.indexed_type, &cf->u._class.start_loc) <= -1) goto oops;
if (emit_long_param(hcl, cf->u._class.nsuperclasses) <= -1) goto oops;
if (emit_long_param(hcl, vardcl.nivars) <= -1) goto oops;
if (emit_long_param(hcl, vardcl.ncvars) <= -1) goto oops;
@ -2799,13 +2945,11 @@ 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,
hcl_cnode_t* cmd, hcl_cnode_t* class_name, hcl_cnode_t* fun_name)
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;
ft = 0;
ft = FUN_IM;
HCL_ASSERT (hcl, attr_list != HCL_NULL);
HCL_ASSERT (hcl, HCL_CNODE_IS_CONS_CONCODED(attr_list, HCL_CONCODE_XLIST) ||
@ -2866,7 +3010,7 @@ static int check_fun_attr_list (
if (hcl_comp_oochars_bcstr(tokptr, toklen, "class") == 0 ||
hcl_comp_oochars_bcstr(tokptr, toklen, "c") == 0)
{
if (ft != 0)
if (ft != FUN_IM)
{
conflicting:
hcl_setsynerrbfmt (
@ -2879,7 +3023,7 @@ static int check_fun_attr_list (
else if (hcl_comp_oochars_bcstr(tokptr, toklen, "classinst") == 0 ||
hcl_comp_oochars_bcstr(tokptr, toklen, "ci") == 0)
{
if (ft != 0) goto conflicting;
if (ft != FUN_IM) goto conflicting;
ft = FUN_CIM;
}
else
@ -3150,7 +3294,6 @@ static int compile_fun (hcl_t* hcl, hcl_cnode_t* src)
* 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 */
}
@ -3177,7 +3320,7 @@ static int compile_fun (hcl_t* hcl, hcl_cnode_t* src)
{
if (is_in_class_init_scope(hcl) || class_name)
{
fun_type = FUN_IM;
fun_type = FUN_IM;
if (class_name) fun_type |= 0x100;
}
}
@ -5163,13 +5306,7 @@ redo:
goto redo;
case HCL_CNODE_ELLIPSIS:
hcl_setsynerrbfmt (hcl, HCL_SYNERR_ELLIPSISBANNED, HCL_CNODE_GET_LOC(oprnd), HCL_CNODE_GET_TOK(oprnd), "ellipsis disallowed in this context", HCL_CNODE_GET_TYPE(oprnd));
return -1;
case HCL_CNODE_TRPCOLONS:
hcl_setsynerrbfmt (hcl, HCL_SYNERR_TRPCOLONSBANNED, HCL_CNODE_GET_LOC(oprnd), HCL_CNODE_GET_TOK(oprnd), "triple colons disallowed in this context", HCL_CNODE_GET_TYPE(oprnd));
return -1;
case HCL_CNODE_DBLCOLONS:
case HCL_CNODE_COLON:
case HCL_CNODE_COLONLT:

View File

@ -379,13 +379,13 @@ int hcl_decode (hcl_t* hcl, const hcl_code_t* code, hcl_oow_t start, hcl_oow_t e
case HCL_CODE_CLASS_ENTER:
{
hcl_oow_t b3;
hcl_oow_t b0, b3;
FETCH_BYTE_CODE_TO (hcl, b0);
FETCH_PARAM_CODE_TO (hcl, b1);
FETCH_PARAM_CODE_TO (hcl, b2);
FETCH_PARAM_CODE_TO (hcl, b3);
LOG_INST_3 (hcl, "class_enter %zu %zu %zu", b1, b2, b3);
LOG_INST_4 (hcl, "class_enter %zu %zu %zu %zu", b0, b1, b2, b3);
break;
}

View File

@ -110,7 +110,6 @@ static const char* synerrstr[] =
"invalid radix for a numeric literal",
"sudden end of input",
"sudden end of expression",
"( expected",
") expected",
"] expected",
@ -139,7 +138,6 @@ static const char* synerrstr[] =
"if body too big",
"block too big",
"block too deep",
"name expected",
"argument name list expected",
"argument name expected",
"duplicate argument name",
@ -155,6 +153,7 @@ static const char* synerrstr[] =
"disallowed argument name",
"disallowed",
"invalid class definition",
"invalid function definition",
"elif without if",
"else without if",

View File

@ -4032,18 +4032,19 @@ static int execute (hcl_t* hcl)
push superclass (only if nsuperclassses > 0)
push ivars_string
push cvars_string
class_enter nsuperclasses nivars ncvars
class_enter indexed_type nsuperclasses nivars ncvars
*/
hcl_oop_t superclass, ivars_str, cvars_str, class_name;
hcl_oop_t v;
hcl_oop_class_t class_obj;
hcl_oow_t b3;
hcl_oow_t b0, b3;
FETCH_BYTE_CODE_TO (hcl, b0); /* indexed_type */
FETCH_PARAM_CODE_TO (hcl, b1); /* nsuperclasses */
FETCH_PARAM_CODE_TO (hcl, b2); /* nivars */
FETCH_PARAM_CODE_TO (hcl, b3); /* ncvars */
LOG_INST_3 (hcl, "class_enter %zu %zu %zu", b1, b2, b3);
LOG_INST_4 (hcl, "class_enter %zu %zu %zu %zu", b0, b1, b2, b3);
if (b3 > 0)
{
@ -4073,7 +4074,6 @@ static int execute (hcl_t* hcl)
HCL_STACK_POP_TO(hcl, v);
//////////////
if (HCL_IS_CONS(hcl, v))
{
/* named class. the compiler generates code to push a pair holding
@ -4091,15 +4091,22 @@ static int execute (hcl_t* hcl)
{
/* check if the new definition is compatible with kernel definition */
hcl_ooi_t spec, selfspec, nivars_super, nivars_super_real;
hcl_obj_type_t indexed_type;
spec = HCL_OOP_TO_SMOOI(class_obj->spec);
selfspec = HCL_OOP_TO_SMOOI(class_obj->selfspec);
nivars_super = HCL_OOP_TO_SMOOI(class_obj->nivars_super);
nivars_super_real = HCL_IS_NIL(hcl, superclass)? 0: HCL_OOP_TO_SMOOI(((hcl_oop_class_t)superclass)->nivars_super);
//if (HCL_CLASS_SPEC_IS_INDEXED(spec))
//indexed_type = (hcl_obj_type_t)HCL_CLASS_SPEC_INDEXED_TYPE(spec);
#if 0
hcl_logbfmt (hcl, HCL_LOG_STDERR, ">>>%O c->sc=%O sc=%O b2=%d b3=%d nivars=%d ncvars=%d<<<\n", class_obj, class_obj->superclass, superclass, b2, b3, (int)HCL_CLASS_SPEC_NAMED_INSTVARS(spec), (int)HCL_CLASS_SELFSPEC_CLASSVARS(spec));
#endif
if (class_obj->superclass != superclass || HCL_CLASS_SPEC_NAMED_INSTVARS(spec) != b2 || HCL_CLASS_SELFSPEC_CLASSVARS(selfspec) != b3 || nivars_super != nivars_super_real)
if (class_obj->superclass != superclass ||
HCL_CLASS_SPEC_NAMED_INSTVARS(spec) != b2 ||
HCL_CLASS_SELFSPEC_CLASSVARS(selfspec) != b3 ||
nivars_super != nivars_super_real)
{
hcl_seterrbfmt (hcl, HCL_EPERM, "incompatible redefintion of %.*js", HCL_OBJ_GET_SIZE(class_name), HCL_OBJ_GET_CHAR_SLOT(class_name));
if (do_throw_with_internal_errmsg(hcl, fetched_instruction_pointer) >= 0) break;
@ -4129,7 +4136,6 @@ hcl_logbfmt (hcl, HCL_LOG_STDERR, ">>>%O c->sc=%O sc=%O b2=%d b3=%d nivars=%d nc
class_obj = (hcl_oop_class_t)hcl_makeclass(hcl, class_name, superclass, b2, b3, ivars_str, cvars_str);
if (HCL_UNLIKELY(!class_obj)) goto oops_with_errmsg_supplement;
}
//////////////
/* push the class created to the class stack. but don't push to the normal operation stack */
HCL_CLSTACK_PUSH (hcl, (hcl_oop_t)class_obj);
@ -5019,7 +5025,7 @@ hcl_oop_t hcl_execute (hcl_t* hcl)
HCL_ASSERT (hcl, hcl->code.bc.ptr[hcl->code.bc.len - 1] == HCL_CODE_POP_STACKTOP);
#if 1
/* append RETURN_FROM_BLOCK
if (hcl_emitbyteinstruction(hcl, HCL_CODE_RETURN_FROM_BLOCK) <= -1) return -1;*/
* if (hcl_emitbyteinstruction(hcl, HCL_CODE_RETURN_FROM_BLOCK) <= -1) return -1;*/
/* substitute RETURN_FROM_BLOCK for POP_STACKTOP) */
hcl->code.bc.ptr[hcl->code.bc.len - 1] = HCL_CODE_RETURN_FROM_BLOCK;
#else

View File

@ -677,6 +677,7 @@ struct hcl_cframe_t
struct
{
hcl_ooi_t nsuperclasses;
unsigned int indexed_type;
hcl_loc_t start_loc;
hcl_cnode_t* cmd_cnode;
} _class;

View File

@ -114,7 +114,6 @@ enum hcl_synerrnum_t
HCL_SYNERR_RADIX, /* invalid radix for a numeric literal */
HCL_SYNERR_EOF, /* sudden end of input */
HCL_SYNERR_EOX, /* sudden end of expression */
HCL_SYNERR_LPAREN, /* ( expected */
HCL_SYNERR_RPAREN, /* ) expected */
HCL_SYNERR_RBRACK, /* ] expected */
@ -143,7 +142,6 @@ enum hcl_synerrnum_t
HCL_SYNERR_IFFLOOD, /* if body too big */
HCL_SYNERR_BLKFLOOD, /* block too big */
HCL_SYNERR_BLKDEPTH, /* block too deep */
HCL_SYNERR_NAME, /* name expected */
HCL_SYNERR_ARGNAMELIST, /* argument name list expected */
HCL_SYNERR_ARGNAME, /* argument name expected */
HCL_SYNERR_ARGNAMEDUP, /* duplicate argument name */
@ -159,6 +157,7 @@ enum hcl_synerrnum_t
HCL_SYNERR_BANNEDARGNAME, /* disallowed argument name */
HCL_SYNERR_BANNED, /* prohibited */
HCL_SYNERR_CLASS, /* invalid class definition */
HCL_SYNERR_FUN, /* invalid function definition */
HCL_SYNERR_ELIF, /* elif without if */
HCL_SYNERR_ELSE, /* else without if */

View File

@ -893,7 +893,8 @@ static HCL_INLINE int can_colon_list (hcl_t* hcl)
if (rstl->count <= 0) return 0; /* not allowed at the list beginning */
/* mark the state that a colon has appeared in the list */
if (HCL_CNODE_IS_TYPED(HCL_CNODE_CONS_CAR(rstl->head), HCL_CNODE_CLASS))
/*if (HCL_CNODE_IS_TYPED(HCL_CNODE_CONS_CAR(rstl->head), HCL_CNODE_CLASS))*/
if (HCL_CNODE_IS_FOR_LANG(HCL_CNODE_CONS_CAR(rstl->head)))
{
/* class :superclassame ...
* class name:superclassname ... */
@ -903,6 +904,9 @@ static HCL_INLINE int can_colon_list (hcl_t* hcl)
if (rstl->count == 1) rstl->flagv |= JSON; /* mark that the first key is colon-delimited */
else if (!(rstl->flagv & JSON))
{
#if 0
/* this strict check is not needed as it returns 2 above if the first element is a language keyword element */
/* handling of a colon sign in out-of-class instance method definition.
* e.g. fun String:length() { return (str.length self). }
* TODO: inject a symbol ':' to differentiate form '::' or ':*' methods.
@ -933,6 +937,7 @@ static HCL_INLINE int can_colon_list (hcl_t* hcl)
}
}
}
#endif
return 0; /* the first key is not colon-delimited. so not allowed to colon-delimit other keys */
}

View File

@ -1,8 +1,8 @@
class ##ERROR: syntax error - no class body
class ##ERROR: syntax error - incomplete defintion of unnamed class for 'class'
---
class B ##ERROR: syntax error - no class body
class B ##ERROR: syntax error - incomplete definition of 'B' for 'class'
---