Created
September 17, 2008 17:47
-
-
Save rue/11263 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef RBX_BUILTIN_NATIVEMETHOD_HPP | |
| #define RBX_BUILTIN_NATIVEMETHOD_HPP | |
| /* Project */ | |
| #include "builtin/class.hpp" | |
| #include "builtin/executable.hpp" | |
| #include "builtin/task.hpp" | |
| #include "vm.hpp" | |
| #include "vmnativemethod.hpp" | |
| #include "builtin/nativemethodcontext.hpp" | |
| namespace rubinius { | |
| class Message; | |
| /** | |
| * The various special method arities from a | |
| * C method. If not one of these, then the | |
| * number denotes the exact number of args | |
| * in addition to the receiver instead. | |
| */ | |
| enum Arity { | |
| ARGS_IN_RUBY_ARRAY = -3, | |
| RECEIVER_PLUS_ARGS_IN_RUBY_ARRAY = -2, | |
| ARG_COUNT_ARGS_IN_C_ARRAY_PLUS_RECEIVER = -1 | |
| }; | |
| /* The various function signatures needed since C++ requires strict typing here. */ | |
| /** Generic function pointer used to store any type of functor. */ | |
| typedef void (*GenericFunctor)(void); | |
| /* Actual functor types. */ | |
| typedef HandleTo (*ArgcFunctor) (int, HandleTo*, HandleTo); | |
| typedef HandleTo (*OneArgFunctor) (HandleTo); | |
| typedef HandleTo (*TwoArgFunctor) (HandleTo, HandleTo); | |
| typedef HandleTo (*ThreeArgFunctor) (HandleTo, HandleTo, HandleTo); | |
| typedef HandleTo (*FourArgFunctor) (HandleTo, HandleTo, HandleTo, HandleTo); | |
| typedef HandleTo (*FiveArgFunctor) (HandleTo, HandleTo, HandleTo, HandleTo, HandleTo); | |
| typedef HandleTo (*SixArgFunctor) (HandleTo, HandleTo, HandleTo, HandleTo, HandleTo, HandleTo); | |
| /** | |
| * Ruby side of a NativeMethod, i.e. a C-implemented method. | |
| * | |
| * The possible signatures for the C function are: | |
| * | |
| * VALUE func(VALUE argument_array); | |
| * VALUE func(VALUE receiver, VALUE argument_array); | |
| * VALUE func(VALUE receiver, int argument_count, VALUE*); | |
| * VALUE func(VALUE receiver, ...); // Some limited number of VALUE arguments | |
| * | |
| * VALUE is an opaque type from which a handle to the actual object | |
| * can be extracted. User code never operates on the VALUE itself. | |
| * | |
| * TODO: Add tests. | |
| */ | |
| class NativeMethod : public Executable { | |
| public: /* Ctors */ | |
| /** | |
| * Create a NativeMethod object. | |
| * | |
| * May take one of several types of functors but the calling | |
| * code is responsible for figuring out which type to cast | |
| * the functor back to for use, that information is not | |
| * stored here. | |
| * | |
| * @see functor_as() for the cast back. | |
| */ | |
| template <typename FunctorType> | |
| static NativeMethod* create(VM* state, FunctorType functor = static_cast<GenericFunctor>(NULL), int arity = 0) | |
| { | |
| NativeMethod* obj = static_cast<NativeMethod*>(state->new_object(state->globals.nmethod.get())); | |
| obj->arity(state, Fixnum::from(arity)); | |
| obj->my_functor = reinterpret_cast<GenericFunctor>(functor); | |
| return obj; | |
| } | |
| /** | |
| * Allocate a functional but empty NativeMethod. | |
| */ | |
| static NativeMethod* allocate(VM* state) | |
| { | |
| return create<GenericFunctor>(state); | |
| } | |
| public: /* Accessors */ | |
| /** Arity of the method within. @see Arity. */ | |
| attr_accessor(arity, Fixnum); | |
| public: /* Interface */ | |
| /** | |
| * Start running the C method. | |
| */ | |
| bool execute(VM* state, Task* task, Message& message) | |
| { | |
| return VMNativeMethod::execute(state, task, &message, this); | |
| } | |
| /** | |
| * Return the functor cast into the specified type. | |
| */ | |
| template <typename FunctorType> | |
| FunctorType functor_as() const | |
| { | |
| return reinterpret_cast<FunctorType>(my_functor); | |
| } | |
| public: /* Ruby bookkeeping */ | |
| /** Size in Object*'s. Executable + 2. */ | |
| const static size_t fields = 5; | |
| /** Statically held object type. */ | |
| const static object_type type = NMethodType; | |
| /** | |
| * Set class up in the VM. @see vm/ontology.cpp. | |
| */ | |
| static void register_class_with(VM* state) | |
| { | |
| state->globals.nmethod.set(state->new_class("NativeMethod", state->globals.executable.get(), NativeMethod::fields)); | |
| state->globals.nmethod.get()->set_object_type(state, NMethodType); | |
| } | |
| private: /* Slots */ | |
| /** Arity of the method. @see Arity. */ | |
| Fixnum* arity_; // slot | |
| private: /* Instance variables */ | |
| /** Function object that implements this method. */ | |
| GenericFunctor my_functor; | |
| public: /* Type information */ | |
| /** Type information for NativeMethod. */ | |
| class Info : public Executable::Info { | |
| public: | |
| BASIC_TYPEINFO(Executable::Info) | |
| }; | |
| }; /* NativeMethod */ | |
| } | |
| #endif | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment