first commit
CI / Build (clang, clang++, ubuntu-22.04, linux, 3.10, master, x86,x86_64) (push) Canceled after 0s
CI / Build (clang, clang++, windows-2022, windows, 3.10, master, x86,x86_64) (push) Canceled after 0s
CI / Release (push) Canceled after 0s

This commit is contained in:
2026-09-13 22:18:11 +01:00
commit 08c03ac533
6701 changed files with 1577314 additions and 0 deletions
+39
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -0,0 +1,7 @@
class Symbol
def to_proc
->(obj,*args,&block) do
obj.__send__(self, *args, &block)
end
end
end