first commit
This commit is contained in:
+39
@@ -0,0 +1,39 @@
|
||||
class BasicObject
|
||||
def !=(other)
|
||||
if self == other
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Module
|
||||
# 15.2.2.4.12
|
||||
def attr_accessor(*names)
|
||||
attr_reader(*names)
|
||||
attr_writer(*names)
|
||||
end
|
||||
# 15.2.2.4.11
|
||||
alias attr attr_reader
|
||||
#def attr(name)
|
||||
# attr_reader(name)
|
||||
#end
|
||||
|
||||
# 15.2.2.4.27
|
||||
def include(*args)
|
||||
args.reverse.each do |m|
|
||||
m.append_features(self)
|
||||
m.included(self)
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
def prepend(*args)
|
||||
args.reverse.each do |m|
|
||||
m.prepend_features(self)
|
||||
m.prepended(self)
|
||||
end
|
||||
self
|
||||
end
|
||||
end
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
# ISO 15.2.24
|
||||
class ArgumentError < StandardError
|
||||
end
|
||||
|
||||
# ISO 15.2.25 says "LocalJumpError < StandardError"
|
||||
class LocalJumpError < ScriptError
|
||||
end
|
||||
|
||||
# ISO 15.2.26
|
||||
class RangeError < StandardError
|
||||
end
|
||||
|
||||
class FloatDomainError < RangeError
|
||||
end
|
||||
|
||||
# ISO 15.2.26
|
||||
class RegexpError < StandardError
|
||||
end
|
||||
|
||||
# ISO 15.2.29
|
||||
class TypeError < StandardError
|
||||
end
|
||||
|
||||
# ISO 15.2.31
|
||||
class NameError < StandardError
|
||||
attr_accessor :name
|
||||
|
||||
def initialize(message=nil, name=nil)
|
||||
@name = name
|
||||
super(message)
|
||||
end
|
||||
end
|
||||
|
||||
# ISO 15.2.32
|
||||
class NoMethodError < NameError
|
||||
attr_reader :args
|
||||
|
||||
def initialize(message=nil, name=nil, args=nil)
|
||||
@args = args
|
||||
super message, name
|
||||
end
|
||||
end
|
||||
|
||||
# ISO 15.2.33
|
||||
class IndexError < StandardError
|
||||
end
|
||||
|
||||
class KeyError < IndexError
|
||||
end
|
||||
|
||||
class NotImplementedError < ScriptError
|
||||
end
|
||||
|
||||
class FrozenError < RuntimeError
|
||||
end
|
||||
|
||||
class StopIteration < IndexError
|
||||
attr_accessor :result
|
||||
end
|
||||
+271
@@ -0,0 +1,271 @@
|
||||
# coding: utf-8
|
||||
##
|
||||
# Array
|
||||
#
|
||||
# ISO 15.2.12
|
||||
class Array
|
||||
|
||||
##
|
||||
# Calls the given block for each element of +self+
|
||||
# and pass the respective element.
|
||||
#
|
||||
# ISO 15.2.12.5.10
|
||||
# def each(&block)
|
||||
# return to_enum :each unless block
|
||||
|
||||
# idx = 0
|
||||
# while idx < length
|
||||
# block.call(self[idx])
|
||||
# idx += 1
|
||||
# end
|
||||
# self
|
||||
# end
|
||||
|
||||
##
|
||||
# Calls the given block for each element of +self+
|
||||
# and pass the index of the respective element.
|
||||
#
|
||||
# ISO 15.2.12.5.11
|
||||
def each_index(&block)
|
||||
return to_enum :each_index unless block
|
||||
|
||||
idx = 0
|
||||
while idx < length
|
||||
block.call(idx)
|
||||
idx += 1
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Calls the given block for each element of +self+
|
||||
# and pass the respective element. Each element will
|
||||
# be replaced by the resulting values.
|
||||
#
|
||||
# ISO 15.2.12.5.7
|
||||
def collect!(&block)
|
||||
return to_enum :collect! unless block
|
||||
|
||||
idx = 0
|
||||
len = size
|
||||
while idx < len
|
||||
self[idx] = block.call self[idx]
|
||||
idx += 1
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Alias for collect!
|
||||
#
|
||||
# ISO 15.2.12.5.20
|
||||
alias map! collect!
|
||||
|
||||
##
|
||||
# Private method for Array creation.
|
||||
#
|
||||
# ISO 15.2.12.5.15
|
||||
def initialize(size=0, obj=nil, &block)
|
||||
size = size.__to_int
|
||||
raise ArgumentError, "negative array size" if size < 0
|
||||
|
||||
self.clear
|
||||
if size > 0
|
||||
self[size - 1] = nil # allocate
|
||||
|
||||
idx = 0
|
||||
while idx < size
|
||||
self[idx] = (block)? block.call(idx): obj
|
||||
idx += 1
|
||||
end
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
def _inspect(recur_list)
|
||||
size = self.size
|
||||
return "[]" if size == 0
|
||||
return "[...]" if recur_list[self.object_id]
|
||||
recur_list[self.object_id] = true
|
||||
ary=[]
|
||||
i=0
|
||||
while i<size
|
||||
ary<<self[i]._inspect(recur_list)
|
||||
i+=1
|
||||
end
|
||||
"["+ary.join(", ")+"]"
|
||||
end
|
||||
##
|
||||
# Return the contents of this array as a string.
|
||||
#
|
||||
# ISO 15.2.12.5.31 (x)
|
||||
def inspect
|
||||
self._inspect({})
|
||||
end
|
||||
# ISO 15.2.12.5.32 (x)
|
||||
alias to_s inspect
|
||||
|
||||
##
|
||||
# Equality---Two arrays are equal if they contain the same number
|
||||
# of elements and if each element is equal to (according to
|
||||
# Object.==) the corresponding element in the other array.
|
||||
#
|
||||
# ISO 15.2.12.5.33 (x)
|
||||
def ==(other)
|
||||
other = self.__ary_eq(other)
|
||||
return false if other == false
|
||||
return true if other == true
|
||||
len = self.size
|
||||
i = 0
|
||||
while i < len
|
||||
return false if self[i] != other[i]
|
||||
i += 1
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
##
|
||||
# Returns <code>true</code> if +self+ and _other_ are the same object,
|
||||
# or are both arrays with the same content.
|
||||
#
|
||||
# ISO 15.2.12.5.34 (x)
|
||||
def eql?(other)
|
||||
other = self.__ary_eq(other)
|
||||
return false if other == false
|
||||
return true if other == true
|
||||
len = self.size
|
||||
i = 0
|
||||
while i < len
|
||||
return false unless self[i].eql?(other[i])
|
||||
i += 1
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
##
|
||||
# Comparison---Returns an integer (-1, 0, or +1)
|
||||
# if this array is less than, equal to, or greater than <i>other_ary</i>.
|
||||
# Each object in each array is compared (using <=>). If any value isn't
|
||||
# equal, then that inequality is the return value. If all the
|
||||
# values found are equal, then the return is based on a
|
||||
# comparison of the array lengths. Thus, two arrays are
|
||||
# "equal" according to <code>Array#<=></code> if and only if they have
|
||||
# the same length and the value of each element is equal to the
|
||||
# value of the corresponding element in the other array.
|
||||
#
|
||||
# ISO 15.2.12.5.36 (x)
|
||||
def <=>(other)
|
||||
other = self.__ary_cmp(other)
|
||||
return 0 if 0 == other
|
||||
return nil if nil == other
|
||||
|
||||
len = self.size
|
||||
n = other.size
|
||||
len = n if len > n
|
||||
i = 0
|
||||
while i < len
|
||||
n = (self[i] <=> other[i])
|
||||
return n if n.nil? || n != 0
|
||||
i += 1
|
||||
end
|
||||
len = self.size - other.size
|
||||
if len == 0
|
||||
0
|
||||
elsif len > 0
|
||||
1
|
||||
else
|
||||
-1
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Delete element with index +key+
|
||||
def delete(key, &block)
|
||||
while i = self.index(key)
|
||||
self.delete_at(i)
|
||||
ret = key
|
||||
end
|
||||
return block.call if ret.nil? && block
|
||||
ret
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Array is enumerable
|
||||
class Array
|
||||
# ISO 15.2.12.3
|
||||
include Enumerable
|
||||
|
||||
##
|
||||
# Sort all elements and replace +self+ with these
|
||||
# elements.
|
||||
def sort!(&block)
|
||||
stack = [ [ 0, self.size - 1 ] ]
|
||||
until stack.empty?
|
||||
left, mid, right = stack.pop
|
||||
if right == nil
|
||||
right = mid
|
||||
# sort self[left..right]
|
||||
if left < right
|
||||
if left + 1 == right
|
||||
lval = self[left]
|
||||
rval = self[right]
|
||||
cmp = if block then block.call(lval,rval) else lval <=> rval end
|
||||
if cmp.nil?
|
||||
raise ArgumentError, "comparison of #{lval.inspect} and #{rval.inspect} failed"
|
||||
end
|
||||
if cmp > 0
|
||||
self[left] = rval
|
||||
self[right] = lval
|
||||
end
|
||||
else
|
||||
mid = ((left + right + 1) / 2).floor
|
||||
stack.push [ left, mid, right ]
|
||||
stack.push [ mid, right ]
|
||||
stack.push [ left, (mid - 1) ] if left < mid - 1
|
||||
end
|
||||
end
|
||||
else
|
||||
lary = self[left, mid - left]
|
||||
lsize = lary.size
|
||||
|
||||
# The entity sharing between lary and self may cause a large memory
|
||||
# copy operation in the merge loop below. This harmless operation
|
||||
# cancels the sharing and provides a huge performance gain.
|
||||
lary[0] = lary[0]
|
||||
|
||||
# merge
|
||||
lidx = 0
|
||||
ridx = mid
|
||||
(left..right).each { |i|
|
||||
if lidx >= lsize
|
||||
break
|
||||
elsif ridx > right
|
||||
self[i, lsize - lidx] = lary[lidx, lsize - lidx]
|
||||
break
|
||||
else
|
||||
lval = lary[lidx]
|
||||
rval = self[ridx]
|
||||
cmp = if block then block.call(lval,rval) else lval <=> rval end
|
||||
if cmp.nil?
|
||||
raise ArgumentError, "comparison of #{lval.inspect} and #{rval.inspect} failed"
|
||||
end
|
||||
if cmp <= 0
|
||||
self[i] = lval
|
||||
lidx += 1
|
||||
else
|
||||
self[i] = rval
|
||||
ridx += 1
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
def sort(&block)
|
||||
self.dup.sort!(&block)
|
||||
end
|
||||
end
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
##
|
||||
# Comparable
|
||||
#
|
||||
# ISO 15.3.3
|
||||
module Comparable
|
||||
|
||||
##
|
||||
# Return true if +self+ is less
|
||||
# than +other+. Otherwise return
|
||||
# false.
|
||||
#
|
||||
# ISO 15.3.3.2.1
|
||||
def < other
|
||||
cmp = self <=> other
|
||||
if cmp.nil?
|
||||
raise ArgumentError, "comparison of #{self.class} with #{other.class} failed"
|
||||
end
|
||||
cmp < 0
|
||||
end
|
||||
|
||||
##
|
||||
# Return true if +self+ is less
|
||||
# than or equal to +other+.
|
||||
# Otherwise return false.
|
||||
#
|
||||
# ISO 15.3.3.2.2
|
||||
def <= other
|
||||
cmp = self <=> other
|
||||
if cmp.nil?
|
||||
raise ArgumentError, "comparison of #{self.class} with #{other.class} failed"
|
||||
end
|
||||
cmp <= 0
|
||||
end
|
||||
|
||||
##
|
||||
# Return true if +self+ is equal
|
||||
# to +other+. Otherwise return
|
||||
# false.
|
||||
#
|
||||
# ISO 15.3.3.2.3
|
||||
def == other
|
||||
cmp = self <=> other
|
||||
cmp == 0
|
||||
end
|
||||
|
||||
##
|
||||
# Return true if +self+ is greater
|
||||
# than +other+. Otherwise return
|
||||
# false.
|
||||
#
|
||||
# ISO 15.3.3.2.4
|
||||
def > other
|
||||
cmp = self <=> other
|
||||
if cmp.nil?
|
||||
raise ArgumentError, "comparison of #{self.class} with #{other.class} failed"
|
||||
end
|
||||
cmp > 0
|
||||
end
|
||||
|
||||
##
|
||||
# Return true if +self+ is greater
|
||||
# than or equal to +other+.
|
||||
# Otherwise return false.
|
||||
#
|
||||
# ISO 15.3.3.2.5
|
||||
def >= other
|
||||
cmp = self <=> other
|
||||
if cmp.nil?
|
||||
raise ArgumentError, "comparison of #{self.class} with #{other.class} failed"
|
||||
end
|
||||
cmp >= 0
|
||||
end
|
||||
|
||||
##
|
||||
# Return true if +self+ is greater
|
||||
# than or equal to +min+ and
|
||||
# less than or equal to +max+.
|
||||
# Otherwise return false.
|
||||
#
|
||||
# ISO 15.3.3.2.6
|
||||
def between?(min, max)
|
||||
self >= min and self <= max
|
||||
end
|
||||
end
|
||||
+353
@@ -0,0 +1,353 @@
|
||||
##
|
||||
# Enumerable
|
||||
#
|
||||
# The <code>Enumerable</code> mixin provides collection classes with
|
||||
# several traversal and searching methods, and with the ability to
|
||||
# sort. The class must provide a method `each`, which
|
||||
# yields successive members of the collection. If
|
||||
# {Enumerable#max}, {#min}, or
|
||||
# {#sort} is used, the objects in the collection must also
|
||||
# implement a meaningful `<=>` operator, as these methods
|
||||
# rely on an ordering between members of the collection.
|
||||
#
|
||||
# @ISO 15.3.2
|
||||
module Enumerable
|
||||
|
||||
NONE = Object.new
|
||||
|
||||
##
|
||||
# Call the given block for each element
|
||||
# which is yield by +each+. Return false
|
||||
# if one block value is false. Otherwise
|
||||
# return true. If no block is given and
|
||||
# +self+ is false return false.
|
||||
#
|
||||
# ISO 15.3.2.2.1
|
||||
def all?(&block)
|
||||
if block
|
||||
self.each{|*val| return false unless block.call(*val)}
|
||||
else
|
||||
self.each{|*val| return false unless val.__svalue}
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
##
|
||||
# Call the given block for each element
|
||||
# which is yield by +each+. Return true
|
||||
# if one block value is true. Otherwise
|
||||
# return false. If no block is given and
|
||||
# +self+ is true object return true.
|
||||
#
|
||||
# ISO 15.3.2.2.2
|
||||
def any?(&block)
|
||||
if block
|
||||
self.each{|*val| return true if block.call(*val)}
|
||||
else
|
||||
self.each{|*val| return true if val.__svalue}
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
##
|
||||
# Call the given block for each element
|
||||
# which is yield by +each+. Append all
|
||||
# values of each block together and
|
||||
# return this value.
|
||||
#
|
||||
# ISO 15.3.2.2.3
|
||||
def collect(&block)
|
||||
return to_enum :collect unless block
|
||||
|
||||
ary = []
|
||||
self.each{|*val| ary.push(block.call(*val))}
|
||||
ary
|
||||
end
|
||||
|
||||
##
|
||||
# Return the first element for which
|
||||
# value from the block is true. If no
|
||||
# object matches, calls +ifnone+ and
|
||||
# returns its result. Otherwise returns
|
||||
# +nil+.
|
||||
#
|
||||
# ISO 15.3.2.2.4
|
||||
def detect(ifnone=nil, &block)
|
||||
return to_enum :detect, ifnone unless block
|
||||
|
||||
self.each{|*val|
|
||||
if block.call(*val)
|
||||
return val.__svalue
|
||||
end
|
||||
}
|
||||
ifnone.call unless ifnone.nil?
|
||||
end
|
||||
|
||||
##
|
||||
# Call the given block for each element
|
||||
# which is yield by +each+. Pass an
|
||||
# index to the block which starts at 0
|
||||
# and increase by 1 for each element.
|
||||
#
|
||||
# ISO 15.3.2.2.5
|
||||
def each_with_index(&block)
|
||||
return to_enum :each_with_index unless block
|
||||
|
||||
i = 0
|
||||
self.each{|*val|
|
||||
block.call(val.__svalue, i)
|
||||
i += 1
|
||||
}
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Return an array of all elements which
|
||||
# are yield by +each+.
|
||||
#
|
||||
# ISO 15.3.2.2.6
|
||||
def entries
|
||||
ary = []
|
||||
self.each{|*val|
|
||||
# __svalue is an internal method
|
||||
ary.push val.__svalue
|
||||
}
|
||||
ary
|
||||
end
|
||||
|
||||
##
|
||||
# Alias for find
|
||||
#
|
||||
# ISO 15.3.2.2.7
|
||||
alias find detect
|
||||
|
||||
##
|
||||
# Call the given block for each element
|
||||
# which is yield by +each+. Return an array
|
||||
# which contains all elements whose block
|
||||
# value was true.
|
||||
#
|
||||
# ISO 15.3.2.2.8
|
||||
def find_all(&block)
|
||||
return to_enum :find_all unless block
|
||||
|
||||
ary = []
|
||||
self.each{|*val|
|
||||
ary.push(val.__svalue) if block.call(*val)
|
||||
}
|
||||
ary
|
||||
end
|
||||
|
||||
##
|
||||
# Call the given block for each element
|
||||
# which is yield by +each+ and which return
|
||||
# value was true when invoking === with
|
||||
# +pattern+. Return an array with all
|
||||
# elements or the respective block values.
|
||||
#
|
||||
# ISO 15.3.2.2.9
|
||||
def grep(pattern, &block)
|
||||
ary = []
|
||||
self.each{|*val|
|
||||
sv = val.__svalue
|
||||
if pattern === sv
|
||||
ary.push((block)? block.call(*val): sv)
|
||||
end
|
||||
}
|
||||
ary
|
||||
end
|
||||
|
||||
##
|
||||
# Return true if at least one element which
|
||||
# is yield by +each+ returns a true value
|
||||
# by invoking == with +obj+. Otherwise return
|
||||
# false.
|
||||
#
|
||||
# ISO 15.3.2.2.10
|
||||
def include?(obj)
|
||||
self.each{|*val|
|
||||
return true if val.__svalue == obj
|
||||
}
|
||||
false
|
||||
end
|
||||
|
||||
##
|
||||
# Call the given block for each element
|
||||
# which is yield by +each+. Return value
|
||||
# is the sum of all block values. Pass
|
||||
# to each block the current sum and the
|
||||
# current element.
|
||||
#
|
||||
# ISO 15.3.2.2.11
|
||||
def inject(*args, &block)
|
||||
raise ArgumentError, "too many arguments" if args.size > 2
|
||||
if Symbol === args[-1]
|
||||
sym = args[-1]
|
||||
block = ->(x,y){x.__send__(sym,y)}
|
||||
args.pop
|
||||
end
|
||||
if args.empty?
|
||||
flag = true # no initial argument
|
||||
result = nil
|
||||
else
|
||||
flag = false
|
||||
result = args[0]
|
||||
end
|
||||
self.each{|*val|
|
||||
val = val.__svalue
|
||||
if flag
|
||||
# push first element as initial
|
||||
flag = false
|
||||
result = val
|
||||
else
|
||||
result = block.call(result, val)
|
||||
end
|
||||
}
|
||||
result
|
||||
end
|
||||
alias reduce inject
|
||||
|
||||
##
|
||||
# Alias for collect
|
||||
#
|
||||
# ISO 15.3.2.2.12
|
||||
alias map collect
|
||||
|
||||
##
|
||||
# Return the maximum value of all elements
|
||||
# yield by +each+. If no block is given <=>
|
||||
# will be invoked to define this value. If
|
||||
# a block is given it will be used instead.
|
||||
#
|
||||
# ISO 15.3.2.2.13
|
||||
def max(&block)
|
||||
flag = true # 1st element?
|
||||
result = nil
|
||||
self.each{|*val|
|
||||
val = val.__svalue
|
||||
if flag
|
||||
# 1st element
|
||||
result = val
|
||||
flag = false
|
||||
else
|
||||
if block
|
||||
result = val if block.call(val, result) > 0
|
||||
else
|
||||
result = val if (val <=> result) > 0
|
||||
end
|
||||
end
|
||||
}
|
||||
result
|
||||
end
|
||||
|
||||
##
|
||||
# Return the minimum value of all elements
|
||||
# yield by +each+. If no block is given <=>
|
||||
# will be invoked to define this value. If
|
||||
# a block is given it will be used instead.
|
||||
#
|
||||
# ISO 15.3.2.2.14
|
||||
def min(&block)
|
||||
flag = true # 1st element?
|
||||
result = nil
|
||||
self.each{|*val|
|
||||
val = val.__svalue
|
||||
if flag
|
||||
# 1st element
|
||||
result = val
|
||||
flag = false
|
||||
else
|
||||
if block
|
||||
result = val if block.call(val, result) < 0
|
||||
else
|
||||
result = val if (val <=> result) < 0
|
||||
end
|
||||
end
|
||||
}
|
||||
result
|
||||
end
|
||||
|
||||
##
|
||||
# Alias for include?
|
||||
#
|
||||
# ISO 15.3.2.2.15
|
||||
alias member? include?
|
||||
|
||||
##
|
||||
# Call the given block for each element
|
||||
# which is yield by +each+. Return an
|
||||
# array which contains two arrays. The
|
||||
# first array contains all elements
|
||||
# whose block value was true. The second
|
||||
# array contains all elements whose
|
||||
# block value was false.
|
||||
#
|
||||
# ISO 15.3.2.2.16
|
||||
def partition(&block)
|
||||
return to_enum :partition unless block
|
||||
|
||||
ary_T = []
|
||||
ary_F = []
|
||||
self.each{|*val|
|
||||
if block.call(*val)
|
||||
ary_T.push(val.__svalue)
|
||||
else
|
||||
ary_F.push(val.__svalue)
|
||||
end
|
||||
}
|
||||
[ary_T, ary_F]
|
||||
end
|
||||
|
||||
##
|
||||
# Call the given block for each element
|
||||
# which is yield by +each+. Return an
|
||||
# array which contains only the elements
|
||||
# whose block value was false.
|
||||
#
|
||||
# ISO 15.3.2.2.17
|
||||
def reject(&block)
|
||||
return to_enum :reject unless block
|
||||
|
||||
ary = []
|
||||
self.each{|*val|
|
||||
ary.push(val.__svalue) unless block.call(*val)
|
||||
}
|
||||
ary
|
||||
end
|
||||
|
||||
##
|
||||
# Alias for find_all.
|
||||
#
|
||||
# ISO 15.3.2.2.18
|
||||
alias select find_all
|
||||
|
||||
##
|
||||
# Return a sorted array of all elements
|
||||
# which are yield by +each+. If no block
|
||||
# is given <=> will be invoked on each
|
||||
# element to define the order. Otherwise
|
||||
# the given block will be used for
|
||||
# sorting.
|
||||
#
|
||||
# ISO 15.3.2.2.19
|
||||
def sort(&block)
|
||||
self.map{|*val| val.__svalue}.sort(&block)
|
||||
end
|
||||
|
||||
##
|
||||
# Alias for entries.
|
||||
#
|
||||
# ISO 15.3.2.2.20
|
||||
alias to_a entries
|
||||
|
||||
# redefine #hash 15.3.1.3.15
|
||||
def hash
|
||||
h = 12347
|
||||
i = 0
|
||||
self.each do |e|
|
||||
h = __update_hash(h, i, e.hash)
|
||||
i += 1
|
||||
end
|
||||
h
|
||||
end
|
||||
end
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
##
|
||||
# Hash
|
||||
#
|
||||
# ISO 15.2.13
|
||||
class Hash
|
||||
##
|
||||
# Equality---Two hashes are equal if they each contain the same number
|
||||
# of keys and if each key-value pair is equal to (according to
|
||||
# <code>Object#==</code>) the corresponding elements in the other
|
||||
# hash.
|
||||
#
|
||||
# ISO 15.2.13.4.1
|
||||
def ==(hash)
|
||||
return true if self.equal?(hash)
|
||||
unless Hash === hash
|
||||
return false
|
||||
end
|
||||
return false if self.size != hash.size
|
||||
self.each do |k,v|
|
||||
return false unless hash.key?(k)
|
||||
return false unless self[k] == hash[k]
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
##
|
||||
# Returns <code>true</code> if <i>hash</i> and <i>other</i> are
|
||||
# both hashes with the same content compared by eql?.
|
||||
#
|
||||
# ISO 15.2.13.4.32 (x)
|
||||
def eql?(hash)
|
||||
return true if self.equal?(hash)
|
||||
unless Hash === hash
|
||||
return false
|
||||
end
|
||||
return false if self.size != hash.size
|
||||
self.each do |k,v|
|
||||
return false unless hash.key?(k)
|
||||
return false unless self[k].eql?(hash[k])
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
##
|
||||
# Delete the element with the key +key+.
|
||||
# Return the value of the element if +key+
|
||||
# was found. Return nil if nothing was
|
||||
# found. If a block is given, call the
|
||||
# block with the value of the element.
|
||||
#
|
||||
# ISO 15.2.13.4.8
|
||||
def delete(key, &block)
|
||||
if block && !self.has_key?(key)
|
||||
return block.call(key)
|
||||
end
|
||||
self.__delete(key)
|
||||
end
|
||||
|
||||
##
|
||||
# Calls the given block for each element of +self+
|
||||
# and pass the key and value of each element.
|
||||
#
|
||||
# call-seq:
|
||||
# hsh.each {| key, value | block } -> hsh
|
||||
# hsh.each_pair {| key, value | block } -> hsh
|
||||
# hsh.each -> an_enumerator
|
||||
# hsh.each_pair -> an_enumerator
|
||||
#
|
||||
#
|
||||
# If no block is given, an enumerator is returned instead.
|
||||
#
|
||||
# h = { "a" => 100, "b" => 200 }
|
||||
# h.each {|key, value| puts "#{key} is #{value}" }
|
||||
#
|
||||
# <em>produces:</em>
|
||||
#
|
||||
# a is 100
|
||||
# b is 200
|
||||
#
|
||||
# ISO 15.2.13.4.9
|
||||
def each(&block)
|
||||
return to_enum :each unless block
|
||||
|
||||
keys = self.keys
|
||||
vals = self.values
|
||||
len = self.size
|
||||
i = 0
|
||||
while i < len
|
||||
block.call [keys[i], vals[i]]
|
||||
i += 1
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Calls the given block for each element of +self+
|
||||
# and pass the key of each element.
|
||||
#
|
||||
# call-seq:
|
||||
# hsh.each_key {| key | block } -> hsh
|
||||
# hsh.each_key -> an_enumerator
|
||||
#
|
||||
# If no block is given, an enumerator is returned instead.
|
||||
#
|
||||
# h = { "a" => 100, "b" => 200 }
|
||||
# h.each_key {|key| puts key }
|
||||
#
|
||||
# <em>produces:</em>
|
||||
#
|
||||
# a
|
||||
# b
|
||||
#
|
||||
# ISO 15.2.13.4.10
|
||||
def each_key(&block)
|
||||
return to_enum :each_key unless block
|
||||
|
||||
self.keys.each{|k| block.call(k)}
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Calls the given block for each element of +self+
|
||||
# and pass the value of each element.
|
||||
#
|
||||
# call-seq:
|
||||
# hsh.each_value {| value | block } -> hsh
|
||||
# hsh.each_value -> an_enumerator
|
||||
#
|
||||
# If no block is given, an enumerator is returned instead.
|
||||
#
|
||||
# h = { "a" => 100, "b" => 200 }
|
||||
# h.each_value {|value| puts value }
|
||||
#
|
||||
# <em>produces:</em>
|
||||
#
|
||||
# 100
|
||||
# 200
|
||||
#
|
||||
# ISO 15.2.13.4.11
|
||||
def each_value(&block)
|
||||
return to_enum :each_value unless block
|
||||
|
||||
self.values.each{|v| block.call(v)}
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Replaces the contents of <i>hsh</i> with the contents of other hash
|
||||
#
|
||||
# ISO 15.2.13.4.23
|
||||
def replace(hash)
|
||||
raise TypeError, "Hash required (#{hash.class} given)" unless Hash === hash
|
||||
self.clear
|
||||
hash.each_key{|k|
|
||||
self[k] = hash[k]
|
||||
}
|
||||
if hash.default_proc
|
||||
self.default_proc = hash.default_proc
|
||||
else
|
||||
self.default = hash.default
|
||||
end
|
||||
self
|
||||
end
|
||||
# ISO 15.2.13.4.17
|
||||
alias initialize_copy replace
|
||||
|
||||
##
|
||||
# Return a hash which contains the content of
|
||||
# +self+ and +other+. If a block is given
|
||||
# it will be called for each element with
|
||||
# a duplicate key. The value of the block
|
||||
# will be the final value of this element.
|
||||
#
|
||||
# ISO 15.2.13.4.22
|
||||
def merge(other, &block)
|
||||
raise TypeError, "Hash required (#{other.class} given)" unless Hash === other
|
||||
h = self.dup
|
||||
if block
|
||||
other.each_key{|k|
|
||||
h[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k]
|
||||
}
|
||||
else
|
||||
other.each_key{|k| h[k] = other[k]}
|
||||
end
|
||||
h
|
||||
end
|
||||
|
||||
# internal method for Hash inspection
|
||||
def _inspect(recur_list)
|
||||
return "{}" if self.size == 0
|
||||
return "{...}" if recur_list[self.object_id]
|
||||
recur_list[self.object_id] = true
|
||||
ary=[]
|
||||
keys=self.keys
|
||||
vals=self.values
|
||||
size=keys.size
|
||||
i=0
|
||||
while i<size
|
||||
ary<<(keys[i]._inspect(recur_list) + "=>" + vals[i]._inspect(recur_list))
|
||||
i+=1
|
||||
end
|
||||
"{"+ary.join(", ")+"}"
|
||||
end
|
||||
##
|
||||
# Return the contents of this hash as a string.
|
||||
#
|
||||
# ISO 15.2.13.4.30 (x)
|
||||
def inspect
|
||||
self._inspect({})
|
||||
end
|
||||
# ISO 15.2.13.4.31 (x)
|
||||
alias to_s inspect
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# hsh.reject! {| key, value | block } -> hsh or nil
|
||||
# hsh.reject! -> an_enumerator
|
||||
#
|
||||
# Equivalent to <code>Hash#delete_if</code>, but returns
|
||||
# <code>nil</code> if no changes were made.
|
||||
#
|
||||
# 1.8/1.9 Hash#reject! returns Hash; ISO says nothing.
|
||||
#
|
||||
def reject!(&block)
|
||||
return to_enum :reject! unless block
|
||||
|
||||
keys = []
|
||||
self.each{|k,v|
|
||||
if block.call([k, v])
|
||||
keys.push(k)
|
||||
end
|
||||
}
|
||||
return nil if keys.size == 0
|
||||
keys.each{|k|
|
||||
self.delete(k)
|
||||
}
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# hsh.reject {|key, value| block} -> a_hash
|
||||
# hsh.reject -> an_enumerator
|
||||
#
|
||||
# Returns a new hash consisting of entries for which the block returns false.
|
||||
#
|
||||
# If no block is given, an enumerator is returned instead.
|
||||
#
|
||||
# h = { "a" => 100, "b" => 200, "c" => 300 }
|
||||
# h.reject {|k,v| k < "b"} #=> {"b" => 200, "c" => 300}
|
||||
# h.reject {|k,v| v > 100} #=> {"a" => 100}
|
||||
#
|
||||
# 1.8/1.9 Hash#reject returns Hash; ISO says nothing.
|
||||
#
|
||||
def reject(&block)
|
||||
return to_enum :reject unless block
|
||||
|
||||
h = {}
|
||||
self.each{|k,v|
|
||||
unless block.call([k, v])
|
||||
h[k] = v
|
||||
end
|
||||
}
|
||||
h
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# hsh.select! {| key, value | block } -> hsh or nil
|
||||
# hsh.select! -> an_enumerator
|
||||
#
|
||||
# Equivalent to <code>Hash#keep_if</code>, but returns
|
||||
# <code>nil</code> if no changes were made.
|
||||
#
|
||||
# 1.9 Hash#select! returns Hash; ISO says nothing.
|
||||
#
|
||||
def select!(&block)
|
||||
return to_enum :select! unless block
|
||||
|
||||
keys = []
|
||||
self.each{|k,v|
|
||||
unless block.call([k, v])
|
||||
keys.push(k)
|
||||
end
|
||||
}
|
||||
return nil if keys.size == 0
|
||||
keys.each{|k|
|
||||
self.delete(k)
|
||||
}
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# hsh.select {|key, value| block} -> a_hash
|
||||
# hsh.select -> an_enumerator
|
||||
#
|
||||
# Returns a new hash consisting of entries for which the block returns true.
|
||||
#
|
||||
# If no block is given, an enumerator is returned instead.
|
||||
#
|
||||
# h = { "a" => 100, "b" => 200, "c" => 300 }
|
||||
# h.select {|k,v| k > "a"} #=> {"b" => 200, "c" => 300}
|
||||
# h.select {|k,v| v < 200} #=> {"a" => 100}
|
||||
#
|
||||
# 1.9 Hash#select returns Hash; ISO says nothing
|
||||
#
|
||||
def select(&block)
|
||||
return to_enum :select unless block
|
||||
|
||||
h = {}
|
||||
self.each{|k,v|
|
||||
if block.call([k, v])
|
||||
h[k] = v
|
||||
end
|
||||
}
|
||||
h
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Hash is enumerable
|
||||
#
|
||||
# ISO 15.2.13.3
|
||||
class Hash
|
||||
include Enumerable
|
||||
end
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
#include <mruby.h>
|
||||
#include <mruby/irep.h>
|
||||
|
||||
extern const uint8_t mrblib_irep[];
|
||||
|
||||
void
|
||||
mrb_init_mrblib(mrb_state *mrb)
|
||||
{
|
||||
mrb_load_irep(mrb, mrblib_irep);
|
||||
}
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
##
|
||||
# Kernel
|
||||
#
|
||||
# ISO 15.3.1
|
||||
module Kernel
|
||||
|
||||
# 15.3.1.2.1 Kernel.`
|
||||
# provided by Kernel#`
|
||||
# 15.3.1.3.3
|
||||
def `(s)
|
||||
raise NotImplementedError.new("backquotes not implemented")
|
||||
end
|
||||
|
||||
##
|
||||
# 15.3.1.2.3 Kernel.eval
|
||||
# 15.3.1.3.12 Kernel#eval
|
||||
# NotImplemented by mruby core; use mruby-eval gem
|
||||
|
||||
##
|
||||
# ISO 15.3.1.2.8 Kernel.loop
|
||||
# provided by Kernel#loop
|
||||
|
||||
##
|
||||
# Calls the given block repetitively.
|
||||
#
|
||||
# ISO 15.3.1.3.29
|
||||
def loop(&block)
|
||||
return to_enum :loop unless block
|
||||
|
||||
while true
|
||||
yield
|
||||
end
|
||||
rescue StopIteration => e
|
||||
e.result
|
||||
end
|
||||
|
||||
# 11.4.4 Step c)
|
||||
def !~(y)
|
||||
!(self =~ y)
|
||||
end
|
||||
|
||||
# internal method for inspect
|
||||
def _inspect(_recur_list)
|
||||
self.inspect
|
||||
end
|
||||
|
||||
def to_enum(*a)
|
||||
raise NotImplementedError.new("fiber required for enumerator")
|
||||
end
|
||||
end
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
MRuby.each_target do
|
||||
current_dir = File.dirname(__FILE__)
|
||||
relative_from_root = File.dirname(__FILE__).relative_path_from(MRUBY_ROOT)
|
||||
current_build_dir = "#{build_dir}/#{relative_from_root}"
|
||||
|
||||
self.libmruby_objs << objfile("#{current_build_dir}/mrblib")
|
||||
|
||||
file objfile("#{current_build_dir}/mrblib") => "#{current_build_dir}/mrblib.c"
|
||||
file "#{current_build_dir}/mrblib.c" => [mrbcfile, __FILE__] + Dir.glob("#{current_dir}/*.rb").sort do |t|
|
||||
_, _, *rbfiles = t.prerequisites
|
||||
mkdir_p File.dirname(t.name)
|
||||
open(t.name, 'w') do |f|
|
||||
_pp "GEN", "*.rb", "#{t.name.relative_path}"
|
||||
f.puts File.read("#{current_dir}/init_mrblib.c")
|
||||
mrbc.run f, rbfiles, 'mrblib_irep'
|
||||
end
|
||||
end
|
||||
end
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
##
|
||||
# Numeric
|
||||
#
|
||||
# ISO 15.2.7
|
||||
class Numeric
|
||||
include Comparable
|
||||
##
|
||||
# Returns the receiver simply.
|
||||
#
|
||||
# ISO 15.2.7.4.1
|
||||
def +@
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the receiver's value, negated.
|
||||
#
|
||||
# ISO 15.2.7.4.2
|
||||
def -@
|
||||
0 - self
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the absolute value of the receiver.
|
||||
#
|
||||
# ISO 15.2.7.4.3
|
||||
def abs
|
||||
if self < 0
|
||||
-self
|
||||
else
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Integral
|
||||
#
|
||||
# mruby special - module to share methods between Floats and Integers
|
||||
# to make them compatible
|
||||
module Integral
|
||||
##
|
||||
# Calls the given block once for each Integer
|
||||
# from +self+ downto +num+.
|
||||
#
|
||||
# ISO 15.2.8.3.15
|
||||
def downto(num, &block)
|
||||
return to_enum(:downto, num) unless block
|
||||
|
||||
i = self.to_i
|
||||
while i >= num
|
||||
block.call(i)
|
||||
i -= 1
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Returns self + 1
|
||||
#
|
||||
# ISO 15.2.8.3.19
|
||||
def next
|
||||
self + 1
|
||||
end
|
||||
# ISO 15.2.8.3.21
|
||||
alias succ next
|
||||
|
||||
##
|
||||
# Calls the given block +self+ times.
|
||||
#
|
||||
# ISO 15.2.8.3.22
|
||||
def times &block
|
||||
return to_enum :times unless block
|
||||
|
||||
i = 0
|
||||
while i < self
|
||||
block.call i
|
||||
i += 1
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Calls the given block once for each Integer
|
||||
# from +self+ upto +num+.
|
||||
#
|
||||
# ISO 15.2.8.3.27
|
||||
def upto(num, &block)
|
||||
return to_enum(:upto, num) unless block
|
||||
|
||||
i = self.to_i
|
||||
while i <= num
|
||||
block.call(i)
|
||||
i += 1
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Calls the given block from +self+ to +num+
|
||||
# incremented by +step+ (default 1).
|
||||
#
|
||||
def step(num=nil, step=1, &block)
|
||||
raise ArgumentError, "step can't be 0" if step == 0
|
||||
return to_enum(:step, num, step) unless block
|
||||
|
||||
i = __coerce_step_counter(num, step)
|
||||
if num == self || step.infinite?
|
||||
block.call(i) if step > 0 && i <= (num||i) || step < 0 && i >= (num||-i)
|
||||
elsif num == nil
|
||||
while true
|
||||
block.call(i)
|
||||
i += step
|
||||
end
|
||||
elsif step > 0
|
||||
while i <= num
|
||||
block.call(i)
|
||||
i += step
|
||||
end
|
||||
else
|
||||
while i >= num
|
||||
block.call(i)
|
||||
i += step
|
||||
end
|
||||
end
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Integer
|
||||
#
|
||||
# ISO 15.2.8
|
||||
class Integer
|
||||
include Integral
|
||||
##
|
||||
# Returns the receiver simply.
|
||||
#
|
||||
# ISO 15.2.8.3.14
|
||||
def ceil
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the receiver simply.
|
||||
#
|
||||
# ISO 15.2.8.3.17
|
||||
def floor
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the receiver simply.
|
||||
#
|
||||
# ISO 15.2.8.3.24
|
||||
alias round floor
|
||||
|
||||
##
|
||||
# Returns the receiver simply.
|
||||
#
|
||||
# ISO 15.2.8.3.26
|
||||
alias truncate floor
|
||||
end
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
##
|
||||
# Range
|
||||
#
|
||||
# ISO 15.2.14
|
||||
class Range
|
||||
|
||||
##
|
||||
# Calls the given block for each element of +self+
|
||||
# and pass the respective element.
|
||||
#
|
||||
# ISO 15.2.14.4.4
|
||||
def each(&block)
|
||||
return to_enum :each unless block
|
||||
|
||||
val = self.first
|
||||
last = self.last
|
||||
|
||||
if val.kind_of?(Fixnum) && last.kind_of?(Fixnum) # fixnums are special
|
||||
lim = last
|
||||
lim += 1 unless exclude_end?
|
||||
i = val
|
||||
while i < lim
|
||||
block.call(i)
|
||||
i += 1
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
if val.kind_of?(String) && last.kind_of?(String) # strings are special
|
||||
if val.respond_to? :upto
|
||||
return val.upto(last, exclude_end?, &block)
|
||||
else
|
||||
str_each = true
|
||||
end
|
||||
end
|
||||
|
||||
raise TypeError, "can't iterate" unless val.respond_to? :succ
|
||||
|
||||
return self if (val <=> last) > 0
|
||||
|
||||
while (val <=> last) < 0
|
||||
block.call(val)
|
||||
val = val.succ
|
||||
if str_each
|
||||
break if val.size > last.size
|
||||
end
|
||||
end
|
||||
|
||||
block.call(val) if !exclude_end? && (val <=> last) == 0
|
||||
self
|
||||
end
|
||||
|
||||
# redefine #hash 15.3.1.3.15
|
||||
def hash
|
||||
h = first.hash ^ last.hash
|
||||
h += 1 if self.exclude_end?
|
||||
h
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Range is enumerable
|
||||
#
|
||||
# ISO 15.2.14.3
|
||||
class Range
|
||||
include Enumerable
|
||||
end
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
##
|
||||
# String
|
||||
#
|
||||
# ISO 15.2.10
|
||||
class String
|
||||
# ISO 15.2.10.3
|
||||
include Comparable
|
||||
|
||||
##
|
||||
# Calls the given block for each line
|
||||
# and pass the respective line.
|
||||
#
|
||||
# ISO 15.2.10.5.15
|
||||
def each_line(separator = "\n", &block)
|
||||
return to_enum(:each_line, separator) unless block
|
||||
|
||||
if separator.nil?
|
||||
block.call(self)
|
||||
return self
|
||||
end
|
||||
raise TypeError unless separator.is_a?(String)
|
||||
|
||||
paragraph_mode = false
|
||||
if separator.empty?
|
||||
paragraph_mode = true
|
||||
separator = "\n\n"
|
||||
end
|
||||
start = 0
|
||||
string = dup
|
||||
self_len = length
|
||||
sep_len = separator.length
|
||||
should_yield_subclass_instances = self.class != String
|
||||
|
||||
while (pointer = string.index(separator, start))
|
||||
pointer += sep_len
|
||||
pointer += 1 while paragraph_mode && string[pointer] == "\n"
|
||||
if should_yield_subclass_instances
|
||||
block.call(self.class.new(string[start, pointer - start]))
|
||||
else
|
||||
block.call(string[start, pointer - start])
|
||||
end
|
||||
start = pointer
|
||||
end
|
||||
return self if start == self_len
|
||||
|
||||
if should_yield_subclass_instances
|
||||
block.call(self.class.new(string[start, self_len - start]))
|
||||
else
|
||||
block.call(string[start, self_len - start])
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
# private method for gsub/sub
|
||||
def __sub_replace(pre, m, post)
|
||||
s = ""
|
||||
i = 0
|
||||
while j = index("\\", i)
|
||||
break if j == length-1
|
||||
t = case self[j+1]
|
||||
when "\\"
|
||||
"\\"
|
||||
when "`"
|
||||
pre
|
||||
when "&", "0"
|
||||
m
|
||||
when "'"
|
||||
post
|
||||
when "1", "2", "3", "4", "5", "6", "7", "8", "9"
|
||||
""
|
||||
else
|
||||
self[j, 2]
|
||||
end
|
||||
s += self[i, j-i] + t
|
||||
i = j + 2
|
||||
end
|
||||
s + self[i, length-i]
|
||||
end
|
||||
|
||||
##
|
||||
# Replace all matches of +pattern+ with +replacement+.
|
||||
# Call block (if given) for each match and replace
|
||||
# +pattern+ with the value of the block. Return the
|
||||
# final value.
|
||||
#
|
||||
# ISO 15.2.10.5.18
|
||||
def gsub(*args, &block)
|
||||
return to_enum(:gsub, *args) if args.length == 1 && !block
|
||||
raise ArgumentError, "wrong number of arguments" unless (1..2).include?(args.length)
|
||||
|
||||
pattern, replace = *args
|
||||
plen = pattern.length
|
||||
if args.length == 2 && block
|
||||
block = nil
|
||||
end
|
||||
if !replace.nil? || !block
|
||||
replace.__to_str
|
||||
end
|
||||
offset = 0
|
||||
result = []
|
||||
while found = index(pattern, offset)
|
||||
result << self[offset, found - offset]
|
||||
offset = found + plen
|
||||
result << if block
|
||||
block.call(pattern).to_s
|
||||
else
|
||||
replace.__sub_replace(self[0, found], pattern, self[offset..-1] || "")
|
||||
end
|
||||
if plen == 0
|
||||
result << self[offset, 1]
|
||||
offset += 1
|
||||
end
|
||||
end
|
||||
result << self[offset..-1] if offset < length
|
||||
result.join
|
||||
end
|
||||
|
||||
##
|
||||
# Replace all matches of +pattern+ with +replacement+.
|
||||
# Call block (if given) for each match and replace
|
||||
# +pattern+ with the value of the block. Modify
|
||||
# +self+ with the final value.
|
||||
#
|
||||
# ISO 15.2.10.5.19
|
||||
def gsub!(*args, &block)
|
||||
raise FrozenError, "can't modify frozen String" if frozen?
|
||||
return to_enum(:gsub!, *args) if args.length == 1 && !block
|
||||
str = self.gsub(*args, &block)
|
||||
return nil unless self.index(args[0])
|
||||
self.replace(str)
|
||||
end
|
||||
|
||||
# ##
|
||||
# # Calls the given block for each match of +pattern+
|
||||
# # If no block is given return an array with all
|
||||
# # matches of +pattern+.
|
||||
# #
|
||||
# # ISO 15.2.10.5.32
|
||||
# def scan(pattern, &block)
|
||||
# # TODO: String#scan is not implemented yet
|
||||
# end
|
||||
|
||||
##
|
||||
# Replace only the first match of +pattern+ with
|
||||
# +replacement+. Call block (if given) for each
|
||||
# match and replace +pattern+ with the value of the
|
||||
# block. Return the final value.
|
||||
#
|
||||
# ISO 15.2.10.5.36
|
||||
def sub(*args, &block)
|
||||
unless (1..2).include?(args.length)
|
||||
raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 2)"
|
||||
end
|
||||
|
||||
pattern, replace = *args
|
||||
pattern.__to_str
|
||||
if args.length == 2 && block
|
||||
block = nil
|
||||
end
|
||||
unless block
|
||||
replace.__to_str
|
||||
end
|
||||
result = []
|
||||
this = dup
|
||||
found = index(pattern)
|
||||
return this unless found
|
||||
result << this[0, found]
|
||||
offset = found + pattern.length
|
||||
result << if block
|
||||
block.call(pattern).to_s
|
||||
else
|
||||
replace.__sub_replace(this[0, found], pattern, this[offset..-1] || "")
|
||||
end
|
||||
result << this[offset..-1] if offset < length
|
||||
result.join
|
||||
end
|
||||
|
||||
##
|
||||
# Replace only the first match of +pattern+ with
|
||||
# +replacement+. Call block (if given) for each
|
||||
# match and replace +pattern+ with the value of the
|
||||
# block. Modify +self+ with the final value.
|
||||
#
|
||||
# ISO 15.2.10.5.37
|
||||
def sub!(*args, &block)
|
||||
raise FrozenError, "can't modify frozen String" if frozen?
|
||||
str = self.sub(*args, &block)
|
||||
return nil unless self.index(args[0])
|
||||
self.replace(str)
|
||||
end
|
||||
|
||||
##
|
||||
# Call the given block for each byte of +self+.
|
||||
def each_byte(&block)
|
||||
return to_enum(:each_byte, &block) unless block
|
||||
bytes = self.bytes
|
||||
pos = 0
|
||||
while pos < bytes.size
|
||||
block.call(bytes[pos])
|
||||
pos += 1
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
# those two methods requires Regexp that is optional in mruby
|
||||
##
|
||||
# ISO 15.2.10.5.3
|
||||
#def =~(re)
|
||||
# re =~ self
|
||||
#end
|
||||
|
||||
##
|
||||
# ISO 15.2.10.5.27
|
||||
#def match(re, &block)
|
||||
# re.match(self, &block)
|
||||
#end
|
||||
end
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class Symbol
|
||||
def to_proc
|
||||
->(obj,*args,&block) do
|
||||
obj.__send__(self, *args, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user