rcx 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Rakefile +5 -0
- data/examples/class.cpp +1 -1
- data/include/rcx/internal/rcx.hpp +339 -64
- data/include/rcx/internal/rcx_impl.hpp +56 -5
- data/lib/rcx/mkmf.rb +2 -0
- data/lib/rcx/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 291d8e72a9ddea530ab4aa2d585c5d97406603a97d5b72a75caeb2cb79eea8aa
|
4
|
+
data.tar.gz: 570ed623fd7e76df3df6808559d1195476690b2983889e5fc76945e61a1936a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b33290743f173becad0b8736cc6c50c34d5cd3057aedd07dca97500021f64dd7e900b00fc34f35bd9291b46aad91761d4a212b51b339931391040cd6f9461430
|
7
|
+
data.tar.gz: 2322cb7a7e48eb414cce22352b36f9bd8d21ee481bb742f4f3b60ac7a75715277ddc6c39daa43a4e59e2e6354d304935f4995607175c257e6abbda44930024c4
|
data/CHANGELOG.md
CHANGED
data/Rakefile
CHANGED
data/examples/class.cpp
CHANGED
@@ -60,6 +60,7 @@ namespace rcx {
|
|
60
60
|
#ifdef RCX_IO_BUFFER
|
61
61
|
class IOBuffer;
|
62
62
|
#endif
|
63
|
+
class IO;
|
63
64
|
}
|
64
65
|
using namespace value;
|
65
66
|
|
@@ -256,6 +257,9 @@ namespace rcx {
|
|
256
257
|
IOBuffer convert(Value value);
|
257
258
|
};
|
258
259
|
#endif
|
260
|
+
template <> struct FromValue<IO> {
|
261
|
+
IO convert(Value value);
|
262
|
+
};
|
259
263
|
|
260
264
|
#define RCX_DECLARE_CLASS_CONV(CLS) \
|
261
265
|
template <> struct FromValue<ClassT<CLS>> { \
|
@@ -269,6 +273,7 @@ namespace rcx {
|
|
269
273
|
RCX_DECLARE_CLASS_CONV(String);
|
270
274
|
RCX_DECLARE_CLASS_CONV(Array);
|
271
275
|
RCX_DECLARE_CLASS_CONV(Exception);
|
276
|
+
RCX_DECLARE_CLASS_CONV(IO);
|
272
277
|
#ifdef RCX_IO_BUFFER
|
273
278
|
RCX_DECLARE_CLASS_CONV(IOBuffer);
|
274
279
|
#endif
|
@@ -358,8 +363,10 @@ namespace rcx {
|
|
358
363
|
///
|
359
364
|
constexpr inline ArgSplat arg_splat;
|
360
365
|
/// Block.
|
366
|
+
///
|
361
367
|
constexpr inline Block block;
|
362
368
|
/// Optional block.
|
369
|
+
///
|
363
370
|
constexpr inline BlockOpt block_opt;
|
364
371
|
}
|
365
372
|
|
@@ -577,28 +584,40 @@ namespace rcx {
|
|
577
584
|
|
578
585
|
/// Defines a module under this module.
|
579
586
|
///
|
587
|
+
/// Creates a new module nested under this module. The module will be accessible
|
588
|
+
/// as a constant within this module's namespace.
|
589
|
+
///
|
580
590
|
/// @warning Modules defined this way will be never garbage-collected.
|
581
591
|
///
|
582
|
-
/// @param name Name of the module.
|
592
|
+
/// @param name Name of the module to define.
|
583
593
|
/// @return The newly defined module.
|
584
594
|
Module define_module(concepts::Identifier auto &&name) const;
|
585
595
|
|
586
|
-
/// Defines a class under this module.
|
596
|
+
/// Defines a class under this module with a specified superclass.
|
597
|
+
///
|
598
|
+
/// Creates a new class nested under this module with the given superclass.
|
599
|
+
/// The class will be accessible as a constant within this module's namespace.
|
587
600
|
///
|
588
601
|
/// @warning Classes defined this way will be never garbage-collected.
|
589
602
|
///
|
590
|
-
/// @
|
591
|
-
/// @
|
603
|
+
/// @tparam T The C++ type of the class.
|
604
|
+
/// @tparam S The C++ type of the superclass.
|
605
|
+
/// @param name Name of the class to define.
|
606
|
+
/// @param superclass The class that will serve as the superclass.
|
592
607
|
/// @return The newly defined class.
|
593
608
|
template <typename T = Value, typename S>
|
594
609
|
ClassT<T> define_class(concepts::Identifier auto &&name, ClassT<S> superclass) const;
|
595
610
|
|
596
|
-
/// Defines a
|
611
|
+
/// Defines a class under this module inheriting from Object.
|
612
|
+
///
|
613
|
+
/// Creates a new class nested under this module, with Object as the superclass.
|
614
|
+
/// The class will be accessible as a constant within this module's namespace.
|
597
615
|
///
|
598
616
|
/// @warning Classes defined this way will be never garbage-collected.
|
599
617
|
///
|
600
|
-
/// @
|
601
|
-
/// @
|
618
|
+
/// @tparam T The C++ type of the class.
|
619
|
+
/// @param name Name of the class to define.
|
620
|
+
/// @return The newly defined class.
|
602
621
|
template <typename T = Value> ClassT<T> define_class(concepts::Identifier auto &&name) const;
|
603
622
|
|
604
623
|
/// Defines an instance method.
|
@@ -639,7 +658,7 @@ namespace rcx {
|
|
639
658
|
|
640
659
|
/// Creates an anonymous module.
|
641
660
|
///
|
642
|
-
/// @return The newly created module.
|
661
|
+
/// @return The newly created anonymous module.
|
643
662
|
static Module new_module();
|
644
663
|
};
|
645
664
|
|
@@ -713,59 +732,142 @@ namespace rcx {
|
|
713
732
|
ClassT<T> define_copy_constructor() const
|
714
733
|
requires std::copy_constructible<T>;
|
715
734
|
|
716
|
-
/// Creates
|
735
|
+
/// Creates an anonymous class inheriting from Object.
|
736
|
+
///
|
737
|
+
/// Creates a new anonymous class that is not assigned to any constant,
|
738
|
+
/// with Object as the superclass. The class can be used dynamically
|
739
|
+
/// or assigned to constants later.
|
717
740
|
///
|
718
|
-
/// @return The newly created class.
|
741
|
+
/// @return The newly created anonymous class.
|
719
742
|
static Class new_class();
|
720
743
|
|
721
|
-
/// Creates
|
744
|
+
/// Creates an anonymous class with a specified superclass.
|
745
|
+
///
|
746
|
+
/// Creates a new anonymous class that is not assigned to any constant,
|
747
|
+
/// with the given class as the superclass. The class can be used dynamically
|
748
|
+
/// or assigned to constants later.
|
722
749
|
///
|
723
|
-
/// @
|
724
|
-
/// @
|
750
|
+
/// @tparam S The C++ type of the superclass.
|
751
|
+
/// @param superclass The class that will serve as the superclass.
|
752
|
+
/// @return The newly created anonymous class.
|
725
753
|
template <typename S> static ClassT<S> new_class(ClassT<S> superclass);
|
726
754
|
};
|
727
755
|
|
756
|
+
/// Represents a Ruby `Symbol`.
|
757
|
+
///
|
758
|
+
/// A `Symbol` object represents a name inside the Ruby interpreter.
|
728
759
|
class Symbol: public ValueT<Symbol, Value> {
|
729
760
|
public:
|
730
761
|
using ValueT<Symbol, Value>::ValueT;
|
731
|
-
|
762
|
+
|
763
|
+
/// Creates a `Symbol` from a C string literal.
|
764
|
+
///
|
765
|
+
/// @param s The C string literal.
|
766
|
+
template <size_t N> explicit Symbol(char const (&s)[N]) noexcept;
|
767
|
+
|
768
|
+
/// Creates a `Symbol` from a string view.
|
769
|
+
///
|
770
|
+
/// @param sv The string view.
|
732
771
|
explicit Symbol(std::string_view sv) noexcept;
|
733
772
|
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
*/
|
773
|
+
/// Returns Ruby-internal ID.
|
774
|
+
///
|
775
|
+
/// @warning The ID returned by this method may be dynamic and subject to garbage collection.
|
776
|
+
/// So do not store, whether on stack or in heap.
|
777
|
+
/// @return The Ruby-internal ID.
|
740
778
|
ID as_ID() const noexcept;
|
741
779
|
};
|
742
780
|
|
781
|
+
/// Represents a Ruby `String`.
|
782
|
+
///
|
743
783
|
class String: public ValueT<String, Value> {
|
744
784
|
public:
|
745
785
|
using ValueT<String, Value>::ValueT;
|
746
786
|
|
787
|
+
/// Creates a deduped frozen `String` from a C++ string-like object.
|
788
|
+
///
|
789
|
+
/// @param s The C++ string-like object.
|
790
|
+
/// @return The created deduped frozen `String`.
|
747
791
|
template <concepts::StringLike S> static String intern_from(S &&s);
|
792
|
+
|
793
|
+
/// Creates a deduped frozen `String` from a C string.
|
794
|
+
///
|
795
|
+
/// @param s The C string.
|
796
|
+
/// @return The created deduped frozen `String`.
|
748
797
|
template <concepts::CharLike CharT> static String intern_from(CharT const *RCX_Nonnull s);
|
798
|
+
|
799
|
+
/// Creates a mutable `String` from a C++ string-like object.
|
800
|
+
///
|
801
|
+
/// @param s The C++ string-like object.
|
802
|
+
/// @return The created mutable `String`.
|
749
803
|
template <concepts::StringLike S> static String copy_from(S &&s);
|
804
|
+
|
805
|
+
/// Creates a mutable `String` from a C string.
|
806
|
+
///
|
807
|
+
/// @param s The C string.
|
808
|
+
/// @return The created mutable `String`.
|
750
809
|
template <concepts::CharLike CharT> static String copy_from(CharT const *RCX_Nonnull s);
|
751
810
|
|
811
|
+
/// Returns the length of the string in octets.
|
812
|
+
///
|
813
|
+
/// @return The length of the string in octets.
|
752
814
|
size_t size() const noexcept;
|
815
|
+
|
816
|
+
/// Returns a mutable pointer to the string's content.
|
817
|
+
///
|
818
|
+
/// @return A mutable pointer to the string's content.
|
819
|
+
/// @throws FrozenError When the string is frozen.
|
753
820
|
char *RCX_Nonnull data() const;
|
821
|
+
|
822
|
+
/// Returns a const pointer to the string's content.
|
823
|
+
///
|
824
|
+
/// @return A const pointer to the string's content.
|
754
825
|
char const *RCX_Nonnull cdata() const noexcept;
|
826
|
+
|
827
|
+
/// Returns a string view of the string's content.
|
828
|
+
///
|
829
|
+
/// @return A string view of the string's content.
|
755
830
|
explicit operator std::string_view() const noexcept;
|
756
831
|
|
832
|
+
/// Locks the string to prevent it from being freed or relocated.
|
833
|
+
///
|
834
|
+
/// @return The locked string.
|
757
835
|
String lock() const;
|
836
|
+
|
837
|
+
/// Unlocks the string to allow it to be modified.
|
838
|
+
///
|
839
|
+
/// @return The unlocked string.
|
758
840
|
String unlock() const;
|
759
841
|
};
|
760
842
|
|
843
|
+
/// Represents a Ruby `Array`.
|
844
|
+
///
|
761
845
|
class Array: public ValueT<Array, Value> {
|
762
846
|
public:
|
763
847
|
using ValueT<Array, Value>::ValueT;
|
764
848
|
|
849
|
+
/// Returns the number of elements in the array.
|
850
|
+
///
|
851
|
+
/// @return The number of elements in the array.
|
765
852
|
size_t size() const noexcept;
|
853
|
+
|
854
|
+
/// Returns the element at the given index.
|
855
|
+
///
|
856
|
+
/// @tparam T The type to convert the element to.
|
857
|
+
/// @param i The index of the element.
|
858
|
+
/// @return The element at the given index.
|
766
859
|
template <concepts::ConvertibleFromValue T = Value> decltype(auto) at(size_t i) const;
|
860
|
+
|
861
|
+
/// Returns the element at the given index.
|
862
|
+
///
|
863
|
+
/// @param i The index of the element.
|
864
|
+
/// @return The element at the given index.
|
767
865
|
Value operator[](size_t i) const;
|
768
866
|
|
867
|
+
/// Creates a new `Array` from a contiguous range of values.
|
868
|
+
///
|
869
|
+
/// @param elements The contiguous range of values.
|
870
|
+
/// @return The new `Array`.
|
769
871
|
template <std::ranges::contiguous_range R>
|
770
872
|
#ifdef HAVE_STD_IS_LAYOUT_COMPATIBLE
|
771
873
|
requires std::is_layout_compatible_v<std::ranges::range_value_t<R>, ValueBase>
|
@@ -775,38 +877,131 @@ namespace rcx {
|
|
775
877
|
#endif
|
776
878
|
static Array new_from(R const &elements);
|
777
879
|
|
880
|
+
/// Creates a new `Array` from an initializer list of values.
|
881
|
+
///
|
882
|
+
/// @param elements The initializer list of values.
|
883
|
+
/// @return The new `Array`.
|
778
884
|
static Array new_from(std::initializer_list<ValueBase> elements);
|
779
885
|
|
886
|
+
/// Creates a new `Array` from a tuple of values.
|
887
|
+
///
|
888
|
+
/// @param elements The tuple of values.
|
889
|
+
/// @return The new `Array`.
|
780
890
|
template <std::derived_from<ValueBase>... T>
|
781
891
|
static Array new_from(std::tuple<T...> const &elements);
|
782
892
|
|
893
|
+
/// Creates a new empty `Array`.
|
894
|
+
///
|
895
|
+
/// @return The new empty `Array`.
|
783
896
|
static Array new_array();
|
897
|
+
|
898
|
+
/// Creates a new empty `Array` with the given capacity.
|
899
|
+
///
|
900
|
+
/// @param capacity The capacity of the new `Array`.
|
901
|
+
/// @return The new empty `Array`.
|
784
902
|
static Array new_array(long capacity);
|
785
903
|
|
904
|
+
/// Appends a value to the end of the array.
|
905
|
+
///
|
906
|
+
/// @param value The value to append.
|
907
|
+
/// @return The array itself.
|
786
908
|
template <concepts::ConvertibleIntoValue T = Value> Array push_back(T value) const;
|
909
|
+
|
910
|
+
/// Removes and returns the last element of the array.
|
911
|
+
///
|
912
|
+
/// @tparam T The type to convert the element to.
|
913
|
+
/// @return The last element of the array.
|
787
914
|
template <concepts::ConvertibleFromValue T = Value> T pop_back() const;
|
915
|
+
|
916
|
+
/// Prepends a value to the beginning of the array.
|
917
|
+
///
|
918
|
+
/// @param value The value to prepend.
|
919
|
+
/// @return The array itself.
|
788
920
|
template <concepts::ConvertibleIntoValue T = Value> Array push_front(T value) const;
|
921
|
+
|
922
|
+
/// Removes and returns the first element of the array.
|
923
|
+
///
|
924
|
+
/// @tparam T The type to convert the element to.
|
925
|
+
/// @return The first element of the array.
|
789
926
|
template <concepts::ConvertibleFromValue T = Value> T pop_front() const;
|
790
927
|
};
|
791
928
|
|
929
|
+
/// Represents a Ruby `Proc`.
|
930
|
+
///
|
792
931
|
class Proc: public ValueT<Proc, Value> {
|
793
932
|
public:
|
794
933
|
using ValueT<Proc, Value>::ValueT;
|
795
934
|
|
935
|
+
/// Checks if this `Proc` is a lambda.
|
936
|
+
///
|
937
|
+
/// @return `true` if this `Proc` is a lambda, `false` otherwise.
|
796
938
|
bool is_lambda() const;
|
939
|
+
|
940
|
+
/// Calls this `Proc` with the given arguments.
|
941
|
+
///
|
942
|
+
/// @param args The arguments to pass to the `Proc`.
|
943
|
+
/// @return The result of calling the `Proc`.
|
797
944
|
Value call(Array args) const;
|
798
945
|
};
|
799
946
|
|
947
|
+
/// Represents a Ruby exception.
|
948
|
+
///
|
949
|
+
/// This class provides functionality for creating and formatting exceptions in Ruby.
|
800
950
|
class Exception: public ValueT<Exception, Value> {
|
801
951
|
public:
|
802
952
|
using ValueT<Exception, Value>::ValueT;
|
803
953
|
|
954
|
+
/// Creates a formatted exception of the specified type.
|
955
|
+
///
|
956
|
+
/// This method creates an exception instance with a formatted message using C++20 std::format
|
957
|
+
/// syntax. The message is created as a frozen string and passed to the exception constructor.
|
958
|
+
///
|
959
|
+
/// @tparam E The type of exception class (must be derived from Exception).
|
960
|
+
/// @tparam Args The argument types for the format string.
|
961
|
+
/// @param cls The exception class to instantiate.
|
962
|
+
/// @param fmt The format string (follows std::format syntax).
|
963
|
+
/// @param args The arguments to format into the string.
|
964
|
+
/// @return A new exception instance with the formatted message.
|
804
965
|
template <std::derived_from<Exception> E, typename... Args>
|
805
966
|
static E format(ClassT<E> cls, std::format_string<Args...> fmt, Args &&...args);
|
967
|
+
|
968
|
+
/// Creates a `SystemCallError` from an errno value.
|
969
|
+
///
|
970
|
+
/// This method creates a SystemCallError exception based on the provided errno value.
|
971
|
+
/// The errno is converted to an appropriate Ruby exception message automatically.
|
972
|
+
///
|
973
|
+
/// @param message An optional message to be appended to the error message.
|
974
|
+
/// @param err The errno value (defaults to the current errno).
|
975
|
+
/// @return The newly created `SystemCallError`.
|
976
|
+
static Exception new_from_errno(char const *RCX_Nullable message = nullptr, int err = errno);
|
977
|
+
};
|
978
|
+
|
979
|
+
/// Represents a Ruby `IO`.
|
980
|
+
///
|
981
|
+
class IO: public ValueT<IO, Value> {
|
982
|
+
public:
|
983
|
+
using ValueT<IO, Value>::ValueT;
|
984
|
+
|
985
|
+
/// The file descriptor of the IO object.
|
986
|
+
///
|
987
|
+
/// @return The file descriptor.
|
988
|
+
/// @throws IOError If file IO object is closed.
|
989
|
+
int descriptor() const;
|
990
|
+
|
991
|
+
/// Checks if the IO object is opened for reading.
|
992
|
+
///
|
993
|
+
/// @throws IOError If the IO object is not readable.
|
994
|
+
void check_readable() const;
|
995
|
+
|
996
|
+
/// Checks if the IO object is opened for writing.
|
997
|
+
///
|
998
|
+
/// @throws IOError If the IO object is not writable.
|
999
|
+
void check_writable() const;
|
806
1000
|
};
|
807
1001
|
|
808
1002
|
#ifdef RCX_IO_BUFFER
|
809
1003
|
/// Represents an `IO::Buffer` object.
|
1004
|
+
///
|
810
1005
|
class IOBuffer: public ValueT<IOBuffer, Value> {
|
811
1006
|
public:
|
812
1007
|
using ValueT<IOBuffer, Value>::ValueT;
|
@@ -958,6 +1153,10 @@ namespace rcx {
|
|
958
1153
|
///
|
959
1154
|
inline value::ClassT<value::Exception> const Exception =
|
960
1155
|
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eException);
|
1156
|
+
/// `StandardError` class
|
1157
|
+
///
|
1158
|
+
inline value::ClassT<value::Exception> const StandardError =
|
1159
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eStandardError);
|
961
1160
|
/// `SystemExit` class
|
962
1161
|
///
|
963
1162
|
inline value::ClassT<value::Exception> const SystemExit =
|
@@ -970,30 +1169,22 @@ namespace rcx {
|
|
970
1169
|
///
|
971
1170
|
inline value::ClassT<value::Exception> const SignalException =
|
972
1171
|
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eSignal);
|
973
|
-
/// `StandardError` class
|
974
|
-
///
|
975
|
-
inline value::ClassT<value::Exception> const StandardError =
|
976
|
-
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eStandardError);
|
977
|
-
/// `RuntimeError` class
|
978
|
-
///
|
979
|
-
inline value::ClassT<value::Exception> const RuntimeError =
|
980
|
-
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eRuntimeError);
|
981
|
-
/// `FrozenError` class
|
982
|
-
///
|
983
|
-
inline value::ClassT<value::Exception> const FrozenError =
|
984
|
-
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eFrozenError);
|
985
|
-
/// `TypeError` class
|
986
|
-
///
|
987
|
-
inline value::ClassT<value::Exception> const TypeError =
|
988
|
-
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eTypeError);
|
989
1172
|
/// `ArgumentError` class
|
990
1173
|
///
|
991
1174
|
inline value::ClassT<value::Exception> const ArgumentError =
|
992
1175
|
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eArgError);
|
1176
|
+
/// `EOFError` class
|
1177
|
+
///
|
1178
|
+
inline value::ClassT<value::Exception> const EOFError =
|
1179
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eEOFError);
|
993
1180
|
/// `IndexError` class
|
994
1181
|
///
|
995
1182
|
inline value::ClassT<value::Exception> const IndexError =
|
996
1183
|
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eIndexError);
|
1184
|
+
/// `StopIteration` class
|
1185
|
+
///
|
1186
|
+
inline value::ClassT<value::Exception> const StopIteration =
|
1187
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eStopIteration);
|
997
1188
|
/// `KeyError` class
|
998
1189
|
///
|
999
1190
|
inline value::ClassT<value::Exception> const KeyError =
|
@@ -1002,26 +1193,38 @@ namespace rcx {
|
|
1002
1193
|
///
|
1003
1194
|
inline value::ClassT<value::Exception> const RangeError =
|
1004
1195
|
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eRangeError);
|
1005
|
-
/// `
|
1006
|
-
///
|
1007
|
-
inline value::ClassT<value::Exception> const NameError =
|
1008
|
-
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eNameError);
|
1009
|
-
/// `EncodingError` class
|
1196
|
+
/// `IOError` class
|
1010
1197
|
///
|
1011
|
-
inline value::ClassT<value::Exception> const
|
1012
|
-
detail::unsafe_coerce<value::ClassT<value::Exception>>(::
|
1013
|
-
/// `
|
1198
|
+
inline value::ClassT<value::Exception> const IOError =
|
1199
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eIOError);
|
1200
|
+
/// `RuntimeError` class
|
1014
1201
|
///
|
1015
|
-
inline value::ClassT<value::Exception> const
|
1016
|
-
detail::unsafe_coerce<value::ClassT<value::Exception>>(::
|
1017
|
-
/// `
|
1202
|
+
inline value::ClassT<value::Exception> const RuntimeError =
|
1203
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eRuntimeError);
|
1204
|
+
/// `FrozenError` class
|
1018
1205
|
///
|
1019
|
-
inline value::ClassT<value::Exception> const
|
1020
|
-
detail::unsafe_coerce<value::ClassT<value::Exception>>(::
|
1206
|
+
inline value::ClassT<value::Exception> const FrozenError =
|
1207
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eFrozenError);
|
1021
1208
|
/// `SecurityError` class
|
1022
1209
|
///
|
1023
1210
|
inline value::ClassT<value::Exception> const SecurityError =
|
1024
1211
|
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eSecurityError);
|
1212
|
+
/// `SystemCallError` class
|
1213
|
+
///
|
1214
|
+
inline value::ClassT<value::Exception> const SystemCallError =
|
1215
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eSystemCallError);
|
1216
|
+
/// `ThreadError` class
|
1217
|
+
///
|
1218
|
+
inline value::ClassT<value::Exception> const ThreadError =
|
1219
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eThreadError);
|
1220
|
+
/// `TypeError` class
|
1221
|
+
///
|
1222
|
+
inline value::ClassT<value::Exception> const TypeError =
|
1223
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eTypeError);
|
1224
|
+
/// `ZeroDivisionError` class
|
1225
|
+
///
|
1226
|
+
inline value::ClassT<value::Exception> const ZeroDivisionError =
|
1227
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eZeroDivError);
|
1025
1228
|
/// `NotImplementedError` class
|
1026
1229
|
///
|
1027
1230
|
inline value::ClassT<value::Exception> const NotImplementedError =
|
@@ -1030,6 +1233,34 @@ namespace rcx {
|
|
1030
1233
|
///
|
1031
1234
|
inline value::ClassT<value::Exception> const NoMemoryError =
|
1032
1235
|
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eNoMemError);
|
1236
|
+
/// `NoMethodError` class
|
1237
|
+
///
|
1238
|
+
inline value::ClassT<value::Exception> const NoMethodError =
|
1239
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eNoMethodError);
|
1240
|
+
/// `FloatDomainError` class
|
1241
|
+
///
|
1242
|
+
inline value::ClassT<value::Exception> const FloatDomainError =
|
1243
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eFloatDomainError);
|
1244
|
+
/// `LocalJumpError` class
|
1245
|
+
///
|
1246
|
+
inline value::ClassT<value::Exception> const LocalJumpError =
|
1247
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eLocalJumpError);
|
1248
|
+
/// `SystemStackError` class
|
1249
|
+
///
|
1250
|
+
inline value::ClassT<value::Exception> const SystemStackError =
|
1251
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eSysStackError);
|
1252
|
+
/// `RegexpError` class
|
1253
|
+
///
|
1254
|
+
inline value::ClassT<value::Exception> const RegexpError =
|
1255
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eRegexpError);
|
1256
|
+
/// `EncodingError` class
|
1257
|
+
///
|
1258
|
+
inline value::ClassT<value::Exception> const EncodingError =
|
1259
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eEncodingError);
|
1260
|
+
/// `Encoding::CompatibilityError` class
|
1261
|
+
///
|
1262
|
+
inline value::ClassT<value::Exception> const EncodingCompatibilityError =
|
1263
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eEncCompatError);
|
1033
1264
|
/// `NoMatchingPatternError` class
|
1034
1265
|
///
|
1035
1266
|
inline value::ClassT<value::Exception> const NoMatchingPatternError =
|
@@ -1042,6 +1273,10 @@ namespace rcx {
|
|
1042
1273
|
///
|
1043
1274
|
inline value::ClassT<value::Exception> const ScriptError =
|
1044
1275
|
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eScriptError);
|
1276
|
+
/// `NameError` class
|
1277
|
+
///
|
1278
|
+
inline value::ClassT<value::Exception> const NameError =
|
1279
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eNameError);
|
1045
1280
|
/// `SyntaxError` class
|
1046
1281
|
///
|
1047
1282
|
inline value::ClassT<value::Exception> const SyntaxError =
|
@@ -1050,10 +1285,10 @@ namespace rcx {
|
|
1050
1285
|
///
|
1051
1286
|
inline value::ClassT<value::Exception> const LoadError =
|
1052
1287
|
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eLoadError);
|
1053
|
-
/// `
|
1288
|
+
/// `Math::DomainError` class
|
1054
1289
|
///
|
1055
|
-
inline value::ClassT<value::Exception> const
|
1056
|
-
detail::unsafe_coerce<value::ClassT<value::Exception>>(::
|
1290
|
+
inline value::ClassT<value::Exception> const MathDomainError =
|
1291
|
+
detail::unsafe_coerce<value::ClassT<value::Exception>>(::rb_eMathDomainError);
|
1057
1292
|
|
1058
1293
|
#ifdef RCX_IO_BUFFER
|
1059
1294
|
/// `IO::Buffer` class
|
@@ -1224,27 +1459,67 @@ namespace rcx {
|
|
1224
1459
|
};
|
1225
1460
|
template <std::derived_from<ValueBase> T> Leak(T) -> Leak<T>;
|
1226
1461
|
|
1462
|
+
/// Provides access to Ruby's environment.
|
1463
|
+
///
|
1227
1464
|
class Ruby {
|
1465
|
+
private:
|
1466
|
+
Ruby() = default;
|
1467
|
+
|
1228
1468
|
public:
|
1469
|
+
/// Defines a module at the top level.
|
1470
|
+
///
|
1471
|
+
/// Creates a new module under Ruby's Object class. The module will be accessible
|
1472
|
+
/// as a top-level constant in Ruby code.
|
1473
|
+
///
|
1474
|
+
/// @warning Modules defined this way will be never garbage-collected.
|
1475
|
+
///
|
1476
|
+
/// @param name Name of the module to define.
|
1477
|
+
/// @return The newly defined module.
|
1229
1478
|
Module define_module(concepts::Identifier auto &&name);
|
1230
1479
|
|
1480
|
+
/// Defines a class at the top level with a specified superclass.
|
1481
|
+
///
|
1482
|
+
/// Creates a new class under Ruby's Object class with the given superclass.
|
1483
|
+
/// The class will be accessible as a top-level constant in Ruby code.
|
1484
|
+
///
|
1485
|
+
/// @warning Classes defined this way will be never garbage-collected.
|
1486
|
+
///
|
1487
|
+
/// @tparam T The C++ type of the class.
|
1488
|
+
/// @tparam S The C++ type of the superclass.
|
1489
|
+
/// @param name Name of the class to define.
|
1490
|
+
/// @param superclass The class that will serve as the superclass.
|
1491
|
+
/// @return The newly defined class.
|
1231
1492
|
template <typename T = Value, typename S>
|
1232
1493
|
ClassT<T> define_class(concepts::Identifier auto &&name, ClassT<S> superclass);
|
1233
1494
|
|
1495
|
+
/// Defines a class at the top level inheriting from Object.
|
1496
|
+
///
|
1497
|
+
/// Creates a new class under Ruby's Object class, with Object as the superclass.
|
1498
|
+
/// The class will be accessible as a top-level constant in Ruby code.
|
1499
|
+
///
|
1500
|
+
/// @warning Classes defined this way will be never garbage-collected.
|
1501
|
+
///
|
1502
|
+
/// @tparam T The C++ type of the class.
|
1503
|
+
/// @param name Name of the class to define.
|
1504
|
+
/// @return The newly defined class.
|
1234
1505
|
template <typename T = Value> ClassT<T> define_class(concepts::Identifier auto &&name);
|
1235
|
-
};
|
1236
1506
|
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1507
|
+
/// Gets the Ruby environment without GVL checking.
|
1508
|
+
///
|
1509
|
+
/// @warning This method bypasses GVL checking and should only be used
|
1510
|
+
/// when you are certain the GVL is held or when calling from Ruby callbacks.
|
1511
|
+
/// @return Reference to the Ruby environment instance.
|
1512
|
+
static Ruby &unsafe_get();
|
1513
|
+
|
1514
|
+
/// Gets the Ruby environment with GVL checking.
|
1515
|
+
///
|
1516
|
+
/// This method asserts that the Global VM Lock is held before returning
|
1517
|
+
/// the Ruby environment instance. This is the recommended way to access
|
1518
|
+
/// the Ruby environment from C++ code.
|
1519
|
+
///
|
1520
|
+
/// @return Reference to the Ruby environment instance.
|
1521
|
+
static Ruby &get();
|
1522
|
+
};
|
1248
1523
|
}
|
1249
1524
|
|
1250
1525
|
namespace std {
|
@@ -13,6 +13,7 @@
|
|
13
13
|
|
14
14
|
#include <ffi.h>
|
15
15
|
#include <rcx/internal/rcx.hpp>
|
16
|
+
#include <ruby/io.h>
|
16
17
|
|
17
18
|
#if HAVE_CXXABI_H
|
18
19
|
#include <cxxabi.h>
|
@@ -119,12 +120,12 @@ namespace rcx {
|
|
119
120
|
template <typename F> static NativeRbFunc *RCX_Nonnull alloc(F &&function) {
|
120
121
|
return alloc_callback([function](std::span<Value> args, Value self) -> Value {
|
121
122
|
Parser<ArgSpec...> parser{args, self};
|
122
|
-
using Result = decltype(parser.parse(
|
123
|
+
using Result = decltype(parser.parse(Ruby::unsafe_get(), std::move(function)));
|
123
124
|
if constexpr(std::is_void_v<Result>) {
|
124
|
-
parser.parse(
|
125
|
+
parser.parse(Ruby::unsafe_get(), std::move(function));
|
125
126
|
return {};
|
126
127
|
} else {
|
127
|
-
return into_Value<Result>(parser.parse(
|
128
|
+
return into_Value<Result>(parser.parse(Ruby::unsafe_get(), function));
|
128
129
|
}
|
129
130
|
});
|
130
131
|
}
|
@@ -955,7 +956,7 @@ namespace rcx {
|
|
955
956
|
return std::string_view(from_Value<String>(value));
|
956
957
|
}
|
957
958
|
|
958
|
-
|
959
|
+
// Proc
|
959
960
|
|
960
961
|
namespace value {
|
961
962
|
inline bool Proc::is_lambda() const {
|
@@ -980,7 +981,7 @@ namespace rcx {
|
|
980
981
|
};
|
981
982
|
}
|
982
983
|
|
983
|
-
|
984
|
+
// Exception
|
984
985
|
|
985
986
|
namespace value {
|
986
987
|
template <std::derived_from<Exception> E, typename... Args>
|
@@ -988,6 +989,10 @@ namespace rcx {
|
|
988
989
|
auto const msg = std::vformat(fmt.get(), std::make_format_args(args...));
|
989
990
|
return cls.new_instance(String::intern_from(msg));
|
990
991
|
}
|
992
|
+
|
993
|
+
inline Exception Exception::new_from_errno(char const *RCX_Nullable message, int err) {
|
994
|
+
return detail::unsafe_coerce<Exception>(rb_syserr_new(err, message));
|
995
|
+
}
|
991
996
|
}
|
992
997
|
|
993
998
|
namespace convert {
|
@@ -1000,6 +1005,40 @@ namespace rcx {
|
|
1000
1005
|
}
|
1001
1006
|
}
|
1002
1007
|
|
1008
|
+
// IO
|
1009
|
+
|
1010
|
+
namespace value {
|
1011
|
+
inline int IO::descriptor() const {
|
1012
|
+
return detail::protect([this]() noexcept { return rb_io_descriptor(as_VALUE()); });
|
1013
|
+
}
|
1014
|
+
|
1015
|
+
inline void IO::check_readable() const {
|
1016
|
+
return detail::protect([this]() noexcept {
|
1017
|
+
rb_io_t *pio;
|
1018
|
+
RB_IO_POINTER(as_VALUE(), pio);
|
1019
|
+
rb_io_check_readable(pio);
|
1020
|
+
});
|
1021
|
+
}
|
1022
|
+
|
1023
|
+
inline void IO::check_writable() const {
|
1024
|
+
return detail::protect([this]() noexcept {
|
1025
|
+
rb_io_t *pio;
|
1026
|
+
RB_IO_POINTER(as_VALUE(), pio);
|
1027
|
+
rb_io_check_writable(pio);
|
1028
|
+
});
|
1029
|
+
}
|
1030
|
+
}
|
1031
|
+
|
1032
|
+
namespace convert {
|
1033
|
+
inline IO FromValue<IO>::convert(Value value) {
|
1034
|
+
if(!value.is_kind_of(builtin::IO)) {
|
1035
|
+
throw Exception::format(
|
1036
|
+
builtin::TypeError, "Expected an IO but got a {}", value.get_class());
|
1037
|
+
}
|
1038
|
+
return detail::unsafe_coerce<IO>(value.as_VALUE());
|
1039
|
+
}
|
1040
|
+
}
|
1041
|
+
|
1003
1042
|
#ifdef RCX_IO_BUFFER
|
1004
1043
|
/// IOBuffer
|
1005
1044
|
namespace value {
|
@@ -1319,6 +1358,18 @@ namespace rcx {
|
|
1319
1358
|
return define_class<T>(std::forward<decltype(name)>(name), builtin::Object);
|
1320
1359
|
}
|
1321
1360
|
|
1361
|
+
inline Ruby &Ruby::unsafe_get() {
|
1362
|
+
static Ruby ruby = {};
|
1363
|
+
return ruby;
|
1364
|
+
}
|
1365
|
+
|
1366
|
+
inline Ruby &Ruby::get() {
|
1367
|
+
#ifdef HAVE_RUBY_THREAD_HAS_GVL_P
|
1368
|
+
rcx_assert(::ruby_thread_has_gvl_p() && "GVL must be held when calling Ruby APIs");
|
1369
|
+
#endif
|
1370
|
+
return unsafe_get();
|
1371
|
+
}
|
1372
|
+
|
1322
1373
|
namespace detail {
|
1323
1374
|
inline std::string demangle_type_info(std::type_info const &ti) {
|
1324
1375
|
if constexpr(have_abi_cxa_demangle) {
|
data/lib/rcx/mkmf.rb
CHANGED
data/lib/rcx/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rcx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kasumi Hanazuki
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: shellwords
|
@@ -68,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '0'
|
70
70
|
requirements: []
|
71
|
-
rubygems_version: 3.7
|
71
|
+
rubygems_version: 3.6.7
|
72
72
|
specification_version: 4
|
73
73
|
summary: Write Ruby extension in modern C++
|
74
74
|
test_files: []
|