adding code to support class attribute list. work in progress
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
f4d223f646
commit
3f350dd38a
189
lib/comp.c
189
lib/comp.c
@ -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
|
(class A
|
||||||
[ x y ] ## instance variables
|
[ x y ] ## instance variables
|
||||||
@ -2495,29 +2621,42 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src)
|
|||||||
{
|
{
|
||||||
hcl_cframe_t* cf;
|
hcl_cframe_t* cf;
|
||||||
hcl_cnode_t* cmd, * obj, * tmp;
|
hcl_cnode_t* cmd, * obj, * tmp;
|
||||||
|
hcl_cnode_t* attr_list;
|
||||||
hcl_cnode_t* class_name, * superclass;
|
hcl_cnode_t* class_name, * superclass;
|
||||||
int nsuperclasses;
|
int nsuperclasses;
|
||||||
|
unsigned int indexed_type;
|
||||||
|
|
||||||
cmd = HCL_CNODE_CONS_CAR(src);
|
cmd = HCL_CNODE_CONS_CAR(src);
|
||||||
obj = HCL_CNODE_CONS_CDR(src);
|
obj = HCL_CNODE_CONS_CDR(src);
|
||||||
|
|
||||||
|
attr_list = HCL_NULL;
|
||||||
class_name = HCL_NULL;
|
class_name = HCL_NULL;
|
||||||
|
indexed_type = HCL_OBJ_TYPE_OOP;
|
||||||
|
|
||||||
HCL_ASSERT (hcl, HCL_CNODE_IS_TYPED(cmd, HCL_CNODE_CLASS));
|
HCL_ASSERT (hcl, HCL_CNODE_IS_TYPED(cmd, HCL_CNODE_CLASS));
|
||||||
|
|
||||||
/* TODO: attribute lsit */
|
if (obj)
|
||||||
|
|
||||||
if (obj /*&& HCL_CNODE_IS_CONS(obj)*/)
|
|
||||||
{
|
{
|
||||||
HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(obj));
|
HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(obj));
|
||||||
|
|
||||||
tmp = HCL_CNODE_CONS_CAR(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_FOR_DATA_SIMPLE(tmp) || HCL_CNODE_IS_FOR_LANG(tmp))
|
||||||
{
|
{
|
||||||
if (!HCL_CNODE_IS_SYMBOL_IDENT(tmp))
|
if (!HCL_CNODE_IS_SYMBOL_IDENT(tmp))
|
||||||
{
|
{
|
||||||
hcl_setsynerrbfmt (
|
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'",
|
"invalid class name '%.*js' for '%.*js'",
|
||||||
HCL_CNODE_GET_TOKLEN(tmp), HCL_CNODE_GET_TOKPTR(tmp),
|
HCL_CNODE_GET_TOKLEN(tmp), HCL_CNODE_GET_TOKPTR(tmp),
|
||||||
HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
|
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)
|
if (class_name)
|
||||||
{
|
{
|
||||||
hcl_setsynerrbfmt (
|
hcl_setsynerrbfmt (
|
||||||
hcl, HCL_SYNERR_BLOCK, HCL_CNODE_GET_LOC(src), HCL_NULL,
|
hcl, HCL_SYNERR_CLASS, HCL_CNODE_GET_LOC(src), HCL_NULL,
|
||||||
"no class body defined for '%.*js'",
|
"incomplete definition of '%.*js' for '%.*js'",
|
||||||
HCL_CNODE_GET_TOKLEN(class_name), HCL_CNODE_GET_TOKPTR(class_name));
|
HCL_CNODE_GET_TOKLEN(class_name), HCL_CNODE_GET_TOKPTR(class_name),
|
||||||
|
HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hcl_setsynerrbfmt (
|
hcl_setsynerrbfmt (
|
||||||
hcl, HCL_SYNERR_BLOCK, HCL_CNODE_GET_LOC(src), HCL_NULL,
|
hcl, HCL_SYNERR_CLASS, HCL_CNODE_GET_LOC(src), HCL_NULL,
|
||||||
"no class body defined for unnamed class");
|
"incomplete defintion of unnamed class for '%.*js'",
|
||||||
|
HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
|
||||||
}
|
}
|
||||||
return -1;
|
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);
|
tmp = HCL_CNODE_CONS_CAR(obj);
|
||||||
if (HCL_CNODE_IS_COLON(tmp)) /* check for superclass marker */
|
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))
|
if (!obj || !HCL_CNODE_IS_CONS(obj))
|
||||||
{
|
{
|
||||||
hcl_setsynerrbfmt (
|
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",
|
"no expression or declaration after %.*js",
|
||||||
HCL_CNODE_GET_TOKLEN(marker), HCL_CNODE_GET_TOKPTR(marker));
|
HCL_CNODE_GET_TOKLEN(marker), HCL_CNODE_GET_TOKPTR(marker));
|
||||||
return -1;
|
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))
|
if (HCL_CNODE_IS_FOR_DATA_SIMPLE(superclass) || HCL_CNODE_IS_FOR_LANG(superclass))
|
||||||
{
|
{
|
||||||
hcl_setsynerrbfmt (
|
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'",
|
"invalid superclass name '%.*js' after '%.*js' for '%.*js'",
|
||||||
HCL_CNODE_GET_TOKLEN(superclass), HCL_CNODE_GET_TOKPTR(superclass),
|
HCL_CNODE_GET_TOKLEN(superclass), HCL_CNODE_GET_TOKPTR(superclass),
|
||||||
HCL_CNODE_GET_TOKLEN(marker), HCL_CNODE_GET_TOKPTR(marker),
|
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
|
else
|
||||||
{
|
{
|
||||||
hcl_setsynerrbfmt (
|
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'",
|
"no valid superclass name after '%.*js' for '%.*js'",
|
||||||
HCL_CNODE_GET_TOKLEN(marker), HCL_CNODE_GET_TOKPTR(marker),
|
HCL_CNODE_GET_TOKLEN(marker), HCL_CNODE_GET_TOKPTR(marker),
|
||||||
HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
|
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 */
|
PUSH_CFRAME (hcl, COP_COMPILE_CLASS_P2, class_name); /* 3 - use class name for assignment */
|
||||||
cf = GET_TOP_CFRAME(hcl);
|
cf = GET_TOP_CFRAME(hcl);
|
||||||
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.start_loc = *HCL_CNODE_GET_LOC(src); /* TODO: use *HCL_CNODE_GET_LOC(cmd) instead? */
|
cf->u._class.start_loc = *HCL_CNODE_GET_LOC(src); /* TODO: use *HCL_CNODE_GET_LOC(cmd) instead? */
|
||||||
cf->u._class.cmd_cnode = cmd;
|
cf->u._class.cmd_cnode = cmd;
|
||||||
|
|
||||||
PUSH_CFRAME (hcl, COP_COMPILE_CLASS_P1, obj); /* 2 - variables declaraions and actual body */
|
PUSH_CFRAME (hcl, COP_COMPILE_CLASS_P1, obj); /* 2 - variables declaraions and actual body */
|
||||||
cf = GET_TOP_CFRAME(hcl);
|
cf = GET_TOP_CFRAME(hcl);
|
||||||
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.start_loc = *HCL_CNODE_GET_LOC(src); /* TODO: use *HCL_CNODE_GET_LOC(cmd) instead? */
|
cf->u._class.start_loc = *HCL_CNODE_GET_LOC(src); /* TODO: use *HCL_CNODE_GET_LOC(cmd) instead? */
|
||||||
cf->u._class.cmd_cnode = cmd;
|
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 */
|
/* 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_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, cf->u._class.nsuperclasses) <= -1) goto oops;
|
||||||
if (emit_long_param(hcl, vardcl.nivars) <= -1) goto oops;
|
if (emit_long_param(hcl, vardcl.nivars) <= -1) goto oops;
|
||||||
if (emit_long_param(hcl, vardcl.ncvars) <= -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 (
|
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)
|
||||||
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;
|
unsigned int ft;
|
||||||
|
|
||||||
ft = 0;
|
ft = FUN_IM;
|
||||||
|
|
||||||
HCL_ASSERT (hcl, attr_list != HCL_NULL);
|
HCL_ASSERT (hcl, attr_list != HCL_NULL);
|
||||||
HCL_ASSERT (hcl, HCL_CNODE_IS_CONS_CONCODED(attr_list, HCL_CONCODE_XLIST) ||
|
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 ||
|
if (hcl_comp_oochars_bcstr(tokptr, toklen, "class") == 0 ||
|
||||||
hcl_comp_oochars_bcstr(tokptr, toklen, "c") == 0)
|
hcl_comp_oochars_bcstr(tokptr, toklen, "c") == 0)
|
||||||
{
|
{
|
||||||
if (ft != 0)
|
if (ft != FUN_IM)
|
||||||
{
|
{
|
||||||
conflicting:
|
conflicting:
|
||||||
hcl_setsynerrbfmt (
|
hcl_setsynerrbfmt (
|
||||||
@ -2879,7 +3023,7 @@ static int check_fun_attr_list (
|
|||||||
else if (hcl_comp_oochars_bcstr(tokptr, toklen, "classinst") == 0 ||
|
else if (hcl_comp_oochars_bcstr(tokptr, toklen, "classinst") == 0 ||
|
||||||
hcl_comp_oochars_bcstr(tokptr, toklen, "ci") == 0)
|
hcl_comp_oochars_bcstr(tokptr, toklen, "ci") == 0)
|
||||||
{
|
{
|
||||||
if (ft != 0) goto conflicting;
|
if (ft != FUN_IM) goto conflicting;
|
||||||
ft = FUN_CIM;
|
ft = FUN_CIM;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3150,7 +3294,6 @@ static int compile_fun (hcl_t* hcl, hcl_cnode_t* src)
|
|||||||
* class X {
|
* class X {
|
||||||
* a := (fun x(){}) ## this context is also class_init_scope. so the check above isn't good enough
|
* 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 (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 */
|
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)
|
if (is_in_class_init_scope(hcl) || class_name)
|
||||||
{
|
{
|
||||||
fun_type = FUN_IM;
|
fun_type = FUN_IM;
|
||||||
if (class_name) fun_type |= 0x100;
|
if (class_name) fun_type |= 0x100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5163,13 +5306,7 @@ redo:
|
|||||||
goto redo;
|
goto redo;
|
||||||
|
|
||||||
case HCL_CNODE_ELLIPSIS:
|
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:
|
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_DBLCOLONS:
|
||||||
case HCL_CNODE_COLON:
|
case HCL_CNODE_COLON:
|
||||||
case HCL_CNODE_COLONLT:
|
case HCL_CNODE_COLONLT:
|
||||||
|
@ -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:
|
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, b1);
|
||||||
FETCH_PARAM_CODE_TO (hcl, b2);
|
FETCH_PARAM_CODE_TO (hcl, b2);
|
||||||
FETCH_PARAM_CODE_TO (hcl, b3);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,6 @@ static const char* synerrstr[] =
|
|||||||
"invalid radix for a numeric literal",
|
"invalid radix for a numeric literal",
|
||||||
|
|
||||||
"sudden end of input",
|
"sudden end of input",
|
||||||
"sudden end of expression",
|
|
||||||
"( expected",
|
"( expected",
|
||||||
") expected",
|
") expected",
|
||||||
"] expected",
|
"] expected",
|
||||||
@ -139,7 +138,6 @@ static const char* synerrstr[] =
|
|||||||
"if body too big",
|
"if body too big",
|
||||||
"block too big",
|
"block too big",
|
||||||
"block too deep",
|
"block too deep",
|
||||||
"name expected",
|
|
||||||
"argument name list expected",
|
"argument name list expected",
|
||||||
"argument name expected",
|
"argument name expected",
|
||||||
"duplicate argument name",
|
"duplicate argument name",
|
||||||
@ -155,6 +153,7 @@ static const char* synerrstr[] =
|
|||||||
"disallowed argument name",
|
"disallowed argument name",
|
||||||
"disallowed",
|
"disallowed",
|
||||||
|
|
||||||
|
"invalid class definition",
|
||||||
"invalid function definition",
|
"invalid function definition",
|
||||||
"elif without if",
|
"elif without if",
|
||||||
"else without if",
|
"else without if",
|
||||||
|
20
lib/exec.c
20
lib/exec.c
@ -4032,18 +4032,19 @@ static int execute (hcl_t* hcl)
|
|||||||
push superclass (only if nsuperclassses > 0)
|
push superclass (only if nsuperclassses > 0)
|
||||||
push ivars_string
|
push ivars_string
|
||||||
push cvars_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 superclass, ivars_str, cvars_str, class_name;
|
||||||
hcl_oop_t v;
|
hcl_oop_t v;
|
||||||
hcl_oop_class_t class_obj;
|
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, b1); /* nsuperclasses */
|
||||||
FETCH_PARAM_CODE_TO (hcl, b2); /* nivars */
|
FETCH_PARAM_CODE_TO (hcl, b2); /* nivars */
|
||||||
FETCH_PARAM_CODE_TO (hcl, b3); /* ncvars */
|
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)
|
if (b3 > 0)
|
||||||
{
|
{
|
||||||
@ -4073,7 +4074,6 @@ static int execute (hcl_t* hcl)
|
|||||||
|
|
||||||
HCL_STACK_POP_TO(hcl, v);
|
HCL_STACK_POP_TO(hcl, v);
|
||||||
|
|
||||||
//////////////
|
|
||||||
if (HCL_IS_CONS(hcl, v))
|
if (HCL_IS_CONS(hcl, v))
|
||||||
{
|
{
|
||||||
/* named class. the compiler generates code to push a pair holding
|
/* 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 */
|
/* check if the new definition is compatible with kernel definition */
|
||||||
hcl_ooi_t spec, selfspec, nivars_super, nivars_super_real;
|
hcl_ooi_t spec, selfspec, nivars_super, nivars_super_real;
|
||||||
|
hcl_obj_type_t indexed_type;
|
||||||
|
|
||||||
spec = HCL_OOP_TO_SMOOI(class_obj->spec);
|
spec = HCL_OOP_TO_SMOOI(class_obj->spec);
|
||||||
selfspec = HCL_OOP_TO_SMOOI(class_obj->selfspec);
|
selfspec = HCL_OOP_TO_SMOOI(class_obj->selfspec);
|
||||||
nivars_super = HCL_OOP_TO_SMOOI(class_obj->nivars_super);
|
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);
|
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
|
#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));
|
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
|
#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));
|
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;
|
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);
|
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;
|
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 */
|
/* 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);
|
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);
|
HCL_ASSERT (hcl, hcl->code.bc.ptr[hcl->code.bc.len - 1] == HCL_CODE_POP_STACKTOP);
|
||||||
#if 1
|
#if 1
|
||||||
/* append RETURN_FROM_BLOCK
|
/* 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) */
|
/* substitute RETURN_FROM_BLOCK for POP_STACKTOP) */
|
||||||
hcl->code.bc.ptr[hcl->code.bc.len - 1] = HCL_CODE_RETURN_FROM_BLOCK;
|
hcl->code.bc.ptr[hcl->code.bc.len - 1] = HCL_CODE_RETURN_FROM_BLOCK;
|
||||||
#else
|
#else
|
||||||
|
@ -677,6 +677,7 @@ struct hcl_cframe_t
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
hcl_ooi_t nsuperclasses;
|
hcl_ooi_t nsuperclasses;
|
||||||
|
unsigned int indexed_type;
|
||||||
hcl_loc_t start_loc;
|
hcl_loc_t start_loc;
|
||||||
hcl_cnode_t* cmd_cnode;
|
hcl_cnode_t* cmd_cnode;
|
||||||
} _class;
|
} _class;
|
||||||
|
@ -114,7 +114,6 @@ enum hcl_synerrnum_t
|
|||||||
HCL_SYNERR_RADIX, /* invalid radix for a numeric literal */
|
HCL_SYNERR_RADIX, /* invalid radix for a numeric literal */
|
||||||
|
|
||||||
HCL_SYNERR_EOF, /* sudden end of input */
|
HCL_SYNERR_EOF, /* sudden end of input */
|
||||||
HCL_SYNERR_EOX, /* sudden end of expression */
|
|
||||||
HCL_SYNERR_LPAREN, /* ( expected */
|
HCL_SYNERR_LPAREN, /* ( expected */
|
||||||
HCL_SYNERR_RPAREN, /* ) expected */
|
HCL_SYNERR_RPAREN, /* ) expected */
|
||||||
HCL_SYNERR_RBRACK, /* ] expected */
|
HCL_SYNERR_RBRACK, /* ] expected */
|
||||||
@ -143,7 +142,6 @@ enum hcl_synerrnum_t
|
|||||||
HCL_SYNERR_IFFLOOD, /* if body too big */
|
HCL_SYNERR_IFFLOOD, /* if body too big */
|
||||||
HCL_SYNERR_BLKFLOOD, /* block too big */
|
HCL_SYNERR_BLKFLOOD, /* block too big */
|
||||||
HCL_SYNERR_BLKDEPTH, /* block too deep */
|
HCL_SYNERR_BLKDEPTH, /* block too deep */
|
||||||
HCL_SYNERR_NAME, /* name expected */
|
|
||||||
HCL_SYNERR_ARGNAMELIST, /* argument name list expected */
|
HCL_SYNERR_ARGNAMELIST, /* argument name list expected */
|
||||||
HCL_SYNERR_ARGNAME, /* argument name expected */
|
HCL_SYNERR_ARGNAME, /* argument name expected */
|
||||||
HCL_SYNERR_ARGNAMEDUP, /* duplicate argument name */
|
HCL_SYNERR_ARGNAMEDUP, /* duplicate argument name */
|
||||||
@ -159,6 +157,7 @@ enum hcl_synerrnum_t
|
|||||||
HCL_SYNERR_BANNEDARGNAME, /* disallowed argument name */
|
HCL_SYNERR_BANNEDARGNAME, /* disallowed argument name */
|
||||||
HCL_SYNERR_BANNED, /* prohibited */
|
HCL_SYNERR_BANNED, /* prohibited */
|
||||||
|
|
||||||
|
HCL_SYNERR_CLASS, /* invalid class definition */
|
||||||
HCL_SYNERR_FUN, /* invalid function definition */
|
HCL_SYNERR_FUN, /* invalid function definition */
|
||||||
HCL_SYNERR_ELIF, /* elif without if */
|
HCL_SYNERR_ELIF, /* elif without if */
|
||||||
HCL_SYNERR_ELSE, /* else without if */
|
HCL_SYNERR_ELSE, /* else without if */
|
||||||
|
@ -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 */
|
if (rstl->count <= 0) return 0; /* not allowed at the list beginning */
|
||||||
|
|
||||||
/* mark the state that a colon has appeared in the list */
|
/* 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 :superclassame ...
|
||||||
* class name:superclassname ... */
|
* 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 */
|
if (rstl->count == 1) rstl->flagv |= JSON; /* mark that the first key is colon-delimited */
|
||||||
else if (!(rstl->flagv & JSON))
|
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.
|
/* handling of a colon sign in out-of-class instance method definition.
|
||||||
* e.g. fun String:length() { return (str.length self). }
|
* e.g. fun String:length() { return (str.length self). }
|
||||||
* TODO: inject a symbol ':' to differentiate form '::' or ':*' methods.
|
* 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 */
|
return 0; /* the first key is not colon-delimited. so not allowed to colon-delimit other keys */
|
||||||
}
|
}
|
||||||
|
@ -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'
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user