Skip to content

Commit

Permalink
First stab at supporting :16<DEADBEEF> style numbers.
Browse files Browse the repository at this point in the history
  • Loading branch information
colomon committed Mar 20, 2010
1 parent 3075a5f commit 52ea36c
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 1 deletion.
13 changes: 13 additions & 0 deletions src/Perl6/Actions.pm
Expand Up @@ -2086,6 +2086,7 @@ method number:sym<numish>($/) {
method numish($/) {
if $<integer> { make PAST::Val.new( :value($<integer>.ast) ); }
elsif $<dec_number> { make $<dec_number>.ast; }
elsif $<rad_number> { make $<rad_number>.ast; }
else {
make PAST::Var.new( :name(~$/), :namespace(''), :scope('package') );
}
Expand Down Expand Up @@ -2127,6 +2128,18 @@ method dec_number($/) {
}
}

method rad_number($/) {
my $radix := +($<radix>.Str);
my $intpart := $<intpart>.Str;
my $fracpart := $<fracpart> ?? $<fracpart>.Str !! "0";
my $base := $<base> ?? $<base>.ast !! 0;
my $exp := $<exp> ?? $<exp>.ast !! 0;

make PAST::Op.new( :name('&radcalc'), :pasttype('call'),
$radix, $intpart, $fracpart, $base, $exp
);
}

method typename($/) {
my $past;

Expand Down
29 changes: 28 additions & 1 deletion src/Perl6/Grammar.pm
Expand Up @@ -938,7 +938,7 @@ token numish {
[
| <dec_number>
| <integer>
# | <rad_number>
| <rad_number>
| 'NaN' >>
| 'Inf' >>
| '+Inf' >>
Expand All @@ -952,6 +952,33 @@ token dec_number {
| $<coeff> = [ <int=.decint> ] <escale>
}

token rad_number {
<!before '::'> ':' $<radix> = [\d+] <.unsp>?
# {} # don't recurse in lexer
# :dba('number in radix notation')
[
|| '<'
$<intpart> = [ <[ 0..9 a..z A..Z ]>+ [ _ <[ 0..9 a..z A..Z ]>+ ]* ]
$<fracpart> = [ '.' <[ 0..9 a..z A..Z ]>+ [ _ <[ 0..9 a..z A..Z ]>+ ]* ]?
[ '*' <base=.radint> '**' <exp=.radint> ]?
'>'
# || <?before '['> <circumfix>
# || <?before '('> <circumfix>
|| <.panic: "Malformed radix number">
]
}

token radint {
[
| <integer>
# | <?before ':'\d> <rad_number> <?{
# defined $<rad_number><intpart>
# and
# not defined $<rad_number><fracpart>
# }>
]
}

token escale { <[Ee]> $<sign>=[<[+\-]>?] <decint> }

token typename {
Expand Down
78 changes: 78 additions & 0 deletions src/builtins/Num.pir
Expand Up @@ -117,6 +117,84 @@ Value type, so return self.

=cut

=item radcalc

=cut

.namespace []

.sub '&radcalc'
.param int radix
.param string intpart
.param string fracpart :optional
.param int has_fracpart :opt_flag
.param num base :optional
.param int has_base :opt_flag
.param num exp :optional
.param int has_exp :opt_flag
.local num result, fracdivisor, magnitude
.local pmc it

if radix <= 1 goto err_range
if radix > 36 goto err_range

result = 0.0
fracdivisor = 1.0

$P0 = split '', intpart
it = iter $P0

lp1: # Accumulate over decimal part
unless it goto ex1
$S0 = shift it
$S0 = downcase $S0
if $S0 == "_" goto lp1
$I0 = index "0123456789abcdefghijklmnopqrstuvwxyz", $S0
if $I0 == -1 goto err_char
$N0 = $I0
result *= radix
result += $N0
goto lp1

ex1:
unless has_fracpart goto nofracpart
$I0 = length fracpart
unless $I0 goto nofracpart
$P0 = split '', fracpart
$P99 = shift $P0 # remove the radix point

lp2: # Accumulate over fractional part, keep length
unless it goto ex2
$S0 = shift it
$S0 = downcase $S0
if $S0 == "_" goto lp2
$I0 = index "0123456789abcdefghijklmnopqrstuvwxyz", $S0
if $I0 == -1 goto err_char
$N0 = $I0

result *= radix
result += $N0
fracdivisor *= radix
goto lp2

ex2:
result /= fracdivisor

nofracpart:
unless has_base goto ret
magnitude = base ** exp
result *= magnitude
ret:
.return (result)

err_range:
die "radix out of range (2-36)"
err_char:
$S0 = concat "unrecognized character: ", $S0
die $S0
.end


# Local Variables:
# mode: pir
# fill-column: 100
Expand Down

0 comments on commit 52ea36c

Please sign in to comment.