diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2019-07-17 10:35:41 +0900 |
|---|---|---|
| committer | GitHub <[email protected]> | 2019-07-17 10:35:41 +0900 |
| commit | d605b72c1d6fa4564a0a5e88535504b6850463b5 (patch) | |
| tree | 774fc0de56002abb3bb2b1c3387ff08f91876d17 /mrblib | |
| parent | 2af92d0ebcbeca6d3d85a27c8193273080a63090 (diff) | |
| parent | 9af3b7c6258de327218dd04e69d76ae68caf17b1 (diff) | |
| download | mruby-d605b72c1d6fa4564a0a5e88535504b6850463b5.tar.gz mruby-d605b72c1d6fa4564a0a5e88535504b6850463b5.zip | |
Merge branch 'master' into i110/inspect-recursion
Diffstat (limited to 'mrblib')
| -rw-r--r-- | mrblib/array.rb | 105 | ||||
| -rw-r--r-- | mrblib/enum.rb | 18 | ||||
| -rw-r--r-- | mrblib/float.rb | 9 | ||||
| -rw-r--r-- | mrblib/hash.rb | 60 | ||||
| -rw-r--r-- | mrblib/kernel.rb | 2 | ||||
| -rw-r--r-- | mrblib/mrblib.rake | 5 | ||||
| -rw-r--r-- | mrblib/numeric.rb | 12 | ||||
| -rw-r--r-- | mrblib/range.rb | 2 | ||||
| -rw-r--r-- | mrblib/string.rb | 133 | ||||
| -rw-r--r-- | mrblib/symbol.rb | 7 |
10 files changed, 135 insertions, 218 deletions
diff --git a/mrblib/array.rb b/mrblib/array.rb index bc9a2a492..2b080564c 100644 --- a/mrblib/array.rb +++ b/mrblib/array.rb @@ -66,7 +66,7 @@ class Array # # ISO 15.2.12.5.15 def initialize(size=0, obj=nil, &block) - raise TypeError, "expected Integer for 1st argument" unless size.kind_of? Integer + size = size.__to_int raise ArgumentError, "negative array size" if size < 0 self.clear @@ -84,10 +84,17 @@ class Array end def _inspect(recur_list) - return "[]" if self.size == 0 + size = self.size + return "[]" if size == 0 return "[...]" if recur_list[self.object_id] recur_list[self.object_id] = true - "["+self.map{|x|x._inspect(recur_list)}.join(", ")+"]" + 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. @@ -191,43 +198,69 @@ class Array include Enumerable ## - # Quick sort - # left : the beginning of sort region - # right : the end of sort region - def __sort_sub__(left, right, &block) - stack = [ [left, right] ] + # Sort all elements and replace +self+ with these + # elements. + def sort!(&block) + stack = [ [ 0, self.size - 1 ] ] until stack.empty? - left, right = stack.pop - if left < right - i = left - j = right - pivot = self[i + (j - i) / 2] - while true - while ((block)? block.call(self[i], pivot): (self[i] <=> pivot)) < 0 - i += 1 + 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 - while ((block)? block.call(pivot, self[j]): (pivot <=> self[j])) < 0 - j -= 1 - end - break if (i >= j) - tmp = self[i]; self[i] = self[j]; self[j] = tmp; - i += 1 - j -= 1 end - stack.push [left, i-1] - stack.push [j+1, right] - end - end - end - # private :__sort_sub__ + else + lary = self[left, mid - left] + lsize = lary.size - ## - # Sort all elements and replace +self+ with these - # elements. - def sort!(&block) - size = self.size - if size > 1 - __sort_sub__(0, size - 1, &block) + # 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 diff --git a/mrblib/enum.rb b/mrblib/enum.rb index a97a26f97..fe40b4d27 100644 --- a/mrblib/enum.rb +++ b/mrblib/enum.rb @@ -13,6 +13,8 @@ # @ISO 15.3.2 module Enumerable + NONE = Object.new + ## # Call the given block for each element # which is yield by +each+. Return false @@ -63,22 +65,20 @@ module Enumerable end ## - # Call the given block for each element - # which is yield by +each+. Return - # +ifnone+ if no block value was true. - # Otherwise return the first block value - # which had was true. + # 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) - ret = ifnone self.each{|*val| if block.call(*val) - ret = val.__svalue - break + return val.__svalue end } - ret + ifnone.call unless ifnone.nil? end ## diff --git a/mrblib/float.rb b/mrblib/float.rb deleted file mode 100644 index 2b86dc1e5..000000000 --- a/mrblib/float.rb +++ /dev/null @@ -1,9 +0,0 @@ -## -# Float -# -# ISO 15.2.9 -class Float - # mruby special - since mruby integers may be upgraded to floats, - # floats should be compatible to integers. - include Integral -end if class_defined?("Float") diff --git a/mrblib/hash.rb b/mrblib/hash.rb index 6fcbba173..0e2da62e1 100644 --- a/mrblib/hash.rb +++ b/mrblib/hash.rb @@ -12,9 +12,7 @@ class Hash # ISO 15.2.13.4.1 def ==(hash) return true if self.equal?(hash) - begin - hash = hash.to_hash - rescue NoMethodError + unless Hash === hash return false end return false if self.size != hash.size @@ -32,9 +30,7 @@ class Hash # ISO 15.2.13.4.32 (x) def eql?(hash) return true if self.equal?(hash) - begin - hash = hash.to_hash - rescue NoMethodError + unless Hash === hash return false end return false if self.size != hash.size @@ -55,10 +51,9 @@ class Hash # ISO 15.2.13.4.8 def delete(key, &block) if block && !self.has_key?(key) - block.call(key) - else - self.__delete(key) + return block.call(key) end + self.__delete(key) end ## @@ -154,9 +149,8 @@ class Hash # # ISO 15.2.13.4.23 def replace(hash) - raise TypeError, "can't convert argument into Hash" unless hash.respond_to?(:to_hash) + raise TypeError, "Hash required (#{hash.class} given)" unless Hash === hash self.clear - hash = hash.to_hash hash.each_key{|k| self[k] = hash[k] } @@ -179,8 +173,7 @@ class Hash # # ISO 15.2.13.4.22 def merge(other, &block) - raise TypeError, "can't convert argument into Hash" unless other.respond_to?(:to_hash) - other = other.to_hash + raise TypeError, "Hash required (#{other.class} given)" unless Hash === other h = self.dup if block other.each_key{|k| @@ -197,9 +190,16 @@ class Hash return "{}" if self.size == 0 return "{...}" if recur_list[self.object_id] recur_list[self.object_id] = true - "{"+self.map {|k,v| - k._inspect(recur_list) + "=>" + v._inspect(recur_list) - }.join(", ")+"}" + ary=[] + keys=self.keys + size=keys.size + i=0 + while i<size + k=keys[i] + ary<<(k._inspect + "=>" + self[k]._inspect) + i+=1 + end + "{"+ary.join(", ")+"}" end ## # Return the contents of this hash as a string. @@ -316,34 +316,6 @@ class Hash } h end - - ## - # call-seq: - # hsh.rehash -> hsh - # - # Rebuilds the hash based on the current hash values for each key. If - # values of key objects have changed since they were inserted, this - # method will reindex <i>hsh</i>. - # - # h = {"AAA" => "b"} - # h.keys[0].chop! - # h #=> {"AA"=>"b"} - # h["AA"] #=> nil - # h.rehash #=> {"AA"=>"b"} - # h["AA"] #=> "b" - # - def rehash - h = {} - self.each{|k,v| - h[k] = v - } - self.replace(h) - end - - def __update(h) - h.each_key{|k| self[k] = h[k]} - self - end end ## diff --git a/mrblib/kernel.rb b/mrblib/kernel.rb index 3fb324908..7c3ea9420 100644 --- a/mrblib/kernel.rb +++ b/mrblib/kernel.rb @@ -6,7 +6,7 @@ module Kernel # 15.3.1.2.1 Kernel.` # provided by Kernel#` - # 15.3.1.3.5 + # 15.3.1.3.3 def `(s) raise NotImplementedError.new("backquotes not implemented") end diff --git a/mrblib/mrblib.rake b/mrblib/mrblib.rake index fe4aae1f7..e96decb27 100644 --- a/mrblib/mrblib.rake +++ b/mrblib/mrblib.rake @@ -3,14 +3,11 @@ MRuby.each_target do relative_from_root = File.dirname(__FILE__).relative_path_from(MRUBY_ROOT) current_build_dir = "#{build_dir}/#{relative_from_root}" - self.libmruby << objfile("#{current_build_dir}/mrblib") + 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 - if self.cc.defines.flatten.include?("MRB_WITHOUT_FLOAT") - rbfiles.delete("#{current_dir}/float.rb") - end FileUtils.mkdir_p File.dirname(t.name) open(t.name, 'w') do |f| _pp "GEN", "*.rb", "#{t.name.relative_path}" diff --git a/mrblib/numeric.rb b/mrblib/numeric.rb index 1b11e92ad..5926518d5 100644 --- a/mrblib/numeric.rb +++ b/mrblib/numeric.rb @@ -104,15 +104,15 @@ module Integral raise ArgumentError, "step can't be 0" if step == 0 return to_enum(:step, num, step) unless block - i = if class_defined?("Float") && num.kind_of?(Float) then self.to_f else self end - if num == nil + 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 + i += step end - return self - end - if step > 0 + elsif step > 0 while i <= num block.call(i) i += step diff --git a/mrblib/range.rb b/mrblib/range.rb index 5bd2521e8..392cc2274 100644 --- a/mrblib/range.rb +++ b/mrblib/range.rb @@ -26,7 +26,7 @@ class Range return self end - if val.kind_of?(String) && last.kind_of?(String) # fixnums are special + 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 diff --git a/mrblib/string.rb b/mrblib/string.rb index ee98cfa0c..c26cdb1e2 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -3,7 +3,9 @@ # # 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. @@ -12,7 +14,7 @@ class String def each_line(rs = "\n", &block) return to_enum(:each_line, rs, &block) unless block return block.call(self) if rs.nil? - rs = rs.to_str + rs.__to_str offset = 0 rs_len = rs.length this = dup @@ -67,7 +69,7 @@ class String block = nil end if !replace.nil? || !block - replace = replace.to_str + replace.__to_str end offset = 0 result = [] @@ -99,22 +101,19 @@ class String 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 if str == self + 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(reg, &block) - ### *** TODO *** ### - unless Object.const_defined?(:Regexp) - raise NotImplementedError, "scan not available (yet)" - end - 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 @@ -129,12 +128,12 @@ class String end pattern, replace = *args - pattern = pattern.to_str + pattern.__to_str if args.length == 2 && block block = nil end unless block - replace = replace.to_str + replace.__to_str end result = [] this = dup @@ -161,25 +160,14 @@ class String def sub!(*args, &block) raise FrozenError, "can't modify frozen String" if frozen? str = self.sub(*args, &block) - return nil if str == self + return nil unless self.index(args[0]) self.replace(str) end ## - # Call the given block for each character of - # +self+. - def each_char(&block) - pos = 0 - while pos < self.size - block.call(self[pos]) - pos += 1 - end - self - 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 @@ -189,87 +177,16 @@ class String self end - ## - # Modify +self+ by replacing the content of +self+. - # The portion of the string affected is determined using the same criteria as +String#[]+. - def []=(*args) - anum = args.size - if anum == 2 - pos, value = args - case pos - when String - posnum = self.index(pos) - if posnum - b = self[0, posnum.to_i] - a = self[(posnum + pos.length)..-1] - self.replace([b, value, a].join('')) - else - raise IndexError, "string not matched" - end - when Range - head = pos.begin - tail = pos.end - tail += self.length if tail < 0 - unless pos.exclude_end? - tail += 1 - end - return self[head, tail-head]=value - else - pos += self.length if pos < 0 - if pos < 0 || pos > self.length - raise IndexError, "index #{args[0]} out of string" - end - b = self[0, pos.to_i] - a = self[pos + 1..-1] - self.replace([b, value, a].join('')) - end - return value - elsif anum == 3 - pos, len, value = args - pos += self.length if pos < 0 - if pos < 0 || pos > self.length - raise IndexError, "index #{args[0]} out of string" - end - if len < 0 - raise IndexError, "negative length #{len}" - end - b = self[0, pos.to_i] - a = self[pos + len..-1] - self.replace([b, value, a].join('')) - return value - else - raise ArgumentError, "wrong number of arguments (#{anum} for 2..3)" - end - end - + # those two methods requires Regexp that is optional in mruby ## # ISO 15.2.10.5.3 - def =~(re) - raise TypeError, "type mismatch: String given" if re.respond_to? :to_str - re =~ self - end + #def =~(re) + # re =~ self + #end ## # ISO 15.2.10.5.27 - def match(re, &block) - if re.respond_to? :to_str - if Object.const_defined?(:Regexp) - r = Regexp.new(re) - r.match(self, &block) - else - raise NotImplementedError, "String#match needs Regexp class" - end - else - re.match(self, &block) - end - end -end - -## -# String is comparable -# -# ISO 15.2.10.3 -module Comparable; end -class String - include Comparable + #def match(re, &block) + # re.match(self, &block) + #end end diff --git a/mrblib/symbol.rb b/mrblib/symbol.rb new file mode 100644 index 000000000..9c981dd9e --- /dev/null +++ b/mrblib/symbol.rb @@ -0,0 +1,7 @@ +class Symbol + def to_proc + ->(obj,*args,&block) do + obj.__send__(self, *args, &block) + end + end +end |
