Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add a few more useful option flags to nqp_radix opcode.
  • Loading branch information
pmichaud committed Jul 14, 2011
1 parent 0eea302 commit 134720b
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 18 deletions.
1 change: 1 addition & 0 deletions src/PAST/NQP.pir
Expand Up @@ -379,6 +379,7 @@ entry to produce the node to be returned.
maphash['floor_n'] = 'floor__NN'
maphash['ln_n'] = 'ln__Nn'
maphash['sqrt_n'] = 'sqrt__Nn'
maphash['radix'] = 'nqp_radix__Pisii'

# string opcodes
maphash['chars'] = 'length__Is'
Expand Down
44 changes: 26 additions & 18 deletions src/ops/nqp.ops
Expand Up @@ -1274,39 +1274,46 @@ Convert string $3 into a number starting at offset $4 and using radix $2.
The result of the conversion returns a FixedFloatArray PMC with
out[0] = converted value
out[1] = radix ** (number of digits converted)
out[2] = offset after consuming digits
out[2] = offset after consuming digits, -1 if no digits consumed
The opcode skips single underscores between pairs of digits, per the Perl 6
specification. Leading spaces are not skipped, nor does it honor a leading
plus or minus sign.
specification.

If $5 is set, then trailing zeroes are not included in the conversion.
(This is useful when converting values following a decimal point, for
example.)
The $5 flags is a bitmask that modifies the parse and/or result:
0x01: negate the result (useful if you've already parsed a minus)
0x02: parse a leading +/- and negate the result on -
0x04: parse trailing zeroes but do not include in result
(for parsing values after a decimal point)

=cut

*/

inline op nqp_radix(out PMC, in INT, in STR, in INT, in INT) :base_core {
PMC *out;
INTVAL radix = $2;
STRING *str = $3;
INTVAL pos = $4;
INTVAL flag = $5;
INTVAL chars = Parrot_str_length(interp, str);
FLOATVAL value = 0.0;
FLOATVAL base = 1.0;
FLOATVAL zvalue = value;
FLOATVAL zbase = base;
INTVAL zpos = pos;
INTVAL ch;
INTVAL radix = $2;
STRING *str = $3;
INTVAL zpos = $4;
INTVAL flags = $5;
FLOATVAL zvalue = 0.0;
FLOATVAL zbase = 1.0;
INTVAL chars = Parrot_str_length(interp, str);
FLOATVAL value = zvalue;
FLOATVAL base = zbase;
INTVAL pos = -1;
INTVAL ch;
int neg = 0;

if (radix > 36) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"Cannot convert radix of %d (max 36)", radix);
}

ch = (zpos < chars) ? STRING_ord(interp, str, zpos) : 0;
if ((flags & 0x02) && (ch == '+' || ch == '-')) {
neg = (ch == '-');
zpos++;
ch = (zpos < chars) ? STRING_ord(interp, str, zpos) : 0;
}
while (zpos < chars) {
if (ch >= '0' && ch <= '9') ch = ch - '0';
else if (ch >= 'a' && ch <= 'z') ch = ch - 'a' + 10;
Expand All @@ -1316,7 +1323,7 @@ inline op nqp_radix(out PMC, in INT, in STR, in INT, in INT) :base_core {
zvalue = zvalue * radix + ch;
zbase = zbase * radix;
zpos++; pos = zpos;
if (ch != 0 || !flag) { value=zvalue; base=zbase; }
if (ch != 0 || (flags & 0x04 == 0)) { value=zvalue; base=zbase; }
if (zpos >= chars) break;
ch = STRING_ord(interp, str, zpos);
if (ch != '_') continue;
Expand All @@ -1325,6 +1332,7 @@ inline op nqp_radix(out PMC, in INT, in STR, in INT, in INT) :base_core {
ch = STRING_ord(interp, str, zpos);
}

if (neg || flags & 0x01) { value = -value; }
out = pmc_new(interp, enum_class_FixedFloatArray);
VTABLE_set_integer_native(interp, out, 3);
VTABLE_set_number_keyed_int(interp, out, 0, value);
Expand Down

0 comments on commit 134720b

Please sign in to comment.