introduced #extend for extending a class.

#class XXX without a superclass inherits nil
This commit is contained in:
hyunghwan.chung 2015-07-06 13:27:49 +00:00
parent 132e4b48bb
commit 4d181b521a
3 changed files with 97 additions and 92 deletions

View File

@ -40,8 +40,7 @@
enum class_mod_t enum class_mod_t
{ {
CLASS_INDEXED = (1 << 0), CLASS_INDEXED = (1 << 0)
CLASS_EXTENDED = (1 << 1)
}; };
enum mth_type_t enum mth_type_t
@ -85,6 +84,7 @@ static struct voca_t
{ 9, { 'c','l','a','s','s','i','n','s','t' } }, { 9, { 'c','l','a','s','s','i','n','s','t' } },
{ 3, { 'd','c','l' } }, { 3, { 'd','c','l' } },
{ 7, { 'd','e','c','l','a','r','e' } }, { 7, { 'd','e','c','l','a','r','e' } },
{ 6, { 'e','x','t','e','n','d' } },
{ 5, { 'f','a','l','s','e' } }, { 5, { 'f','a','l','s','e' } },
{ 7, { 'i','n','c','l','u','d','e' } }, { 7, { 'i','n','c','l','u','d','e' } },
{ 4, { 'm','a','i','n' } }, { 4, { 'm','a','i','n' } },
@ -114,6 +114,7 @@ enum voca_id_t
VOCA_CLASSINST, VOCA_CLASSINST,
VOCA_DCL, VOCA_DCL,
VOCA_DECLARE, VOCA_DECLARE,
VOCA_EXTEND,
VOCA_FALSE, VOCA_FALSE,
VOCA_INCLUDE, VOCA_INCLUDE,
VOCA_MAIN, VOCA_MAIN,
@ -3893,7 +3894,7 @@ printf (" CONFLICTING CLASS DEFINITION %lu %lu %lu %lu\n",
return 0; return 0;
} }
static int __compile_class_definition (stix_t* stix) static int __compile_class_definition (stix_t* stix, int extend)
{ {
/* /*
* class-definition := #class class-modifier? "{" class-body "}" * class-definition := #class class-modifier? "{" class-body "}"
@ -3910,7 +3911,7 @@ static int __compile_class_definition (stix_t* stix)
*/ */
stix_oop_association_t ass; stix_oop_association_t ass;
if (stix->c->tok.type == STIX_IOTOK_LPAREN) if (!extend && stix->c->tok.type == STIX_IOTOK_LPAREN)
{ {
/* process class modifiers */ /* process class modifiers */
@ -3966,14 +3967,44 @@ static int __compile_class_definition (stix_t* stix)
stix->c->cls.name_loc = stix->c->tok.loc; stix->c->cls.name_loc = stix->c->tok.loc;
GET_TOKEN (stix); GET_TOKEN (stix);
if (stix->c->tok.type == STIX_IOTOK_LPAREN) if (extend)
{
/* extending class */
STIX_ASSERT (stix->c->cls.flags == 0);
ass = stix_lookupsysdic(stix, &stix->c->cls.name);
if (ass &&
STIX_CLASSOF(stix, ass->value) == stix->_class &&
STIX_OBJ_GET_FLAGS_KERNEL(ass->value) != 1)
{
/* the value must be a class object.
* and it must be either a user-defined(0) or
* completed kernel built-in(2).
* an incomplete kernel built-in class object(1) can not be
* extended */
stix->c->cls.self_oop = (stix_oop_class_t)ass->value;
}
else
{
/* only an existing class can be extended. */
set_syntax_error (stix, STIX_SYNERR_CLASSUNDEF, &stix->c->cls.name_loc, &stix->c->cls.name);
return -1;
}
stix->c->cls.super_oop = stix->c->cls.self_oop->superclass;
STIX_ASSERT ((stix_oop_t)stix->c->cls.super_oop == stix->_nil ||
STIX_CLASSOF(stix, stix->c->cls.super_oop) == stix->_class);
}
else
{ {
int super_is_nil = 0; int super_is_nil = 0;
printf ("DEFININING.."); printf ("DEFININING..");
print_ucs (&stix->c->cls.name); print_ucs (&stix->c->cls.name);
printf ("\n"); printf ("\n");
if (stix->c->tok.type == STIX_IOTOK_LPAREN)
{
/* superclass is specified. new class defintion. /* superclass is specified. new class defintion.
* for example, #class Class(Stix) * for example, #class Class(Stix)
*/ */
@ -4003,6 +4034,11 @@ printf ("\n");
} }
GET_TOKEN (stix); GET_TOKEN (stix);
}
else
{
super_is_nil = 1;
}
ass = stix_lookupsysdic(stix, &stix->c->cls.name); ass = stix_lookupsysdic(stix, &stix->c->cls.name);
if (ass) if (ass)
@ -4051,45 +4087,7 @@ printf ("\n");
return -1; return -1;
} }
} }
}
else
{
/* extending class */
if (stix->c->cls.flags != 0)
{
/* the class definition specified with modifiers cannot extend
* an existing class. the superclass must be specified enclosed
* in parentheses. an opening parenthesis is expected to specify
* a superclass here. */
set_syntax_error (stix, STIX_SYNERR_LPAREN, &stix->c->tok.loc, &stix->c->tok.name);
return -1;
}
stix->c->cls.flags |= CLASS_EXTENDED;
ass = stix_lookupsysdic(stix, &stix->c->cls.name);
if (ass &&
STIX_CLASSOF(stix, ass->value) == stix->_class &&
STIX_OBJ_GET_FLAGS_KERNEL(ass->value) != 1)
{
/* the value must be a class object.
* and it must be either a user-defined(0) or
* completed kernel built-in(2).
* an incomplete kernel built-in class object(1) can not be
* extended */
stix->c->cls.self_oop = (stix_oop_class_t)ass->value;
}
else
{
/* only an existing class can be extended. */
set_syntax_error (stix, STIX_SYNERR_CLASSUNDEF, &stix->c->cls.name_loc, &stix->c->cls.name);
return -1;
}
stix->c->cls.super_oop = stix->c->cls.self_oop->superclass;
STIX_ASSERT ((stix_oop_t)stix->c->cls.super_oop == stix->_nil ||
STIX_CLASSOF(stix, stix->c->cls.super_oop) == stix->_class);
} }
if (stix->c->tok.type != STIX_IOTOK_LBRACE) if (stix->c->tok.type != STIX_IOTOK_LBRACE)
@ -4114,7 +4112,7 @@ printf ("\n");
GET_TOKEN (stix); GET_TOKEN (stix);
if (stix->c->cls.flags & CLASS_EXTENDED) if (extend)
{ {
/* when a class is extended, a new variable cannot be added */ /* when a class is extended, a new variable cannot be added */
if (is_token_symbol(stix, VOCA_DCL) || is_token_symbol(stix, VOCA_DECLARE)) if (is_token_symbol(stix, VOCA_DCL) || is_token_symbol(stix, VOCA_DECLARE))
@ -4154,7 +4152,7 @@ printf ("\n");
return -1; return -1;
} }
if (!(stix->c->cls.flags & CLASS_EXTENDED)) if (!extend)
{ {
/* TODO: anything else to set? */ /* TODO: anything else to set? */
stix->c->cls.self_oop->mthdic[STIX_CLASS_MTHDIC_INSTANCE] = stix->c->cls.mthdic_oop[MTH_INSTANCE]; stix->c->cls.self_oop->mthdic[STIX_CLASS_MTHDIC_INSTANCE] = stix->c->cls.mthdic_oop[MTH_INSTANCE];
@ -4165,7 +4163,7 @@ printf ("\n");
return 0; return 0;
} }
static int compile_class_definition (stix_t* stix) static int compile_class_definition (stix_t* stix, int extend)
{ {
int n; int n;
stix_size_t i; stix_size_t i;
@ -4195,7 +4193,7 @@ static int compile_class_definition (stix_t* stix)
stix->c->mth.arlit_count = 0; stix->c->mth.arlit_count = 0;
/* do main compilation work */ /* do main compilation work */
n = __compile_class_definition (stix); n = __compile_class_definition (stix, extend);
/* reset these oops plus literal pointers not to confuse gc_compiler() */ /* reset these oops plus literal pointers not to confuse gc_compiler() */
stix->c->cls.self_oop = STIX_NULL; stix->c->cls.self_oop = STIX_NULL;
@ -4231,7 +4229,13 @@ static int compile_stream (stix_t* stix)
{ {
/* #class Selfclass(Superclass) { } */ /* #class Selfclass(Superclass) { } */
GET_TOKEN (stix); GET_TOKEN (stix);
if (compile_class_definition(stix) <= -1) return -1; if (compile_class_definition(stix, 0) <= -1) return -1;
}
else if (is_token_symbol(stix, VOCA_EXTEND))
{
/* #extend Selfclass {} */
GET_TOKEN (stix);
if (compile_class_definition(stix, 1) <= -1) return -1;
} }
#if 0 #if 0
else if (is_token_symbol(stix, VOCA_MAIN)) else if (is_token_symbol(stix, VOCA_MAIN))

View File

@ -598,7 +598,7 @@ static int primitive_basic_at_put (stix_t* stix, stix_ooi_t nargs)
return 1; return 1;
} }
static int primitive_block_context_value (stix_t* stix, stix_ooi_t nargs) static int primitive_block_value (stix_t* stix, stix_ooi_t nargs)
{ {
stix_oop_context_t blkctx, org_blkctx; stix_oop_context_t blkctx, org_blkctx;
stix_ooi_t local_ntmprs, i; stix_ooi_t local_ntmprs, i;
@ -853,24 +853,25 @@ struct primitive_t
{ {
stix_ooi_t nargs; /* expected number of arguments */ stix_ooi_t nargs; /* expected number of arguments */
primitive_handler_t handler; primitive_handler_t handler;
stix_ucs_t name;
}; };
typedef struct primitive_t primitive_t; typedef struct primitive_t primitive_t;
static primitive_t primitives[] = static primitive_t primitives[] =
{ {
{ -1, primitive_dump }, /* 0 */ /* 0 */ { -1, primitive_dump },
{ 0, primitive_new }, /* 1 */ /* 1 */ { 0, primitive_new },
{ 1, primitive_new_with_size }, /* 2 */ /* 2 */ { 1, primitive_new_with_size },
{ 0, primitive_basic_size }, /* 3 */ /* 3 */ { 0, primitive_basic_size },
{ 1, primitive_basic_at }, /* 4 */ /* 4 */ { 1, primitive_basic_at },
{ 2, primitive_basic_at_put }, /* 5 */ /* 5 */ { 2, primitive_basic_at_put },
{ -1, primitive_block_context_value }, /* 6 */ /* 6 */ { -1, primitive_block_value },
{ 1, primitive_integer_add }, /* 7 */ /* 7 */ { 1, primitive_integer_add },
{ 1, primitive_integer_sub }, /* 8 */ /* 8 */ { 1, primitive_integer_sub },
{ 1, primitive_integer_mul }, /* 9 */ /* 9 */ { 1, primitive_integer_mul },
{ 1, primitive_integer_eq }, /* 10 */ /* 10 */ { 1, primitive_integer_eq },
{ 1, primitive_integer_lt }, /* 11 */ /* 11 */ { 1, primitive_integer_lt },
{ 1, primitive_integer_gt } /* 12 */ /* 12 */ { 1, primitive_integer_gt }
}; };
int stix_execute (stix_t* stix) int stix_execute (stix_t* stix)
@ -1654,7 +1655,7 @@ printf ("MAKE_BLOCK %d %d\n", (int)b1, (int)b2);
/* the block context object created here is used /* the block context object created here is used
* as a base object for block context activation. * as a base object for block context activation.
* primitive_block_context_value() clones a block * primitive_block_value() clones a block
* context and activates the cloned context. * context and activates the cloned context.
* this base block context is created with no * this base block context is created with no
* stack for this reason. */ * stack for this reason. */
@ -1705,7 +1706,7 @@ printf ("SEND_BLOCK_COPY\n");
/* the block context object created here is used /* the block context object created here is used
* as a base object for block context activation. * as a base object for block context activation.
* primitive_block_context_value() clones a block * primitive_block_value() clones a block
* context and activates the cloned context. * context and activates the cloned context.
* this base block context is created with no * this base block context is created with no
* stack for this reason. */ * stack for this reason. */
@ -1720,7 +1721,7 @@ printf ("SEND_BLOCK_COPY\n");
/* [NOTE] /* [NOTE]
* blkctx->caller is left to nil. it is set to the * blkctx->caller is left to nil. it is set to the
* active context before it gets activated. see * active context before it gets activated. see
* primitive_block_context_value(). * primitive_block_value().
* *
* blkctx->home is set here to the active context. * blkctx->home is set here to the active context.
* it's redundant to have them pushed to the stack * it's redundant to have them pushed to the stack

View File

@ -9,12 +9,12 @@
## use #extend to extend a class ## use #extend to extend a class
## using #class for both feels confusing. ## using #class for both feels confusing.
#class Stix #extend Stix
{ {
} }
#class SmallInteger #extend SmallInteger
{ {
#method getTrue: anInteger #method getTrue: anInteger
{ {