Skip to content

Commit

Permalink
Merge pull request #2263 from leocassarani/sprinter-negative-int
Browse files Browse the repository at this point in the history
Extend the 1.9 Sprinter to handle negative numbers in hex, octal, binary
  • Loading branch information
dbussink committed Apr 9, 2013
2 parents 39c8659 + 157860a commit 9fed5da
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 79 deletions.
84 changes: 13 additions & 71 deletions kernel/common/sprinter.rb
Expand Up @@ -440,7 +440,6 @@ def push_width_value
end

def push_width(adjust=true)
yield if block_given?
if @width_static
raise ArgumentError, "width too big" unless @width_static.class == Fixnum
if adjust && @full_leader_size > 0
Expand All @@ -449,14 +448,6 @@ def push_width(adjust=true)
@g.push @width_static
end

if block_given?
@g.swap
@b.if_true do
@g.meta_push_1
@b.meta_op_minus
end
end

elsif @width_index
@g.push_local @width_index

Expand All @@ -473,30 +464,6 @@ def push_width(adjust=true)
end
end

n = adjust ? @full_leader_size : 0
if block_given?
adjusted = @g.new_label

@g.swap
@b.if_true do
@g.push n + 1
@b.meta_op_minus
if n > 0
@g.goto adjusted
end
end

if n > 0
@g.push n
@b.meta_op_minus
adjusted.set!
end

elsif n > 0
@g.push n
@b.meta_op_minus
end

else
raise "push without a width"

Expand All @@ -512,7 +479,6 @@ def push_precision_value
end

def push_precision
yield if block_given?
if @prec_static
raise ArgumentError, "precision too big" unless @prec_static.class == Fixnum
@g.push @prec_static
Expand All @@ -537,14 +503,6 @@ def push_precision
raise "push without a precision"

end

if block_given?
@g.swap
@b.if_true do
@g.meta_push_1
@b.meta_op_minus
end
end
end

def push_format_string
Expand Down Expand Up @@ -607,32 +565,24 @@ def justify_width(adjust=true)
end
end

def zero_pad?
@has_precision || (@has_width && @f_zero)
end

def zero_pad(pad="0", &readjust)
def zero_pad(pad="0")
if @has_precision
push_precision(&readjust)
push_precision

# let the caller adjust the width if needed
yield if block_given?

@g.push_literal pad
@g.send :rjust, 2
elsif @has_width && @f_zero
push_width true, &readjust
push_width true
@g.push_literal pad
@g.send :rjust, 2
end
end

def width?
@has_width
end

attr_reader :width_static

def precision?
@has_precision
end

def leader?
@full_leader_size > 0
end
Expand All @@ -650,7 +600,7 @@ def string_justify

justify_width

if precision?
if @has_precision
@g.meta_push_0
push_precision
@g.send :[], 2
Expand Down Expand Up @@ -761,15 +711,15 @@ def bytecode
@b.append_str
end

if precision?
if @has_precision
@g.push :self
@g.push_stack_local val_idx

push_precision_value

@g.send :digit_expand_precision, 2

if width?
if @has_width
@g.push :self
@g.swap
push_width_value
Expand All @@ -783,7 +733,7 @@ def bytecode

@b.append_str

elsif width?
elsif @has_width
@g.push :self
@g.push_stack_local val_idx

Expand Down Expand Up @@ -857,15 +807,7 @@ def bytecode
end

padding = format_negative_int(radix)

if zero_pad?
zero_pad padding

elsif !precision? && !@f_zero
@g.push_literal ".."
@g.string_dup
@g.string_append
end
pad_negative_int(padding)

have_formatted.set!
end
Expand Down Expand Up @@ -901,7 +843,7 @@ def bytecode
end


if precision? || !@f_zero
if @has_precision || !@f_zero
justify_width false
end

Expand Down
17 changes: 17 additions & 0 deletions kernel/common/sprinter18.rb
Expand Up @@ -8,6 +8,12 @@ class Builder
def encode_result
end

class Atom
def zero_pad?
@has_precision || (@has_width && @f_zero)
end
end

class CharAtom < Atom
def bytecode
push_value
Expand Down Expand Up @@ -70,6 +76,17 @@ def expand_with_width
end

class ExtIntegerAtom < Atom
def pad_negative_int(padding)
if zero_pad?
zero_pad(padding)

elsif !@has_precision && !@f_zero
@g.push_literal ".."
@g.string_dup
@g.string_append
end
end

def prepend_prefix_bytecode
prepend_prefix
end
Expand Down
12 changes: 12 additions & 0 deletions kernel/common/sprinter19.rb
Expand Up @@ -86,6 +86,18 @@ def expand_with_width
end

class ExtIntegerAtom < Atom
def pad_negative_int(padding)
zero_pad(padding) do
# decrease the width by 2 to account for the ".." below
@g.meta_push_2
@b.meta_op_minus
end

@g.push_literal ".."
@g.string_dup
@g.string_append
end

def prepend_prefix_bytecode
skip_prefix = @g.new_label

Expand Down
4 changes: 0 additions & 4 deletions spec/tags/19/ruby/core/string/modulo_tags.txt
@@ -1,5 +1 @@
fails:String#% supports binary formats using %b for negative numbers
fails:String#% supports octal formats using %o for negative numbers
fails:String#% supports negative bignums with %u or %d
fails:String#% supports hex formats using %x for negative numbers
fails:String#% supports hex formats using %X for negative numbers
4 changes: 0 additions & 4 deletions spec/tags/20/ruby/core/string/modulo_tags.txt
@@ -1,5 +1 @@
fails:String#% supports binary formats using %b for negative numbers
fails:String#% supports octal formats using %o for negative numbers
fails:String#% supports negative bignums with %u or %d
fails:String#% supports hex formats using %x for negative numbers
fails:String#% supports hex formats using %X for negative numbers

0 comments on commit 9fed5da

Please sign in to comment.