[macruby-changes] [2357] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Sat Aug 22 12:05:32 PDT 2009
Revision: 2357
http://trac.macosforge.org/projects/ruby/changeset/2357
Author: lsansonetti at apple.com
Date: 2009-08-22 12:05:28 -0700 (Sat, 22 Aug 2009)
Log Message:
-----------
fixing and adding several missing ruby method features
Modified Paths:
--------------
MacRuby/trunk/array.c
MacRuby/trunk/class.c
MacRuby/trunk/compiler.cpp
MacRuby/trunk/compiler.h
MacRuby/trunk/id.c
MacRuby/trunk/id.h
MacRuby/trunk/include/ruby/ruby.h
MacRuby/trunk/lib/yaml/rubytypes.rb
MacRuby/trunk/object.c
MacRuby/trunk/proc.c
MacRuby/trunk/spec/frozen/language/def_spec.rb
MacRuby/trunk/spec/frozen/library/date/conversions_spec.rb
MacRuby/trunk/spec/frozen/tags/macruby/core/array/initialize_copy_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/array/initialize_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/basicobject/method_missing_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/module/alias_method_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/module/method_added_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/module/remove_const_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/string/initialize_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/language/def_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/language/method_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/library/net/ftp/initialize_tags.txt
MacRuby/trunk/vm.cpp
MacRuby/trunk/vm.h
MacRuby/trunk/vm_eval.c
MacRuby/trunk/vm_method.c
Removed Paths:
-------------
MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/respond_to_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/singleton_method_added_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/singleton_method_removed_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/singleton_method_undefined_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/module/extended_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/module/included_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_class_method_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_instance_methods_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_method_defined_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/range/initialize_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/struct/initialize_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/language/private_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/initialize_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/library/net/http/http/initialize_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/library/set/initialize_copy_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/library/set/initialize_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/library/set/sortedset/initialize_copy_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/library/set/sortedset/initialize_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/library/stringio/initialize_copy_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/library/stringscanner/initialize_copy_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/library/stringscanner/initialize_tags.txt
Modified: MacRuby/trunk/array.c
===================================================================
--- MacRuby/trunk/array.c 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/array.c 2009-08-22 19:05:28 UTC (rev 2357)
@@ -213,6 +213,9 @@
if (SPECIAL_CONST_P(x) && SPECIAL_CONST_P(y) && TYPE(x) == TYPE(y)) {
return Qfalse;
}
+ if (SYMBOL_P(x)) {
+ return x == y ? Qtrue : Qfalse;
+ }
return rb_equal(x, y);
}
Modified: MacRuby/trunk/class.c
===================================================================
--- MacRuby/trunk/class.c 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/class.c 2009-08-22 19:05:28 UTC (rev 2357)
@@ -121,8 +121,8 @@
rb_objc_define_method(*(VALUE *)klass, "__new__",
rb_class_new_instance_imp, -1);
rb_objc_define_method(klass, "dup", rb_obj_dup, 0);
- rb_objc_define_method(klass, "initialize", rb_objc_init, 0);
- rb_objc_define_method(klass, "initialize_copy", rb_obj_init_copy, 1);
+ rb_objc_define_private_method(klass, "initialize", rb_objc_init, 0);
+ rb_objc_define_private_method(klass, "initialize_copy", rb_obj_init_copy, 1);
rb_objc_install_method(*(Class *)klass, selAllocWithZone,
(IMP)rb_obj_imp_allocWithZone);
@@ -400,20 +400,20 @@
VALUE
rb_define_class_id(ID id, VALUE super)
{
- VALUE klass;
-
- if (!super) super = rb_cObject;
- klass = rb_objc_create_class(rb_id2name(id), super);
-
- return klass;
+ if (super == 0) {
+ super = rb_cObject;
+ }
+ return rb_objc_create_class(rb_id2name(id), super);
}
VALUE
rb_class_inherited(VALUE super, VALUE klass)
{
if (rb_vm_running()) {
- if (!super) super = rb_cObject;
- return rb_funcall(super, rb_intern("inherited"), 1, klass);
+ if (super == 0) {
+ super = rb_cObject;
+ }
+ return rb_vm_call(super, selInherited, 1, &klass, false);
}
return Qnil;
}
@@ -717,21 +717,22 @@
static int
ins_methods_push(VALUE name, long type, VALUE ary, long visi)
{
- if (type == -1) return ST_CONTINUE;
-
- switch (visi) {
- case NOEX_PRIVATE:
- case NOEX_PROTECTED:
- case NOEX_PUBLIC:
- visi = (type == visi);
- break;
- default:
- visi = (type != NOEX_PRIVATE);
- break;
+ if (type != -1) {
+ bool visible;
+ switch (visi) {
+ case NOEX_PRIVATE:
+ case NOEX_PROTECTED:
+ case NOEX_PUBLIC:
+ visible = (type == visi);
+ break;
+ default:
+ visible = (type != NOEX_PRIVATE);
+ break;
+ }
+ if (visible) {
+ rb_ary_push(ary, name);
+ }
}
- if (visi) {
- rb_ary_push(ary, name);
- }
return ST_CONTINUE;
}
@@ -1010,7 +1011,7 @@
void
rb_undef_method(VALUE klass, const char *name)
{
- rb_vm_undef_method((Class)klass, name, false);
+ rb_vm_undef_method((Class)klass, rb_intern(name), false);
}
#define SPECIAL_SINGLETON(x,c) do {\
Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/compiler.cpp 2009-08-22 19:05:28 UTC (rev 2357)
@@ -121,6 +121,8 @@
longjmpFunc = NULL;
setjmpFunc = NULL;
popBrokenValue = NULL;
+ setScopeFunc = NULL;
+ setCurrentClassFunc = NULL;
#if __LP64__
RubyObjTy = IntTy = Type::Int64Ty;
@@ -133,6 +135,9 @@
twoVal = ConstantInt::get(IntTy, 2);
threeVal = ConstantInt::get(IntTy, 3);
+ defaultScope = ConstantInt::get(Type::Int32Ty, SCOPE_DEFAULT);
+ publicScope = ConstantInt::get(Type::Int32Ty, SCOPE_PUBLIC);
+
RubyObjPtrTy = PointerType::getUnqual(RubyObjTy);
RubyObjPtrPtrTy = PointerType::getUnqual(RubyObjPtrTy);
nilVal = ConstantInt::get(RubyObjTy, Qnil);
@@ -622,22 +627,23 @@
}
void
-RoxorCompiler::compile_prepare_method(Value *classVal, Value *sel,
- Function *new_function, rb_vm_arity_t &arity, NODE *body)
+RoxorCompiler::compile_prepare_method(Value *classVal, bool singleton,
+ Value *sel, Function *new_function, rb_vm_arity_t &arity, NODE *body)
{
if (prepareMethodFunc == NULL) {
- // void rb_vm_prepare_method(Class klass, SEL sel,
- // Function *func, rb_vm_arity_t arity, int flags)
+ // void rb_vm_prepare_method(Class klass, unsigned char singleton,
+ // SEL sel, Function *func, rb_vm_arity_t arity, int flags)
prepareMethodFunc =
cast<Function>(module->getOrInsertFunction(
"rb_vm_prepare_method",
- Type::VoidTy, RubyObjTy, PtrTy, PtrTy,
+ Type::VoidTy, RubyObjTy, Type::Int8Ty, PtrTy, PtrTy,
Type::Int64Ty, Type::Int32Ty, NULL));
}
std::vector<Value *> params;
params.push_back(classVal);
+ params.push_back(ConstantInt::get(Type::Int8Ty, singleton));
params.push_back(sel);
params.push_back(compile_const_pointer(new_function));
@@ -650,22 +656,23 @@
}
void
-RoxorAOTCompiler::compile_prepare_method(Value *classVal, Value *sel,
- Function *new_function, rb_vm_arity_t &arity, NODE *body)
+RoxorAOTCompiler::compile_prepare_method(Value *classVal, bool singleton,
+ Value *sel, Function *new_function, rb_vm_arity_t &arity, NODE *body)
{
if (prepareMethodFunc == NULL) {
- // void rb_vm_prepare_method2(Class klass, SEL sel,
- // IMP ruby_imp, rb_vm_arity_t arity, int flags)
+ // void rb_vm_prepare_method2(Class klass, unsigned char singleton,
+ // SEL sel, IMP ruby_imp, rb_vm_arity_t arity, int flags)
prepareMethodFunc =
cast<Function>(module->getOrInsertFunction(
"rb_vm_prepare_method2",
- Type::VoidTy, RubyObjTy, PtrTy, PtrTy,
+ Type::VoidTy, RubyObjTy, Type::Int8Ty, PtrTy, PtrTy,
Type::Int64Ty, Type::Int32Ty, NULL));
}
std::vector<Value *> params;
params.push_back(classVal);
+ params.push_back(ConstantInt::get(Type::Int8Ty, singleton));
params.push_back(sel);
// Make sure the function is compiled before use, this way LLVM won't use
@@ -674,6 +681,7 @@
params.push_back(new BitCastInst(new_function, PtrTy, "", bb));
params.push_back(compile_arity(arity));
+
params.push_back(ConstantInt::get(Type::Int32Ty, rb_vm_node_flags(body)));
CallInst::Create(prepareMethodFunc, params.begin(),
@@ -733,7 +741,11 @@
params.push_back(recv);
params.push_back(compile_sel(sel));
params.push_back(compile_const_pointer(NULL));
- params.push_back(ConstantInt::get(Type::Int8Ty, 0));
+ unsigned char opt = 0;
+ if (recv == current_self) {
+ opt = DISPATCH_SELF_ATTRASGN;
+ }
+ params.push_back(ConstantInt::get(Type::Int8Ty, opt));
params.push_back(ConstantInt::get(Type::Int32Ty, argc));
for (std::vector<Value *>::iterator i = args.begin();
i != args.end();
@@ -2469,7 +2481,7 @@
new_params.push_back(params[1]);
new_params.push_back(compile_sel(new_sel));
new_params.push_back(params[3]);
- new_params.push_back(params[4]);
+ new_params.push_back(ConstantInt::get(Type::Int8Ty, DISPATCH_FCALL));
new_params.push_back(ConstantInt::get(Type::Int32Ty, argc - 1));
for (int i = 0; i < argc - 1; i++) {
new_params.push_back(params[7 + i]);
@@ -2727,7 +2739,41 @@
return new LoadInst(gvar, "", bb);
}
+Value *
+RoxorCompiler::compile_set_current_class(Value *klass)
+{
+ if (setCurrentClassFunc == NULL) {
+ // Class rb_vm_set_current_class(Class klass)
+ setCurrentClassFunc = cast<Function>(
+ module->getOrInsertFunction("rb_vm_set_current_class",
+ RubyObjTy, RubyObjTy, NULL));
+ }
+
+ std::vector<Value *> params;
+ params.push_back(klass);
+
+ return CallInst::Create(setCurrentClassFunc, params.begin(), params.end(),
+ "", bb);
+}
+
void
+RoxorCompiler::compile_set_current_scope(Value *klass, Value *scope)
+{
+ if (setScopeFunc == NULL) {
+ // void rb_vm_set_current_scope(VALUE mod, int scope)
+ setScopeFunc = cast<Function>(
+ module->getOrInsertFunction("rb_vm_set_current_scope",
+ Type::VoidTy, RubyObjTy, Type::Int32Ty, NULL));
+ }
+
+ std::vector<Value *> params;
+ params.push_back(klass);
+ params.push_back(scope);
+
+ CallInst::Create(setScopeFunc, params.begin(), params.end(), "", bb);
+}
+
+void
RoxorCompiler::compile_ivar_slots(Value *klass,
BasicBlock::InstListType &list,
BasicBlock::InstListType::iterator list_iter)
@@ -3692,8 +3738,16 @@
current_module = nd_type(node) == NODE_MODULE;
+ compile_set_current_scope(classVal, publicScope);
+ Value *old_current_class =
+ compile_set_current_class(
+ ConstantInt::get(RubyObjTy, 0));
+
Value *val = compile_node(body->nd_body);
+ compile_set_current_class(old_current_class);
+ compile_set_current_scope(classVal, defaultScope);
+
BasicBlock::InstListType &list = bb->getInstList();
compile_ivar_slots(classVal, list, list.end());
@@ -3844,7 +3898,8 @@
? DISPATCH_SUPER
: (nd_type(node) == NODE_VCALL)
? DISPATCH_VCALL
- : 0;
+ : (nd_type(node) == NODE_FCALL)
+ ? DISPATCH_FCALL : 0;
params.push_back(ConstantInt::get(Type::Int8Ty, call_opt));
// Arguments.
@@ -4271,7 +4326,7 @@
rb_vm_arity_t arity = rb_vm_node_arity(body);
const SEL sel = mid_to_sel(mid, arity.real);
- compile_prepare_method(classVal, compile_sel(sel),
+ compile_prepare_method(classVal, singleton_method, compile_sel(sel),
new_function, arity, body);
return nilVal;
Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/compiler.h 2009-08-22 19:05:28 UTC (rev 2357)
@@ -12,9 +12,11 @@
#if defined(__cplusplus)
// For the dispatcher.
-#define DISPATCH_VCALL 1
-#define DISPATCH_SUPER 2
-#define SPLAT_ARG_FOLLOWS 0xdeadbeef
+#define DISPATCH_VCALL 1 // no receiver, no argument
+#define DISPATCH_FCALL 2 // no receiver, one or more arguments
+#define DISPATCH_SUPER 3 // super call
+#define DISPATCH_SELF_ATTRASGN 4 // self attribute assignment
+#define SPLAT_ARG_FOLLOWS 0xdeadbeef
// For defined?
#define DEFINED_IVAR 1
@@ -172,6 +174,8 @@
Function *longjmpFunc;
Function *setjmpFunc;
Function *popBrokenValue;
+ Function *setScopeFunc;
+ Function *setCurrentClassFunc;
Constant *zeroVal;
Constant *oneVal;
@@ -183,6 +187,8 @@
Constant *undefVal;
Constant *splatArgFollowsVal;
Constant *cObject;
+ Constant *defaultScope;
+ Constant *publicScope;
const Type *RubyObjTy;
const Type *RubyObjPtrTy;
const Type *RubyObjPtrPtrTy;
@@ -222,8 +228,9 @@
BasicBlock *thenBB);
void compile_single_when_argument(NODE *arg, Value *comparedToVal,
BasicBlock *thenBB);
- virtual void compile_prepare_method(Value *classVal, Value *sel,
- Function *new_function, rb_vm_arity_t &arity, NODE *body);
+ virtual void compile_prepare_method(Value *classVal, bool singleton,
+ Value *sel, Function *new_function, rb_vm_arity_t &arity,
+ NODE *body);
Value *compile_dispatch_call(std::vector<Value *> ¶ms);
Value *compile_when_splat(Value *comparedToVal, Value *splatVal);
Value *compile_fast_op_call(SEL sel, Value *selfVal, Value *comparedToVal);
@@ -273,6 +280,9 @@
virtual Value *compile_immutable_literal(VALUE val);
virtual Value *compile_global_entry(NODE *node);
+ void compile_set_current_scope(Value *klass, Value *scope);
+ Value *compile_set_current_class(Value *klass);
+
Value *compile_landing_pad_header(void);
Value *compile_landing_pad_header(const std::type_info &eh_type);
void compile_landing_pad_footer(bool pop_exception=true);
@@ -333,8 +343,9 @@
Value *compile_mcache(SEL sel, bool super);
Value *compile_ccache(ID id);
Instruction *compile_sel(SEL sel, bool add_to_bb=true);
- void compile_prepare_method(Value *classVal, Value *sel,
- Function *new_function, rb_vm_arity_t &arity, NODE *body);
+ void compile_prepare_method(Value *classVal, bool singleton,
+ Value *sel, Function *new_function, rb_vm_arity_t &arity,
+ NODE *body);
Value *compile_prepare_block_args(Function *func, int *flags);
Value *compile_nsobject(void);
Value *compile_id(ID id);
Modified: MacRuby/trunk/id.c
===================================================================
--- MacRuby/trunk/id.c 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/id.c 2009-08-22 19:05:28 UTC (rev 2357)
@@ -65,6 +65,7 @@
selInit = sel_registerName("init");
selInitialize = sel_registerName("initialize");
selInitialize2 = sel_registerName("initialize:");
+ selInitializeCopy = sel_registerName("initialize_copy:");
selDescription = sel_registerName("description");
selInspect = sel_registerName("inspect");
selNew = sel_registerName("new");
@@ -95,6 +96,7 @@
selSingletonMethodAdded = sel_registerName("singleton_method_added:");
selIsEqual = sel_registerName("isEqual:");
selWrite = sel_registerName("write:");
+ selInherited = sel_registerName("inherited:");
cacheEach = rb_vm_get_call_cache(selEach);
#endif
Modified: MacRuby/trunk/id.h
===================================================================
--- MacRuby/trunk/id.h 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/id.h 2009-08-22 19:05:28 UTC (rev 2357)
@@ -75,6 +75,7 @@
extern SEL selInit;
extern SEL selInitialize;
extern SEL selInitialize2;
+extern SEL selInitializeCopy;
extern SEL selDescription;
extern SEL selInspect;
extern SEL selNew;
@@ -104,6 +105,7 @@
extern SEL selSingletonMethodAdded;
extern SEL selIsEqual;
extern SEL selWrite;
+extern SEL selInherited;
extern ID idIncludedModules;
extern ID idIncludedInClasses;
extern ID idAncestors;
Modified: MacRuby/trunk/include/ruby/ruby.h
===================================================================
--- MacRuby/trunk/include/ruby/ruby.h 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/include/ruby/ruby.h 2009-08-22 19:05:28 UTC (rev 2357)
@@ -542,18 +542,21 @@
# define RMODULE_M_TBL(m) RCLASS_M_TBL(m)
# define RMODULE_SUPER(m) RCLASS_SUPER(m)
#else
-# define RCLASS_IS_OBJECT_SUBCLASS 0x1000 /* class is a true RBObject subclass */
-# define RCLASS_IS_RUBY_CLASS 0x2000 /* class was created from Ruby */
-# define RCLASS_IS_MODULE 0x4000 /* class represents a Ruby Module */
-# define RCLASS_IS_SINGLETON 0x8000 /* class represents a singleton */
-# define RCLASS_IS_FROZEN 0x10000 /* class is frozen */
-# define RCLASS_IS_TAINTED 0x20000 /* class is tainted */
-# define RCLASS_IS_STRING_SUBCLASS 0x40000 /* class is a subclass of NSCFString */
-# define RCLASS_IS_ARRAY_SUBCLASS 0x80000 /* class is a subclass of NSCFArray */
-# define RCLASS_IS_HASH_SUBCLASS 0x100000 /* class is a subclass of NSCFDictionary */
-# define RCLASS_IS_INCLUDED 0x200000 /* module is included */
-# define RCLASS_IS_SET_SUBCLASS 0x400000 /* class is a subclass of NSCFSet */
-# define RCLASS_HAS_ROBJECT_ALLOC 0x800000 /* class uses the default RObject alloc */
+# define RCLASS_IS_OBJECT_SUBCLASS (1<<12) /* class is a true RBObject subclass */
+# define RCLASS_IS_RUBY_CLASS (1<<13) /* class was created from Ruby */
+# define RCLASS_IS_MODULE (1<<14) /* class represents a Ruby Module */
+# define RCLASS_IS_SINGLETON (1<<15) /* class represents a singleton */
+# define RCLASS_IS_FROZEN (1<<16) /* class is frozen */
+# define RCLASS_IS_TAINTED (1<<17) /* class is tainted */
+# define RCLASS_IS_STRING_SUBCLASS (1<<18) /* class is a subclass of NSCFString */
+# define RCLASS_IS_ARRAY_SUBCLASS (1<<19) /* class is a subclass of NSCFArray */
+# define RCLASS_IS_HASH_SUBCLASS (1<<20) /* class is a subclass of NSCFDictionary */
+# define RCLASS_IS_INCLUDED (1<<21) /* module is included */
+# define RCLASS_IS_SET_SUBCLASS (1<<22) /* class is a subclass of NSCFSet */
+# define RCLASS_HAS_ROBJECT_ALLOC (1<<23) /* class uses the default RObject alloc */
+# define RCLASS_SCOPE_PRIVATE (1<<24) /* class opened for private methods */
+# define RCLASS_SCOPE_PROTECTED (1<<25) /* class opened for protected methods */
+# define RCLASS_SCOPE_MOD_FUNC (1<<26) /* class opened for module_function methods */
# if defined(__LP64__)
# define _PTR_TYPE uint64_t
# define RCLASS_VERSION(m) (class_getVersion((Class)m))
Modified: MacRuby/trunk/lib/yaml/rubytypes.rb
===================================================================
--- MacRuby/trunk/lib/yaml/rubytypes.rb 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/lib/yaml/rubytypes.rb 2009-08-22 19:05:28 UTC (rev 2357)
@@ -12,8 +12,10 @@
def yaml_as(tag)
attr_writer :taguri
klass = (self.is_a? Class) ? self : (class << self; self; end)
- klass.define_method(:taguri) do
- @taguri || tag
+ klass.instance_eval do
+ define_method(:taguri) do
+ @taguri || tag
+ end
end
YAML::LibYAML::DEFAULT_RESOLVER.add_type(tag, self)
end
@@ -556,4 +558,4 @@
end
-=end
\ No newline at end of file
+=end
Modified: MacRuby/trunk/object.c
===================================================================
--- MacRuby/trunk/object.c 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/object.c 2009-08-22 19:05:28 UTC (rev 2357)
@@ -252,7 +252,7 @@
break;
}
call_init_copy:
- rb_funcall(dest, id_init_copy, 1, obj);
+ rb_vm_call(dest, selInitializeCopy, 1, &obj, false);
}
/*
@@ -386,18 +386,17 @@
rb_any_to_string(VALUE obj, SEL sel)
{
const char *cname = rb_obj_classname(obj);
- VALUE str;
-
- str = rb_sprintf("#<%s:%p>", cname, (void*)obj);
- if (OBJ_TAINTED(obj)) OBJ_TAINT(str);
-
+ VALUE str = rb_sprintf("#<%s:%p>", cname, (void*)obj);
+ if (OBJ_TAINTED(obj)) {
+ OBJ_TAINT(str);
+ }
return str;
}
VALUE
rb_any_to_s(VALUE obj)
{
- return rb_any_to_string(obj, 0);
+ return rb_any_to_string(obj, 0);
}
VALUE
@@ -1789,8 +1788,9 @@
RCLASS_SET_VERSION(klass, v);
}
rb_objc_install_primitives((Class)klass, (Class)super);
- if (super == rb_cObject)
+ if (super == rb_cObject) {
rb_define_object_special_methods(klass);
+ }
rb_class_inherited(super, klass);
rb_mod_initialize(klass, 0);
Modified: MacRuby/trunk/proc.c
===================================================================
--- MacRuby/trunk/proc.c 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/proc.c 2009-08-22 19:05:28 UTC (rev 2357)
@@ -677,14 +677,17 @@
{
rb_vm_method_t *m1, *m2;
- if (CLASS_OF(method) != CLASS_OF(other))
+ if (CLASS_OF(method) != CLASS_OF(other)) {
return Qfalse;
+ }
Data_Get_Struct(method, rb_vm_method_t, m1);
Data_Get_Struct(other, rb_vm_method_t, m2);
- if (m1->oclass != m2->oclass || m1->rclass != m2->rclass ||
- m1->recv != m2->recv || m1->node != m2->node) {
+ if (m1->oclass != m2->oclass
+ || m1->rclass != m2->rclass
+ || m1->recv != m2->recv
+ || m1->node->objc_imp != m2->node->objc_imp) {
return Qfalse;
}
Modified: MacRuby/trunk/spec/frozen/language/def_spec.rb
===================================================================
--- MacRuby/trunk/spec/frozen/language/def_spec.rb 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/language/def_spec.rb 2009-08-22 19:05:28 UTC (rev 2357)
@@ -491,4 +491,4 @@
end
end
-language_version __FILE__, "def"
\ No newline at end of file
+language_version __FILE__, "def"
Modified: MacRuby/trunk/spec/frozen/library/date/conversions_spec.rb
===================================================================
--- MacRuby/trunk/spec/frozen/library/date/conversions_spec.rb 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/library/date/conversions_spec.rb 2009-08-22 19:05:28 UTC (rev 2357)
@@ -42,6 +42,11 @@
end
end
+# The following methods are private in 1.9's date.rb.
+# XXX should we write specs that test if they are private?
+# should we rewrite the specs using #send?
+ruby_version_is "" ... "1.9" do
+
describe "Date#ordinal_to_jd" do
it "should convert an ordinal date (year-day) to a Julian day number" do
Date.ordinal_to_jd(2007, 55).should == 2454156
@@ -150,4 +155,6 @@
it "should be able to convert a Julian day number into a week day number" do
Date.jd_to_wday(2454482).should == 3
end
-end
\ No newline at end of file
+end
+
+end # "" ... "1.9"
Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/array/initialize_copy_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/array/initialize_copy_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/array/initialize_copy_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,2 +1 @@
-fails:Array#initialize_copy is private
fails:Array#initialize_copy tries to convert the passed argument to an Array using #to_ary
Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/array/initialize_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/array/initialize_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/array/initialize_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,4 +1,3 @@
-fails:Array#initialize is private
fails:Array#initialize with (array) calls #to_ary to convert the value to an array
fails:Array#initialize with (size, object=nil) calls #to_int to convert the size argument to an Integer when object is given
fails:Array#initialize with (size, object=nil) calls #to_int to convert the size argument to an Integer when object is not given
Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/basicobject/method_missing_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/basicobject/method_missing_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/basicobject/method_missing_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,3 +1,2 @@
-fails:BasicObject#method_missing is a private method
fails:BasicObject#method_missing is called when a private method is called
fails:BasicObject#method_missing is called when a protected method is called
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/respond_to_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/respond_to_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/respond_to_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,2 +0,0 @@
-fails:Kernel#respond_to? returns false if the given method was undefined
-fails:Kernel#respond_to? returns true if obj responds to the given private method, include_private = true
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/singleton_method_added_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/singleton_method_added_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/singleton_method_added_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Kernel#singleton_method_added is a private method
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/singleton_method_removed_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/singleton_method_removed_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/singleton_method_removed_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Kernel#singleton_method_removed is a private method
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/singleton_method_undefined_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/singleton_method_undefined_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/singleton_method_undefined_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Kernel#singleton_method_undefined is a private method
Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/module/alias_method_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/module/alias_method_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/module/alias_method_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,3 +1,2 @@
fails:Module#alias_method retains method visibility
-fails:Module#alias_method is a private method
fails:Module#alias_method converts a non string/symbol/fixnum name to string using to_str
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/module/extended_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/module/extended_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/module/extended_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Module#extended is private in its default implementation
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/module/included_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/module/included_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/module/included_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Module#included is private in its default implementation
Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/module/method_added_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/module/method_added_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/module/method_added_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,2 +1 @@
-fails:Module#method_added is a private instance method
fails:Module#method_added is called when a new method is defined in self
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_class_method_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_class_method_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_class_method_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,6 +0,0 @@
-fails:Module#private_class_method makes an existing class method private
-fails:Module#private_class_method makes an existing class method private up the inheritance tree
-fails:Module#private_class_method accepts more than one method at a time
-fails:Module#private_class_method makes a class method private
-fails:Module#private_class_method raises a NameError when the given name is an instance method
-fails:Module#private_class_method raises a NameError when the given name is not a method
\ No newline at end of file
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_instance_methods_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_instance_methods_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_instance_methods_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Module#private_instance_methods returns a list of private methods in module and its ancestors
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_method_defined_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_method_defined_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_method_defined_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,4 +0,0 @@
-fails:Module#private_method_defined? returns true if the named private method is defined by module or its ancestors
-fails:Module#private_method_defined? accepts symbols for the method name
-fails:Module#private_method_defined? raises an ArgumentError if passed a Fixnum
-fails:Module#private_method_defined? calls #to_str to coerce the passed object to a String
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Module#private should make the target method uncallable from other types
Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/module/remove_const_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/module/remove_const_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/module/remove_const_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,5 +1,4 @@
fails:Module#remove_const removes the constant specified by a String or Symbol from the receiver's constant table
fails:Module#remove_const raises a NameError if the constant is not defined directly in the module
-fails:Module#remove_const is a private method
fails:Module#remove_const calls #to_str to convert the given name to a String
fails:Module#remove_const raises a TypeError if conversion to a String by calling #to_str fails
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/range/initialize_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/range/initialize_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/range/initialize_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Range#initialize is private
Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/string/initialize_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/string/initialize_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/string/initialize_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,6 +1,5 @@
critical:String#initialize raises TypeError on inconvertible object
critical:String#initialize converts its argument to a string representation
-fails:String#initialize is a private method
fails:String#initialize returns an instance of a subclass
fails:String#initialize is called on subclasses
fails:String#initialize raises a TypeError if self is frozen
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/struct/initialize_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/struct/initialize_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/struct/initialize_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Struct#initialize is private
Modified: MacRuby/trunk/spec/frozen/tags/macruby/language/def_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/language/def_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/language/def_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,4 +1,3 @@
-fails:Defining an 'initialize' method should make it private
fails:An instance method with a default argument evaluates the default when required arguments precede it
fails:An instance method with a default argument prefers to assign to a default argument before a splat argument
fails:Redefining a singleton method does not inherit a previously set visibility
@@ -7,4 +6,4 @@
fails:A method definition inside an instance_eval creates a class method when the receiver is a class
fails:A method definition in an eval creates an instance method
fails:A method definition in an eval creates a class method
-fails:A method definition in an eval creates a singleton method
\ No newline at end of file
+fails:A method definition in an eval creates a singleton method
Modified: MacRuby/trunk/spec/frozen/tags/macruby/language/method_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/language/method_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/language/method_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,2 +1 @@
critical:Calling a method allows any number of args beyond required to method with a splat
-fails:Calling a private getter method does not permit self as a receiver
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/language/private_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/language/private_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/language/private_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,5 +0,0 @@
-fails:The private keyword marks following methods as being private
-fails:The private keyword is overridden when a new class is opened
-fails:The private keyword changes visibility of previously called method
-fails:The private keyword changes the visibility of the existing method in the subclass
-fails:The private keyword changes visiblity of previously called methods with same send/call site
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/initialize_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/initialize_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/matrix/initialize_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Matrix#initialize is private
Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/net/ftp/initialize_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/net/ftp/initialize_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/net/ftp/initialize_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1,2 +1 @@
-fails:Net::FTP#initialize is private
fails:Net::FTP#initialize sets self into binary mode
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/library/net/http/http/initialize_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/net/http/http/initialize_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/net/http/http/initialize_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Net::HTTP#initialize is private
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/library/set/initialize_copy_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/set/initialize_copy_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/set/initialize_copy_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Set#initialize_copy is private
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/library/set/initialize_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/set/initialize_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/set/initialize_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:Set#initialize is private
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/library/set/sortedset/initialize_copy_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/set/sortedset/initialize_copy_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/set/sortedset/initialize_copy_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:SortedSet#initialize_copy is private
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/library/set/sortedset/initialize_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/set/sortedset/initialize_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/set/sortedset/initialize_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:SortedSet#initialize is private
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/library/stringio/initialize_copy_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/stringio/initialize_copy_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/stringio/initialize_copy_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:StringIO#initialize_copy is private
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/library/stringscanner/initialize_copy_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/stringscanner/initialize_copy_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/stringscanner/initialize_copy_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:StringScanner#initialize_copy is a private method
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/library/stringscanner/initialize_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/stringscanner/initialize_tags.txt 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/stringscanner/initialize_tags.txt 2009-08-22 19:05:28 UTC (rev 2357)
@@ -1 +0,0 @@
-fails:StringScanner#initialize is a private method
Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/vm.cpp 2009-08-22 19:05:28 UTC (rev 2357)
@@ -179,7 +179,7 @@
#define VALUE_TO_GV(v) (value2gv((VALUE)v))
extern "C" void *__cxa_allocate_exception(size_t);
-extern "C" void __cxa_throw(void *, void *, void (*)(void*));
+extern "C" void __cxa_throw(void *, void *, void (*)(void *));
RoxorCore::RoxorCore(void)
{
@@ -472,7 +472,6 @@
return GET_CORE()->constant_cache_get(rb_intern(name));
}
-
struct mcache *
RoxorCore::method_cache_get(SEL sel, bool super)
{
@@ -503,15 +502,31 @@
RoxorCore::method_node_get(IMP imp)
{
std::map<IMP, rb_vm_method_node_t *>::iterator iter = ruby_imps.find(imp);
- rb_vm_method_node_t *m = iter == ruby_imps.end() ? NULL : iter->second;
- return m;
+ return iter == ruby_imps.end() ? NULL : iter->second;
}
+inline rb_vm_method_node_t *
+RoxorCore::method_node_get(Method m, bool create)
+{
+ std::map<Method, rb_vm_method_node_t *>::iterator iter =
+ ruby_methods.find(m);
+ if (iter == ruby_methods.end()) {
+ if (create) {
+ rb_vm_method_node_t *n =
+ (rb_vm_method_node_t *)malloc(sizeof(rb_vm_method_node_t));
+ ruby_methods[m] = n;
+ return n;
+ }
+ return NULL;
+ }
+ return iter->second;
+}
+
extern "C"
-rb_vm_method_node_t *
-rb_vm_get_method_node(IMP imp)
+bool
+rb_vm_is_ruby_method(Method m)
{
- return GET_CORE()->method_node_get(imp);
+ return GET_CORE()->method_node_get(m) != NULL;
}
size_t
@@ -597,28 +612,47 @@
RoxorCore::add_method(Class klass, SEL sel, IMP imp, IMP ruby_imp,
const rb_vm_arity_t &arity, int flags, const char *types)
{
+ // #initialize and #initialize_copy are always private.
+ if (sel == selInitialize || sel == selInitialize2
+ || sel == selInitializeCopy) {
+ flags |= VM_METHOD_PRIVATE;
+ }
+
#if ROXOR_VM_DEBUG
- printf("defining %c[%s %s] with imp %p types %s\n",
+ printf("defining %c[%s %s] with imp %p/%p types %s flags %d\n",
class_isMetaClass(klass) ? '+' : '-',
class_getName(klass),
sel_getName(sel),
imp,
- types);
+ ruby_imp,
+ types,
+ flags);
#endif
// Register the implementation into the runtime.
class_replaceMethod(klass, sel, imp, types);
- // Cache the method node.
- std::map<IMP, rb_vm_method_node_t *>::iterator iter = ruby_imps.find(imp);
+ // Cache the method.
+ Method m = class_getInstanceMethod(klass, sel);
+ assert(m != NULL);
+ assert(method_getImplementation(m) == imp);
+ rb_vm_method_node_t *real_node = method_node_get(m, true);
+ real_node->objc_imp = imp;
+ real_node->ruby_imp = ruby_imp;
+ real_node->arity = arity;
+ real_node->flags = flags;
+ real_node->sel = sel;
+
+ // Cache the implementation.
+ std::map<IMP, rb_vm_method_node_t *>::iterator iter2 = ruby_imps.find(imp);
rb_vm_method_node_t *node;
- if (iter == ruby_imps.end()) {
+ if (iter2 == ruby_imps.end()) {
node = (rb_vm_method_node_t *)malloc(sizeof(rb_vm_method_node_t));
+ node->objc_imp = imp;
ruby_imps[imp] = node;
- node->objc_imp = imp;
}
else {
- node = iter->second;
+ node = iter2->second;
assert(node->objc_imp == imp);
}
node->arity = arity;
@@ -630,9 +664,9 @@
}
// Invalidate dispatch cache.
- std::map<SEL, struct mcache *>::iterator iter2 = mcache.find(sel);
- if (iter2 != mcache.end()) {
- iter2->second->flag = 0;
+ std::map<SEL, struct mcache *>::iterator iter3 = mcache.find(sel);
+ if (iter3 != mcache.end()) {
+ iter3->second->flag = 0;
}
// Invalidate inline operations.
@@ -678,7 +712,6 @@
int i, count = RARRAY_LEN(included_in_classes);
for (i = 0; i < count; i++) {
VALUE mod = RARRAY_AT(included_in_classes, i);
- class_replaceMethod((Class)mod, sel, imp, types);
#if ROXOR_VM_DEBUG
printf("forward %c[%s %s] with imp %p node %p types %s\n",
class_isMetaClass((Class)mod) ? '+' : '-',
@@ -688,11 +721,22 @@
node,
types);
#endif
+ class_replaceMethod((Class)mod, sel, imp, types);
+
+ Method m = class_getInstanceMethod((Class)mod, sel);
+ assert(m != NULL);
+ assert(method_getImplementation(m) == imp);
+ node = method_node_get(m, true);
+ node->objc_imp = imp;
+ node->ruby_imp = ruby_imp;
+ node->arity = arity;
+ node->flags = flags;
+ node->sel = sel;
}
}
}
- return node;
+ return real_node;
}
void
@@ -1085,9 +1129,10 @@
IMP imp = method_getImplementation(method);
const char *types = method_getTypeEncoding(method);
- rb_vm_method_node_t *node = GET_CORE()->method_node_get(imp);
+ rb_vm_method_node_t *node = GET_CORE()->method_node_get(method);
if (node == NULL) {
- rb_raise(rb_eArgError, "cannot alias non-Ruby method `%s'",
+ rb_raise(rb_eArgError,
+ "only pure Ruby methods can be aliased (`%s' is not)",
sel_getName(method_getName(method)));
}
@@ -1144,13 +1189,13 @@
extern "C"
void
-rb_vm_undef(VALUE klass, ID name)
+rb_vm_undef(VALUE klass, VALUE name)
{
Class k = GET_VM()->get_current_class();
if (k != NULL) {
klass = (VALUE)k;
}
- rb_undef(klass, name);
+ rb_vm_undef_method((Class)klass, rb_to_id(name), true);
}
extern "C"
@@ -1283,14 +1328,17 @@
const rb_vm_arity_t &arity, int flags, IMP imp, Method m)
{
if (imp == NULL) {
+ // Compile if necessary.
assert(func != NULL);
imp = compile(func);
}
+ // Resolve Objective-C signature.
const int oc_arity = arity.real + 3;
char types[100];
resolve_method_type(types, sizeof types, klass, m, sel, oc_arity);
+ // Generate Objective-C stub if needed.
std::map<IMP, IMP>::iterator iter = objc_to_ruby_stubs.find(imp);
IMP objc_imp;
if (iter == objc_to_ruby_stubs.end()) {
@@ -1303,6 +1351,21 @@
objc_imp = iter->second;
}
+ // Delete the selector from the not-yet-JIT'ed cache if needed.
+ std::multimap<Class, SEL>::iterator iter2, last2;
+ iter2 = method_source_sels.find(klass);
+ if (iter2 != method_source_sels.end()) {
+ last2 = method_source_sels.upper_bound(klass);
+ while (iter2 != last2) {
+ if (iter2->second == sel) {
+ method_source_sels.erase(iter2);
+ break;
+ }
+ ++iter2;
+ }
+ }
+
+ // Finally, add the method.
return add_method(klass, sel, objc_imp, imp, arity, flags, types);
}
@@ -1380,11 +1443,13 @@
const rb_vm_arity_t &arity, int flags)
{
#if ROXOR_VM_DEBUG
- printf("preparing %c[%s %s] with LLVM func %p\n",
+ printf("preparing %c[%s %s] on class %p LLVM func %p flags %d\n",
class_isMetaClass(klass) ? '+' : '-',
class_getName(klass),
sel_getName(sel),
- func);
+ klass,
+ func,
+ flags);
#endif
std::map<Class, rb_vm_method_source_t *> *map =
@@ -1408,18 +1473,33 @@
}
static void
-prepare_method(Class klass, SEL sel, void *data,
+prepare_method(Class klass, bool singleton, SEL sel, void *data,
const rb_vm_arity_t &arity, int flags, bool precompiled)
{
- Class k = GET_VM()->get_current_class();
- if (k != NULL) {
- const bool meta = class_isMetaClass(klass);
- klass = k;
- if (meta) {
- klass = *(Class *)klass;
+ if (!singleton) {
+ Class k = GET_VM()->get_current_class();
+ if (k != NULL) {
+ const bool meta = class_isMetaClass(klass);
+ klass = k;
+ if (meta) {
+ klass = *(Class *)klass;
+ }
}
}
+ const long v = RCLASS_VERSION(klass);
+ if (v & RCLASS_SCOPE_PRIVATE) {
+ flags |= VM_METHOD_PRIVATE;
+ }
+ else if (v & RCLASS_SCOPE_PROTECTED) {
+ flags |= VM_METHOD_PROTECTED;
+ }
+
+ if (sel == sel_ignored) {
+ // TODO
+ return;
+ }
+
const char *sel_name = sel_getName(sel);
const bool genuine_selector = sel_name[strlen(sel_name) - 1] == ':';
bool redefined = false;
@@ -1476,8 +1556,10 @@
int i, count = RARRAY_LEN(included_in_classes);
for (i = 0; i < count; i++) {
VALUE mod = RARRAY_AT(included_in_classes, i);
- prepare_method((Class)mod, orig_sel, data, arity, flags,
+ rb_vm_set_current_scope(mod, SCOPE_PUBLIC);
+ prepare_method((Class)mod, false, orig_sel, data, arity, flags,
precompiled);
+ rb_vm_set_current_scope(mod, SCOPE_DEFAULT);
}
}
}
@@ -1485,29 +1567,29 @@
extern "C"
void
-rb_vm_prepare_method(Class klass, SEL sel, Function *func,
+rb_vm_prepare_method(Class klass, bool singleton, SEL sel, Function *func,
const rb_vm_arity_t arity, int flags)
{
- prepare_method(klass, sel, (void *)func, arity, flags, false);
+ prepare_method(klass, singleton, sel, (void *)func, arity, flags, false);
}
extern "C"
void
-rb_vm_prepare_method2(Class klass, SEL sel, IMP ruby_imp,
+rb_vm_prepare_method2(Class klass, bool singleton, SEL sel, IMP ruby_imp,
const rb_vm_arity_t arity, int flags)
{
- prepare_method(klass, sel, (void *)ruby_imp, arity, flags, true);
+ prepare_method(klass, singleton, sel, (void *)ruby_imp, arity, flags, true);
}
-static void __rb_vm_define_method(Class klass, SEL sel, IMP objc_imp,
- IMP ruby_imp, const rb_vm_arity_t &arity, int flags, bool direct);
+static rb_vm_method_node_t * __rb_vm_define_method(Class klass, SEL sel,
+ IMP objc_imp, IMP ruby_imp, const rb_vm_arity_t &arity, int flags,
+ bool direct);
#define VISI(x) ((x)&NOEX_MASK)
#define VISI_CHECK(x,f) (VISI(x) == (f))
static void
-push_method(VALUE ary, SEL sel, rb_vm_method_node_t *node,
- int (*filter) (VALUE, ID, VALUE))
+push_method(VALUE ary, SEL sel, int flags, int (*filter) (VALUE, ID, VALUE))
{
if (sel == sel_ignored) {
return;
@@ -1530,16 +1612,33 @@
VALUE sym = ID2SYM(mid);
if (rb_ary_includes(ary, sym) == Qfalse) {
- if (node != NULL) {
- const int type = rb_vm_method_node_noex(node);
- (*filter)(sym, type, ary);
+ int type = NOEX_PUBLIC;
+ if (flags & VM_METHOD_PRIVATE) {
+ type = NOEX_PRIVATE;
}
- else {
- rb_ary_push(ary, sym);
+ else if (flags & VM_METHOD_PROTECTED) {
+ type = NOEX_PROTECTED;
}
+ (*filter)(sym, type, ary);
}
}
+rb_vm_method_source_t *
+RoxorCore::method_source_get(Class klass, SEL sel)
+{
+ std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>::iterator iter
+ = method_sources.find(sel);
+ if (iter != method_sources.end()) {
+ std::map<Class, rb_vm_method_source_t *> *m = iter->second;
+ std::map<Class, rb_vm_method_source_t *>::iterator iter2
+ = m->find(klass);
+ if (iter2 != m->end()) {
+ return iter2->second;
+ }
+ }
+ return NULL;
+}
+
void
RoxorCore::get_methods(VALUE ary, Class klass, bool include_objc_methods,
int (*filter) (VALUE, ID, VALUE))
@@ -1551,13 +1650,12 @@
if (methods != NULL) {
for (unsigned int i = 0; i < count; i++) {
Method m = methods[i];
- SEL sel = method_getName(m);
- IMP imp = method_getImplementation(m);
- rb_vm_method_node_t *node = rb_vm_get_method_node(imp);
+ rb_vm_method_node_t *node = method_node_get(m);
if (node == NULL && !include_objc_methods) {
continue;
}
- push_method(ary, sel, node, filter);
+ SEL sel = method_getName(m);
+ push_method(ary, sel, node == NULL ? 0 : node->flags, filter);
}
free(methods);
}
@@ -1573,8 +1671,9 @@
for (; iter != last; ++iter) {
SEL sel = iter->second;
- // TODO retrieve method NODE*
- push_method(ary, sel, NULL, filter);
+ rb_vm_method_source_t *src = method_source_get(k, sel);
+ assert(src != NULL);
+ push_method(ary, sel, src->flags, filter);
}
}
@@ -1628,8 +1727,13 @@
methods = class_copyMethodList(from_class, &methods_count);
if (methods != NULL) {
for (i = 0; i < methods_count; i++) {
- Method method = methods[i];
- SEL sel = method_getName(method);
+ Method m = methods[i];
+ rb_vm_method_node_t *node = method_node_get(m);
+ if (node == NULL) {
+ // Only copy pure-Ruby methods.
+ continue;
+ }
+ SEL sel = method_getName(m);
#if ROXOR_VM_DEBUG
printf("copy %c[%s %s] to %s\n",
@@ -1641,9 +1745,15 @@
class_replaceMethod(to_class,
sel,
- method_getImplementation(method),
- method_getTypeEncoding(method));
+ method_getImplementation(m),
+ method_getTypeEncoding(m));
+ Method m2 = class_getInstanceMethod(to_class, sel);
+ assert(m2 != NULL);
+ assert(method_getImplementation(m2) == method_getImplementation(m));
+ rb_vm_method_node_t *node2 = method_node_get(m2, true);
+ memcpy(node2, node, sizeof(rb_vm_method_node_t));
+
std::map<Class, rb_vm_method_source_t *> *map =
method_sources_for_sel(sel, false);
if (map != NULL) {
@@ -1740,15 +1850,14 @@
*pimp = imp;
}
if (pnode != NULL) {
- *pnode = GET_CORE()->method_node_get(imp);
+ *pnode = GET_CORE()->method_node_get(m);
}
return true;
}
extern "C"
void
-rb_vm_define_attr(Class klass, const char *name, bool read, bool write,
- int noex)
+rb_vm_define_attr(Class klass, const char *name, bool read, bool write)
{
assert(klass != NULL);
assert(read || write);
@@ -1760,27 +1869,35 @@
if (read) {
Function *f = RoxorCompiler::shared->compile_read_attr(iname);
SEL sel = sel_registerName(name);
- rb_vm_prepare_method(klass, sel, f, rb_vm_arity(0), NODE_FBODY);
+ rb_vm_prepare_method(klass, false, sel, f, rb_vm_arity(0),
+ VM_METHOD_FBODY);
}
if (write) {
Function *f = RoxorCompiler::shared->compile_write_attr(iname);
snprintf(buf, sizeof buf, "%s=:", name);
SEL sel = sel_registerName(buf);
- rb_vm_prepare_method(klass, sel, f, rb_vm_arity(1), NODE_FBODY);
+ rb_vm_prepare_method(klass, false, sel, f, rb_vm_arity(1),
+ VM_METHOD_FBODY);
}
}
-static void
+static rb_vm_method_node_t *
__rb_vm_define_method(Class klass, SEL sel, IMP objc_imp, IMP ruby_imp,
const rb_vm_arity_t &arity, int flags, bool direct)
{
assert(klass != NULL);
+ if (sel == sel_ignored) {
+ // TODO
+ return NULL;
+ }
+
const char *sel_name = sel_getName(sel);
const bool genuine_selector = sel_name[strlen(sel_name) - 1] == ':';
int oc_arity = genuine_selector ? arity.real : 0;
bool redefined = direct;
+ rb_vm_method_node_t *node;
define_method:
Method method = class_getInstanceMethod(klass, sel);
@@ -1788,7 +1905,8 @@
char types[100];
resolve_method_type(types, sizeof types, klass, method, sel, oc_arity);
- GET_CORE()->add_method(klass, sel, objc_imp, ruby_imp, arity, flags, types);
+ node = GET_CORE()->add_method(klass, sel, objc_imp, ruby_imp, arity,
+ flags, types);
if (!redefined) {
if (!genuine_selector && arity.max != arity.min) {
@@ -1811,28 +1929,34 @@
goto define_method;
}
}
+
+ return node;
}
extern "C"
-void
+rb_vm_method_node_t *
rb_vm_define_method(Class klass, SEL sel, IMP imp, NODE *node, bool direct)
{
assert(node != NULL);
// TODO: create objc_imp
- __rb_vm_define_method(klass, sel, imp, imp, rb_vm_node_arity(node),
+ return __rb_vm_define_method(klass, sel, imp, imp, rb_vm_node_arity(node),
rb_vm_node_flags(node), direct);
}
extern "C"
-void
+rb_vm_method_node_t *
rb_vm_define_method2(Class klass, SEL sel, rb_vm_method_node_t *node,
- bool direct)
+ bool direct)
{
assert(node != NULL);
- __rb_vm_define_method(klass, sel, node->objc_imp, node->ruby_imp,
- node->arity, node->flags, direct);
+ long flags = node->flags;
+ flags &= ~VM_METHOD_PRIVATE;
+ flags &= ~VM_METHOD_PROTECTED;
+
+ return __rb_vm_define_method(klass, sel, node->objc_imp, node->ruby_imp,
+ node->arity, flags, direct);
}
extern "C"
@@ -1850,38 +1974,77 @@
rb_vm_define_method(klass, sel, imp, body, false);
}
+static VALUE method_missing(VALUE obj, SEL sel, int argc, const VALUE *argv,
+ rb_vm_method_missing_reason_t call_status);
+
+static void *
+undefined_imp(void *rcv, SEL sel)
+{
+ method_missing((VALUE)rcv, sel, NULL, NULL, METHOD_MISSING_DEFAULT);
+ return NULL; // never reached
+}
+
+#define UNDEFINED_IMP(imp) (imp == NULL || imp == (IMP)undefined_imp)
+
+void
+RoxorCore::undef_method(Class klass, SEL sel)
+{
+#if ROXOR_VM_DEBUG
+ printf("undef %c[%s %s]\n",
+ class_isMetaClass(klass) ? '+' : '-',
+ class_getName(klass),
+ sel_getName(sel));
+#endif
+
+ class_replaceMethod((Class)klass, sel, (IMP)undefined_imp, "@@:");
+
+#if 0
+ std::map<Method, rb_vm_method_node_t *>::iterator iter
+ = ruby_methods.find(m);
+ assert(iter != ruby_methods.end());
+ free(iter->second);
+ ruby_methods.erase(iter);
+#endif
+
+#if 0
+ // TODO call undefined
+ if (RCLASS_SINGLETON(klass)) {
+ rb_funcall(rb_iv_get(klass, "__attached__"),
+ singleton_undefined, 1, ID2SYM(id));
+ }
+ else {
+ rb_funcall(klass, undefined, 1, ID2SYM(id));
+ }
+#endif
+}
+
extern "C"
void
-rb_vm_undef_method(Class klass, const char *name, bool must_exist)
+rb_vm_undef_method(Class klass, ID name, bool must_exist)
{
rb_vm_method_node_t *node = NULL;
- if (!rb_vm_lookup_method2((Class)klass, rb_intern(name), NULL, NULL,
- &node)) {
+ if (!rb_vm_lookup_method2((Class)klass, name, NULL, NULL, &node)) {
if (must_exist) {
rb_raise(rb_eNameError, "undefined method `%s' for %s `%s'",
- name,
+ rb_id2name(name),
TYPE(klass) == T_MODULE ? "module" : "class",
rb_class2name((VALUE)klass));
}
- assert(name[strlen(name) - 1] != ':');
- SEL sel = sel_registerName(name);
- class_replaceMethod((Class)klass, sel, NULL, "@@:");
+ const char *namestr = rb_id2name(name);
+ SEL sel = sel_registerName(namestr);
+ GET_CORE()->undef_method(klass, sel);
}
-
- if (node == NULL) {
+ else if (node == NULL) {
if (must_exist) {
rb_raise(rb_eRuntimeError,
"cannot undefine method `%s' because it is a native method",
- name);
+ rb_id2name(name));
}
- return; // Do nothing.
}
-
- Method m = class_getInstanceMethod((Class)klass, node->sel);
- assert(m != NULL);
- class_replaceMethod((Class)klass, node->sel, NULL,
- method_getTypeEncoding(m));
+ else {
+ GET_CORE()->undef_method(klass, node->sel);
+ }
}
extern "C"
@@ -2157,41 +2320,48 @@
rb_raise(rb_eArgError, "no id given");
}
- const unsigned char last_call_status =
+ const rb_vm_method_missing_reason_t last_call_status =
GET_VM()->get_method_missing_reason();
const char *format = NULL;
VALUE exc = rb_eNoMethodError;
switch (last_call_status) {
-#if 0 // TODO
- case NOEX_PRIVATE:
+ case METHOD_MISSING_PRIVATE:
format = "private method `%s' called for %s";
break;
- case NOEX_PROTECTED:
+ case METHOD_MISSING_PROTECTED:
format = "protected method `%s' called for %s";
break;
-#endif
- case DISPATCH_VCALL:
+ case METHOD_MISSING_VCALL:
format = "undefined local variable or method `%s' for %s";
exc = rb_eNameError;
break;
- case DISPATCH_SUPER:
+ case METHOD_MISSING_SUPER:
format = "super: no superclass method `%s' for %s";
break;
+ case METHOD_MISSING_DEFAULT:
default:
format = "undefined method `%s' for %s";
break;
}
+ VALUE meth = rb_sym_to_s(argv[0]);
+ if (!rb_vm_respond_to(obj, selToS, true)) {
+ // In case #to_s was undefined on the object, let's generate a
+ // basic string based on it, because otherwise the following code
+ // will raise a #method_missing which will result in an infinite loop.
+ obj = rb_any_to_s(obj);
+ }
+
int n = 0;
VALUE args[3];
- args[n++] = rb_funcall(rb_cNameErrorMesg, '!', 3, rb_str_new2(format), obj,
- argv[0]);
- args[n++] = argv[0];
+ args[n++] = rb_funcall(rb_cNameErrorMesg, '!', 3, rb_str_new2(format),
+ obj, meth);
+ args[n++] = meth;
if (exc == rb_eNoMethodError) {
args[n++] = rb_ary_new4(argc - 1, argv + 1);
}
@@ -2204,7 +2374,7 @@
static VALUE
method_missing(VALUE obj, SEL sel, int argc, const VALUE *argv,
- unsigned char call_status)
+ rb_vm_method_missing_reason_t call_status)
{
GET_VM()->set_method_missing_reason(call_status);
@@ -2326,7 +2496,7 @@
static force_inline VALUE
__rb_vm_ruby_dispatch(VALUE self, SEL sel, rb_vm_method_node_t *node,
- int argc, const VALUE *argv)
+ unsigned char opt, int argc, const VALUE *argv)
{
const rb_vm_arity_t &arity = node->arity;
if ((argc < arity.min) || ((arity.max != -1) && (argc > arity.max))) {
@@ -2334,11 +2504,18 @@
argc, arity.min);
}
- if (rb_vm_method_node_empty(node) && arity.max == arity.min) {
+ if ((node->flags & VM_METHOD_PRIVATE) && opt == 0) {
+ // Calling a private method with no explicit receiver OR an attribute
+ // assignment to non-self, triggering #method_missing.
+ method_missing(self, sel, argc, argv, METHOD_MISSING_PRIVATE);
+ }
+
+ if ((node->flags & VM_METHOD_EMPTY) && arity.max == arity.min) {
// Calling an empty method, let's just return nil!
return Qnil;
}
- if (rb_vm_method_node_type(node) == NODE_FBODY && arity.max != arity.min) {
+
+ if ((node->flags & VM_METHOD_FBODY) && arity.max != arity.min) {
// Calling a function defined with rb_objc_define_method with
// a negative arity, which means a different calling convention.
if (arity.real == 2) {
@@ -2360,7 +2537,8 @@
}
static force_inline void
-fill_rcache(struct mcache *cache, Class klass, rb_vm_method_node_t *node)
+fill_rcache(struct mcache *cache, Class klass, SEL sel,
+ rb_vm_method_node_t *node)
{
cache->flag = MCACHE_RCALL;
rcache.klass = klass;
@@ -2446,16 +2624,16 @@
recache2:
IMP imp = method_getImplementation(method);
- if (imp == NULL) {
+ if (UNDEFINED_IMP(imp)) {
// Method was undefined.
goto call_method_missing;
}
- rb_vm_method_node_t *node = GET_CORE()->method_node_get(imp);
+ rb_vm_method_node_t *node = GET_CORE()->method_node_get(method);
if (node != NULL) {
// ruby call
- fill_rcache(cache, klass, node);
+ fill_rcache(cache, klass, sel, node);
}
else {
// objc call
@@ -2523,8 +2701,7 @@
if (new_sel != NULL) {
Method m = class_getInstanceMethod(klass, new_sel);
if (m != NULL) {
- IMP imp = method_getImplementation(m);
- if (rb_vm_get_method_node(imp) == NULL) {
+ if (GET_CORE()->method_node_get(m) == NULL) {
sel = new_sel;
method = m;
goto recache2;
@@ -2596,7 +2773,7 @@
}
} finalizer(block_already_current, vm);
- return __rb_vm_ruby_dispatch(self, sel, rcache.node, argc, argv);
+ return __rb_vm_ruby_dispatch(self, sel, rcache.node, opt, argc, argv);
}
else if (cache->flag == MCACHE_OCALL) {
if (ocache.klass != klass) {
@@ -2723,14 +2900,17 @@
if (new_sel != 0) {
Method m = class_getInstanceMethod(klass, new_sel);
if (m != NULL
- && GET_CORE()->method_node_get(method_getImplementation(m))
- != NULL) {
+ && GET_CORE()->method_node_get(m) != NULL) {
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
argc, argc_expected);
}
}
- return method_missing((VALUE)self, sel, argc, argv, opt);
+ rb_vm_method_missing_reason_t status =
+ opt == DISPATCH_VCALL
+ ? METHOD_MISSING_VCALL : opt == DISPATCH_SUPER
+ ? METHOD_MISSING_SUPER : METHOD_MISSING_DEFAULT;
+ return method_missing((VALUE)self, sel, argc, argv, status);
}
#define MAX_DISPATCH_ARGS 200
@@ -3441,17 +3621,17 @@
rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *argv, bool super)
{
struct mcache *cache;
- unsigned char flg = 0;
+ unsigned char opt = DISPATCH_FCALL;
if (super) {
cache = (struct mcache *)alloca(sizeof(struct mcache));
cache->flag = 0;
- flg = DISPATCH_SUPER;
+ opt = DISPATCH_SUPER;
}
else {
cache = GET_CORE()->method_cache_get(sel, false);
}
- return __rb_vm_dispatch(GET_VM(), cache, self, NULL, sel, NULL, flg, argc,
+ return __rb_vm_dispatch(GET_VM(), cache, self, NULL, sel, NULL, opt, argc,
argv);
}
@@ -3461,7 +3641,7 @@
const VALUE *argv)
{
return __rb_vm_dispatch(GET_VM(), (struct mcache *)cache, self, NULL, sel,
- NULL, 0, argc, argv);
+ NULL, DISPATCH_FCALL, argc, argv);
}
extern "C"
@@ -3470,8 +3650,7 @@
VALUE klass, SEL sel, int argc, const VALUE *argv)
{
return __rb_vm_dispatch(GET_VM(), (struct mcache *)cache, self,
- (Class)klass, sel,
- block, 0, argc, argv);
+ (Class)klass, sel, block, DISPATCH_FCALL, argc, argv);
}
extern "C"
@@ -3551,14 +3730,18 @@
assert(method != NULL);
int arity;
+ rb_vm_method_node_t *new_node;
if (node == NULL) {
arity = method_getNumberOfArguments(method) - 2;
+ new_node = NULL;
}
else {
arity = node->arity.min;
if (node->arity.min != node->arity.max) {
arity = -arity - 1;
}
+ new_node = (rb_vm_method_node_t *)xmalloc(sizeof(rb_vm_method_node_t));
+ memcpy(new_node, node, sizeof(rb_vm_method_node_t));
}
rb_vm_method_t *m = (rb_vm_method_t *)xmalloc(sizeof(rb_vm_method_t));
@@ -3568,18 +3751,16 @@
GC_WB(&m->recv, obj);
m->sel = sel;
m->arity = arity;
- m->node = node;
+ GC_WB(&m->node, new_node);
// Let's allocate a static cache here, since a rb_vm_method_t must always
// point to the method it was created from.
struct mcache *c = (struct mcache *)xmalloc(sizeof(struct mcache));
- if (node == NULL) {
+ if (new_node == NULL) {
fill_ocache(c, obj, oklass, imp, sel, method, arity);
}
else {
- rb_vm_method_node_t *node = GET_CORE()->method_node_get(imp);
- assert(node != NULL);
- fill_rcache(c, oklass, node);
+ fill_rcache(c, oklass, sel, new_node);
}
GC_WB(&m->cache, c);
@@ -3856,16 +4037,10 @@
extern "C" id _objc_msgForward(id receiver, SEL sel, ...);
#endif
+#if 0
static inline IMP
class_respond_to(Class klass, SEL sel)
{
-#if 0
- Method m = class_getInstanceMethod(klass, sel);
- if (m != NULL) {
- return method_getImplementation(m);
- }
- return NULL;
-#else
IMP imp = class_getMethodImplementation(klass, sel);
if (imp == _objc_msgForward) {
if (rb_vm_resolve_method(klass, sel)) {
@@ -3876,8 +4051,8 @@
}
}
return imp;
+}
#endif
-}
extern "C"
bool
@@ -3889,28 +4064,26 @@
selRespondTo);
if (respond_to_imp == basic_respond_to_imp) {
+ // FIXME: too slow!
bool reject_pure_ruby_methods = false;
- IMP imp = class_respond_to((Class)klass, sel);
- if (imp == NULL) {
+ Method m = class_getInstanceMethod((Class)klass, sel);
+ if (m == NULL) {
const char *selname = sel_getName(sel);
sel = helper_sel(selname, strlen(selname));
if (sel != NULL) {
- imp = class_respond_to((Class)klass, sel);
- if (imp == NULL) {
- return false;
- }
+ m = class_getInstanceMethod((Class)klass, sel);
reject_pure_ruby_methods = true;
}
}
- if (imp == NULL) {
+
+ if (m == NULL || UNDEFINED_IMP(method_getImplementation(m))) {
return false;
}
- rb_vm_method_node_t *node = GET_CORE()->method_node_get(imp);
+ rb_vm_method_node_t *node = GET_CORE()->method_node_get(m);
if (node != NULL
- && (reject_pure_ruby_methods
- || (priv == 0
- && (rb_vm_method_node_noex(node) & NOEX_PRIVATE)))) {
+ && (reject_pure_ruby_methods
+ || (!priv && (node->flags & VM_METHOD_PRIVATE)))) {
return false;
}
return true;
@@ -4968,6 +5141,76 @@
rb_thread_wait_for(time);
}
+extern "C"
+Class
+rb_vm_set_current_class(Class klass)
+{
+ RoxorVM *vm = GET_VM();
+ Class old = vm->get_current_class();
+ vm->set_current_class(klass);
+ return old;
+}
+
+extern "C"
+void
+rb_vm_set_current_scope(VALUE mod, rb_vm_scope_t scope)
+{
+ if (scope == SCOPE_DEFAULT) {
+ scope = mod == rb_cObject ? SCOPE_PRIVATE : SCOPE_PUBLIC;
+ }
+ long v = RCLASS_VERSION(mod);
+#if ROXOR_VM_DEBUG
+ const char *scope_name = NULL;
+#endif
+ switch (scope) {
+ case SCOPE_PUBLIC:
+#if ROXOR_VM_DEBUG
+ scope_name = "public";
+#endif
+ v &= ~RCLASS_SCOPE_PRIVATE;
+ v &= ~RCLASS_SCOPE_PROTECTED;
+ v &= ~RCLASS_SCOPE_MOD_FUNC;
+ break;
+
+ case SCOPE_PRIVATE:
+#if ROXOR_VM_DEBUG
+ scope_name = "private";
+#endif
+ v |= RCLASS_SCOPE_PRIVATE;
+ v &= ~RCLASS_SCOPE_PROTECTED;
+ v &= ~RCLASS_SCOPE_MOD_FUNC;
+ break;
+
+ case SCOPE_PROTECTED:
+#if ROXOR_VM_DEBUG
+ scope_name = "protected";
+#endif
+ v &= ~RCLASS_SCOPE_PRIVATE;
+ v |= RCLASS_SCOPE_PROTECTED;
+ v &= ~RCLASS_SCOPE_MOD_FUNC;
+ break;
+
+ case SCOPE_MODULE_FUNC:
+#if ROXOR_VM_DEBUG
+ scope_name = "module_func";
+#endif
+ v &= ~RCLASS_SCOPE_PRIVATE;
+ v &= ~RCLASS_SCOPE_PROTECTED;
+ v |= RCLASS_SCOPE_MOD_FUNC;
+ break;
+
+ case SCOPE_DEFAULT:
+ abort(); // handled earlier
+ }
+
+#if ROXOR_VM_DEBUG
+ printf("changing scope of %s (%p) to %s\n",
+ class_getName((Class)mod), (void *)mod, scope_name);
+#endif
+
+ RCLASS_SET_VERSION(mod, v);
+}
+
static VALUE
builtin_ostub1(IMP imp, id self, SEL sel, int argc, VALUE *argv)
{
@@ -5109,6 +5352,8 @@
VALUE top_self = rb_obj_alloc(rb_cTopLevel);
rb_objc_retain((void *)top_self);
GET_VM()->set_current_top_object(top_self);
+
+ rb_vm_set_current_scope(rb_cNSObject, SCOPE_PRIVATE);
}
extern "C"
Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/vm.h 2009-08-22 19:05:28 UTC (rev 2357)
@@ -55,9 +55,42 @@
rb_vm_local_t *locals;
} rb_vm_binding_t;
-#define VM_METHOD_EMPTY 1000
+#define VM_METHOD_EMPTY 1 // method has an empty body (compilation)
+#define VM_METHOD_PRIVATE 2 // method is private (runtime)
+#define VM_METHOD_PROTECTED 4 // method is protected (runtime)
+#define VM_METHOD_FBODY 8 // method has a MRI C prototype (compilation)
-typedef struct {
+static inline int
+rb_vm_noex_flag(const int noex)
+{
+ switch (noex) {
+ case NOEX_PRIVATE:
+ return VM_METHOD_PRIVATE;
+ case NOEX_PROTECTED:
+ return VM_METHOD_PROTECTED;
+ default:
+ case NOEX_PUBLIC:
+ return 0;
+ }
+}
+
+static inline int
+rb_vm_node_flags(NODE *node)
+{
+ int flags = 0;
+ if (nd_type(node) == NODE_FBODY) {
+ flags |= VM_METHOD_FBODY;
+ if (nd_type(node->nd_body) == NODE_METHOD) {
+ flags |= rb_vm_noex_flag(node->nd_body->nd_noex);
+ }
+ }
+ if (node->nd_body == NULL) {
+ flags |= VM_METHOD_EMPTY;
+ }
+ return flags;
+}
+
+typedef struct rb_vm_method_node {
rb_vm_arity_t arity;
SEL sel;
IMP objc_imp;
@@ -102,16 +135,16 @@
rb_vm_block_t *body;
int argc;
const VALUE *argv;
- void *vm; // a C++ instance of RoxorVM
+ void *vm; // a C++ instance of RoxorVM
VALUE value;
pthread_mutex_t sleep_mutex;
pthread_cond_t sleep_cond;
rb_vm_thread_status_t status;
bool in_cond_wait;
- VALUE locals; // a Hash object or Qnil
- VALUE exception; // killed-by exception or Qnil
- VALUE group; // always a ThreadGroup object
- VALUE mutexes; // an Array object or Qnil
+ VALUE locals; // a Hash object or Qnil
+ VALUE exception; // killed-by exception or Qnil
+ VALUE group; // always a ThreadGroup object
+ VALUE mutexes; // an Array object or Qnil
} rb_vm_thread_t;
typedef struct rb_vm_outer {
@@ -206,36 +239,6 @@
abort();
}
-static inline int
-rb_vm_node_flags(NODE *node)
-{
- int flags = nd_type(node);
- if (node->nd_body == NULL) {
- flags |= VM_METHOD_EMPTY;
- }
- return flags;
-}
-
-static inline int
-rb_vm_method_node_type(rb_vm_method_node_t *node)
-{
- return node->flags & VM_METHOD_EMPTY
- ? node->flags ^ VM_METHOD_EMPTY : node->flags;
-}
-
-static inline bool
-rb_vm_method_node_empty(rb_vm_method_node_t *node)
-{
- return node->flags & VM_METHOD_EMPTY;
-}
-
-static inline int
-rb_vm_method_node_noex(rb_vm_method_node_t *node)
-{
- // TODO
- return 0;
-}
-
static inline NODE *
rb_vm_cfunc_node_from_imp(Class klass, int arity, IMP imp, int noex)
{
@@ -265,15 +268,14 @@
rb_vm_method_node_t **pnode);
bool rb_vm_lookup_method2(Class klass, ID mid, SEL *psel, IMP *pimp,
rb_vm_method_node_t **pnode);
-rb_vm_method_node_t *rb_vm_get_method_node(IMP imp);
-void rb_vm_define_method(Class klass, SEL sel, IMP imp, NODE *node,
- bool direct);
-void rb_vm_define_method2(Class klass, SEL sel, rb_vm_method_node_t *node,
- bool direct);
+bool rb_vm_is_ruby_method(Method m);
+rb_vm_method_node_t *rb_vm_define_method(Class klass, SEL sel, IMP imp,
+ NODE *node, bool direct);
+rb_vm_method_node_t *rb_vm_define_method2(Class klass, SEL sel,
+ rb_vm_method_node_t *node, bool direct);
void rb_vm_define_method3(Class klass, SEL sel, rb_vm_block_t *node);
-void rb_vm_define_attr(Class klass, const char *name, bool read, bool write,
- int noex);
-void rb_vm_undef_method(Class klass, const char *name, bool must_exist);
+void rb_vm_define_attr(Class klass, const char *name, bool read, bool write);
+void rb_vm_undef_method(Class klass, ID name, bool must_exist);
void rb_vm_alias(VALUE klass, ID name, ID def);
void rb_vm_copy_methods(Class from_class, Class to_class);
VALUE rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *args, bool super);
@@ -415,6 +417,16 @@
void rb_vm_load_bridge_support(const char *path, const char *framework_path,
int options);
+typedef enum {
+ SCOPE_DEFAULT = 0, // public for everything but Object
+ SCOPE_PUBLIC,
+ SCOPE_PRIVATE,
+ SCOPE_PROTECTED,
+ SCOPE_MODULE_FUNC,
+} rb_vm_scope_t;
+
+void rb_vm_set_current_scope(VALUE mod, rb_vm_scope_t scope);
+
VALUE rb_iseq_compile(VALUE src, VALUE file, VALUE line);
VALUE rb_iseq_eval(VALUE iseq);
VALUE rb_iseq_new(NODE *node, VALUE filename);
@@ -528,8 +540,9 @@
// Cache to avoid compiling the same Function twice.
std::map<Function *, IMP> JITcache;
- // Cache to identify pure Ruby methods.
+ // Cache to identify pure Ruby implementations / methods.
std::map<IMP, rb_vm_method_node_t *> ruby_imps;
+ std::map<Method, rb_vm_method_node_t *> ruby_methods;
// Method and constant caches.
std::map<SEL, struct mcache *> mcache;
@@ -651,7 +664,10 @@
struct mcache *method_cache_get(SEL sel, bool super);
rb_vm_method_node_t *method_node_get(IMP imp);
+ rb_vm_method_node_t *method_node_get(Method m, bool create=false);
+ rb_vm_method_source_t *method_source_get(Class klass, SEL sel);
+
void prepare_method(Class klass, SEL sel, Function *func,
const rb_vm_arity_t &arity, int flag);
rb_vm_method_node_t *add_method(Class klass, SEL sel, IMP imp,
@@ -660,6 +676,7 @@
rb_vm_method_node_t *resolve_method(Class klass, SEL sel,
Function *func, const rb_vm_arity_t &arity, int flags,
IMP imp, Method m);
+ void undef_method(Class klass, SEL sel);
bool resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
Class klass, SEL sel);
void copy_methods(Class from_class, Class to_class);
@@ -717,6 +734,14 @@
#define GET_CORE() (RoxorCore::shared)
+typedef enum {
+ METHOD_MISSING_DEFAULT = 0,
+ METHOD_MISSING_PRIVATE,
+ METHOD_MISSING_PROTECTED,
+ METHOD_MISSING_VCALL,
+ METHOD_MISSING_SUPER
+} rb_vm_method_missing_reason_t;
+
// The VM class is instantiated per thread. There is always at least one
// instance. The VM class is purely thread-safe and concurrent, it does not
// acquire any lock, except when it calls the Core.
@@ -764,7 +789,7 @@
VALUE last_status;
VALUE errinfo;
int safe_level;
- unsigned char method_missing_reason;
+ rb_vm_method_missing_reason_t method_missing_reason;
bool parse_in_eval;
public:
@@ -780,7 +805,7 @@
ACCESSOR(last_status, VALUE);
ACCESSOR(errinfo, VALUE);
ACCESSOR(safe_level, int);
- ACCESSOR(method_missing_reason, unsigned char);
+ ACCESSOR(method_missing_reason, rb_vm_method_missing_reason_t);
ACCESSOR(parse_in_eval, bool);
std::string debug_blocks(void);
Modified: MacRuby/trunk/vm_eval.c
===================================================================
--- MacRuby/trunk/vm_eval.c 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/vm_eval.c 2009-08-22 19:05:28 UTC (rev 2357)
@@ -500,7 +500,7 @@
klass = 0;
}
else {
- klass = CLASS_OF(self);
+ klass = rb_singleton_class(self);
}
return specific_eval(argc, argv, klass, self);
}
Modified: MacRuby/trunk/vm_method.c
===================================================================
--- MacRuby/trunk/vm_method.c 2009-08-21 22:00:44 UTC (rev 2356)
+++ MacRuby/trunk/vm_method.c 2009-08-22 19:05:28 UTC (rev 2357)
@@ -143,7 +143,7 @@
rb_name_error(mid, "method `%s' not defined in %s",
rb_id2name(mid), rb_class2name(klass));
}
- if (rb_vm_get_method_node(method_getImplementation(m)) == NULL) {
+ if (!rb_vm_is_ruby_method(m)) {
rb_warn("removing pure Objective-C method `%s' may cause serious " \
"problem", rb_id2name(mid));
}
@@ -217,15 +217,35 @@
}
}
-#if 0 // TODO
- if (node->nd_noex != noex) {
- // TODO if the method exists on a super class, we should add a new method
- // with the correct noex that calls super
- assert(!rb_vm_lookup_method((Class)RCLASS_SUPER(klass), sel, NULL, NULL));
+ if (node == NULL) {
+ rb_raise(rb_eRuntimeError,
+ "can't change visibility of non Ruby method `%s'",
+ sel_getName(sel));
+ }
- node->nd_noex = noex;
+ VALUE sklass = RCLASS_SUPER(klass);
+ if (sklass != 0) {
+ Method m = class_getInstanceMethod((Class)sklass, sel);
+ if (m != NULL && method_getImplementation(m) == node->objc_imp) {
+ // The method actually exists on a superclass, we need to duplicate
+ // it to the current class then change its visibility.
+ node = rb_vm_define_method2((Class)klass, sel, node, false);
+ }
}
-#endif
+
+ switch (noex) {
+ case NOEX_PUBLIC:
+ node->flags |= 0;
+ break;
+
+ case NOEX_PRIVATE:
+ node->flags |= VM_METHOD_PRIVATE;
+ break;
+
+ case NOEX_PROTECTED:
+ node->flags |= VM_METHOD_PROTECTED;
+ break;
+ }
}
int
@@ -245,25 +265,14 @@
void
rb_attr(VALUE klass, ID id, int read, int write, int ex)
{
- const char *name;
- int noex;
-
- if (!ex) {
- noex = NOEX_PUBLIC;
- }
- else {
- // TODO honor current scope ex
- noex = NOEX_PUBLIC;
- }
-
if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
}
- name = rb_id2name(id);
- if (!name) {
+ const char *name = rb_id2name(id);
+ if (name == NULL) {
rb_raise(rb_eArgError, "argument needs to be symbol or string");
}
- rb_vm_define_attr((Class)klass, name, read, write, noex);
+ rb_vm_define_attr((Class)klass, name, read, write);
if (write) {
rb_objc_define_kvo_setter(klass, id);
}
@@ -272,59 +281,19 @@
void
rb_undef(VALUE klass, ID id)
{
- // TODO
-#if 0
- VALUE origin;
- NODE *body;
-
-#if 0 // TODO
- if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) {
+ if (klass == rb_cObject) {
rb_secure(4);
}
-#endif
if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
- rb_id2name(id));
+ rb_id2name(id));
}
rb_frozen_class_p(klass);
if (id == object_id || id == __send__ || id == idInitialize) {
rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
}
- /* TODO: warn if a very important method of NSObject is undefined
- * by default, pure objc methods are not exposed by introspections API
- */
- body = search_method(klass, id, &origin);
- if (!body || !body->nd_body) {
- const char *s0 = " class";
- VALUE c = klass;
- if (RCLASS_SINGLETON(c)) {
- VALUE obj = rb_iv_get(klass, "__attached__");
-
- switch (TYPE(obj)) {
- case T_MODULE:
- case T_CLASS:
- c = obj;
- s0 = "";
- }
- }
- else if (TYPE(c) == T_MODULE) {
- s0 = " module";
- }
- rb_name_error(id, "undefined method `%s' for%s `%s'",
- rb_id2name(id), s0, rb_class2name(c));
- }
-
- rb_add_method(klass, id, 0, NOEX_PUBLIC);
-
- if (RCLASS_SINGLETON(klass)) {
- rb_funcall(rb_iv_get(klass, "__attached__"),
- singleton_undefined, 1, ID2SYM(id));
- }
- else {
- rb_funcall(klass, undefined, 1, ID2SYM(id));
- }
-#endif
+ rb_vm_undef_method((Class)klass, id, true);
}
/*
@@ -373,8 +342,7 @@
static VALUE
rb_mod_undef_method(VALUE mod, SEL sel, int argc, VALUE *argv)
{
- int i;
- for (i = 0; i < argc; i++) {
+ for (int i = 0; i < argc; i++) {
rb_undef(mod, rb_to_id(argv[i]));
}
return mod;
@@ -441,19 +409,26 @@
*/
static VALUE
-rb_mod_public_method_defined(VALUE mod, SEL sel, VALUE mid)
+check_method_visibility(VALUE mod, ID id, int visi)
{
- ID id = rb_to_id(mid);
- NODE *method;
-
- method = rb_method_node(mod, id);
- if (method) {
- if (VISI_CHECK(method->nd_noex, NOEX_PUBLIC))
- return Qtrue;
+ rb_vm_method_node_t *node;
+ if (rb_vm_lookup_method2((Class)mod, id, NULL, NULL, &node)) {
+ if (node != NULL) {
+ if (node->flags & rb_vm_noex_flag(visi)) {
+ return Qtrue;
+ }
+ }
}
return Qfalse;
}
+static VALUE
+rb_mod_public_method_defined(VALUE mod, SEL sel, VALUE mid)
+{
+ ID id = rb_to_id(mid);
+ return check_method_visibility(mod, id, NOEX_PUBLIC);
+}
+
/*
* call-seq:
* mod.private_method_defined?(symbol) => true or false
@@ -484,14 +459,7 @@
rb_mod_private_method_defined(VALUE mod, SEL sel, VALUE mid)
{
ID id = rb_to_id(mid);
- NODE *method;
-
- method = rb_method_node(mod, id);
- if (method) {
- if (VISI_CHECK(method->nd_noex, NOEX_PRIVATE))
- return Qtrue;
- }
- return Qfalse;
+ return check_method_visibility(mod, id, NOEX_PRIVATE);
}
/*
@@ -524,14 +492,7 @@
rb_mod_protected_method_defined(VALUE mod, SEL sel, VALUE mid)
{
ID id = rb_to_id(mid);
- NODE *method;
-
- method = rb_method_node(mod, id);
- if (method) {
- if (VISI_CHECK(method->nd_noex, NOEX_PROTECTED))
- return Qtrue;
- }
- return Qfalse;
+ return check_method_visibility(mod, id, NOEX_PROTECTED);
}
void
@@ -581,9 +542,8 @@
static void
set_method_visibility(VALUE self, int argc, VALUE *argv, ID ex)
{
- int i;
secure_visibility(self);
- for (i = 0; i < argc; i++) {
+ for (int i = 0; i < argc; i++) {
rb_export_method(self, rb_to_id(argv[i]), ex);
}
}
@@ -603,7 +563,7 @@
{
secure_visibility(module);
if (argc == 0) {
- // TODO change scope!
+ rb_vm_set_current_scope(module, SCOPE_PUBLIC);
}
else {
set_method_visibility(module, argc, argv, NOEX_PUBLIC);
@@ -626,7 +586,7 @@
{
secure_visibility(module);
if (argc == 0) {
- // TODO change scope!
+ rb_vm_set_current_scope(module, SCOPE_PROTECTED);
}
else {
set_method_visibility(module, argc, argv, NOEX_PROTECTED);
@@ -658,7 +618,7 @@
{
secure_visibility(module);
if (argc == 0) {
- // TODO change scope!
+ rb_vm_set_current_scope(module, SCOPE_PRIVATE);
}
else {
set_method_visibility(module, argc, argv, NOEX_PRIVATE);
@@ -764,21 +724,19 @@
static VALUE
rb_mod_modfunc(VALUE module, SEL sel, int argc, VALUE *argv)
{
- int i;
-
if (TYPE(module) != T_MODULE) {
rb_raise(rb_eTypeError, "module_function must be called for modules");
}
secure_visibility(module);
if (argc == 0) {
- // TODO change scope!
+ rb_vm_set_current_scope(module, SCOPE_MODULE_FUNC);
return module;
}
set_method_visibility(module, argc, argv, NOEX_PRIVATE);
- for (i = 0; i < argc; i++) {
+ for (int i = 0; i < argc; i++) {
ID id = rb_to_id(argv[i]);
IMP imp;
rb_vm_method_node_t *node;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090822/fcf59771/attachment-0001.html>
More information about the macruby-changes
mailing list