Index: generic/xotcl.c =================================================================== diff -u -r6b268aad6ca544a21458a5299568fe91d6cddaac -ref3421c713c73a847d5d3a2b8c70aa720c725f47 --- generic/xotcl.c (.../xotcl.c) (revision 6b268aad6ca544a21458a5299568fe91d6cddaac) +++ generic/xotcl.c (.../xotcl.c) (revision ef3421c713c73a847d5d3a2b8c70aa720c725f47) @@ -1369,7 +1369,7 @@ static void -FlushPrecedences(XOTclClass *cl) { +FlushPrecedencesOnSubclasses(XOTclClass *cl) { XOTclClasses *pc; XOTclFreeClasses(cl->order); cl->order = 0; @@ -1501,6 +1501,7 @@ /*fprintf(stderr, "find %s in %p returns %p\n", methodName, cmdTable, cmd);*/ return NULL; #endif + if ((entryPtr = Tcl_FindHashEntry(Tcl_Namespace_cmdTable(nsPtr), methodName))) { return (Tcl_Command) Tcl_GetHashValue(entryPtr); } @@ -1510,7 +1511,7 @@ static XOTclClass* SearchPLMethod(register XOTclClasses *pl, char *nm, Tcl_Command *cmd) { - /* Search the class hierarchy */ + /* Search the precedence list (class hierarchy) */ for (; pl; pl = pl->next) { Tcl_Command pi = FindMethod(nm, pl->cl->nsPtr); if (pi) { @@ -4637,10 +4638,11 @@ osl->next = l; (void)RemoveSuper(cl, cl->super->cl); } - for (i = 0; i < oc; i++) + for (i = 0; i < oc; i++) { AddSuper(cl, scl[i]); + } FREE(XOTclClass**, scl); - FlushPrecedences(cl); + FlushPrecedencesOnSubclasses(cl); if (!ComputeOrder(cl, cl->order, Super)) { @@ -7426,6 +7428,7 @@ Tcl_HashEntry *hPtr; XOTclClass *theobj = RUNTIME_STATE(interp)->theObject; XOTclClassOpt *clopt = cl->opt; + assert(softrecreate? recreate == 1 : 1); if (clopt) { @@ -7507,12 +7510,18 @@ clopt = cl->opt = 0; } + /* On a recreate, it might be possible that the newly created class + has a different superclass. So we have to flush the precedence list + on a recreate as well. + */ + FlushPrecedencesOnSubclasses(cl); + while (cl->super) (void)RemoveSuper(cl, cl->super->cl); + if (!softrecreate) { /* * flush all caches, unlink superclasses */ - - FlushPrecedences(cl); + while (cl->sub) { XOTclClass *subClass = cl->sub->cl; (void)RemoveSuper(subClass, cl); @@ -7523,7 +7532,6 @@ if (subClass->super == 0 && cl != theobj) AddSuper(subClass, theobj); } - while (cl->super) (void)RemoveSuper(cl, cl->super->cl); } } @@ -7552,11 +7560,16 @@ XOTclObjectSetClass(obj); cl->nsPtr = namespacePtr; - + if (!softrecreate) { + /* subclasses are preserved during recreate, superclasses not (since + the creation statement defined the superclass, might be different + the second time) + */ + cl->sub = 0; + } cl->super = 0; - cl->sub = 0; AddSuper(cl, RUNTIME_STATE(interp)->theObject); - cl->parent = RUNTIME_STATE(interp)->theObject; + cl->color = WHITE; cl->order = 0; cl->parameters = 0; @@ -7599,6 +7612,7 @@ * call and latch user destroy with obj->id if we haven't */ /*fprintf(stderr,"PrimitiveCDestroy %s flags %x\n", ObjStr(obj->cmdName), obj->flags);*/ + if (!(obj->flags & XOTCL_DESTROY_CALLED)) /*fprintf(stderr,"PrimitiveCDestroy call destroy\n");*/ callDestroyMethod(cd, interp, obj, 0); @@ -7617,7 +7631,7 @@ /* * class object destroy + physical destroy */ - /*fprintf(stderr,"primitive cdestroy calls primitive odestroy\n");*/ + /* fprintf(stderr,"primitive cdestroy calls primitive odestroy\n");*/ PrimitiveODestroy(cd); /*fprintf(stderr,"primitive cdestroy calls deletenamespace for obj %p\n", cl);*/ @@ -12519,9 +12533,6 @@ RUNTIME_STATE(interp)->theClass = thecls; if (!thecls) Tcl_Panic("Cannot create ::xotcl::Class", NULL); - theobj->parent = 0; - thecls->parent = theobj; - Tcl_Export(interp, RUNTIME_STATE(interp)->XOTclNS, "Object", 0); Tcl_Export(interp, RUNTIME_STATE(interp)->XOTclNS, "Class", 0); /*Tcl_AddInterpResolvers(interp, "XOTcl", XOTclResolveCmd, 0, 0);*/ Index: generic/xotclInt.h =================================================================== diff -u -r4486d6fcdfe92418d68bf73e9c75dc869b78902e -ref3421c713c73a847d5d3a2b8c70aa720c725f47 --- generic/xotclInt.h (.../xotclInt.h) (revision 4486d6fcdfe92418d68bf73e9c75dc869b78902e) +++ generic/xotclInt.h (.../xotclInt.h) (revision ef3421c713c73a847d5d3a2b8c70aa720c725f47) @@ -511,7 +511,7 @@ struct XOTclClasses* sub; short color; struct XOTclClasses* order; - struct XOTclClass* parent; + /*struct XOTclClass* parent;*/ Tcl_HashTable instances; Tcl_Namespace *nsPtr; Tcl_Obj* parameters; Index: tests/mixinoftest.xotcl =================================================================== diff -u -r4486d6fcdfe92418d68bf73e9c75dc869b78902e -ref3421c713c73a847d5d3a2b8c70aa720c725f47 --- tests/mixinoftest.xotcl (.../mixinoftest.xotcl) (revision 4486d6fcdfe92418d68bf73e9c75dc869b78902e) +++ tests/mixinoftest.xotcl (.../mixinoftest.xotcl) (revision ef3421c713c73a847d5d3a2b8c70aa720c725f47) @@ -85,16 +85,16 @@ ? {b1 info precedence} "::M ::A ::B ::xotcl::Object" ? {c1 info precedence} "::M ::A ::C ::B ::xotcl::Object" -# Wie werden transitive instmixin behandelt? -# M ist ein instmixin von A, A ist ein instmixin von B, -# so würde ich erwarten, dass M auch ein transitives instmixin -# von A ist. Sollte das instmixinof nicht -# - das Ergebnis von getAllClassMixinsOf liefern? -# - getAllClassMixinsOf nicht auch die subklassen inkludieren -# (siehe MixinResetOrderForAllInstances) -#? {M info instmixinof} "::A ::B" oder "::A ::B ::C"" -#? {M info instmixinof} "::A ::B" +? {M info instmixinof} "::A" +# since M is an instmixin of A and A is a instmixin of B, +# M is a instmixin of B as well, and of its subclasses +? {M info instmixinof -closure} "::A ::B ::C" +? {A info instmixinof} "::B" +? {A info instmixinof -closure} "::B ::C" +? {B info instmixinof} "" +? {B info instmixinof -closure} "" +# and now destroy mixin classes M destroy ? {a1 info precedence} "::A ::xotcl::Object" ? {b1 info precedence} "::A ::B ::xotcl::Object" @@ -104,9 +104,7 @@ ? {A info instmixinof} "" ? {c1 info precedence} "::C ::xotcl::Object" -foreach o {A C a1 b1 c1} { - $o destroy -} +foreach o {A C a1 b1 c1} { $o destroy } ########################################### @@ -127,19 +125,21 @@ ? {b1 info precedence} "::M ::A ::B ::xotcl::Object" ? {c1 info precedence} "::M ::A ::C ::B ::xotcl::Object" +# and now destroy A A destroy ? {a1 info precedence} "::xotcl::Object" ? {b1 info precedence} "::B ::xotcl::Object" ? {c1 info precedence} "::C ::B ::xotcl::Object" -#? {M info instmixinof} "????" +? {M info instmixinof} "" +? {M info instmixinof -closure} "" + + B destroy ? {M info instmixinof} "" ? {c1 info precedence} "::C ::xotcl::Object" -foreach o {M C a1 b1 c1} { - $o destroy -} +foreach o {M C a1 b1 c1} { $o destroy } ########################################### # testing transitive per class mixins (part 3) @@ -164,9 +164,9 @@ ? {b1 info precedence} "::xotcl::Object" ? {c1 info precedence} "::C ::xotcl::Object" +? {M info instmixinof} "::A" +? {M info instmixinof -closure} "::A" ? {A info instmixinof} "" -#? {M info instmixinof} "???" -? {c1 info precedence} "::C ::xotcl::Object" foreach o {M C a1 b1 c1} { $o destroy @@ -237,6 +237,139 @@ C destroy c1 destroy + +########################################### +# test of recreate with same superclass, +# with softrecreate off +########################################### +::xotcl::test::case precedence +::xotcl::configure softrecreate false +Class O +Class A -superclass O +Class B -superclass A +B b1 +A a1 +O o1 +? {A info superclass} "::O" +? {B info heritage} "::A ::O ::xotcl::Object" +? {list [A info subclass] [B info subclass] [O info subclass]} "::B {} ::A" +? {list [A info superclass] [B info superclass] [O info superclass]} "::O ::A ::xotcl::Object" +? {list [a1 info class] [b1 info class] [o1 info class]} "::A ::B ::O" +? {o1 info precedence} "::O ::xotcl::Object" +? {a1 info precedence} "::A ::O ::xotcl::Object" +? {b1 info precedence} "::B ::A ::O ::xotcl::Object" +# we recreate the class new, with the same superclass +Class A -superclass O +? {A info superclass} "::O" +? {B info heritage} "::xotcl::Object" +? {list [A info subclass] [B info subclass] [O info subclass]} "{} {} ::A" +? {list [A info superclass] [B info superclass] [O info superclass]} "::O ::xotcl::Object ::xotcl::Object" +? {list [a1 info class] [b1 info class] [o1 info class]} "::xotcl::Object ::B ::O" +? {o1 info precedence} "::O ::xotcl::Object" +? {a1 info precedence} "::xotcl::Object" +? {b1 info precedence} "::B ::xotcl::Object" +foreach o {A O B a1 b1 o1} {$o destroy} + +########################################### +# test of recreate with different superclass +# with softrecreate on +########################################### +::xotcl::test::case alternate-precedence +::xotcl::configure softrecreate false +Class O +Class A -superclass O +Class B -superclass A +B b1 +A a1 +O o1 +? {A info superclass} "::O" +? {B info heritage} "::A ::O ::xotcl::Object" +? {list [A info subclass] [B info subclass] [O info subclass]} "::B {} ::A" +? {list [A info superclass] [B info superclass] [O info superclass]} "::O ::A ::xotcl::Object" +? {list [a1 info class] [b1 info class] [o1 info class]} "::A ::B ::O" +? {o1 info precedence} "::O ::xotcl::Object" +? {a1 info precedence} "::A ::O ::xotcl::Object" +? {b1 info precedence} "::B ::A ::O ::xotcl::Object" +# we recreate the class new, with a different superclass +Class A +? {A info superclass} "::xotcl::Object" +? {B info heritage} "::xotcl::Object" +? {list [A info subclass] [B info subclass] [O info subclass]} "{} {} {}" +? {list [A info superclass] [B info superclass] [O info superclass]} "::xotcl::Object ::xotcl::Object ::xotcl::Object" +? {list [a1 info class] [b1 info class] [o1 info class]} "::xotcl::Object ::B ::O" +? {o1 info precedence} "::O ::xotcl::Object" +? {a1 info precedence} "::xotcl::Object" +? {b1 info precedence} "::B ::xotcl::Object" +foreach o {A O B a1 b1 o1} {$o destroy} + + +########################################### +# test of recreate with same superclass, +# with softrecreate on +########################################### +::xotcl::test::case recreate-precedence +::xotcl::configure softrecreate true +Class O +Class A -superclass O +Class B -superclass A +B b1 +A a1 +O o1 +? {A info superclass} "::O" +? {B info heritage} "::A ::O ::xotcl::Object" +? {list [A info subclass] [B info subclass] [O info subclass]} "::B {} ::A" +? {list [A info superclass] [B info superclass] [O info superclass]} "::O ::A ::xotcl::Object" +? {list [a1 info class] [b1 info class] [o1 info class]} "::A ::B ::O" +? {o1 info precedence} "::O ::xotcl::Object" +? {a1 info precedence} "::A ::O ::xotcl::Object" +? {b1 info precedence} "::B ::A ::O ::xotcl::Object" +# we recreate the class new, with the same superclass +Class A -superclass O +? {A info superclass} "::O" +? {B info heritage} "::A ::O ::xotcl::Object" +? {list [A info subclass] [B info subclass] [O info subclass]} "::B {} ::A" +? {list [A info superclass] [B info superclass] [O info superclass]} "::O ::A ::xotcl::Object" +? {list [a1 info class] [b1 info class] [o1 info class]} "::A ::B ::O" +? {o1 info precedence} "::O ::xotcl::Object" +? {a1 info precedence} "::A ::O ::xotcl::Object" +? {b1 info precedence} "::B ::A ::O ::xotcl::Object" +foreach o {A O B a1 b1 o1} {$o destroy} + +########################################### +# test of recreate with different superclass +# with softrecreate on +########################################### +::xotcl::test::case recreate-alternate-precedence +::xotcl::configure softrecreate true +Class O +Class A -superclass O +Class B -superclass A +B b1 +A a1 +O o1 +? {B info heritage} "::A ::O ::xotcl::Object" +? {list [A info subclass] [B info subclass] [O info subclass]} "::B {} ::A" +? {list [A info superclass] [B info superclass] [O info superclass]} "::O ::A ::xotcl::Object" +? {list [a1 info class] [b1 info class] [o1 info class]} "::A ::B ::O" +? {o1 info precedence} "::O ::xotcl::Object" +? {a1 info precedence} "::A ::O ::xotcl::Object" +? {b1 info precedence} "::B ::A ::O ::xotcl::Object" +# we recreate the class new, with a different superclass +Class A +? {A info superclass} "::xotcl::Object" +? {B info heritage} "::A ::xotcl::Object" +? {B info heritage} "::A ::xotcl::Object" +? {list [A info subclass] [B info subclass] [O info subclass]} "::B {} {}" +? {list [A info superclass] [B info superclass] [O info superclass]} "::xotcl::Object ::A ::xotcl::Object" +? {list [a1 info class] [b1 info class] [o1 info class]} "::A ::B ::O" +? {o1 info precedence} "::O ::xotcl::Object" +? {a1 info precedence} "::A ::xotcl::Object" +? {b1 info precedence} "::B ::A ::xotcl::Object" +foreach o {A O B a1 b1 o1} {$o destroy} + + + + #foreach o [::xotcl::test::Test info instances] {$o destroy} #::xotcl::test::Test destroy #puts [lsort [::xotcl::Object allinstances]]