diff options
| -rw-r--r-- | build_config.rb | 8 | ||||
| -rw-r--r-- | include/mrbconf.h | 2 | ||||
| -rw-r--r-- | include/mruby.h | 9 | ||||
| -rw-r--r-- | include/mruby/compile.h | 8 | ||||
| -rw-r--r-- | include/mruby/hash.h | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-array-ext/mrblib/array.rb | 98 | ||||
| -rw-r--r-- | mrbgems/mruby-array-ext/test/array.rb | 79 | ||||
| -rw-r--r-- | mrbgems/mruby-enum-ext/mrblib/enum.rb | 79 | ||||
| -rw-r--r-- | mrbgems/mruby-enum-ext/test/enum.rb | 19 | ||||
| -rw-r--r-- | mrbgems/mruby-eval/mrbgem.rake | 4 | ||||
| -rw-r--r-- | mrbgems/mruby-eval/src/eval.c | 23 | ||||
| -rw-r--r-- | mrbgems/mruby-hash-ext/mrbgem.rake | 4 | ||||
| -rw-r--r-- | mrbgems/mruby-hash-ext/mrblib/hash.rb | 12 | ||||
| -rw-r--r-- | mrbgems/mruby-hash-ext/test/hash.rb | 20 | ||||
| -rw-r--r-- | mrbgems/mruby-struct/src/struct.c | 6 | ||||
| -rw-r--r-- | src/array.c | 4 | ||||
| -rw-r--r-- | src/class.c | 17 | ||||
| -rw-r--r-- | src/codegen.c | 42 | ||||
| -rw-r--r-- | src/error.c | 26 | ||||
| -rw-r--r-- | src/hash.c | 10 | ||||
| -rw-r--r-- | src/kernel.c | 6 | ||||
| -rw-r--r-- | src/node.h | 2 | ||||
| -rw-r--r-- | src/parse.y | 183 | ||||
| -rw-r--r-- | src/string.c | 6 | ||||
| -rw-r--r-- | src/symbol.c | 2 | ||||
| -rw-r--r-- | src/variable.c | 4 | ||||
| -rw-r--r-- | src/vm.c | 12 |
27 files changed, 572 insertions, 115 deletions
diff --git a/build_config.rb b/build_config.rb index d41c44b98..475ff27a8 100644 --- a/build_config.rb +++ b/build_config.rb @@ -35,9 +35,15 @@ MRuby::Build.new do |conf| # Use extensional Array class conf.gem "#{root}/mrbgems/mruby-array-ext" + # Use extensional Hash class + conf.gem "#{root}/mrbgems/mruby-hash-ext" + + # No use eval method + # conf.gem "#{root}/mrbgems/mruby-eval + # Generate binaries # conf.bins = %w(mrbc mruby mirb) - + # C compiler settings # conf.cc do |cc| # cc.command = ENV['CC'] || 'gcc' diff --git a/include/mrbconf.h b/include/mrbconf.h index 030e00c9f..a6914cdb4 100644 --- a/include/mrbconf.h +++ b/include/mrbconf.h @@ -49,6 +49,8 @@ /* initial minimum size for string buffer */ //#define MRB_STR_BUF_MIN_SIZE 128 +/* array size for parser buffer */ +//#define MRB_PARSER_BUF_SIZE 1024 /* -DDISABLE_XXXX to drop following features */ //#define DISABLE_STDIO /* use of stdio */ diff --git a/include/mruby.h b/include/mruby.h index 84aeff0d7..c5c607893 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -189,13 +189,20 @@ int mrb_get_args(mrb_state *mrb, const char *format, ...); mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, int,...); mrb_value mrb_funcall_argv(mrb_state*, mrb_value, mrb_sym, int, mrb_value*); mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, mrb_sym, int, mrb_value*, mrb_value); -mrb_sym mrb_intern(mrb_state*,const char*); +mrb_sym mrb_intern_cstr(mrb_state*,const char*); mrb_sym mrb_intern2(mrb_state*,const char*,size_t); mrb_sym mrb_intern_str(mrb_state*,mrb_value); const char *mrb_sym2name(mrb_state*,mrb_sym); const char *mrb_sym2name_len(mrb_state*,mrb_sym,size_t*); mrb_value mrb_str_format(mrb_state *, int, const mrb_value *, mrb_value); +/* For backward compatibility. */ +static inline +mrb_sym mrb_intern(mrb_state *mrb,const char *cstr) +{ + return mrb_intern_cstr(mrb, cstr); +} + void *mrb_malloc(mrb_state*, size_t); void *mrb_calloc(mrb_state*, size_t, size_t); void *mrb_realloc(mrb_state*, void*, size_t); diff --git a/include/mruby/compile.h b/include/mruby/compile.h index 8b0743fa3..26f8a597f 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -65,6 +65,7 @@ struct mrb_parser_message { #define STR_FUNC_SYMBOL 0x10 #define STR_FUNC_ARRAY 0x20 #define STR_FUNC_HEREDOC 0x40 +#define STR_FUNC_XQUOTE 0x80 enum mrb_string_type { str_not_parsing = (0), @@ -77,6 +78,7 @@ enum mrb_string_type { str_ssymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY), str_dsymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY|STR_FUNC_EXPAND), str_heredoc = (STR_FUNC_PARSING|STR_FUNC_HEREDOC), + str_xquote = (STR_FUNC_PARSING|STR_FUNC_XQUOTE|STR_FUNC_EXPAND), }; /* heredoc structure */ @@ -89,6 +91,10 @@ struct mrb_parser_heredoc_info { mrb_ast_node *doc; }; +#ifndef MRB_PARSER_BUF_SIZE +# define MRB_PARSER_BUF_SIZE 1024 +#endif + /* parser structure */ struct mrb_parser_state { mrb_state *mrb; @@ -111,7 +117,7 @@ struct mrb_parser_state { mrb_ast_node *locals; mrb_ast_node *pb; - char buf[1024]; + char buf[MRB_PARSER_BUF_SIZE]; int bidx; mrb_ast_node *heredocs; /* list of mrb_parser_heredoc_info* */ diff --git a/include/mruby/hash.h b/include/mruby/hash.h index ac28f13fd..baace7567 100644 --- a/include/mruby/hash.h +++ b/include/mruby/hash.h @@ -33,7 +33,7 @@ mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); /* RHASH_TBL allocates st_table if not available. */ #define RHASH(obj) ((struct RHash*)((obj).value.p)) #define RHASH_TBL(h) (RHASH(h)->ht) -#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern(mrb, "ifnone")) +#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern2(mrb, "ifnone", 6)) #define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h) struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash); diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb new file mode 100644 index 000000000..b3ff9bfca --- /dev/null +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -0,0 +1,98 @@ +class Array + def uniq! + ary = self.dup + result = [] + while ary.size > 0 + result << ary.shift + ary.delete(result.last) + end + if result.size == self.size + nil + else + self.replace(result) + end + end + + def uniq + ary = self.dup + ary.uniq! + ary + end + + def -(elem) + raise TypeError, "can't convert to Array" unless elem.class == Array + + hash = {} + array = [] + elem.each { |x| hash[x] = true } + self.each { |x| array << x unless hash[x] } + array + end + + def |(elem) + raise TypeError, "can't convert to Array" unless elem.class == Array + + ary = self + elem + ary.uniq! or ary + end + + def &(elem) + raise TypeError, "can't convert to Array" unless elem.class == Array + + hash = {} + array = [] + elem.each{|v| hash[v] = true } + self.each do |v| + if hash[v] + array << v + hash.delete v + end + end + array + end + + def flatten(depth=nil) + ar = [] + self.each do |e| + if e.is_a?(Array) && (depth.nil? || depth > 0) + ar += e.flatten(depth.nil? ? nil : depth - 1) + else + ar << e + end + end + ar + end + + def flatten!(depth=nil) + modified = false + ar = [] + self.each do |e| + if e.is_a?(Array) && (depth.nil? || depth > 0) + ar += e.flatten(depth.nil? ? nil : depth - 1) + modified = true + else + ar << e + end + end + if modified + self.replace(ar) + else + nil + end + end + + def compact + result = self.dup + result.compact! + result + end + + def compact! + result = self.select { |e| e != nil } + if result.size == self.size + nil + else + self.replace(result) + end + end +end diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb index 36da6bb17..1c441cec4 100644 --- a/mrbgems/mruby-array-ext/test/array.rb +++ b/mrbgems/mruby-array-ext/test/array.rb @@ -28,3 +28,82 @@ assert("Array#rassoc") do a.rassoc("four").nil? end +assert("Array#uniq!") do + a = [1, 2, 3, 1] + a.uniq! + a == [1, 2, 3] +end + +assert("Array#uniq") do + a = [1, 2, 3, 1] + a.uniq == [1, 2, 3] && a == [1, 2, 3, 1] +end + +assert("Array#-") do + a = [1, 2, 3, 1] + b = [1] + c = 1 + e1 = nil + + begin + a - c + rescue => e1 + end + + (a - b) == [2, 3] and e1.class == TypeError and a == [1, 2, 3, 1] +end + +assert("Array#|") do + a = [1, 2, 3, 1] + b = [1, 4] + c = 1 + e1 = nil + + begin + a | c + rescue => e1 + end + + (a | b) == [1, 2, 3, 4] and e1.class == TypeError and a == [1, 2, 3, 1] +end + +assert("Array#&") do + a = [1, 2, 3, 1] + b = [1, 4] + c = 1 + e1 = nil + + begin + a & c + rescue => e1 + end + + (a & b) == [1] and e1.class == TypeError and a == [1, 2, 3, 1] +end + +assert("Array#flatten") do + [1, 2, "3", {4=>5}, :'6'] == [1, 2, "3", {4=>5}, :'6'].flatten and + [1, 2, 3, 4, 5, 6] == [1, 2, [3, 4, 5], 6].flatten and + [1, 2, 3, 4, 5, 6] == [1, 2, [3, [4, 5], 6]].flatten and + [1, [2, [3, [4, [5, [6]]]]]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(0) and + [1, 2, [3, [4, [5, [6]]]]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(1) and + [1, 2, 3, [4, [5, [6]]]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(2) and + [1, 2, 3, 4, [5, [6]]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(3) and + [1, 2, 3, 4, 5, [6]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(4) and + [1, 2, 3, 4, 5, 6] == [1, [2, [3, [4, [5, [6]]]]]].flatten(5) +end + +assert("Array#flatten!") do + [1, 2, 3, 4, 5, 6] == [1, 2, [3, [4, 5], 6]].flatten! +end + +assert("Array#compact") do + a = [1, nil, "2", nil, :t, false, nil] + a.compact == [1, "2", :t, false] && a == [1, nil, "2", nil, :t, false, nil] +end + +assert("Array#compact!") do + a = [1, nil, "2", nil, :t, false, nil] + a.compact! + a == [1, "2", :t, false] +end diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index a9545da98..f250d39f1 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -82,4 +82,83 @@ module Enumerable ary end + ## + # call-seq: + # enum.each_cons(n) {...} -> nil + # + # Iterates the given block for each array of consecutive <n> + # elements. + # + # e.g.: + # (1..10).each_cons(3) {|a| p a} + # # outputs below + # [1, 2, 3] + # [2, 3, 4] + # [3, 4, 5] + # [4, 5, 6] + # [5, 6, 7] + # [6, 7, 8] + # [7, 8, 9] + # [8, 9, 10] + + def each_cons(n, &block) + raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer + raise ArgumentError, "invalid size" if n <= 0 + + ary = [] + self.each do |e| + ary.shift if ary.size == n + ary << e + block.call(ary.dup) if ary.size == n + end + end + + ## + # call-seq: + # enum.each_slice(n) {...} -> nil + # + # Iterates the given block for each slice of <n> elements. + # + # e.g.: + # (1..10).each_slice(3) {|a| p a} + # # outputs below + # [1, 2, 3] + # [4, 5, 6] + # [7, 8, 9] + # [10] + + def each_slice(n, &block) + raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer + raise ArgumentError, "invalid slice size" if n <= 0 + + ary = [] + self.each do |e| + ary << e + if ary.size == n + block.call(ary) + ary = [] + end + end + block.call(ary) unless ary.empty? + end + + ## + # call-seq: + # enum.group_by {| obj | block } -> a_hash + # + # Returns a hash, which keys are evaluated result from the + # block, and values are arrays of elements in <i>enum</i> + # corresponding to the key. + # + # (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]} + + def group_by(&block) + h = {} + self.each do |e| + key = block.call(e) + h.key?(key) ? (h[key] << e) : (h[key] = [e]) + end + h + end + end diff --git a/mrbgems/mruby-enum-ext/test/enum.rb b/mrbgems/mruby-enum-ext/test/enum.rb index 5fc9759ad..aa56cdf84 100644 --- a/mrbgems/mruby-enum-ext/test/enum.rb +++ b/mrbgems/mruby-enum-ext/test/enum.rb @@ -23,3 +23,22 @@ assert("Enumerable#take_while") do assert_equal a.take_while {|i| i < 3 }, [1, 2] end +assert("Enumerable#each_cons") do + a = [] + (1..5).each_cons(3){|e| a << e} + assert_equal a, [[1, 2, 3], [2, 3, 4], [3, 4, 5]] +end + +assert("Enumerable#each_slice") do + a = [] + (1..10).each_slice(3){|e| a << e} + assert_equal a, [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] +end + +assert("Enumerable#group_by") do + r = (1..6).group_by {|i| i % 3 } + assert_equal r[0], [3, 6] + assert_equal r[1], [1, 4] + assert_equal r[2], [2, 5] +end + diff --git a/mrbgems/mruby-eval/mrbgem.rake b/mrbgems/mruby-eval/mrbgem.rake new file mode 100644 index 000000000..f80cf1b9e --- /dev/null +++ b/mrbgems/mruby-eval/mrbgem.rake @@ -0,0 +1,4 @@ +MRuby::Gem::Specification.new('mruby-eval') do |spec| + spec.license = 'MIT' + spec.authors = 'mruby developers' +end diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c new file mode 100644 index 000000000..039558596 --- /dev/null +++ b/mrbgems/mruby-eval/src/eval.c @@ -0,0 +1,23 @@ +#include "mruby.h" +#include "mruby/compile.h" + +static mrb_value +f_eval(mrb_state *mrb, mrb_value self) +{ + char *s; + int len; + + mrb_get_args(mrb, "s", &s, &len); + return mrb_load_nstring(mrb, s, len); +} + +void +mrb_mruby_eval_gem_init(mrb_state* mrb) +{ + mrb_define_class_method(mrb, mrb->kernel_module, "eval", f_eval, ARGS_REQ(1)); +} + +void +mrb_mruby_eval_gem_final(mrb_state* mrb) +{ +} diff --git a/mrbgems/mruby-hash-ext/mrbgem.rake b/mrbgems/mruby-hash-ext/mrbgem.rake new file mode 100644 index 000000000..3163c8c88 --- /dev/null +++ b/mrbgems/mruby-hash-ext/mrbgem.rake @@ -0,0 +1,4 @@ +MRuby::Gem::Specification.new('mruby-hash-ext') do |spec| + spec.license = 'MIT' + spec.authors = 'mruby developers' +end diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb new file mode 100644 index 000000000..3e1bac0a2 --- /dev/null +++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb @@ -0,0 +1,12 @@ +class Hash + def merge!(other, &block) + if block + other.each_key{|k| + self[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k] + } + else + other.each_key{|k| self[k] = other[k]} + end + self + end +end diff --git a/mrbgems/mruby-hash-ext/test/hash.rb b/mrbgems/mruby-hash-ext/test/hash.rb new file mode 100644 index 000000000..98eb313a4 --- /dev/null +++ b/mrbgems/mruby-hash-ext/test/hash.rb @@ -0,0 +1,20 @@ +## +# Hash(Ext) Test + +assert('Hash#merge!') do + a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' } + b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' } + + result_1 = a.merge! b + + a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' } + result_2 = a.merge!(b) do |key, original, new| + original + end + + result_1 == {'abc_key' => 'abc_value', 'cba_key' => 'XXX', + 'xyz_key' => 'xyz_value' } and + result_2 == {'abc_key' => 'abc_value', 'cba_key' => 'cba_value', + 'xyz_key' => 'xyz_value' } +end + diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index cf2085614..082843f12 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -49,7 +49,7 @@ mrb_struct_iv_get(mrb_state *mrb, mrb_value c, const char *name) mrb_value mrb_struct_s_members(mrb_state *mrb, mrb_value klass) { - mrb_value members = struct_ivar_get(mrb, klass, mrb_intern(mrb, "__members__")); + mrb_value members = struct_ivar_get(mrb, klass, mrb_intern2(mrb, "__members__", 11)); if (mrb_nil_p(members)) { mrb_raise(mrb, E_TYPE_ERROR, "uninitialized struct"); @@ -258,7 +258,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k } MRB_SET_INSTANCE_TT(c, MRB_TT_ARRAY); nstr = mrb_obj_value(c); - mrb_iv_set(mrb, nstr, mrb_intern(mrb, "__members__"), members); + mrb_iv_set(mrb, nstr, mrb_intern2(mrb, "__members__", 11), members); mrb_define_class_method(mrb, c, "new", mrb_instance_new, ARGS_ANY()); mrb_define_class_method(mrb, c, "[]", mrb_instance_new, ARGS_ANY()); @@ -393,7 +393,7 @@ num_members(mrb_state *mrb, struct RClass *klass) { mrb_value members; - members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern(mrb, "__members__")); + members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern2(mrb, "__members__", 11)); if (!mrb_array_p(members)) { mrb_raise(mrb, E_TYPE_ERROR, "broken members"); } diff --git a/src/array.c b/src/array.c index f5d82d326..bfdb1bb97 100644 --- a/src/array.c +++ b/src/array.c @@ -301,7 +301,7 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1) a1 = RARRAY(ary1); a2 = RARRAY(ary2); if (a1->len == a2->len && a1->ptr == a2->ptr) return mrb_fixnum_value(0); else { - mrb_sym cmp = mrb_intern(mrb, "<=>"); + mrb_sym cmp = mrb_intern2(mrb, "<=>", 3); len = RARRAY_LEN(ary1); if (len > RARRAY_LEN(ary2)) { @@ -1069,7 +1069,7 @@ mrb_ary_equal(mrb_state *mrb, mrb_value ary1) equal_p = 0; } else if (!mrb_array_p(ary2)) { - if (!mrb_respond_to(mrb, ary2, mrb_intern(mrb, "to_ary"))) { + if (!mrb_respond_to(mrb, ary2, mrb_intern2(mrb, "to_ary", 6))) { equal_p = 0; } else { diff --git a/src/class.c b/src/class.c index 74bd10415..63b9b39da 100644 --- a/src/class.c +++ b/src/class.c @@ -54,7 +54,7 @@ void mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name) { mrb_obj_iv_set(mrb, (struct RObject*)c, - mrb_intern(mrb, "__classid__"), mrb_symbol_value(name)); + mrb_intern2(mrb, "__classid__", 11), mrb_symbol_value(name)); } #define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c)) @@ -88,7 +88,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o) o->c = sc; mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc); mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o); - mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern(mrb, "__attached__"), mrb_obj_value(o)); + mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern2(mrb, "__attached__", 12), mrb_obj_value(o)); } struct RClass* @@ -115,7 +115,7 @@ setup_class(mrb_state *mrb, mrb_value outer, struct RClass *c, mrb_sym id) mrb_name_class(mrb, c, id); mrb_const_set(mrb, outer, id, mrb_obj_value(c)); mrb_obj_iv_set(mrb, (struct RObject*)c, - mrb_intern(mrb, "__outer__"), outer); + mrb_intern2(mrb, "__outer__", 9), outer); } struct RClass* @@ -123,7 +123,7 @@ mrb_class_outer_module(mrb_state *mrb, struct RClass *c) { mrb_value outer; - outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__outer__")); + outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__outer__", 9)); if (mrb_nil_p(outer)) return 0; return mrb_class_ptr(outer); } @@ -1138,7 +1138,7 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod) mrb_raise(mrb, E_TYPE_ERROR, "name should be a symbol"); } - if (mrb_respond_to(mrb,mod,mrb_intern(mrb,"inspect"))){ + if (mrb_respond_to(mrb,mod,mrb_intern2(mrb,"inspect",7))){ inspect = mrb_funcall(mrb, mod, "inspect", 0); if (RSTRING_LEN(inspect) > 64) { inspect = mrb_any_to_s(mrb, mod); @@ -1190,8 +1190,9 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) mrb_value path; const char *name; size_t len; + mrb_sym classpath = mrb_intern2(mrb, "__classpath__", 13); - path = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__")); + path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath); if (mrb_nil_p(path)) { struct RClass *outer = mrb_class_outer_module(mrb, c); mrb_sym sym = mrb_class_sym(mrb, c, outer); @@ -1208,7 +1209,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) name = mrb_sym2name_len(mrb, sym, &len); path = mrb_str_new(mrb, name, len); } - mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__"), path); + mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path); } return path; } @@ -1351,7 +1352,7 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass) { if (mrb_type(klass) == MRB_TT_SCLASS) { mrb_value s = mrb_str_new(mrb, "#<", 2); - mrb_value v = mrb_iv_get(mrb, klass, mrb_intern(mrb, "__attached__")); + mrb_value v = mrb_iv_get(mrb, klass, mrb_intern2(mrb, "__attached__", 12)); mrb_str_cat2(mrb, s, "Class:"); switch (mrb_type(v)) { diff --git a/src/codegen.c b/src/codegen.c index 3141fafe1..30efa248e 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -560,7 +560,7 @@ for_body(codegen_scope *s, node *tree) s = prev; genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx - base, OP_L_BLOCK)); pop(); - idx = new_msym(s, mrb_intern(s->mrb, "each")); + idx = new_msym(s, mrb_intern2(s->mrb, "each", 4)); genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0)); } @@ -960,7 +960,7 @@ static void gen_send_intern(codegen_scope *s) { pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "intern")), 0)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "intern", 6)), 0)); push(); } static void @@ -1152,12 +1152,12 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, n4->car, VAL); } else { - genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern(s->mrb, "StandardError")))); + genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern2(s->mrb, "StandardError", 13)))); push(); } genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1)); tmp = new_label(s); genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); pos2 = tmp; @@ -1361,7 +1361,7 @@ codegen(codegen_scope *s, node *tree, int val) if (head) { genop(s, MKOP_AB(OP_MOVE, cursp(), head)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1)); } else { pop(); @@ -1702,7 +1702,7 @@ codegen(codegen_scope *s, node *tree, int val) } pop_n(n+1); if (sendv) n = CALL_MAXARGS; - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "call")), n)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "call", 4)), n)); if (val) push(); } break; @@ -1969,7 +1969,7 @@ codegen(codegen_scope *s, node *tree, int val) default: { - int sym = new_msym(s, mrb_intern(s->mrb, "-")); + int sym = new_msym(s, mrb_intern2(s->mrb, "-", 1)); genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); push(); @@ -2032,6 +2032,26 @@ codegen(codegen_scope *s, node *tree, int val) gen_literal_array(s, tree, TRUE, val); break; + case NODE_XSTR: + if (val) { + char *p = (char*)tree->car; + size_t len = (intptr_t)tree->cdr; + int ai = mrb_gc_arena_save(s->mrb); + int sym = new_sym(s, mrb_intern2(s->mrb, "Kernel", 6)); + int off = new_lit(s, mrb_str_new(s->mrb, p, len)); + + genop(s, MKOP_A(OP_OCLASS, cursp())); + genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); + push(); + genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + pop(); + sym = new_sym(s, mrb_intern2(s->mrb, "`", 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); + mrb_gc_arena_restore(s->mrb, ai); + push(); + } + break; + case NODE_REGX: if (val) { char *p1 = (char*)tree->car; @@ -2053,7 +2073,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); } pop(); - sym = new_sym(s, mrb_intern(s->mrb, "compile")); + sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2101,7 +2121,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); } pop(); - sym = new_sym(s, mrb_intern(s->mrb, "compile")); + sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2166,7 +2186,7 @@ codegen(codegen_scope *s, node *tree, int val) { int a = new_msym(s, sym(tree->car)); int b = new_msym(s, sym(tree->cdr)); - int c = new_msym(s, mrb_intern(s->mrb, "alias_method")); + int c = new_msym(s, mrb_intern2(s->mrb, "alias_method", 12)); genop(s, MKOP_A(OP_TCLASS, cursp())); push(); @@ -2185,7 +2205,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_UNDEF: { - int undef = new_msym(s, mrb_intern(s->mrb, "undef_method")); + int undef = new_msym(s, mrb_intern2(s->mrb, "undef_method", 12)); int num = 0; node *t = tree; diff --git a/src/error.c b/src/error.c index b65ff2183..7cb6b53ef 100644 --- a/src/error.c +++ b/src/error.c @@ -44,7 +44,7 @@ exc_initialize(mrb_state *mrb, mrb_value exc) mrb_value mesg; if (mrb_get_args(mrb, "|o", &mesg) == 1) { - mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), mesg); + mrb_iv_set(mrb, exc, mrb_intern2(mrb, "mesg", 4), mesg); } return exc; } @@ -73,7 +73,7 @@ exc_exception(mrb_state *mrb, mrb_value self) if (argc == 0) return self; if (mrb_obj_equal(mrb, self, a)) return self; exc = mrb_obj_clone(mrb, self); - mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), a); + mrb_iv_set(mrb, exc, mrb_intern2(mrb, "mesg", 4), a); return exc; } @@ -89,7 +89,7 @@ exc_exception(mrb_state *mrb, mrb_value self) static mrb_value exc_to_s(mrb_state *mrb, mrb_value exc) { - mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg")); + mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "mesg", 4)); if (mrb_nil_p(mesg)) return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc)); return mesg; @@ -123,9 +123,9 @@ exc_inspect(mrb_state *mrb, mrb_value exc) { mrb_value str, mesg, file, line; - mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg")); - file = mrb_attr_get(mrb, exc, mrb_intern(mrb, "file")); - line = mrb_attr_get(mrb, exc, mrb_intern(mrb, "line")); + mesg = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "mesg", 4)); + file = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "file", 4)); + line = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "line", 4)); if (!mrb_nil_p(file) && !mrb_nil_p(line)) { str = file; @@ -161,7 +161,7 @@ exc_equal(mrb_state *mrb, mrb_value exc) mrb_value obj; mrb_value mesg; mrb_bool equal_p; - mrb_sym id_mesg = mrb_intern(mrb, "mesg"); + mrb_sym id_mesg = mrb_intern2(mrb, "mesg", 4); mrb_get_args(mrb, "o", &obj); if (mrb_obj_equal(mrb, exc, obj)) { @@ -169,7 +169,7 @@ exc_equal(mrb_state *mrb, mrb_value exc) } else { if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) { - if (mrb_respond_to(mrb, obj, mrb_intern(mrb, "message"))) { + if (mrb_respond_to(mrb, obj, mrb_intern2(mrb, "message", 7))) { mesg = mrb_funcall(mrb, obj, "message", 0); } else @@ -191,15 +191,15 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) mrb_callinfo *ci = mrb->ci; mrb_code *pc = ci->pc; - mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->cibase)); + mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->cibase)); ci--; while (ci >= mrb->cibase) { if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) { mrb_irep *irep = ci->proc->body.irep; if (irep->filename && irep->lines && irep->iseq <= pc && pc < irep->iseq + irep->ilen) { - mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "file"), mrb_str_new_cstr(mrb, irep->filename)); - mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "line"), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1])); + mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "file", 4), mrb_str_new_cstr(mrb, irep->filename)); + mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "line", 4), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1])); return; } } @@ -335,7 +335,7 @@ mrb_bug_errno(const char *mesg, int errno_arg) int sysexit_status(mrb_state *mrb, mrb_value err) { - mrb_value st = mrb_iv_get(mrb, err, mrb_intern(mrb, "status")); + mrb_value st = mrb_iv_get(mrb, err, mrb_intern2(mrb, "status", 6)); return mrb_fixnum(st); } @@ -373,7 +373,7 @@ make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr) n = 1; exception_call: { - mrb_sym exc = mrb_intern(mrb, "exception"); + mrb_sym exc = mrb_intern2(mrb, "exception", 9); if (mrb_respond_to(mrb, argv[0], exc)) { mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1); } diff --git a/src/hash.c b/src/hash.c index 262c713b6..6976530e1 100644 --- a/src/hash.c +++ b/src/hash.c @@ -262,7 +262,7 @@ mrb_hash_init_core(mrb_state *mrb, mrb_value hash) RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; ifnone = block; } - mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); return hash; } @@ -427,7 +427,7 @@ mrb_hash_set_default(mrb_state *mrb, mrb_value hash) mrb_get_args(mrb, "o", &ifnone); mrb_hash_modify(mrb, hash); - mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); RHASH(hash)->flags &= ~(MRB_HASH_PROC_DEFAULT); return ifnone; @@ -478,7 +478,7 @@ mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash) mrb_get_args(mrb, "o", &ifnone); mrb_hash_modify(mrb, hash); - mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; return ifnone; @@ -759,7 +759,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash) else { ifnone = RHASH_IFNONE(hash2); } - mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); return hash; } @@ -1104,7 +1104,7 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value(); if (!mrb_hash_p(hash2)) { - if (!mrb_respond_to(mrb, hash2, mrb_intern(mrb, "to_hash"))) { + if (!mrb_respond_to(mrb, hash2, mrb_intern2(mrb, "to_hash", 7))) { return mrb_false_value(); } if (eql) diff --git a/src/kernel.c b/src/kernel.c index 66bd7b233..0c746d987 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -29,7 +29,7 @@ typedef enum { int mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) { - struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern(mrb, "to_s")); + struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern2(mrb, "to_s", 4)); if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s)) return TRUE; return FALSE; @@ -283,7 +283,7 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) clone->super = klass->super; if (klass->iv) { mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass)); - mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern(mrb, "__attached__"), obj); + mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern2(mrb, "__attached__", 12), obj); } if (klass->mt) { clone->mt = kh_copy(mt, mrb, klass->mt); @@ -928,7 +928,7 @@ mrb_f_raise(mrb_state *mrb, mrb_value self) /* fall through */ default: exc = mrb_make_exception(mrb, argc, a); - mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern(mrb, "lastpc"), mrb_voidp_value(mrb->ci->pc)); + mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(mrb->ci->pc)); mrb_exc_raise(mrb, exc); break; } diff --git a/src/node.h b/src/node.h index 4f9db8265..df27c431f 100644 --- a/src/node.h +++ b/src/node.h @@ -65,6 +65,8 @@ enum node_type { NODE_SYM, NODE_STR, NODE_DSTR, + NODE_XSTR, + NODE_DXSTR, NODE_REGX, NODE_DREGX, NODE_DREGX_ONCE, diff --git a/src/parse.y b/src/parse.y index 8f1241d33..29ea34c59 100644 --- a/src/parse.y +++ b/src/parse.y @@ -61,13 +61,27 @@ typedef unsigned int stack_type; #define sym(x) ((mrb_sym)(intptr_t)(x)) #define nsym(x) ((node*)(intptr_t)(x)) -static mrb_sym +static inline mrb_sym intern_gen(parser_state *p, const char *s) { return mrb_intern(p->mrb, s); } #define intern(s) intern_gen(p,(s)) +static inline mrb_sym +intern_gen2(parser_state *p, const char *s, size_t len) +{ + return mrb_intern2(p->mrb, s, len); +} +#define intern2(s,len) intern_gen2(p,(s),(len)) + +static inline mrb_sym +intern_gen_c(parser_state *p, const char c) +{ + return mrb_intern2(p->mrb, &c, 1); +} +#define intern_c(c) intern_gen_c(p,(c)) + static void cons_free_gen(parser_state *p, node *cons) { @@ -702,6 +716,20 @@ new_dstr(parser_state *p, node *a) return cons((node*)NODE_DSTR, a); } +// (:str . (s . len)) +static node* +new_xstr(parser_state *p, const char *s, int len) +{ + return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), (node*)(intptr_t)len)); +} + +// (:xstr . a) +static node* +new_dxstr(parser_state *p, node *a) +{ + return cons((node*)NODE_DXSTR, a); +} + // (:dsym . a) static node* new_dsym(parser_state *p, node *a) @@ -974,12 +1002,12 @@ heredoc_end(parser_state *p) keyword__ENCODING__ %token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL -%token <nd> tINTEGER tFLOAT tCHAR tREGEXP +%token <nd> tINTEGER tFLOAT tCHAR tXSTRING tREGEXP %token <nd> tSTRING tSTRING_PART tSTRING_MID %token <nd> tNTH_REF tBACK_REF %token <num> tREGEXP_END -%type <nd> singleton string string_rep string_interp regexp +%type <nd> singleton string string_rep string_interp xstring regexp %type <nd> literal numeric cpath symbol %type <nd> top_compstmt top_stmts top_stmt %type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call @@ -1028,7 +1056,7 @@ heredoc_end(parser_state *p) %token tAMPER /* & */ %token tLAMBDA /* -> */ %token tSYMBEG tREGEXP_BEG tWORDS_BEG tSYMBOLS_BEG -%token tSTRING_BEG tSTRING_DVAR tLAMBEG +%token tSTRING_BEG tXSTRING_BEG tSTRING_DVAR tLAMBEG %token <nd> tHEREDOC_BEG /* <<, <<- */ %token tHEREDOC_END tLITERAL_DELIM @@ -1214,7 +1242,7 @@ stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym } | primary_value '[' opt_call_args rbracket tOP_ASGN command_call { - $$ = new_op_asgn(p, new_call(p, $1, intern("[]"), $3), $5, $6); + $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6); } | primary_value '.' tIDENTIFIER tOP_ASGN command_call { @@ -1453,7 +1481,7 @@ mlhs_node : variable } | primary_value '[' opt_call_args rbracket { - $$ = new_call(p, $1, intern("[]"), $3); + $$ = new_call(p, $1, intern2("[]",2), $3); } | primary_value '.' tIDENTIFIER { @@ -1492,7 +1520,7 @@ lhs : variable } | primary_value '[' opt_call_args rbracket { - $$ = new_call(p, $1, intern("[]"), $3); + $$ = new_call(p, $1, intern2("[]",2), $3); } | primary_value '.' tIDENTIFIER { @@ -1575,34 +1603,35 @@ undef_list : fsym } ; -op : '|' { $$ = intern("|"); } - | '^' { $$ = intern("^"); } - | '&' { $$ = intern("&"); } - | tCMP { $$ = intern("<=>"); } - | tEQ { $$ = intern("=="); } - | tEQQ { $$ = intern("==="); } - | tMATCH { $$ = intern("=~"); } - | tNMATCH { $$ = intern("!~"); } - | '>' { $$ = intern(">"); } - | tGEQ { $$ = intern(">="); } - | '<' { $$ = intern("<"); } - | tLEQ { $$ = intern("<="); } - | tNEQ { $$ = intern("!="); } - | tLSHFT { $$ = intern("<<"); } - | tRSHFT { $$ = intern(">>"); } - | '+' { $$ = intern("+"); } - | '-' { $$ = intern("-"); } - | '*' { $$ = intern("*"); } - | tSTAR { $$ = intern("*"); } - | '/' { $$ = intern("/"); } - | '%' { $$ = intern("%"); } - | tPOW { $$ = intern("**"); } - | '!' { $$ = intern("!"); } - | '~' { $$ = intern("~"); } - | tUPLUS { $$ = intern("+@"); } - | tUMINUS { $$ = intern("-@"); } - | tAREF { $$ = intern("[]"); } - | tASET { $$ = intern("[]="); } +op : '|' { $$ = intern_c('|'); } + | '^' { $$ = intern_c('^'); } + | '&' { $$ = intern_c('&'); } + | tCMP { $$ = intern2("<=>",3); } + | tEQ { $$ = intern2("==",2); } + | tEQQ { $$ = intern2("===",3); } + | tMATCH { $$ = intern2("=~",2); } + | tNMATCH { $$ = intern2("!~",2); } + | '>' { $$ = intern_c('>'); } + | tGEQ { $$ = intern2(">=",2); } + | '<' { $$ = intern_c('<'); } + | tLEQ { $$ = intern2("<=",2); } + | tNEQ { $$ = intern2("!=",2); } + | tLSHFT { $$ = intern2("<<",2); } + | tRSHFT { $$ = intern2(">>",2); } + | '+' { $$ = intern_c('+'); } + | '-' { $$ = intern_c('-'); } + | '*' { $$ = intern_c('*'); } + | tSTAR { $$ = intern_c('*'); } + | '/' { $$ = intern_c('/'); } + | '%' { $$ = intern_c('%'); } + | tPOW { $$ = intern2("**",2); } + | '!' { $$ = intern_c('!'); } + | '~' { $$ = intern_c('~'); } + | tUPLUS { $$ = intern2("+@",2); } + | tUMINUS { $$ = intern2("-@",2); } + | tAREF { $$ = intern2("[]",2); } + | tASET { $$ = intern2("[]=",3); } + | '`' { $$ = intern_c('`'); } ; reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ @@ -1637,7 +1666,7 @@ arg : lhs '=' arg } | primary_value '[' opt_call_args rbracket tOP_ASGN arg { - $$ = new_op_asgn(p, new_call(p, $1, intern("[]"), $3), $5, $6); + $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6); } | primary_value '.' tIDENTIFIER tOP_ASGN arg { @@ -1936,6 +1965,7 @@ mrhs : args ',' arg_value primary : literal | string + | xstring | regexp | heredoc | var_ref @@ -2445,11 +2475,11 @@ method_call : operation paren_args } | primary_value '.' paren_args { - $$ = new_call(p, $1, intern("call"), $3); + $$ = new_call(p, $1, intern2("call",4), $3); } | primary_value tCOLON2 paren_args { - $$ = new_call(p, $1, intern("call"), $3); + $$ = new_call(p, $1, intern2("call",4), $3); } | keyword_super paren_args { @@ -2461,7 +2491,7 @@ method_call : operation paren_args } | primary_value '[' opt_call_args rbracket { - $$ = new_call(p, $1, intern("[]"), $3); + $$ = new_call(p, $1, intern2("[]",2), $3); } ; @@ -2585,6 +2615,16 @@ string_interp : tSTRING_MID } ; +xstring : tXSTRING_BEG tXSTRING + { + $$ = $2; + } + | tXSTRING_BEG string_rep tXSTRING + { + $$ = new_dxstr(p, push($2, $3)); + } + ; + regexp : tREGEXP_BEG tREGEXP { $$ = $2; @@ -2985,6 +3025,8 @@ singleton : var_ref switch ((enum node_type)(int)(intptr_t)$3->car) { case NODE_STR: case NODE_DSTR: + case NODE_XSTR: + case NODE_DXSTR: case NODE_DREGX: case NODE_MATCH: case NODE_FLOAT: @@ -3314,7 +3356,7 @@ newtok(parser_state *p) static void tokadd(parser_state *p, int c) { - if (p->bidx < 1024) { + if (p->bidx < MRB_PARSER_BUF_SIZE) { p->buf[p->bidx++] = c; } } @@ -3328,7 +3370,7 @@ toklast(parser_state *p) static void tokfix(parser_state *p) { - if (p->bidx >= 1024) { + if (p->bidx >= MRB_PARSER_BUF_SIZE) { yyerror(p, "string too long (truncated)"); } p->buf[p->bidx] = '\0'; @@ -3641,6 +3683,11 @@ parse_string(parser_state *p) p->lstate = EXPR_END; end_strterm(p); + if (type & STR_FUNC_XQUOTE) { + yylval.nd = new_xstr(p, tok(p), toklen(p)); + return tXSTRING; + } + if (type & STR_FUNC_REGEXP) { int f = 0; int c; @@ -3840,7 +3887,7 @@ parser_yylex(parser_state *p) case '*': if ((c = nextc(p)) == '*') { if ((c = nextc(p)) == '=') { - yylval.id = intern("**"); + yylval.id = intern2("**",2); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -3849,7 +3896,7 @@ parser_yylex(parser_state *p) } else { if (c == '=') { - yylval.id = intern("*"); + yylval.id = intern_c('*'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -3949,7 +3996,7 @@ parser_yylex(parser_state *p) } if (c == '<') { if ((c = nextc(p)) == '=') { - yylval.id = intern("<<"); + yylval.id = intern2("<<",2); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -3970,7 +4017,7 @@ parser_yylex(parser_state *p) } if (c == '>') { if ((c = nextc(p)) == '=') { - yylval.id = intern(">>"); + yylval.id = intern2(">>",2); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -3988,6 +4035,21 @@ parser_yylex(parser_state *p) p->lex_strterm = new_strterm(p, str_squote, '\'', 0); return parse_string(p); + case '`': + if (p->lstate == EXPR_FNAME) { + p->lstate = EXPR_ENDFN; + return '`'; + } + if (p->lstate == EXPR_DOT) { + if (cmd_state) + p->lstate = EXPR_CMDARG; + else + p->lstate = EXPR_ARG; + return '`'; + } + p->lex_strterm = new_strterm(p, str_xquote, '`', 0); + return tXSTRING_BEG; + case '?': if (IS_END()) { p->lstate = EXPR_VALUE; @@ -4069,7 +4131,7 @@ parser_yylex(parser_state *p) if ((c = nextc(p)) == '&') { p->lstate = EXPR_BEG; if ((c = nextc(p)) == '=') { - yylval.id = intern("&&"); + yylval.id = intern2("&&",2); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4077,7 +4139,7 @@ parser_yylex(parser_state *p) return tANDOP; } else if (c == '=') { - yylval.id = intern("&"); + yylval.id = intern_c('&'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4103,7 +4165,7 @@ parser_yylex(parser_state *p) if ((c = nextc(p)) == '|') { p->lstate = EXPR_BEG; if ((c = nextc(p)) == '=') { - yylval.id = intern("||"); + yylval.id = intern2("||",2); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4111,7 +4173,7 @@ parser_yylex(parser_state *p) return tOROP; } if (c == '=') { - yylval.id = intern("|"); + yylval.id = intern_c('|'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4135,7 +4197,7 @@ parser_yylex(parser_state *p) return '+'; } if (c == '=') { - yylval.id = intern("+"); + yylval.id = intern_c('+'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4163,7 +4225,7 @@ parser_yylex(parser_state *p) return '-'; } if (c == '=') { - yylval.id = intern("-"); + yylval.id = intern_c('-'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4463,7 +4525,7 @@ parser_yylex(parser_state *p) return tREGEXP_BEG; } if ((c = nextc(p)) == '=') { - yylval.id = intern("/"); + yylval.id = intern_c('/'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4481,7 +4543,7 @@ parser_yylex(parser_state *p) case '^': if ((c = nextc(p)) == '=') { - yylval.id = intern("^"); + yylval.id = intern_c('^'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4628,6 +4690,10 @@ parser_yylex(parser_state *p) p->lex_strterm = new_strterm(p, str_sword, term, paren); return tWORDS_BEG; + case 'x': + p->lex_strterm = new_strterm(p, str_xquote, term, paren); + return tXSTRING_BEG; + case 'r': p->lex_strterm = new_strterm(p, str_regexp, term, paren); return tREGEXP_BEG; @@ -4650,7 +4716,7 @@ parser_yylex(parser_state *p) } } if ((c = nextc(p)) == '=') { - yylval.id = intern("%"); + yylval.id = intern_c('%'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -5693,6 +5759,15 @@ parser_dump(mrb_state *mrb, node *tree, int offset) dump_recur(mrb, tree, offset+1); break; + case NODE_XSTR: + printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr); + break; + + case NODE_DXSTR: + printf("NODE_DXSTR\n"); + dump_recur(mrb, tree, offset+1); + break; + case NODE_REGX: printf("NODE_REGX /%s/%s\n", (char*)tree->car, (char*)tree->cdr); break; diff --git a/src/string.c b/src/string.c index 8f16a4ef0..97d53cd6c 100644 --- a/src/string.c +++ b/src/string.c @@ -532,10 +532,10 @@ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1) mrb_get_args(mrb, "o", &str2); if (!mrb_string_p(str2)) { - if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "to_s"))) { + if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "to_s", 4))) { return mrb_nil_value(); } - else if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "<=>"))) { + else if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "<=>", 3))) { return mrb_nil_value(); } else { @@ -572,7 +572,7 @@ mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2) if (mrb_obj_equal(mrb, str1, str2)) return TRUE; if (!mrb_string_p(str2)) { if (mrb_nil_p(str2)) return FALSE; - if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "to_str"))) { + if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "to_str", 6))) { return FALSE; } str2 = mrb_funcall(mrb, str2, "to_str", 0); diff --git a/src/symbol.c b/src/symbol.c index 6afc6b7a6..243cb4b5d 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -62,7 +62,7 @@ mrb_intern2(mrb_state *mrb, const char *name, size_t len) } mrb_sym -mrb_intern(mrb_state *mrb, const char *name) +mrb_intern_cstr(mrb_state *mrb, const char *name) { return mrb_intern2(mrb, name, strlen(name)); } diff --git a/src/variable.c b/src/variable.c index 850999042..4345f49a7 100644 --- a/src/variable.c +++ b/src/variable.c @@ -832,7 +832,7 @@ L_RETRY: goto L_RETRY; } c = base; - cm = mrb_intern(mrb, "const_missing"); + cm = mrb_intern2(mrb, "const_missing", 13); while (c) { if (mrb_respond_to(mrb, mrb_obj_value(c), cm)) { mrb_value name = mrb_symbol_value(sym); @@ -1047,7 +1047,7 @@ mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer) { mrb_value name; - name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classid__")); + name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__classid__", 11)); if (mrb_nil_p(name)) { if (!outer) return 0; @@ -349,7 +349,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr p = mrb_method_search_vm(mrb, &c, mid); if (!p) { undef = mid; - mid = mrb_intern(mrb, "method_missing"); + mid = mrb_intern2(mrb, "method_missing", 14); p = mrb_method_search_vm(mrb, &c, mid); n++; argc++; } @@ -869,7 +869,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (!m) { mrb_value sym = mrb_symbol_value(mid); - mid = mrb_intern(mrb, "method_missing"); + mid = mrb_intern2(mrb, "method_missing", 14); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); @@ -1011,7 +1011,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) c = mrb->ci->target_class->super; m = mrb_method_search_vm(mrb, &c, mid); if (!m) { - mid = mrb_intern(mrb, "method_missing"); + mid = mrb_intern2(mrb, "method_missing", 14); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid)); @@ -1216,8 +1216,8 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) L_RAISE: ci = mrb->ci; - mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern(mrb, "lastpc"), mrb_voidp_value(pc)); - mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->cibase)); + mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(pc)); + mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->cibase)); eidx = ci->eidx; if (ci == mrb->cibase) { if (ci->ridx == 0) goto L_STOP; @@ -1333,7 +1333,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (!m) { mrb_value sym = mrb_symbol_value(mid); - mid = mrb_intern(mrb, "method_missing"); + mid = mrb_intern2(mrb, "method_missing", 14); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); |
