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
{
CLASS_INDEXED = (1 << 0),
CLASS_EXTENDED = (1 << 1)
CLASS_INDEXED = (1 << 0)
};
enum mth_type_t
@ -85,6 +84,7 @@ static struct voca_t
{ 9, { 'c','l','a','s','s','i','n','s','t' } },
{ 3, { 'd','c','l' } },
{ 7, { 'd','e','c','l','a','r','e' } },
{ 6, { 'e','x','t','e','n','d' } },
{ 5, { 'f','a','l','s','e' } },
{ 7, { 'i','n','c','l','u','d','e' } },
{ 4, { 'm','a','i','n' } },
@ -114,6 +114,7 @@ enum voca_id_t
VOCA_CLASSINST,
VOCA_DCL,
VOCA_DECLARE,
VOCA_EXTEND,
VOCA_FALSE,
VOCA_INCLUDE,
VOCA_MAIN,
@ -3893,7 +3894,7 @@ printf (" CONFLICTING CLASS DEFINITION %lu %lu %lu %lu\n",
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 "}"
@ -3910,7 +3911,7 @@ static int __compile_class_definition (stix_t* stix)
*/
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 */
@ -3966,43 +3967,78 @@ static int __compile_class_definition (stix_t* stix)
stix->c->cls.name_loc = stix->c->tok.loc;
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;
printf ("DEFININING..");
print_ucs (&stix->c->cls.name);
printf ("\n");
if (stix->c->tok.type == STIX_IOTOK_LPAREN)
{
/* superclass is specified. new class defintion.
* for example, #class Class(Stix)
*/
GET_TOKEN (stix); /* read superclass name */
/* superclass is specified. new class defintion.
* for example, #class Class(Stix)
*/
GET_TOKEN (stix); /* read superclass name */
/* TODO: multiple inheritance */
/* TODO: multiple inheritance */
if (stix->c->tok.type == STIX_IOTOK_NIL)
{
super_is_nil = 1;
}
else if (stix->c->tok.type != STIX_IOTOK_IDENT)
{
/* superclass name expected */
set_syntax_error (stix, STIX_SYNERR_IDENT, &stix->c->tok.loc, &stix->c->tok.name);
return -1;
}
if (stix->c->tok.type == STIX_IOTOK_NIL)
if (set_superclass_name(stix, &stix->c->tok.name) <= -1) return -1;
stix->c->cls.supername_loc = stix->c->tok.loc;
GET_TOKEN (stix);
if (stix->c->tok.type != STIX_IOTOK_RPAREN)
{
set_syntax_error (stix, STIX_SYNERR_RPAREN, &stix->c->tok.loc, &stix->c->tok.name);
return -1;
}
GET_TOKEN (stix);
}
else
{
super_is_nil = 1;
}
else if (stix->c->tok.type != STIX_IOTOK_IDENT)
{
/* superclass name expected */
set_syntax_error (stix, STIX_SYNERR_IDENT, &stix->c->tok.loc, &stix->c->tok.name);
return -1;
}
if (set_superclass_name(stix, &stix->c->tok.name) <= -1) return -1;
stix->c->cls.supername_loc = stix->c->tok.loc;
GET_TOKEN (stix);
if (stix->c->tok.type != STIX_IOTOK_RPAREN)
{
set_syntax_error (stix, STIX_SYNERR_RPAREN, &stix->c->tok.loc, &stix->c->tok.name);
return -1;
}
GET_TOKEN (stix);
ass = stix_lookupsysdic(stix, &stix->c->cls.name);
if (ass)
@ -4051,45 +4087,7 @@ printf ("\n");
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)
@ -4114,7 +4112,7 @@ printf ("\n");
GET_TOKEN (stix);
if (stix->c->cls.flags & CLASS_EXTENDED)
if (extend)
{
/* when a class is extended, a new variable cannot be added */
if (is_token_symbol(stix, VOCA_DCL) || is_token_symbol(stix, VOCA_DECLARE))
@ -4154,7 +4152,7 @@ printf ("\n");
return -1;
}
if (!(stix->c->cls.flags & CLASS_EXTENDED))
if (!extend)
{
/* TODO: anything else to set? */
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;
}
static int compile_class_definition (stix_t* stix)
static int compile_class_definition (stix_t* stix, int extend)
{
int n;
stix_size_t i;
@ -4195,7 +4193,7 @@ static int compile_class_definition (stix_t* stix)
stix->c->mth.arlit_count = 0;
/* 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() */
stix->c->cls.self_oop = STIX_NULL;
@ -4231,7 +4229,13 @@ static int compile_stream (stix_t* stix)
{
/* #class Selfclass(Superclass) { } */
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
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;
}
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_ooi_t local_ntmprs, i;
@ -853,24 +853,25 @@ struct primitive_t
{
stix_ooi_t nargs; /* expected number of arguments */
primitive_handler_t handler;
stix_ucs_t name;
};
typedef struct primitive_t primitive_t;
static primitive_t primitives[] =
{
{ -1, primitive_dump }, /* 0 */
{ 0, primitive_new }, /* 1 */
{ 1, primitive_new_with_size }, /* 2 */
{ 0, primitive_basic_size }, /* 3 */
{ 1, primitive_basic_at }, /* 4 */
{ 2, primitive_basic_at_put }, /* 5 */
{ -1, primitive_block_context_value }, /* 6 */
{ 1, primitive_integer_add }, /* 7 */
{ 1, primitive_integer_sub }, /* 8 */
{ 1, primitive_integer_mul }, /* 9 */
{ 1, primitive_integer_eq }, /* 10 */
{ 1, primitive_integer_lt }, /* 11 */
{ 1, primitive_integer_gt } /* 12 */
/* 0 */ { -1, primitive_dump },
/* 1 */ { 0, primitive_new },
/* 2 */ { 1, primitive_new_with_size },
/* 3 */ { 0, primitive_basic_size },
/* 4 */ { 1, primitive_basic_at },
/* 5 */ { 2, primitive_basic_at_put },
/* 6 */ { -1, primitive_block_value },
/* 7 */ { 1, primitive_integer_add },
/* 8 */ { 1, primitive_integer_sub },
/* 9 */ { 1, primitive_integer_mul },
/* 10 */ { 1, primitive_integer_eq },
/* 11 */ { 1, primitive_integer_lt },
/* 12 */ { 1, primitive_integer_gt }
};
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
* 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.
* this base block context is created with no
* stack for this reason. */
@ -1705,7 +1706,7 @@ printf ("SEND_BLOCK_COPY\n");
/* the block context object created here is used
* 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.
* this base block context is created with no
* stack for this reason. */
@ -1720,7 +1721,7 @@ printf ("SEND_BLOCK_COPY\n");
/* [NOTE]
* blkctx->caller is left to nil. it is set to the
* active context before it gets activated. see
* primitive_block_context_value().
* primitive_block_value().
*
* blkctx->home is set here to the active context.
* it's redundant to have them pushed to the stack

View File

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