touching up variable declaration handling in a class

This commit is contained in:
hyung-hwan 2022-01-03 17:59:55 +00:00
parent 57bb1657b3
commit a830d578e0
4 changed files with 163 additions and 91 deletions

View File

@ -207,13 +207,7 @@ static void kill_temporary_variable_at_offset (hcl_t* hcl, hcl_oow_t offset)
/* this is a hacky function. it's better to implement kill_temporary_variables() which uses word positions */ /* this is a hacky function. it's better to implement kill_temporary_variables() which uses word positions */
HCL_ASSERT (hcl, offset < hcl->c->tv.s.len); HCL_ASSERT (hcl, offset < hcl->c->tv.s.len);
HCL_ASSERT (hcl, hcl->c->tv.s.ptr[offset] != ' '); HCL_ASSERT (hcl, hcl->c->tv.s.ptr[offset] != ' ');
hcl->c->tv.s.ptr[offset] = '('; /* put a special character which can't form a variable name */ hcl->c->tv.s.ptr[offset] = '('; /* HACK!! put a special character which can't form a variable name */
}
static int find_temporary_variable_backward (hcl_t* hcl, const hcl_oocs_t* name, hcl_oow_t* index)
{
/* find the last element */
return __find_word_in_string(&hcl->c->tv.s, name, 1, index);
} }
static int find_variable_backward (hcl_t* hcl, const hcl_oocs_t* name, hcl_var_info_t* vi) static int find_variable_backward (hcl_t* hcl, const hcl_oocs_t* name, hcl_var_info_t* vi)
@ -830,7 +824,7 @@ static void pop_cblk (hcl_t* hcl)
hcl->c->cblk.depth--; hcl->c->cblk.depth--;
} }
static int push_clsblk (hcl_t* hcl, const hcl_ioloc_t* errloc, hcl_oow_t nivars, hcl_oow_t ncvars, const hcl_ooch_t* ivars_str, const hcl_ooch_t* cvars_str) static int push_clsblk (hcl_t* hcl, const hcl_ioloc_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_oow_t new_depth;
hcl_clsblk_info_t* ci; hcl_clsblk_info_t* ci;
@ -866,13 +860,13 @@ static int push_clsblk (hcl_t* hcl, const hcl_ioloc_t* errloc, hcl_oow_t nivars,
if (nivars > 0) if (nivars > 0)
{ {
HCL_ASSERT (hcl, ivars_str != HCL_NULL); HCL_ASSERT (hcl, ivars_str != HCL_NULL);
ci->ivars_str = hcl_dupoocstr(hcl, ivars_str, HCL_NULL); ci->ivars_str = hcl_dupoochars(hcl, ivars_str, ivars_strlen);
if (HCL_UNLIKELY(!ci->ivars_str)) return -1; if (HCL_UNLIKELY(!ci->ivars_str)) return -1;
} }
if (ncvars > 0) if (ncvars > 0)
{ {
HCL_ASSERT (hcl, cvars_str != HCL_NULL); HCL_ASSERT (hcl, cvars_str != HCL_NULL);
ci->cvars_str = hcl_dupoocstr(hcl, cvars_str, HCL_NULL); ci->cvars_str = hcl_dupoochars(hcl, cvars_str, cvars_strlen);
if (HCL_UNLIKELY(!ci->cvars_str)) if (HCL_UNLIKELY(!ci->cvars_str))
{ {
if (ci->ivars_str) hcl_freemem (hcl, ci->ivars_str); if (ci->ivars_str) hcl_freemem (hcl, ci->ivars_str);
@ -1829,15 +1823,14 @@ static HCL_INLINE int compile_else (hcl_t* hcl)
static int collect_vardcl (hcl_t* hcl, hcl_cnode_t* obj, hcl_cnode_t** nextobj, hcl_oow_t tv_dup_check_start, hcl_oow_t* nvardcls, const hcl_bch_t* desc) static int collect_vardcl (hcl_t* hcl, hcl_cnode_t* obj, hcl_cnode_t** nextobj, hcl_oow_t tv_dup_check_start, hcl_oow_t* nvardcls, const hcl_bch_t* desc)
{ {
hcl_oow_t ndcls = 0; /* process a single variable declaration list */
while (obj && HCL_CNODE_IS_CONS(obj)) hcl_oow_t ndcls = 0;
{
hcl_cnode_t* dcl; hcl_cnode_t* dcl;
dcl = HCL_CNODE_CONS_CAR(obj); dcl = HCL_CNODE_CONS_CAR(obj);
if (HCL_CNODE_IS_CONS_CONCODED(dcl, HCL_CONCODE_VLIST)) HCL_ASSERT (hcl, HCL_CNODE_IS_CONS_CONCODED(dcl, HCL_CONCODE_VLIST));
{
hcl_cnode_t* var; hcl_cnode_t* var;
do do
{ {
@ -1880,9 +1873,27 @@ static int collect_vardcl (hcl_t* hcl, hcl_cnode_t* obj, hcl_cnode_t** nextobj,
} }
while (1); while (1);
obj = HCL_CNODE_CONS_CDR(obj); *nextobj = HCL_CNODE_CONS_CDR(obj);
*nvardcls = ndcls;
return 0;
} }
else break;
static int collect_vardcls (hcl_t* hcl, hcl_cnode_t* obj, hcl_cnode_t** nextobj, hcl_oow_t tv_dup_check_start, hcl_oow_t* nvardcls, const hcl_bch_t* desc)
{
/* process zero or more variable declaration lists in a row */
hcl_oow_t ndcls = 0;
while (obj && HCL_CNODE_IS_CONS(obj))
{
hcl_cnode_t* dcl;
hcl_oow_t dclcount;
dcl = HCL_CNODE_CONS_CAR(obj);
if (!HCL_CNODE_IS_CONS_CONCODED(dcl, HCL_CONCODE_VLIST)) break;
if (collect_vardcl(hcl, obj, &obj, tv_dup_check_start, &dclcount, desc) <= -1) return -1;
ndcls += dclcount;
} }
*nvardcls = ndcls; *nvardcls = ndcls;
@ -1963,27 +1974,42 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src)
if (obj) if (obj)
{ {
hcl_cnode_t* tmp; hcl_cnode_t* tmp, * dcl;
tmp = HCL_CNODE_CONS_CAR(obj); tmp = HCL_CNODE_CONS_CAR(obj);
if (!HCL_CNODE_IS_TRPCOLONS(tmp)) goto no_superclass; if (!HCL_CNODE_IS_TRPCOLONS(tmp)) goto no_superclass;
{
tmp = obj;
obj = HCL_CNODE_CONS_CDR(obj); obj = HCL_CNODE_CONS_CDR(obj);
if (!obj || !HCL_CNODE_IS_CONS(obj))
{
hcl_setsynerrbfmt (hcl, HCL_SYNERR_EOX, HCL_CNODE_GET_LOC(tmp), HCL_NULL, "no expression or declaration after triple colons");
return -1;
}
/* if the tricolons symbol is followed by a variable declaration list,
* there is no superclass */
dcl = HCL_CNODE_CONS_CAR(obj);
if (HCL_CNODE_IS_CONS_CONCODED(dcl, HCL_CONCODE_VLIST))
{
obj = tmp; /* rewind to the cons cell of the triple colons */
goto no_superclass;
}
/* superclass part */ /* superclass part */
SWITCH_TOP_CFRAME (hcl, COP_COMPILE_OBJECT, obj); /* 1 */ tmp = HCL_CNODE_CONS_CAR(obj);
SWITCH_TOP_CFRAME (hcl, COP_COMPILE_OBJECT, tmp); /* 1 - superclass expression */
PUSH_SUBCFRAME (hcl, COP_COMPILE_CLASS_P2, class_name); /* 3 */ PUSH_SUBCFRAME (hcl, COP_COMPILE_CLASS_P2, class_name); /* 3 - class name */
cf = GET_SUBCFRAME(hcl); cf = GET_SUBCFRAME(hcl);
cf->u._class.nsuperclasses = 0; /* unsed for CLASS_P2 */ cf->u._class.nsuperclasses = 0; /* unsed for CLASS_P2 */
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? */
obj = HCL_CNODE_CONS_CDR(obj); obj = HCL_CNODE_CONS_CDR(obj);
PUSH_SUBCFRAME (hcl, COP_COMPILE_CLASS_P1, obj); /* 2 */ PUSH_SUBCFRAME (hcl, COP_COMPILE_CLASS_P1, obj); /* 2 - variables declaraions and actual body */
cf = GET_SUBCFRAME(hcl); cf = GET_SUBCFRAME(hcl);
cf->u._class.nsuperclasses = 1; /* this one needs to change if we support multiple superclasses... */ cf->u._class.nsuperclasses = 1; /* this one needs to change if we support multiple superclasses... */
} }
}
else else
{ {
no_superclass: no_superclass:
@ -2006,8 +2032,7 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl)
/* collect information about declared variables */ /* collect information about declared variables */
hcl_cframe_t* cf; hcl_cframe_t* cf;
hcl_cnode_t* obj; hcl_cnode_t* obj;
hcl_oop_t tmp; hcl_oow_t nivars, ncvars, saved_tv_wcount, tv_dup_check_start, cv_dup_check_start;
hcl_oow_t nivars, ncvars, saved_tv_wcount, tv_dup_check_start;
cf = GET_TOP_CFRAME(hcl); cf = GET_TOP_CFRAME(hcl);
obj = cf->operand; obj = cf->operand;
@ -2015,14 +2040,58 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl)
saved_tv_wcount = hcl->c->tv.wcount; saved_tv_wcount = hcl->c->tv.wcount;
tv_dup_check_start = hcl->c->tv.s.len; tv_dup_check_start = hcl->c->tv.s.len;
/* TODO: class variables */ cv_dup_check_start = hcl->c->tv.s.len; // this is buggy... correct this...
nivars = ncvars = 0; nivars = ncvars = 0;
/* use the temporary variable collection buffer for convenience when scanning /* use the temporary variable collection buffer for convenience when scanning
* instance variables and class variables */ * instance variables and class variables */
if (collect_vardcl(hcl, obj, &obj, tv_dup_check_start, &nivars, "instance") <= -1) goto oops; while (obj && HCL_CNODE_IS_CONS(obj))
{
hcl_cnode_t* tmp, * tmp2;
hcl_oow_t dclcount;
/*
(defclass X ::: T
::: | a b c | ; class variables
)
(defclass X
::: T | a b c | ; instance varaiables.
)
(defclass X
::: | a b c | ; class variables
)
*/
tmp2 = obj;
tmp = HCL_CNODE_CONS_CAR(obj);
if (HCL_CNODE_IS_TRPCOLONS(tmp))
{
obj = HCL_CNODE_CONS_CDR(obj);
if (!obj || !HCL_CNODE_IS_CONS(obj))
{
hcl_setsynerrbfmt (hcl, HCL_SYNERR_EOX, HCL_CNODE_GET_LOC(tmp), HCL_NULL, "no expression or declaration after triple colons");
return -1;
}
tmp = HCL_CNODE_CONS_CAR(obj);
if (!HCL_CNODE_IS_CONS_CONCODED(tmp, HCL_CONCODE_VLIST))
{
hcl_setsynerrbfmt (hcl, HCL_SYNERR_EOX, HCL_CNODE_GET_LOC(tmp), HCL_NULL, "no declaration after triple colons");
return -1;
}
if (collect_vardcl(hcl, obj, &obj, tv_dup_check_start, &dclcount, "class") <= -1) return -1;
ncvars += dclcount;
}
else
{
if (!HCL_CNODE_IS_CONS_CONCODED(tmp, HCL_CONCODE_VLIST)) break;
if (collect_vardcl(hcl, obj, &obj, tv_dup_check_start, &dclcount, "instance") <= -1) return -1;
nivars += dclcount;
}
}
if (nivars > 0) if (nivars > 0)
{ {
hcl_oop_t tmp;
if (nivars > HCL_SMOOI_MAX) if (nivars > HCL_SMOOI_MAX)
{ {
hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARFLOOD, HCL_CNODE_GET_LOC(cf->operand), HCL_NULL, "too many(%zu) instance variables", nivars); hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARFLOOD, HCL_CNODE_GET_LOC(cf->operand), HCL_NULL, "too many(%zu) instance variables", nivars);
@ -2036,6 +2105,7 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl)
if (ncvars > 0) if (ncvars > 0)
{ {
hcl_oop_t tmp;
if (ncvars > HCL_SMOOI_MAX) if (ncvars > HCL_SMOOI_MAX)
{ {
/* TOOD: change the error location ?? */ /* TOOD: change the error location ?? */
@ -2043,12 +2113,14 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl)
goto oops; goto oops;
} }
tmp = hcl_makestring(hcl, HCL_NULL, 0, 0); /* TODO: set this to the proper string pointer and length ... */ tmp = hcl_makestring(hcl, &hcl->c->tv.s.ptr[cv_dup_check_start + 1], hcl->c->tv.s.len - cv_dup_check_start - 1, 0);
if (HCL_UNLIKELY(!tmp)) goto oops; if (HCL_UNLIKELY(!tmp)) goto oops;
if (emit_push_literal(hcl, tmp, &cf->u._class.start_loc) <= -1) goto oops; if (emit_push_literal(hcl, tmp, &cf->u._class.start_loc) <= -1) goto oops;
} }
if (push_clsblk(hcl, &cf->u._class.start_loc, nivars, ncvars, &hcl->c->tv.s.ptr[tv_dup_check_start + 1], HCL_NULL) <= -1) goto oops; if (push_clsblk(hcl, &cf->u._class.start_loc, nivars, ncvars,
&hcl->c->tv.s.ptr[tv_dup_check_start + 1], 0, /* TODO: wrong length.... */
&hcl->c->tv.s.ptr[cv_dup_check_start + 1], hcl->c->tv.s.len - cv_dup_check_start - 1) <= -1) goto oops;
/* discard the instance variables and class variables in the temporary variable collection buffer /* discard the instance variables and class variables in the temporary variable collection buffer
* because they have been pushed to the class block structure */ * because they have been pushed to the class block structure */
@ -2066,6 +2138,10 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl)
* end of the class before 'class_exit' is generated */ * end of the class before 'class_exit' is generated */
hcl->c->clsblk.info[hcl->c->clsblk.depth].class_start_inst_pos = hcl->code.bc.len; hcl->c->clsblk.info[hcl->c->clsblk.depth].class_start_inst_pos = hcl->code.bc.len;
{
hcl_cnode_t* tmp = HCL_CNODE_CONS_CAR(obj);
HCL_DEBUG2 (hcl, "^^JJJJJJJJJJJJJJJJJJJJ %d[%js]\n", HCL_CNODE_GET_TYPE(tmp), HCL_CNODE_GET_TOKPTR(tmp));
}
SWITCH_TOP_CFRAME (hcl, COP_COMPILE_OBJECT_LIST, obj); SWITCH_TOP_CFRAME (hcl, COP_COMPILE_OBJECT_LIST, obj);
return 0; return 0;
@ -2108,14 +2184,13 @@ static HCL_INLINE int compile_class_p2 (hcl_t* hcl)
pop_clsblk (hcl); /* end of the class block */ pop_clsblk (hcl); /* end of the class block */
if (emit_byte_instruction(hcl, HCL_CODE_CLASS_PUSH_EXIT, HCL_CNODE_GET_LOC(cf->operand)) <= -1) return -1; if (emit_byte_instruction(hcl, HCL_CODE_CLASS_PUSH_EXIT, HCL_CNODE_GET_LOC(cf->operand)) <= -1) return -1;
// if (cf->operand) // if (cf->operand)
{ {
/* (defclass X() ; this x refers to a variable in the outer scope. /* (defclass X() ; this x refers to a variable in the outer scope.
* | t1 t2 x | * ::: | t1 t2 x |
* (set x 10) ; this x refers to the local variable. * (set x 10) ; this x refers to the class variable.
* ) * )
* *
* the block has been exited(blk.depth--) before finding 'x' in the outer scope. * the block has been exited(blk.depth--) before finding 'x' in the outer scope.
@ -2346,7 +2421,7 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
obj = HCL_CNODE_CONS_CDR(obj); obj = HCL_CNODE_CONS_CDR(obj);
tv_dup_start = hcl->c->tv.s.len; tv_dup_start = hcl->c->tv.s.len;
if (collect_vardcl(hcl, obj, &obj, tv_dup_start, &nlvars, "local") <= -1) return -1; if (collect_vardcls(hcl, obj, &obj, tv_dup_start, &nlvars, "local") <= -1) return -1;
if (nlvars > MAX_CODE_NBLKLVARS) if (nlvars > MAX_CODE_NBLKLVARS)
{ {
@ -3723,6 +3798,7 @@ static int compile_object_list (hcl_t* hcl)
{ {
hcl_cnode_t* car, * cdr; hcl_cnode_t* car, * cdr;
#if 0
if (cop != COP_COMPILE_ARGUMENT_LIST) if (cop != COP_COMPILE_ARGUMENT_LIST)
{ {
/* eliminate unnecessary non-function calls. keep the last one */ /* eliminate unnecessary non-function calls. keep the last one */
@ -3740,13 +3816,14 @@ static int compile_object_list (hcl_t* hcl)
} }
car = HCL_CNODE_CONS_CAR(oprnd); car = HCL_CNODE_CONS_CAR(oprnd);
if (HCL_CNODE_IS_CONS(car) || (HCL_CNODE_IS_SYMBOL(car) && HCL_CNODE_SYMBOL_SYNCODE(car))) break; /* this optimization is buggy for now... need to perfect the break condition here */
if (HCL_CNODE_IS_CONS(car) || (HCL_CNODE_IS_SYMBOL(car) && HCL_CNODE_SYMBOL_SYNCODE(car)) || HCL_CNODE_IS_ELLIPSIS(car) || HCL_CNODE_IS_TRPCOLONS(car)) break;
oprnd = cdr; oprnd = cdr;
} }
HCL_ASSERT (hcl, oprnd != HCL_NULL); HCL_ASSERT (hcl, oprnd != HCL_NULL);
} }
#endif
if (!HCL_CNODE_IS_CONS(oprnd)) if (!HCL_CNODE_IS_CONS(oprnd))
{ {
hcl_setsynerrbfmt (hcl, HCL_SYNERR_DOTBANNED, HCL_CNODE_GET_LOC(oprnd), HCL_CNODE_GET_TOK(oprnd), "redundant cdr in the object list"); hcl_setsynerrbfmt (hcl, HCL_SYNERR_DOTBANNED, HCL_CNODE_GET_LOC(oprnd), HCL_CNODE_GET_TOK(oprnd), "redundant cdr in the object list");

View File

@ -107,6 +107,7 @@ static 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",

View File

@ -532,13 +532,6 @@ struct hcl_compiler_t
hcl_oow_t wcount; /* word count */ hcl_oow_t wcount; /* word count */
} tv; /* temporary variables including arguments */ } tv; /* temporary variables including arguments */
struct
{
hcl_oocs_t s; /* buffer */
hcl_oow_t capa; /* bufer capacity */
hcl_oow_t wcount; /* word count */
} cv; /* class variables */
struct struct
{ {
hcl_ooi_t depth; /* signed because it starts with -1 */ hcl_ooi_t depth; /* signed because it starts with -1 */

View File

@ -113,6 +113,7 @@ 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 */
@ -130,7 +131,7 @@ enum hcl_synerrnum_t
HCL_SYNERR_COLONBANNED, /* : disallowed */ HCL_SYNERR_COLONBANNED, /* : disallowed */
HCL_SYNERR_COMMANOVALUE, /* no value after , */ HCL_SYNERR_COMMANOVALUE, /* no value after , */
HCL_SYNERR_COLONNOVALUE, /* no value after : */ HCL_SYNERR_COLONNOVALUE, /* no value after : */
HCL_SYNERR_NOSEP, /* no seperator between array/dictionary elements */ HCL_SYNERR_NOSEP, /* no separator between array/dictionary elements */
HCL_SYNERR_INCLUDE, /* #include error */ HCL_SYNERR_INCLUDE, /* #include error */
HCL_SYNERR_ELLIPSISBANNED, /* ... disallowed */ HCL_SYNERR_ELLIPSISBANNED, /* ... disallowed */