M include/natalie/method.hpp => include/natalie/method.hpp +17 -12
@@ 9,12 9,16 @@
namespace Natalie {
struct Method : public gc {
- Method(MethodFnPtr fn)
- : m_fn { fn }
+ Method(const char *name, ModuleValue *owner, MethodFnPtr fn)
+ : m_name { name }
+ , m_owner { owner }
+ , m_fn { fn }
, m_undefined { !fn } { }
- Method(Block *block)
- : m_env { *block->env() } {
+ Method(const char *name, ModuleValue *owner, Block *block)
+ : m_name { name }
+ , m_owner { owner }
+ , m_env { *block->env() } {
block->copy_fn_pointer_to_method(this);
m_env.clear_caller();
}
@@ 26,27 30,28 @@ struct Method : public gc {
bool is_undefined() { return m_undefined; }
- ValuePtr run(Env *env, ValuePtr self, size_t argc = 0, ValuePtr *args = nullptr, Block *block = nullptr) {
- return m_fn(env, self, argc, args, block);
- }
-
- ValuePtr call(Env *env, ModuleValue *method_owner, const char *method_name, ValuePtr self, size_t argc, ValuePtr *args, Block *block) {
+ ValuePtr call(Env *env, ValuePtr self, size_t argc, ValuePtr *args, Block *block) {
assert(!is_undefined());
Env *closure_env;
if (has_env()) {
closure_env = this->env();
} else {
- closure_env = method_owner->env();
+ closure_env = m_owner->env();
}
Env e = Env { closure_env, env };
e.set_file(env->file());
e.set_line(env->line());
- e.set_method_name(method_name);
+ e.set_method_name(m_name);
e.set_block(block);
- return run(&e, self, argc, args, block);
+ return m_fn(&e, self, argc, args, block);
}
+ const char *name() { return m_name; }
+ ModuleValue *owner() { return m_owner; }
+
private:
+ const char *m_name;
+ ModuleValue *m_owner;
MethodFnPtr m_fn;
Env m_env {};
bool m_undefined { false };
M include/natalie/method_value.hpp => include/natalie/method_value.hpp +6 -9
@@ 4,6 4,7 @@
#include "natalie/env.hpp"
#include "natalie/forward.hpp"
#include "natalie/global_env.hpp"
+#include "natalie/method.hpp"
#include "natalie/string_value.hpp"
#include "natalie/symbol_value.hpp"
#include "natalie/value.hpp"
@@ 11,33 12,29 @@
namespace Natalie {
struct MethodValue : Value {
- MethodValue(Env *env, ModuleValue *owner, SymbolValue *owner_name, bool owner_is_singleton, SymbolValue *name, Method *method)
+ MethodValue(Env *env, SymbolValue *owner_name, bool owner_is_singleton, Method *method)
: Value { Value::Type::Method, env->Object()->const_fetch(env, "Method")->as_class() }
- , m_owner { owner }
, m_owner_name { owner_name }
, m_owner_is_singleton { owner_is_singleton }
- , m_name { name }
, m_method { method } { }
MethodValue(Env *env, ClassValue *klass)
: Value { Value::Type::Method, klass } { }
- ModuleValue *owner() { return m_owner; }
- SymbolValue *name() { return m_name; }
+ ModuleValue *owner() { return m_method->owner(); }
+ SymbolValue *name(Env *env) { return SymbolValue::intern(env, m_method->name()); }
Method *method() { return m_method; }
ValuePtr inspect(Env *env) {
if (m_owner_is_singleton)
- return StringValue::sprintf(env, "#<Method: %s.%s(*)>", m_owner_name->c_str(), m_name->c_str());
+ return StringValue::sprintf(env, "#<Method: %s.%s(*)>", m_owner_name->c_str(), m_method->name());
else
- return StringValue::sprintf(env, "#<Method: %s#%s(*)>", m_owner_name->c_str(), m_name->c_str());
+ return StringValue::sprintf(env, "#<Method: %s#%s(*)>", m_owner_name->c_str(), m_method->name());
}
private:
- ModuleValue *m_owner { nullptr };
SymbolValue *m_owner_name { nullptr };
bool m_owner_is_singleton { false };
- SymbolValue *m_name { nullptr };
Method *m_method { nullptr };
};
}
M src/kernel_module.cpp => src/kernel_module.cpp +2 -2
@@ 175,12 175,12 @@ ValuePtr KernelModule::method(Env *env, Value *name) {
env->raise("NoMethodError", "undefined method `%s' for %s:Class", name, m_klass->class_name());
}
auto owner_name = this->inspect(env)->to_symbol(env, Conversion::Strict);
- return new MethodValue { env, singleton, owner_name, true, name_symbol, method };
+ return new MethodValue { env, owner_name, true, method };
}
}
Method *method = m_klass->find_method(env, name_symbol->c_str());
if (method)
- return new MethodValue { env, m_klass, SymbolValue::intern(env, m_klass->class_name()), false, name_symbol, method };
+ return new MethodValue { env, SymbolValue::intern(env, m_klass->class_name()), false, method };
env->raise("NoMethodError", "undefined method `%s' for %s:Class", name, m_klass->class_name());
}
M src/module_value.cpp => src/module_value.cpp +4 -5
@@ 178,13 178,13 @@ ValuePtr ModuleValue::cvar_set(Env *env, const char *name, ValuePtr val) {
}
void ModuleValue::define_method(Env *env, const char *name, MethodFnPtr fn) {
- Method *method = new Method { fn };
+ Method *method = new Method { name, this, fn };
GC_FREE(hashmap_remove(env, &m_methods, name));
hashmap_put(env, &m_methods, name, method);
}
void ModuleValue::define_method_with_block(Env *env, const char *name, Block *block) {
- Method *method = new Method { block };
+ Method *method = new Method { name, this, block };
GC_FREE(hashmap_remove(env, &m_methods, name));
hashmap_put(env, &m_methods, name, method);
}
@@ 240,10 240,9 @@ Method *ModuleValue::find_method(Env *env, const char *method_name, ModuleValue
}
ValuePtr ModuleValue::call_method(Env *env, ValuePtr instance_class, const char *method_name, ValuePtr self, size_t argc, ValuePtr *args, Block *block) {
- ModuleValue *method_owner;
- Method *method = find_method(env, method_name, &method_owner);
+ Method *method = find_method(env, method_name);
if (method && !method->is_undefined()) {
- return method->call(env, method_owner, method_name, self, argc, args, block);
+ return method->call(env, self, argc, args, block);
} else if (self->is_module()) {
env->raise("NoMethodError", "undefined method `%s' for %s:%v", method_name, self->as_module()->class_name(), instance_class);
} else if (strcmp(method_name, "inspect") == 0) {
M src/value.cpp => src/value.cpp +5 -10
@@ 49,10 49,6 @@ ValuePtr Value::_new(Env *env, ValuePtr klass_value, size_t argc, ValuePtr *args
obj = new MatchDataValue { env, klass };
break;
- case Value::Type::Method:
- obj = new MethodValue { env, klass };
- break;
-
case Value::Type::Module:
obj = new ModuleValue { env, klass };
break;
@@ 81,6 77,7 @@ ValuePtr Value::_new(Env *env, ValuePtr klass_value, size_t argc, ValuePtr *args
obj = new VoidPValue { env, klass };
break;
+ case Value::Type::Method:
case Value::Type::Nil:
case Value::Type::False:
case Value::Type::True:
@@ 94,10 91,9 @@ ValuePtr Value::_new(Env *env, ValuePtr klass_value, size_t argc, ValuePtr *args
}
ValuePtr Value::initialize(Env *env, size_t argc, ValuePtr *args, Block *block) {
- ModuleValue *method_owner;
- Method *method = m_klass->find_method(env, "initialize", &method_owner);
+ Method *method = m_klass->find_method(env, "initialize");
if (method && !method->is_undefined()) {
- method->call(env, method_owner, "initialize", this, argc, args, block);
+ method->call(env, this, argc, args, block);
}
return this;
}
@@ 418,12 414,11 @@ void Value::undefine_method(Env *env, const char *name) {
ValuePtr Value::send(Env *env, const char *name, size_t argc, ValuePtr *args, Block *block) {
auto singleton = singleton_class();
if (singleton) {
- ModuleValue *method_owner;
- Method *method = singleton_class()->find_method(env, name, &method_owner);
+ Method *method = singleton_class()->find_method(env, name);
if (method) {
if (method->is_undefined())
env->raise("NoMethodError", "undefined method `%s' for %s:Class", name, m_klass->class_name());
- return method->call(env, method_owner, name, this, argc, args, block);
+ return method->call(env, this, argc, args, block);
}
}
return m_klass->call_method(env, m_klass, name, this, argc, args, block);