cvsuser     03/09/11 04:19:25

  Modified:    classes  perlint.pmc
               languages/imcc optimizer.c
               .        math.ops
               t/pmc    perlint.t
  Log:
  PerlInt math: divide gives int if possible
  add documented but missing div_p_p op
  
  Revision  Changes    Path
  1.43      +95 -66    parrot/classes/perlint.pmc
  
  Index: perlint.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/classes/perlint.pmc,v
  retrieving revision 1.42
  retrieving revision 1.43
  diff -u -w -r1.42 -r1.43
  --- perlint.pmc       9 Sep 2003 10:25:35 -0000       1.42
  +++ perlint.pmc       11 Sep 2003 11:19:21 -0000      1.43
  @@ -1,7 +1,7 @@
   /* perlint.pmc
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: perlint.pmc,v 1.42 2003/09/09 10:25:35 leo Exp $
  + *     $Id: perlint.pmc,v 1.43 2003/09/11 11:19:21 leo Exp $
    *  Overview:
    *     These are the vtable functions for the PerlInt base class
    *  Data Structure and Algorithms:
  @@ -69,9 +69,6 @@
           DYNSELF.set_string_native(value);
       }
   
  -    /* XXX -lt: only add done yet, others will follow, when
  -     * vtable changes are carved in electrons
  -     */
       void add (PMC* value, PMC* dest) {
           INTVAL pmci;
        int vtype = VTABLE_type(INTERP, value);
  @@ -109,26 +106,35 @@
       }
   
       void subtract (PMC* value, PMC* dest) {
  -     int type = enum_class_PerlInt;
  -     INTVAL i;
  +        INTVAL pmci;
  +     int vtype = VTABLE_type(INTERP, value);
  +     FLOATVAL valf;
  +     FLOATVAL diff;
  +
  +     pmci = SELF->cache.int_val;
  +     if (vtype == enum_class_PerlUndef) {
  +            VTABLE_set_integer_native(INTERP, dest, pmci);
  +         return;
  +     }
  +
  +     valf = VTABLE_get_number(INTERP, value);
  +     diff = pmci - valf;
  +     if (vtype == enum_class_PerlNum) {
  +            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;
   
  -     if(value->vtable == &Parrot_base_vtables[enum_class_PerlNum]) {
  -         type = enum_class_PerlNum;
        }
  -     else if(value->vtable == &Parrot_base_vtables[enum_class_PerlString]) {
  -         FLOATVAL f = VTABLE_get_number(INTERP, value);
  -         i = VTABLE_get_integer(INTERP, value);
  -         if(f != i) {
  -             type = enum_class_PerlNum;
  -         }
  -     }
  -     i = SELF->cache.int_val;
  -     if(type == enum_class_PerlNum)
  -            VTABLE_set_number_native(INTERP, dest,
  -             i - VTABLE_get_number(INTERP, value));
  -     else
  -            VTABLE_set_integer_native(INTERP, dest,
  -             i - VTABLE_get_integer(INTERP, value));
       }
   
       void subtract_int (INTVAL value, PMC* dest) {
  @@ -142,26 +148,35 @@
       }
   
       void multiply (PMC* value, PMC* dest) {
  -     int type = enum_class_PerlInt;
  -     INTVAL i;
  +        INTVAL pmci;
  +     int vtype = VTABLE_type(INTERP, value);
  +     FLOATVAL valf;
  +     FLOATVAL mulf;
  +
  +     pmci = SELF->cache.int_val;
  +     if (vtype == enum_class_PerlUndef) {
  +            VTABLE_set_integer_native(INTERP, dest, pmci);
  +         return;
  +     }
  +
  +     valf = VTABLE_get_number(INTERP, value);
  +     mulf = pmci * valf;
  +     if (vtype == enum_class_PerlNum) {
  +            VTABLE_set_number_native(INTERP, dest, mulf);
  +         return;
  +     }
  +     {
  +         INTVAL vali = (INTVAL) valf;
  +         INTVAL   muli = pmci * vali;
  +         if (mulf == muli)
  +             VTABLE_set_integer_native(INTERP, dest, muli);
  +         else {
  +             /* TODO BIG* promotion */
  +             VTABLE_set_number_native(INTERP, dest, mulf);
  +         }
  +         return;
   
  -     if(value->vtable == &Parrot_base_vtables[enum_class_PerlNum]) {
  -         type = enum_class_PerlNum;
        }
  -     else if(value->vtable == &Parrot_base_vtables[enum_class_PerlString]) {
  -         FLOATVAL f = VTABLE_get_number(INTERP, value);
  -         i = VTABLE_get_integer(INTERP, value);
  -         if(f != i) {
  -             type = enum_class_PerlNum;
  -         }
  -     }
  -     i = SELF->cache.int_val;
  -     if(type == enum_class_PerlNum)
  -            VTABLE_set_number_native(INTERP, dest,
  -             i * VTABLE_get_number(INTERP, value));
  -     else
  -            VTABLE_set_integer_native(INTERP, dest,
  -             i * VTABLE_get_integer(INTERP, value));
       }
   
       void multiply_int (INTVAL value, PMC* dest) {
  @@ -175,45 +190,59 @@
       }
   
       void divide (PMC* value, PMC* dest) {
  -     VTABLE_set_number_native(INTERP, dest,
  -             SELF->cache.int_val / VTABLE_get_number(INTERP, value));
  +        INTVAL pmci;
  +     int vtype = VTABLE_type(INTERP, value);
  +     FLOATVAL valf;
  +     FLOATVAL divf;
  +
  +     pmci = SELF->cache.int_val;
  +     if (vtype == enum_class_PerlUndef) {
  +            VTABLE_set_integer_native(INTERP, dest, pmci);
  +         return;
  +     }
  +
  +     valf = VTABLE_get_number(INTERP, value);
  +     divf = pmci / valf;
  +     if (vtype == enum_class_PerlNum) {
  +            VTABLE_set_number_native(INTERP, dest, divf);
  +         return;
  +     }
  +     {
  +         INTVAL vali = (INTVAL) valf;
  +         INTVAL   divi = pmci / vali;
  +         /* if result is an integer or zero yield an integer */
  +         if (divf == divi || !pmci)
  +             VTABLE_set_integer_native(INTERP, dest, divi);
  +         else {
  +             /* TODO BIG* promotion */
  +             VTABLE_set_number_native(INTERP, dest, divf);
  +         }
  +         return;
  +
  +     }
       }
   
       void divide_int (INTVAL value, PMC* dest) {
  -        VTABLE_set_number_native(INTERP, dest,
  -            (FLOATVAL)SELF->cache.int_val / value
  -        );
  +     INTVAL pmci, divi;
  +     FLOATVAL valf, divf;
  +
  +     pmci = SELF->cache.int_val;
  +     /* TODO exception */
  +     divf = (FLOATVAL)pmci / value;
  +     divi = pmci / value;
  +     if (divf == divi || !pmci)
  +         VTABLE_set_integer_native(INTERP, dest, divi);
  +     else {
  +         /* TODO BIG* promotion */
  +         VTABLE_set_number_native(INTERP, dest, divf);
  +     }
       }
   
       void divide_same (PMC* value, PMC* dest) {
  -        dest->cache.int_val = SELF->cache.int_val / value->cache.int_val;
  +        SELF.divide_int(value->cache.int_val, dest);
       }
   
       void cmodulus (PMC* value, PMC* dest) {
  -        INTVAL i;
  -        FLOATVAL f;
  -     /*
  -      * XXX:leo shouldn't that just call get_integer on value
  -      *     and proceed?
  -      */
  -        switch(VTABLE_type(INTERP, value)) {
  -            case enum_class_PerlNum:
  -                internal_exception(INVALID_OPERATION,
  -                 "modulus() not implemented for mix of INTs and FLOATs\n");
  -                break;
  -            case enum_class_PerlString:
  -                /* Is the string an integer or a number? */
  -                f = VTABLE_get_number(INTERP, value);
  -                i = VTABLE_get_integer(INTERP, value);
  -                if(f != i) {
  -                    internal_exception(INVALID_OPERATION,
  -                     "modulus() not implemented for mix of INTs and FLOATs\n");
  -                }
  -                break;
  -        }
  -        /* If we're here, then we can assume that get_integer will return
  -         *  something sensible
  -         */
           VTABLE_set_integer_native(INTERP, dest,
                                     SELF->cache.int_val %
                                     VTABLE_get_integer(INTERP, value));
  
  
  
  1.38      +1 -1      parrot/languages/imcc/optimizer.c
  
  Index: optimizer.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/optimizer.c,v
  retrieving revision 1.37
  retrieving revision 1.38
  diff -u -w -r1.37 -r1.38
  --- optimizer.c       5 Sep 2003 15:31:23 -0000       1.37
  +++ optimizer.c       11 Sep 2003 11:19:22 -0000      1.38
  @@ -99,7 +99,7 @@
       if (optimizer_level & OPT_CFG) {
           info(interpreter, 2, "optimize\n");
           any = constant_propagation(interpreter);
  -        if (clone_remove(interpreter))
  +        if (0 && clone_remove(interpreter))
               return 1;
           if (used_once(interpreter))
               return 1;
  
  
  
  1.10      +5 -0      parrot/math.ops
  
  Index: math.ops
  ===================================================================
  RCS file: /cvs/public/parrot/math.ops,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -w -r1.9 -r1.10
  --- math.ops  9 Sep 2003 10:25:29 -0000       1.9
  +++ math.ops  11 Sep 2003 11:19:24 -0000      1.10
  @@ -366,6 +366,11 @@
     goto NEXT();
   }
   
  +inline op div (in PMC, in PMC) {
  +  $1->vtable->divide(interpreter, $1, $2, $1);
  +  goto NEXT();
  +}
  +
   inline op div (in PMC, in INT) {
     $1->vtable->divide_int(interpreter, $1, $2, $1);
     goto NEXT();
  
  
  
  1.8       +24 -2     parrot/t/pmc/perlint.t
  
  Index: perlint.t
  ===================================================================
  RCS file: /cvs/public/parrot/t/pmc/perlint.t,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -w -r1.7 -r1.8
  --- perlint.t 7 Aug 2003 14:25:53 -0000       1.7
  +++ perlint.t 11 Sep 2003 11:19:25 -0000      1.8
  @@ -1,6 +1,6 @@
   #! perl -w
   
  -use Parrot::Test tests => 10;
  +use Parrot::Test tests => 11;
   use Parrot::PMC '%pmc_types';
   my $perlint = $pmc_types{'PerlInt'};
   my $ok = '"ok 1\n"';
  @@ -335,5 +335,27 @@
       end
   CODE
   12-1-2
  +OUTPUT
  +
  +output_is(<<'CODE', <<'OUTPUT', "divide gives int if possible");
  +    new P0, .PerlInt
  +    new P1, .PerlInt
  +    new P2, .PerlUndef
  +    set P0, 12
  +    set P1, 2
  +    div P2, P0, P1
  +    print P2
  +    print "\n"
  +    div P2, P1
  +    print P2
  +    print "\n"
  +    div P2, 2
  +    print P2
  +    print "\n"
  +    end
  +CODE
  +6
  +3
  +1.500000
   OUTPUT
   
  
  
  

Reply via email to