summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/api/mruby/string.h.md91
-rw-r--r--include/mruby/string.h11
-rw-r--r--include/mruby/version.h12
-rw-r--r--mrbgems/mruby-array-ext/mrblib/array.rb24
-rwxr-xr-xmrbgems/mruby-bin-debugger/mrbgem.rake2
-rw-r--r--mrbgems/mruby-enum-ext/mrblib/enum.rb6
-rw-r--r--mrbgems/mruby-sprintf/src/sprintf.c2
-rw-r--r--mrbgems/mruby-string-ext/mrblib/string.rb12
-rw-r--r--mrblib/array.rb29
-rw-r--r--mrblib/enum.rb32
-rw-r--r--mrblib/error.rb15
-rw-r--r--mrblib/numeric.rb32
-rw-r--r--mrblib/range.rb12
-rw-r--r--mrblib/string.rb26
-rw-r--r--src/dump.c2
-rw-r--r--src/numeric.c12
-rw-r--r--src/string.c33
-rw-r--r--src/version.c1
-rw-r--r--src/vm.c3
-rw-r--r--test/bintest.rb2
-rw-r--r--test/t/float.rb22
-rw-r--r--test/t/integer.rb10
-rw-r--r--test/t/string.rb8
23 files changed, 244 insertions, 155 deletions
diff --git a/doc/api/mruby/string.h.md b/doc/api/mruby/string.h.md
new file mode 100644
index 000000000..7bf94df5b
--- /dev/null
+++ b/doc/api/mruby/string.h.md
@@ -0,0 +1,91 @@
+## Macros
+### mrb_str_ptr(s)
+Returns a pointer from a Ruby string.
+## Functions
+### mrb_str_plus
+```C
+ mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value);
+```
+Adds to strings together.
+### mrb_ptr_to_str
+```C
+ mrb_value mrb_ptr_to_str(mrb_state *, void*);
+```
+Converts pointer into a Ruby string.
+### mrb_obj_as_string
+```C
+ mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj);
+```
+Returns an object as a Ruby string.
+### mrb_str_resize
+```C
+ mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len);
+```
+Resizes the string's length.
+### mrb_str_substr
+```C
+ mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
+```
+Returns a sub string.
+### mrb_string_type
+```C
+ mrb_value mrb_string_type(mrb_state *mrb, mrb_value str);
+```
+Returns a Ruby string type.
+### mrb_str_new_cstr
+```C
+ const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr);
+```
+Returns a Ruby string as a C string.
+### mrb_str_dup
+```C
+ mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str);
+```
+Duplicates a string object.
+### mrb_str_intern
+```C
+ mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self);
+```
+Returns a symbol from a passed in string.
+### mrb_str_to_str
+```C
+ mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str);
+```
+Returns a converted string type.
+### mrb_str_equal
+```C
+ mrb_bool mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2);
+```
+Returns true if the strings match and false if the strings don't match.
+### mrb_str_cat
+```C
+ mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len);
+```
+Returns a concated string comprised of a Ruby string and a C string.
+### mrb_str_cat_cstr
+```C
+ mrb_value mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2);
+```
+Returns a concated string comprised of a Ruby string and a C string(A shorter alternative to mrb_str_cat).
+### mrb_str_append
+```C
+ mrb_value mrb_str_append(mrb_state *mrb, mrb_value str1, mrb_value str2);
+```
+Adds str2 to the end of str1.
+### mrb_str_cmp
+```C
+ int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
+```
+Returns 0 if both Ruby strings are equal.
+Returns a value < 0 if Ruby str1 is less than Ruby str2.
+Returns a value > 0 if Ruby str2 is greater than Ruby str1.
+### mrb_str_to_cstr
+```C
+ char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str);
+```
+Returns a C string from a Ruby string.
+### mrb_str_inspect
+```C
+ mrb_str_inspect(mrb_state *mrb, mrb_value str);
+```
+Returns a printable version of str, surrounded by quote marks, with special characters escaped.
diff --git a/include/mruby/string.h b/include/mruby/string.h
index 5228dcbca..c4b31216e 100644
--- a/include/mruby/string.h
+++ b/include/mruby/string.h
@@ -59,6 +59,10 @@ struct RString {
#define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE)
#define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE)
+#define RSTR_FROZEN_P(s) ((s)->flags & MRB_STR_FROZEN)
+#define RSTR_SET_FROZEN_FLAG(s) ((s)->flags |= MRB_STR_FROZEN)
+#define RSTR_UNSET_FROZEN_FLAG(s) ((s)->flags &= ~MRB_STR_FROZEN)
+
#define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s)))
#define RSTRING(s) mrb_str_ptr(s)
#define RSTRING_PTR(s) RSTR_PTR(RSTRING(s))
@@ -70,9 +74,10 @@ mrb_int mrb_str_strlen(mrb_state*, struct RString*);
#define MRB_STR_SHARED 1
#define MRB_STR_NOFREE 2
-#define MRB_STR_EMBED 4
-#define MRB_STR_EMBED_LEN_MASK 0xf8
-#define MRB_STR_EMBED_LEN_SHIFT 3
+#define MRB_STR_FROZEN 4
+#define MRB_STR_EMBED 8
+#define MRB_STR_EMBED_LEN_MASK 0x1f0
+#define MRB_STR_EMBED_LEN_SHIFT 4
void mrb_gc_free_str(mrb_state*, struct RString*);
MRB_API void mrb_str_modify(mrb_state*, struct RString*);
diff --git a/include/mruby/version.h b/include/mruby/version.h
index ea044d6da..c2a9b6306 100644
--- a/include/mruby/version.h
+++ b/include/mruby/version.h
@@ -7,25 +7,27 @@
#ifndef MRUBY_VERSION_H
#define MRUBY_VERSION_H
+#define MRB_STRINGIZE0(expr) #expr
+#define MRB_STRINGIZE(expr) MRB_STRINGIZE0(expr)
+
#define MRUBY_RUBY_VERSION "1.9"
#define MRUBY_RUBY_ENGINE "mruby"
-#define MRUBY_VERSION "1.1.0"
#define MRUBY_RELEASE_MAJOR 1
#define MRUBY_RELEASE_MINOR 1
#define MRUBY_RELEASE_TEENY 1
-#define MRUBY_RELEASE_NO 10101
-#define MRUBY_RELEASE_DATE "2014-11-19"
+
+#define MRUBY_VERSION MRB_STRINGIZE(MRUBY_RELEASE_MAJOR) "." MRB_STRINGIZE(MRUBY_RELEASE_MINOR) "." MRB_STRINGIZE(MRUBY_RELEASE_TEENY)
+#define MRUBY_RELEASE_NO (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY)
#define MRUBY_RELEASE_YEAR 2014
#define MRUBY_RELEASE_MONTH 11
#define MRUBY_RELEASE_DAY 19
+#define MRUBY_RELEASE_DATE MRB_STRINGIZE(MRUBY_RELEASE_YEAR) "-" MRB_STRINGIZE(MRUBY_RELEASE_MONTH) "-" MRB_STRINGIZE(MRUBY_RELEASE_DAY)
#define MRUBY_BIRTH_YEAR 2010
#define MRUBY_AUTHOR "mruby developers"
-#define MRB_STRINGIZE0(expr) #expr
-#define MRB_STRINGIZE(expr) MRB_STRINGIZE0(expr)
#define MRUBY_DESCRIPTION \
"mruby " MRUBY_VERSION \
diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb
index fd80fa0bb..1f1d97376 100644
--- a/mrbgems/mruby-array-ext/mrblib/array.rb
+++ b/mrbgems/mruby-array-ext/mrblib/array.rb
@@ -217,7 +217,7 @@ class Array
# [ "a", "b", "c" ].compact! #=> nil
#
def compact!
- result = self.select { |e| e != nil }
+ result = self.select { |e| !e.nil? }
if result.size == self.size
nil
else
@@ -262,7 +262,7 @@ class Array
#
def fetch(n=nil, ifnone=NONE, &block)
- warn "block supersedes default value argument" if n != nil && ifnone != NONE && block
+ warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block
idx = n
if idx < 0
@@ -312,51 +312,51 @@ class Array
#
def fill(arg0=nil, arg1=nil, arg2=nil, &block)
- if arg0 == nil && arg1 == nil && arg2 == nil && !block
+ if arg0.nil? && arg1.nil? && arg2.nil? && !block
raise ArgumentError, "wrong number of arguments (0 for 1..3)"
end
beg = len = 0
ary = []
if block
- if arg0 == nil && arg1 == nil && arg2 == nil
+ if arg0.nil? && arg1.nil? && arg2.nil?
# ary.fill { |index| block } -> ary
beg = 0
len = self.size
- elsif arg0 != nil && arg0.kind_of?(Range)
+ elsif !arg0.nil? && arg0.kind_of?(Range)
# ary.fill(range) { |index| block } -> ary
beg = arg0.begin
beg += self.size if beg < 0
len = arg0.end
len += self.size if len < 0
len += 1 unless arg0.exclude_end?
- elsif arg0 != nil
+ elsif !arg0.nil?
# ary.fill(start [, length] ) { |index| block } -> ary
beg = arg0
beg += self.size if beg < 0
- if arg1 == nil
+ if arg1.nil?
len = self.size
else
len = arg0 + arg1
end
end
else
- if arg0 != nil && arg1 == nil && arg2 == nil
+ if !arg0.nil? && arg1.nil? && arg2.nil?
# ary.fill(obj) -> ary
beg = 0
len = self.size
- elsif arg0 != nil && arg1 != nil && arg1.kind_of?(Range)
+ elsif !arg0.nil? && !arg1.nil? && arg1.kind_of?(Range)
# ary.fill(obj, range ) -> ary
beg = arg1.begin
beg += self.size if beg < 0
len = arg1.end
len += self.size if len < 0
len += 1 unless arg1.exclude_end?
- elsif arg0 != nil && arg1 != nil
+ elsif !arg0.nil? && !arg1.nil?
# ary.fill(obj, start [, length]) -> ary
beg = arg1
beg += self.size if beg < 0
- if arg2 == nil
+ if arg2.nil?
len = self.size
else
len = beg + arg2
@@ -582,7 +582,7 @@ class Array
elsif v == true
satisfied = true
smaller = true
- elsif v == false || v == nil
+ elsif v == false || v.nil?
smaller = false
end
if smaller
diff --git a/mrbgems/mruby-bin-debugger/mrbgem.rake b/mrbgems/mruby-bin-debugger/mrbgem.rake
index b9d664779..764f431af 100755
--- a/mrbgems/mruby-bin-debugger/mrbgem.rake
+++ b/mrbgems/mruby-bin-debugger/mrbgem.rake
@@ -1,7 +1,7 @@
MRuby::Gem::Specification.new('mruby-bin-debugger') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
- spec.summary = 'mruby debuggeer command'
+ spec.summary = 'mruby debugger command'
spec.add_dependency('mruby-eval', :core => 'mruby-eval')
diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb
index f6629ed79..6fef0c077 100644
--- a/mrbgems/mruby-enum-ext/mrblib/enum.rb
+++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb
@@ -515,7 +515,7 @@ module Enumerable
#
def each_with_object(obj=nil, &block)
- raise ArgumentError, "wrong number of arguments (0 for 1)" if obj == nil
+ raise ArgumentError, "wrong number of arguments (0 for 1)" if obj.nil?
return to_enum(:each_with_object, obj) unless block
@@ -574,10 +574,10 @@ module Enumerable
#
def cycle(n=nil, &block)
- return to_enum(:cycle, n) if !block && n == nil
+ return to_enum(:cycle, n) if !block && n.nil?
ary = []
- if n == nil
+ if n.nil?
self.each do|*val|
ary.push val
block.call(*val)
diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c
index de216f69f..81b48b10d 100644
--- a/mrbgems/mruby-sprintf/src/sprintf.c
+++ b/mrbgems/mruby-sprintf/src/sprintf.c
@@ -73,7 +73,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
{
char buf[64], *b = buf + sizeof buf;
mrb_int num = mrb_fixnum(x);
- unsigned long val = (unsigned long)num;
+ uint64_t val = (uint64_t)num;
char d;
if (base != 2) {
diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb
index 2b61fdb48..7d9bc00b9 100644
--- a/mrbgems/mruby-string-ext/mrblib/string.rb
+++ b/mrbgems/mruby-string-ext/mrblib/string.rb
@@ -164,9 +164,9 @@ class String
# string #=> "thsa sting"
#
def slice!(arg1, arg2=nil)
- raise "wrong number of arguments (for 1..2)" if arg1 == nil && arg2 == nil
+ raise "wrong number of arguments (for 1..2)" if arg1.nil? && arg2.nil?
- if arg1 != nil && arg2 != nil
+ if !arg1.nil? && !arg2.nil?
idx = arg1
idx += self.size if arg1 < 0
if idx >= 0 && idx <= self.size && arg2 > 0
@@ -196,8 +196,8 @@ class String
return nil
end
end
- unless str == nil || str == ""
- if arg1 != nil && arg2 !=nil
+ unless str.nil? || str == ""
+ if !arg1.nil? && !arg2.nil?
idx = arg1 >= 0 ? arg1 : self.size+arg1
str2 = self[0...idx] + self[idx+arg2..-1].to_s
else
@@ -207,13 +207,13 @@ class String
str2 = self[0...idx] + self[idx2+1..-1].to_s
elsif arg1.kind_of?(String)
idx = self.index(arg1)
- str2 = self[0...idx] + self[idx+arg1.size..-1] unless idx == nil
+ str2 = self[0...idx] + self[idx+arg1.size..-1] unless idx.nil?
else
idx = arg1 >= 0 ? arg1 : self.size+arg1
str2 = self[0...idx] + self[idx+1..-1].to_s
end
end
- self.replace(str2) unless str2 == nil
+ self.replace(str2) unless str2.nil?
end
str
end
diff --git a/mrblib/array.rb b/mrblib/array.rb
index 933f822db..65dd0d665 100644
--- a/mrblib/array.rb
+++ b/mrblib/array.rb
@@ -16,7 +16,7 @@ class Array
while idx < length and length <= self.length and length = self.length-1
elm = self[idx += 1]
unless elm
- if elm == nil and length >= self.length
+ if elm.nil? and length >= self.length
break
end
end
@@ -50,9 +50,7 @@ class Array
def collect!(&block)
return to_enum :collect! unless block_given?
- self.each_index{|idx|
- self[idx] = block.call(self[idx])
- }
+ self.each_index { |idx| self[idx] = block.call(self[idx]) }
self
end
@@ -72,7 +70,7 @@ class Array
self.clear
if size > 0
- self[size - 1] = nil # allocate
+ self[size - 1] = nil # allocate
idx = 0
while idx < size
@@ -158,14 +156,11 @@ class Array
len = self.size
n = other.size
- if len > n
- len = n
- end
+ len = n if len > n
i = 0
while i < len
n = (self[i] <=> other[i])
- return n if n == nil
- return n if n != 0
+ return n if n.nil? || n != 0
i += 1
end
len = self.size - other.size
@@ -185,20 +180,14 @@ class Array
self.delete_at(i)
ret = key
end
- if ret == nil && block
- block.call
- else
- ret
- end
+ return block.call if ret.nil? && block
+ ret
end
# internal method to convert multi-value to single value
def __svalue
- if self.size < 2
- self.first
- else
- self
- end
+ return self.first if self.size < 2
+ self
end
end
diff --git a/mrblib/enum.rb b/mrblib/enum.rb
index e979fe90e..f0c9a4884 100644
--- a/mrblib/enum.rb
+++ b/mrblib/enum.rb
@@ -24,17 +24,9 @@ module Enumerable
# ISO 15.3.2.2.1
def all?(&block)
if block
- self.each{|*val|
- unless block.call(*val)
- return false
- end
- }
+ self.each{|*val| return false unless block.call(*val)}
else
- self.each{|*val|
- unless val.__svalue
- return false
- end
- }
+ self.each{|*val| return false unless val.__svalue}
end
true
end
@@ -49,17 +41,9 @@ module Enumerable
# ISO 15.3.2.2.2
def any?(&block)
if block
- self.each{|*val|
- if block.call(*val)
- return true
- end
- }
+ self.each{|*val| return true if block.call(*val)}
else
- self.each{|*val|
- if val.__svalue
- return true
- end
- }
+ self.each{|*val| return true if val.__svalue}
end
false
end
@@ -75,9 +59,7 @@ module Enumerable
return to_enum :collect unless block
ary = []
- self.each{|*val|
- ary.push(block.call(*val))
- }
+ self.each{|*val| ary.push(block.call(*val))}
ary
end
@@ -183,9 +165,7 @@ module Enumerable
# ISO 15.3.2.2.10
def include?(obj)
self.each{|*val|
- if val.__svalue == obj
- return true
- end
+ return true if val.__svalue == obj
}
false
end
diff --git a/mrblib/error.rb b/mrblib/error.rb
index d76dd9c56..2674af7a2 100644
--- a/mrblib/error.rb
+++ b/mrblib/error.rb
@@ -1,18 +1,3 @@
-##
-# Exception
-#
-# ISO 15.2.22
-class Exception
-
- ##
- # Raise an exception.
- #
- # ISO 15.2.22.4.1
- def self.exception(*args, &block)
- self.new(*args, &block)
- end
-end
-
# ISO 15.2.24
class ArgumentError < StandardError
end
diff --git a/mrblib/numeric.rb b/mrblib/numeric.rb
index cf608b04b..6e4c5027f 100644
--- a/mrblib/numeric.rb
+++ b/mrblib/numeric.rb
@@ -100,7 +100,7 @@ module Integral
# Calls the given block from +self+ to +num+
# incremented by +step+ (default 1).
#
- def step(num, step=1, &block)
+ def step(num, step = 1, &block)
raise ArgumentError, "step can't be 0" if step == 0
return to_enum(:step, num, step) unless block_given?
@@ -165,16 +165,30 @@ class Float
# floats should be compatible to integers.
def >> other
n = self.to_i
- other.to_i.times {
- n /= 2
- }
- n
+ other = other.to_i
+ if other < 0
+ n << -other
+ else
+ other.times { n /= 2 }
+ if n.abs < 1
+ if n >= 0
+ 0
+ else
+ -1
+ end
+ else
+ n.to_i
+ end
+ end
end
def << other
n = self.to_i
- other.to_i.times {
- n *= 2
- }
- n.to_i
+ other = other.to_i
+ if other < 0
+ n >> -other
+ else
+ other.times { n *= 2 }
+ n
+ end
end
end
diff --git a/mrblib/range.rb b/mrblib/range.rb
index 64fa0cb6c..5e5fd9bdc 100644
--- a/mrblib/range.rb
+++ b/mrblib/range.rb
@@ -26,9 +26,7 @@ class Range
return self
end
- unless val.respond_to? :succ
- raise TypeError, "can't iterate"
- end
+ raise TypeError, "can't iterate" unless val.respond_to? :succ
return self if (val <=> last) > 0
@@ -37,18 +35,14 @@ class Range
val = val.succ
end
- if not exclude_end? and (val <=> last) == 0
- block.call(val)
- 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
- if self.exclude_end?
- h += 1
- end
+ h += 1 if self.exclude_end?
h
end
end
diff --git a/mrblib/string.rb b/mrblib/string.rb
index 23cf02e97..05b13cb43 100644
--- a/mrblib/string.rb
+++ b/mrblib/string.rb
@@ -80,12 +80,8 @@ class String
# ISO 15.2.10.5.19
def gsub!(*args, &block)
str = self.gsub(*args, &block)
- if str != self
- self.replace(str)
- self
- else
- nil
- end
+ return nil if str == self
+ self.replace(str)
end
##
@@ -129,12 +125,8 @@ class String
# ISO 15.2.10.5.37
def sub!(*args, &block)
str = self.sub(*args, &block)
- if str != self
- self.replace(str)
- self
- else
- nil
- end
+ return nil if str == self
+ self.replace(str)
end
##
@@ -165,20 +157,16 @@ class String
# Modify +self+ by replacing the content of +self+
# at the position +pos+ with +value+.
def []=(pos, value)
- if pos < 0
- pos += self.length
- end
+ pos += self.length if pos < 0
b = self[0, pos]
- a = self[pos+1..-1]
+ a = self[pos + 1..-1]
self.replace([b, value, a].join(''))
end
##
# ISO 15.2.10.5.3
def =~(re)
- if re.respond_to? :to_str
- raise TypeError, "type mismatch: String given"
- end
+ raise TypeError, "type mismatch: String given" if re.respond_to? :to_str
re =~ self
end
diff --git a/src/dump.c b/src/dump.c
index 462e036b4..734f38043 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -16,7 +16,7 @@
#define FLAG_BYTEORDER_NONATIVE 0
#ifdef MRB_USE_FLOAT
-#define MRB_FLOAT_FMT "%.9e"
+#define MRB_FLOAT_FMT "%.8e"
#else
#define MRB_FLOAT_FMT "%.16e"
#endif
diff --git a/src/numeric.c b/src/numeric.c
index 14c0b76a6..1a3c903f0 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -820,11 +820,13 @@ fix_xor(mrb_state *mrb, mrb_value x)
static mrb_value
lshift(mrb_state *mrb, mrb_int val, mrb_int width)
{
- mrb_assert(width >= 0);
+ mrb_assert(width > 0);
if (width > NUMERIC_SHIFT_WIDTH_MAX) {
- mrb_raisef(mrb, E_RANGE_ERROR, "width(%S) > (%S:MRB_INT_BIT-1)",
- mrb_fixnum_value(width),
- mrb_fixnum_value(NUMERIC_SHIFT_WIDTH_MAX));
+ mrb_float f = (mrb_float)val;
+ while (width--) {
+ f *= 2;
+ }
+ return mrb_float_value(mrb, f);
}
return mrb_fixnum_value(val << width);
}
@@ -832,7 +834,7 @@ lshift(mrb_state *mrb, mrb_int val, mrb_int width)
static mrb_value
rshift(mrb_int val, mrb_int width)
{
- mrb_assert(width >= 0);
+ mrb_assert(width > 0);
if (width >= NUMERIC_SHIFT_WIDTH_MAX) {
if (val < 0) {
return mrb_fixnum_value(-1);
diff --git a/src/string.c b/src/string.c
index 45ba38c9d..08caf3bae 100644
--- a/src/string.c
+++ b/src/string.c
@@ -75,9 +75,18 @@ str_decref(mrb_state *mrb, mrb_shared_string *shared)
}
}
+static void
+check_frozen(mrb_state *mrb, struct RString *s)
+{
+ if (RSTR_FROZEN_P(s)) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string");
+ }
+}
+
MRB_API void
mrb_str_modify(mrb_state *mrb, struct RString *s)
{
+ check_frozen(mrb, s);
if (RSTR_SHARED_P(s)) {
mrb_shared_string *shared = s->as.heap.aux.shared;
@@ -119,6 +128,15 @@ mrb_str_modify(mrb_state *mrb, struct RString *s)
}
}
+static mrb_value
+mrb_str_freeze(mrb_state *mrb, mrb_value str)
+{
+ struct RString *s = mrb_str_ptr(str);
+
+ RSTR_SET_FROZEN_FLAG(s);
+ return str;
+}
+
MRB_API mrb_value
mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len)
{
@@ -1345,6 +1363,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
{
long len;
+ check_frozen(mrb, s1);
len = RSTR_LEN(s2);
if (RSTR_SHARED_P(s1)) {
str_decref(mrb, s1->as.heap.aux.shared);
@@ -1844,7 +1863,7 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
const char *p;
char sign = 1;
int c, uscore;
- unsigned long n = 0;
+ uint64_t n = 0;
mrb_int val;
#define conv_digit(c) \
@@ -1964,9 +1983,9 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
}
n *= base;
n += c;
- }
- if (n > MRB_INT_MAX) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", mrb_str_new_cstr(mrb, str));
+ if (n > MRB_INT_MAX) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", mrb_str_new_cstr(mrb, str));
+ }
}
val = n;
if (badcheck) {
@@ -2366,10 +2385,10 @@ mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2)
}
MRB_API mrb_value
-mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2)
+mrb_str_append(mrb_state *mrb, mrb_value str1, mrb_value str2)
{
str2 = mrb_str_to_str(mrb, str2);
- return mrb_str_cat_str(mrb, str, str2);
+ return mrb_str_cat_str(mrb, str1, str2);
}
#define CHAR_ESC_LEN 13 /* sizeof(\x{ hex of 32bit unsigned int } \0) */
@@ -2514,4 +2533,6 @@ mrb_init_string(mrb_state *mrb)
mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */
mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */
mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE());
}
diff --git a/src/version.c b/src/version.c
index 7aac44d62..fc3b2fc7a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -7,6 +7,7 @@ mrb_init_version(mrb_state* mrb)
mrb_define_global_const(mrb, "RUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_RUBY_VERSION));
mrb_define_global_const(mrb, "RUBY_ENGINE", mrb_str_new_lit(mrb, MRUBY_RUBY_ENGINE));
mrb_define_global_const(mrb, "MRUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_VERSION));
+ mrb_define_global_const(mrb, "MRUBY_RELEASE_NO", mrb_fixnum_value(MRUBY_RELEASE_NO));
mrb_define_global_const(mrb, "MRUBY_RELEASE_DATE", mrb_str_new_lit(mrb, MRUBY_RELEASE_DATE));
mrb_define_global_const(mrb, "MRUBY_DESCRIPTION", mrb_str_new_lit(mrb, MRUBY_DESCRIPTION));
mrb_define_global_const(mrb, "MRUBY_COPYRIGHT", mrb_str_new_lit(mrb, MRUBY_COPYRIGHT));
diff --git a/src/vm.c b/src/vm.c
index 00636a870..8419931d0 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -1486,9 +1486,6 @@ RETRY_TRY_BLOCK:
if (ci->ridx == 0) goto L_STOP;
goto L_RESCUE;
}
- while (eidx > ci[-1].eidx) {
- ecall(mrb, --eidx);
- }
while (ci[0].ridx == ci[-1].ridx) {
cipop(mrb);
ci = mrb->c->ci;
diff --git a/test/bintest.rb b/test/bintest.rb
index 0ff3341a0..49990abb9 100644
--- a/test/bintest.rb
+++ b/test/bintest.rb
@@ -2,7 +2,7 @@ $:.unshift File.dirname(File.dirname(File.expand_path(__FILE__)))
require 'test/assert.rb'
ARGV.each do |gem|
- Dir["#{gem}/bintest/*.rb"].each do |file|
+ Dir["#{gem}/bintest/**/*.rb"].each do |file|
load file
end
end
diff --git a/test/t/float.rb b/test/t/float.rb
index d45709173..0aab0b1f2 100644
--- a/test/t/float.rb
+++ b/test/t/float.rb
@@ -178,3 +178,25 @@ assert('Float#nan?') do
assert_false (1.0/0.0).nan?
assert_false (-1.0/0.0).nan?
end
+
+assert('Float#<<') do
+ # Left Shift by one
+ assert_equal 46, 23.0 << 1
+
+ # Left Shift by a negative is Right Shift
+ assert_equal 23, 46.0 << -1
+end
+
+assert('Float#>>') do
+ # Right Shift by one
+ assert_equal 23, 46.0 >> 1
+
+ # Right Shift by a negative is Left Shift
+ assert_equal 46, 23.0 >> -1
+
+ # Don't raise on large Right Shift
+ assert_equal 0, 23.0 >> 128
+
+ # Don't raise on large Right Shift
+ assert_equal -1, -23.0 >> 128
+end
diff --git a/test/t/integer.rb b/test/t/integer.rb
index 6b8cc308d..be3c13db2 100644
--- a/test/t/integer.rb
+++ b/test/t/integer.rb
@@ -147,11 +147,6 @@ assert('Integer#<<', '15.2.8.3.12') do
# Left Shift by a negative is Right Shift
assert_equal 23, 46 << -1
-
- # Raise when shift is too large
- assert_raise(RangeError) do
- 2 << 128
- end
end
assert('Integer#>>', '15.2.8.3.13') do
@@ -165,11 +160,6 @@ assert('Integer#>>', '15.2.8.3.13') do
# Don't raise on large Right Shift
assert_equal 0, 23 >> 128
-
- # Raise when shift is too large
- assert_raise(RangeError) do
- 2 >> -128
- end
end
assert('Integer#ceil', '15.2.8.3.14') do
diff --git a/test/t/string.rb b/test/t/string.rb
index ee6fe0848..7326adce9 100644
--- a/test/t/string.rb
+++ b/test/t/string.rb
@@ -542,3 +542,11 @@ assert('String#each_byte') do
assert_equal bytes1, bytes2
end
+
+assert('String#freeze') do
+ str = "hello"
+ str.freeze
+
+ assert_raise(RuntimeError) { str.upcase! }
+end
+