added a class-side dictionary to the class object

This commit is contained in:
hyung-hwan 2022-02-13 10:15:14 +00:00
parent eefc544644
commit 4b4e6a6385
3 changed files with 72 additions and 20 deletions

View File

@ -30,7 +30,7 @@ enum
{
VAR_NAMED,
VAR_INDEXED,
VAR_INST,
VAR_INST, /* instance variable */
VAR_CLASS_I, /* class variable in class initialization scope */
VAR_CLASS_CM, /* class variable in class method scope */
VAR_CLASS_IM, /* class variable in instance method scope */
@ -281,7 +281,7 @@ static int find_variable_backward (hcl_t* hcl, const hcl_cnode_t* token, hcl_var
{
if (i >= hcl->c->fnblk.depth)
{
/* instance variables are not accessible if not in class method scope.
/* instance variables are not accessible if not in method definition scope.
* it is in class initialization scope */
hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, HCL_CNODE_GET_LOC(token), name, "prohibited to access an instance variable");
return -1;
@ -303,6 +303,7 @@ HCL_INFO6 (hcl, "FOUND INST VAR [%.*js]...[%.*js]................ ===> ctx_offse
if (__find_word_in_string(&haystack, name, 1, &index) >= 0)
{
/* TODO: VAR_CLASS_CM vs VAR_CLASS_IM, need to know if it's an instance method or a class method */
/* TODO: check if it's in the class variable .... */
vi->type = (i >= hcl->c->fnblk.depth? VAR_CLASS_I: VAR_CLASS_IM);
vi->ctx_offset = 0;
vi->index_in_ctx = index;
@ -824,15 +825,15 @@ static int emit_variable_access (hcl_t* hcl, int mode, const hcl_var_info_t* vi,
return emit_double_param_instruction(hcl, inst_map[0][mode], vi->ctx_offset, vi->index_in_ctx, srcloc);
case VAR_INST:
case VAR_CLASS_CM:
case VAR_CLASS_CM: /* class variable in class method scope */
HCL_ASSERT (hcl, vi->ctx_offset == 0);
return emit_single_param_instruction(hcl, inst_map[1][mode], vi->index_in_ctx, srcloc);
case VAR_CLASS_I:
case VAR_CLASS_I: /* class variable in initialization scope */
HCL_ASSERT (hcl, vi->ctx_offset == 0);
return emit_single_param_instruction(hcl, inst_map[2][mode], vi->index_in_ctx, srcloc);
case VAR_CLASS_IM:
case VAR_CLASS_IM: /* class variable in instance method scope */
HCL_ASSERT (hcl, vi->ctx_offset == 0);
return emit_single_param_instruction(hcl, inst_map[3][mode], vi->index_in_ctx, srcloc);
}

View File

@ -2148,7 +2148,47 @@ static HCL_INLINE int call_primitive (hcl_t* hcl, hcl_ooi_t nargs)
/* ------------------------------------------------------------------------- */
static hcl_oop_block_t find_method_noseterr (hcl_t* hcl, hcl_oop_class_t class_, hcl_oop_t op, hcl_ooi_t* ivaroff)
static hcl_oop_block_t find_cmethod_noseterr (hcl_t* hcl, hcl_oop_class_t class_, hcl_oop_t op)
{
hcl_oocs_t name;
/* TODO: implement method cache */
HCL_ASSERT (hcl, HCL_IS_CLASS(hcl, class_));
HCL_ASSERT (hcl, HCL_IS_SYMBOL(hcl, op));
name.ptr = HCL_OBJ_GET_CHAR_SLOT(op);
name.len = HCL_OBJ_GET_SIZE(op);
do
{
hcl_oop_t dic;
dic = class_->cdic;
HCL_ASSERT (hcl, HCL_IS_NIL(hcl, dic) || HCL_IS_DIC(hcl, dic));
if (HCL_LIKELY(!HCL_IS_NIL(hcl, dic)))
{
hcl_oop_cons_t ass;
ass = (hcl_oop_cons_t)hcl_lookupdicforsymbol_noseterr(hcl, (hcl_oop_dic_t)dic, &name);
if (HCL_LIKELY(ass))
{
hcl_oop_t val;
val = HCL_CONS_CDR(ass);
if (HCL_IS_BLOCK(hcl, val))
{
/* TODO: futher check if it's a method block? */
return (hcl_oop_block_t)val;
}
}
}
class_ = (hcl_oop_class_t)class_->superclass;
}
while (HCL_IS_CLASS(hcl, class_));
return HCL_NULL;
}
static hcl_oop_block_t find_imethod_noseterr (hcl_t* hcl, hcl_oop_class_t class_, hcl_oop_t op, hcl_ooi_t* ivaroff)
{
hcl_oocs_t name;
@ -2162,7 +2202,7 @@ static hcl_oop_block_t find_method_noseterr (hcl_t* hcl, hcl_oop_class_t class_,
{
hcl_oop_t dic;
dic = class_->memdic;
dic = class_->idic;
HCL_ASSERT (hcl, HCL_IS_NIL(hcl, dic) || HCL_IS_DIC(hcl, dic));
if (HCL_LIKELY(!HCL_IS_NIL(hcl, dic)))
@ -2195,13 +2235,19 @@ static HCL_INLINE int send_message (hcl_t* hcl, hcl_oop_t rcv, hcl_oop_t msg, in
hcl_ooi_t ivaroff;
int x;
HCL_ASSERT (hcl, HCL_IS_INSTANCE(hcl, rcv));
HCL_ASSERT (hcl, HCL_IS_SYMBOL(hcl, msg));
/* TODO: implement method cache */
HCL_ASSERT (hcl, HCL_IS_CLASS(hcl, rcv->_class));
mth = find_method_noseterr(hcl, (hcl_oop_class_t)rcv->_class, msg, &ivaroff);
if (HCL_IS_CLASS(hcl, rcv))
{
mth = find_cmethod_noseterr(hcl, (hcl_oop_class_t)rcv, msg);
}
else
{
HCL_ASSERT (hcl, HCL_IS_INSTANCE(hcl, rcv));
HCL_ASSERT (hcl, HCL_IS_CLASS(hcl, rcv->_class));
mth = find_imethod_noseterr(hcl, (hcl_oop_class_t)rcv->_class, msg, &ivaroff);
}
if (!mth)
{
hcl_seterrbfmt (hcl, HCL_ENOENT, "'%.*js' not found in the %O", HCL_OBJ_GET_SIZE(msg), HCL_OBJ_GET_CHAR_SLOT(msg), rcv->_class);
@ -3596,7 +3642,6 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1)
case HCL_CODE_CLASS_CMSTORE:
{
/* TODO: change this part */
hcl_oop_t class_;
hcl_oop_t dic;
@ -3610,7 +3655,7 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1)
HCL_CLSTACK_FETCH_TOP_TO (hcl, class_);
HCL_ASSERT (hcl, HCL_IS_CLASS(hcl, class_));
dic = ((hcl_oop_class_t)class_)->memdic;
dic = ((hcl_oop_class_t)class_)->cdic; /* class-side dictionary */
HCL_ASSERT (hcl, HCL_IS_NIL(hcl, dic) || HCL_IS_DIC(hcl, dic));
if (HCL_IS_NIL(hcl, dic))
{
@ -3618,7 +3663,7 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1)
dic = hcl_makedic(hcl, 16); /* TODO: configurable initial size? */
hcl_popvolat (hcl);
if (HCL_UNLIKELY(!dic)) goto oops_with_errmsg_supplement;
((hcl_oop_class_t)class_)->memdic = dic;
((hcl_oop_class_t)class_)->cdic = dic;
}
if (!hcl_putatdic(hcl, (hcl_oop_dic_t)dic, hcl->active_function->literal_frame[b1], HCL_STACK_GETTOP(hcl))) goto oops_with_errmsg_supplement;
@ -3640,7 +3685,7 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1)
HCL_CLSTACK_FETCH_TOP_TO (hcl, class_);
HCL_ASSERT (hcl, HCL_IS_CLASS(hcl, class_));
dic = ((hcl_oop_class_t)class_)->memdic;
dic = ((hcl_oop_class_t)class_)->idic; /* instance-side dictionary */
HCL_ASSERT (hcl, HCL_IS_NIL(hcl, dic) || HCL_IS_DIC(hcl, dic));
if (HCL_IS_NIL(hcl, dic))
{
@ -3648,7 +3693,7 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1)
dic = hcl_makedic(hcl, 16); /* TODO: configurable initial size? */
hcl_popvolat (hcl);
if (HCL_UNLIKELY(!dic)) goto oops_with_errmsg_supplement;
((hcl_oop_class_t)class_)->memdic = dic;
((hcl_oop_class_t)class_)->idic = dic;
}
if (!hcl_putatdic(hcl, (hcl_oop_dic_t)dic, hcl->active_function->literal_frame[b1], HCL_STACK_GETTOP(hcl))) goto oops_with_errmsg_supplement;
@ -3817,9 +3862,14 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1)
rcv = HCL_STACK_GETRCV(hcl, b1);
op = HCL_STACK_GETOP(hcl, b1);
if (HCL_IS_INSTANCE(hcl, rcv) && HCL_IS_SYMBOL(hcl, op))
if (!HCL_IS_SYMBOL(hcl, op))
{
if (send_message(hcl, rcv, op, ((bcode >> 2) & 1), b1) <= -1)
hcl_seterrbfmt (hcl, HCL_ECALL, "unable to send %O to %O - invalid message", op, rcv); /* TODO: change to HCL_ESEND?? */
goto cannot_send;
}
else if (HCL_IS_CLASS(hcl, rcv) || HCL_IS_INSTANCE(hcl, rcv))
{
if (send_message(hcl, rcv, op, ((bcode >> 2) & 1) /* to_super */, b1 /* nargs */) <= -1)
{
const hcl_ooch_t* msg = hcl_backuperrmsg (hcl);
hcl_seterrbfmt (hcl, HCL_ECALL, "unable to send %O to %O - %js", op, rcv, msg); /* TODO: change to HCL_ESEND?? */

View File

@ -863,14 +863,15 @@ struct hcl_process_scheduler_t
};
#define HCL_CLASS_NAMED_INSTVARS 7
#define HCL_CLASS_NAMED_INSTVARS 8
typedef struct hcl_class_t hcl_class_t;
typedef struct hcl_class_t* hcl_oop_class_t;
struct hcl_class_t
{
HCL_OBJ_HEADER;
hcl_oop_t memdic; /* nil or dictionary of named elements including methods and variables */
hcl_oop_t idic; /* nil or dictionary of named elements including instance methods and variables */
hcl_oop_t cdic; /* nil or dictionary of named elements including class methods and variables */
hcl_oop_t superclass;
hcl_oop_t nivars; /* smooi. */