[macruby-changes] [3617] MacRuby/branches/icu
source_changes at macosforge.org
source_changes at macosforge.org
Thu Feb 25 00:17:45 PST 2010
Revision: 3617
http://trac.macosforge.org/projects/ruby/changeset/3617
Author: lsansonetti at apple.com
Date: 2010-02-25 00:17:43 -0800 (Thu, 25 Feb 2010)
Log Message:
-----------
a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Modified Paths:
--------------
MacRuby/branches/icu/encoding.h
MacRuby/branches/icu/id.c
MacRuby/branches/icu/id.h
MacRuby/branches/icu/include/ruby/intern.h
MacRuby/branches/icu/include/ruby/ruby.h
MacRuby/branches/icu/inits.c
MacRuby/branches/icu/parse.y
MacRuby/branches/icu/rakelib/builder/builder.rb
MacRuby/branches/icu/string.c
MacRuby/branches/icu/vm.cpp
Added Paths:
-----------
MacRuby/branches/icu/symbol.c
MacRuby/branches/icu/symbol.h
Modified: MacRuby/branches/icu/encoding.h
===================================================================
--- MacRuby/branches/icu/encoding.h 2010-02-25 08:15:14 UTC (rev 3616)
+++ MacRuby/branches/icu/encoding.h 2010-02-25 08:17:43 UTC (rev 3617)
@@ -290,6 +290,8 @@
STRING_VALID_ENCODING);
}
+VALUE str_inspect(rb_str_t *str, bool dump);
+
// The following functions should always been prefered over anything else,
// especially if this "else" is RSTRING_PTR and RSTRING_LEN.
// They also work on CFStrings.
@@ -299,6 +301,7 @@
long rb_str_chars_len(VALUE str);
UChar rb_str_get_uchar(VALUE str, long pos);
void rb_str_append_uchar(VALUE str, UChar c);
+unsigned long rb_str_hash_uchars(UChar *chars, long chars_len);
VALUE mr_enc_s_is_compatible(VALUE klass, SEL sel, VALUE str1, VALUE str2);
Modified: MacRuby/branches/icu/id.c
===================================================================
--- MacRuby/branches/icu/id.c 2010-02-25 08:15:14 UTC (rev 3616)
+++ MacRuby/branches/icu/id.c 2010-02-25 08:17:43 UTC (rev 3617)
@@ -61,6 +61,7 @@
selLength = sel_registerName("length");
selSucc = sel_registerName("succ");
selNot = sel_registerName("!");
+ selNot2 = sel_registerName("!:");
selAlloc = sel_registerName("alloc");
selAllocWithZone = sel_registerName("allocWithZone:");
selCopyWithZone = sel_registerName("copyWithZone:");
Modified: MacRuby/branches/icu/id.h
===================================================================
--- MacRuby/branches/icu/id.h 2010-02-25 08:15:14 UTC (rev 3616)
+++ MacRuby/branches/icu/id.h 2010-02-25 08:17:43 UTC (rev 3617)
@@ -71,6 +71,7 @@
extern SEL selLength;
extern SEL selSucc;
extern SEL selNot;
+extern SEL selNot2;
extern SEL selAlloc;
extern SEL selAllocWithZone;
extern SEL selCopyWithZone;
Modified: MacRuby/branches/icu/include/ruby/intern.h
===================================================================
--- MacRuby/branches/icu/include/ruby/intern.h 2010-02-25 08:15:14 UTC (rev 3616)
+++ MacRuby/branches/icu/include/ruby/intern.h 2010-02-25 08:17:43 UTC (rev 3617)
@@ -587,7 +587,7 @@
VALUE rb_str_append(VALUE, VALUE);
VALUE rb_str_concat(VALUE, VALUE);
VALUE rb_str_plus(VALUE str1, VALUE str2);
-int rb_memhash(const void *ptr, long len);
+long rb_memhash(const void *ptr, long len);
int rb_str_hash(VALUE);
int rb_str_hash_cmp(VALUE,VALUE);
int rb_str_comparable(VALUE, VALUE);
Modified: MacRuby/branches/icu/include/ruby/ruby.h
===================================================================
--- MacRuby/branches/icu/include/ruby/ruby.h 2010-02-25 08:15:14 UTC (rev 3616)
+++ MacRuby/branches/icu/include/ruby/ruby.h 2010-02-25 08:17:43 UTC (rev 3617)
@@ -249,7 +249,8 @@
#else
// voodoo_float must be a function
// because the parameter must be converted to float
-static inline VALUE voodoo_float(float f)
+static inline VALUE
+voodoo_float(float f)
{
return *(VALUE *)(&f);
}
@@ -258,15 +259,9 @@
#define FIXFLOAT_P(v) (((VALUE)v & IMMEDIATE_MASK) == FIXFLOAT_FLAG)
#define FIXFLOAT2DBL(v) coerce_ptr_to_double((VALUE)v)
-#if WITH_OBJC
-# define SYMBOL_P(x) (TYPE(x) == T_SYMBOL)
-# define ID2SYM(x) (rb_id2str((ID)x))
-# define SYM2ID(x) (RSYMBOL(x)->id)
-#else
-# define SYMBOL_P(x) (((VALUE)(x)&~(~(VALUE)0<<RUBY_SPECIAL_SHIFT))==SYMBOL_FLAG)
-# define ID2SYM(x) (((VALUE)(x)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG)
-# define SYM2ID(x) RSHIFT((unsigned long)x,RUBY_SPECIAL_SHIFT)
-#endif
+#define SYMBOL_P(x) (TYPE(x) == T_SYMBOL)
+#define ID2SYM(x) (rb_id2str((ID)x))
+#define SYM2ID(x) (rb_sym2id((VALUE)x))
/* special contants - i.e. non-zero and non-fixnum constants */
enum ruby_special_consts {
@@ -783,7 +778,6 @@
#define RFLOAT(obj) (R_CAST(RFloat)(obj))
#if WITH_OBJC
# define RFIXNUM(obj) (R_CAST(RFixnum)(obj))
-# define RSYMBOL(obj) (R_CAST(RSymbol)(obj))
#endif
#define RDATA(obj) (R_CAST(RData)(obj))
#define RSTRUCT(obj) (R_CAST(RStruct)(obj))
@@ -918,34 +912,19 @@
ID rb_intern2(const char*, long);
ID rb_intern_str(VALUE str);
ID rb_to_id(VALUE);
+ID rb_sym2id(VALUE sym);
VALUE rb_id2str(ID);
VALUE rb_name2sym(const char *);
-#if WITH_OBJC
-# define rb_sym2name(sym) (RSYMBOL(sym)->str)
+const char *rb_sym2name(VALUE sym);
+VALUE rb_sym2str(VALUE sym);
+
static inline
const char *rb_id2name(ID val)
{
VALUE s = rb_id2str(val);
return s == 0 ? NULL : rb_sym2name(s);
}
-#else
-const char *rb_id2name(ID);
-#endif
-#ifdef __GNUC__
-/* __builtin_constant_p and statement expression is available
- * since gcc-2.7.2.3 at least. */
-#define rb_intern(str) \
- (__builtin_constant_p(str) ? \
- ({ \
- static ID rb_intern_id_cache; \
- if (!rb_intern_id_cache) \
- rb_intern_id_cache = rb_intern(str); \
- rb_intern_id_cache; \
- }) : \
- rb_intern(str))
-#endif
-
const char *rb_class2name(VALUE);
const char *rb_obj_classname(VALUE);
Modified: MacRuby/branches/icu/inits.c
===================================================================
--- MacRuby/branches/icu/inits.c 2010-02-25 08:15:14 UTC (rev 3616)
+++ MacRuby/branches/icu/inits.c 2010-02-25 08:17:43 UTC (rev 3617)
@@ -36,7 +36,8 @@
void Init_Object(void);
void Init_pack(void);
void Init_Precision(void);
-void Init_sym(void);
+void Init_Symbol(void);
+void Init_PreSymbol(void);
void Init_id(void);
void Init_process(void);
void Init_Random(void);
@@ -63,7 +64,7 @@
void
rb_call_inits()
{
- Init_sym();
+ Init_PreSymbol();
Init_id();
Init_var_tables();
Init_Object();
@@ -73,6 +74,7 @@
Init_Enumerable();
Init_Precision();
Init_String();
+ Init_Symbol();
Init_Exception();
Init_eval();
Init_jump();
Modified: MacRuby/branches/icu/parse.y
===================================================================
--- MacRuby/branches/icu/parse.y 2010-02-25 08:15:14 UTC (rev 3616)
+++ MacRuby/branches/icu/parse.y 2010-02-25 08:17:43 UTC (rev 3617)
@@ -22,6 +22,7 @@
#include "ruby/st.h"
#include "ruby/encoding.h"
#include "encoding.h"
+#include "symbol.h"
#include "id.h"
#include "re.h"
#include <stdio.h>
@@ -38,31 +39,6 @@
#define calloc YYCALLOC
#define free YYFREE
-#define ID_SCOPE_SHIFT 3
-#define ID_SCOPE_MASK 0x07
-#define ID_LOCAL 0x00
-#define ID_INSTANCE 0x01
-#define ID_GLOBAL 0x03
-#define ID_ATTRSET 0x04
-#define ID_CONST 0x05
-#define ID_CLASS 0x06
-#define ID_JUNK 0x07
-#define ID_INTERNAL ID_JUNK
-
-#define is_notop_id(id) ((id)>tLAST_TOKEN)
-#define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
-#define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
-#define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
-#define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
-#define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
-#define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
-#define is_junk_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)
-
-#define is_asgn_or_id(id) ((is_notop_id(id)) && \
- (((id)&ID_SCOPE_MASK) == ID_GLOBAL || \
- ((id)&ID_SCOPE_MASK) == ID_INSTANCE || \
- ((id)&ID_SCOPE_MASK) == ID_CLASS))
-
enum lex_state_e {
EXPR_BEG, /* ignore newline, +/- is a sign. */
EXPR_END, /* newline significant, +/- is a operator. */
@@ -511,7 +487,6 @@
#define reg_fragment_check(str,options) reg_fragment_check_gen(parser, str, options)
static NODE *reg_named_capture_assign_gen(struct parser_params* parser, VALUE regexp, NODE *match);
#define reg_named_capture_assign(regexp,match) reg_named_capture_assign_gen(parser,regexp,match)
-int rb_enc_symname2_p(const char *, int, rb_encoding *);
#else
#define remove_begin(node) (node)
#endif /* !RIPPER */
@@ -4912,10 +4887,6 @@
# define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
#endif
-#if !WITH_OBJC
-#define parser_mbclen() mbclen((lex_p-1),lex_pend,parser->enc)
-#define parser_precise_mbclen() rb_enc_precise_mbclen((lex_p-1),lex_pend,parser->enc)
-#endif
#define is_identchar(p,e,enc) (rb_enc_isalnum(*p,enc) || (*p) == '_' || !ISASCII(*p))
#define parser_is_identchar() (!parser->eofp && is_identchar((lex_p-1),lex_pend,parser->enc))
@@ -8165,14 +8136,6 @@
}
}
-ID
-rb_id_attrset(ID id)
-{
- id &= ~ID_SCOPE_MASK;
- id |= ID_ATTRSET;
- return id;
-}
-
static NODE *
attrset_gen(struct parser_params *parser, NODE *recv, ID id)
{
@@ -9260,533 +9223,53 @@
return scope;
}
-static const struct {
- ID token;
- const char *name;
-} op_tbl[] = {
- {tDOT2, ".."},
- {tDOT3, "..."},
- {'+', "+"},
- {'-', "-"},
- {'+', "+(binary)"},
- {'-', "-(binary)"},
- {'*', "*"},
- {'/', "/"},
- {'%', "%"},
- {tPOW, "**"},
- {tUPLUS, "+@"},
- {tUMINUS, "-@"},
- {'|', "|"},
- {'^', "^"},
- {'&', "&"},
- {'!', "!"},
- {tCMP, "<=>"},
- {'>', ">"},
- {tGEQ, ">="},
- {'<', "<"},
- {tLEQ, "<="},
- {tEQ, "=="},
- {tEQQ, "==="},
- {tNEQ, "!="},
- {tMATCH, "=~"},
- {tNMATCH, "!~"},
- {'~', "~"},
- {'!', "!"},
- {tAREF, "[]"},
- {tASET, "[]="},
- {tLSHFT, "<<"},
- {tRSHFT, ">>"},
- {tCOLON2, "::"},
- {'`', "`"},
- {0, 0}
-};
-
-static struct symbols {
- ID last_id;
-#if WITH_OBJC
- CFMutableDictionaryRef sym_id;
- CFMutableDictionaryRef id_str;
-#else
- st_table *sym_id;
- st_table *id_str;
-#endif
- VALUE op_sym[tLAST_TOKEN];
-} global_symbols = {tLAST_TOKEN >> ID_SCOPE_SHIFT};
-
-static const struct st_hash_type symhash = {
- rb_str_hash_cmp,
- rb_str_hash,
-};
-
-struct ivar2_key {
- ID id;
- VALUE klass;
-};
-
-static int
-ivar2_cmp(struct ivar2_key *key1, struct ivar2_key *key2)
-{
- if (key1->id == key2->id && key1->klass == key2->klass) {
- return 0;
- }
- return 1;
-}
-
-static int
-ivar2_hash(struct ivar2_key *key)
-{
- return (key->id << 8) ^ (key->klass >> 2);
-}
-
-static const struct st_hash_type ivar2_hash_type = {
- ivar2_cmp,
- ivar2_hash,
-};
-
-void
-Init_sym(void)
-{
-#if WITH_OBJC
- global_symbols.sym_id = CFDictionaryCreateMutable(NULL,
- 0, NULL, NULL);
- GC_ROOT(&global_symbols.sym_id);
- global_symbols.id_str = CFDictionaryCreateMutable(NULL,
- 0, NULL, NULL);
- GC_ROOT(&global_symbols.id_str);
-#else
- global_symbols.sym_id = st_init_table_with_size(&symhash, 1000);
- global_symbols.id_str = st_init_numtable_with_size(1000);
-#endif
- rb_intern2("", 0);
-}
-
-#if !WITH_OBJC
-void
-rb_gc_mark_symbols(void)
-{
- rb_mark_tbl(global_symbols.id_str);
- rb_gc_mark_locations(global_symbols.op_sym,
- global_symbols.op_sym + tLAST_TOKEN);
-}
-#endif
-
// XXX not thread-safe
static long internal_count = 0;
static ID
internal_id_gen(struct parser_params *parser)
{
-#if 1
char buf[100];
snprintf(buf, sizeof buf, "__internal_id_tmp_%ld__", internal_count++);
return rb_intern(buf);
-#else
- ID id = (ID)vtable_size(lvtbl->args) + (ID)vtable_size(lvtbl->vars);
- id += ((tLAST_TOKEN - ID_INTERNAL) >> ID_SCOPE_SHIFT) + 1;
- return ID_INTERNAL | (id << ID_SCOPE_SHIFT);
-#endif
}
-static int
-is_special_global_name(const char *m, const char *e, rb_encoding *enc)
-{
- int mb = 0;
+struct rb_op_tbl_entry rb_op_tbl[] = {
+ {'+', "+"},
+ {'-', "-"},
+ {'*', "*"},
+ {'/', "/"},
+ {'%', "%"},
+ {'|', "|"},
+ {'^', "^"},
+ {'&', "&"},
+ {'!', "!"},
+ {'>', ">"},
+ {'<', "<"},
+ {'~', "~"},
+ {'!', "!"},
+ {'`', "`"},
+ {tDOT2, ".."},
+ {tDOT3, "..."},
+ {tPOW, "**"},
+ {tUPLUS, "+@"},
+ {tUMINUS, "-@"},
+ {tCMP, "<=>"},
+ {tGEQ, ">="},
+ {tLEQ, "<="},
+ {tEQ, "=="},
+ {tEQQ, "==="},
+ {tNEQ, "!="},
+ {tMATCH, "=~"},
+ {tNMATCH, "!~"},
+ {tAREF, "[]"},
+ {tASET, "[]="},
+ {tLSHFT, "<<"},
+ {tRSHFT, ">>"},
+ {tCOLON2, "::"},
+ {0, NULL}
+};
- if (m >= e) return 0;
- switch (*m) {
- case '~': case '*': case '$': case '?': case '!': case '@':
- case '/': case '\\': case ';': case ',': case '.': case '=':
- case ':': case '<': case '>': case '\"':
- case '&': case '`': case '\'': case '+':
- case '0':
- ++m;
- break;
- case '-':
- ++m;
- if (m < e && is_identchar(m, e, enc)) {
- if (!ISASCII(*m)) mb = 1;
-#if WITH_OBJC
- m += 1;
-#else
- m += rb_enc_mbclen(m, e, enc);
-#endif
- }
- break;
- default:
- if (!rb_enc_isdigit(*m, enc)) return 0;
- do {
- if (!ISASCII(*m)) mb = 1;
- ++m;
- } while (rb_enc_isdigit(*m, enc));
- }
- return m == e ? mb + 1 : 0;
-}
-
-int
-rb_symname_p(const char *name)
-{
-#if WITH_OBJC
- return rb_enc_symname_p(name, NULL);
-#else
- return rb_enc_symname_p(name, rb_ascii8bit_encoding());
-#endif
-}
-
-int
-rb_enc_symname_p(const char *name, rb_encoding *enc)
-{
- return rb_enc_symname2_p(name, strlen(name), enc);
-}
-
-int
-rb_enc_symname2_p(const char *name, int len, rb_encoding *enc)
-{
- const char *m = name;
- const char *e = m + len;
- int localid = Qfalse;
-
- if (!m) return Qfalse;
- switch (*m) {
- case '\0':
- return Qfalse;
-
- case '$':
- if (is_special_global_name(++m, e, enc)) return Qtrue;
- goto id;
-
- case '@':
- if (*++m == '@') ++m;
- goto id;
-
- case '<':
- switch (*++m) {
- case '<': ++m; break;
- case '=': if (*++m == '>') ++m; break;
- default: break;
- }
- break;
-
- case '>':
- switch (*++m) {
- case '>': case '=': ++m; break;
- }
- break;
-
- case '=':
- switch (*++m) {
- case '~': ++m; break;
- case '=': if (*++m == '=') ++m; break;
- default: return Qfalse;
- }
- break;
-
- case '*':
- if (*++m == '*') ++m;
- break;
-
- case '+': case '-':
- if (*++m == '@') ++m;
- break;
-
- case '|': case '^': case '&': case '/': case '%': case '~': case '`':
- ++m;
- break;
-
- case '[':
- if (*++m != ']') return Qfalse;
- if (*++m == '=') ++m;
- break;
-
- case '!':
- switch (*++m) {
- case '\0': return Qtrue;
- case '=': case '~': ++m; break;
- default: return Qfalse;
- }
- break;
-
- default:
- localid = !rb_enc_isupper(*m, enc);
- id:
- if (m >= e || (*m != '_' && !rb_enc_isalpha(*m, enc) && ISASCII(*m)))
- return Qfalse;
-#if WITH_OBJC
- while (m < e && is_identchar(m, e, enc)) m += 1;
-#else
- while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc);
-#endif
- if (localid) {
- switch (*m) {
- case '!': case '?': case '=': ++m;
- }
- }
- break;
- }
- return *m ? Qfalse : Qtrue;
-}
-
-#if WITH_OBJC
-static inline VALUE
-rsymbol_new(const char *name, const int len, ID id)
-{
- assert(rb_cSymbol != 0);
-
- struct RSymbol *sym = (struct RSymbol *)orig_malloc(sizeof(struct RSymbol));
- sym->klass = rb_cSymbol;
- sym->str = orig_malloc(len + 1);
- strcpy(sym->str, name);
- sym->len = len;
- sym->id = id;
-
- return (VALUE)sym;
-}
-#endif
-
-ID
-rb_intern3(const char *name, long len, rb_encoding *enc)
-{
- const char *m = name;
- const char *e = m + len;
- VALUE str;
- ID id;
- int last;
- int mb;
-#if !WITH_OBJC
- struct RString fake_str;
- fake_str.basic.isa = NULL;
- fake_str.basic.flags = T_STRING|RSTRING_NOEMBED|FL_FREEZE;
- fake_str.basic.klass = rb_cString;
- fake_str.as.heap.len = len;
- fake_str.as.heap.ptr = (char *)name;
- fake_str.as.heap.aux.capa = len;
- str = (VALUE)&fake_str;
- rb_enc_associate(str, enc);
-
- if (st_lookup(global_symbols.sym_id, str, (st_data_t *)&id))
- return id;
-#else
- long sname = strlen(name);
- assert(len <= sname);
- if (sname != len) {
- char *tmp = (char *)alloca(len + 1);
- memcpy(tmp, name, len);
- tmp[len] = '\0';
- m = name = tmp;
- e = m + len;
- }
- SEL name_hash = sel_registerName(name);
- if (name_hash == sel_ignored) {
- if (strcmp(name, "retain") == 0) {
- name_hash = (SEL)0x1000;
- }
- else if (strcmp(name, "release") == 0) {
- name_hash = (SEL)0x2000;
- }
- else if (strcmp(name, "retainCount") == 0) {
- name_hash = (SEL)0x3000;
- }
- else if (strcmp(name, "autorelease") == 0) {
- name_hash = (SEL)0x4000;
- }
- else if (strcmp(name, "dealloc") == 0) {
- name_hash = (SEL)0x5000;
- }
- else {
- printf("unrecognized ignored sel %s\n", name);
- abort();
- }
- }
- id = (ID)CFDictionaryGetValue((CFDictionaryRef)global_symbols.sym_id,
- (const void *)name_hash);
- if (id != 0)
- return id;
-#endif
-
- last = len-1;
- id = 0;
- switch (*m) {
- case '$':
- id |= ID_GLOBAL;
- if ((mb = is_special_global_name(++m, e, enc)) != 0) {
- if (!--mb) {
-#if WITH_OBJC
- enc = NULL;
-#else
- enc = rb_ascii8bit_encoding();
-#endif
- }
- goto new_id;
- }
- break;
- case '@':
- if (m[1] == '@') {
- m++;
- id |= ID_CLASS;
- }
- else {
- id |= ID_INSTANCE;
- }
- m++;
- break;
- default:
- if (m[0] != '_' && rb_enc_isascii((unsigned char)m[0], enc)
- && !rb_enc_isalnum(m[0], enc)) {
- /* operators */
- int i;
-
- for (i=0; op_tbl[i].token; i++) {
- if (*op_tbl[i].name == *m &&
- strcmp(op_tbl[i].name, m) == 0) {
- id = op_tbl[i].token;
- goto id_register;
- }
- }
- }
-
- if (m[last] == '=') {
- /* attribute assignment */
- id = rb_intern3(name, last, enc);
- if (id > tLAST_TOKEN && !is_attrset_id(id)) {
- enc = rb_enc_get(rb_id2str(id));
- id = rb_id_attrset(id);
- goto id_register;
- }
- id = ID_ATTRSET;
- }
- else if (rb_enc_isupper(m[0], enc)) {
- id = ID_CONST;
- }
- else {
- id = ID_LOCAL;
- }
- break;
- }
- mb = 0;
- if (!rb_enc_isdigit(*m, enc)) {
- while (m <= name + last && is_identchar(m, e, enc)) {
- if (ISASCII(*m)) {
- m++;
- }
- else {
- mb = 1;
-#if WITH_OBJC
- m += 1;
-#else
- m += rb_enc_mbclen(m, e, enc);
-#endif
- }
- }
- }
- if (m - name < len) id = ID_JUNK;
-#if !WITH_OBJC
- if (enc != rb_usascii_encoding()) {
- /*
- * this clause makes sense only when called from other than
- * rb_intern_str() taking care of code-range.
- */
- if (!mb) {
- for (; m <= name + len; ++m) {
- if (!ISASCII(*m)) goto mbstr;
- }
- enc = rb_usascii_encoding();
- }
- mbstr:;
- }
-#endif
- new_id:
- id |= ++global_symbols.last_id << ID_SCOPE_SHIFT;
- id_register:
- str = rsymbol_new(name, len, id);
-#if WITH_OBJC
- CFDictionarySetValue(global_symbols.sym_id, (const void *)name_hash,
- (const void *)id);
- CFDictionarySetValue(global_symbols.id_str, (const void *)id,
- (const void *)str);
-#else
- st_add_direct(global_symbols.sym_id, (st_data_t)str, id);
- st_add_direct(global_symbols.id_str, id, (st_data_t)str);
-#endif
- return id;
-}
-
-ID
-rb_intern2(const char *name, long len)
-{
-#if WITH_OBJC
- return rb_intern3(name, len, NULL);
-#else
- return rb_intern3(name, len, rb_usascii_encoding());
-#endif
-}
-
-#undef rb_intern
-ID
-rb_intern(const char *name)
-{
- return rb_intern2(name, strlen(name));
-}
-
-ID
-rb_intern_str(VALUE str)
-{
- const char *s = RSTRING_PTR(str);
- return rb_intern3(s, strlen(s), NULL);
-}
-
-VALUE
-rb_id2str(ID id)
-{
- st_data_t data;
-
- if (id < tLAST_TOKEN) {
- int i = 0;
-
- for (i=0; op_tbl[i].token; i++) {
- if (op_tbl[i].token == id) {
- VALUE str = global_symbols.op_sym[i];
- if (!str) {
- str = rsymbol_new(op_tbl[i].name, strlen(op_tbl[i].name), op_tbl[i].token);
- global_symbols.op_sym[i] = str;
- }
- return str;
- }
- }
- }
-
- data = (VALUE)CFDictionaryGetValue(
- (CFDictionaryRef)global_symbols.id_str,
- (const void *)id);
- if (data != 0) {
- return data;
- }
-
- if (is_attrset_id(id)) {
- ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
- VALUE str;
-
- while (!(str = rb_id2str(id2))) {
- if (!is_local_id(id2)) return 0;
- id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
- }
- str = rb_str_dup(str);
- rb_str_cat(str, "=", 1);
- rb_intern_str(str);
- data = (VALUE)CFDictionaryGetValue(
- (CFDictionaryRef)global_symbols.id_str,
- (const void *)id);
- if (data != 0) {
- return data;
- }
- }
- return 0;
-}
-
-VALUE
-rb_name2sym(const char *name)
-{
- return rb_id2str(rb_intern(name));
-}
-
const char *
ruby_node_name(int node)
{
@@ -9797,41 +9280,7 @@
return 0;
}
}
-
-/*
- * call-seq:
- * Symbol.all_symbols => array
- *
- * Returns an array of all the symbols currently in Ruby's symbol
- * table.
- *
- * Symbol.all_symbols.size #=> 903
- * Symbol.all_symbols[1,20] #=> [:floor, :ARGV, :Binding, :symlink,
- * :chown, :EOFError, :$;, :String,
- * :LOCK_SH, :"setuid?", :$<,
- * :default_proc, :compact, :extend,
- * :Tms, :getwd, :$=, :ThreadGroup,
- * :wait2, :$>]
- */
-VALUE
-rb_sym_all_symbols(void)
-{
- const void **values;
- long count;
- VALUE ary;
-
- ary = rb_ary_new();
- count = CFDictionaryGetCount(global_symbols.id_str);
- if (count == 0) {
- return ary;
- }
- values = alloca(sizeof(void *) * count);
- CFDictionaryGetKeysAndValues(global_symbols.id_str, NULL, values);
- CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), values, count);
- return ary;
-}
-
int
rb_is_const_id(ID id)
{
@@ -9867,6 +9316,14 @@
return Qfalse;
}
+ID
+rb_id_attrset(ID id)
+{
+ id &= ~ID_SCOPE_MASK;
+ id |= ID_ATTRSET;
+ return id;
+}
+
#endif /* !RIPPER */
static void
Modified: MacRuby/branches/icu/rakelib/builder/builder.rb
===================================================================
--- MacRuby/branches/icu/rakelib/builder/builder.rb 2010-02-25 08:15:14 UTC (rev 3616)
+++ MacRuby/branches/icu/rakelib/builder/builder.rb 2010-02-25 08:17:43 UTC (rev 3617)
@@ -6,7 +6,7 @@
random range rational re ruby signal sprintf st string struct time transcode
util variable version thread id objc bs ucnv encoding main dln dmyext marshal
gcd vm_eval prelude miniprelude gc-stub bridgesupport compiler dispatcher vm
- debugger MacRuby MacRubyDebuggerConnector NSArray NSDictionary
+ symbol debugger MacRuby MacRubyDebuggerConnector NSArray NSDictionary
}
EXTENSIONS = %w{
Modified: MacRuby/branches/icu/string.c
===================================================================
--- MacRuby/branches/icu/string.c 2010-02-25 08:15:14 UTC (rev 3616)
+++ MacRuby/branches/icu/string.c 2010-02-25 08:17:43 UTC (rev 3617)
@@ -22,9 +22,6 @@
#include "ruby/node.h"
#include "vm.h"
-VALUE rb_cSymbol; // XXX move me outside
-VALUE rb_cByteString; // XXX remove all references about me, i'm dead
-
VALUE rb_cString;
VALUE rb_cNSString;
VALUE rb_cNSMutableString;
@@ -706,8 +703,12 @@
// self[pos..pos+len] = str
assert(pos >= 0 && len >= 0);
+ if (str != NULL) {
+ str_must_have_compatible_encoding(self, str);
+ str_make_same_format(self, str);
+ }
+
character_boundaries_t beg, end;
-
if (pos + len == 0) {
// Positioning before the string.
const long offset = 0;
@@ -740,8 +741,6 @@
long bytes_to_add = 0;
if (str != NULL) {
- str_must_have_compatible_encoding(self, str);
- str_make_same_format(self, str);
if (str->length_in_bytes > bytes_to_splice) {
str_resize_bytes(self, self->length_in_bytes
+ (str->length_in_bytes - bytes_to_splice));
@@ -1826,12 +1825,12 @@
str_append_uchar(RSTR(result), c);
}
-static VALUE
-str_inspect(VALUE str, bool dump)
+VALUE
+str_inspect(rb_str_t *str, bool dump)
{
- const bool uchars = str_is_stored_in_uchars(RSTR(str));
+ const bool uchars = str_is_stored_in_uchars(str);
const long len = uchars
- ? str_length(RSTR(str), true) : RSTR(str)->length_in_bytes;
+ ? str_length(str, true) : str->length_in_bytes;
if (len == 0) {
return rb_str_new2("\"\"");
@@ -1840,12 +1839,12 @@
// Allocate an UTF-8 string with a good initial capacity.
// Binary strings will likely have most bytes escaped.
const long result_init_len =
- BINARY_ENC(RSTR(str)->encoding) ? (len * 5) + 2 : len + 2;
+ BINARY_ENC(str->encoding) ? (len * 5) + 2 : len + 2;
VALUE result = rb_unicode_str_new(NULL, result_init_len);
#define GET_UCHAR(pos) \
((uchars \
- ? RSTR(str)->data.uchars[pos] : (UChar)RSTR(str)->data.bytes[pos]))
+ ? str->data.uchars[pos] : (UChar)str->data.bytes[pos]))
inspect_append(result, '"', false);
for (long i = 0; i < len; i++) {
@@ -1908,7 +1907,7 @@
static VALUE
rstr_inspect(VALUE self, SEL sel)
{
- return str_inspect(self, false);
+ return str_inspect(RSTR(self), false);
}
/*
@@ -1922,7 +1921,7 @@
static VALUE
rstr_dump(VALUE self, SEL sel)
{
- return str_inspect(self, true);
+ return str_inspect(RSTR(self), true);
}
/*
@@ -3005,10 +3004,6 @@
rb_fs = Qnil;
rb_define_variable("$;", &rb_fs);
rb_define_variable("$-F", &rb_fs);
-
- // rb_cSymbol is defined earlier in Init_PreVM().
- rb_set_class_path(rb_cSymbol, rb_cObject, "Symbol");
- rb_const_set(rb_cObject, rb_intern("Symbol"), rb_cSymbol);
}
bool
@@ -3487,16 +3482,41 @@
return (VALUE)str_dup(RSTR(str));
}
if (TYPE(str) == T_SYMBOL) {
- return rb_str_new2(RSYMBOL(str)->str);
+ return rb_sym_to_s(str);
}
abort(); // TODO
}
-int
+// Unicode characters hashing function, copied from CoreFoundation.
+// This function might have some performance issues on large strings.
+unsigned long
+rb_str_hash_uchars(UChar *chars, long len)
+{
+#define HashNextFourUniChars(accessStart, accessEnd, pointer) \
+ {result = result * 67503105 + (accessStart 0 accessEnd) * 16974593 + (accessStart 1 accessEnd) * 66049 + (accessStart 2 accessEnd) * 257 + (accessStart 3 accessEnd); pointer += 4;}
+
+#define HashNextUniChar(accessStart, accessEnd, pointer) \
+ {result = result * 257 + (accessStart 0 accessEnd); pointer++;}
+
+ assert(len > 0);
+ unsigned long result = len;
+ const UChar *end4 = chars + (len & ~3);
+ const UChar *end = chars + len;
+ // First count in fours
+ while (chars < end4) HashNextFourUniChars(chars[, ], chars);
+ // Then for the last <4 chars, count in ones...
+ while (chars < end) HashNextUniChar(chars[, ], chars);
+ return result + (result << (len & 31));
+
+#undef HashNextFourUniChars
+#undef HashNextUniChar
+}
+
+long
rb_memhash(const void *ptr, long len)
{
CFDataRef data = CFDataCreate(NULL, (const UInt8 *)ptr, len);
- int code = CFHash(data);
+ const long code = CFHash(data);
CFRelease((CFTypeRef)data);
return code;
}
@@ -3531,11 +3551,3 @@
{
abort(); // TODO
}
-
-// Symbols (TODO: move me outside)
-
-VALUE
-rb_sym_to_s(VALUE sym)
-{
- return rb_str_new2(RSYMBOL(sym)->str);
-}
Added: MacRuby/branches/icu/symbol.c
===================================================================
--- MacRuby/branches/icu/symbol.c (rev 0)
+++ MacRuby/branches/icu/symbol.c 2010-02-25 08:17:43 UTC (rev 3617)
@@ -0,0 +1,362 @@
+/*
+ * MacRuby Symbols.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2010, Apple Inc. All rights reserved.
+ */
+
+#include <wctype.h>
+
+#include "ruby.h"
+#include "ruby/encoding.h"
+#include "encoding.h"
+#include "symbol.h"
+#include "ruby/node.h"
+#include "vm.h"
+
+VALUE rb_cSymbol;
+
+static CFMutableDictionaryRef sym_id = NULL, id_str = NULL;
+static long last_id = 0;
+
+typedef struct {
+ VALUE klass;
+ rb_str_t *str;
+ ID id;
+ SEL sel;
+} rb_sym_t;
+
+#define RSYM(obj) ((rb_sym_t *)(obj))
+
+static rb_sym_t *
+sym_alloc(rb_str_t *str, ID id)
+{
+ rb_sym_t *sym = (rb_sym_t *)malloc(sizeof(rb_sym_t));
+ assert(rb_cSymbol != 0);
+ sym->klass = rb_cSymbol;
+ GC_RETAIN(str); // never released
+ sym->str = str;
+ sym->id = id;
+ sym->sel = NULL; // lazy
+ return sym;
+}
+
+ID
+rb_intern_str(VALUE str)
+{
+ UChar *chars = NULL;
+ long chars_len = 0;
+ bool need_free = false;
+ rb_str_get_uchars(str, &chars, &chars_len, &need_free);
+ assert(chars_len > 0);
+
+ const unsigned long name_hash = rb_str_hash_uchars(chars, chars_len);
+ ID id = (ID)CFDictionaryGetValue(sym_id, (const void *)name_hash);
+ if (id != 0) {
+ goto return_id;
+ }
+
+ rb_sym_t *sym = NULL;
+
+ switch (chars[0]) {
+ case '$':
+ id = ID_GLOBAL;
+ break;
+
+ case '@':
+ if (chars_len > 1 && chars[1] == '@') {
+ id = ID_CLASS;
+ }
+ else {
+ id = ID_INSTANCE;
+ }
+ break;
+
+ default:
+ if (chars_len > 1 && chars[chars_len - 1] == '=') {
+ // Attribute assignment.
+ id = rb_intern_str(rb_str_substr(str, 0, chars_len - 1));
+ if (!is_attrset_id(id)) {
+ id = rb_id_attrset(id);
+ goto id_register;
+ }
+ id = ID_ATTRSET;
+ }
+ else if (iswupper(chars[0])) {
+ id = ID_CONST;
+ }
+ else {
+ id = ID_LOCAL;
+ }
+ break;
+ }
+
+ id |= ++last_id << ID_SCOPE_SHIFT;
+
+id_register:
+//printf("register %s hash %ld id %ld\n", RSTRING_PTR(str), name_hash, id);
+ sym = sym_alloc(RSTR(str), id);
+ CFDictionarySetValue(sym_id, (const void *)name_hash, (const void *)id);
+ CFDictionarySetValue(id_str, (const void *)id, (const void *)sym);
+
+return_id:
+ if (need_free && chars != NULL) {
+ free(chars);
+ }
+ return id;
+}
+
+VALUE
+rb_id2str(ID id)
+{
+ VALUE sym = (VALUE)CFDictionaryGetValue(id_str, (const void *)id);
+ if (sym != 0) {
+//printf("lookup %ld -> %s\n", id, rb_sym2name(sym));
+ return sym;
+ }
+
+ if (is_attrset_id(id)) {
+ // Attribute assignment.
+ ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
+
+ while ((sym = rb_id2str(id2)) == 0) {
+ if (!is_local_id(id2)) {
+//printf("lookup %ld -> FAIL\n", id);
+ return 0;
+ }
+ id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
+ }
+
+ VALUE str = rb_str_dup((VALUE)RSYM(sym)->str);
+ rb_str_cat(str, "=", 1);
+ rb_intern_str(str);
+
+ // Retry one more time.
+ sym = (VALUE)CFDictionaryGetValue(id_str, (const void *)id);
+ if (sym != 0) {
+//printf("lookup %ld -> %s\n", id, rb_sym2name(sym));
+ return sym;
+ }
+ }
+//printf("lookup %ld -> FAIL\n", id);
+ return 0;
+}
+
+ID
+rb_intern3(const char *name, long len, rb_encoding *enc)
+{
+ VALUE str = rb_enc_str_new(name, len, enc);
+ return rb_intern_str(str);
+}
+
+ID
+rb_intern2(const char *name, long len)
+{
+ return rb_intern_str(rb_str_new(name, len));
+}
+
+ID
+rb_intern(const char *name)
+{
+ return rb_intern_str(rb_str_new2(name));
+}
+
+ID
+rb_sym2id(VALUE sym)
+{
+ return RSYM(sym)->id;
+}
+
+VALUE
+rb_name2sym(const char *name)
+{
+ return rb_id2str(rb_intern(name));
+}
+
+VALUE
+rb_sym2str(VALUE sym)
+{
+ return (VALUE)RSYM(sym)->str;
+}
+
+VALUE
+rb_sym_to_s(VALUE sym)
+{
+ return rb_str_dup(rb_sym2str(sym));
+}
+
+const char *
+rb_sym2name(VALUE sym)
+{
+ return RSTRING_PTR(RSYM(sym)->str);
+}
+
+/*
+ * call-seq:
+ * Symbol.all_symbols => array
+ *
+ * Returns an array of all the symbols currently in Ruby's symbol
+ * table.
+ *
+ * Symbol.all_symbols.size #=> 903
+ * Symbol.all_symbols[1,20] #=> [:floor, :ARGV, :Binding, :symlink,
+ * :chown, :EOFError, :$;, :String,
+ * :LOCK_SH, :"setuid?", :$<,
+ * :default_proc, :compact, :extend,
+ * :Tms, :getwd, :$=, :ThreadGroup,
+ * :wait2, :$>]
+ */
+
+static VALUE
+rsym_all_symbols(VALUE klass, SEL sel)
+{
+ VALUE ary = rb_ary_new();
+ const long count = CFDictionaryGetCount(id_str);
+ if (count >= 0) {
+ const void **values = (const void **)malloc(sizeof(void *) * count);
+ CFDictionaryGetKeysAndValues(id_str, NULL, values);
+ for (long i = 0; i < count; i++) {
+ rb_ary_push(ary, (VALUE)values[i]);
+ }
+ free(values);
+ }
+ return ary;
+}
+
+void
+Init_PreSymbol(void)
+{
+ sym_id = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+ id_str = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+ last_id = 1000;
+
+ // Pre-register parser symbols.
+ for (int i = 0; rb_op_tbl[i].token != 0; i++) {
+ VALUE str = rb_str_new2(rb_op_tbl[i].name);
+
+ UChar *chars = NULL;
+ long chars_len = 0;
+ bool need_free = false;
+ rb_str_get_uchars(str, &chars, &chars_len, &need_free);
+ assert(chars_len > 0);
+
+ ID id = rb_op_tbl[i].token;
+ rb_sym_t *sym = sym_alloc(RSTR(str), id);
+ unsigned long name_hash = rb_str_hash_uchars(chars, chars_len);
+
+//printf("pre-register %s hash %ld id %ld\n", RSTRING_PTR(str), name_hash, id);
+
+ CFDictionarySetValue(sym_id, (const void *)name_hash, (const void *)id);
+ CFDictionarySetValue(id_str, (const void *)id, (const void *)sym);
+
+ if (need_free && chars != NULL) {
+ free(chars);
+ }
+ }
+}
+
+/*
+ * call-seq:
+ * sym == obj => true or false
+ *
+ * Equality---If <i>sym</i> and <i>obj</i> are exactly the same
+ * symbol, returns <code>true</code>. Otherwise, compares them
+ * as strings.
+ */
+
+static VALUE
+rsym_equal(VALUE sym, SEL sel, VALUE other)
+{
+ return sym == other ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * sym.inspect => string
+ *
+ * Returns the representation of <i>sym</i> as a symbol literal.
+ *
+ * :fred.inspect #=> ":fred"
+ */
+
+static VALUE
+rsym_inspect(VALUE sym, SEL sel)
+{
+ VALUE str = rb_str_new2(":");
+ rb_str_concat(str, str_inspect(RSYM(sym)->str, true));
+ return str;
+}
+
+/*
+ * call-seq:
+ * sym.to_proc
+ *
+ * Returns a _Proc_ object which respond to the given method by _sym_.
+ *
+ * (1..3).collect(&:to_s) #=> ["1", "2", "3"]
+ */
+
+static VALUE
+rsym_to_proc(VALUE sym, SEL sel)
+{
+ SEL msel = sel_registerName(rb_id2name(SYM2ID(sym)));
+ rb_vm_block_t *b = rb_vm_create_block_calling_sel(msel);
+ return rb_proc_alloc_with_block(rb_cProc, b);
+}
+
+/*
+ * call-seq:
+ * sym.id2name => string
+ * sym.to_s => string
+ *
+ * Returns the name or string corresponding to <i>sym</i>.
+ *
+ * :fred.id2name #=> "fred"
+ */
+
+static VALUE
+rsym_to_s(VALUE sym, SEL sel)
+{
+ return rb_sym_to_s(sym);
+}
+
+/*
+ * call-seq:
+ * sym.to_sym => sym
+ * sym.intern => sym
+ *
+ * In general, <code>to_sym</code> returns the <code>Symbol</code>
+ * corresponding to an object. As <i>sym</i> is already a symbol,
+ * <code>self</code> is returned in this case.
+ */
+
+static VALUE
+rsym_to_sym(VALUE sym, SEL sel)
+{
+ return sym;
+}
+
+void
+Init_Symbol(void)
+{
+ // rb_cSymbol is defined earlier in Init_PreVM().
+ rb_set_class_path(rb_cSymbol, rb_cObject, "Symbol");
+ rb_const_set(rb_cObject, rb_intern("Symbol"), rb_cSymbol);
+
+ rb_undef_alloc_func(rb_cSymbol);
+ rb_undef_method(*(VALUE *)rb_cSymbol, "new");
+ rb_objc_define_method(*(VALUE *)rb_cSymbol, "all_symbols",
+ rsym_all_symbols, 0);
+
+ rb_objc_define_method(rb_cSymbol, "==", rsym_equal, 1);
+ rb_objc_define_method(rb_cSymbol, "eql?", rsym_equal, 1);
+ //rb_objc_define_method(rb_cSymbol, "<=>", rsym_cmp, 1);
+ rb_objc_define_method(rb_cSymbol, "inspect", rsym_inspect, 0);
+ rb_objc_define_method(rb_cSymbol, "to_proc", rsym_to_proc, 0);
+ rb_objc_define_method(rb_cSymbol, "to_s", rsym_to_s, 0);
+ rb_objc_define_method(rb_cSymbol, "id2name", rsym_to_s, 0);
+ rb_objc_define_method(rb_cSymbol, "description", rsym_to_s, 0);
+ rb_objc_define_method(rb_cSymbol, "intern", rsym_to_sym, 0);
+ rb_objc_define_method(rb_cSymbol, "to_sym", rsym_to_sym, 0);
+}
Added: MacRuby/branches/icu/symbol.h
===================================================================
--- MacRuby/branches/icu/symbol.h (rev 0)
+++ MacRuby/branches/icu/symbol.h 2010-02-25 08:17:43 UTC (rev 3617)
@@ -0,0 +1,54 @@
+/*
+ * MacRuby Symbols.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2010, Apple Inc. All rights reserved.
+ */
+
+#ifndef __SYMBOL_H_
+#define __SYMBOL_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+// For the parser.
+#define ID_SCOPE_SHIFT 3
+#define ID_SCOPE_MASK 0x07
+#define ID_LOCAL 0x00
+#define ID_INSTANCE 0x01
+#define ID_GLOBAL 0x03
+#define ID_ATTRSET 0x04
+#define ID_CONST 0x05
+#define ID_CLASS 0x06
+#define ID_JUNK 0x07
+#define ID_INTERNAL ID_JUNK
+
+#define is_notop_id(id) (true)
+#define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
+#define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
+#define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
+#define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
+#define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
+#define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
+#define is_junk_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)
+
+#define is_asgn_or_id(id) ((is_notop_id(id)) && \
+ (((id)&ID_SCOPE_MASK) == ID_GLOBAL || \
+ ((id)&ID_SCOPE_MASK) == ID_INSTANCE || \
+ ((id)&ID_SCOPE_MASK) == ID_CLASS))
+
+struct rb_op_tbl_entry {
+ ID token;
+ const char *name;
+};
+
+// Defined in parse.y.
+extern struct rb_op_tbl_entry rb_op_tbl[];
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
+
+#endif // __SYMBOL_H_
Modified: MacRuby/branches/icu/vm.cpp
===================================================================
--- MacRuby/branches/icu/vm.cpp 2010-02-25 08:15:14 UTC (rev 3616)
+++ MacRuby/branches/icu/vm.cpp 2010-02-25 08:17:43 UTC (rev 3617)
@@ -2845,8 +2845,8 @@
int n = 0;
VALUE args[3];
- args[n++] = rb_funcall(rb_cNameErrorMesg, '!', 3, rb_str_new2(format),
- obj, meth);
+ VALUE not_args[3] = {rb_str_new2(format), obj, meth};
+ args[n++] = rb_vm_call(rb_cNameErrorMesg, selNot2, 3, not_args, false);
args[n++] = meth;
if (exc == rb_eNoMethodError) {
args[n++] = rb_ary_new4(argc - 1, argv + 1);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100225/d24555f1/attachment-0001.html>
More information about the macruby-changes
mailing list