updating the compiler to recognize class-level variables accessors prefixed with self/super in assignment expressions
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
hyung-hwan 2023-12-02 03:35:59 +09:00
parent 70828ac110
commit 924d4ad5e2
9 changed files with 102 additions and 20 deletions

View File

@ -107,9 +107,12 @@ hcl_cnode_t* hcl_makecnodesymbol (hcl_t* hcl, int flags, const hcl_loc_t* loc, c
return c; return c;
} }
hcl_cnode_t* hcl_makecnodedsymbol (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) hcl_cnode_t* hcl_makecnodedsymbol (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok, int is_cla)
{ {
return make_cnode(hcl, HCL_CNODE_DSYMBOL, flags, loc, tok); hcl_cnode_t* c = make_cnode(hcl, HCL_CNODE_DSYMBOL, flags, loc, tok);
if (HCL_UNLIKELY(!c)) return HCL_NULL;
c->u.dsymbol.is_cla = is_cla;
return c;
} }
hcl_cnode_t* hcl_makecnodestrlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) hcl_cnode_t* hcl_makecnodestrlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok)

View File

@ -400,9 +400,24 @@ HCL_INFO2 (hcl, "CLASS NAMED VAR [%.*js]\n", name->len, name->ptr);
return 0; /* not found */ return 0; /* not found */
} }
static int find_variable_backward_with_token (hcl_t* hcl, const hcl_cnode_t* token, hcl_var_info_t* vi) static int find_variable_backward_with_token (hcl_t* hcl, const hcl_cnode_t* cnode, hcl_var_info_t* vi)
{ {
return find_variable_backward_with_word(hcl, HCL_CNODE_GET_TOK(token), HCL_CNODE_GET_LOC(token), 0, vi); if (HCL_CNODE_IS_DSYMBOL_CLA(cnode))
{
/* prefixed with self or super. remove the first segment */
hcl_oocs_t newtok;
newtok = *HCL_CNODE_GET_TOK(cnode);
while (*newtok.ptr != '.')
{
newtok.ptr++;
newtok.len--;
}
newtok.ptr++;
newtok.len--;
return find_variable_backward_with_word(hcl, &newtok, HCL_CNODE_GET_LOC(cnode), 1, vi);
}
return find_variable_backward_with_word(hcl, HCL_CNODE_GET_TOK(cnode), HCL_CNODE_GET_LOC(cnode), HCL_CNODE_IS_DSYMBOL_CLA(cnode), vi);
} }
/* ========================================================================= */ /* ========================================================================= */
@ -1353,7 +1368,7 @@ static int collect_vardcl (hcl_t* hcl, hcl_cnode_t* obj, hcl_cnode_t** nextobj,
#if 0 #if 0
if (!HCL_CNODE_IS_SYMBOL(var)) if (!HCL_CNODE_IS_SYMBOL(var))
{ {
hcl_setsynerrbfmt (hcl, HCL_SYNERR_ARGNAME, HCL_CNODE_GET_LOC(var), HCL_CNODE_GET_TOK(var), "local variable not a symbol"); hcl_setsynerrbfmt (hcl, HCL_SYNERR_ARGNAME, HCL_CNODE_GET_LOC(var), HCL_CNODE_GET_TOK(var), "local variable not symbol");
return -1; return -1;
} }
@ -2343,11 +2358,21 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src)
/* defclass followed by a class name */ /* defclass followed by a class name */
if (HCL_CNODE_SYMBOL_SYNCODE(class_name)) /*|| HCL_OBJ_GET_FLAGS_KERNEL(class_name) >= 1) */ if (HCL_CNODE_SYMBOL_SYNCODE(class_name)) /*|| HCL_OBJ_GET_FLAGS_KERNEL(class_name) >= 1) */
{ {
hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNEDVARNAME, HCL_CNODE_GET_LOC(class_name), HCL_CNODE_GET_TOK(class_name), "special symbol not to be used as a class name"); hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNEDVARNAME, HCL_CNODE_GET_LOC(class_name), HCL_CNODE_GET_TOK(class_name), "special symbol not to be used as class name");
return -1; return -1;
} }
obj = HCL_CNODE_CONS_CDR(obj); obj = HCL_CNODE_CONS_CDR(obj);
} }
else if (HCL_CNODE_IS_DSYMBOL(class_name))
{
if (!HCL_CNODE_IS_DSYMBOL_CLA(class_name))
{
hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNEDVARNAME, HCL_CNODE_GET_LOC(class_name), HCL_CNODE_GET_TOK(class_name), "dottted symbol not to be used as class name");
return -1;
}
obj = HCL_CNODE_CONS_CDR(obj);
}
if (obj) if (obj)
{ {
@ -2636,7 +2661,6 @@ static HCL_INLINE int compile_class_p2 (hcl_t* hcl)
} }
else else
{ {
//POP_CFRAME (hcl);
SWITCH_TOP_CFRAME (hcl, COP_COMPILE_CLASS_P3, cf->operand); SWITCH_TOP_CFRAME (hcl, COP_COMPILE_CLASS_P3, cf->operand);
#endif #endif
} }
@ -2702,7 +2726,7 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
if (!HCL_CNODE_IS_SYMBOL(defun_name)) if (!HCL_CNODE_IS_SYMBOL(defun_name))
{ {
hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAME, HCL_CNODE_GET_LOC(defun_name), HCL_CNODE_GET_TOK(defun_name), "name not a symbol in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAME, HCL_CNODE_GET_LOC(defun_name), HCL_CNODE_GET_TOK(defun_name), "name not symbol in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
return -1; return -1;
} }
@ -2761,7 +2785,7 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
{ {
if (!HCL_CNODE_IS_SYMBOL(arg)) if (!HCL_CNODE_IS_SYMBOL(arg))
{ {
hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAME, HCL_CNODE_GET_LOC(arg), HCL_CNODE_GET_TOK(arg), "return variable not a symbol in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAME, HCL_CNODE_GET_LOC(arg), HCL_CNODE_GET_TOK(arg), "return variable not symbol in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
return -1; return -1;
} }
@ -2805,7 +2829,7 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
} }
else if (!HCL_CNODE_IS_SYMBOL(arg)) else if (!HCL_CNODE_IS_SYMBOL(arg))
{ {
hcl_setsynerrbfmt (hcl, HCL_SYNERR_ARGNAME, HCL_CNODE_GET_LOC(arg), HCL_CNODE_GET_TOK(arg), "argument not a symbol in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); hcl_setsynerrbfmt (hcl, HCL_SYNERR_ARGNAME, HCL_CNODE_GET_LOC(arg), HCL_CNODE_GET_TOK(arg), "argument not symbol in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
return -1; return -1;
} }
else else
@ -3045,13 +3069,13 @@ static int compile_set (hcl_t* hcl, hcl_cnode_t* src)
} }
var = HCL_CNODE_CONS_CAR(obj); var = HCL_CNODE_CONS_CAR(obj);
if (!HCL_CNODE_IS_SYMBOL(var)) if (!HCL_CNODE_IS_SYMBOL(var) && !HCL_CNODE_IS_DSYMBOL_CLA(var))
{ {
hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAME, HCL_CNODE_GET_LOC(var), HCL_CNODE_GET_TOK(var), "variable name not a symbol in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAME, HCL_CNODE_GET_LOC(var), HCL_CNODE_GET_TOK(var), "variable name not symbol in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
return -1; return -1;
} }
if (HCL_CNODE_SYMBOL_SYNCODE(var)/* || HCL_OBJ_GET_FLAGS_KERNEL(var) >= 2*/) if (HCL_CNODE_IS_SYMBOL(var) && HCL_CNODE_SYMBOL_SYNCODE(var)/* || HCL_OBJ_GET_FLAGS_KERNEL(var) >= 2*/)
{ {
hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNEDVARNAME, HCL_CNODE_GET_LOC(var), HCL_CNODE_GET_TOK(var), "special symbol not to be used as a variable name in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNEDVARNAME, HCL_CNODE_GET_LOC(var), HCL_CNODE_GET_TOK(var), "special symbol not to be used as a variable name in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
return -1; return -1;
@ -3085,6 +3109,13 @@ static int compile_set (hcl_t* hcl, hcl_cnode_t* src)
if (x == 0) if (x == 0)
{ {
if (HCL_CNODE_IS_DSYMBOL_CLA(var))
{
hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAMEUNKNOWN, HCL_CNODE_GET_LOC(var), HCL_CNODE_GET_TOK(var), "unknown class-level variable name", HCL_CNODE_GET_TOKLEN(var), HCL_CNODE_GET_TOKPTR(var));
return -1;
}
PUSH_SUBCFRAME (hcl, COP_EMIT_SET, var); /* set doesn't evaluate the variable name */ PUSH_SUBCFRAME (hcl, COP_EMIT_SET, var); /* set doesn't evaluate the variable name */
cf = GET_SUBCFRAME(hcl); cf = GET_SUBCFRAME(hcl);
cf->u.set.vi.type = VAR_NAMED; cf->u.set.vi.type = VAR_NAMED;
@ -3133,7 +3164,7 @@ static int compile_set_r (hcl_t* hcl, hcl_cnode_t* src)
if (!HCL_CNODE_IS_SYMBOL(var)) if (!HCL_CNODE_IS_SYMBOL(var))
{ {
if (nvars > 0) break; if (nvars > 0) break;
hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAME, HCL_CNODE_GET_LOC(var), HCL_CNODE_GET_TOK(var), "variable name not a symbol in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAME, HCL_CNODE_GET_LOC(var), HCL_CNODE_GET_TOK(var), "variable name not symbol in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd));
return -1; return -1;
} }
@ -3184,6 +3215,12 @@ static int compile_set_r (hcl_t* hcl, hcl_cnode_t* src)
if (x == 0) if (x == 0)
{ {
if (HCL_CNODE_IS_DSYMBOL_CLA(var))
{
hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARNAMEUNKNOWN, HCL_CNODE_GET_LOC(var), HCL_CNODE_GET_TOK(var), "unknown class-level variable name", HCL_CNODE_GET_TOKLEN(var), HCL_CNODE_GET_TOKPTR(var));
return -1;
}
PUSH_SUBCFRAME (hcl, COP_EMIT_SET, var); /* set_r doesn't evaluate the variable name */ PUSH_SUBCFRAME (hcl, COP_EMIT_SET, var); /* set_r doesn't evaluate the variable name */
cf = GET_SUBCFRAME(hcl); cf = GET_SUBCFRAME(hcl);
cf->u.set.vi.type = VAR_NAMED; cf->u.set.vi.type = VAR_NAMED;
@ -4057,7 +4094,7 @@ HCL_DEBUG1 (hcl, ">>>> instance variable or method %js\n", sep + 1);
{ {
name.ptr = sep + 1; name.ptr = sep + 1;
name.len -= 6; name.len -= 6;
x = find_variable_backward_with_word(hcl, &name, HCL_CNODE_GET_LOC(obj), 1, &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 */
} }
if (x <= -1) return -1; /* error */ if (x <= -1) return -1; /* error */
@ -5261,6 +5298,8 @@ static HCL_INLINE int post_lambda (hcl_t* hcl)
if (x <= -1) return -1; if (x <= -1) return -1;
if (x == 0) if (x == 0)
{ {
/* TODO: handle if defun_name is DSYMOL_CLA ... */
/* 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)
{ {

View File

@ -146,6 +146,8 @@ static char* synerrstr[] =
"too many variables defined", "too many variables defined",
"variable declaration disallowed", "variable declaration disallowed",
"duplicate variable name", "duplicate variable name",
"unknown variable name",
"disallowed variable name", "disallowed variable name",
"disallowed argument name", "disallowed argument name",
"disallowed", "disallowed",

View File

@ -174,6 +174,7 @@ enum hcl_tok_type_t
HCL_TOK_IDENT, HCL_TOK_IDENT,
HCL_TOK_IDENT_DOTTED, HCL_TOK_IDENT_DOTTED,
HCL_TOK_IDENT_DOTTED_CLA,
HCL_TOK_DOT, /* . */ HCL_TOK_DOT, /* . */
HCL_TOK_DBLDOTS, /* .. */ HCL_TOK_DBLDOTS, /* .. */
HCL_TOK_ELLIPSIS, /* ... */ HCL_TOK_ELLIPSIS, /* ... */
@ -266,6 +267,7 @@ typedef enum hcl_cnode_flagt hcl_cnode_flag_t;
#define HCL_CNODE_SYMBOL_SYNCODE(x) ((x)->u.symbol.syncode) #define HCL_CNODE_SYMBOL_SYNCODE(x) ((x)->u.symbol.syncode)
#define HCL_CNODE_IS_DSYMBOL(x) ((x)->cn_type == HCL_CNODE_DSYMBOL) #define HCL_CNODE_IS_DSYMBOL(x) ((x)->cn_type == HCL_CNODE_DSYMBOL)
#define HCL_CNODE_IS_DSYMBOL_CLA(x) ((x)->cn_type == HCL_CNODE_DSYMBOL && (x)->u.dsymbol.is_cla)
#define HCL_CNODE_IS_CONS(x) ((x)->cn_type == HCL_CNODE_CONS) #define HCL_CNODE_IS_CONS(x) ((x)->cn_type == HCL_CNODE_CONS)
#define HCL_CNODE_IS_CONS_CONCODED(x, code) ((x)->cn_type == HCL_CNODE_CONS && (x)->u.cons.concode == (code)) #define HCL_CNODE_IS_CONS_CONCODED(x, code) ((x)->cn_type == HCL_CNODE_CONS && (x)->u.cons.concode == (code))
@ -296,6 +298,10 @@ struct hcl_cnode_t
hcl_syncode_t syncode; /* special if non-zero */ hcl_syncode_t syncode; /* special if non-zero */
} symbol; } symbol;
struct struct
{
int is_cla; /* class-level accessor. prefixed with self or super */
} dsymbol;
struct
{ {
hcl_oow_t v; hcl_oow_t v;
} smptrlit; } smptrlit;
@ -579,6 +585,7 @@ struct hcl_flx_pi_t
hcl_oow_t seg_len; hcl_oow_t seg_len;
hcl_oow_t non_ident_seg_count; hcl_oow_t non_ident_seg_count;
hcl_tok_type_t last_non_ident_type; hcl_tok_type_t last_non_ident_type;
int is_cla; /* class-level accrssor. prefixed with self/super */
}; };
typedef struct hcl_flx_pn_t hcl_flx_pn_t; typedef struct hcl_flx_pn_t hcl_flx_pn_t;
@ -1723,7 +1730,7 @@ hcl_cnode_t* hcl_makecnodetrpcolons (hcl_t* hcl, int flags, const hcl_loc_t* loc
hcl_cnode_t* hcl_makecnodedcstar (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok); hcl_cnode_t* hcl_makecnodedcstar (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok);
hcl_cnode_t* hcl_makecnodecharlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok, const hcl_ooch_t v); hcl_cnode_t* hcl_makecnodecharlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok, const hcl_ooch_t v);
hcl_cnode_t* hcl_makecnodesymbol (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok); hcl_cnode_t* hcl_makecnodesymbol (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok);
hcl_cnode_t* hcl_makecnodedsymbol (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok); hcl_cnode_t* hcl_makecnodedsymbol (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok, int is_cla);
hcl_cnode_t* hcl_makecnodestrlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok); hcl_cnode_t* hcl_makecnodestrlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok);
hcl_cnode_t* hcl_makecnodenumlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok); hcl_cnode_t* hcl_makecnodenumlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok);
hcl_cnode_t* hcl_makecnoderadnumlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok); hcl_cnode_t* hcl_makecnoderadnumlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok);

View File

@ -150,6 +150,7 @@ enum hcl_synerrnum_t
HCL_SYNERR_VARFLOOD, /* too many variables defined */ HCL_SYNERR_VARFLOOD, /* too many variables defined */
HCL_SYNERR_VARDCLBANNED, /* variable declaration disallowed */ HCL_SYNERR_VARDCLBANNED, /* variable declaration disallowed */
HCL_SYNERR_VARNAMEDUP, /* duplicate variable name */ HCL_SYNERR_VARNAMEDUP, /* duplicate variable name */
HCL_SYNERR_VARNAMEUNKNOWN, /* unknown variable name */
HCL_SYNERR_BANNEDVARNAME, /* disallowed varible name */ HCL_SYNERR_BANNEDVARNAME, /* disallowed varible name */
HCL_SYNERR_BANNEDARGNAME, /* disallowed argument name */ HCL_SYNERR_BANNEDARGNAME, /* disallowed argument name */

View File

@ -1452,7 +1452,11 @@ static int feed_process_token (hcl_t* hcl)
goto auto_xlist; goto auto_xlist;
case HCL_TOK_IDENT_DOTTED: case HCL_TOK_IDENT_DOTTED:
frd->obj = hcl_makecnodedsymbol(hcl, 0, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); frd->obj = hcl_makecnodedsymbol(hcl, 0, TOKEN_LOC(hcl), TOKEN_NAME(hcl), 0);
goto auto_xlist;
case HCL_TOK_IDENT_DOTTED_CLA:
frd->obj = hcl_makecnodedsymbol(hcl, 0, TOKEN_LOC(hcl), TOKEN_NAME(hcl), 1);
goto auto_xlist; goto auto_xlist;
auto_xlist: auto_xlist:
@ -2165,7 +2169,7 @@ static int flx_plain_ident (hcl_t* hcl, hcl_ooci_t c) /* identifier */
if (pi->seg_count == 0 && (tok_type == HCL_TOK_SELF || tok_type == HCL_TOK_SUPER)) if (pi->seg_count == 0 && (tok_type == HCL_TOK_SELF || tok_type == HCL_TOK_SUPER))
{ {
/* allowed if it begins with self. or super. */ /* allowed if it begins with self. or super. */
/* nothing to do */ pi->is_cla = 1; /* mark that it's prefixed with self or super */
} }
else else
{ {
@ -2202,7 +2206,8 @@ static int flx_plain_ident (hcl_t* hcl, hcl_ooci_t c) /* identifier */
/* if single-segmented, perform classification(call classify_ident_token()) again /* if single-segmented, perform classification(call classify_ident_token()) again
* bcause self and super as the first segment have not been marked as a non-identifier above */ * bcause self and super as the first segment have not been marked as a non-identifier above */
tok_type = (pi->seg_count == 1? classify_ident_token(hcl, TOKEN_NAME(hcl)): HCL_TOK_IDENT_DOTTED); tok_type = (pi->seg_count == 1? classify_ident_token(hcl, TOKEN_NAME(hcl)):
(pi->is_cla? HCL_TOK_IDENT_DOTTED_CLA: HCL_TOK_IDENT_DOTTED));
FEED_WRAP_UP (hcl, tok_type); FEED_WRAP_UP (hcl, tok_type);
goto not_consumed; goto not_consumed;
} }

View File

@ -9,6 +9,7 @@ check_SCRIPTS = \
va-01.hcl va-01.hcl
check_ERRORS = \ check_ERRORS = \
class-01.err \
do-01.err \ do-01.err \
do-02.err \ do-02.err \
feed-01.err \ feed-01.err \

View File

@ -480,6 +480,7 @@ check_SCRIPTS = \
va-01.hcl va-01.hcl
check_ERRORS = \ check_ERRORS = \
class-01.err \
do-01.err \ do-01.err \
do-02.err \ do-02.err \
feed-01.err \ feed-01.err \

23
t/class-01.err Normal file
View File

@ -0,0 +1,23 @@
defclass B | x y | {
};
defclass X ::: B | a b | {
defun ::* new(t) {
| a |
set self.a t;
set a 100;
set self.b (* t 2);
set self.c (fun(b) { ##ERROR: syntax error - unknown class-level variable name
printf "xxxx [%d]\n" b;
});
return self;
};
defun print() {
self.c (+ self.a self.b);
printf "a=%d b=%d\n" self.a self.b;
}
};