mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-class-ext: migrate comparison methods to c
The following Module methods were migrated from Ruby to C: - `<` - `<=` - `>` - `>=` - `<=>` Co-authored-by: Gemini <gemini@google.com>
This commit is contained in:
@@ -1,89 +0,0 @@
|
||||
class Module
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# mod < other -> true, false, or nil
|
||||
#
|
||||
# Returns true if `mod` is a subclass of `other`. Returns
|
||||
# <code>nil</code> if there's no relationship between the two.
|
||||
# (Think of the relationship in terms of the class definition:
|
||||
# "class A < B" implies "A < B".)
|
||||
#
|
||||
def <(other)
|
||||
if self.equal?(other)
|
||||
false
|
||||
else
|
||||
self <= other
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# mod <= other -> true, false, or nil
|
||||
#
|
||||
# Returns true if `mod` is a subclass of `other` or
|
||||
# is the same as `other`. Returns
|
||||
# <code>nil</code> if there's no relationship between the two.
|
||||
# (Think of the relationship in terms of the class definition:
|
||||
# "class A < B" implies "A < B".)
|
||||
def <=(other)
|
||||
raise TypeError, 'compared with non class/module' unless other.is_a?(Module)
|
||||
if self.ancestors.include?(other)
|
||||
return true
|
||||
elsif other.ancestors.include?(self)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# mod > other -> true, false, or nil
|
||||
#
|
||||
# Returns true if `mod` is an ancestor of `other`. Returns
|
||||
# <code>nil</code> if there's no relationship between the two.
|
||||
# (Think of the relationship in terms of the class definition:
|
||||
# "class A < B" implies "B > A".)
|
||||
#
|
||||
def >(other)
|
||||
if self.equal?(other)
|
||||
false
|
||||
else
|
||||
self >= other
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# mod >= other -> true, false, or nil
|
||||
#
|
||||
# Returns true if `mod` is an ancestor of `other`, or the
|
||||
# two modules are the same. Returns
|
||||
# <code>nil</code> if there's no relationship between the two.
|
||||
# (Think of the relationship in terms of the class definition:
|
||||
# "class A < B" implies "B > A".)
|
||||
#
|
||||
def >=(other)
|
||||
raise TypeError, 'compared with non class/module' unless other.is_a?(Module)
|
||||
return other < self
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# module <=> other_module -> -1, 0, +1, or nil
|
||||
#
|
||||
# Comparison---Returns -1, 0, +1 or nil depending on whether `module`
|
||||
# includes `other_module`, they are the same, or if `module` is included by
|
||||
# `other_module`.
|
||||
#
|
||||
# Returns `nil` if `module` has no relationship with `other_module`, if
|
||||
# `other_module` is not a module, or if the two values are incomparable.
|
||||
#
|
||||
def <=>(other)
|
||||
return 0 if self.equal?(other)
|
||||
return nil unless other.is_a?(Module)
|
||||
cmp = self < other
|
||||
return -1 if cmp
|
||||
return 1 unless cmp.nil?
|
||||
return nil
|
||||
end
|
||||
end
|
||||
@@ -121,16 +121,206 @@ class_attached_object(mrb_state *mrb, mrb_value self)
|
||||
return mrb_obj_iv_get(mrb, (struct RObject*)c, MRB_SYM(__attached__));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if a class/module is an ancestor of another.
|
||||
*
|
||||
* This function traverses the inheritance chain of `klass` upwards to determine
|
||||
* if `super` appears anywhere in the hierarchy. It handles both regular classes/modules
|
||||
* and included classes (ICLASS) which represent modules included in the inheritance chain.
|
||||
*
|
||||
* Args:
|
||||
* klass: The class/module to check (potential descendant)
|
||||
* super: The class/module to search for (potential ancestor)
|
||||
*
|
||||
* Returns:
|
||||
* true: if `super` is found in `klass`'s inheritance chain
|
||||
* false: if `super` is not an ancestor of `klass`
|
||||
*/
|
||||
static mrb_bool
|
||||
is_ancestor(struct RClass *klass, struct RClass *super)
|
||||
{
|
||||
struct RClass *c = klass;
|
||||
while (c) {
|
||||
if (c->tt == MRB_TT_ICLASS) {
|
||||
if (c->c == super) return TRUE;
|
||||
}
|
||||
else {
|
||||
if (c == super) return TRUE;
|
||||
}
|
||||
c = c->super;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare hierarchy relationship between two modules/classes.
|
||||
*
|
||||
* This function determines the ancestor relationship between `self` and `other`.
|
||||
* It checks if one is an ancestor of the other by traversing the inheritance chain.
|
||||
*
|
||||
* Args:
|
||||
* mrb: The mruby state
|
||||
* self: The first module/class to compare
|
||||
* other: The second module/class to compare
|
||||
*
|
||||
* Returns:
|
||||
* true: if `self` is an ancestor of `other` (self > other)
|
||||
* false: if `other` is an ancestor of `self` (self < other)
|
||||
* nil: if there's no inheritance relationship between them
|
||||
*
|
||||
* Raises:
|
||||
* TypeError: if `other` is not a class, module, or included class
|
||||
*/
|
||||
static mrb_value
|
||||
mod_compare_hierarchy(mrb_state *mrb, mrb_value self, mrb_value other)
|
||||
{
|
||||
if (!mrb_class_p(other) && !mrb_module_p(other) && !mrb_iclass_p(other)) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "compared with non class/module");
|
||||
}
|
||||
|
||||
struct RClass *self_c = mrb_class_ptr(self);
|
||||
struct RClass *other_c = mrb_class_ptr(other);
|
||||
|
||||
if (is_ancestor(self_c, other_c)) {
|
||||
return mrb_true_value();
|
||||
}
|
||||
if (is_ancestor(other_c, self_c)) {
|
||||
return mrb_false_value();
|
||||
}
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* mod <= other -> true, false, or nil
|
||||
*
|
||||
* Returns true if mod is a subclass of other or is the same as other.
|
||||
* Returns nil if there's no relationship between the two.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_mod_le(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
return mod_compare_hierarchy(mrb, self, other);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* mod < other -> true, false, or nil
|
||||
*
|
||||
* Returns true if mod is a subclass of other. Returns false if mod
|
||||
* is the same as other. Returns nil if there's no relationship between the two.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_mod_lt(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
if (mrb_obj_equal(mrb, self, other)) {
|
||||
return mrb_false_value();
|
||||
}
|
||||
return mod_compare_hierarchy(mrb, self, other);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* mod >= other -> true, false, or nil
|
||||
*
|
||||
* Returns true if mod is an ancestor of other, or the two modules are the same.
|
||||
* Returns nil if there's no relationship between the two.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_mod_ge(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
return mod_compare_hierarchy(mrb, other, self);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* mod > other -> true, false, or nil
|
||||
*
|
||||
* Returns true if mod is an ancestor of other. Returns false if mod
|
||||
* is the same as other. Returns nil if there's no relationship between the two.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_mod_gt(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
if (mrb_obj_equal(mrb, self, other)) {
|
||||
return mrb_false_value();
|
||||
}
|
||||
return mod_compare_hierarchy(mrb, other, self);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* module <=> other_module -> -1, 0, +1, or nil
|
||||
*
|
||||
* Comparison - Returns -1, 0, +1 or nil depending on whether module
|
||||
* includes other_module, they are the same, or if module is included by
|
||||
* other_module.
|
||||
*
|
||||
* Returns nil if module has no relationship with other_module, if
|
||||
* other_module is not a module, or if the two values are incomparable.
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_mod_cmp(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
|
||||
if (mrb_obj_equal(mrb, self, other)) {
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
if (!mrb_class_p(other) && !mrb_module_p(other) && !mrb_iclass_p(other)) {
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
mrb_value cmp = mod_compare_hierarchy(mrb, self, other);
|
||||
|
||||
if (mrb_true_p(cmp)) {
|
||||
return mrb_fixnum_value(-1);
|
||||
}
|
||||
else if (mrb_false_p(cmp)) {
|
||||
return mrb_fixnum_value(1);
|
||||
}
|
||||
else {
|
||||
return mrb_nil_value();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the mruby-class-ext gem.
|
||||
*
|
||||
* This function registers all the extension methods to the Module and Class classes.
|
||||
* It's called automatically when the gem is loaded.
|
||||
*
|
||||
* Args:
|
||||
* mrb: The mruby state
|
||||
*/
|
||||
void
|
||||
mrb_mruby_class_ext_gem_init(mrb_state *mrb)
|
||||
{
|
||||
struct RClass *mod = mrb->module_class;
|
||||
|
||||
/* Module methods */
|
||||
mrb_define_method_id(mrb, mod, MRB_SYM(name), mod_name, MRB_ARGS_NONE());
|
||||
mrb_define_method_id(mrb, mod, MRB_SYM_Q(singleton_class), mod_singleton_class_p, MRB_ARGS_NONE());
|
||||
mrb_define_method_id(mrb, mod, MRB_SYM(module_exec), mod_module_exec, MRB_ARGS_ANY()|MRB_ARGS_BLOCK());
|
||||
mrb_define_method_id(mrb, mod, MRB_SYM(class_exec), mod_module_exec, MRB_ARGS_ANY()|MRB_ARGS_BLOCK());
|
||||
|
||||
/* Module comparison operators */
|
||||
mrb_define_method_id(mrb, mod, MRB_OPSYM(lt), mrb_mod_lt, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, mod, MRB_OPSYM(le), mrb_mod_le, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, mod, MRB_OPSYM(gt), mrb_mod_gt, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, mod, MRB_OPSYM(ge), mrb_mod_ge, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, mod, MRB_OPSYM(cmp), mrb_mod_cmp, MRB_ARGS_REQ(1));
|
||||
|
||||
/* Class-specific methods */
|
||||
struct RClass *cls = mrb->class_class;
|
||||
mrb_define_method_id(mrb, cls, MRB_SYM(subclasses), class_subclasses, MRB_ARGS_NONE());
|
||||
mrb_define_method_id(mrb, cls, MRB_SYM(attached_object), class_attached_object, MRB_ARGS_NONE());
|
||||
|
||||
Reference in New Issue
Block a user