Forget to remove the return after real_exception, as recomended in a
talk in #parrot.

Second revision attached.

-- 
Salu2
Index: src/oo.c
===================================================================
--- src/oo.c	(revisión: 27509)
+++ src/oo.c	(copia de trabajo)
@@ -1148,8 +1148,7 @@
 
 =item C<PMC * Parrot_remove_parent>
 
-This currently does nothing but return C<PMCNULL>.
-RT#50646
+Remove a parent class from a PMC, by invoking his remove_parent method.
 
 =cut
 
@@ -1162,11 +1161,8 @@
 Parrot_remove_parent(PARROT_INTERP, ARGIN(PMC *removed_class),
         ARGIN(PMC *existing_class))
 {
-    UNUSED(interp);
-    UNUSED(removed_class);
-    UNUSED(existing_class);
-
-    return PMCNULL;
+    VTABLE_remove_parent(interp, existing_class, removed_class);
+    return existing_class;
 }
 
 
Index: src/pmc/class.pmc
===================================================================
--- src/pmc/class.pmc	(revisión: 27509)
+++ src/pmc/class.pmc	(copia de trabajo)
@@ -780,6 +780,66 @@
 
 /*
 
+=item C<void remove_parent(PMC *parent)>
+
+Remove the supplied PMC from the list of parents for the class.
+Throws E_TypeError if parent is NULL, is not a class, or is not a parent.
+Throws INVALID_OPERATION if the class has been instantiated.
+
+=cut
+
+*/
+    VTABLE void remove_parent(PMC *parent) {
+        Parrot_Class * const _class = PARROT_CLASS(SELF);
+
+        /* get number of direct parents */
+        const int parent_count      = VTABLE_elements(interp, _class->parents);
+
+        int index; /* loop iterator */
+
+        /* If we've been instantiated already, not allowed. */
+        if (_class->instantiated) {
+            real_exception(interp, NULL, INVALID_OPERATION,
+                "Modifications to classes are not allowed after instantiation.");
+        }
+
+        /* Ensure it really is a class. */
+        if (!PObj_is_class_TEST(parent)) {
+            real_exception(interp, NULL, E_TypeError, "Parent isn't a Class.");
+        }
+
+        /* iterate over all direct parents, looking for
+         * the parent to be removed.
+         */
+        for (index = 0; index < parent_count; index++) {
+            /* get the next parent */
+            PMC * const current_parent = VTABLE_get_pmc_keyed_int(interp,
+                                      _class->parents, index);
+            if (current_parent == parent)
+                break;
+        }
+        if (index >= parent_count)
+            real_exception(interp, NULL, INVALID_OPERATION,
+                "Can't remove_parent: is not a parent.");
+
+        /* Move up the remaining parents on the list and pops it */
+        for (; index < parent_count - 1; index++) {
+            PMC * const current_parent = VTABLE_get_pmc_keyed_int(interp,
+                _class->parents, index + 1);
+            VTABLE_set_pmc_keyed_int(interp, _class->parents,
+                index, current_parent);
+        }
+        VTABLE_pop_pmc(interp, _class->parents);
+
+        _class->all_parents = Parrot_ComputeMRO_C3(interp, SELF);
+
+        /* Anonymous classes have no entry in the vtable array */
+        if (!CLASS_is_anon_TEST(SELF))
+            interp->vtables[VTABLE_type(interp, SELF)]->mro = _class->all_parents;
+    }
+
+/*
+
 =item C<void add_role(PMC *role)>
 
 Adds the supplied PMC to the list of roles for the class, provided there are
Index: t/oo/removeparent.t
===================================================================
--- t/oo/removeparent.t	(revisión: 0)
+++ t/oo/removeparent.t	(revisión: 0)
@@ -0,0 +1,123 @@
+#! parrot
+# Copyright (C) 2008, The Perl Foundation.
+# $Id: $
+
+=head1 NAME
+
+t/oo/removeparent.t - Test OO inheritance
+
+=head1 SYNOPSIS
+
+    % prove t/oo/removeparent.t
+
+=head1 DESCRIPTION
+
+Tests OO features related to the removeparent opcode.
+
+=cut
+
+.sub main :main
+    .include 'include/test_more.pir'
+
+    plan(4)
+
+    remove_1()
+    remove_2()
+    remove_Y()
+    remove_diamond()
+.end
+
+.sub remove_1
+    $P1 = newclass "Foo"
+    $P2 = newclass "Bar"
+    $I1 = isa $P2, $P1
+    if $I1, fail
+    addparent $P2, $P1
+    $I1 = isa $P2, $P1
+    unless $I1, fail
+    removeparent $P2, $P1
+    $I1 = isa $P2, $P1
+    if $I1, fail
+    $I1 = 1
+    ok( $I1, 'simple')
+fail:
+.end
+
+.sub remove_2
+    $P1 = newclass "Foo2_1"
+    $P2 = newclass "Foo2_2"
+    $P3 = newclass "Bar2"
+    $I1 = isa $P3, $P1
+    if $I1, fail
+    $I1 = isa $P3, $P2
+    if $I1, fail
+    addparent $P3, $P1
+    $I1 = isa $P3, $P1
+    unless $I1, fail
+    $I1 = isa $P3, $P2
+    if $I1, fail
+    addparent $P3, $P2
+    $I1 = isa $P3, $P2
+    unless $I1, fail
+    removeparent $P3, $P1
+    $I1 = isa $P3, $P1
+    if $I1, fail
+    $I1 = isa $P3, $P2
+    unless $I1, fail
+    removeparent $P3, $P2
+    $I1 = isa $P3, $P1
+    if $I1, fail
+    $I1 = isa $P3, $P2
+    if $I1, fail
+    $I1 = 1
+    ok( $I1, 'multiple')
+fail:
+.end
+
+.sub remove_Y
+    $P1 = newclass "FooY_1"
+    $P2 = newclass "FooY_2"
+    $P3 = newclass "BarY_1"
+    $P4 = newclass "BarY_2"
+    addparent $P3, $P1
+    addparent $P3, $P2
+    $I1 = isa $P4, $P1
+    if $I1, fail
+    $I1 = isa $P4, $P2
+    if $I1, fail
+    addparent $P4, $P3
+    $I1 = isa $P4, $P1
+    unless $I1, fail
+    $I1 = isa $P4, $P2
+    unless $I1, fail
+    removeparent $P4, $P3
+    $I1 = isa $P4, $P1
+    if $I1, fail
+    $I1 = isa $P4, $P2
+    if $I1, fail
+    $I1 = 1
+    ok( $I1, 'Y')
+fail:
+.end
+
+.sub remove_diamond
+    $P1 = newclass "FooD1"
+    $P2 = newclass "FooD2"
+    $P3 = newclass "FooD3"
+    $P4 = newclass "BarD1"
+    addparent $P2, $P1
+    addparent $P3, $P1
+    addparent $P4, $P2
+    addparent $P4, $P3
+    $I1 = isa $P4, $P1
+    unless $I1, fail
+    removeparent $P4, $P2
+    $I1 = isa $P4, $P1
+    unless $I1, fail
+    removeparent $P4, $P3
+    $I1 = isa $P4, $P1
+    if $I1, fail
+    $I1 = 1
+    ok( $I1, 'diamond')
+fail:
+.end

Reply via email to