compiler fix to prohibit self. or super. in out-of-class method defintion nested in a normal method in a class
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
b4d435a593
commit
c25f0dabdb
83
lib/comp.c
83
lib/comp.c
@ -51,6 +51,11 @@ enum
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
/* these enumerators are stored in the lower 8 bits of
|
||||||
|
* the fun_type field of hcl_fnblk_info_t.
|
||||||
|
* the 9th bit of the field indicate a method is defined
|
||||||
|
* out of a class */
|
||||||
|
|
||||||
FUN_PLAIN, /* plain function */
|
FUN_PLAIN, /* plain function */
|
||||||
FUN_IM, /* instance method */
|
FUN_IM, /* instance method */
|
||||||
FUN_CM, /* class method */
|
FUN_CM, /* class method */
|
||||||
@ -323,22 +328,22 @@ static int find_variable_backward_with_word (hcl_t* hcl, const hcl_oocs_t* name,
|
|||||||
{
|
{
|
||||||
/* instance variables are accessible only in an instance method defintion scope.
|
/* instance variables are accessible only in an instance method defintion scope.
|
||||||
* it is in class initialization scope */
|
* it is in class initialization scope */
|
||||||
hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, loc, name, "prohibited access to an instance variable");
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, loc, name, "prohibited access to instance variable");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (fi = hcl->c->fnblk.depth + 1; fi > i; ) /* TOOD: review this loop for correctness */
|
for (fi = hcl->c->fnblk.depth + 1; fi > i; ) /* TOOD: review this loop for correctness */
|
||||||
{
|
{
|
||||||
/* 'i' is the function level that holds the class defintion block. the check must not go past it */
|
/* 'i' is the function level that holds the class defintion block. the check must not go past it */
|
||||||
if (hcl->c->fnblk.info[--fi].fun_type == FUN_CM)
|
if ((hcl->c->fnblk.info[--fi].fun_type & 0xFF) == FUN_CM)
|
||||||
{
|
{
|
||||||
/* the function where this variable is defined is a class method or an plain function block within a class method*/
|
/* the function where this variable is defined is a class method or an plain function block within a class method*/
|
||||||
hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, loc, name, "prohibited access to an instance variable in a class method context");
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, loc, name, "prohibited access to instance variable in class method context");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instance methods and instantiation methods can access instance variables */
|
/* instance methods and instantiation methods can access instance variables */
|
||||||
if (hcl->c->fnblk.info[fi].fun_type != FUN_PLAIN) break;
|
if ((hcl->c->fnblk.info[fi].fun_type & 0xFF) != FUN_PLAIN) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
vi->type = VAR_INST;
|
vi->type = VAR_INST;
|
||||||
@ -363,8 +368,10 @@ HCL_INFO6 (hcl, "FOUND INST VAR [%.*js]...[%.*js]................ ===> ctx_offse
|
|||||||
vi->type = (i >= hcl->c->fnblk.depth? VAR_CLASS_I: VAR_CLASS_IM);
|
vi->type = (i >= hcl->c->fnblk.depth? VAR_CLASS_I: VAR_CLASS_IM);
|
||||||
vi->ctx_offset = 0;
|
vi->ctx_offset = 0;
|
||||||
vi->index_in_ctx = index;
|
vi->index_in_ctx = index;
|
||||||
|
/*
|
||||||
HCL_INFO6 (hcl, "FOUND CLASS VAR [%.*js]...[%.*js]................ ===> ctx_offset %d index %d\n",
|
HCL_INFO6 (hcl, "FOUND CLASS VAR [%.*js]...[%.*js]................ ===> ctx_offset %d index %d\n",
|
||||||
haystack.len, haystack.ptr, name->len, name->ptr, (int)(vi->ctx_offset), (int)vi->index_in_ctx);
|
haystack.len, haystack.ptr, name->len, name->ptr, (int)(vi->ctx_offset), (int)vi->index_in_ctx);
|
||||||
|
*/
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1126,7 +1133,7 @@ static void pop_clsblk (hcl_t* hcl)
|
|||||||
|
|
||||||
static int push_fnblk (hcl_t* hcl, const hcl_loc_t* errloc,
|
static int push_fnblk (hcl_t* hcl, const hcl_loc_t* errloc,
|
||||||
hcl_oow_t tmpr_va, hcl_oow_t tmpr_nargs, hcl_oow_t tmpr_nrvars, hcl_oow_t tmpr_nlvars,
|
hcl_oow_t tmpr_va, hcl_oow_t tmpr_nargs, hcl_oow_t tmpr_nrvars, hcl_oow_t tmpr_nlvars,
|
||||||
hcl_oow_t tmpr_count, hcl_oow_t tmpr_len, hcl_oow_t make_inst_pos, hcl_oow_t lfbase, int fun_type)
|
hcl_oow_t tmpr_count, hcl_oow_t tmpr_len, hcl_oow_t make_inst_pos, hcl_oow_t lfbase, unsigned int fun_type)
|
||||||
{
|
{
|
||||||
hcl_oow_t new_depth;
|
hcl_oow_t new_depth;
|
||||||
hcl_fnblk_info_t* fbi;
|
hcl_fnblk_info_t* fbi;
|
||||||
@ -1240,7 +1247,7 @@ static void pop_fnblk (hcl_t* hcl)
|
|||||||
/* the temporaries mask is a bit-mask that encodes the counts of different temporary variables.
|
/* the temporaries mask is a bit-mask that encodes the counts of different temporary variables.
|
||||||
* and it's split to two intruction parameters when used with MAKE_LAMBDA and MAKE_FUNCTION.
|
* and it's split to two intruction parameters when used with MAKE_LAMBDA and MAKE_FUNCTION.
|
||||||
* the INSTA bit is on if fbi->fun_type == FUN_CIM */
|
* the INSTA bit is on if fbi->fun_type == FUN_CIM */
|
||||||
attr_mask = ENCODE_BLK_MASK((fbi->fun_type == FUN_CIM), fbi->tmpr_va, fbi->tmpr_nargs, fbi->tmpr_nrvars, fbi->tmpr_nlvars);
|
attr_mask = ENCODE_BLK_MASK(((fbi->fun_type & 0xFF) == FUN_CIM), fbi->tmpr_va, fbi->tmpr_nargs, fbi->tmpr_nrvars, fbi->tmpr_nlvars);
|
||||||
patch_double_long_params_with_oow (hcl, fbi->make_inst_pos + 1, attr_mask);
|
patch_double_long_params_with_oow (hcl, fbi->make_inst_pos + 1, attr_mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2752,7 +2759,7 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
|
|||||||
hcl_cnode_t* defun_name;
|
hcl_cnode_t* defun_name;
|
||||||
hcl_cnode_t* class_name;
|
hcl_cnode_t* class_name;
|
||||||
hcl_cframe_t* cf;
|
hcl_cframe_t* cf;
|
||||||
int fun_type = FUN_PLAIN;
|
unsigned int fun_type = FUN_PLAIN;
|
||||||
|
|
||||||
HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(src));
|
HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(src));
|
||||||
|
|
||||||
@ -2822,7 +2829,7 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
|
|||||||
if (tmp && HCL_CNODE_IS_CONS(tmp))
|
if (tmp && HCL_CNODE_IS_CONS(tmp))
|
||||||
{
|
{
|
||||||
tmp = HCL_CNODE_CONS_CAR(tmp);
|
tmp = HCL_CNODE_CONS_CAR(tmp);
|
||||||
if (HCL_CNODE_IS_COLON(tmp) /*(HCL_CNODE_IS_SYMBOL_PLAIN(tmp)*/)
|
if (HCL_CNODE_IS_COLON(tmp) || HCL_CNODE_IS_DBLCOLONS(tmp) || HCL_CNODE_IS_COLONSTAR(tmp)/*(HCL_CNODE_IS_SYMBOL_PLAIN(tmp)*/)
|
||||||
{
|
{
|
||||||
hcl_setsynerrbfmt (
|
hcl_setsynerrbfmt (
|
||||||
hcl, HCL_SYNERR_VARNAME,
|
hcl, HCL_SYNERR_VARNAME,
|
||||||
@ -2847,6 +2854,8 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
|
|||||||
marker = HCL_CNODE_CONS_CAR(tmp);
|
marker = HCL_CNODE_CONS_CAR(tmp);
|
||||||
if (HCL_CNODE_IS_COLON(marker) || HCL_CNODE_IS_DBLCOLONS(marker) || HCL_CNODE_IS_COLONSTAR(marker))
|
if (HCL_CNODE_IS_COLON(marker) || HCL_CNODE_IS_DBLCOLONS(marker) || HCL_CNODE_IS_COLONSTAR(marker))
|
||||||
{
|
{
|
||||||
|
/* fun A:aaa A::aaa A:*aaa */
|
||||||
|
|
||||||
tmp = HCL_CNODE_CONS_CDR(tmp);
|
tmp = HCL_CNODE_CONS_CDR(tmp);
|
||||||
if (tmp && HCL_CNODE_IS_CONS(tmp))
|
if (tmp && HCL_CNODE_IS_CONS(tmp))
|
||||||
{
|
{
|
||||||
@ -2854,12 +2863,23 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
|
|||||||
cand = HCL_CNODE_CONS_CAR(tmp);
|
cand = HCL_CNODE_CONS_CAR(tmp);
|
||||||
if (HCL_CNODE_IS_SYMBOL_PLAIN(cand))
|
if (HCL_CNODE_IS_SYMBOL_PLAIN(cand))
|
||||||
{
|
{
|
||||||
/* out-of-class method definition
|
/* out-of-class method definition
|
||||||
* for defun String:length() { ... }, class_name is String, defun_name is length. */
|
* for defun String:length() { ... },
|
||||||
/* TODO: this must not be allowed at the in-class definition level.... */
|
* class_name is String, defun_name is length. */
|
||||||
/* TODO: can we use fun_type to indicate different types of out-of-class methods? use marker.... */
|
|
||||||
fun_type = HCL_CNODE_IS_DBLCOLONS(marker)? FUN_CM:
|
fun_type = HCL_CNODE_IS_DBLCOLONS(marker)? FUN_CM:
|
||||||
HCL_CNODE_IS_COLONSTAR(marker)? FUN_CIM: FUN_IM;
|
HCL_CNODE_IS_COLONSTAR(marker)? FUN_CIM: FUN_IM;
|
||||||
|
|
||||||
|
/* indicates that this method is defined using the AAA:bbb syntax.
|
||||||
|
* the form of method defintion can still be inside a class if this
|
||||||
|
* form is place inside another normal method.
|
||||||
|
* class X {
|
||||||
|
* fun x() {
|
||||||
|
* fun J:q() { .... } ## this defintion
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* */
|
||||||
|
fun_type |= 0x100;
|
||||||
|
|
||||||
class_name = defun_name;
|
class_name = defun_name;
|
||||||
defun_name = HCL_CNODE_CONS_CAR(tmp);
|
defun_name = HCL_CNODE_CONS_CAR(tmp);
|
||||||
obj = tmp;
|
obj = tmp;
|
||||||
@ -4243,20 +4263,45 @@ static HCL_INLINE int compile_dsymbol (hcl_t* hcl, hcl_cnode_t* obj)
|
|||||||
hcl_oocs_t name;
|
hcl_oocs_t name;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
hcl_var_info_t vi;
|
hcl_var_info_t vi;
|
||||||
|
hcl_fnblk_info_t* fbi;
|
||||||
|
|
||||||
name = *HCL_CNODE_GET_TOK(obj);
|
name = *HCL_CNODE_GET_TOK(obj);
|
||||||
|
fbi = &hcl->c->fnblk.info[hcl->c->fnblk.depth];
|
||||||
|
|
||||||
sep = hcl_find_oochar(name.ptr, name.len, '.');
|
sep = hcl_find_oochar(name.ptr, name.len, '.');
|
||||||
HCL_ASSERT (hcl, sep != HCL_NULL);
|
HCL_ASSERT (hcl, sep != HCL_NULL);
|
||||||
if (hcl_comp_oochars_bcstr(name.ptr, (sep - (const hcl_ooch_t*)name.ptr), "self") == 0)
|
if (hcl_comp_oochars_bcstr(name.ptr, (sep - (const hcl_ooch_t*)name.ptr), "self") == 0)
|
||||||
{
|
{
|
||||||
/* instance variable? or instance method? */
|
/* instance variable? or instance method? */
|
||||||
|
if (fbi->fun_type >> 8)
|
||||||
|
{
|
||||||
|
/* if defined using A::xxx syntax, it's not possible to know the instance position of an instance variable.
|
||||||
|
* class X | a b | {
|
||||||
|
* fun a() {
|
||||||
|
* fun J::t() {
|
||||||
|
* ## J has nothing to to with X in priciple even if J may point to X when a() is executed.
|
||||||
|
* ## it's not meaningful to look up the variable `a` in the context of class X.
|
||||||
|
* ## it must be prohibited to access instance variables using the self or super prefix
|
||||||
|
* ## in this context
|
||||||
|
* return self.a
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAME, HCL_CNODE_GET_LOC(obj), HCL_CNODE_GET_TOK(obj), "not allowed to prefix with self in out-of-class method context");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
name.ptr = (hcl_ooch_t*)(sep + 1);
|
name.ptr = (hcl_ooch_t*)(sep + 1);
|
||||||
name.len -= 5;
|
name.len -= 5;
|
||||||
x = find_variable_backward_with_word(hcl, &name, HCL_CNODE_GET_LOC(obj), 1, &vi);
|
x = find_variable_backward_with_word(hcl, &name, HCL_CNODE_GET_LOC(obj), 1, &vi);
|
||||||
}
|
}
|
||||||
else if (hcl_comp_oochars_bcstr(name.ptr, sep - (const hcl_ooch_t*)name.ptr, "super") == 0)
|
else if (hcl_comp_oochars_bcstr(name.ptr, sep - (const hcl_ooch_t*)name.ptr, "super") == 0)
|
||||||
{
|
{
|
||||||
|
if (fbi->fun_type >> 8) /* if defined using A::xxx syntax */
|
||||||
|
{
|
||||||
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAME, HCL_CNODE_GET_LOC(obj), HCL_CNODE_GET_TOK(obj), "not allowed to prefix with super in out-of-class method context");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
name.ptr = (hcl_ooch_t*)(sep + 1);
|
name.ptr = (hcl_ooch_t*)(sep + 1);
|
||||||
name.len -= 6;
|
name.len -= 6;
|
||||||
x = find_variable_backward_with_word(hcl, &name, HCL_CNODE_GET_LOC(obj), 2, &vi); /* TODO: arrange to skip the current class */
|
x = find_variable_backward_with_word(hcl, &name, HCL_CNODE_GET_LOC(obj), 2, &vi); /* TODO: arrange to skip the current class */
|
||||||
@ -5534,7 +5579,7 @@ static HCL_INLINE int emit_lambda (hcl_t* hcl)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* single return value */
|
/* single return value */
|
||||||
if (cf->u.lambda.fun_type == FUN_PLAIN)
|
if ((cf->u.lambda.fun_type & 0xFF) == FUN_PLAIN)
|
||||||
{
|
{
|
||||||
if (block_code_size == 0)
|
if (block_code_size == 0)
|
||||||
{
|
{
|
||||||
@ -5636,7 +5681,7 @@ static HCL_INLINE int post_lambda (hcl_t* hcl)
|
|||||||
if (x == 0)
|
if (x == 0)
|
||||||
{
|
{
|
||||||
/* arrange to save to the method slot */
|
/* arrange to save to the method slot */
|
||||||
switch (cf->u.lambda.fun_type)
|
switch (cf->u.lambda.fun_type & 0xFF)
|
||||||
{
|
{
|
||||||
case FUN_CM: /* class method */
|
case FUN_CM: /* class method */
|
||||||
SWITCH_TOP_CFRAME (hcl, COP_EMIT_CLASS_CMSTORE, defun_name);
|
SWITCH_TOP_CFRAME (hcl, COP_EMIT_CLASS_CMSTORE, defun_name);
|
||||||
@ -5652,8 +5697,8 @@ static HCL_INLINE int post_lambda (hcl_t* hcl)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
/* in the class initialization scope, the type must not be other than the listed above */
|
/* in the class initialization scope, the type must not be other than the listed above */
|
||||||
HCL_DEBUG1 (hcl, "Internal error - invalid method type %d\n", cf->u.lambda.fun_type);
|
HCL_DEBUG1 (hcl, "Internal error - invalid method type %d\n", cf->u.lambda.fun_type & 0xFF);
|
||||||
hcl_seterrbfmt (hcl, HCL_EINTERN, "internal error - invalid method type %d", cf->u.lambda.fun_type);
|
hcl_seterrbfmt (hcl, HCL_EINTERN, "internal error - invalid method type %d", cf->u.lambda.fun_type & 0xFF);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
cf = GET_TOP_CFRAME(hcl);
|
cf = GET_TOP_CFRAME(hcl);
|
||||||
@ -5703,7 +5748,7 @@ static HCL_INLINE int post_lambda (hcl_t* hcl)
|
|||||||
if (HCL_UNLIKELY(!lit)) return -1;
|
if (HCL_UNLIKELY(!lit)) return -1;
|
||||||
if (add_literal(hcl, lit, &index) <= -1) return -1;
|
if (add_literal(hcl, lit, &index) <= -1) return -1;
|
||||||
|
|
||||||
switch (cf->u.lambda.fun_type)
|
switch (cf->u.lambda.fun_type & 0xFF)
|
||||||
{
|
{
|
||||||
case FUN_CM: /* class method */
|
case FUN_CM: /* class method */
|
||||||
inst = HCL_CODE_CLASS_CMSTORE;
|
inst = HCL_CODE_CLASS_CMSTORE;
|
||||||
@ -5719,8 +5764,8 @@ static HCL_INLINE int post_lambda (hcl_t* hcl)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
/* in the class initialization scope, the type must not be other than the listed above */
|
/* in the class initialization scope, the type must not be other than the listed above */
|
||||||
HCL_DEBUG1 (hcl, "Internal error - invalid function type %d\n", cf->u.lambda.fun_type);
|
HCL_DEBUG1 (hcl, "Internal error - invalid function type %d\n", cf->u.lambda.fun_type & 0xFF);
|
||||||
hcl_seterrbfmt (hcl, HCL_EINTERN, "internal error - invalid function type %d", cf->u.lambda.fun_type);
|
hcl_seterrbfmt (hcl, HCL_EINTERN, "internal error - invalid function type %d", cf->u.lambda.fun_type & 0xFF);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,7 +600,7 @@ struct hcl_cframe_t
|
|||||||
/* COP_POST_LAMBDA, COP_EMIT_LAMBDA */
|
/* COP_POST_LAMBDA, COP_EMIT_LAMBDA */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int fun_type;
|
unsigned int fun_type;
|
||||||
hcl_oow_t jump_inst_pos;
|
hcl_oow_t jump_inst_pos;
|
||||||
hcl_ooi_t lfbase_pos;
|
hcl_ooi_t lfbase_pos;
|
||||||
hcl_ooi_t lfsize_pos;
|
hcl_ooi_t lfsize_pos;
|
||||||
@ -648,7 +648,7 @@ typedef struct hcl_cblk_info_t hcl_cblk_info_t;
|
|||||||
/* function block information for the compiler */
|
/* function block information for the compiler */
|
||||||
struct hcl_fnblk_info_t
|
struct hcl_fnblk_info_t
|
||||||
{
|
{
|
||||||
int fun_type;
|
unsigned int fun_type;
|
||||||
|
|
||||||
hcl_oow_t tmprlen; /* accumulated length of the temporaries string including outer blocks */
|
hcl_oow_t tmprlen; /* accumulated length of the temporaries string including outer blocks */
|
||||||
hcl_oow_t tmprcnt; /* accumulated number of temporaries including outer blocks */
|
hcl_oow_t tmprcnt; /* accumulated number of temporaries including outer blocks */
|
||||||
|
@ -61,7 +61,7 @@ static hcl_pfrc_t pf_arr_get (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs)
|
|||||||
|
|
||||||
if (index >= HCL_OBJ_GET_SIZE(arr))
|
if (index >= HCL_OBJ_GET_SIZE(arr))
|
||||||
{
|
{
|
||||||
hcl_seterrbfmt (hcl, HCL_EINVAL, "array index(%zu) out of boundsfor array of size %zu", index, HCL_OBJ_GET_SIZE(arr));
|
hcl_seterrbfmt (hcl, HCL_EINVAL, "array index %zu out of bounds for array of size %zu", index, HCL_OBJ_GET_SIZE(arr));
|
||||||
return HCL_PF_FAILURE;
|
return HCL_PF_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ static hcl_pfrc_t pf_arr_put (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs)
|
|||||||
|
|
||||||
if (index >= HCL_OBJ_GET_SIZE(arr))
|
if (index >= HCL_OBJ_GET_SIZE(arr))
|
||||||
{
|
{
|
||||||
hcl_seterrbfmt (hcl, HCL_EINVAL, "array index(%zu) out of bounds for array of size %zu", index, HCL_OBJ_GET_SIZE(arr));
|
hcl_seterrbfmt (hcl, HCL_EINVAL, "array index %zu out of bounds for array of size %zu", index, HCL_OBJ_GET_SIZE(arr));
|
||||||
return HCL_PF_FAILURE;
|
return HCL_PF_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,18 +47,61 @@ class X {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
## this will trigger a runtime error as J isn't a class name
|
## this triggers a runtime error as J isn't a class name
|
||||||
fun J:ccc() { ##ERROR: exception not handled
|
fun J:ccc() { ##ERROR: exception not handled - "J accessed without initialization"
|
||||||
return 999
|
return 999
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
X := 20
|
||||||
|
|
||||||
|
## this also raises a runtime error as X isn't a class name
|
||||||
|
fun X:xxx() { ##ERROR: exception not handled - "not class"
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## this must not be very useful as Array is an index item
|
## this must not be very useful as Array is an index item
|
||||||
## and the clase instantiation method can't specify the size
|
## and the clase instantiation method can't specify the size
|
||||||
## you can't place an item in the arrya at all.
|
## you can't place an item in the arrya at all.
|
||||||
|
|
||||||
fun Array:*boom() {
|
fun Array:*boom() {
|
||||||
arr.put self 0 10 ##ERROR: exception not handled
|
arr.put self 0 10 ##ERROR: exception not handled - "array index 0 out of bounds for array of size 0"
|
||||||
printf "%O" self
|
printf "%O" self
|
||||||
}
|
}
|
||||||
Array:boom
|
Array:boom
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
class X | a b c | {
|
||||||
|
fun :* new () {
|
||||||
|
self.a := 20
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getA() { return self.a }
|
||||||
|
}
|
||||||
|
|
||||||
|
## the instance variables are not accessible in out-of-class method
|
||||||
|
## defintionas there isn't a good way to know the class structure
|
||||||
|
## as X isn't known in advance and can point to anything
|
||||||
|
fun X:get_a() {
|
||||||
|
return self.a ##ERROR: syntax error - not allowed to prefix with self
|
||||||
|
}
|
||||||
|
|
||||||
|
printf "%d\n" ((X:new):get_a)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
class F | a b c | {
|
||||||
|
}
|
||||||
|
|
||||||
|
class X | a b c | {
|
||||||
|
fun oh() {
|
||||||
|
fun F:get_a() {
|
||||||
|
return super.a ##ERROR: syntax error - not allowed to prefix with super
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user