Author: jonathan
Date: Thu Mar 15 16:09:32 2007
New Revision: 17514

Modified:
   trunk/CREDITS
   trunk/src/ops/object.ops
   trunk/src/pmc/parrotobject.pmc
   trunk/t/pmc/object-meths.t

Log:
Allow overriding of a few more VTABLE methods in PIR, related to objects. Patch 
courtesy of Alek Storm <[EMAIL PROTECTED]>. RT #41364.

Modified: trunk/CREDITS
==============================================================================
--- trunk/CREDITS       (original)
+++ trunk/CREDITS       Thu Mar 15 16:09:32 2007
@@ -572,3 +572,7 @@
 N: Vishal Soni
 E: [EMAIL PROTECTED]
 D: Bug fixes in IMCC, ECMAScript
+
+N: Alek Storm
+E: [EMAIL PROTECTED]
+D: Fixed object vtable method overrides in PIR

Modified: trunk/src/ops/object.ops
==============================================================================
--- trunk/src/ops/object.ops    (original)
+++ trunk/src/ops/object.ops    Thu Mar 15 16:09:32 2007
@@ -54,13 +54,13 @@
   object = $1;
   meth = $2;
   next = expr NEXT();
-  interp->current_object = object;
-  interp->current_cont = NEED_CONTINUATION;
   method_pmc = VTABLE_find_method(interp, object, meth);
   if (!method_pmc) {
     real_exception(interp, next, METH_NOT_FOUND,
         "Method '%Ss' not found", meth);
   }
+  interp->current_object = object;
+  interp->current_cont = NEED_CONTINUATION;
   dest = (opcode_t *)VTABLE_invoke(interp, method_pmc, next);
   goto ADDRESS(dest);
 }
@@ -90,13 +90,13 @@
   object = $1;
   meth = $2;
   next = expr NEXT();
-  interp->current_object = object;
-  interp->current_cont = $3;
   method_pmc = VTABLE_find_method(interp, object, meth);
   if (!method_pmc) {
     real_exception(interp, next, METH_NOT_FOUND,
         "Method '%Ss' not found", meth);
   }
+  interp->current_object = object;
+  interp->current_cont = $3;
   dest = (opcode_t *)VTABLE_invoke(interp, method_pmc, next);
   goto ADDRESS(dest);
 }
@@ -124,14 +124,14 @@
 
   object = $1;
   meth = $2;
-  interp->current_cont = CONTEXT(interp->ctx)->current_cont;
-  PObj_get_FLAGS(interp->current_cont) |= SUB_FLAG_TAILCALL;
-  interp->current_object = object;
   method_pmc = VTABLE_find_method(interp, object, meth);
   if (!method_pmc) {
     real_exception(interp, next, METH_NOT_FOUND,
         "Method '%Ss' not found", meth);
   }
+  interp->current_cont = CONTEXT(interp->ctx)->current_cont;
+  PObj_get_FLAGS(interp->current_cont) |= SUB_FLAG_TAILCALL;
+  interp->current_object = object;
   dest = (opcode_t *)VTABLE_invoke(interp, method_pmc, next);
   goto ADDRESS(dest);
 }

Modified: trunk/src/pmc/parrotobject.pmc
==============================================================================
--- trunk/src/pmc/parrotobject.pmc      (original)
+++ trunk/src/pmc/parrotobject.pmc      Thu Mar 15 16:09:32 2007
@@ -164,39 +164,90 @@
 
     PMC* find_method(STRING* name) {
         PMC *class = VTABLE_get_class(INTERP, SELF);
-        return VTABLE_find_method(INTERP, class, name);
+        STRING *meth = CONST_STRING(interp, "__find_method");
+        STRING *meth_v = CONST_STRING(interp, "find_method");
+        PMC *sub = Parrot_find_vtable_meth(interp, SELF, meth_v);
+        if (PMC_IS_NULL(sub))
+            sub = find_meth(interp, SELF, meth);
+        if (PMC_IS_NULL(sub))
+            return VTABLE_find_method(INTERP, class, name);
+        return (PMC*) Parrot_run_meth_fromc_args(interp, sub,
+            SELF, meth, "PS", name);
     }
 
     PMC* get_attr(INTVAL idx) {
-        return Parrot_get_attrib_by_num(INTERP, SELF, idx);
+        STRING *meth = CONST_STRING(interp, "__get_attr");
+        STRING *meth_v = CONST_STRING(interp, "get_attr");
+        PMC *sub = Parrot_find_vtable_meth(interp, SELF, meth_v);
+        if (PMC_IS_NULL(sub))
+            sub = find_meth(interp, SELF, meth);
+        if (PMC_IS_NULL(sub))
+            return Parrot_get_attrib_by_num(INTERP, SELF, idx);
+        return (PMC*) Parrot_run_meth_fromc_args(interp, sub,
+            SELF, meth, "PI", idx);
     }
 
     PMC* get_attr_str(STRING* idx) {
-        return Parrot_get_attrib_by_str(INTERP, SELF, idx);
+        STRING *meth = CONST_STRING(interp, "__get_attr_str");
+        STRING *meth_v = CONST_STRING(interp, "get_attr_str");
+        PMC *sub = Parrot_find_vtable_meth(interp, SELF, meth_v);
+        PMC* r;
+        if (PMC_IS_NULL(sub))
+            sub = find_meth(interp, SELF, meth);
+        if (PMC_IS_NULL(sub))
+            r = Parrot_get_attrib_by_str(INTERP, SELF, idx);
+        else r = (PMC*) Parrot_run_meth_fromc_args(interp, sub,
+            SELF, meth, "PS", idx);
+        return r;
     }
 
     void set_attr(INTVAL idx, PMC* value) {
-        Parrot_set_attrib_by_num(INTERP, SELF, idx, value);
+        STRING *meth = CONST_STRING(interp, "__set_attr");
+        STRING *meth_v = CONST_STRING(interp, "set_attr");
+        PMC *sub = Parrot_find_vtable_meth(interp, SELF, meth_v);
+        if (PMC_IS_NULL(sub))
+            sub = find_meth(interp, SELF, meth);
+        if (PMC_IS_NULL(sub))
+            return Parrot_set_attrib_by_num(INTERP, SELF, idx, value);
+        (PMC*) Parrot_run_meth_fromc_args(interp, sub,
+            SELF, meth, "vIP", idx, value);
     }
 
     void set_attr_str(STRING* idx, PMC* value) {
-        Parrot_set_attrib_by_str(INTERP, SELF, idx, value);
+        STRING *meth = CONST_STRING(interp, "__set_attr_str");
+        STRING *meth_v = CONST_STRING(interp, "set_attr_str");
+        PMC *sub = Parrot_find_vtable_meth(interp, SELF, meth_v);
+        if (PMC_IS_NULL(sub))
+            sub = find_meth(interp, SELF, meth);
+        if (PMC_IS_NULL(sub))
+            return Parrot_set_attrib_by_str(INTERP, SELF, idx, value);
+        (PMC*) Parrot_run_meth_fromc_args(interp, sub,
+            SELF, meth, "vSP", idx, value);
     }
 
     PMC* get_class() {
-        if (!PObj_is_PMC_shared_TEST(SELF)) {
-            return GET_CLASS(PMC_data(SELF), SELF);
-        }
-        else {
-            /* get the class object for this interpreter */
-            /* XXX this is rather a hack, it is, however, necessary:
-             * otherwise we will be accessing the wrong interpreter's
-             * namespace
-             */
-            int type_num = SELF->vtable->base_type;
-
-            return INTERP->vtables[type_num]->class;
-        }
+        STRING *meth = CONST_STRING(interp, "__get_class");
+        STRING *meth_v = CONST_STRING(interp, "get_class");
+        PMC *sub = Parrot_find_vtable_meth(interp, SELF, meth_v);
+        if (PMC_IS_NULL(sub))
+            sub = find_meth(interp, SELF, meth);
+        if (PMC_IS_NULL(sub)) {
+            if (!PObj_is_PMC_shared_TEST(SELF)) {
+                return GET_CLASS(PMC_data(SELF), SELF);
+            }
+            else {
+                /* get the class object for this interpreter */
+                /* XXX this is rather a hack, it is, however, necessary:
+                 * otherwise we will be accessing the wrong interpreter's
+                 * namespace
+                 */
+                int type_num = SELF->vtable->base_type;
+ 
+                return INTERP->vtables[type_num]->class;
+            }
+         }
+        return (PMC*) Parrot_run_meth_fromc_args(interp, sub,
+            SELF, meth, "P");
     }
 
 /*

Modified: trunk/t/pmc/object-meths.t
==============================================================================
--- trunk/t/pmc/object-meths.t  (original)
+++ trunk/t/pmc/object-meths.t  Thu Mar 15 16:09:32 2007
@@ -6,7 +6,7 @@
 use warnings;
 use lib qw( . lib ../lib ../../lib );
 use Test::More;
-use Parrot::Test tests => 40;
+use Parrot::Test tests => 43;
 
 =head1 NAME
 
@@ -1325,6 +1325,91 @@
 init_pmc was called
 OUTPUT
 
+
+pir_output_is( <<'CODE', <<'OUTPUT', "overloading find_method vtable" );
+.sub main :main
+    .local pmc cl, o
+    cl = newclass 'MyClass'
+    o = new 'MyClass'
+    o.'foo'()
+.end
+
+.namespace ['MyClass']
+
+.sub find_method :method :vtable
+    .param string methodname
+    print "find_method was called\n"
+    $P0 = find_global "MyClass", methodname
+    .return($P0)
+.end
+
+.sub foo
+  print "foo was called\n"
+.end
+
+CODE
+find_method was called
+foo was called
+OUTPUT
+
+pir_output_is( <<'CODE', <<'OUTPUT', "overloading attribute accessor vtable" );
+.sub main :main
+    .local pmc cl, o
+    cl = newclass 'MyClass'
+    o = new 'MyClass'
+    $P2 = new String
+    $P2 = "blue"
+    setattribute o, 0, $P2
+    setattribute o, "blue", $P2
+    $P1 = getattribute o, 0
+    $P1 = getattribute o, "blue"
+.end
+
+.namespace ['MyClass']
+
+.sub get_attr :method :vtable
+    .param int offset
+    print "get_attr was called\n"
+.end
+.sub get_attr_str :method :vtable
+    .param string attrname
+    print "get_attr_str was called\n"
+.end
+.sub set_attr :method :vtable
+    .param int offset
+    .param pmc val
+    print "set_attr was called\n"
+.end
+.sub set_attr_str :method :vtable
+    .param string attrname
+    .param pmc val
+    print "set_attr_str was called\n"
+.end
+CODE
+set_attr was called
+set_attr_str was called
+get_attr was called
+get_attr_str was called
+OUTPUT
+
+pir_output_is( <<'CODE', <<'OUTPUT', "overloading get_class vtable" );
+.sub main :main
+    .local pmc cl, o, cl2
+    cl = newclass 'MyClass'
+    o = new 'MyClass'
+    cl2 = class o
+.end
+
+.namespace ['MyClass']
+
+.sub get_class :method :vtable
+    print "get_class was called\n"
+.end
+
+CODE
+get_class was called
+OUTPUT
+
 # Local Variables:
 #   mode: cperl
 #   cperl-indent-level: 4

Reply via email to