diff --git a/mrbgems/mruby-class-ext/mrblib/module.rb b/mrbgems/mruby-class-ext/mrblib/module.rb
deleted file mode 100644
index 301585187..000000000
--- a/mrbgems/mruby-class-ext/mrblib/module.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-class Module
-
- ##
- # call-seq:
- # mod < other -> true, false, or nil
- #
- # Returns true if `mod` is a subclass of `other`. Returns
- # nil 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
- # nil 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
- # nil 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
- # nil 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
diff --git a/mrbgems/mruby-class-ext/src/class.c b/mrbgems/mruby-class-ext/src/class.c
index 46149b440..5a14a0c0f 100644
--- a/mrbgems/mruby-class-ext/src/class.c
+++ b/mrbgems/mruby-class-ext/src/class.c
@@ -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());