summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby.h2
-rw-r--r--include/mruby/string.h4
-rw-r--r--lib/mruby-core-ext.rb40
-rw-r--r--lib/mruby/build.rb5
-rw-r--r--mrbgems/mruby-array-ext/mrblib/array.rb1
-rw-r--r--mrbgems/mruby-bin-config/mrbgem.rake (renamed from mrbgems/mruby-bin-mruby-config/mrbgem.rake)14
-rw-r--r--mrbgems/mruby-bin-config/mruby-config (renamed from mrbgems/mruby-bin-mruby-config/mruby-config)0
-rw-r--r--mrbgems/mruby-bin-config/mruby-config.bat (renamed from mrbgems/mruby-bin-mruby-config/mruby-config.bat)0
-rw-r--r--mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c2
-rw-r--r--mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c2
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c24
-rw-r--r--mrbgems/mruby-compiler/core/parse.y33
-rw-r--r--mrbgems/mruby-enum-ext/mrblib/enum.rb1
-rw-r--r--mrbgems/mruby-enumerator/mrblib/enumerator.rb2
-rw-r--r--mrbgems/mruby-struct/src/struct.c2
-rw-r--r--mrbgems/mruby-symbol-ext/src/symbol.c7
-rw-r--r--mrbgems/mruby-symbol-ext/test/symbol.rb15
-rw-r--r--mrblib/enum.rb2
-rw-r--r--src/class.c2
-rw-r--r--src/string.c79
-rw-r--r--src/symbol.c113
-rw-r--r--test/t/class.rb5
-rw-r--r--test/t/module.rb9
23 files changed, 222 insertions, 142 deletions
diff --git a/include/mruby.h b/include/mruby.h
index 8c8360784..2f2d98677 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -239,8 +239,8 @@ typedef struct mrb_state {
#endif
mrb_sym symidx;
- struct kh_n2s *name2sym; /* symbol hash */
struct symbol_name *symtbl; /* symbol table */
+ mrb_sym symhash[256];
size_t symcapa;
#ifdef MRB_ENABLE_DEBUG_HOOK
diff --git a/include/mruby/string.h b/include/mruby/string.h
index 3fe8295ff..6fe0556b0 100644
--- a/include/mruby/string.h
+++ b/include/mruby/string.h
@@ -439,6 +439,10 @@ void mrb_regexp_check(mrb_state *mrb, mrb_value obj);
#define mrb_str_buf_cat(mrb, str, ptr, len) mrb_str_cat(mrb, str, ptr, len)
#define mrb_str_buf_append(mrb, str, str2) mrb_str_cat_str(mrb, str, str2)
+#ifdef MRB_UTF8_STRING
+mrb_int mrb_utf8_len(const char *str, mrb_int byte_len);
+#endif
+
MRB_END_DECL
#endif /* MRUBY_STRING_H */
diff --git a/lib/mruby-core-ext.rb b/lib/mruby-core-ext.rb
index 4c6d3ca76..08e6f6148 100644
--- a/lib/mruby-core-ext.rb
+++ b/lib/mruby-core-ext.rb
@@ -18,18 +18,20 @@ class String
end
# Compatible with 1.9 on 1.8
- def %(params)
- if params.is_a?(Hash)
- str = self.clone
- params.each do |k, v|
- str.gsub!("%{#{k}}") { v }
- end
- str
- else
- if params.is_a?(Array)
- sprintf(self, *params)
+ unless (sprintf("%{a}", :a => 1) rescue false)
+ def %(params)
+ if params.is_a?(Hash)
+ str = self.clone
+ params.each do |k, v|
+ str.gsub!("%{#{k}}") { v }
+ end
+ str
else
- sprintf(self, params)
+ if params.is_a?(Array)
+ sprintf(self, *params)
+ else
+ sprintf(self, params)
+ end
end
end
end
@@ -37,17 +39,21 @@ end
class Symbol
# Compatible with 1.9 on 1.8
- def to_proc
- proc { |obj, *args| obj.send(self, *args) }
+ unless method_defined?(:to_proc)
+ def to_proc
+ proc { |obj, *args| obj.send(self, *args) }
+ end
end
end
module Enumerable
# Compatible with 1.9 on 1.8
- def each_with_object(memo)
- return to_enum :each_with_object, memo unless block_given?
- each { |obj| yield obj, memo }
- memo
+ unless method_defined?(:each_with_object)
+ def each_with_object(memo)
+ return to_enum :each_with_object, memo unless block_given?
+ each { |obj| yield obj, memo }
+ memo
+ end
end
end
diff --git a/lib/mruby/build.rb b/lib/mruby/build.rb
index 63125d4fa..4f81a970b 100644
--- a/lib/mruby/build.rb
+++ b/lib/mruby/build.rb
@@ -270,8 +270,11 @@ EOS
def exefile(name)
if name.is_a?(Array)
name.flatten.map { |n| exefile(n) }
- else
+ elsif File.extname(name).empty?
"#{name}#{exts.executable}"
+ else
+ # `name` sometimes have (non-standard) extension (e.g. `.bat`).
+ name
end
end
diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb
index 6096696cb..387bd6c90 100644
--- a/mrbgems/mruby-array-ext/mrblib/array.rb
+++ b/mrbgems/mruby-array-ext/mrblib/array.rb
@@ -266,7 +266,6 @@ class Array
self
end
- NONE=Object.new
##
# call-seq:
# ary.fetch(index) -> obj
diff --git a/mrbgems/mruby-bin-mruby-config/mrbgem.rake b/mrbgems/mruby-bin-config/mrbgem.rake
index cca7423ac..b9ba0e42c 100644
--- a/mrbgems/mruby-bin-mruby-config/mrbgem.rake
+++ b/mrbgems/mruby-bin-config/mrbgem.rake
@@ -1,17 +1,3 @@
-module MRuby
- class Build
- def exefile(name)
- if name.is_a?(Array)
- name.flatten.map { |n| exefile(n) }
- elsif name !~ /\./
- "#{name}#{exts.executable}"
- else
- name
- end
- end
- end
-end
-
MRuby.each_target do
next if kind_of? MRuby::CrossBuild
diff --git a/mrbgems/mruby-bin-mruby-config/mruby-config b/mrbgems/mruby-bin-config/mruby-config
index 57346c03f..57346c03f 100644
--- a/mrbgems/mruby-bin-mruby-config/mruby-config
+++ b/mrbgems/mruby-bin-config/mruby-config
diff --git a/mrbgems/mruby-bin-mruby-config/mruby-config.bat b/mrbgems/mruby-bin-config/mruby-config.bat
index a1f7bfdd1..a1f7bfdd1 100644
--- a/mrbgems/mruby-bin-mruby-config/mruby-config.bat
+++ b/mrbgems/mruby-bin-config/mruby-config.bat
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
index 0a864567d..2fc661cdf 100644
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
@@ -495,7 +495,7 @@ dbgcmd_quit(mrb_state *mrb, mrdb_state *mrdb)
if (mrdb->dbg->xm == DBG_QUIT) {
struct RClass *exc;
- exc = mrb_define_class(mrb, "DebuggerExit", mrb_class_get(mrb, "Exception"));
+ exc = mrb_define_class(mrb, "DebuggerExit", mrb->eException_class);
mrb_raise(mrb, exc, "Exit mrdb.");
}
return DBGST_PROMPT;
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
index cb4c738fc..233c86cef 100644
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
@@ -19,7 +19,7 @@ dbgcmd_run(mrb_state *mrb, mrdb_state *mrdb)
if (dbg->xphase == DBG_PHASE_RUNNING){
struct RClass *exc;
puts("Start it from the beginning.");
- exc = mrb_define_class(mrb, "DebuggerRestart", mrb_class_get(mrb, "Exception"));
+ exc = mrb_define_class(mrb, "DebuggerRestart", mrb->eException_class);
mrb_raise(mrb, exc, "Restart mrdb.");
}
}
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index a17272ba7..48bf06461 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -734,7 +734,10 @@ lambda_body(codegen_scope *s, node *tree, int blk)
lp->pc0 = new_label(s);
}
tree = tree->cdr;
- if (tree->car) {
+ if (tree->car == NULL) {
+ genop_W(s, OP_ENTER, 0);
+ }
+ else {
mrb_aspec a;
int ma, oa, ra, pa, ka, kd, ba;
int pos, i;
@@ -2806,7 +2809,10 @@ codegen(codegen_scope *s, node *tree, int val)
idx = new_sym(s, nsym(tree->car->cdr));
genop_2(s, OP_CLASS, cursp(), idx);
body = tree->cdr->cdr->car;
- if (!(nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL)) {
+ if (nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL) {
+ genop_1(s, OP_LOADNIL, cursp());
+ }
+ else {
idx = scope_body(s, body, val);
genop_2(s, OP_EXEC, cursp(), idx);
}
@@ -2834,8 +2840,11 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
idx = new_sym(s, nsym(tree->car->cdr));
genop_2(s, OP_MODULE, cursp(), idx);
- if (!(nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
- tree->cdr->car->cdr->cdr == NULL)) {
+ if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
+ tree->cdr->car->cdr->cdr == NULL) {
+ genop_1(s, OP_LOADNIL, cursp());
+ }
+ else {
idx = scope_body(s, tree->cdr->car, val);
genop_2(s, OP_EXEC, cursp(), idx);
}
@@ -2852,8 +2861,11 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->car, VAL);
pop();
genop_1(s, OP_SCLASS, cursp());
- if (!(nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
- tree->cdr->car->cdr->cdr == NULL)) {
+ if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
+ tree->cdr->car->cdr->cdr == NULL) {
+ genop_1(s, OP_LOADNIL, cursp());
+ }
+ else {
idx = scope_body(s, tree->cdr->car, val);
genop_2(s, OP_EXEC, cursp(), idx);
}
diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y
index 6a2defa8f..1b2d64b25 100644
--- a/mrbgems/mruby-compiler/core/parse.y
+++ b/mrbgems/mruby-compiler/core/parse.y
@@ -283,6 +283,20 @@ local_add(parser_state *p, mrb_sym sym)
}
}
+static void
+local_add_blk(parser_state *p, mrb_sym blk)
+{
+ /* allocate register for block */
+ local_add_f(p, blk ? blk : mrb_intern_lit(p->mrb, "&"));
+}
+
+static void
+local_add_kw(parser_state *p, mrb_sym kwd)
+{
+ /* allocate register for keywords hash */
+ local_add_f(p, kwd ? kwd : mrb_intern_lit(p->mrb, "**"));
+}
+
static node*
locals_node(parser_state *p)
{
@@ -726,13 +740,11 @@ new_args_tail(parser_state *p, node *kws, node *kwrest, mrb_sym blk)
{
node *k;
- /* allocate register for keywords hash */
if (kws || kwrest) {
- local_add_f(p, (kwrest && kwrest->cdr)? sym(kwrest->cdr) : mrb_intern_lit(p->mrb, "**"));
+ local_add_kw(p, (kwrest && kwrest->cdr)? sym(kwrest->cdr) : 0);
}
- /* allocate register for block */
- local_add_f(p, blk? blk : mrb_intern_lit(p->mrb, "&"));
+ local_add_blk(p, blk);
// allocate register for keywords arguments
// order is for Proc#parameters
@@ -2567,9 +2579,9 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail
{
$$ = new_args(p, $1, 0, $3, 0, $4);
}
- | f_arg ','
+ | f_arg ',' opt_block_args_tail
{
- $$ = new_args(p, $1, 0, 0, 0, 0);
+ $$ = new_args(p, $1, 0, 0, 0, $3);
}
| f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail
{
@@ -2610,19 +2622,24 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail
;
opt_block_param : none
- | block_param_def
{
+ local_add_blk(p, 0);
+ $$ = 0;
+ }
+ | block_param_def
+ {
p->cmd_start = TRUE;
$$ = $1;
}
;
-block_param_def : '|' opt_bv_decl '|'
+block_param_def : '|' {local_add_blk(p, 0);} opt_bv_decl '|'
{
$$ = 0;
}
| tOROP
{
+ local_add_blk(p, 0);
$$ = 0;
}
| '|' block_param opt_bv_decl '|'
diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb
index fedf8b1ae..99b9cddba 100644
--- a/mrbgems/mruby-enum-ext/mrblib/enum.rb
+++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb
@@ -205,7 +205,6 @@ module Enumerable
ary.collect{|e,i| orig[i]}
end
- NONE = Object.new
##
# call-seq:
# enum.first -> obj or nil
diff --git a/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/mrbgems/mruby-enumerator/mrblib/enumerator.rb
index 5697c6609..cbf53974a 100644
--- a/mrbgems/mruby-enumerator/mrblib/enumerator.rb
+++ b/mrbgems/mruby-enumerator/mrblib/enumerator.rb
@@ -121,7 +121,7 @@ class Enumerator
@obj = obj
@meth = meth
- @args = args.dup
+ @args = args
@fib = nil
@dst = nil
@lookahead = nil
diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c
index 832583f35..c0ce71219 100644
--- a/mrbgems/mruby-struct/src/struct.c
+++ b/mrbgems/mruby-struct/src/struct.c
@@ -399,7 +399,7 @@ struct_aref_sym(mrb_state *mrb, mrb_value obj, mrb_sym id)
return ptr[i];
}
}
- mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, id));
+ mrb_name_error(mrb, id, "no member '%S' in struct", mrb_sym2str(mrb, id));
return mrb_nil_value(); /* not reached */
}
diff --git a/mrbgems/mruby-symbol-ext/src/symbol.c b/mrbgems/mruby-symbol-ext/src/symbol.c
index a992dbfce..215226502 100644
--- a/mrbgems/mruby-symbol-ext/src/symbol.c
+++ b/mrbgems/mruby-symbol-ext/src/symbol.c
@@ -1,6 +1,7 @@
#include <mruby.h>
#include <mruby/khash.h>
#include <mruby/array.h>
+#include <mruby/string.h>
typedef struct symbol_name {
size_t len;
@@ -45,7 +46,13 @@ static mrb_value
mrb_sym_length(mrb_state *mrb, mrb_value self)
{
mrb_int len;
+#ifdef MRB_UTF8_STRING
+ mrb_int byte_len;
+ const char *name = mrb_sym2name_len(mrb, mrb_symbol(self), &byte_len);
+ len = mrb_utf8_len(name, byte_len);
+#else
mrb_sym2name_len(mrb, mrb_symbol(self), &len);
+#endif
return mrb_fixnum_value(len);
}
diff --git a/mrbgems/mruby-symbol-ext/test/symbol.rb b/mrbgems/mruby-symbol-ext/test/symbol.rb
index 63c1bd826..2c7a62b0c 100644
--- a/mrbgems/mruby-symbol-ext/test/symbol.rb
+++ b/mrbgems/mruby-symbol-ext/test/symbol.rb
@@ -7,9 +7,18 @@ assert('Symbol.all_symbols') do
assert_equal foo, symbols
end
-assert("Symbol#length") do
- assert_equal 5, :hello.size
- assert_equal 5, :mruby.length
+%w[size length].each do |n|
+ assert("Symbol##{n}") do
+ assert_equal 5, :hello.__send__(n)
+ assert_equal 4, :"aA\0b".__send__(n)
+ if "あ".size == 1 # enable MRB_UTF8_STRING?
+ assert_equal 8, :"こんにちは世界!".__send__(n)
+ assert_equal 4, :"aあ\0b".__send__(n)
+ else
+ assert_equal 22, :"こんにちは世界!".__send__(n)
+ assert_equal 6, :"aあ\0b".__send__(n)
+ end
+ end
end
assert("Symbol#capitalize") do
diff --git a/mrblib/enum.rb b/mrblib/enum.rb
index a97a26f97..9bd74e1c4 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
diff --git a/src/class.c b/src/class.c
index dd5b65cc3..359bb4fea 100644
--- a/src/class.c
+++ b/src/class.c
@@ -1815,7 +1815,7 @@ mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const
* show information on the thing we're attached to as well.
*/
-static mrb_value
+mrb_value
mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
{
mrb_value str;
diff --git a/src/string.c b/src/string.c
index 52941473c..19962fb30 100644
--- a/src/string.c
+++ b/src/string.c
@@ -20,6 +20,7 @@
#include <mruby/class.h>
#include <mruby/range.h>
#include <mruby/string.h>
+#include <mruby/numeric.h>
#include <mruby/re.h>
typedef struct mrb_shared_string {
@@ -156,13 +157,6 @@ mrb_str_new(mrb_state *mrb, const char *p, size_t len)
return mrb_obj_value(str_new(mrb, p, len));
}
-/*
- * call-seq: (Caution! NULL string)
- * String.new(str="") => new_str
- *
- * Returns a new string object containing a copy of <i>str</i>.
- */
-
MRB_API mrb_value
mrb_str_new_cstr(mrb_state *mrb, const char *p)
{
@@ -238,27 +232,36 @@ utf8len(const char* p, const char* e)
return len;
}
-static mrb_int
-utf8_strlen(mrb_value str, mrb_int len)
+mrb_int
+mrb_utf8_len(const char *str, mrb_int byte_len)
{
mrb_int total = 0;
- char* p = RSTRING_PTR(str);
- char* e = p;
- if (RSTRING(str)->flags & MRB_STR_NO_UTF) {
- return RSTRING_LEN(str);
- }
- e += len < 0 ? RSTRING_LEN(str) : len;
- while (p<e) {
+ const char *p = str;
+ const char *e = p + byte_len;
+
+ while (p < e) {
p += utf8len(p, e);
total++;
}
- if (RSTRING_LEN(str) == total) {
- RSTRING(str)->flags |= MRB_STR_NO_UTF;
- }
return total;
}
-#define RSTRING_CHAR_LEN(s) utf8_strlen(s, -1)
+static mrb_int
+utf8_strlen(mrb_value str)
+{
+ mrb_int byte_len = RSTRING_LEN(str);
+
+ if (RSTRING(str)->flags & MRB_STR_NO_UTF) {
+ return byte_len;
+ }
+ else {
+ mrb_int utf8_len = mrb_utf8_len(RSTRING_PTR(str), byte_len);
+ if (byte_len == utf8_len) RSTRING(str)->flags |= MRB_STR_NO_UTF;
+ return utf8_len;
+ }
+}
+
+#define RSTRING_CHAR_LEN(s) utf8_strlen(s)
/* map character index to byte offset index */
static mrb_int
@@ -739,12 +742,6 @@ mrb_str_to_cstr(mrb_state *mrb, mrb_value str0)
return RSTR_PTR(s);
}
-/*
- * call-seq: (Caution! String("abcd") change)
- * String("abcdefg") = String("abcd") + String("efg")
- *
- * Returns a new string object containing a copy of <i>str</i>.
- */
MRB_API void
mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other)
{
@@ -752,12 +749,6 @@ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other)
mrb_str_cat_str(mrb, self, other);
}
-/*
- * call-seq: (Caution! String("abcd") remain)
- * String("abcdefg") = String("abcd") + String("efg")
- *
- * Returns a new string object containing a copy of <i>str</i>.
- */
MRB_API mrb_value
mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b)
{
@@ -775,10 +766,13 @@ mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b)
/* 15.2.10.5.2 */
/*
- * call-seq: (Caution! String("abcd") remain) for stack_argument
- * String("abcdefg") = String("abcd") + String("efg")
+ * call-seq:
+ * str + other_str -> new_str
*
- * Returns a new string object containing a copy of <i>str</i>.
+ * Concatenation---Returns a new <code>String</code> containing
+ * <i>other_str</i> concatenated to <i>str</i>.
+ *
+ * "Hello from " + self.to_s #=> "Hello from main"
*/
static mrb_value
mrb_str_plus_m(mrb_state *mrb, mrb_value self)
@@ -979,13 +973,22 @@ mrb_str_equal_m(mrb_state *mrb, mrb_value str1)
return mrb_bool_value(mrb_str_equal(mrb, str1, str2));
}
/* ---------------------------------- */
+mrb_value mrb_mod_to_s(mrb_state *mrb, mrb_value klass);
+
MRB_API mrb_value
mrb_str_to_str(mrb_state *mrb, mrb_value str)
{
- if (!mrb_string_p(str)) {
+ switch (mrb_type(str)) {
+ case MRB_TT_STRING:
+ return str;
+ case MRB_TT_FIXNUM:
+ return mrb_fixnum_to_str(mrb, str, 10);
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ return mrb_mod_to_s(mrb, str);
+ default:
return mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_s");
}
- return str;
}
MRB_API const char*
@@ -1587,8 +1590,6 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
return mrb_fixnum_value(pos);
}
-#define STR_REPLACE_SHARED_MIN 10
-
/* 15.2.10.5.24 */
/* 15.2.10.5.28 */
/*
diff --git a/src/symbol.c b/src/symbol.c
index 6b4c7200c..4242f3d8e 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -15,28 +15,11 @@
/* ------------------------------------------------------ */
typedef struct symbol_name {
mrb_bool lit : 1;
+ uint8_t prev;
uint16_t len;
const char *name;
} symbol_name;
-static inline khint_t
-sym_hash_func(mrb_state *mrb, mrb_sym s)
-{
- khint_t h = 0;
- size_t i, len = mrb->symtbl[s].len;
- const char *p = mrb->symtbl[s].name;
-
- for (i=0; i<len; i++) {
- h = (h << 5) - h + *p++;
- }
- return h;
-}
-#define sym_hash_equal(mrb,a, b) (mrb->symtbl[a].len == mrb->symtbl[b].len && memcmp(mrb->symtbl[a].name, mrb->symtbl[b].name, mrb->symtbl[a].len) == 0)
-
-KHASH_DECLARE(n2s, mrb_sym, mrb_sym, FALSE)
-KHASH_DEFINE (n2s, mrb_sym, mrb_sym, FALSE, sym_hash_func, sym_hash_equal)
-/* ------------------------------------------------------ */
-
static void
sym_validate_len(mrb_state *mrb, size_t len)
{
@@ -45,24 +28,62 @@ sym_validate_len(mrb_state *mrb, size_t len)
}
}
+uint8_t
+symhash(const char *key, size_t len)
+{
+ uint32_t hash, i;
+
+ for(hash = i = 0; i < len; ++i) {
+ hash += key[i];
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+ return hash & 0xff;
+}
+
+static mrb_sym
+find_symbol(mrb_state *mrb, const char *name, uint16_t len, uint8_t hash)
+{
+ mrb_sym i;
+ symbol_name *sname;
+
+ i = mrb->symhash[hash];
+ if (i == 0) return 0;
+ do {
+ sname = &mrb->symtbl[i];
+ if (sname->len == len && memcmp(sname->name, name, len) == 0) {
+ return i;
+ }
+ if (sname->prev == 0xff) {
+ i -= 0xff;
+ sname = &mrb->symtbl[i];
+ while (mrb->symtbl < sname) {
+ if (sname->len == len && memcmp(sname->name, name, len) == 0) {
+ return (mrb_sym)(sname - mrb->symtbl);
+ }
+ sname--;
+ }
+ return 0;
+ }
+ i -= sname->prev;
+ } while (sname->prev > 0);
+ return 0;
+}
+
static mrb_sym
sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
{
- khash_t(n2s) *h = mrb->name2sym;
- symbol_name *sname = mrb->symtbl; /* symtbl[0] for working memory */
- khiter_t k;
mrb_sym sym;
- char *p;
+ symbol_name *sname;
+ uint8_t hash;
sym_validate_len(mrb, len);
- if (sname) {
- sname->lit = lit;
- sname->len = (uint16_t)len;
- sname->name = name;
- k = kh_get(n2s, mrb, h, 0);
- if (k != kh_end(h))
- return kh_key(h, k);
- }
+ hash = symhash(name, len);
+ sym = find_symbol(mrb, name, len, hash);
+ if (sym > 0) return sym;
/* registering a new symbol */
sym = ++mrb->symidx;
@@ -78,13 +99,23 @@ sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
sname->lit = TRUE;
}
else {
- p = (char *)mrb_malloc(mrb, len+1);
+ char *p = (char *)mrb_malloc(mrb, len+1);
memcpy(p, name, len);
p[len] = 0;
sname->name = (const char*)p;
sname->lit = FALSE;
}
- kh_put(n2s, mrb, h, sym);
+ if (mrb->symhash[hash]) {
+ mrb_sym i = sym - mrb->symhash[hash];
+ if (i > 0xff)
+ sname->prev = 0xff;
+ else
+ sname->prev = i;
+ }
+ else {
+ sname->prev = 0;
+ }
+ mrb->symhash[hash] = sym;
return sym;
}
@@ -116,25 +147,18 @@ mrb_intern_str(mrb_state *mrb, mrb_value str)
MRB_API mrb_value
mrb_check_intern(mrb_state *mrb, const char *name, size_t len)
{
- khash_t(n2s) *h = mrb->name2sym;
- symbol_name *sname = mrb->symtbl;
- khiter_t k;
+ mrb_sym sym;
sym_validate_len(mrb, len);
- sname->len = (uint16_t)len;
- sname->name = name;
-
- k = kh_get(n2s, mrb, h, 0);
- if (k != kh_end(h)) {
- return mrb_symbol_value(kh_key(h, k));
- }
+ sym = find_symbol(mrb, name, len, symhash(name, len));
+ if (sym > 0) return mrb_symbol_value(sym);
return mrb_nil_value();
}
MRB_API mrb_value
mrb_check_intern_cstr(mrb_state *mrb, const char *name)
{
- return mrb_check_intern(mrb, name, (mrb_int)strlen(name));
+ return mrb_check_intern(mrb, name, strlen(name));
}
MRB_API mrb_value
@@ -143,7 +167,6 @@ mrb_check_intern_str(mrb_state *mrb, mrb_value str)
return mrb_check_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
}
-/* lenp must be a pointer to a size_t variable */
MRB_API const char*
mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
{
@@ -167,13 +190,11 @@ mrb_free_symtbl(mrb_state *mrb)
}
}
mrb_free(mrb, mrb->symtbl);
- kh_destroy(n2s, mrb, mrb->name2sym);
}
void
mrb_init_symtbl(mrb_state *mrb)
{
- mrb->name2sym = kh_init(n2s, mrb);
}
/**********************************************************************
diff --git a/test/t/class.rb b/test/t/class.rb
index f37a891a4..6a0a3225c 100644
--- a/test/t/class.rb
+++ b/test/t/class.rb
@@ -236,6 +236,11 @@ assert('class to return the last value') do
assert_equal(m, :m)
end
+assert('class to return nil if body is empty') do
+ assert_nil(class C end)
+ assert_nil(class << self; end)
+end
+
assert('raise when superclass is not a class') do
module FirstModule; end
assert_raise(TypeError, 'should raise TypeError') do
diff --git a/test/t/module.rb b/test/t/module.rb
index 78cb5d07f..f01245e88 100644
--- a/test/t/module.rb
+++ b/test/t/module.rb
@@ -708,6 +708,15 @@ assert('module with non-class/module outer raises TypeError') do
assert_raise(TypeError) { module []::M2 end }
end
+assert('module to return the last value') do
+ m = module M; :m end
+ assert_equal(m, :m)
+end
+
+assert('module to return nil if body is empty') do
+ assert_nil(module M end)
+end
+
assert('get constant of parent module in singleton class; issue #3568') do
actual = module GetConstantInSingletonTest
EXPECTED = "value"