diff --git a/include/natalie/kernel_module.hpp b/include/natalie/kernel_module.hpp index 37a98e06a..684edead0 100644 --- a/include/natalie/kernel_module.hpp +++ b/include/natalie/kernel_module.hpp @@ -87,11 +87,11 @@ class KernelModule { static bool is_frozen(Value self) { return self.is_frozen(); } static Value loop(Env *env, Value self, Block *block); static Value method(Env *env, Value self, Value name); - static Value methods(Env *env, Value self, Value regular_val); + static Value methods(Env *env, Value self, Optional regular_val); static bool neqtilde(Env *env, Value self, Value other); - static Value private_methods(Env *env, Value self, Value recur = nullptr); - static Value protected_methods(Env *env, Value self, Value recur = nullptr); - static Value public_methods(Env *env, Value self, Value recur = nullptr); + static Value private_methods(Env *env, Value self, Optional recur = {}); + static Value protected_methods(Env *env, Value self, Optional recur = {}); + static Value public_methods(Env *env, Value self, Optional recur = {}); static Value remove_instance_variable(Env *env, Value self, Value name_val); static bool respond_to_missing(Env *, Value, Value, Value) { return false; } static bool respond_to_method(Env *, Value, Value, Value); diff --git a/include/natalie/module_object.hpp b/include/natalie/module_object.hpp index b601be73b..eab035d37 100644 --- a/include/natalie/module_object.hpp +++ b/include/natalie/module_object.hpp @@ -57,7 +57,7 @@ class ModuleObject : public Object { Value const_find(Env *, SymbolObject *, ConstLookupSearchMode = ConstLookupSearchMode::Strict, ConstLookupFailureMode = ConstLookupFailureMode::ConstMissing); Value const_get(SymbolObject *) const; - Value const_get(Env *, Value, Value = nullptr); + Value const_get(Env *, Value, Optional = {}); Value const_fetch(SymbolObject *) const; Value const_set(SymbolObject *, Value); Value const_set(SymbolObject *, MethodFnPtr, StringObject *); @@ -65,7 +65,7 @@ class ModuleObject : public Object { void remove_const(SymbolObject *); Value remove_const(Env *, Value); - Value constants(Env *, Value) const; + Value constants(Env *, Optional) const; Value const_missing(Env *, Value); void make_method_alias(Env *, SymbolObject *, SymbolObject *); @@ -101,10 +101,10 @@ class ModuleObject : public Object { bool class_variable_defined(Env *, Value); Value class_variable_get(Env *, Value); Value class_variable_set(Env *, Value, Value); - ArrayObject *class_variables(Value = nullptr) const; + ArrayObject *class_variables(Optional = {}) const; Value remove_class_variable(Env *, Value); - Value define_method(Env *, Value, Value, Block *); + Value define_method(Env *, Value, Optional, Block *); SymbolObject *define_method(Env *, SymbolObject *, MethodFnPtr, int); SymbolObject *define_method(Env *, SymbolObject *, Block *); SymbolObject *undefine_method(Env *, SymbolObject *); @@ -118,11 +118,11 @@ class ModuleObject : public Object { Value instance_method(Env *, Value); Value public_instance_method(Env *, Value); - Value instance_methods(Env *, Value, std::function); - Value instance_methods(Env *, Value); - Value private_instance_methods(Env *, Value); - Value protected_instance_methods(Env *, Value); - Value public_instance_methods(Env *, Value); + Value instance_methods(Env *, Optional, std::function); + Value instance_methods(Env *, Optional); + Value private_instance_methods(Env *, Optional); + Value protected_instance_methods(Env *, Optional); + Value public_instance_methods(Env *, Optional); ArrayObject *ancestors(Env *); bool ancestors_includes(Env *, ModuleObject *); @@ -163,7 +163,7 @@ class ModuleObject : public Object { Value private_constant(Env *, Args &&); Value public_constant(Env *, Args &&); - bool const_defined(Env *, Value, Value = nullptr); + bool const_defined(Env *, Value, Optional = {}); Value alias_method(Env *, Value, Value); Value remove_method(Env *, Args &&); Value undef_method(Env *, Args &&); diff --git a/lib/natalie/compiler/binding_gen.rb b/lib/natalie/compiler/binding_gen.rb index be406258c..146bac826 100644 --- a/lib/natalie/compiler/binding_gen.rb +++ b/lib/natalie/compiler/binding_gen.rb @@ -1035,12 +1035,12 @@ def generate_name gen.static_binding_as_instance_method('Kernel', 'kind_of?', 'KernelModule', 'is_a', argc: 1, pass_env: true, pass_block: false, return_type: :bool) gen.static_binding_as_instance_method('Kernel', 'loop', 'KernelModule', 'loop', argc: 0, pass_env: true, pass_block: true, return_type: :Object) gen.static_binding_as_instance_method('Kernel', 'method', 'KernelModule', 'method', argc: 1, pass_env: true, pass_block: false, return_type: :Object) -gen.static_binding_as_instance_method('Kernel', 'methods', 'KernelModule', 'methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object) +gen.static_binding_as_instance_method('Kernel', 'methods', 'KernelModule', 'methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object, pass_null: false) gen.static_binding_as_instance_method('Kernel', 'nil?', 'KernelModule', 'is_nil', argc: 0, pass_env: false, pass_block: false, return_type: :bool) gen.static_binding_as_instance_method('Kernel', 'object_id', 'Object', 'object_id', argc: 0, pass_env: false, pass_block: false, return_type: :int) -gen.static_binding_as_instance_method('Kernel', 'private_methods', 'KernelModule', 'private_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object) -gen.static_binding_as_instance_method('Kernel', 'protected_methods', 'KernelModule', 'protected_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object) -gen.static_binding_as_instance_method('Kernel', 'public_methods', 'KernelModule', 'public_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object) +gen.static_binding_as_instance_method('Kernel', 'private_methods', 'KernelModule', 'private_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object, pass_null: false) +gen.static_binding_as_instance_method('Kernel', 'protected_methods', 'KernelModule', 'protected_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object, pass_null: false) +gen.static_binding_as_instance_method('Kernel', 'public_methods', 'KernelModule', 'public_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object, pass_null: false) gen.static_binding_as_instance_method('Kernel', 'remove_instance_variable', 'KernelModule', 'remove_instance_variable', argc: 1, pass_env: true, pass_block: false, return_type: :Object) gen.static_binding_as_instance_method('Kernel', 'singleton_class', 'Object', 'singleton_class', argc: 0, pass_env: true, pass_block: false, return_type: :Object) gen.static_binding_as_instance_method('Kernel', 'tap', 'KernelModule', 'tap', argc: 0, pass_env: true, pass_block: true, return_type: :Object) @@ -1102,20 +1102,20 @@ def generate_name gen.binding('Module', 'class_variable_defined?', 'ModuleObject', 'class_variable_defined', argc: 1, pass_env: true, pass_block: false, return_type: :bool) gen.binding('Module', 'class_variable_get', 'ModuleObject', 'class_variable_get', argc: 1, pass_env: true, pass_block: false, return_type: :Object) gen.binding('Module', 'class_variable_set', 'ModuleObject', 'class_variable_set', argc: 2, pass_env: true, pass_block: false, return_type: :Object) -gen.binding('Module', 'class_variables', 'ModuleObject', 'class_variables', argc: 0..1, pass_env: false, pass_block: false, return_type: :Object) -gen.binding('Module', 'const_defined?', 'ModuleObject', 'const_defined', argc: 1..2, pass_env: true, pass_block: false, return_type: :bool) -gen.binding('Module', 'const_get', 'ModuleObject', 'const_get', argc: 1..2, pass_env: true, pass_block: false, return_type: :Object) +gen.binding('Module', 'class_variables', 'ModuleObject', 'class_variables', argc: 0..1, pass_env: false, pass_block: false, return_type: :Object, pass_null: false) +gen.binding('Module', 'const_defined?', 'ModuleObject', 'const_defined', argc: 1..2, pass_env: true, pass_block: false, return_type: :bool, pass_null: false) +gen.binding('Module', 'const_get', 'ModuleObject', 'const_get', argc: 1..2, pass_env: true, pass_block: false, return_type: :Object, pass_null: false) gen.binding('Module', 'const_missing', 'ModuleObject', 'const_missing', argc: 1, pass_env: true, pass_block: false, return_type: :Object) gen.binding('Module', 'const_set', 'ModuleObject', 'const_set', argc: 2, pass_env: true, pass_block: false, return_type: :Object) -gen.binding('Module', 'constants', 'ModuleObject', 'constants', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object) -gen.binding('Module', 'define_method', 'ModuleObject', 'define_method', argc: 1..2, pass_env: true, pass_block: true, return_type: :Object) +gen.binding('Module', 'constants', 'ModuleObject', 'constants', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object, pass_null: false) +gen.binding('Module', 'define_method', 'ModuleObject', 'define_method', argc: 1..2, pass_env: true, pass_block: true, return_type: :Object, pass_null: false) gen.binding('Module', 'deprecate_constant', 'ModuleObject', 'deprecate_constant', argc: :any, pass_env: true, pass_block: false, return_type: :Object) gen.binding('Module', 'extend_object', 'ModuleObject', 'extend_object', argc: 1, pass_env: true, pass_block: false, return_type: :Object, visibility: :private) gen.binding('Module', 'include', 'ModuleObject', 'include', argc: 1.., pass_env: true, pass_block: false, return_type: :Object) gen.binding('Module', 'include?', 'ModuleObject', 'does_include_module', argc: 1, pass_env: true, pass_block: false, return_type: :bool) gen.binding('Module', 'included_modules', 'ModuleObject', 'included_modules', argc: 0, pass_env: true, pass_block: false, return_type: :Object) gen.binding('Module', 'instance_method', 'ModuleObject', 'instance_method', argc: 1, pass_env: true, pass_block: false, return_type: :Object) -gen.binding('Module', 'instance_methods', 'ModuleObject', 'instance_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object) +gen.binding('Module', 'instance_methods', 'ModuleObject', 'instance_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object, pass_null: false) gen.binding('Module', 'method_defined?', 'ModuleObject', 'is_method_defined', argc: 1, pass_env: true, pass_block: false, return_type: :bool) gen.binding('Module', 'module_eval', 'ModuleObject', 'module_eval', argc: 0, pass_env: true, pass_block: true, aliases: ['class_eval'], return_type: :Object) gen.binding('Module', 'module_exec', 'ModuleObject', 'module_exec', argc: :any, pass_env: true, pass_block: true, aliases: ['class_exec'], return_type: :Object) @@ -1125,13 +1125,13 @@ def generate_name gen.binding('Module', 'private', 'ModuleObject', 'private_method', argc: :any, pass_env: true, pass_block: false, return_type: :Object) gen.binding('Module', 'private_class_method', 'ModuleObject', 'private_class_method', argc: :any, pass_env: true, pass_block: false, return_type: :Object) gen.binding('Module', 'private_constant', 'ModuleObject', 'private_constant', argc: :any, pass_env: true, pass_block: false, return_type: :Object) -gen.binding('Module', 'private_instance_methods', 'ModuleObject', 'private_instance_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object) +gen.binding('Module', 'private_instance_methods', 'ModuleObject', 'private_instance_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object, pass_null: false) gen.binding('Module', 'protected', 'ModuleObject', 'protected_method', argc: :any, pass_env: true, pass_block: false, return_type: :Object) -gen.binding('Module', 'protected_instance_methods', 'ModuleObject', 'protected_instance_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object) +gen.binding('Module', 'protected_instance_methods', 'ModuleObject', 'protected_instance_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object, pass_null: false) gen.binding('Module', 'public', 'ModuleObject', 'public_method', argc: :any, pass_env: true, pass_block: false, return_type: :Object) gen.binding('Module', 'public_class_method', 'ModuleObject', 'public_class_method', argc: :any, pass_env: true, pass_block: false, return_type: :Object) gen.binding('Module', 'public_constant', 'ModuleObject', 'public_constant', argc: :any, pass_env: true, pass_block: false, return_type: :Object) -gen.binding('Module', 'public_instance_methods', 'ModuleObject', 'public_instance_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object) +gen.binding('Module', 'public_instance_methods', 'ModuleObject', 'public_instance_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object, pass_null: false) gen.binding('Module', 'public_instance_method', 'ModuleObject', 'public_instance_method', argc: 1, pass_env: true, pass_block: false, return_type: :Object) gen.binding('Module', 'remove_class_variable', 'ModuleObject', 'remove_class_variable', argc: 1, pass_env: true, pass_block: false, return_type: :Object) gen.binding('Module', 'remove_const', 'ModuleObject', 'remove_const', argc: 1, pass_env: true, pass_block: false, return_type: :Object, visibility: :private) diff --git a/src/kernel_module.cpp b/src/kernel_module.cpp index 5b452b402..3258db6be 100644 --- a/src/kernel_module.cpp +++ b/src/kernel_module.cpp @@ -1059,17 +1059,17 @@ Value KernelModule::method(Env *env, Value self, Value name) { return new MethodObject { self, method_info.method() }; } -Value KernelModule::methods(Env *env, Value self, Value regular_val) { - bool regular = regular_val ? regular_val.is_truthy() : true; +Value KernelModule::methods(Env *env, Value self, Optional regular_val) { + bool regular = regular_val ? regular_val.value().is_truthy() : true; if (regular) { if (self->singleton_class()) { - return self->singleton_class()->instance_methods(env, TrueObject::the()); + return self->singleton_class()->instance_methods(env, Value(TrueObject::the())); } else { - return self.klass()->instance_methods(env, TrueObject::the()); + return self.klass()->instance_methods(env, Value(TrueObject::the())); } } if (self->singleton_class()) - return self->singleton_class()->instance_methods(env, FalseObject::the()); + return self->singleton_class()->instance_methods(env, Value(FalseObject::the())); else return new ArrayObject {}; } @@ -1078,23 +1078,23 @@ bool KernelModule::neqtilde(Env *env, Value self, Value other) { return self.send(env, "=~"_s, { other }).is_falsey(); } -Value KernelModule::private_methods(Env *env, Value self, Value recur) { +Value KernelModule::private_methods(Env *env, Value self, Optional recur) { if (self->singleton_class()) - return self->singleton_class()->private_instance_methods(env, TrueObject::the()); + return self->singleton_class()->private_instance_methods(env, Value(TrueObject::the())); else return self.klass()->private_instance_methods(env, recur); } -Value KernelModule::protected_methods(Env *env, Value self, Value recur) { +Value KernelModule::protected_methods(Env *env, Value self, Optional recur) { if (self->singleton_class()) - return self->singleton_class()->protected_instance_methods(env, TrueObject::the()); + return self->singleton_class()->protected_instance_methods(env, Value(TrueObject::the())); else return self.klass()->protected_instance_methods(env, recur); } -Value KernelModule::public_methods(Env *env, Value self, Value recur) { +Value KernelModule::public_methods(Env *env, Value self, Optional recur) { if (self.singleton_class()) - return self.singleton_class()->public_instance_methods(env, TrueObject::the()); + return self.singleton_class()->public_instance_methods(env, Value(TrueObject::the())); else return self.klass()->public_instance_methods(env, recur); } diff --git a/src/module_object.cpp b/src/module_object.cpp index 31fc965cd..902919b17 100644 --- a/src/module_object.cpp +++ b/src/module_object.cpp @@ -88,11 +88,11 @@ Value ModuleObject::const_get(SymbolObject *name) const { return nullptr; } -Value ModuleObject::const_get(Env *env, Value name, Value inherited) { +Value ModuleObject::const_get(Env *env, Value name, Optional inherited) { auto symbol = name.to_symbol(env, Value::Conversion::Strict); auto constant = const_get(symbol); if (!constant) { - if (inherited && inherited.is_falsey()) + if (inherited && inherited.value().is_falsey()) env->raise("NameError", "uninitialized constant {}", symbol->string()); return send(env, "const_missing"_s, { name }); } @@ -326,11 +326,11 @@ Value ModuleObject::remove_const(Env *env, Value name) { return constant->value(); } -Value ModuleObject::constants(Env *env, Value inherit) const { +Value ModuleObject::constants(Env *env, Optional inherit) const { auto ary = new ArrayObject; for (auto pair : m_constants) ary->push(pair.first); - if (inherit == nullptr || inherit.is_truthy()) { + if (!inherit || inherit.value().is_truthy()) { for (ModuleObject *module : m_included_modules) { if (module != this) { ary->concat(*module->constants(env, inherit).as_array()); @@ -460,7 +460,7 @@ Value ModuleObject::class_variable_set(Env *env, Value name, Value value) { return cvar_set(env, name.to_symbol(env, Value::Conversion::Strict), value); } -ArrayObject *ModuleObject::class_variables(Value inherit) const { +ArrayObject *ModuleObject::class_variables(Optional inherit) const { std::lock_guard lock(g_gc_recursive_mutex); auto result = new ArrayObject {}; @@ -470,7 +470,7 @@ ArrayObject *ModuleObject::class_variables(Value inherit) const { for (auto [cvar, _] : singleton_class()->m_class_vars) result->push(cvar); } - if (inherit && inherit.is_truthy() && m_superclass) + if (inherit && inherit.value().is_truthy() && m_superclass) result->concat(*m_superclass->class_variables(inherit)); return result; } @@ -636,8 +636,8 @@ Value ModuleObject::public_instance_method(Env *env, Value name_value) { } } -Value ModuleObject::instance_methods(Env *env, Value include_super_value, std::function predicate) { - bool include_super = !include_super_value || include_super_value.is_truthy(); +Value ModuleObject::instance_methods(Env *env, Optional include_super_value, std::function predicate) { + bool include_super = !include_super_value || include_super_value.value().is_truthy(); ArrayObject *array = new ArrayObject {}; methods(env, array, include_super); array->select_in_place([this, env, predicate](Value &name_value) -> bool { @@ -648,25 +648,25 @@ Value ModuleObject::instance_methods(Env *env, Value include_super_value, std::f return array; } -Value ModuleObject::instance_methods(Env *env, Value include_super_value) { +Value ModuleObject::instance_methods(Env *env, Optional include_super_value) { return instance_methods(env, include_super_value, [](MethodVisibility visibility) { return visibility == MethodVisibility::Public || visibility == MethodVisibility::Protected; }); } -Value ModuleObject::private_instance_methods(Env *env, Value include_super_value) { +Value ModuleObject::private_instance_methods(Env *env, Optional include_super_value) { return instance_methods(env, include_super_value, [](MethodVisibility visibility) { return visibility == MethodVisibility::Private; }); } -Value ModuleObject::protected_instance_methods(Env *env, Value include_super_value) { +Value ModuleObject::protected_instance_methods(Env *env, Optional include_super_value) { return instance_methods(env, include_super_value, [](MethodVisibility visibility) { return visibility == MethodVisibility::Protected; }); } -Value ModuleObject::public_instance_methods(Env *env, Value include_super_value) { +Value ModuleObject::public_instance_methods(Env *env, Optional include_super_value) { return instance_methods(env, include_super_value, [](MethodVisibility visibility) { return visibility == MethodVisibility::Public; }); @@ -902,9 +902,10 @@ bool ModuleObject::does_include_module(Env *env, Value module) { return false; } -Value ModuleObject::define_method(Env *env, Value name_value, Value method_value, Block *block) { +Value ModuleObject::define_method(Env *env, Value name_value, Optional method_arg, Block *block) { auto name = name_value.to_symbol(env, Value::Conversion::Strict); - if (method_value) { + if (method_arg) { + auto method_value = method_arg.value(); if (method_value.is_proc()) { define_method(env, name, method_value.as_proc()->block()); } else { @@ -1065,12 +1066,12 @@ Value ModuleObject::public_constant(Env *env, Args &&args) { return this; } -bool ModuleObject::const_defined(Env *env, Value name_value, Value inherited) { +bool ModuleObject::const_defined(Env *env, Value name_value, Optional inherited) { auto name = name_value.to_symbol(env, Value::Conversion::NullAllowed); if (!name) { env->raise("TypeError", "no implicit conversion of {} to String", name_value.inspect_str(env)); } - if (inherited && inherited.is_falsey()) { + if (inherited && inherited.value().is_falsey()) { return !!m_constants.get(name); } return !!const_find(env, name, ConstLookupSearchMode::NotStrict, ConstLookupFailureMode::Null); diff --git a/src/object.cpp b/src/object.cpp index 0431c250d..71b8cf33f 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -496,7 +496,7 @@ SymbolObject *Object::undefine_method(Env *env, Value self, SymbolObject *name) } Value Object::main_obj_define_method(Env *env, Value name, Optional proc_or_unbound_method, Block *block) { - return m_klass->define_method(env, name, proc_or_unbound_method.value_or(static_cast(nullptr)), block); + return m_klass->define_method(env, name, proc_or_unbound_method, block); } Value Object::main_obj_inspect(Env *) {