introduced #extend for extending a class.
#class XXX without a superclass inherits nil
This commit is contained in:
parent
132e4b48bb
commit
4d181b521a
102
stix/lib/comp.c
102
stix/lib/comp.c
@ -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))
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user