added a class-side dictionary to the class object
This commit is contained in:
parent
eefc544644
commit
4b4e6a6385
11
lib/comp.c
11
lib/comp.c
@ -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);
|
||||
}
|
||||
|
76
lib/exec.c
76
lib/exec.c
@ -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?? */
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user