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
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
70828ac110
commit
924d4ad5e2
@ -107,9 +107,12 @@ hcl_cnode_t* hcl_makecnodesymbol (hcl_t* hcl, int flags, const hcl_loc_t* loc, 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)
|
||||
|
67
lib/comp.c
67
lib/comp.c
@ -400,9 +400,24 @@ HCL_INFO2 (hcl, "CLASS NAMED VAR [%.*js]\n", name->len, name->ptr);
|
||||
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);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
@ -987,7 +1002,7 @@ static void pop_cblk (hcl_t* hcl)
|
||||
hcl->c->cblk.depth--;
|
||||
}
|
||||
|
||||
static int push_clsblk (hcl_t* hcl, const hcl_loc_t* errloc, hcl_oow_t nivars, hcl_oow_t ncvars, const hcl_ooch_t* ivars_str, hcl_oow_t ivars_strlen, const hcl_ooch_t* cvars_str, hcl_oow_t cvars_strlen)
|
||||
static int push_clsblk (hcl_t* hcl, const hcl_loc_t* errloc, hcl_oow_t nivars, hcl_oow_t ncvars, const hcl_ooch_t* ivars_str, hcl_oow_t ivars_strlen, const hcl_ooch_t* cvars_str, hcl_oow_t cvars_strlen)
|
||||
{
|
||||
hcl_oow_t new_depth;
|
||||
hcl_clsblk_info_t* ci;
|
||||
@ -1353,7 +1368,7 @@ static int collect_vardcl (hcl_t* hcl, hcl_cnode_t* obj, hcl_cnode_t** nextobj,
|
||||
#if 0
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2343,11 +2358,21 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src)
|
||||
/* defclass followed by a class name */
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
@ -2636,7 +2661,6 @@ static HCL_INLINE int compile_class_p2 (hcl_t* hcl)
|
||||
}
|
||||
else
|
||||
{
|
||||
//POP_CFRAME (hcl);
|
||||
SWITCH_TOP_CFRAME (hcl, COP_COMPILE_CLASS_P3, cf->operand);
|
||||
#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))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2761,7 +2785,7 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2805,7 +2829,7 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
|
||||
}
|
||||
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;
|
||||
}
|
||||
else
|
||||
@ -3045,13 +3069,13 @@ static int compile_set (hcl_t* hcl, hcl_cnode_t* src)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
return -1;
|
||||
@ -3085,6 +3109,13 @@ static int compile_set (hcl_t* hcl, hcl_cnode_t* src)
|
||||
|
||||
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 */
|
||||
cf = GET_SUBCFRAME(hcl);
|
||||
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 (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;
|
||||
}
|
||||
|
||||
@ -3184,6 +3215,12 @@ static int compile_set_r (hcl_t* hcl, hcl_cnode_t* src)
|
||||
|
||||
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 */
|
||||
cf = GET_SUBCFRAME(hcl);
|
||||
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.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 */
|
||||
@ -5261,6 +5298,8 @@ static HCL_INLINE int post_lambda (hcl_t* hcl)
|
||||
if (x <= -1) return -1;
|
||||
if (x == 0)
|
||||
{
|
||||
/* TODO: handle if defun_name is DSYMOL_CLA ... */
|
||||
|
||||
/* arrange to save to the method slot */
|
||||
switch (cf->u.lambda.fun_type)
|
||||
{
|
||||
|
@ -146,6 +146,8 @@ static char* synerrstr[] =
|
||||
"too many variables defined",
|
||||
"variable declaration disallowed",
|
||||
"duplicate variable name",
|
||||
"unknown variable name",
|
||||
|
||||
"disallowed variable name",
|
||||
"disallowed argument name",
|
||||
"disallowed",
|
||||
|
@ -174,6 +174,7 @@ enum hcl_tok_type_t
|
||||
|
||||
HCL_TOK_IDENT,
|
||||
HCL_TOK_IDENT_DOTTED,
|
||||
HCL_TOK_IDENT_DOTTED_CLA,
|
||||
HCL_TOK_DOT, /* . */
|
||||
HCL_TOK_DBLDOTS, /* .. */
|
||||
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_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_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 */
|
||||
} symbol;
|
||||
struct
|
||||
{
|
||||
int is_cla; /* class-level accessor. prefixed with self or super */
|
||||
} dsymbol;
|
||||
struct
|
||||
{
|
||||
hcl_oow_t v;
|
||||
} smptrlit;
|
||||
@ -579,6 +585,7 @@ struct hcl_flx_pi_t
|
||||
hcl_oow_t seg_len;
|
||||
hcl_oow_t non_ident_seg_count;
|
||||
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;
|
||||
@ -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_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_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_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);
|
||||
|
@ -150,6 +150,7 @@ enum hcl_synerrnum_t
|
||||
HCL_SYNERR_VARFLOOD, /* too many variables defined */
|
||||
HCL_SYNERR_VARDCLBANNED, /* variable declaration disallowed */
|
||||
HCL_SYNERR_VARNAMEDUP, /* duplicate variable name */
|
||||
HCL_SYNERR_VARNAMEUNKNOWN, /* unknown variable name */
|
||||
|
||||
HCL_SYNERR_BANNEDVARNAME, /* disallowed varible name */
|
||||
HCL_SYNERR_BANNEDARGNAME, /* disallowed argument name */
|
||||
|
11
lib/read.c
11
lib/read.c
@ -1452,7 +1452,11 @@ static int feed_process_token (hcl_t* hcl)
|
||||
goto auto_xlist;
|
||||
|
||||
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;
|
||||
|
||||
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))
|
||||
{
|
||||
/* 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
|
||||
{
|
||||
@ -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
|
||||
* 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);
|
||||
goto not_consumed;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ check_SCRIPTS = \
|
||||
va-01.hcl
|
||||
|
||||
check_ERRORS = \
|
||||
class-01.err \
|
||||
do-01.err \
|
||||
do-02.err \
|
||||
feed-01.err \
|
||||
|
@ -480,6 +480,7 @@ check_SCRIPTS = \
|
||||
va-01.hcl
|
||||
|
||||
check_ERRORS = \
|
||||
class-01.err \
|
||||
do-01.err \
|
||||
do-02.err \
|
||||
feed-01.err \
|
||||
|
23
t/class-01.err
Normal file
23
t/class-01.err
Normal 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;
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user