mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #6540 from mruby/add-comments-object-c
This commit is contained in:
+227
-9
@@ -12,6 +12,18 @@
|
||||
#include <mruby/internal.h>
|
||||
#include <mruby/presym.h>
|
||||
|
||||
/*
|
||||
* Checks if two mruby values, `v1` and `v2`, are identical.
|
||||
* For most types, this is equivalent to pointer equality.
|
||||
* For immediate values (integers, symbols, true, false, nil),
|
||||
* it compares their actual values.
|
||||
*
|
||||
* Behavior under different boxing configurations:
|
||||
* - MRB_NAN_BOXING: Compares the raw `uint64_t` values.
|
||||
* - MRB_WORD_BOXING: Compares the raw `mrb_word` values.
|
||||
* - MRB_NO_BOXING: Checks if types are equal. If so, performs
|
||||
* type-specific comparisons (value for immediates, pointer for others).
|
||||
*/
|
||||
MRB_API mrb_bool
|
||||
mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2)
|
||||
{
|
||||
@@ -43,13 +55,27 @@ mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if two mruby values, `v1` and `v2`, are equal.
|
||||
* This function currently calls mrb_obj_eq to perform the comparison.
|
||||
*/
|
||||
MRB_API mrb_bool
|
||||
mrb_obj_equal(mrb_state *mrb, mrb_value v1, mrb_value v2)
|
||||
{
|
||||
/* temporary definition */
|
||||
return mrb_obj_eq(mrb, v1, v2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks for equality between `obj1` and `obj2`.
|
||||
*
|
||||
* It first uses `mrb_obj_eq` for an identity check. If that fails,
|
||||
* it handles cases like mixed integer/float comparisons.
|
||||
* If `MRB_USE_BIGINT` is defined, it also considers comparisons
|
||||
* involving BigInts against Integers, other BigInts, or Floats.
|
||||
* Finally, if none of the above apply, it attempts to call the
|
||||
* `==` operator (MRB_OPSYM(eq)) on `obj1` with `obj2` as an argument,
|
||||
* unless `obj1`'s `==` method is the default `mrb_obj_equal_m`.
|
||||
*/
|
||||
MRB_API mrb_bool
|
||||
mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
|
||||
{
|
||||
@@ -355,6 +381,21 @@ convert_type(mrb_state *mrb, mrb_value val, const char *tname, mrb_sym method, m
|
||||
return mrb_funcall_argv(mrb, val, method, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempts to convert the mruby value `val` to the specified `type`
|
||||
* by calling the given `method` (a symbol) on `val`.
|
||||
*
|
||||
* It first checks if `val` is already of the target `type`. If not, it
|
||||
* proceeds to call the conversion `method` on `val`.
|
||||
*
|
||||
* If the conversion method does not return a value of the target `type`,
|
||||
* a `TypeError` is raised. However, as a special case, if the target
|
||||
* `type` is `MRB_TT_STRING`, and the initial conversion fails to produce
|
||||
* a string, this function will then attempt to call `mrb_any_to_s` on
|
||||
* the original `val` as a fallback mechanism.
|
||||
*
|
||||
* Returns the converted value if successful.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_type_convert(mrb_state *mrb, mrb_value val, enum mrb_vtype type, mrb_sym method)
|
||||
{
|
||||
@@ -371,6 +412,25 @@ mrb_type_convert(mrb_state *mrb, mrb_value val, enum mrb_vtype type, mrb_sym met
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempts to convert the mruby value `val` to the specified `type`
|
||||
* by calling the given `method` (a symbol) on `val`.
|
||||
*
|
||||
* This function first checks if `val` is already of the target `type`.
|
||||
* An exception to this initial check is if the target `type` is
|
||||
* `MRB_TT_CDATA` or `MRB_TT_ISTRUCT`; in these cases, the conversion
|
||||
* attempt proceeds regardless of `val`'s current type.
|
||||
*
|
||||
* If `val` is not already of the target `type` (or if it's `MRB_TT_CDATA`
|
||||
* or `MRB_TT_ISTRUCT`), the specified `method` is called on `val` to
|
||||
* perform the conversion. Unlike `mrb_type_convert`, this function
|
||||
* does *not* raise an error if the conversion fails or if the returned
|
||||
* value is not of the target `type`.
|
||||
*
|
||||
* Returns the converted value if the conversion was successful and the
|
||||
* resulting value is of the target `type`. Otherwise, it returns
|
||||
* `mrb_nil_value()`.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_type_convert_check(mrb_state *mrb, mrb_value val, enum mrb_vtype type, mrb_sym method)
|
||||
{
|
||||
@@ -382,6 +442,13 @@ mrb_type_convert_check(mrb_state *mrb, mrb_value val, enum mrb_vtype type, mrb_s
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the mruby value `x` is of the specified type `t`.
|
||||
*
|
||||
* If the type of `x` does not match `t`, this function raises
|
||||
* a `TypeError`. The error message provides details about the
|
||||
* actual type of `x` and the expected type `t`.
|
||||
*/
|
||||
MRB_API void
|
||||
mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t)
|
||||
{
|
||||
@@ -446,9 +513,15 @@ mrb_any_to_s(mrb_state *mrb, mrb_value obj)
|
||||
* obj.is_a?(class) => true or false
|
||||
* obj.kind_of?(class) => true or false
|
||||
*
|
||||
* Returns <code>true</code> if <i>class</i> is the class of
|
||||
* <i>obj</i>, or if <i>class</i> is one of the superclasses of
|
||||
* <i>obj</i> or modules included in <i>obj</i>.
|
||||
* Checks if the mruby object `obj` is an instance of class `c`,
|
||||
* or an instance of a class that inherits from `c`, or an instance
|
||||
* of a class that includes `c` if `c` is a module.
|
||||
*
|
||||
* This function traverses the class hierarchy of `obj` upwards.
|
||||
* It returns `TRUE` if `c` is found in the ancestry. Otherwise,
|
||||
* it returns `FALSE`.
|
||||
*
|
||||
* If `c` is not a class or module, a `TypeError` is raised.
|
||||
*
|
||||
* module M; end
|
||||
* class A
|
||||
@@ -457,16 +530,13 @@ mrb_any_to_s(mrb_state *mrb, mrb_value obj)
|
||||
* class B < A; end
|
||||
* class C < B; end
|
||||
* b = B.new
|
||||
* b.instance_of? A #=> false
|
||||
* b.instance_of? B #=> true
|
||||
* b.instance_of? C #=> false
|
||||
* b.instance_of? M #=> false
|
||||
* b.instance_of? A #=> false (mrb_obj_is_instance_of)
|
||||
* b.instance_of? B #=> true (mrb_obj_is_instance_of)
|
||||
* b.kind_of? A #=> true
|
||||
* b.kind_of? B #=> true
|
||||
* b.kind_of? C #=> false
|
||||
* b.kind_of? M #=> true
|
||||
*/
|
||||
|
||||
MRB_API mrb_bool
|
||||
mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c)
|
||||
{
|
||||
@@ -503,6 +573,28 @@ mrb_value mrb_complex_to_f(mrb_state *mrb, mrb_value comp);
|
||||
mrb_value mrb_complex_to_i(mrb_state *mrb, mrb_value comp);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ensures that the given mruby value `val` is an Integer.
|
||||
*
|
||||
* If `val` is already an `MRB_TT_INTEGER`, it is returned directly.
|
||||
*
|
||||
* If `val` is an `MRB_TT_FLOAT` (and `MRB_NO_FLOAT` is not defined),
|
||||
* it is converted to an integer using `mrb_float_to_integer`.
|
||||
*
|
||||
* The function also handles conversions from other numeric types if
|
||||
* the respective modules are enabled:
|
||||
* - `MRB_TT_BIGINT` (if `MRB_USE_BIGINT` is defined): `val` is returned as is,
|
||||
* as BigInts are considered integers.
|
||||
* - `MRB_TT_RATIONAL` (if `MRB_USE_RATIONAL` is defined): Converted using
|
||||
* `mrb_rational_to_i`.
|
||||
* - `MRB_TT_COMPLEX` (if `MRB_USE_COMPLEX` is defined): Converted using
|
||||
* `mrb_complex_to_i` (typically if the imaginary part is zero).
|
||||
*
|
||||
* If `val` cannot be converted to an Integer (e.g., it's a String or Array,
|
||||
* or a Complex with a non-zero imaginary part), a `TypeError` is raised.
|
||||
*
|
||||
* Returns the (potentially converted) integer value.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_ensure_integer_type(mrb_state *mrb, mrb_value val)
|
||||
{
|
||||
@@ -535,6 +627,25 @@ mrb_ensure_integer_type(mrb_state *mrb, mrb_value val)
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensures that the given mruby value `val` is a C `mrb_int` (fixed-size integer).
|
||||
*
|
||||
* This function first calls `mrb_ensure_integer_type` to convert `val`
|
||||
* to a generic mruby Integer if it's not already. This step might result
|
||||
* in `val` being a Fixnum or a BigInt (if `MRB_USE_BIGINT` is enabled).
|
||||
*
|
||||
* If `mrb_ensure_integer_type` returns a BigInt (and `MRB_USE_BIGINT`
|
||||
* is defined), this function then attempts to convert the BigInt to a C
|
||||
* `mrb_int` using `mrb_bint_as_int`. This conversion may involve truncation
|
||||
* if the BigInt's value is outside the representable range of `mrb_int`,
|
||||
* or it could raise an error (e.g., RangeError) depending on the
|
||||
* `mrb_bint_as_int` implementation if the value is too large to truncate.
|
||||
*
|
||||
* If `val` is already a standard Integer (Fixnum) after the call to
|
||||
* `mrb_ensure_integer_type`, it is returned directly as it fits `mrb_int`.
|
||||
*
|
||||
* Returns an `mrb_value` that represents a C `mrb_int`.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_ensure_int_type(mrb_state *mrb, mrb_value val)
|
||||
{
|
||||
@@ -548,6 +659,28 @@ mrb_ensure_int_type(mrb_state *mrb, mrb_value val)
|
||||
}
|
||||
|
||||
#ifndef MRB_NO_FLOAT
|
||||
/*
|
||||
* Ensures that the given mruby value `val` is a Float.
|
||||
*
|
||||
* If `val` is `nil`, this function raises a `TypeError`.
|
||||
*
|
||||
* If `val` is an `MRB_TT_INTEGER`, it is converted to an `mrb_float`.
|
||||
* If `val` is already an `MRB_TT_FLOAT`, it is returned directly.
|
||||
*
|
||||
* The function also handles conversions from other numeric types if the
|
||||
* respective mruby modules are enabled:
|
||||
* - `MRB_TT_RATIONAL` (if `MRB_USE_RATIONAL` is defined): Converted to Float
|
||||
* using `mrb_rational_to_f`.
|
||||
* - `MRB_TT_COMPLEX` (if `MRB_USE_COMPLEX` is defined): Converted to Float
|
||||
* using `mrb_complex_to_f` (typically requires the imaginary part to be zero).
|
||||
* - `MRB_TT_BIGINT` (if `MRB_USE_BIGINT` is defined): Converted to Float
|
||||
* using `mrb_bint_as_float`.
|
||||
*
|
||||
* If `val` cannot be converted to a Float (e.g., it's a String, Array, or
|
||||
* an incompatible Complex number), a `TypeError` is raised.
|
||||
*
|
||||
* Returns an `mrb_value` representing an `mrb_float`.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_ensure_float_type(mrb_state *mrb, mrb_value val)
|
||||
{
|
||||
@@ -584,6 +717,13 @@ mrb_ensure_float_type(mrb_state *mrb, mrb_value val)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ensures that the given mruby value `str` is a String.
|
||||
*
|
||||
* If `str` is not of type `MRB_TT_STRING`, this function raises
|
||||
* a `TypeError`.
|
||||
* Otherwise, `str` itself is returned.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_ensure_string_type(mrb_state *mrb, mrb_value str)
|
||||
{
|
||||
@@ -593,6 +733,14 @@ mrb_ensure_string_type(mrb_state *mrb, mrb_value str)
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the given mruby value `str` is a String.
|
||||
*
|
||||
* If `str` is of type `MRB_TT_STRING`, this function returns `str`.
|
||||
* Otherwise (if `str` is not a String), it returns `mrb_nil_value()`
|
||||
* without raising an error. This allows for type checking without
|
||||
* forcing error handling.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_check_string_type(mrb_state *mrb, mrb_value str)
|
||||
{
|
||||
@@ -600,6 +748,13 @@ mrb_check_string_type(mrb_state *mrb, mrb_value str)
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensures that the given mruby value `ary` is an Array.
|
||||
*
|
||||
* If `ary` is not of type `MRB_TT_ARRAY`, this function raises
|
||||
* a `TypeError`.
|
||||
* Otherwise, `ary` itself is returned.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_ensure_array_type(mrb_state *mrb, mrb_value ary)
|
||||
{
|
||||
@@ -609,6 +764,14 @@ mrb_ensure_array_type(mrb_state *mrb, mrb_value ary)
|
||||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the given mruby value `ary` is an Array.
|
||||
*
|
||||
* If `ary` is of type `MRB_TT_ARRAY`, this function returns `ary`.
|
||||
* Otherwise (if `ary` is not an Array), it returns `mrb_nil_value()`
|
||||
* without raising an error. This allows for type checking without
|
||||
* forcing error handling.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_check_array_type(mrb_state *mrb, mrb_value ary)
|
||||
{
|
||||
@@ -616,6 +779,13 @@ mrb_check_array_type(mrb_state *mrb, mrb_value ary)
|
||||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensures that the given mruby value `hash` is a Hash.
|
||||
*
|
||||
* If `hash` is not of type `MRB_TT_HASH`, this function raises
|
||||
* a `TypeError`.
|
||||
* Otherwise, `hash` itself is returned.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash)
|
||||
{
|
||||
@@ -625,6 +795,14 @@ mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash)
|
||||
return hash;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the given mruby value `hash` is a Hash.
|
||||
*
|
||||
* If `hash` is of type `MRB_TT_HASH`, this function returns `hash`.
|
||||
* Otherwise (if `hash` is not a Hash), it returns `mrb_nil_value()`
|
||||
* without raising an error. This allows for type checking without
|
||||
* forcing error handling.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_check_hash_type(mrb_state *mrb, mrb_value hash)
|
||||
{
|
||||
@@ -632,6 +810,22 @@ mrb_check_hash_type(mrb_state *mrb, mrb_value hash)
|
||||
return hash;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a human-readable string representation of the mruby object `obj`.
|
||||
*
|
||||
* This function calls the `inspect` method (identified by `MRB_SYM(inspect)`)
|
||||
* on the given `obj`. The `inspect` method is expected to return a string
|
||||
* that is suitable for debugging and inspection.
|
||||
*
|
||||
* If the object's `inspect` method does not return a String value (e.g., it
|
||||
* returns `nil` or another type, or if the class doesn't define `inspect`
|
||||
* appropriately), this function falls back to calling `mrb_obj_as_string`.
|
||||
* `mrb_obj_as_string` typically provides a basic string representation,
|
||||
* such as "#<ClassName:0xPointer>" if `inspect` is unavailable or
|
||||
* misbehaves by not returning a string.
|
||||
*
|
||||
* The function ultimately returns the resulting string `mrb_value`.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_inspect(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
@@ -642,6 +836,22 @@ mrb_inspect(mrb_state *mrb, mrb_value obj)
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if two mruby values, `obj1` and `obj2`, are equal using
|
||||
* `eql?` semantics.
|
||||
*
|
||||
* This function first performs an identity check on `obj1` and `obj2`
|
||||
* using `mrb_obj_eq`. If they are identical (i.e., the same object),
|
||||
* it returns `TRUE` immediately.
|
||||
*
|
||||
* Otherwise, it calls the `eql?` method on `obj1`, passing `obj2` as
|
||||
* an argument. The symbol for the `eql?` method is `MRB_SYM_Q(eql)`.
|
||||
*
|
||||
* The function returns `TRUE` if the `eql?` method call returns a truthy
|
||||
* value (any value other than `false` or `nil`). Otherwise, it returns
|
||||
* `FALSE`. This is determined by `mrb_test` on the result of the
|
||||
* method call.
|
||||
*/
|
||||
MRB_API mrb_bool
|
||||
mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
|
||||
{
|
||||
@@ -649,6 +859,14 @@ mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
|
||||
return mrb_test(mrb_funcall_argv(mrb, obj1, MRB_SYM_Q(eql), 1, &obj2));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the receiver object itself.
|
||||
*
|
||||
* This function simply returns the mruby value `self` that it was passed.
|
||||
* It corresponds to the `Object#itself` method in Ruby, which is useful
|
||||
* in some functional programming patterns or for obtaining the object
|
||||
* itself in a chain of method calls.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_obj_itself(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user