Author: leo
Date: Fri Apr 15 02:20:26 2005
New Revision: 7837

Modified:
   trunk/classes/bigint.pmc
   trunk/classes/complex.pmc
   trunk/classes/float.pmc
   trunk/classes/integer.pmc
   trunk/classes/perlint.pmc
   trunk/classes/perlstring.pmc
   trunk/classes/perlundef.pmc
   trunk/classes/scalar.pmc
   trunk/classes/string.pmc
   trunk/dynclasses/foo.pmc
   trunk/dynclasses/matchrange.pmc
   trunk/dynclasses/pyint.pmc
   trunk/dynclasses/tclfloat.pmc
   trunk/dynclasses/tclint.pmc
   trunk/dynclasses/tclstring.pmc
   trunk/imcc/parser_util.c
   trunk/include/parrot/mmd.h
   trunk/ops/experimental.ops
   trunk/src/call_list.txt
   trunk/src/mmd.c
   trunk/t/dynclass/foo.t
   trunk/t/dynclass/pycomplex.t
   trunk/t/dynclass/pyint.t
   trunk/t/pmc/complex.t
   trunk/vtable.tbl
Log:
MMD 23 - convert subtract MMD functions and opcodes

* see note on p6i


Modified: trunk/classes/bigint.pmc
==============================================================================
--- trunk/classes/bigint.pmc    (original)
+++ trunk/classes/bigint.pmc    Fri Apr 15 02:20:26 2005
@@ -115,7 +115,6 @@
 static void
 bigint_sub_bigint(Interp *interpreter, PMC* self, PMC *value, PMC *dest)
 {
-    VTABLE_morph(interpreter, dest, enum_class_BigInt);
     mpz_sub(BN(dest), BN(self), BN(value));
 }
 
@@ -123,7 +122,6 @@
 bigint_sub_bigint_int(Interp *interpreter, PMC* self, INTVAL value,
         PMC *dest)
 {
-    VTABLE_morph(interpreter, dest, enum_class_BigInt);
     mpz_sub_ui(BN(dest), BN(self), (long)value);
 }
 static void
@@ -521,16 +519,16 @@
 
 /*
 
-=item C<BIGNUM* get_bignum()>
+=item C<PMC* get_bignum()>
 
-Returns the BIGNUM.
+Returns SELF
 
 =cut
 
 */
 
-    BIGNUM* get_bignum() {
-        return bigint_get_self(INTERP, SELF);
+    PMC* get_bignum() {
+        return SELF;
     }
 
 /*
@@ -623,24 +621,60 @@
              }
     }
 
-    void subtract(PMC* value, PMC* dest) {
+    PMC* subtract(PMC* value, PMC* dest) {
 MMD_BigInt: {
+                if (dest)
+                    VTABLE_morph(interpreter, dest, SELF->vtable->base_type);
+                else
+                    dest = pmc_new(INTERP, SELF->vtable->base_type);
                 bigint_sub_bigint(INTERP, SELF, value, dest);
+                return dest;
             }
 MMD_Integer: {
+                if (dest)
+                    VTABLE_morph(interpreter, dest, SELF->vtable->base_type);
+                else
+                    dest = pmc_new(INTERP, SELF->vtable->base_type);
                 bigint_sub_bigint_int(INTERP, SELF, PMC_int_val(value), dest);
+                return dest;
             }
 MMD_DEFAULT: {
-                 internal_exception(1, "unimp sub");
+                internal_exception(1, "unimp sub");
+                return dest;
              }
     }
 
-    void add_int(INTVAL value, PMC* dest) {
-        bigint_add_bigint_int(INTERP, SELF, value, dest);
+    PMC* subtract_int(INTVAL value, PMC* dest) {
+        if (dest)
+            VTABLE_morph(interpreter, dest, SELF->vtable->base_type);
+        else
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        bigint_sub_bigint_int(INTERP, SELF, value, dest);
+        return dest;
     }
 
-    void subtract_int(INTVAL value, PMC* dest) {
-        bigint_sub_bigint_int(INTERP, SELF, value, dest);
+    void i_subtract (PMC* value) {
+MMD_BigInt: {
+                bigint_sub_bigint(INTERP, SELF, value, SELF);
+            }
+MMD_Integer: {
+                bigint_sub_bigint_int(INTERP, SELF, PMC_int_val(value), SELF);
+             }
+MMD_DEFAULT: {
+                internal_exception(1, "unimp sub");
+             }
+    }
+
+    void i_subtract_int (INTVAL value) {
+        bigint_sub_bigint_int(INTERP, SELF, value, SELF);
+    }
+
+    void i_subtract_float (FLOATVAL value) {
+        internal_exception(1, "unimp sub");
+    }
+
+    void add_int(INTVAL value, PMC* dest) {
+        bigint_add_bigint_int(INTERP, SELF, value, dest);
     }
 
 

Modified: trunk/classes/complex.pmc
==============================================================================
--- trunk/classes/complex.pmc   (original)
+++ trunk/classes/complex.pmc   Fri Apr 15 02:20:26 2005
@@ -610,11 +610,11 @@
 
 /*
 
-=item C<void subtract (PMC* value, PMC* dest)>
+=item C<PMC* subtract (PMC* value, PMC* dest)>
 
-=item C<void subtract_int (INTVAL value, PMC* dest)>
+=item C<PMC* subtract_int (INTVAL value, PMC* dest)>
 
-=item C<void subtract_float (FLOATVAL value, PMC* dest)>
+=item C<PMC* subtract_float (FLOATVAL value, PMC* dest)>
 
 Subtracts C<value> from the complex number, placing the result in C<dest>.
 
@@ -622,31 +622,67 @@
 
 */
 
-    void subtract (PMC* value, PMC* dest) {
+    PMC* subtract (PMC* value, PMC* dest) {
 MMD_Complex: {
-        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        if (dest)
+            VTABLE_morph(INTERP, dest, enum_class_Complex);
+        else {
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        }
         RE(dest) = RE(SELF) - RE(value);
         IM(dest) = IM(SELF) - IM(value);
-        }
+        return dest;
+    }
 MMD_DEFAULT: {
-        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        if (dest)
+            VTABLE_morph(INTERP, dest, enum_class_Complex);
+        else {
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        }
         RE(dest) = RE(SELF) - VTABLE_get_number(INTERP, value);
         IM(dest) = IM(SELF);
-        }
+        return dest;
+    }
     }
 
-    void subtract_int (INTVAL value, PMC* dest) {
-        VTABLE_morph(INTERP, dest, enum_class_Complex);
+    PMC* subtract_int (INTVAL value, PMC* dest) {
+        if (dest)
+            VTABLE_morph(INTERP, dest, enum_class_Complex);
+        else {
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        }
         RE(dest) = RE(SELF) - value;
         IM(dest) = IM(SELF);
+        return dest;
     }
 
-    void subtract_float (FLOATVAL value, PMC* dest) {
-        VTABLE_morph(INTERP, dest, enum_class_Complex);
+    PMC* subtract_float (FLOATVAL value, PMC* dest) {
+        if (dest)
+            VTABLE_morph(INTERP, dest, enum_class_Complex);
+        else {
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        }
         RE(dest) = RE(SELF) - value;
         IM(dest) = IM(SELF);
+        return dest;
     }
 
+    void i_subtract (PMC* value) {
+MMD_Complex: {
+            RE(SELF) -= RE(value);
+            IM(SELF) -= IM(value);
+        }
+MMD_DEFAULT: {
+            RE(SELF) -= VTABLE_get_number(INTERP, value);
+        }
+    }
+
+    void i_subtract_int (INTVAL value) {
+        RE(SELF) -= (FLOATVAL)value;
+    }
+    void i_subtract_float (FLOATVAL value) {
+        RE(SELF) -= value;
+    }
 /*
 
 =item C<void multiply (PMC* value, PMC* dest)>

Modified: trunk/classes/float.pmc
==============================================================================
--- trunk/classes/float.pmc     (original)
+++ trunk/classes/float.pmc     Fri Apr 15 02:20:26 2005
@@ -279,52 +279,88 @@
 
 /*
 
-=item C<void subtract(PMC *value, PMC *dest)>
+=item C<PMC* subtract(PMC *value, PMC *dest)>
 
-Subtracts C<*value> from the number and returns the result in C<*dest>.
+=item C<PMC* subtract_int(INTVAL value, PMC *dest)>
 
-=cut
+=item C<PMC* subtract_float(FLOATVAL value, PMC *dest)>
 
-*/
+Subtracts C<value> from the number and returns the result in C<*dest>.
+If C<dest> doesn't exist a new C<Float> is created.
 
-    void subtract (PMC* value, PMC* dest) {
-MMD_Float: {
-        VTABLE_set_number_native(INTERP, dest,
-            PMC_num_val(SELF) - PMC_num_val(value));
-        }
-MMD_DEFAULT: {
-        VTABLE_set_number_native(INTERP, dest,
-            PMC_num_val(SELF) - VTABLE_get_number(INTERP, value));
-        }
-    }
+=item C<void i_subtract(PMC *value)>
 
-/*
+=item C<void i_subtract_int(INTVAL value)>
 
-=item C<void subtract_int(INTVAL value, PMC *dest)>
+=item C<void i_subtract_float(FLOATVAL value)>
 
-Subtracts C<value> from the number and returns the result in C<*dest>.
+Subtracts C<value> from C<SELF> inplace.
 
 =cut
 
 */
 
-    void subtract_int (INTVAL value, PMC* dest) {
-        VTABLE_set_number_native(INTERP, dest,
-            PMC_num_val(SELF) - (FLOATVAL)value);
+    PMC* subtract (PMC* value, PMC* dest) {
+MMD_Complex: {
+            FLOATVAL a = DYNSELF.get_number();
+            if (dest)
+                VTABLE_morph(INTERP, dest, value->vtable->base_type);
+            else
+                dest = pmc_new(INTERP, value->vtable->base_type);
+            VTABLE_set_number_native(INTERP, dest,
+                    a - VTABLE_get_number_keyed_int(INTERP, value, 0));
+            VTABLE_set_number_keyed_int(INTERP, dest, 1,
+                    -VTABLE_get_number_keyed_int(INTERP, value, 1));
+            return dest;
+        }
+MMD_DEFAULT: {
+            if (!dest)
+                dest = pmc_new(INTERP, SELF->vtable->base_type);
+            VTABLE_set_number_native(INTERP, dest,
+                    DYNSELF.get_number() - VTABLE_get_number(INTERP, value));
+            return dest;
+        }
     }
-/*
 
-=item C<void subtract_float(FLOATVAL value, PMC *dest)>
+    PMC* subtract_int (INTVAL value, PMC* dest) {
+        if (!dest)
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        VTABLE_set_number_native(INTERP, dest,
+                DYNSELF.get_number() - (FLOATVAL)value);
+        return dest;
+    }
 
-Subtracts C<value> from the number and returns the result in C<*dest>.
+    PMC* subtract_float (FLOATVAL value, PMC* dest) {
+        if (!dest)
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        VTABLE_set_number_native(INTERP, dest,
+                DYNSELF.get_number() - value);
+        return dest;
+    }
 
-=cut
+    void i_subtract (PMC* value) {
+MMD_Complex: {
+            FLOATVAL a = DYNSELF.get_number();
+            VTABLE_morph(INTERP, SELF, value->vtable->base_type);
+            VTABLE_set_number_native(INTERP, SELF,
+                    a - VTABLE_get_number_keyed_int(INTERP, value, 0));
+            VTABLE_set_number_keyed_int(INTERP, SELF, 1,
+                    -VTABLE_get_number_keyed_int(INTERP, value, 1));
+        }
+MMD_DEFAULT: {
+            VTABLE_set_number_native(INTERP, SELF,
+                DYNSELF.get_number() - VTABLE_get_number(INTERP, value));
+        }
+    }
 
-*/
+    void i_subtract_int (INTVAL value) {
+        VTABLE_set_number_native(INTERP, SELF,
+            DYNSELF.get_number() - (FLOATVAL)value);
+    }
 
-    void subtract_float (FLOATVAL value, PMC* dest) {
-        VTABLE_set_number_native(INTERP, dest,
-            PMC_num_val(SELF) - value);
+    void i_subtract_float (FLOATVAL value) {
+        VTABLE_set_number_native(INTERP, SELF,
+            DYNSELF.get_number() - value);
     }
 
 /*

Modified: trunk/classes/integer.pmc
==============================================================================
--- trunk/classes/integer.pmc   (original)
+++ trunk/classes/integer.pmc   Fri Apr 15 02:20:26 2005
@@ -28,7 +28,7 @@
 extern void Parrot_BigInt_multiply_int(Interp* interpreter,
         PMC* pmc, INTVAL value, PMC* dest) ;
 
-static void
+static PMC*
 overflow(Interp *interpreter, PMC *self, INTVAL b, PMC *dest, int mmd)
 {
     PMC *temp;
@@ -42,16 +42,15 @@
         /* TODO preserve type system */
         VTABLE_morph(interpreter, self, enum_class_BigInt);
         VTABLE_set_integer_native(interpreter, self, a);
-        mmd_dispatch_v_pip(interpreter, self, b, dest, mmd);
+        return mmd_dispatch_p_pip(interpreter, self, b, dest, mmd);
     }
     else {
-        temp = pmc_new(interpreter, enum_class_BigInt);
-        VTABLE_set_integer_native(interpreter, temp, a);
-        mmd_dispatch_v_pip(interpreter, temp, b, dest, mmd);
+        temp = VTABLE_get_bignum(interpreter, self);
+        return mmd_dispatch_p_pip(interpreter, temp, b, dest, mmd);
     }
 }
 
-static void
+static PMC*
 overflow_p(Interp *interpreter, PMC *self, PMC *val, PMC *dest, int mmd)
 {
     PMC *temp;
@@ -64,12 +63,11 @@
     if (self == dest) {
         VTABLE_morph(interpreter, self, enum_class_BigInt);
         VTABLE_set_integer_native(interpreter, self, a);
-        mmd_dispatch_v_ppp(interpreter, self, val, dest, mmd);
+        return mmd_dispatch_p_ppp(interpreter, self, val, dest, mmd);
     }
     else {
-        temp = pmc_new(interpreter, enum_class_BigInt);
-        VTABLE_set_integer_native(interpreter, temp, a);
-        mmd_dispatch_v_ppp(interpreter, temp, val, dest, mmd);
+        temp = VTABLE_get_bignum(interpreter, self);
+        return mmd_dispatch_p_ppp(interpreter, temp, val, dest, mmd);
     }
 }
 
@@ -195,16 +193,18 @@
 
 /*
 
-=item C<BIGNUM *get_bignum()>
+=item C<PMC *get_bignum()>
 
-Unimplemented. Returns C<NULL>.
+Return a new BigInt PMC with the value of C<SELF>.
 
 =cut
 
 */
-    BIGNUM* get_bignum () {
-        /* XXX */
-        return NULL;
+    PMC* get_bignum () {
+        INTVAL val = DYNSELF.get_integer();
+        PMC *ret = pmc_new(INTERP, enum_class_BigInt);
+        VTABLE_set_integer_native(INTERP, ret, val);
+        return ret;
     }
 
 /*
@@ -254,7 +254,7 @@
     }
 /*
 
-=item C<void set_pmc(PMC *value)>
+=item C<void assign_pmc(PMC *value)>
 
 Sets the PMC C<*value>, calling the appropriate C<set_*> method
 according to the type of C<*value>.
@@ -263,7 +263,9 @@
 
 */
 
-    void set_pmc (PMC* value) {
+    void assign_pmc (PMC* value) {
+        if (SELF == value)
+            return;
         DYNSELF.morph(value->vtable->base_type);
         switch (value->vtable->base_type) {
             case enum_class_Integer:
@@ -279,7 +281,7 @@
                 (void) VTABLE_get_pmc(INTERP, value);
                 break;
             default:
-                DYNSELF.set_pmc(value);
+                SUPER(value);
                 break;
         }
     }
@@ -303,25 +305,24 @@
     }
 
 
+
 /*
 
-=item C<void set_number(PMC *value)>
+=item C<void set_number_native(FLOATVAL value)>
 
-Morphs the integer to a C<Float> and sets the value from C<*value>.
+Morphs the integer to a C<Float> and sets the value from C<value>.
 
-=cut
+=item C<void set_bool(INTVAL value)>
 
-*/
-    void set_number (PMC* value) {
-        DYNSELF.morph(enum_class_Float);
-        DYNSELF.set_number(value);
-    }
+Morphs the integer to a C<Boolean> and sets the value from C<value>.
 
-/*
+=item C<void set_bigint_int(INTVAL value)>
 
-=item C<void set_number_native(FLOATVAL value)>
+Morphs the integer to a C<BigInt> and sets the value from C<value>.
 
-Morphs the integer to a C<Float> and sets the value from C<value>.
+=item C<void set_string_native(STRING *value)>
+
+Morphs the integer to a C<String> and sets the value from C<value>.
 
 =cut
 
@@ -331,63 +332,16 @@
         DYNSELF.set_number_native(value);
     }
 
-/*
-
-=item C<void set_bignum(PMC *value)>
-
-=cut
-
-*/
-    void set_bignum (PMC* value) {
-        DYNSELF.morph(enum_class_BigInt);
-        DYNSELF.set_bignum(value);
-    }
-
-/*
-
-=item C<void set_bool(INTVAL value)>
-
-=cut
-
-*/
     void set_bool (INTVAL value) {
         DYNSELF.morph(enum_class_Boolean);
         DYNSELF.set_bool(value);
     }
 
-/*
-
-=item C<void set_bignum_native(BIGNUM *value)>
-
-=cut
-
-*/
-    void set_bignum_native (BIGNUM* value) {
+    void set_bignum_int (INTVAL value) {
         DYNSELF.morph(enum_class_BigInt);
-        DYNSELF.set_bignum_native(value);
-    }
-
-/*
-
-=item C<void set_string (PMC *value)>
-
-=cut
-
-*/
-    void set_string (PMC* value) {
-        DYNSELF.morph(enum_class_tring);
-        DYNSELF.set_string(value);
+        DYNSELF.set_integer_native(value);
     }
 
-/*
-
-=item C<void set_string_native(STRING *value)>
-
-Sets the value of the integer to C<*value>.
-
-=cut
-
-*/
     void set_string_native (STRING* value) {
         DYNSELF.morph(enum_class_String);
         DYNSELF.set_string_native(value);
@@ -428,12 +382,9 @@
          * so we can't used PMC_int_val(SELF) in any of these
          * Integer methods
          *
-         * TODO one of
-         *   a) remember MMD distance of this call
-         *      (works only for dynamic dispatch)
-         *   b) check for exact Integer type
-         *   c) create MMD_Any_Integer MMD
-         *   d) or dispatch to MMD_DEFAULT
+         * TODO
+         *   check for exact Integer type
+         *   e.g. MMD_Integer_EXACT
          */
 
         INTVAL a = VTABLE_get_integer(INTERP, SELF);
@@ -478,71 +429,123 @@
 
 /*
 
-=item C<void subtract(PMC *value, PMC *dest)>
+=item C<PMC* subtract(PMC *value, PMC *dest)>
 
 Subtracts C<*value> from the integer and returns the result in C<*dest>.
+If C<dest> is NULL, a new int PMC is created.
+
+Please note: as C<SELF> or C<value> maybe be subclassed, we have to
+call C<get_integer> and C<set_integer_native> always.
 
 =cut
 
 */
-    void subtract (PMC* value, PMC* dest) {
+    PMC* subtract (PMC* value, PMC* dest) {
 MMD_Integer: {
-        INTVAL a = PMC_int_val(SELF);
-        INTVAL b = PMC_int_val(value);
-        INTVAL c = a - b;
-        if ((c^a) >= 0 || (c^~b) >= 0)
-            VTABLE_set_integer_native(INTERP, dest, c);
-        else
-            overflow(INTERP, SELF, b, dest, MMD_SUBTRACT);
-    }
+            INTVAL a = DYNSELF.get_integer();
+            INTVAL b = VTABLE_get_integer(INTERP, value);
+            INTVAL c = a - b;
+            if ((c^a) >= 0 || (c^~b) >= 0) {
+                if (!dest)
+                    dest = pmc_new(INTERP, SELF->vtable->base_type);
+                VTABLE_set_integer_native(INTERP, dest, c);
+                return dest;
+            }
+            else
+                return overflow(INTERP, SELF, b, dest, MMD_SUBTRACT);
+        }
 MMD_Complex: {
-        if (dest != SELF) {
-            VTABLE_morph(INTERP, dest, enum_class_Complex);
+            INTVAL a = DYNSELF.get_integer();
+            if (dest)
+                VTABLE_morph(INTERP, dest, value->vtable->base_type);
+            else
+                dest = pmc_new(INTERP, value->vtable->base_type);
             VTABLE_set_number_native(INTERP, dest,
-                    PMC_int_val(SELF) -
-                    VTABLE_get_number_keyed_int(INTERP, value, 0));
+                    a - VTABLE_get_number_keyed_int(INTERP, value, 0));
             VTABLE_set_number_keyed_int(INTERP, dest, 1,
-                    VTABLE_get_number_keyed_int(INTERP, value, 1));
-
+                    -VTABLE_get_number_keyed_int(INTERP, value, 1));
+            return dest;
         }
-        else {
-            internal_exception(1, "Complex: unimp sub self");
-        }
-    }
 MMD_BigInt: {
-            overflow_p(INTERP, SELF, value, dest, MMD_SUBTRACT);
-        }
-MMD_PerlUndef: {
-        Parrot_warn(INTERP, PARROT_WARNINGS_UNDEF_FLAG,
-            "Use of uninitialized value in integer context");
-        VTABLE_set_integer_native(INTERP, dest, PMC_int_val(SELF));
-        }
-MMD_Float: {
-        VTABLE_set_number_native(INTERP, dest,
-            PMC_int_val(SELF) - PMC_num_val(value));
+            return overflow_p(INTERP, SELF, value, dest, MMD_SUBTRACT);
         }
 MMD_DEFAULT: {
-        VTABLE_set_number_native(INTERP, dest,
-            PMC_int_val(SELF) - VTABLE_get_number(INTERP, value));
+            if (!dest)
+                dest = pmc_new(INTERP, value->vtable->base_type);
+            VTABLE_set_number_native(INTERP, dest,
+                DYNSELF.get_integer() - VTABLE_get_number(INTERP, value));
+            return dest;
         }
     }
 
 /*
 
-=item C<void subtract_int(INTVAL value, PMC *dest)>
+=item C<PMC* subtract_int(INTVAL value, PMC *dest)>
 
 Subtracts C<value> from the integer and returns the result in C<*dest>.
 
 =cut
 
 */
-    void subtract_int (INTVAL b, PMC* dest) {
-        INTVAL a = PMC_int_val(SELF);
+    PMC* subtract_int (INTVAL b, PMC* dest) {
+        INTVAL a = DYNSELF.get_integer();
         INTVAL c = a - b;
-        if ((c^a) >= 0 || (c^~b) >= 0)
+        if ((c^a) >= 0 || (c^~b) >= 0) {
+            if (!dest)
+                dest = pmc_new(INTERP, SELF->vtable->base_type);
             VTABLE_set_integer_native(INTERP, dest, c);
+            return dest;
+        }
         else
-            overflow(INTERP, SELF, b, dest, MMD_SUBTRACT);
+            return overflow(INTERP, SELF, b, dest, MMD_SUBTRACT);
+    }
+
+/*
+
+=item C<void i_subtract(PMC *value)>
+
+=item C<void i_subtract_int(INTVAL value)>
+
+=item C<void i_subtract_float(FLOATVAL value)>
+
+Subtracts C<value> from C<SELF> inplace.
+
+=cut
+
+*/
+
+    void i_subtract (PMC* value) {
+MMD_Integer: {
+            SELF.i_subtract_int(VTABLE_get_integer(INTERP, value));
+        }
+MMD_Complex: {
+            INTVAL a = DYNSELF.get_integer();
+            VTABLE_morph(INTERP, SELF, value->vtable->base_type);
+            VTABLE_set_number_native(INTERP, SELF,
+                    (FLOATVAL)a -
+                    VTABLE_get_number_keyed_int(INTERP, value, 0));
+            VTABLE_set_number_keyed_int(INTERP, SELF, 1,
+                    -VTABLE_get_number_keyed_int(INTERP, value, 1));
+        }
+MMD_DEFAULT: {
+        VTABLE_set_number_native(INTERP, SELF,
+            PMC_int_val(SELF) - VTABLE_get_number(INTERP, value));
+        }
+    }
+
+    void i_subtract_int (INTVAL b) {
+        INTVAL a = DYNSELF.get_integer();
+        INTVAL c = a - b;
+        if ((c^a) >= 0 || (c^~b) >= 0) {
+            VTABLE_set_integer_native(INTERP, SELF, c);
+        }
+        else
+            overflow(INTERP, SELF, b, SELF, MMD_SUBTRACT);
+    }
+
+    void i_subtract_float (FLOATVAL value) {
+        INTVAL a = DYNSELF.get_integer();
+        VTABLE_set_number_native(INTERP, SELF, a - value);
     }
 
 /*

Modified: trunk/classes/perlint.pmc
==============================================================================
--- trunk/classes/perlint.pmc   (original)
+++ trunk/classes/perlint.pmc   Fri Apr 15 02:20:26 2005
@@ -43,20 +43,6 @@
 
 /*
 
-=item C<void set_number(PMC *value)>
-
-Morphs the integer to a C<PerlNum> and sets the value from C<*value>.
-
-=cut
-
-*/
-    void set_number (PMC* value) {
-        DYNSELF.morph(enum_class_PerlNum);
-        DYNSELF.set_number(value);
-    }
-
-/*
-
 =item C<void set_number_native(FLOATVAL value)>
 
 Morphs the integer to a C<PerlNum> and sets the value from C<value>.
@@ -69,41 +55,6 @@
         DYNSELF.set_number_native(value);
     }
 
-/*
-
-=item C<void set_bignum(PMC *value)>
-
-=cut
-
-*/
-    void set_bignum (PMC* value) {
-        DYNSELF.morph(enum_class_BigInt);
-        DYNSELF.set_bignum(value);
-    }
-
-/*
-
-=item C<void set_bignum_native(BIGNUM *value)>
-
-=cut
-
-*/
-    void set_bignum_native (BIGNUM* value) {
-        DYNSELF.morph(enum_class_BigInt);
-        DYNSELF.set_bignum_native(value);
-    }
-
-/*
-
-=item C<void set_string (PMC *value)>
-
-=cut
-
-*/
-    void set_string (PMC* value) {
-        DYNSELF.morph(enum_class_PerlString);
-        DYNSELF.set_string(value);
-    }
 
 /*
 

Modified: trunk/classes/perlstring.pmc
==============================================================================
--- trunk/classes/perlstring.pmc        (original)
+++ trunk/classes/perlstring.pmc        Fri Apr 15 02:20:26 2005
@@ -151,7 +151,7 @@
 
 /*
 
-=item C<void subtract(PMC *value, PMC *dest)>
+=item C<PMC* subtract(PMC *value, PMC *dest)>
 
 Subtracts C<*value> from the string and returns the result in C<*dest>.
 
@@ -159,18 +159,20 @@
 
 */
 
-    void subtract (PMC* value, PMC* dest) {
+    PMC* subtract (PMC* value, PMC* dest) {
 MMD_PerlString: {
             /* work around MMD setup bug */
             VTABLE_set_number_native(INTERP, dest,
                     VTABLE_get_number(INTERP, SELF) -
                     VTABLE_get_number(INTERP, value));
+            return dest;        /* XXX */
         }
 MMD_PerlNum: {
             VTABLE_set_number_native(INTERP, dest,
                     VTABLE_get_number(INTERP, SELF) -
                     PMC_num_val(value)
                     );
+            return dest;        /* XXX */
         }
 MMD_DEFAULT: {
             FLOATVAL pmcf, valf;
@@ -185,6 +187,7 @@
                 VTABLE_set_integer_native(INTERP, dest, pmci - vali);
             else
                 VTABLE_set_number_native(INTERP, dest, pmcf - valf);
+            return dest;        /* XXX */
         }
     }
 

Modified: trunk/classes/perlundef.pmc
==============================================================================
--- trunk/classes/perlundef.pmc (original)
+++ trunk/classes/perlundef.pmc Fri Apr 15 02:20:26 2005
@@ -210,45 +210,47 @@
 
 /*
 
-=item C<void subtract(PMC *value,  PMC *dest)>
+=item C<PMC* subtract(PMC *value,  PMC *dest)>
 
 =cut
 
 */
 
-    void subtract (PMC* value,  PMC* dest) {
+    PMC* subtract (PMC* value,  PMC* dest) {
         Parrot_warn(INTERP, PARROT_WARNINGS_UNDEF_FLAG,
         "Use of uninitialized value in subtraction");
-        SUPER(value, dest);
+        return SUPER(value, dest);
     }
 
 /*
 
-=item C<void subtract_int(INTVAL value,  PMC *dest)>
+=item C<PMC* subtract_int(INTVAL value,  PMC *dest)>
 
 =cut
 
 */
 
-    void subtract_int (INTVAL value,  PMC* dest) {
+    PMC* subtract_int (INTVAL value,  PMC* dest) {
         Parrot_warn(INTERP, PARROT_WARNINGS_UNDEF_FLAG,
         "Use of uninitialized value in integer subtraction");
         VTABLE_set_integer_native(INTERP, dest, 0-value);
+        return dest;    /* XXX */
     }
 
 
 /*
 
-=item C<void subtract_float(FLOATVAL value, PMC *dest)>
+=item C<PMC* subtract_float(FLOATVAL value, PMC *dest)>
 
 =cut
 
 */
 
-    void subtract_float (FLOATVAL value,  PMC* dest) {
+    PMC* subtract_float (FLOATVAL value,  PMC* dest) {
         Parrot_warn(INTERP, PARROT_WARNINGS_UNDEF_FLAG,
         "Use of uninitialized value in numeric subtraction");
         VTABLE_set_number_native(INTERP, dest, 0-value);
+        return dest;    /* XXX */
     }
 
 /*

Modified: trunk/classes/scalar.pmc
==============================================================================
--- trunk/classes/scalar.pmc    (original)
+++ trunk/classes/scalar.pmc    Fri Apr 15 02:20:26 2005
@@ -68,19 +68,6 @@
         return PMC_num_val(SELF);
     }
 
-/*
-
-=item C<BIGNUM *get_bignum()>
-
-Returns the big number value of the scalar.
-
-=cut
-
-*/
-
-    BIGNUM* get_bignum () {
-        return (BIGNUM*) PMC_struct_val(SELF);
-    }
 
 /*
 
@@ -147,19 +134,6 @@
         PMC_num_val(SELF) = value;
     }
 
-/*
-
-=item C<void set_bignum_native(BIGNUM *value)>
-
-Sets the big number value.
-
-=cut
-
-*/
-
-    void set_bignum_native (BIGNUM* value) {
-        PMC_struct_val(SELF) = (DPOINTER*)value;
-    }
 
 /*
 
@@ -222,24 +196,27 @@
 
 /*
 
-=item C<void subtract(PMC *value, PMC *dest)>
+=item C<PMC* subtract(PMC *value, PMC *dest)>
 
 =cut
 
 */
 
-    void subtract (PMC* value,  PMC* dest) {
+    PMC* subtract (PMC* value,  PMC* dest) {
         FLOATVAL result;
 
         result = DYNSELF.get_number()
             - VTABLE_get_number(INTERP, value);
 
+        if (!dest)
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
         VTABLE_set_number_native(INTERP, dest, result);
+        return dest;
     }
 
 /*
 
-=item C<void subtract_int(INTVAL value, PMC *dest)>
+=item C<PMC* subtract_int(INTVAL value, PMC *dest)>
 
 Subtracts C<value> from the scalar and returns the result in C<*dest>.
 
@@ -249,19 +226,22 @@
 
 */
 
-    void subtract_int (INTVAL value,  PMC* dest) {
+    PMC* subtract_int (INTVAL value,  PMC* dest) {
         FLOATVAL result;
 
         result = DYNSELF.get_number()
             - value;
 
+        if (!dest)
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
         VTABLE_set_number_native(INTERP, dest, result);
+        return dest;
     }
 
 
 /*
 
-=item C<void subtract_float (FLOATVAL value,  PMC* dest)>
+=item C<PMC* subtract_float (FLOATVAL value,  PMC* dest)>
 
 Subtracts C<value> from the scalar and returns the result in C<*dest>.
 
@@ -271,13 +251,16 @@
 
 */
 
-    void subtract_float (FLOATVAL value,  PMC* dest) {
+    PMC* subtract_float (FLOATVAL value,  PMC* dest) {
         FLOATVAL result;
 
         result = DYNSELF.get_number()
             - value;
 
+        if (!dest)
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
         VTABLE_set_number_native(INTERP, dest, result);
+        return dest;
     }
 
 /*

Modified: trunk/classes/string.pmc
==============================================================================
--- trunk/classes/string.pmc    (original)
+++ trunk/classes/string.pmc    Fri Apr 15 02:20:26 2005
@@ -123,18 +123,19 @@
 
 /*
 
-=item C<BIGNUM* get_bignum()>
+=item C<PMC* get_bignum()>
 
 Returns the big numbers representation of the string.
-(unimplemented, returns NULL)
 
 =cut
 
 */
 
-    BIGNUM* get_bignum () {
-        /* XXX */
-        return (BIGNUM*)0;
+    PMC* get_bignum () {
+       STRING *s = DYNSELF.get_string();
+        PMC *ret = pmc_new(INTERP, enum_class_BigInt);
+        VTABLE_set_string_native(INTERP, ret, s);
+        return ret;
     }
 
 /*
@@ -194,20 +195,6 @@
         PMC_str_val(SELF) = string_from_num(INTERP, value);
     }
 
-/*
-
-=item C<VOID set_bignum_native(BIGNUM* value)>
-
-Sets the value of the string to the big number C<value>.
-(unimplemented, no-op)
-
-=cut
-
-*/
-
-    void set_bignum_native (BIGNUM* value) {
-        /* XXX */
-    }
 
 /*
 

Modified: trunk/dynclasses/foo.pmc
==============================================================================
--- trunk/dynclasses/foo.pmc    (original)
+++ trunk/dynclasses/foo.pmc    Fri Apr 15 02:20:26 2005
@@ -11,12 +11,18 @@
        return 42;
     }
 
-    void subtract (PMC* value, PMC* dest) {
+    PMC* subtract (PMC* value, PMC* dest) {
 MMD_Integer: {
+       if (!dest)
+           dest = pmc_new(INTERP, SELF->vtable->base_type);
        VTABLE_set_integer_native(INTERP, dest, 144);
+       return dest;
        }
 MMD_DEFAULT: {
+       if (!dest)
+           dest = pmc_new(INTERP, SELF->vtable->base_type);
        VTABLE_set_integer_native(INTERP, dest, 244);
+       return dest;
        }
     }
 }

Modified: trunk/dynclasses/matchrange.pmc
==============================================================================
--- trunk/dynclasses/matchrange.pmc     (original)
+++ trunk/dynclasses/matchrange.pmc     Fri Apr 15 02:20:26 2005
@@ -375,11 +375,11 @@
 
 /*
 
-=item C<void subtract (PMC* value, PMC* dest)>
+=item C<PMC* subtract (PMC* value, PMC* dest)>
 
-=item C<void subtract_int (INTVAL value, PMC* dest)>
+=item C<PMC* subtract_int (INTVAL value, PMC* dest)>
 
-=item C<void subtract_float (FLOATVAL value, PMC* dest)>
+=item C<PMC* subtract_float (FLOATVAL value, PMC* dest)>
 
 Subtracts C<value> from the ending offset of the match range, placing
 the result in C<dest>.
@@ -388,20 +388,24 @@
 
 */
 
-    void subtract (PMC* value, PMC* dest) {
+    PMC* subtract (PMC* value, PMC* dest) {
         INTVAL v = VTABLE_get_integer(INTERP, dest);
-        SELF.subtract_int(v, dest);
+        return SELF.subtract_int(v, dest);
     }
 
-    void subtract_int (INTVAL value, PMC* dest) {
-        VTABLE_morph(INTERP, dest, MatchRange_type_id);
+    PMC* subtract_int (INTVAL value, PMC* dest) {
+        if (dest)
+            VTABLE_morph(INTERP, dest, MatchRange_type_id);
+        else
+            dest = pmc_new(INTERP,  MatchRange_type_id);
         RANGE_END(dest) = RANGE_END(SELF) - value;
         if (RANGE_END(dest) <= -2 || RANGE_END(dest) < RANGE_START(dest) - 1)
             RANGE_END(dest) = -2;
+        return dest;
     }
 
-    void subtract_float (FLOATVAL value, PMC* dest) {
-        SELF.subtract_int((INTVAL) value, dest);
+    PMC* subtract_float (FLOATVAL value, PMC* dest) {
+        return SELF.subtract_int((INTVAL) value, dest);
     }
 
 /*

Modified: trunk/dynclasses/pyint.pmc
==============================================================================
--- trunk/dynclasses/pyint.pmc  (original)
+++ trunk/dynclasses/pyint.pmc  Fri Apr 15 02:20:26 2005
@@ -49,10 +49,25 @@
     mmd_dispatch_v_ppp(interpreter, temp, b, dest, mmd);
 }
 
-pmclass PyInt extends PyObject dynpmc group python_group {
+pmclass PyInt extends PyObject extends Integer dynpmc group python_group {
 
 /*
 
+=item C<PMC *get_bignum()>
+
+Return a new PyLong PMC with the value of C<SELF>.
+
+=cut
+
+*/
+    PMC* get_bignum () {
+        INTVAL val = DYNSELF.get_integer();
+        PMC *ret = pmc_new(INTERP, PyBuiltin_PyLong);
+        VTABLE_set_integer_native(INTERP, ret, val);
+        return ret;
+    }
+/*
+
 =item C<PMC* clone()>
 
 Return a clone of the integer.
@@ -958,46 +973,6 @@
     }
 
 /*
-
-=item C<void subtract(PMC *value, PMC *dest)>
-
-Subtracts C<*value> from the integer and returns the result in C<*dest>.
-
-=cut
-
-*/
-
-    void subtract (PMC* value, PMC* dest) {
-MMD_PyInt: {
-            INTVAL pmci = PMC_int_val(SELF);
-            INTVAL vali = VTABLE_get_integer(INTERP, value);
-            VTABLE_set_integer_native(INTERP, dest, pmci - vali);
-        }
-MMD_PyFloat: {
-            INTVAL pmci = PMC_int_val(SELF);
-            FLOATVAL valf = VTABLE_get_number(INTERP, value);
-            /* XXX: Morph? */
-            VTABLE_set_number_native(INTERP, dest, pmci - valf);
-        }
-    }
-
-/*
-
-=item C<void subtract_int(INTVAL value, PMC *dest)>
-
-Subtracts C<value> from the integer and returns the result in C<*dest>.
-
-=cut
-
-*/
-
-    void subtract_int (INTVAL value, PMC* dest) {
-        VTABLE_set_integer_native(INTERP, dest,
-            PMC_int_val(SELF) - value
-        );
-    }
-
-/*
 
 =back
 

Modified: trunk/dynclasses/tclfloat.pmc
==============================================================================
--- trunk/dynclasses/tclfloat.pmc       (original)
+++ trunk/dynclasses/tclfloat.pmc       Fri Apr 15 02:20:26 2005
@@ -23,7 +23,7 @@
 
 
 
-pmclass TclFloat extends TclObject dynpmc group tcl_group {
+pmclass TclFloat extends TclObject extend Float dynpmc group tcl_group {
 
     void init () {
         PMC_num_val(SELF) = 0.0;
@@ -33,11 +33,6 @@
         return (INTVAL)PMC_num_val(SELF);
     }
 
-    BIGNUM* get_bignum () {
-        /* XXX */
-        return NULL;
-    }
-
 
     STRING* get_string () {
         char* buff = mem_sys_allocate(80);
@@ -51,7 +46,7 @@
         sprintf(buff,FLOATVAL_FMT,PMC_num_val(SELF));  /* XXX buffer overflow! 
*/
 #endif
         check_flag = 1;
-        checklen = buflen = strlen(buff); 
+        checklen = buflen = strlen(buff);
         while (check_flag && buflen) {
                if (buff[buflen-1] == 48) {  /* 0 */
                        buflen--;
@@ -91,14 +86,6 @@
         PMC_num_val(SELF) = PMC_num_val(value);
     }
 
-    void set_bignum_native (BIGNUM* value) {
-      /* XXX */
-    }
-
-    void set_bignum_same (PMC* value) {
-      /* XXX */
-    }
-
     void set_string_native (STRING * value) {
         DYNSELF.morph(TclString_type);
         DYNSELF.set_string_native(value);
@@ -125,28 +112,6 @@
             PMC_num_val(SELF) + value);
     }
 
-    void subtract (PMC* value, PMC* dest) {
-        VTABLE_set_number_native(INTERP, dest,
-            PMC_num_val(SELF) -
-            VTABLE_get_number(INTERP, value)
-        );
-    }
-
-    void subtract_int (INTVAL value, PMC* dest) {
-        VTABLE_set_number_native(INTERP, dest,
-            PMC_num_val(SELF) - (FLOATVAL)value
-        );
-    }
-
-    void subtract_bignum (BIGNUM* value, PMC* dest) {
-        /* XXX */
-    }
-
-    void subtract_float (FLOATVAL value, PMC* dest) {
-        VTABLE_set_number_native(INTERP, dest,
-            PMC_num_val(SELF) - value);
-    }
-
     void multiply (PMC* value, PMC* dest) {
         VTABLE_set_number_native(INTERP, dest,
             PMC_num_val(SELF) *

Modified: trunk/dynclasses/tclint.pmc
==============================================================================
--- trunk/dynclasses/tclint.pmc (original)
+++ trunk/dynclasses/tclint.pmc Fri Apr 15 02:20:26 2005
@@ -17,7 +17,7 @@
 static INTVAL dynclass_TclFloat;
 static INTVAL dynclass_TclInt;
 
-pmclass TclInt extends TclObject dynpmc group tcl_group {
+pmclass TclInt extends TclObject extends Integer dynpmc group tcl_group {
 
     void class_init() {
       if (pass) {
@@ -49,14 +49,10 @@
         return (FLOATVAL)PMC_int_val(SELF);
     }
 
-    BIGNUM* get_bignum () {
-        /* XXX */
-        return NULL;
-    }
 
     INTVAL get_bool() {
       return (PMC_int_val(SELF))?1:0;
-    } 
+    }
 
     STRING* get_string () {
         return string_from_int(INTERP, PMC_int_val(SELF));
@@ -76,16 +72,6 @@
         DYNSELF.set_number_native(value);
     }
 
-    void set_bignum (PMC* value) {
-       /* XXX */
-        PMC_struct_val(SELF) = (DPOINTER*)VTABLE_get_bignum(INTERP, value);
-    }
-
-    void set_bignum_native (BIGNUM* value) {
-        /* XXX */
-        PMC_struct_val(SELF) = value; /* Maybe we need a copy */
-    }
-
     void set_string (PMC* value) {
         DYNSELF.morph(dynclass_TclString);
         DYNSELF.set_string(value);
@@ -124,41 +110,6 @@
         }
     }
 
-    void subtract (PMC* value, PMC* dest) {
-        INTVAL pmci;
-        int vtype = VTABLE_type(INTERP, value);
-        FLOATVAL valf;
-        FLOATVAL diff;
-
-        pmci = PMC_int_val(SELF);
-        valf = VTABLE_get_number(INTERP, value);
-        diff = pmci - valf;
-
-        if (vtype == dynclass_TclFloat) {
-            VTABLE_set_number_native(INTERP, dest, diff);
-            return;
-        }
-
-        {
-            INTVAL vali = (INTVAL) valf;
-            INTVAL   difi = pmci - vali;
-            if (diff == difi)
-                VTABLE_set_integer_native(INTERP, dest, difi);
-            else {
-                /* TODO BIG* promotion */
-                VTABLE_set_number_native(INTERP, dest, diff);
-            }
-            return;
-
-        }
-    }
-
-    void subtract_int (INTVAL value, PMC* dest) {
-        VTABLE_set_integer_native(INTERP, dest,
-            PMC_int_val(SELF) - value
-        );
-    }
-
     void multiply (PMC* value, PMC* dest) {
         INTVAL pmci;
         int vtype = VTABLE_type(INTERP, value);

Modified: trunk/dynclasses/tclstring.pmc
==============================================================================
--- trunk/dynclasses/tclstring.pmc      (original)
+++ trunk/dynclasses/tclstring.pmc      Fri Apr 15 02:20:26 2005
@@ -68,13 +68,9 @@
         return string_to_num(INTERP, s);
     }
 
-    BIGNUM* get_bignum () {
-       /* XXX */
-        return NULL;
-    }
 
     INTVAL get_bool () {
- 
+
         STRING* s = (STRING*) PMC_str_val(SELF);
         if (!string_compare(INTERP,s,true)) {
           return 1;

Modified: trunk/imcc/parser_util.c
==============================================================================
--- trunk/imcc/parser_util.c    (original)
+++ trunk/imcc/parser_util.c    Fri Apr 15 02:20:26 2005
@@ -329,6 +329,35 @@
         || Parrot_is_builtin(interpreter, name, NULL) >= 0;
 }
 
+/* sub x, y, z  => infix .MMD_SUBTRACT, x, y, z */
+static char *
+to_infix(Interp *interpreter, char *name, SymReg **r, int *n)
+{
+    SymReg *mmd;
+    char buf[10];
+
+    assert(*n >= 2);
+    if (r[0]->set != 'P')
+        return name;
+    if (*n == 3 && r[0] == r[1]) {       /* cvt to inplace */
+        sprintf(buf, "%d", MMD_I_SUBTRACT);  /* XXX */
+        mmd = mk_const(interpreter, str_dup(buf), 'I');
+    }
+    else {
+        int i;
+        for (i = *n; i > 0; --i)
+            r[i] = r[i - 1];
+        if (*n == 2)
+            sprintf(buf, "%d", MMD_I_SUBTRACT);  /* XXX */
+        else
+            sprintf(buf, "%d", MMD_SUBTRACT);  /* XXX */
+        mmd = mk_const(interpreter, str_dup(buf), 'I');
+        (*n)++;
+    }
+    r[0] = mmd;
+    return "infix";
+}
+
 /* make a instruction
  * name ... op name
  * fmt ... optional format
@@ -352,6 +381,12 @@
     char format[128];
     int len;
 
+    if (strcmp(name, "sub") == 0) {     /* XXX is_infix */
+        /* sub x, y, z  => infix .MMD_SUBTRACT, x, y, z */
+        name = to_infix(interpreter, name, r, &n);
+    }
+
+
 #if 1
     ins = multi_keyed(interpreter, unit, name, r, n, keyvec, emit);
     if (ins)

Modified: trunk/include/parrot/mmd.h
==============================================================================
--- trunk/include/parrot/mmd.h  (original)
+++ trunk/include/parrot/mmd.h  Fri Apr 15 02:20:26 2005
@@ -18,6 +18,16 @@
 void mmd_dispatch_v_pnp(Parrot_Interp, PMC *, FLOATVAL, PMC *, INTVAL);
 void mmd_dispatch_v_psp(Parrot_Interp, PMC *, STRING *, PMC *, INTVAL);
 
+void mmd_dispatch_v_pp(Parrot_Interp, PMC *, PMC *, INTVAL);
+void mmd_dispatch_v_pi(Parrot_Interp, PMC *, INTVAL, INTVAL);
+void mmd_dispatch_v_pn(Parrot_Interp, PMC *, FLOATVAL, INTVAL);
+void mmd_dispatch_v_ps(Parrot_Interp, PMC *, STRING *, INTVAL);
+
+PMC* mmd_dispatch_p_ppp(Parrot_Interp, PMC *, PMC *, PMC *, INTVAL);
+PMC* mmd_dispatch_p_pip(Parrot_Interp, PMC *, INTVAL, PMC *, INTVAL);
+PMC* mmd_dispatch_p_pnp(Parrot_Interp, PMC *, FLOATVAL, PMC *, INTVAL);
+PMC* mmd_dispatch_p_psp(Parrot_Interp, PMC *, STRING *, PMC *, INTVAL);
+
 INTVAL mmd_dispatch_i_pp(Parrot_Interp, PMC *, PMC *, INTVAL);
 void mmd_add_by_class(Parrot_Interp, INTVAL, STRING *, STRING *, funcptr_t);
 void mmd_register(Parrot_Interp, INTVAL, INTVAL, INTVAL, funcptr_t);

Modified: trunk/ops/experimental.ops
==============================================================================
--- trunk/ops/experimental.ops  (original)
+++ trunk/ops/experimental.ops  Fri Apr 15 02:20:26 2005
@@ -246,6 +246,68 @@
   goto NEXT();
 }
 
+=item C<infix(inconst INT, in PMC, in INT)>
+
+=item C<infix(inconst INT, in PMC, in NUM)>
+
+=item C<infix(inconst INT, in PMC, in STR)>
+
+=item C<infix(inconst INT, in PMC, in PMC)>
+
+General inplace infix dispatch opcode. $1 is the MMD function number.
+
+=item C<infix(inconst INT, out PMC, in PMC, in INT)>
+
+=item C<infix(inconst INT, out PMC, in PMC, in NUM)>
+
+=item C<infix(inconst INT, out PMC, in PMC, in STR)>
+
+=item C<infix(inconst INT, out PMC, in PMC, in PMC)>
+
+General infix dispatch opcode. $1 is the MMD function number.
+
+=cut
+
+inline op infix(inconst INT, in PMC, in INT) :base_core {
+  mmd_dispatch_v_pi(interpreter, $2, $3, $1);
+  goto NEXT();
+}
+
+inline op infix(inconst INT, in PMC, in NUM) :base_core {
+  mmd_dispatch_v_pn(interpreter, $2, $3, $1);
+  goto NEXT();
+}
+
+inline op infix(inconst INT, in PMC, in STR) :base_core {
+  mmd_dispatch_v_ps(interpreter, $2, $3, $1);
+  goto NEXT();
+}
+
+inline op infix(inconst INT, in PMC, in PMC) :base_core {
+  mmd_dispatch_v_pp(interpreter, $2, $3, $1);
+  goto NEXT();
+}
+
+inline op infix(inconst INT, out PMC, in PMC, in INT) :base_core {
+  $2 = mmd_dispatch_p_pip(interpreter, $3, $4, $2, $1);
+  goto NEXT();
+}
+
+inline op infix(inconst INT, out PMC, in PMC, in NUM) :base_core {
+  $2 = mmd_dispatch_p_pnp(interpreter, $3, $4, $2, $1);
+  goto NEXT();
+}
+
+inline op infix(inconst INT, out PMC, in PMC, in STR) :base_core {
+  $2 = mmd_dispatch_p_psp(interpreter, $3, $4, $2, $1);
+  goto NEXT();
+}
+
+inline op infix(inconst INT, out PMC, in PMC, in PMC) :base_core {
+  $2 = mmd_dispatch_p_ppp(interpreter, $3, $4, $2, $1);
+  goto NEXT();
+}
+
 =back
 
 ###############################################################################

Modified: trunk/src/call_list.txt
==============================================================================
--- trunk/src/call_list.txt     (original)
+++ trunk/src/call_list.txt     Fri Apr 15 02:20:26 2005
@@ -63,6 +63,17 @@
 v      JPIP
 v      JPSP
 v      JPNP
+
+v      JPP      # inplace infix MMD
+v      JPI
+v      JPS
+v      JPN
+
+P      JPPP     # infix MMD new
+P      JPIP
+P      JPSP
+P      JPNP
+
 I      JPP      # MMD compare
 
 f                # t/pmc/nci.t
@@ -213,7 +224,6 @@
 # Py_func signatures
 P      JP
 P      JPP
-P      JPPP
 P      JO
 S      JO
 i       P

Modified: trunk/src/mmd.c
==============================================================================
--- trunk/src/mmd.c     (original)
+++ trunk/src/mmd.c     Fri Apr 15 02:20:26 2005
@@ -51,6 +51,17 @@
 typedef void    (*mmd_f_v_pip)(Interp *, PMC *, INTVAL, PMC *);
 typedef void    (*mmd_f_v_pnp)(Interp *, PMC *, FLOATVAL, PMC *);
 typedef void    (*mmd_f_v_psp)(Interp *, PMC *, STRING *, PMC *);
+
+typedef PMC*    (*mmd_f_p_ppp)(Interp *, PMC *, PMC *, PMC *);
+typedef PMC*    (*mmd_f_p_pip)(Interp *, PMC *, INTVAL, PMC *);
+typedef PMC*    (*mmd_f_p_pnp)(Interp *, PMC *, FLOATVAL, PMC *);
+typedef PMC*    (*mmd_f_p_psp)(Interp *, PMC *, STRING *, PMC *);
+
+typedef void    (*mmd_f_v_pp)(Interp *, PMC *, PMC *);
+typedef void    (*mmd_f_v_pi)(Interp *, PMC *, INTVAL);
+typedef void    (*mmd_f_v_pn)(Interp *, PMC *, FLOATVAL);
+typedef void    (*mmd_f_v_ps)(Interp *, PMC *, STRING *);
+
 typedef INTVAL  (*mmd_f_i_pp) (Interp *, PMC *, PMC *);
 
 #ifndef NDEBUG
@@ -309,6 +320,182 @@
     }
 }
 
+/*
+ * return possibly new dstination
+ */
+PMC*
+mmd_dispatch_p_ppp(Interp *interpreter,
+                PMC *left, PMC *right, PMC *dest, INTVAL function)
+{
+    mmd_f_p_ppp real_function;
+    PMC *sub;
+    int is_pmc;
+
+    real_function = (mmd_f_p_ppp)get_mmd_dispatcher(interpreter,
+            left, right, function, &is_pmc);
+
+    if (is_pmc) {
+        sub = (PMC*)real_function;
+        return Parrot_runops_fromc_args(interpreter, sub, "PPPP",
+                left, right, dest);
+    }
+    else {
+        return (*real_function)(interpreter, left, right, dest);
+    }
+}
+
+PMC*
+mmd_dispatch_p_pip(Interp *interpreter,
+                PMC *left, INTVAL right, PMC *dest, INTVAL function)
+{
+    mmd_f_p_pip real_function;
+    PMC *sub;
+    int is_pmc;
+    UINTVAL left_type;
+
+    left_type = left->vtable->base_type;
+    real_function = (mmd_f_p_pip)get_mmd_dispatch_type(interpreter,
+            function, left_type, enum_type_INTVAL, &is_pmc);
+    if (is_pmc) {
+        sub = (PMC*)real_function;
+        return Parrot_runops_fromc_args(interpreter, sub, "PPIP",
+                left, right, dest);
+    }
+    else {
+        return (*real_function)(interpreter, left, right, dest);
+    }
+}
+
+PMC*
+mmd_dispatch_p_pnp(Interp *interpreter,
+                PMC *left, FLOATVAL right, PMC *dest, INTVAL function)
+{
+    mmd_f_p_pnp real_function;
+    PMC *sub;
+    int is_pmc;
+    UINTVAL left_type;
+
+    left_type = left->vtable->base_type;
+    real_function = (mmd_f_p_pnp)get_mmd_dispatch_type(interpreter,
+            function, left_type, enum_type_FLOATVAL, &is_pmc);
+    if (is_pmc) {
+        sub = (PMC*)real_function;
+        return Parrot_runops_fromc_args(interpreter, sub, "PPNP",
+                left, right, dest);
+    }
+    else {
+        return (*real_function)(interpreter, left, right, dest);
+    }
+}
+
+PMC*
+mmd_dispatch_p_psp(Interp *interpreter,
+                PMC *left, STRING *right, PMC *dest, INTVAL function)
+{
+    mmd_f_p_psp real_function;
+    PMC *sub;
+    int is_pmc;
+    UINTVAL left_type;
+
+    left_type = left->vtable->base_type;
+    real_function = (mmd_f_p_psp)get_mmd_dispatch_type(interpreter,
+            function, left_type, enum_type_STRING, &is_pmc);
+    if (is_pmc) {
+        sub = (PMC*)real_function;
+        return Parrot_runops_fromc_args(interpreter, sub, "PPSP",
+                left, right, dest);
+    }
+    else {
+        return (*real_function)(interpreter, left, right, dest);
+    }
+}
+
+/*
+ * inplace variants
+ */
+void
+mmd_dispatch_v_pp(Interp *interpreter,
+                PMC *left, PMC *right, INTVAL function)
+{
+    mmd_f_v_pp real_function;
+    PMC *sub;
+    int is_pmc;
+
+    real_function = (mmd_f_v_pp)get_mmd_dispatcher(interpreter,
+            left, right, function, &is_pmc);
+
+    if (is_pmc) {
+        sub = (PMC*)real_function;
+        Parrot_runops_fromc_args(interpreter, sub, "vPP", left, right);
+    }
+    else {
+        (*real_function)(interpreter, left, right);
+    }
+}
+
+void
+mmd_dispatch_v_pi(Interp *interpreter,
+                PMC *left, INTVAL right, INTVAL function)
+{
+    mmd_f_v_pi real_function;
+    PMC *sub;
+    int is_pmc;
+    UINTVAL left_type;
+
+    left_type = left->vtable->base_type;
+    real_function = (mmd_f_v_pi)get_mmd_dispatch_type(interpreter,
+            function, left_type, enum_type_INTVAL, &is_pmc);
+    if (is_pmc) {
+        sub = (PMC*)real_function;
+        Parrot_runops_fromc_args(interpreter, sub, "vPI", left, right);
+    }
+    else {
+        (*real_function)(interpreter, left, right);
+    }
+}
+
+void
+mmd_dispatch_v_pn(Interp *interpreter,
+                PMC *left, FLOATVAL right, INTVAL function)
+{
+    mmd_f_v_pn real_function;
+    PMC *sub;
+    int is_pmc;
+    UINTVAL left_type;
+
+    left_type = left->vtable->base_type;
+    real_function = (mmd_f_v_pn)get_mmd_dispatch_type(interpreter,
+            function, left_type, enum_type_FLOATVAL, &is_pmc);
+    if (is_pmc) {
+        sub = (PMC*)real_function;
+        Parrot_runops_fromc_args(interpreter, sub, "vPN", left, right);
+    }
+    else {
+        (*real_function)(interpreter, left, right);
+    }
+}
+
+void
+mmd_dispatch_v_ps(Interp *interpreter,
+                PMC *left, STRING *right, INTVAL function)
+{
+    mmd_f_v_ps real_function;
+    PMC *sub;
+    int is_pmc;
+    UINTVAL left_type;
+
+    left_type = left->vtable->base_type;
+    real_function = (mmd_f_v_ps)get_mmd_dispatch_type(interpreter,
+            function, left_type, enum_type_STRING, &is_pmc);
+    if (is_pmc) {
+        sub = (PMC*)real_function;
+        Parrot_runops_fromc_args(interpreter, sub, "vPS", left, right);
+    }
+    else {
+        (*real_function)(interpreter, left, right);
+    }
+}
+
 /*
 
 =item C<INTVAL

Modified: trunk/t/dynclass/foo.t
==============================================================================
--- trunk/t/dynclass/foo.t      (original)
+++ trunk/t/dynclass/foo.t      Fri Apr 15 02:20:26 2005
@@ -42,7 +42,7 @@
     $P0 = loadlib "foo"
     print "ok\n"
     l = new "Foo"
-    l = 3
+    l = 42
     r = new BigInt
     r = 0x7ffffff
     d = new Undef
@@ -55,7 +55,7 @@
 .end
 CODE
 ok
-134217730
+134217769
 BigInt
 OUTPUT
 

Modified: trunk/t/dynclass/pycomplex.t
==============================================================================
--- trunk/t/dynclass/pycomplex.t        (original)
+++ trunk/t/dynclass/pycomplex.t        Fri Apr 15 02:20:26 2005
@@ -17,7 +17,7 @@
 
 =cut
 
-use Parrot::Test tests => 1;
+use Parrot::Test tests => 2;
 
 pir_output_is(<< 'CODE', << 'OUTPUT', "eq");
 
@@ -36,3 +36,32 @@
 CODE
 1
 OUTPUT
+
+pir_output_is(<< 'CODE', << 'OUTPUT', "sub");
+.sub main @MAIN
+    .local pmc d, i, c
+    d = new "PyObject"
+    i = new "PyInt"
+    c = new "PyComplex"
+    i = 2
+    c = "5+2j"
+    d = c - i
+    print d
+    print "\n"
+    typeof $S0, d
+    print $S0
+    print "\n"
+    d = i - c
+    print d
+    print "\n"
+    typeof $S0, d
+    print $S0
+    print "\n"
+.end
+CODE
+(3+2j)
+PyComplex
+(-3-2j)
+PyComplex
+OUTPUT
+

Modified: trunk/t/dynclass/pyint.t
==============================================================================
--- trunk/t/dynclass/pyint.t    (original)
+++ trunk/t/dynclass/pyint.t    Fri Apr 15 02:20:26 2005
@@ -16,7 +16,7 @@
 
 =cut
 
-use Parrot::Test tests => 25;
+use Parrot::Test tests => 26;
 
 pir_output_is(<< 'CODE', << 'OUTPUT', "abs");
 
@@ -471,7 +471,7 @@
 
     set $P0, 31
     set $P1, 2
-    set $P2, -1 
+    set $P2, -1
 
     new $P3, $I0
     $P3 = $P0 ** $P1
@@ -616,3 +616,34 @@
 CODE
 -20 -20 -20
 OUTPUT
+
+pir_output_like(<< 'CODE', << 'OUTPUT', "sub - propagate to PyLong");
+.sub main @MAIN
+    .include "sysinfo.pasm"
+    .local pmc d, l, r
+    .local int b, i
+    d = new "PyObject"
+    l = new "PyInt"
+    r = new "PyInt"
+    b = sysinfo .SYSINFO_PARROT_INTSIZE
+    b *= 8  # CHAR_BITS
+    dec b
+    i = 1 << b
+    dec i   # sys.maxint
+    print i
+    print "\n"
+    r = i
+    neg i
+    l = i
+    d = l - r
+    print d
+    print "\n"
+    typeof $S0, d
+    print $S0
+    print "\n"
+.end
+CODE
+/^\d+
+-\d+
+PyLong/
+OUTPUT

Modified: trunk/t/pmc/complex.t
==============================================================================
--- trunk/t/pmc/complex.t       (original)
+++ trunk/t/pmc/complex.t       Fri Apr 15 02:20:26 2005
@@ -16,7 +16,7 @@
 
 =cut
 
-use Parrot::Test tests => 24;
+use Parrot::Test tests => 26;
 use Test::More;
 
 my $fp_equality_macro = <<'ENDOFMACRO';
@@ -306,7 +306,7 @@
 2-2i
 1.8+1i
 -1024-3i
-1024-3i
+1024+3i
 OUTPUT
 
 output_is(<<'CODE', <<'OUTPUT', "multiply");
@@ -735,3 +735,53 @@
 ok 2
 ok 3
 OUTPUT
+
+pir_output_is(<< 'CODE', << 'OUTPUT', "sub");
+.sub main @MAIN
+    .local pmc d, f, c
+    d = new Undef
+    f = new Float
+    c = new Complex
+    f = 2.2
+    c = "5+2j"
+    d = c - f
+    print d
+    print "\n"
+    typeof $S0, d
+    print $S0
+    print "\n"
+    d = f - c
+    print d
+    print "\n"
+    typeof $S0, d
+    print $S0
+    print "\n"
+.end
+CODE
+2.8+2i
+Complex
+-2.8-2i
+Complex
+OUTPUT
+
+pir_output_is(<< 'CODE', << 'OUTPUT', "i_sub");
+.sub main @MAIN
+    .local pmc f, c
+    f = new Float
+    f = 2.2
+    c = new Complex
+    c = "5+2j"
+    c -= f
+    print c
+    print "\n"
+    c = new Complex
+    c = "5+2j"
+    f -= c
+    print f
+    print "\n"
+.end
+CODE
+2.8+2i
+-2.8-2i
+OUTPUT
+

Modified: trunk/vtable.tbl
==============================================================================
--- trunk/vtable.tbl    (original)
+++ trunk/vtable.tbl    Fri Apr 15 02:20:26 2005
@@ -48,7 +48,7 @@
 FLOATVAL get_number_keyed_int(INTVAL key)
 FLOATVAL get_number_keyed_str(STRING* key)
 
-BIGNUM* get_bignum()
+PMC* get_bignum()
 
 STRING* get_string()
 STRING* get_repr()
@@ -57,9 +57,6 @@
 STRING* get_string_keyed_str(STRING* key)
 
 INTVAL get_bool()
-INTVAL get_bool_keyed(PMC* key)
-INTVAL get_bool_keyed_int(INTVAL key)
-INTVAL get_bool_keyed_str(STRING* key)
 
 PMC* get_pmc()
 PMC* get_pmc_keyed(PMC* key)
@@ -85,8 +82,9 @@
 void set_number_keyed_int(INTVAL key, FLOATVAL value)
 void set_number_keyed_str(STRING* key, FLOATVAL value)
 
-void set_bignum_native(BIGNUM* value)
-void set_bignum_same(PMC* value)
+void set_bignum_int(INTVAL value)
+void set_bignum_num(FLOATVAL value)
+void set_bignum_str(STRING* value)
 
 void set_string_native(STRING* value)
 void assign_string_native(STRING* value)
@@ -96,9 +94,6 @@
 void set_string_keyed_str(STRING* key, STRING* value)
 
 void set_bool(INTVAL value)
-void set_bool_keyed(PMC* key, INTVAL value)
-void set_bool_keyed_int(INTVAL key, INTVAL value)
-void set_bool_keyed_str(STRING* key, INTVAL value)
 
 void set_pmc(PMC* value)
 void assign_pmc(PMC* value)
@@ -148,9 +143,15 @@
 void add_int(INTVAL value, PMC* dest)       MMD_ADD_INT
 void add_float(FLOATVAL value, PMC* dest)   MMD_ADD_FLOAT
 
-void subtract(PMC* value, PMC* dest)        MMD_SUBTRACT
-void subtract_int(INTVAL value, PMC* dest)  MMD_SUBTRACT_INT
-void subtract_float(FLOATVAL value, PMC* dest)  MMD_SUBTRACT_FLOAT
+# one for a test first
+PMC* subtract(PMC* value, PMC* dest)        MMD_SUBTRACT
+PMC* subtract_int(INTVAL value, PMC* dest)  MMD_SUBTRACT_INT
+PMC* subtract_float(FLOATVAL value, PMC* dest)  MMD_SUBTRACT_FLOAT
+
+# and inplace
+void i_subtract(PMC* value)                 MMD_I_SUBTRACT
+void i_subtract_int(INTVAL value)           MMD_I_SUBTRACT_INT
+void i_subtract_float(FLOATVAL value)       MMD_I_SUBTRACT_FLOAT
 
 void multiply(PMC* value, PMC* dest)        MMD_MULTIPLY
 void multiply_int(INTVAL value, PMC* dest)  MMD_MULTIPLY_INT

Reply via email to