The enclosed patch makes a number of changes to perlstring.pmc, to bring it in line with my understanding of how PMCs are supposed to work. Specifically, unless we _know_ the type of the source and destination PMCs, we should always access them through their get_... and set_... methods.
In practical terms, this means that in arithmetical ops, for instance, we shouldn't change the vtable of the destination PMC: the only thing that does that should be its own set_... ops (if changing the vtable is appropriate). It also means that in concat ops, we should be assigning directly to dest->data, as we have no idea what's actually stored there. This patch makes the appropriate changes for add, sub, mul, div and the concat_... ops; I haven't looked at the others in any detail yet. In addition to the above, I also fix up the indentation in a few places -- I can send this as a separate patch if necessary. Finally, I also include a patch to perlstring.t that substantially extends the test suite by providing basic tests for all of the aforementioned ops. Simon --- classes/perlstring.pmc.old Tue Apr 9 14:26:06 2002 +++ classes/perlstring.pmc Wed Apr 10 14:35:55 2002 @@ -24,7 +24,7 @@ void init (INTVAL size) { SELF->data = string_make(INTERP,NULL,0,NULL,0,NULL); - SELF->flags = PMC_is_buffer_ptr_FLAG; + SELF->flags = PMC_is_buffer_ptr_FLAG; } void clone (PMC* dest) { @@ -49,12 +49,12 @@ INTVAL get_integer () { STRING* s = (STRING*) SELF->data; - return string_to_int(s); + return string_to_int(s); } FLOATVAL get_number () { STRING* s = (STRING*) SELF->data; - return string_to_num(s); + return string_to_num(s); } STRING* get_string () { @@ -62,7 +62,7 @@ } BOOLVAL get_bool () { - return string_bool(SELF->data); + return string_bool(SELF->data); } void* get_value () { @@ -141,27 +141,28 @@ void add (PMC * value, PMC* dest) { if(value->vtable == &Parrot_base_vtables[enum_class_PerlInt]) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlInt]; - dest->vtable->set_integer_native(INTERP, dest, - SELF->vtable->get_integer(INTERP, SELF) + + dest->vtable->set_number_native(INTERP, dest, + SELF->vtable->get_number(INTERP, SELF) + value->cache.int_val ); } else if(value->vtable == &Parrot_base_vtables[enum_class_PerlNum]) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlNum]; dest->vtable->set_number_native(INTERP, dest, SELF->vtable->get_number(INTERP, SELF) + value->cache.num_val ); } - else { + else { + dest->vtable->set_number_native(INTERP, dest, + SELF->vtable->get_number(INTERP, SELF) + + value->vtable->get_number(INTERP,value) + ); } } void add_int (INTVAL value, PMC* dest) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlInt]; - dest->vtable->set_integer_native(INTERP, dest, - SELF->vtable->get_integer(INTERP, SELF) + + dest->vtable->set_number_native(INTERP, dest, + SELF->vtable->get_number(INTERP, SELF) + value ); } @@ -170,7 +171,6 @@ } void add_float (FLOATVAL value, PMC* dest) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlNum]; dest->vtable->set_number_native(INTERP, dest, SELF->vtable->get_number(INTERP, SELF) + value @@ -185,27 +185,28 @@ void subtract (PMC * value, PMC* dest) { if(value->vtable == &Parrot_base_vtables[enum_class_PerlInt]) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlInt]; - dest->vtable->set_integer_native(INTERP, dest, - SELF->vtable->get_integer(INTERP, SELF) - + dest->vtable->set_number_native(INTERP, dest, + SELF->vtable->get_number(INTERP, SELF) - value->cache.int_val ); } else if(value->vtable == &Parrot_base_vtables[enum_class_PerlNum]) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlNum]; dest->vtable->set_number_native(INTERP, dest, SELF->vtable->get_number(INTERP, SELF) - value->cache.num_val ); } else { + dest->vtable->set_number_native(INTERP, dest, + SELF->vtable->get_number(INTERP, SELF) - + value->vtable->get_number(INTERP, value) + ); } } void subtract_int (INTVAL value, PMC* dest) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlInt]; - dest->vtable->set_integer_native(INTERP, dest, - SELF->vtable->get_integer(INTERP, SELF) - + dest->vtable->set_number_native(INTERP, dest, + SELF->vtable->get_number(INTERP, SELF) - value ); } @@ -214,7 +215,6 @@ } void subtract_float (FLOATVAL value, PMC* dest) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlNum]; dest->vtable->set_number_native(INTERP, dest, SELF->vtable->get_number(INTERP, SELF) - value @@ -229,27 +229,28 @@ void multiply (PMC * value, PMC* dest) { if(value->vtable == &Parrot_base_vtables[enum_class_PerlInt]) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlInt]; - dest->vtable->set_integer_native(INTERP, dest, - SELF->vtable->get_integer(INTERP, SELF) * + dest->vtable->set_number_native(INTERP, dest, + SELF->vtable->get_number(INTERP, SELF) * value->cache.int_val ); } else if(value->vtable == &Parrot_base_vtables[enum_class_PerlNum]) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlNum]; dest->vtable->set_number_native(INTERP, dest, SELF->vtable->get_number(INTERP, SELF) * value->cache.num_val ); } else { + dest->vtable->set_number_native(INTERP, dest, + SELF->vtable->get_number(INTERP, SELF) * + value->vtable->get_number(INTERP, value) + ); } } void multiply_int (INTVAL value, PMC* dest) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlInt]; - dest->vtable->set_integer_native(INTERP, dest, - SELF->vtable->get_integer(INTERP, SELF) * + dest->vtable->set_number_native(INTERP, dest, + SELF->vtable->get_number(INTERP, SELF) * value ); } @@ -258,7 +259,6 @@ } void multiply_float (FLOATVAL value, PMC* dest) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlNum]; dest->vtable->set_number_native(INTERP, dest, SELF->vtable->get_number(INTERP, SELF) * value @@ -273,27 +273,29 @@ void divide (PMC * value, PMC* dest) { if(value->vtable == &Parrot_base_vtables[enum_class_PerlInt]) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlInt]; - dest->vtable->set_integer_native(INTERP, dest, - SELF->vtable->get_integer(INTERP, SELF) / + dest->vtable->set_number_native(INTERP, dest, + SELF->vtable->get_number(INTERP, SELF) / value->cache.int_val ); } else if(value->vtable == &Parrot_base_vtables[enum_class_PerlNum]) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlNum]; dest->vtable->set_number_native(INTERP, dest, SELF->vtable->get_number(INTERP, SELF) / value->cache.num_val ); } else { + dest->vtable->set_number_native(INTERP, dest, + SELF->vtable->get_number(INTERP, SELF) / + value->vtable->get_number(INTERP, value) + ); + } } void divide_int (INTVAL value, PMC* dest) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlInt]; - dest->vtable->set_integer_native(INTERP, dest, - SELF->vtable->get_integer(INTERP, SELF) / + dest->vtable->set_number_native(INTERP, dest, + SELF->vtable->get_number(INTERP, SELF) / value ); } @@ -302,7 +304,6 @@ } void divide_float (FLOATVAL value, PMC* dest) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlNum]; dest->vtable->set_number_native(INTERP, dest, SELF->vtable->get_number(INTERP, SELF) / value @@ -317,7 +318,6 @@ void modulus (PMC * value, PMC* dest) { if(value->vtable == &Parrot_base_vtables[enum_class_PerlInt]) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlInt]; dest->vtable->set_integer_native(INTERP, dest, SELF->vtable->get_integer(INTERP, SELF) % value->cache.int_val @@ -328,7 +328,6 @@ } void modulus_int (INTVAL value, PMC* dest) { - dest->vtable = &Parrot_base_vtables[enum_class_PerlInt]; dest->vtable->set_integer_native(INTERP, dest, SELF->vtable->get_integer(INTERP, SELF) % value @@ -348,56 +347,53 @@ } void concatenate (PMC * value, PMC* dest) { - STRING* s = string_copy(INTERP, (STRING*)SELF->data); - dest->data = + dest->vtable->set_string_native(INTERP, dest, string_concat(INTERP, - s, + string_copy(INTERP, (STRING*)SELF->data), value->vtable->get_string(INTERP, value), 0 - ); - /* don't destroy s, as it is dest->data */ + ) + ); } void concatenate_native (STRING * value, PMC* dest) { - STRING* s = string_copy(INTERP, (STRING*)SELF->data); - dest->data = + dest->vtable->set_string_native(INTERP, dest, string_concat(INTERP, - s, + string_copy(INTERP, (STRING*)SELF->data), value, 0 - ); - /* don't destroy s, as it is dest->data */ + ) + ); } void concatenate_unicode (STRING * value, PMC* dest) { - STRING* s = string_copy(INTERP, (STRING*)SELF->data); - dest->data = + dest->vtable->set_string_unicode(INTERP, dest, string_concat(INTERP, - s, + string_copy(INTERP, (STRING*)SELF->data), value, 0 - ); - /* don't destroy s, as it is dest->data */ + ) + ); } void concatenate_other (STRING * value, PMC* dest) { - STRING* s = string_copy(INTERP, (STRING*)SELF->data); - dest->data = + dest->vtable->set_string_other(INTERP, dest, string_concat(INTERP, - s, + string_copy(INTERP, (STRING*)SELF->data), value, 0 - ); - /* don't destroy s, as it is dest->data */ + ) + ); } void concatenate_same (PMC * value, PMC* dest) { - dest->data = + dest->vtable->set_string_native(INTERP, dest, string_concat(INTERP, SELF->data, value->data, 0 - ); + ) + ); } /* == operation */ --- t/pmc/perlstring.t.old Tue Apr 9 14:08:46 2002 +++ t/pmc/perlstring.t Wed Apr 10 14:32:00 2002 @@ -1,6 +1,6 @@ #! perl -w -use Parrot::Test tests => 8; +use Parrot::Test tests => 30; use Test::More; # Included for skip(). my $fp_equality_macro = <<'ENDOFMACRO'; @@ -46,6 +46,32 @@ endm ENDOFMACRO +output_is(<<'CODE', <<OUTPUT, "Creating a PerlString"); + print "Starting\n" + new P0, PerlString + print "Ending\n" + end +CODE +Starting +Ending +OUTPUT + +output_is(<<'CODE', <<OUTPUT, "Creating lots of PerlStrings"); + set I0, 0 + print "Starting\n" + +FOO: inc I0 + new P0, PerlString + lt I0, 10000, FOO + + print "Ending\n" + end +CODE +Starting +Ending +OUTPUT + + output_is(<<CODE, <<OUTPUT, "Set/get strings"); new P0, PerlString set P0, "foo" @@ -188,6 +214,702 @@ ok 6 OUTPUT +output_is(<<"CODE", <<OUTPUT, "Creating new PMC clears old value"); +@{[ $fp_equality_macro ]} + new P0, PerlString + set P0, "Foo" + new P0, PerlString + set S0, P0 + eq S0, "", OK1 + + print "not " +OK1: print "ok 1\\n" + new P1, PerlString + set P1, 10.0 + new P1, PerlString + set N1, P1 + fp_eq N1, 0.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlString + set P2, 1 + new P2, PerlString + set I2, P2 + eq I2, 0, OK3 + print "not " +OK3: print "ok 3\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +OUTPUT + + +# Arithmetic + +output_is(<<"CODE", <<OUTPUT, "Addition: (numeric) string + (numeric) string"); +@{[ $fp_equality_macro ]} + new P0, PerlString + new P1, PerlString + set P0, "2.0" + set P1, "10" + + new P2, PerlString + add P2, P1, P0 + set N0, P2 + fp_eq N0, 12.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + add P2, P1, P0 + set N0, P2 + fp_eq N0, 12.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + add P2, P1, P0 + set N0, P2 + fp_eq N0, 12.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + add P2, P1, P0 + set N0, P2 + fp_eq N0, 12.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Addition: (numeric) string + int"); +@{[ $fp_equality_macro ]} + new P0, PerlInt + new P1, PerlString + set P0, 2 + set P1, "10.0" + + new P2, PerlString + add P2, P1, P0 + set N0, P2 + fp_eq N0, 12.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + add P2, P1, P0 + set N0, P2 + fp_eq N0, 12.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + add P2, P1, P0 + set N0, P2 + fp_eq N0, 12.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + add P2, P1, P0 + set N0, P2 + fp_eq N0, 12.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Addition: (numeric) string + num"); +@{[ $fp_equality_macro ]} + new P0, PerlNum + new P1, PerlString + set P0, 2.0 + set P1, "10.0" + + new P2, PerlString + add P2, P1, P0 + set N0, P2 + fp_eq N0, 12.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + add P2, P1, P0 + set N0, P2 + fp_eq N0, 12.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + add P2, P1, P0 + set N0, P2 + fp_eq N0, 12.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + add P2, P1, P0 + set N0, P2 + fp_eq N0, 12.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Addition: (numeric) string + undef"); +@{[ $fp_equality_macro ]} + new P0, PerlUndef + new P1, PerlString + set P1, "10.0" + + new P2, PerlString + add P2, P1, P0 + set N0, P2 + fp_eq N0, 10.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + add P2, P1, P0 + set N0, P2 + fp_eq N0, 10.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + add P2, P1, P0 + set N0, P2 + fp_eq N0, 10.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + add P2, P1, P0 + set N0, P2 + fp_eq N0, 10.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Subtraction: string - string"); +@{[ $fp_equality_macro ]} + new P0, PerlString + new P1, PerlString + set P0, "2.0" + set P1, "10" + + new P2, PerlString + sub P2, P1, P0 + set N0, P2 + fp_eq N0, 8.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + sub P2, P1, P0 + set N0, P2 + fp_eq N0, 8.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + sub P2, P1, P0 + set N0, P2 + fp_eq N0, 8.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + sub P2, P1, P0 + set N0, P2 + fp_eq N0, 8.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Subtraction: string - int"); +@{[ $fp_equality_macro ]} + new P0, PerlInt + new P1, PerlString + set P0, 11 + set P1, "10" + + new P2, PerlString + sub P2, P1, P0 + set N0, P2 + fp_eq N0, -1.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + sub P2, P1, P0 + set N0, P2 + fp_eq N0, -1.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + sub P2, P1, P0 + set N0, P2 + fp_eq N0, -1.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + sub P2, P1, P0 + set N0, P2 + fp_eq N0, -1.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Subtraction: string - num"); +@{[ $fp_equality_macro ]} + new P0, PerlNum + new P1, PerlString + set P0, 5.5 + set P1, "10" + + new P2, PerlString + sub P2, P1, P0 + set N0, P2 + fp_eq N0, 4.5, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + sub P2, P1, P0 + set N0, P2 + fp_eq N0, 4.5, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + sub P2, P1, P0 + set N0, P2 + fp_eq N0, 4.5, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + sub P2, P1, P0 + set N0, P2 + fp_eq N0, 4.5, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Subtraction: string - undef"); +@{[ $fp_equality_macro ]} + new P0, PerlUndef + new P1, PerlString + set P1, "10" + + new P2, PerlString + sub P2, P1, P0 + set N0, P2 + fp_eq N0, 10.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + sub P2, P1, P0 + set N0, P2 + fp_eq N0, 10.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + sub P2, P1, P0 + set N0, P2 + fp_eq N0, 10.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + sub P2, P1, P0 + set N0, P2 + fp_eq N0, 10.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Multiplication: string * string"); +@{[ $fp_equality_macro ]} + new P0, PerlString + new P1, PerlString + set P0, "2.0" + set P1, "10" + + new P2, PerlString + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 20.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 20.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 20.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 20.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Multiplication: string * int"); +@{[ $fp_equality_macro ]} + new P0, PerlInt + new P1, PerlString + set P0, -1 + set P1, "-1" + + new P2, PerlString + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 1.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 1.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 1.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 1.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Multiplication: string * num"); +@{[ $fp_equality_macro ]} + new P0, PerlNum + new P1, PerlString + set P0, 3.0 + set P1, "3" + + new P2, PerlString + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 9.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 9.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 9.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 9.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Multiplication: string * undef"); +@{[ $fp_equality_macro ]} + new P0, PerlUndef + new P1, PerlString + set P1, "3" + + new P2, PerlString + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 0.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 0.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 0.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + mul P2, P1, P0 + set N0, P2 + fp_eq N0, 0.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Division: string / string"); +@{[ $fp_equality_macro ]} + new P0, PerlString + new P1, PerlString + set P0, "2.0" + set P1, "10" + + new P2, PerlString + div P2, P1, P0 + set N0, P2 + fp_eq N0, 5.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + div P2, P1, P0 + set N0, P2 + fp_eq N0, 5.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + div P2, P1, P0 + set N0, P2 + fp_eq N0, 5.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + div P2, P1, P0 + set N0, P2 + fp_eq N0, 5.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Division: string / int"); +@{[ $fp_equality_macro ]} + new P0, PerlInt + new P1, PerlString + set P0, 2 + set P1, "10" + + new P2, PerlString + div P2, P1, P0 + set N0, P2 + fp_eq N0, 5.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + div P2, P1, P0 + set N0, P2 + fp_eq N0, 5.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + div P2, P1, P0 + set N0, P2 + fp_eq N0, 5.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + div P2, P1, P0 + set N0, P2 + fp_eq N0, 5.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +output_is(<<"CODE", <<OUTPUT, "Division: string / num"); +@{[ $fp_equality_macro ]} + new P0, PerlNum + new P1, PerlString + set P0, 2.0 + set P1, "10" + + new P2, PerlString + div P2, P1, P0 + set N0, P2 + fp_eq N0, 5.0, OK1 + + print "not " +OK1: print "ok 1\\n" + new P2, PerlNum + div P2, P1, P0 + set N0, P2 + fp_eq N0, 5.0, OK2 + + print "not " +OK2: print "ok 2\\n" + new P2, PerlInt + div P2, P1, P0 + set N0, P2 + fp_eq N0, 5.0, OK3 + + print "not " +OK3: print "ok 3\\n" + new P2, PerlUndef + div P2, P1, P0 + set N0, P2 + fp_eq N0, 5.0, OK4 + print "not " +OK4: print "ok 4\\n" + + end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +OUTPUT + +SKIP: { +skip("Pending exception handling",1); + +output_is(<<"CODE", <<OUTPUT, "Division: string / undef"); +@{[ $fp_equality_macro ]} + new P0, PerlUndef + new P1, PerlString + set P1, "10" + + new P2, PerlString + div P2, P1, P0 +CODE +OUTPUT +} + + +#Stringy ops: + output_is(<<CODE, <<OUTPUT, "ensure that concat ppp copies strings"); new P0, PerlString new P1, PerlString @@ -220,6 +942,107 @@ You can't teach an old dog new...clear physics OUTPUT +output_is(<<CODE, <<OUTPUT, "concat string & int"); + new P0, PerlInt + new P1, PerlString + set P0, 1234 + set P1, "abcd" + + new P2, PerlString + concat P2, P1, P0 + print P2 + print "\\n" + + new P2, PerlInt + concat P2, P1, P0 + print P2 + print "\\n" + + new P2, PerlNum + concat P2, P1, P0 + print P2 + print "\\n" + + new P2, PerlUndef + concat P2, P1, P0 + print P2 + print "\\n" + + end +CODE +abcd1234 +abcd1234 +abcd1234 +abcd1234 +OUTPUT + +output_is(<<CODE, <<OUTPUT, "concat string & num"); + new P0, PerlNum + new P1, PerlString + set P0, 12.345678 + set P1, "abcd" + + new P2, PerlString + concat P2, P1, P0 + print P2 + print "\\n" + + new P2, PerlInt + concat P2, P1, P0 + print P2 + print "\\n" + + new P2, PerlNum + concat P2, P1, P0 + print P2 + print "\\n" + + new P2, PerlUndef + concat P2, P1, P0 + print P2 + print "\\n" + + end +CODE +abcd12.345678 +abcd12.345678 +abcd12.345678 +abcd12.345678 +OUTPUT + +output_is(<<CODE, <<OUTPUT, "concat string & undef"); + new P0, PerlUndef + new P1, PerlString + set P1, "abcd" + + new P2, PerlString + concat P2, P1, P0 + print P2 + print "\\n" + + new P2, PerlInt + concat P2, P1, P0 + print P2 + print "\\n" + + new P2, PerlNum + concat P2, P1, P0 + print P2 + print "\\n" + + new P2, PerlUndef + concat P2, P1, P0 + print P2 + print "\\n" + + end +CODE +abcd +abcd +abcd +abcd +OUTPUT + SKIP: { skip("Pending new version of concat_p_p_s",1); output_is(<<CODE, <<OUTPUT, "ensure that concat pps copies strings"); @@ -300,8 +1123,6 @@ OUTPUT - - output_is(<<CODE, <<OUTPUT, "if(PerlString)"); new P0, PerlString set S0, "True"