From 5bf8d20a93a097712fea018627d48291c5d7fd50 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Mon, 24 Apr 2017 04:26:03 +0000 Subject: [PATCH] enhanced the compiler to handle default initial values for instance variables and class variables --- moo/kernel/Process.moo | 23 ++++----- moo/kernel/X11.moo | 12 +---- moo/lib/comp.c | 111 ++++++++++++++++++++++++++++++----------- moo/lib/moo-prv.h | 16 +++--- moo/lib/obj.c | 16 ++---- 5 files changed, 109 insertions(+), 69 deletions(-) diff --git a/moo/kernel/Process.moo b/moo/kernel/Process.moo index c5569fb..359b2d3 100644 --- a/moo/kernel/Process.moo +++ b/moo/kernel/Process.moo @@ -99,7 +99,15 @@ class(#pointer) Process(Object) class Semaphore(Object) { - var count, waiting_head, waiting_tail, heapIndex, fireTimeSec, fireTimeNsec, ioIndex, ioData, ioMask. + var count := 0, + waiting_head := nil, + waiting_tail := nil, + heapIndex := -1, + fireTimeSec := 0, + fireTimeNsec := 0, + ioIndex := -1, + ioData := nil, + ioMask := 0. method(#class) forMutualExclusion { @@ -109,19 +117,6 @@ class Semaphore(Object) ^sem } - method initialize - { - self.count := 0. - - self.heapIndex := -1. - self.fireTimeSec := 0. - self.fireTimeNsec := 0. - - self.ioIndex := -1. - self.ioData := nil. - self.ioMask := 0. - } - ## ================================================================== method(#primitive) signal. diff --git a/moo/kernel/X11.moo b/moo/kernel/X11.moo index 570ba63..e628f24 100644 --- a/moo/kernel/X11.moo +++ b/moo/kernel/X11.moo @@ -35,16 +35,8 @@ class X11.Exception(System.Exception) class X11.Rectangle(Object) { - var x, y, width, height. + var x := 0, y := 0, width := 0, height := 0. - method initialize - { - self.x := 0. - self.y := 0. - self.width := 0. - self.height := 0. - } - method x { ^self.x } method y { ^self.y } method width { ^self.width } @@ -178,7 +170,7 @@ class X11.ExposeEvent(X11.Event) pooldic X11.GCAttr { (* see xcb/xproto.h *) - GC_FOREGROUND := 4. + GC_FOREGROUND := 4. GC_BACKGROUND := 8. GC_LINE_WIDTH := 16. GC_LINE_STYLE := 32. diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 66c0f47..9a92a4b 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -3204,12 +3204,8 @@ if super is variable-nonpointer, no instance variable is allowed. GET_TOKEN (moo); - /* default value assignment. only a literal is allowed */ - #if defined(MOO_SIMPLE_INITV) + /* [NOTE] default value assignment. only a literal is allowed */ lit = token_to_literal (moo, 1); - #else - lit = token_to_literal (moo, 0); - #endif if (!lit) return -1; /* set the initial value for the variable added above */ @@ -6224,7 +6220,7 @@ static int make_defined_class (moo_t* moo) /* this function make a class object with no functions/methods */ moo_oop_t tmp; - moo_oow_t spec, self_spec; + moo_oow_t spec, self_spec, initv_count; int just_made = 0; spec = MOO_CLASS_SPEC_MAKE (moo->c->cls.var[VAR_INSTANCE].total_count, @@ -6311,28 +6307,97 @@ static int make_defined_class (moo_t* moo) if (!tmp) return -1; moo->c->cls.self_oop->mthdic[MOO_METHOD_CLASS] = (moo_oop_set_t)tmp; -#if 0 - if (moo->c->cls.var[VAR_INSTANCE].initv_total_count > 0) + + /* create an array of default initial values for instance variables */ + initv_count = moo->c->cls.var[VAR_INSTANCE].initv_count; + if (moo->c->cls.super_oop != moo->_nil && ((moo_oop_class_t)moo->c->cls.super_oop)->initv != moo->_nil) { - moo_oow_t i; + initv_count += MOO_OBJ_GET_SIZE(((moo_oop_class_t)moo->c->cls.super_oop)->initv); + } + if (initv_count > 0) + { + moo_oow_t i, j = 0; + + /* [NOTE] + * if some elements at the back of a class definition are lacking default values, + * initv_count is less than total_count. + * in the following case(no inheritance for simplicity): + * class ... { var a, b := 10, c. } + * initv_count is 1 whereas total_count is 3. */ + MOO_ASSERT (moo, initv_count <= moo->c->cls.var[VAR_INSTANCE].total_count); tmp = moo_instantiate (moo, moo->_array, MOO_NULL, moo->c->cls.var[VAR_INSTANCE].total_count); if (!tmp) return -1; - for (i = 0; i < moo->c->cls.var[VAR_INSTANCE].initv_count; i++) + + if (initv_count > moo->c->cls.var[VAR_INSTANCE].initv_count) { - ((moo_oop_oop_t)tmp)->slot[i] = moo->c->cls.var[VAR_INSTANCE].initv[i]; + /* handle default values defined in the superclass chain. + * i merge them into a single array for convenience and + * efficiency of object instantiation by moo_instantiate(). + * it can avoid looking up superclasses upon instantiaion */ + moo_oop_oop_t initv; + moo_oow_t super_count; + + MOO_ASSERT (moo, moo->c->cls.super_oop != moo->_nil); + super_count = initv_count - moo->c->cls.var[VAR_INSTANCE].initv_count; + initv = (moo_oop_oop_t)((moo_oop_class_t)moo->c->cls.super_oop)->initv; + MOO_ASSERT (moo, MOO_CLASSOF(moo, initv) == moo->_array); + for (i = 0; i < super_count; i++) + { + ((moo_oop_oop_t)tmp)->slot[j++] = initv->slot[i]; + } } - moo->c->cls. + for (i = 0; i < moo->c->cls.var[VAR_INSTANCE].initv_count; i++) + { + ((moo_oop_oop_t)tmp)->slot[j++] = moo->c->cls.var[VAR_INSTANCE].initv[i]; + } + + moo->c->cls.self_oop->initv = tmp; + } + + /* initialize class variables with default initial values */ + initv_count = moo->c->cls.var[VAR_CLASS].initv_count; + if (initv_count > 0) + { + moo_oow_t i, j; + /* name instance variables and class instance variables are placed + * in the front part. let's skip them */ + #if 0 + /* this part is almost identical to the actual code after #else + * i keep this for demonstration purpose only */ + j = MOO_CLASS_NAMED_INSTVARS + moo->c->cls.var[VAR_CLASSINST].total_count; + MOO_ASSERT (moo, j + initv_count < MOO_OBJ_GET_SIZE(moo->c->cls.self_oop)); + for (i = 0; i < initv_count; i++) + { + ((moo_oop_oop_t)moo->c->cls.self_oop)->slot[j++] = moo->c->cls.var[VAR_CLASS].initv[i]; + } + #else + j = moo->c->cls.var[VAR_CLASSINST].total_count; + for (i = 0; i < initv_count; i++) + { + moo->c->cls.self_oop->slot[j++] = moo->c->cls.var[VAR_CLASS].initv[i]; + } + #endif + } + +#if 0 + /* create an array of default values for class instance variables */ + initv_count = moo->c->cls.var[VAR_CLASSINST].initv_count; + if (moo->c->cls.super_oop != moo->_nil && ((moo_oop_class_t)moo->c->cls.super_oop)->initv_ci != moo->_nil) + { + initv_count += MOO_OBJ_GET_SIZE(((moo_oop_class_t)moo->c->cls.super_oop)->initv_ci); } #endif +/* TODO: class instance variables ... */ + /* [NOTE] don't create a dictionary on the nsdic. keep it to be nil. * add_nsdic_to_class() instantiates a dictionary if necessary. */ /* [NOTE] don't set the trsize field yet here. */ -/* TODO: initialize more fields??? whatelse. */ +/* TODO: initialize more fields??? what else. */ /* TODO: update the subclasses field of the superclass if it's not nil */ @@ -6659,14 +6724,6 @@ static int __compile_class_definition (moo_t* moo, int extend) moo->c->cls.var[VAR_INSTANCE].total_count = MOO_CLASS_SPEC_NAMED_INSTVAR(spec); moo->c->cls.var[VAR_CLASSINST].total_count = MOO_CLASS_SELFSPEC_CLASSINSTVAR(self_spec); - - if (c->initv != moo->_nil) - { - MOO_ASSERT (moo, MOO_CLASSOF(moo, c->initv) == moo->_array); - moo->c->cls.var[VAR_INSTANCE].initv_total_count = MOO_OBJ_GET_SIZE(c->initv); - } - - /*TODO: moo->c->cls.var[VAR_CLASSINST].total_initv_count = */ } GET_TOKEN (moo); @@ -6693,7 +6750,7 @@ static int __compile_class_definition (moo_t* moo, int extend) ptr = pds->slot; end = pds->slot + MOO_OBJ_GET_SIZE(pds); - /* this loop handles the pooldics string as if it's a pooldic import. + /* this loop handles the pooldic string as if it's a pooldic import. * see compile_class_level_variables() for mostly identical code except token handling */ do { @@ -6839,7 +6896,6 @@ static int compile_class_definition (moo_t* moo, int extend) moo->c->cls.var[i].count = 0; moo->c->cls.var[i].total_count = 0; moo->c->cls.var[i].initv_count = 0; - moo->c->cls.var[i].initv_total_count = 0; /* this reinitialization is needed because set_class_level_variable_initv() * doesn't fill the gap between the last inserted item and the new item inserted */ @@ -7035,11 +7091,10 @@ static int __compile_pooldic_definition (moo_t* moo) GET_TOKEN (moo); - #if defined(MOO_SIMPLE_INITV) - lit = token_to_literal (moo, 1); - #else + /* [NOTE] + * values assigned to a pool dictinary member are not read-only + * unlike the default initial values defined in a class */ lit = token_to_literal (moo, 0); - #endif if (!lit) return -1; /* for this definition, #pooldic MyPoolDic { a := 10. b := 20 }, @@ -7142,7 +7197,7 @@ static int compile_stream (moo_t* moo) } else if (is_token_word(moo, VOCA_POOLDIC)) { - /* pooldic SharedPoolDic { #ABC := 20. #DEFG := 'ayz' } */ + /* pooldic SharedPoolDic { ABC := 20. DEFG := 'ayz' } */ GET_TOKEN (moo); if (compile_pooldic_definition(moo) <= -1) return -1; } diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 680a8dd..78696ac 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -44,10 +44,6 @@ * PUSH_CONTEXT, PUSH_INTLIT, PUSH_INTLIT, SEND_BLOCK_COPY */ #define MOO_USE_MAKE_BLOCK -/* define this to limit the default values for instance variables - * to simple values like numbers or characters */ -#define MOO_SIMPLE_INITV - #if !defined(NDEBUG) /* this is for gc debugging */ #define MOO_DEBUG_GC @@ -468,8 +464,16 @@ struct moo_compiler_t moo_oop_t* initv; moo_oow_t initv_capa; - moo_oow_t initv_count; - moo_oow_t initv_total_count; + /* initv_count holds the index to the last variable with a + * default initial value defined in this class only plus one. + * inheritance is handled by the compiler separately using + * the reference to the superclass. so it doesn't include + * the variables defined in the superclass chain. + * for a definition: class ... { var a, b := 0, c }, + * initv_count is set to 2 while count is 3. totoal_count + * will be 3 too if there is no variabled defined in the + * superclass chain. */ + moo_oow_t initv_count; } var[3]; /* buffer to hold pooldic import declaration */ diff --git a/moo/lib/obj.c b/moo/lib/obj.c index d058861..0ed5c7e 100644 --- a/moo/lib/obj.c +++ b/moo/lib/obj.c @@ -280,22 +280,16 @@ moo_oop_t moo_instantiate (moo_t* moo, moo_oop_class_t _class, const void* vptr, moo_oow_t i = MOO_OBJ_GET_SIZE(_class->initv); - #if defined(MOO_SIMPLE_INITV) + /* [NOTE] i don't deep-copy initial values. + * if you change the contents of compound values like arrays, + * it affects subsequent instantiation of the class. + * it's important that the compiler should mark compound initial + * values read-only. */ while (i > 0) { --i; ((moo_oop_oop_t)oop)->slot[i] = ((moo_oop_oop_t)_class->initv)->slot[i]; } - #else - moo_pushtmp (moo, (moo_oop_t*)&oop); tmp_count++; - while (i > 0) - { - --i; -/* TODO: deep copy the object so that the items can be modified without side-effects.... */ - ((moo_oop_oop_t)oop)->slot[i] = ((moo_oop_oop_t)_class->initv)->slot[i]; - } - moo_poptmp (moo); tmp_count--; - #endif } }