wip - out-of-class method definition
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
hyung-hwan 2024-04-01 01:24:00 +09:00
parent e0ba7c6f12
commit da4e895f6f
3 changed files with 62 additions and 11 deletions

View File

@ -655,6 +655,7 @@ static int emit_single_param_instruction (hcl_t* hcl, int cmd, hcl_oow_t param_1
case HCL_CODE_STORE_INTO_CVAR_M_X: case HCL_CODE_STORE_INTO_CVAR_M_X:
case HCL_CODE_POP_INTO_CVAR_M_X: case HCL_CODE_POP_INTO_CVAR_M_X:
case HCL_CODE_CLASS_LOAD_X:
case HCL_CODE_CLASS_CMSTORE: case HCL_CODE_CLASS_CMSTORE:
case HCL_CODE_CLASS_CIMSTORE: case HCL_CODE_CLASS_CIMSTORE:
case HCL_CODE_CLASS_IMSTORE: case HCL_CODE_CLASS_IMSTORE:
@ -2815,14 +2816,16 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
tmp = HCL_CNODE_CONS_CDR(obj); tmp = HCL_CNODE_CONS_CDR(obj);
if (tmp && HCL_CNODE_IS_CONS(tmp) && HCL_CNODE_IS_SYMBOL_PLAIN(HCL_CNODE_CONS_CAR(tmp))) if (tmp && HCL_CNODE_IS_CONS(tmp) && HCL_CNODE_IS_SYMBOL_PLAIN(HCL_CNODE_CONS_CAR(tmp)))
{ {
/* for defun String:length() { ... } , class_name is String, defun_name is length. */ /* out-of-class method definition
* for defun String:length() { ... }, class_name is String, defun_name is length. */
/* TODO: this must be treated as an error - defun String length() { ... } /* TODO: this must be treated as an error - defun String length() { ... }
for this, the reader must be able to tell between String:length and String:length... for this, the reader must be able to tell between String:length and String length...
or it must inject a special symbol between String and length or must use a different list type... */ or it must inject a special symbol between String and length or must use a different list type... */
/* TODO: this must not be allowed at the in-class definition level.... */ /* TODO: this must not be allowed at the in-class definition level.... */
/* TODO: can we use fun_type to indicate different types of out-of-class methods? */
class_name = defun_name; class_name = defun_name;
defun_name = HCL_CNODE_CONS_CAR(tmp); defun_name = HCL_CNODE_CONS_CAR(tmp);
obj = HCL_CNODE_CONS_CDR(tmp); obj = tmp;
} }
} }
@ -3044,6 +3047,7 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun)
PUSH_SUBCFRAME (hcl, COP_POST_LAMBDA, defun_name); /* 3*/ PUSH_SUBCFRAME (hcl, COP_POST_LAMBDA, defun_name); /* 3*/
cf = GET_SUBCFRAME(hcl); cf = GET_SUBCFRAME(hcl);
cf->u.lambda.fun_type = fun_type; cf->u.lambda.fun_type = fun_type;
cf->u.lambda.class_name = class_name;
PUSH_SUBCFRAME (hcl, COP_EMIT_LAMBDA, src); /* 2 */ PUSH_SUBCFRAME (hcl, COP_EMIT_LAMBDA, src); /* 2 */
cf = GET_SUBCFRAME(hcl); cf = GET_SUBCFRAME(hcl);
@ -5559,6 +5563,7 @@ static HCL_INLINE int post_lambda (hcl_t* hcl)
* 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.
*/ */
hcl_cnode_t* defun_name = cf->operand; hcl_cnode_t* defun_name = cf->operand;
hcl_cnode_t* class_name = cf->u.lambda.class_name;
hcl_var_info_t vi; hcl_var_info_t vi;
int x; int x;
@ -5567,6 +5572,15 @@ static HCL_INLINE int post_lambda (hcl_t* hcl)
if (is_in_class_init_scope(hcl)) if (is_in_class_init_scope(hcl))
{ {
/* method definition */ /* method definition */
if (class_name)
{
/* something wrong - this must not happen because the reader must prevent this
* but if it happens, it is a syntax error */
hcl_setsynerrbfmt(hcl, HCL_SYNERR_BANNED, HCL_CNODE_GET_LOC(class_name), HCL_CNODE_GET_TOK(class_name), "class name prohibited");
return -1;
}
x = find_variable_backward_with_token(hcl, defun_name, &vi); x = find_variable_backward_with_token(hcl, defun_name, &vi);
if (x <= -1) return -1; if (x <= -1) return -1;
if (x == 0) if (x == 0)
@ -5620,11 +5634,42 @@ static HCL_INLINE int post_lambda (hcl_t* hcl)
} }
cf->u.set.mode = VAR_ACCESS_STORE; cf->u.set.mode = VAR_ACCESS_STORE;
#else #else
if (class_name)
{
/* out-of-class definition */
/* TODO: - other types of out-of-class definition */
#if 0
SWITCH_TOP_CFRAME (hcl, COP_EMIT_CLASS_LOAD, class_name); /* 1 */
PUSH_SUBCFRAME (hcl, COP_EMIT_CLASS_EXIT, defun_name); /* 3 */
PUSH_SUBCFRAME (hcl, COP_EMIT_CLASS_IMSTORE, defun_name); /* 2 */
#else
hcl_oow_t index;
hcl_oop_t lit;
/* TODO: CLASS_LOAD_X must be emited before the defun method code instruction is emitted ? */
lit = hcl_makesymbol(hcl, HCL_CNODE_GET_TOKPTR(class_name), HCL_CNODE_GET_TOKLEN(class_name));
if (HCL_UNLIKELY(!lit)) return -1;
if (add_literal(hcl, lit, &index) <= -1) return -1;
if (emit_single_param_instruction(hcl, HCL_CODE_CLASS_LOAD_X, index, HCL_CNODE_GET_LOC(class_name)) <= -1) return -1;
lit = hcl_makesymbol(hcl, HCL_CNODE_GET_TOKPTR(defun_name), HCL_CNODE_GET_TOKLEN(defun_name));
if (HCL_UNLIKELY(!lit)) return -1;
if (add_literal(hcl, lit, &index) <= -1) return -1;
if (emit_single_param_instruction(hcl, HCL_CODE_CLASS_IMSTORE, index, HCL_CNODE_GET_LOC(defun_name)) <= -1) return -1;
if (emit_byte_instruction(hcl, HCL_CODE_CLASS_EXIT, HCL_CNODE_GET_LOC(class_name)) <= -1) return -1;
POP_CFRAME (hcl);
#endif
}
else
{
/* An explicitly named function is always global */ /* An explicitly named function is always global */
SWITCH_TOP_CFRAME (hcl, COP_EMIT_SET, defun_name); SWITCH_TOP_CFRAME (hcl, COP_EMIT_SET, defun_name);
cf = GET_TOP_CFRAME(hcl); cf = GET_TOP_CFRAME(hcl);
cf->u.set.vi.type = VAR_NAMED; cf->u.set.vi.type = VAR_NAMED;
cf->u.set.mode = VAR_ACCESS_STORE; cf->u.set.mode = VAR_ACCESS_STORE;
}
#endif #endif
} }
} }

View File

@ -602,6 +602,7 @@ struct hcl_cframe_t
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;
hcl_cnode_t* class_name; /* class name for out-of-class method definition */
} lambda; } lambda;
/* COP_EMIT_RETURN */ /* COP_EMIT_RETURN */

View File

@ -831,9 +831,14 @@ 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))
{ {
/* handling of a coloe sign in out-of-class method definition. /* handling of a coloe sign in out-of-class instance method definition.
* e.g. defun String:length() { return (str.length self). } */ * e.g. defun String:length() { return (str.length self). }
if (HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(rstl->head), HCL_SYNCODE_DEFUN)) * TODO: inject a symbol ':' to differenticate form '::' or ':*' methods.
* these class methods and class instantiation methods are supposed to be
* implemented elsewhere because ':' has dual use while '::' or ':*' are
* independent tokens */
if (HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(rstl->head), HCL_SYNCODE_DEFUN) ||
HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(rstl->head), HCL_SYNCODE_LAMBDA))
{ {
if (rstl->count == 2) return 1; if (rstl->count == 2) return 1;
} }