2 Copyright (C) 2001-2009, Parrot Foundation.
7 src/pmc/scalar.pmc - Scalar Abstract Superclass
11 These are the vtable functions for the scalar base PMC class
21 #include "pmc_bigint.h"
24 bitwise_left_shift_internal(PARROT_INTERP, PMC *self,
25 PMC *dest, INTVAL shift_amount)
27 /* This handles both left and right shifts; the sign of shift_amount
28 controls the direction, shifting left if positive and right if negative.
29 If we get an error (which can only happen for left shifts) and
30 PARROT_ERRORS_OVERFLOW_FLAG is set, then we throw an error, else the
31 destination is promoted to a BigInt before shifting. If dest == self,
32 then the shift is done in place. */
33 const INTVAL base = VTABLE_get_integer(interp, self);
37 /* Compute the shift. */
38 if (shift_amount >= 8*INTVAL_SIZE) {
39 /* Extreme left shift; no need to do an integer shift first. */
42 else if (shift_amount >= 0) {
44 result = base << shift_amount;
45 overflow_p = (result >> shift_amount) != base;
47 else if (shift_amount > -8*INTVAL_SIZE) {
48 /* Right shift. By definition, this can never overflow. */
49 result = base >> -shift_amount;
52 /* Extreme right shift. */
56 /* Store the result. */
58 /* If SELF is the destination, we won't want to create a
59 new PMC, because then we won't have the result in SELF.
60 Only create a new PMC if we aren't saving the result
61 to SELF, or if they are both NULL */
62 if (dest != self || dest == NULL)
63 dest = pmc_new(interp, VTABLE_type(interp, self));
65 VTABLE_set_integer_native(interp, dest, result);
67 else if (PARROT_ERRORS_test(interp, PARROT_ERRORS_OVERFLOW_FLAG)) {
68 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_ERR_OVERFLOW,
72 /* Overflow; must promote dest to BigInt, and do a BigInt shift. */
74 pmc_reuse(interp, self, enum_class_BigInt, 0);
76 dest = pmc_new(interp, enum_class_BigInt);
78 VTABLE_set_integer_native(interp, dest, base);
79 VTABLE_i_bitwise_shl_int(interp, dest, shift_amount);
89 =item C<void assign_pmc(PMC *value)>
91 Sets the PMC C<*value>, calling the appropriate C<set_*> method
92 according to the type of C<*value>.
98 VTABLE void assign_pmc(PMC *value) {
99 STRING * const s_int = CONST_STRING(INTERP, "Integer");
103 if (SELF->vtable->base_type == enum_class_Boolean)
105 pmc_reuse(INTERP, SELF, value->vtable->base_type, 0);
107 if (value->vtable->base_type == enum_class_Undef) {
108 pmc_reuse(INTERP, SELF, value->vtable->base_type, 0);
112 if (VTABLE_isa(INTERP, value, s_int)) {
113 const INTVAL v = VTABLE_get_integer(INTERP, value);
114 SELF.set_integer_native(v);
118 s_num = CONST_STRING(INTERP, "Float");
120 if (VTABLE_isa(INTERP, value, s_num)) {
121 const FLOATVAL v = VTABLE_get_number(INTERP, value);
122 SELF.set_number_native(v);
126 s_str = CONST_STRING(INTERP, "String");
128 if (VTABLE_isa(INTERP, value, s_str)) {
129 STRING * const v = VTABLE_get_string(INTERP, value);
130 SELF.set_string_native(v);
133 pmc_reuse(INTERP, SELF, value->vtable->base_type, 0);
141 =head1 Mathematical Methods
145 =item C<PMC *subtract(PMC *value, PMC *dest)>
153 =item C<void add(PMC *value, PMC *dest)>
155 =item C<void add_int(INTVAL value, PMC *dest)>
157 =item C<void add_float(FLOATVAL value, PMC *dest)>
159 Adds C<value> to the number and returns the result in C<*dest>.
160 If C<dest> is NULL it's created.
162 =item C<void i_add(PMC *value)>
164 =item C<void i_add(INTVAL value)>
166 =item C<void i_add(FLOATVAL value)>
168 Adds C<value> to C<SELF> inplace.
174 MULTI PMC *add(Complex value, PMC *dest) {
175 const FLOATVAL a = SELF.get_number();
177 dest = pmc_new(INTERP, VTABLE_type(INTERP, value));
179 VTABLE_set_number_native(INTERP, dest,
180 a + VTABLE_get_number_keyed_int(INTERP, value, 0));
181 VTABLE_set_number_keyed_int(INTERP, dest, 1,
182 VTABLE_get_number_keyed_int(INTERP, value, 1));
186 MULTI PMC *add(DEFAULT value, PMC *dest) {
187 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
189 VTABLE_set_number_native(INTERP, dest,
190 SELF.get_number() + VTABLE_get_number(INTERP, value));
194 VTABLE PMC *add_int(INTVAL value, PMC *dest) {
195 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
197 VTABLE_set_number_native(INTERP, dest,
198 SELF.get_number() + (FLOATVAL)value);
202 VTABLE PMC *add_float(FLOATVAL value, PMC *dest) {
203 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
205 VTABLE_set_number_native(INTERP, dest,
206 SELF.get_number() + value);
210 MULTI void i_add(Complex value) {
211 const FLOATVAL a = SELF.get_number();
213 pmc_reuse(INTERP, SELF, enum_class_Complex, 0);
214 VTABLE_set_number_native(INTERP, SELF,
215 a + VTABLE_get_number_keyed_int(INTERP, value, 0));
216 VTABLE_set_number_keyed_int(INTERP, SELF, 1,
217 VTABLE_get_number_keyed_int(INTERP, value, 1));
220 MULTI void i_add(DEFAULT value) {
221 VTABLE_set_number_native(INTERP, SELF,
222 SELF.get_number() + VTABLE_get_number(INTERP, value));
225 VTABLE void i_add_int(INTVAL value) {
226 VTABLE_set_number_native(INTERP, SELF,
227 SELF.get_number() + (FLOATVAL)value);
230 VTABLE void i_add_float(FLOATVAL value) {
231 VTABLE_set_number_native(INTERP, SELF,
232 SELF.get_number() + value);
237 =item C<PMC *subtract(PMC *value, PMC *dest)>
239 =item C<PMC *subtract_int(INTVAL value, PMC *dest)>
241 =item C<PMC *subtract_float(FLOATVAL value, PMC *dest)>
243 Subtracts C<value> from the number and returns the result in C<*dest>.
244 If C<dest> doesn't exist a new C<Float> is created.
246 =item C<void i_subtract(PMC *value)>
248 =item C<void i_subtract_int(INTVAL value)>
250 =item C<void i_subtract_float(FLOATVAL value)>
252 Subtracts C<value> from C<SELF> inplace.
258 MULTI PMC *subtract(Complex value, PMC *dest) {
259 const FLOATVAL a = SELF.get_number();
260 dest = pmc_new(INTERP, VTABLE_type(INTERP, value));
262 VTABLE_set_number_native(INTERP, dest,
263 a - VTABLE_get_number_keyed_int(INTERP, value, 0));
264 VTABLE_set_number_keyed_int(INTERP, dest, 1,
265 -VTABLE_get_number_keyed_int(INTERP, value, 1));
269 MULTI PMC *subtract(DEFAULT value, PMC *dest) {
270 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
271 VTABLE_set_number_native(INTERP, dest,
272 SELF.get_number() - VTABLE_get_number(INTERP, value));
276 VTABLE PMC *subtract_int(INTVAL value, PMC *dest) {
277 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
279 VTABLE_set_number_native(INTERP, dest,
280 SELF.get_number() - (FLOATVAL)value);
284 VTABLE PMC *subtract_float(FLOATVAL value, PMC *dest) {
285 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
287 VTABLE_set_number_native(INTERP, dest,
288 SELF.get_number() - value);
292 MULTI void i_subtract(Complex value) {
293 const FLOATVAL a = SELF.get_number();
295 pmc_reuse(INTERP, SELF, enum_class_Complex, 0);
296 VTABLE_set_number_native(INTERP, SELF,
297 a - VTABLE_get_number_keyed_int(INTERP, value, 0));
298 VTABLE_set_number_keyed_int(INTERP, SELF, 1,
299 -VTABLE_get_number_keyed_int(INTERP, value, 1));
302 MULTI void i_subtract(DEFAULT value) {
303 VTABLE_set_number_native(INTERP, SELF,
304 SELF.get_number() - VTABLE_get_number(INTERP, value));
307 VTABLE void i_subtract_int(INTVAL value) {
308 VTABLE_set_number_native(INTERP, SELF,
309 SELF.get_number() - (FLOATVAL)value);
312 VTABLE void i_subtract_float(FLOATVAL value) {
313 VTABLE_set_number_native(INTERP, SELF,
314 SELF.get_number() - value);
319 =item C<PMC *multiply(PMC *value, PMC *dest)>
321 =item C<PMC *multiply_int(INTVAL value, PMC *dest)>
323 =item C<PMC *multiply_float(FLOATVAL value, PMC *dest)>
325 Multiplies the number by C<value> and returns the result in C<*dest>.
331 MULTI PMC *multiply(Complex value, PMC *dest) {
332 Parrot_ex_throw_from_c_args(INTERP, NULL,
333 EXCEPTION_INTERNAL_NOT_IMPLEMENTED, "TODO mul<Float, Complex>");
336 MULTI PMC *multiply(DEFAULT value, PMC *dest) {
337 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
339 VTABLE_set_number_native(INTERP, dest,
340 SELF.get_number() * VTABLE_get_number(INTERP, value));
344 VTABLE PMC *multiply_int(INTVAL value, PMC *dest) {
345 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
347 VTABLE_set_number_native(INTERP, dest,
348 SELF.get_number() * value);
352 VTABLE PMC *multiply_float(FLOATVAL value, PMC *dest) {
353 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
355 VTABLE_set_number_native(INTERP, dest,
356 SELF.get_number() * value);
360 MULTI void i_multiply(Complex value) {
361 Parrot_ex_throw_from_c_args(INTERP, NULL,
362 EXCEPTION_INTERNAL_NOT_IMPLEMENTED,
363 "TODO i_mul<Float, Complex>");
366 MULTI void i_multiply(DEFAULT value) {
367 VTABLE_set_number_native(INTERP, SELF,
368 SELF.get_number() * VTABLE_get_number(INTERP, value));
371 VTABLE void i_multiply_int(INTVAL value) {
372 VTABLE_set_number_native(INTERP, SELF,
373 SELF.get_number() * (FLOATVAL)value);
376 VTABLE void i_multiply_float(FLOATVAL value) {
377 VTABLE_set_number_native(INTERP, SELF, SELF.get_number() * value);
382 =item C<PMC *divide(PMC *value, PMC *dest)>
384 =item C<PMC *divide_int(INTVAL value, PMC *dest)>
386 =item C<PMC *divide_float(FLOATVAL value, PMC *dest)>
388 Divides the number by C<value> and returns the result in C<*dest>.
390 =item C<void i_divide(PMC *value)>
392 =item C<void i_divide_int(INTVAL value)>
394 =item C<void i_divide_float(FLOATVAL value)>
396 Divides C<SELF> by C<value> inplace.
402 MULTI PMC *divide(PMC *value, PMC *dest) {
403 const FLOATVAL d = VTABLE_get_number(INTERP, value);
405 if (FLOAT_IS_ZERO(d))
406 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
407 "float division by zero");
409 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
411 VTABLE_set_number_native(INTERP, dest, SELF.get_number() / d);
415 VTABLE PMC *divide_int(INTVAL value, PMC *dest) {
417 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
418 "float division by zero");
420 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
422 VTABLE_set_number_native(INTERP, dest, SELF.get_number() / value);
426 VTABLE PMC *divide_float(FLOATVAL value, PMC *dest) {
427 if (FLOAT_IS_ZERO(value))
428 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
429 "float division by zero");
431 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
433 VTABLE_set_number_native(INTERP, dest, SELF.get_number() / value);
437 VTABLE void i_divide(PMC *value) {
438 const FLOATVAL d = VTABLE_get_number(INTERP, value);
440 if (FLOAT_IS_ZERO(d))
441 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
442 "float division by zero");
444 VTABLE_set_number_native(INTERP, SELF, SELF.get_number() / d);
447 VTABLE void i_divide_int(INTVAL value) {
449 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
450 "float division by zero");
452 VTABLE_set_number_native(INTERP, SELF, SELF.get_number() / value);
455 VTABLE void i_divide_float(FLOATVAL value) {
456 if (FLOAT_IS_ZERO(value))
457 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
458 "float division by zero");
460 VTABLE_set_number_native(INTERP, SELF, SELF.get_number() / value);
465 =item C<PMC *floor_divide(PMC *value, PMC *dest)>
467 =item C<PMC *floor_divide_int(INTVAL value, PMC *dest)>
469 =item C<PMC *floor_divide_float(FLOATVAL value, PMC *dest)>
471 Divides the number by C<value> and returns the result in C<*dest>.
473 =item C<void i_floor_divide(PMC *value)>
475 =item C<void i_floor_divide_int(INTVAL value)>
477 =item C<void i_floor_divide_float(FLOATVAL value)>
479 Divides C<SELF> by C<value> inplace.
485 MULTI PMC *floor_divide(PMC *value, PMC *dest) {
486 FLOATVAL d = VTABLE_get_number(INTERP, value);
488 if (FLOAT_IS_ZERO(d))
489 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
490 "float division by zero");
492 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
493 d = floor(SELF.get_number() / d);
495 VTABLE_set_integer_native(INTERP, dest, (INTVAL)d);
499 VTABLE PMC *floor_divide_int(INTVAL value, PMC *dest) {
501 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
502 "float division by zero");
504 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
506 VTABLE_set_number_native(INTERP, dest,
507 floor(SELF.get_number() / value));
511 VTABLE PMC *floor_divide_float(FLOATVAL value, PMC *dest) {
512 if (FLOAT_IS_ZERO(value))
513 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
514 "float division by zero");
516 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
518 VTABLE_set_number_native(INTERP, dest,
519 floor(SELF.get_number() / value));
523 VTABLE void i_floor_divide(PMC *value) {
524 const FLOATVAL d = VTABLE_get_number(INTERP, value);
526 if (FLOAT_IS_ZERO(d))
527 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
528 "float division by zero");
530 VTABLE_set_number_native(INTERP, SELF,
531 floor(SELF.get_number() / d));
534 VTABLE void i_floor_divide_int(INTVAL value) {
536 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
537 "float division by zero");
539 VTABLE_set_number_native(INTERP, SELF,
540 floor(SELF.get_number() / value));
543 VTABLE void i_floor_divide_float(FLOATVAL value) {
544 if (FLOAT_IS_ZERO(value))
545 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
546 "float division by zero");
548 VTABLE_set_number_native(INTERP, SELF,
549 floor(SELF.get_number() / value));
554 =item C<PMC *modulus(PMC *value, PMC *dest)>
556 =item C<PMC *modulus(INTVAL value, PMC *dest)>
558 =item C<PMC *modulus(FLOATVAL value, PMC *dest)>
560 Calculates the value of corrected C<mod> C<value> and returns
561 the result in C<dest>. See also ops/math.ops.
563 =item C<void i_modulus(PMC *value)>
565 =item C<void i_modulus(INTVAL value)>
567 =item C<void i_modulus(FLOATVAL value)>
569 Calculates modulus inplace
575 MULTI PMC *modulus(PMC *value, PMC *dest) {
576 const FLOATVAL d = VTABLE_get_number(INTERP, value);
578 if (FLOAT_IS_ZERO(d))
579 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
580 "float modulus by zero");
582 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
584 VTABLE_set_number_native(INTERP, dest,
585 floatval_mod(SELF.get_number(), d));
589 VTABLE PMC *modulus_int(INTVAL value, PMC *dest) {
591 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
592 "float modulus by zero");
594 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
596 VTABLE_set_number_native(INTERP, dest,
597 floatval_mod(SELF.get_number(), (FLOATVAL)value));
601 VTABLE PMC *modulus_float(FLOATVAL value, PMC *dest) {
602 if (FLOAT_IS_ZERO(value))
603 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
604 "float modulus by zero");
606 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
608 VTABLE_set_number_native(INTERP, dest,
609 floatval_mod(SELF.get_number(), value));
613 VTABLE void i_modulus(PMC *value) {
614 const FLOATVAL d = VTABLE_get_number(INTERP, value);
616 if (FLOAT_IS_ZERO(d))
617 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
618 "float modulus by zero");
620 VTABLE_set_number_native(INTERP, SELF,
621 floatval_mod(SELF.get_number(), d));
624 VTABLE void i_modulus_int(INTVAL value) {
626 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
627 "float modulus by zero");
629 VTABLE_set_number_native(INTERP, SELF,
630 floatval_mod(SELF.get_number(), (FLOATVAL)value));
633 VTABLE void i_modulus_float(FLOATVAL value) {
634 if (FLOAT_IS_ZERO(value))
635 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
636 "float modulus by zero");
638 VTABLE_set_number_native(INTERP, SELF,
639 floatval_mod(SELF.get_number(), value));
644 =item C<PMC *pow(PMC *value, PMC *dest)>
646 =item C<PMC *pow_int(INTVAL value, PMC *dest)>
648 =item C<PMC *pow_float(FLOATVAL value, PMC *dest)>
650 Calculates C<SELF pow value> and returns
651 the result in C<dest>. See also ops/math.ops.
653 =item C<void i_pow(PMC *value)>
655 =item C<void i_pow_int(INTVAL value)>
657 =item C<void i_pow_float(FLOATVAL value)>
659 Calculates pow inplace
665 MULTI PMC *pow(PMC *value, PMC *dest) {
666 const FLOATVAL d = VTABLE_get_number(INTERP, value);
668 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
670 VTABLE_set_number_native(INTERP, dest, pow(SELF.get_number(), d));
674 VTABLE PMC *pow_int(INTVAL value, PMC *dest) {
675 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
677 VTABLE_set_number_native(INTERP, dest,
678 pow(SELF.get_number(), (double)value));
683 VTABLE PMC *pow_float(FLOATVAL value, PMC *dest) {
684 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
686 VTABLE_set_number_native(INTERP, dest,
687 pow(SELF.get_number(), value));
691 VTABLE void i_pow(PMC *value) {
692 const FLOATVAL d = VTABLE_get_number(INTERP, value);
694 VTABLE_set_number_native(INTERP, SELF,
695 pow(SELF.get_number(), d));
698 VTABLE void i_pow_int(INTVAL value) {
699 VTABLE_set_number_native(INTERP, SELF,
700 pow(SELF.get_number(), (float)value));
703 VTABLE void i_pow_float(FLOATVAL value) {
704 VTABLE_set_number_native(INTERP, SELF,
705 pow(SELF.get_number(), value));
710 =item C<PMC *neg(PMC *dest)>
712 =item C<void i_neg()>
714 Set C<dest> to the negated value of C<SELF>.
720 VTABLE PMC *neg(PMC *dest) {
721 const INTVAL a = -SELF.get_integer();
723 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
725 VTABLE_set_integer_native(INTERP, dest, a);
729 VTABLE void i_neg() {
730 VTABLE_set_integer_native(INTERP, SELF, -SELF.get_integer());
737 =head2 Bitwise Methods
741 =item C<PMC *bitwise_or(PMC *value, PMC *dest)>
743 =item C<PMC *bitwise_or_int(INTVAL value, PMC *dest)>
745 Returns in C<*dest> the bitwise C<OR> of the scalar and C<value>.
747 =item C<void i_bitwise_or(PMC *value)>
749 =item C<void i_bitwise_or_int(INTVAL value)>
757 VTABLE PMC *bitwise_or(PMC *value, PMC *dest) {
758 const INTVAL result = SELF.get_integer() | VTABLE_get_integer(INTERP, value);
760 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
762 VTABLE_set_integer_native(INTERP, dest, result);
767 VTABLE PMC *bitwise_or_int(INTVAL value, PMC *dest) {
768 const INTVAL result = SELF.get_integer() | value;
770 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
772 VTABLE_set_integer_native(INTERP, dest, result);
776 VTABLE void i_bitwise_or(PMC *value) {
777 const INTVAL result =
778 SELF.get_integer() | VTABLE_get_integer(INTERP, value);
780 SELF.set_integer_native(result);
784 VTABLE void i_bitwise_or_int(INTVAL value) {
785 const INTVAL result = SELF.get_integer() | value;
786 SELF.set_integer_native(result);
791 =item C<PMC *bitwise_and(PMC *value, PMC *dest)>
793 =item C<PMC *bitwise_and_int(INTVAL value, PMC *dest)>
795 Returns in C<*dest> the bitwise C<AND> of the scalar and C<value>.
797 =item C<void i_bitwise_and(PMC *value)>
799 =item C<void i_bitwise_and_int(INTVAL value)>
807 VTABLE PMC *bitwise_and(PMC *value, PMC *dest) {
808 const INTVAL result =
809 SELF.get_integer() & VTABLE_get_integer(INTERP, value);
811 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
813 VTABLE_set_integer_native(INTERP, dest, result);
817 VTABLE PMC *bitwise_and_int(INTVAL value, PMC *dest) {
818 const INTVAL result = SELF.get_integer() & value;
820 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
822 VTABLE_set_integer_native(INTERP, dest, result);
826 VTABLE void i_bitwise_and(PMC *value) {
827 const INTVAL result =
828 SELF.get_integer() & VTABLE_get_integer(INTERP, value);
829 SELF.set_integer_native(result);
833 VTABLE void i_bitwise_and_int(INTVAL value) {
834 const INTVAL result = SELF.get_integer() & value;
835 SELF.set_integer_native(result);
840 =item C<void bitwise_xor(PMC *value, PMC *dest)>
842 =item C<void bitwise_xor_int(INTVAL value, PMC *dest)>
844 Returns in C<*dest> the bitwise C<XOR> of the scalar and C<*value>.
846 =item C<void i_bitwise_xor(PMC *value)>
848 =item C<void i_bitwise_xor_int(INTVAL value)>
856 MULTI PMC *bitwise_xor(PMC *value, PMC *dest) {
857 const INTVAL result =
858 SELF.get_integer() ^ VTABLE_get_integer(INTERP, value);
860 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
862 VTABLE_set_integer_native(INTERP, dest, result);
866 VTABLE PMC *bitwise_xor_int(INTVAL value, PMC *dest) {
867 const INTVAL result = SELF.get_integer() ^ value;
869 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
871 VTABLE_set_integer_native(INTERP, dest, result);
875 VTABLE void i_bitwise_xor(PMC *value) {
876 const INTVAL result =
877 SELF.get_integer() ^ VTABLE_get_integer(INTERP, value);
878 SELF.set_integer_native(result);
881 VTABLE void i_bitwise_xor_int(INTVAL value) {
882 const INTVAL result = SELF.get_integer() ^ value;
883 SELF.set_integer_native(result);
888 =item C<PMC *bitwise_not(PMC *dest)>
890 =item C<void i_bitwise_not()>
892 Returns in C<*dest> the bitwise negation of the scalar and C<value>.
898 VTABLE PMC *bitwise_not(PMC *dest) {
899 const INTVAL a = ~SELF.get_integer();
901 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
903 VTABLE_set_integer_native(INTERP, dest, a);
907 VTABLE void i_bitwise_not() {
908 VTABLE_set_integer_native(INTERP, SELF, ~SELF.get_integer());
913 =item C<PMC *bitwise_shr(PMC *value, PMC *dest)>
915 =item C<PMC *bitwise_shr_int(INTVAL value, PMC *dest)>
917 Returns in C<*dest> the arithmetic shift right of the scalar by C<value>.
918 A negative C<value> shifts left.
919 The destination may become a C<BigInt> as a result (but only if the shift amount
922 =item C<void i_bitwise_shr(PMC *value)>
924 =item C<void i_bitwise_shr_int(INTVAL value)>
926 Inplace shift right. A negative C<value> shifts left.
927 SELF may become a C<BigInt> as a result (but only if the shift amount is less
934 VTABLE PMC *bitwise_shr(PMC *value, PMC *dest) {
935 return bitwise_left_shift_internal(INTERP, SELF, dest,
936 -VTABLE_get_integer(INTERP, value));
939 VTABLE PMC *bitwise_shr_int(INTVAL value, PMC *dest) {
940 return bitwise_left_shift_internal(INTERP, SELF, dest, -value);
943 VTABLE void i_bitwise_shr(PMC *value) {
944 bitwise_left_shift_internal(INTERP, SELF, SELF,
945 -VTABLE_get_integer(INTERP, value));
948 VTABLE void i_bitwise_shr_int(INTVAL value) {
949 bitwise_left_shift_internal(INTERP, SELF, SELF, -value);
954 =item C<PMC *bitwise_lsr(PMC *value, PMC *dest)>
956 =item C<PMC *bitwise_lsr_int(INTVAL value, PMC *dest)>
958 Returns in C<*dest> the logical shift right of the scalar by C<*value>.
960 =item C<void i_bitwise_lsr(PMC *value)>
962 =item C<void i_bitwise_lsr_int(INTVAL value)>
970 VTABLE PMC *bitwise_lsr(PMC *value, PMC *dest) {
971 const INTVAL result = (UINTVAL)SELF.get_integer() >>
972 VTABLE_get_integer(INTERP, value);
974 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
976 VTABLE_set_integer_native(INTERP, dest, result);
980 VTABLE PMC *bitwise_lsr_int(INTVAL value, PMC *dest) {
981 const INTVAL result = (UINTVAL)SELF.get_integer() >> value;
983 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
985 VTABLE_set_integer_native(INTERP, dest, result);
989 VTABLE void i_bitwise_lsr(PMC *value) {
990 const INTVAL result = (UINTVAL)SELF.get_integer() >>
991 VTABLE_get_integer(INTERP, value);
992 SELF.set_integer_native(result);
995 VTABLE void i_bitwise_lsr_int(INTVAL value) {
996 const INTVAL result = (UINTVAL)SELF.get_integer() >> value;
997 SELF.set_integer_native(result);
1002 =item C<PMC *bitwise_shl(PMC *value, PMC *dest)>
1004 =item C<PMC *bitwise_shl_int(INTVAL value, PMC *dest)>
1006 Returns in C<*dest> the shift left of the scalar by C<*value>. A negative
1007 C<value> shifts right. The destination may become a C<BigInt> as a result.
1009 =item C<void i_bitwise_shl(PMC *value)>
1011 =item C<void i_bitwise_shl_int(INTVAL value)>
1013 Inplace shift left. A negative C<value> shifts right. SELF may become a
1014 C<BigInt> as a result.
1020 VTABLE PMC *bitwise_shl(PMC *value, PMC *dest) {
1021 return bitwise_left_shift_internal(INTERP, SELF, dest,
1022 VTABLE_get_integer(INTERP, value));
1025 VTABLE PMC *bitwise_shl_int(INTVAL value, PMC *dest) {
1026 return bitwise_left_shift_internal(INTERP, SELF, dest, value);
1029 VTABLE void i_bitwise_shl(PMC *value) {
1030 bitwise_left_shift_internal(INTERP, SELF, SELF,
1031 VTABLE_get_integer(INTERP, value));
1034 VTABLE void i_bitwise_shl_int(INTVAL value) {
1035 bitwise_left_shift_internal(INTERP, SELF, SELF, value);
1042 =head2 String Methods
1046 =item C<PMC *concatenate(PMC *value, PMC *dest)>
1048 =item C<PMC *concatenate_str(STRING *value, PMC *dest)>
1050 Returns in C<*dest> the result of concatenating the scalar and C<*value>.
1052 =item C<void concatenate(PMC *value)>
1054 =item C<void concatenate_str(STRING *value)>
1056 Concatenate the string C<value> in place.
1062 VTABLE PMC *concatenate(PMC *value, PMC *dest) {
1063 STRING * const s = Parrot_str_concat(INTERP, SELF.get_string(),
1064 VTABLE_get_string(INTERP, value), 0);
1066 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1068 VTABLE_set_string_native(INTERP, dest, s);
1072 VTABLE PMC *concatenate_str(STRING *value, PMC *dest) {
1073 STRING * const s = Parrot_str_concat(INTERP,
1074 SELF.get_string(), value, 0);
1076 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1078 VTABLE_set_string_native(INTERP, dest, s);
1082 VTABLE void i_concatenate(PMC *value) {
1083 STRING * const s = SELF.get_string();
1084 STRING * const v = VTABLE_get_string(INTERP, value);
1085 SELF.set_string_native(Parrot_str_append(INTERP, s, v));
1088 VTABLE void i_concatenate_str(STRING *value) {
1089 STRING * const s = SELF.get_string();
1090 SELF.set_string_native(Parrot_str_append(INTERP, s, value));
1095 =item C<PMC *repeat(PMC *value, PMC *dest)>
1097 =item C<PMC *repeat_int(INTVAL value, PMC *dest)>
1099 Returns in C<*dest> the result of repeating the scalar C<value> times.
1101 =item C<void i_repeat(PMC *value)>
1103 =item C<void i_repeat_int(INTVAL value)>
1105 Repeat the string C<SELF> in place C<value> times.
1111 VTABLE PMC *repeat(PMC *value, PMC *dest) {
1112 STRING * const s = SELF.get_string();
1113 const UINTVAL n = (UINTVAL)VTABLE_get_integer(INTERP, value);
1115 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1117 VTABLE_set_string_native(INTERP, dest,
1118 Parrot_str_repeat(INTERP, s, n));
1122 VTABLE PMC *repeat_int(INTVAL value, PMC *dest) {
1123 STRING * const s = SELF.get_string();
1124 const UINTVAL n = value;
1126 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1128 VTABLE_set_string_native(INTERP, dest,
1129 Parrot_str_repeat(INTERP, s, n));
1134 VTABLE void i_repeat(PMC *value) {
1135 STRING * const s = SELF.get_string();
1136 const UINTVAL n = (UINTVAL)VTABLE_get_integer(INTERP, value);
1137 SELF.set_string_native(Parrot_str_repeat(INTERP, s, n));
1140 VTABLE void i_repeat_int(INTVAL value) {
1141 STRING * const s = SELF.get_string();
1142 const UINTVAL n = value;
1143 SELF.set_string_native(Parrot_str_repeat(INTERP, s, n));
1152 =head2 Compare Methods
1156 =item C<INTVAL cmp_num(PMC *value)>
1158 Returns the result of comparing the floating-point values of the scalar
1165 MULTI INTVAL cmp_num(PMC *value) {
1166 /* XXX - Floating-point precision errors possible? */
1167 FLOATVAL diff = VTABLE_get_number(INTERP, value) -
1170 return FLOAT_IS_ZERO(diff) ? 0 : diff < 0.0 ? -1 : 1;
1175 =item C<INTVAL cmp_string(PMC *value)>
1177 Returns the result of comparing the string values of the scalar and
1184 MULTI INTVAL cmp_string(PMC *value) {
1185 return Parrot_str_compare(INTERP, SELF.get_string(),
1186 VTABLE_get_string(INTERP, value));
1191 =item C<INTVAL is_equal(PMC *value)>
1193 Returns whether the PMC is equal to C<*value>.
1200 MULTI INTVAL is_equal(PMC *value) {
1201 return (SELF->vtable == value->vtable
1202 && PMC_data(SELF) == PMC_data(value));
1208 =item C<INTVAL is_equal_num(PMC *value)>
1210 Returns whether the PMC is numerically equal to C<*value>.
1216 MULTI INTVAL is_equal_num(PMC *value) {
1217 return (VTABLE_get_number(INTERP, SELF) ==
1218 VTABLE_get_number(INTERP, value));
1223 =item C<INTVAL is_equal_string(PMC *value)>
1225 Returns whether the PMC has string equality with C<*value>.
1231 MULTI INTVAL is_equal_string(PMC *value) {
1232 return (0 != Parrot_str_equal(INTERP, VTABLE_get_string(INTERP, SELF),
1233 VTABLE_get_string(INTERP, value)));
1241 =head2 Logical Methods
1245 =item C<PMC *logical_or(PMC *value, PMC *dest)>
1247 Returns the result of the logical C<OR> of C<SELF> and C<value>, i.e. returns
1248 C<SELF> it is true or C<value>: C<dest> is alway ignored.
1254 VTABLE PMC *logical_or(PMC *value, PMC *dest) {
1255 if (SELF.get_bool())
1263 =item C< PMC *logical_and(PMC *value, PMC *dest)>
1265 Returns the result of the logical C<AND> of C<SELF> and C<value>, i.e.
1266 returns C<value> if C<SELF> is true else C<SELF>. C<dest> is always ignored.
1272 VTABLE PMC *logical_and(PMC *value, PMC *dest) {
1273 if (SELF.get_bool())
1281 =item C<PMC *logical_xor(PMC *value, PMC *dest)>
1283 Returns the result of the logical C<XOR> of C<SELF> and C<*value>.
1289 VTABLE PMC *logical_xor(PMC *value, PMC *dest) {
1290 const INTVAL my_bool = SELF.get_bool();
1291 const INTVAL value_bool = VTABLE_get_bool(INTERP, value);
1293 if (my_bool && ! value_bool)
1295 else if (value_bool && ! my_bool)
1298 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1299 VTABLE_set_bool(INTERP, dest, 0);
1305 =item C<PMC *logical_not(PMC *dest)>
1307 =item C<void i_logical_not()>
1309 Returns in C<*dest> the result of the logical negation of the scalar and
1316 VTABLE PMC *logical_not(PMC *dest) {
1317 const INTVAL a = ! SELF.get_bool();
1319 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1321 VTABLE_set_bool(INTERP, dest, a);
1325 VTABLE void i_logical_not() {
1326 VTABLE_set_bool(INTERP, SELF, ! SELF.get_bool());
1331 =item C<INTVAL defined()>
1333 Always returns true.
1339 VTABLE INTVAL defined() {
1345 =item C<STRING *substr_str(INTVAL offset, INTVAL length)>
1347 Returns the substring of length C<length> of the scalar starting at
1354 VTABLE STRING *substr_str(INTVAL offset, INTVAL length) {
1355 return Parrot_str_substr(INTERP, VTABLE_get_string(INTERP, SELF),
1356 offset, length, NULL, 0);
1361 =item C<void share_ro()>
1363 Sets this PMC as shared and read-only.
1368 VTABLE PMC *share_ro() {
1369 PMC *ret = pt_shared_fixup(INTERP, SELF);
1370 PMC * const _true = pmc_new(INTERP, enum_class_Integer);
1372 VTABLE_set_integer_native(INTERP, _true, 1);
1374 /* first set readonly */
1375 VTABLE_setprop(INTERP, ret, CONST_STRING(INTERP, "_ro"), _true);
1377 /* We're sharing this, so make sure it has a PMC_sync */
1378 Parrot_gc_add_pmc_sync(INTERP, ret);
1379 PObj_is_PMC_shared_SET(ret);
1381 /* XXX FIXME workaround lack of metadata sharing*/
1382 PMC_metadata(SELF) = NULL;
1399 * c-file-style: "parrot"
1401 * vim: expandtab shiftwidth=4: