290 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			290 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | #ifndef INCLUDED_HX_SCRIPTABLE
 | ||
|  | #define INCLUDED_HX_SCRIPTABLE
 | ||
|  | 
 | ||
|  | #include <typeinfo>
 | ||
|  | #ifdef __clang__
 | ||
|  | #pragma clang diagnostic ignored "-Winvalid-offsetof"
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 
 | ||
|  | namespace hx | ||
|  | { | ||
|  | 
 | ||
|  | extern bool gEnableJit; | ||
|  | inline void EnableJit(bool inEnable) { gEnableJit = inEnable; } | ||
|  | 
 | ||
|  | #define HXCPP_CPPIA_SUPER_ARG(x) , (x)
 | ||
|  | 
 | ||
|  | struct ScriptNamedFunction : public ScriptFunction | ||
|  | { | ||
|  |    ScriptNamedFunction(const ScriptFunction &s) : ScriptFunction(s), name(0), isStatic(false), superExecute(0) { } | ||
|  | 
 | ||
|  |    ScriptNamedFunction(const char *inName=0,StackExecute inExe=0,const char *inSig=0, bool inIsStatic=false, StackExecute superExecute=0) | ||
|  |       : ScriptFunction(inExe, inSig), name(inName), isStatic(inIsStatic), superExecute(superExecute)  { } | ||
|  | 
 | ||
|  |    const char *name; | ||
|  |    bool isStatic; | ||
|  |    StackExecute superExecute; | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | inline void SetFloatAligned(void *inPtr, const Float &inValue) | ||
|  | { | ||
|  |    #ifdef HXCPP_ALIGN_FLOAT
 | ||
|  |    int *dest = (int *)inPtr; | ||
|  |    const int *src = (const int *)&inValue; | ||
|  |    dest[1] = src[1]; | ||
|  |    #else
 | ||
|  |    *(Float *)inPtr = inValue; | ||
|  |    #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | inline Float GetFloatAligned(const void *inPtr) | ||
|  | { | ||
|  |    #ifdef HXCPP_ALIGN_FLOAT
 | ||
|  |    Float result; | ||
|  |    int *dest = (int *)&result; | ||
|  |    const int *src = (const int *)inPtr; | ||
|  |    dest[0] = src[0]; | ||
|  |    dest[1] = src[1]; | ||
|  |    return result; | ||
|  |    #else
 | ||
|  |    return *(Float *)inPtr; | ||
|  |    #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | inline void StackContext::pushFloat(Float f) | ||
|  | { | ||
|  |    SetFloatAligned(pointer, f); | ||
|  |    pointer += sizeof(Float); | ||
|  | } | ||
|  | inline void StackContext::pushString(const String &s) | ||
|  | { | ||
|  |    *(String *)pointer = s; | ||
|  |    pointer += sizeof(String); | ||
|  | } | ||
|  | 
 | ||
|  | inline void StackContext::pushObject(Dynamic d) | ||
|  | { | ||
|  |    *(hx::Object **)pointer = d.mPtr; | ||
|  |    pointer += sizeof(hx::Object *); | ||
|  | } | ||
|  | 
 | ||
|  | inline void StackContext::returnFloat(Float f) | ||
|  | { | ||
|  |    SetFloatAligned(frame, f); | ||
|  | } | ||
|  | inline void StackContext::returnString(const String &s) | ||
|  | { | ||
|  |    *(String *)frame = s; | ||
|  | } | ||
|  | inline void StackContext::returnObject(Dynamic d) | ||
|  | { | ||
|  |    *(hx::Object **)frame = d.mPtr; | ||
|  | } | ||
|  | 
 | ||
|  | inline hx::Object *StackContext::getThis(bool inCheckPtr) | ||
|  | { | ||
|  |    #ifdef HXCPP_CHECK_POINTER
 | ||
|  |       if (inCheckPtr) | ||
|  |       { | ||
|  |          if (!*(hx::Object **)frame) NullReference("This", false); | ||
|  |          #ifdef HXCPP_GC_CHECK_POINTER
 | ||
|  |          GCCheckPointer(*(hx::Object **)frame); | ||
|  |          #endif
 | ||
|  |       } | ||
|  |    #endif
 | ||
|  |    return *(hx::Object **)frame; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | inline Float StackContext::getFloat(int inPos) | ||
|  | { | ||
|  |    return GetFloatAligned(frame+inPos); | ||
|  | } | ||
|  | inline String StackContext::getString(int inPos) | ||
|  | { | ||
|  |    return *(String *)(frame+inPos); | ||
|  | } | ||
|  | inline Dynamic StackContext::getObject(int inPos) | ||
|  | { | ||
|  |    return *(hx::Object **)(frame+inPos); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | enum SignatureChar | ||
|  | { | ||
|  |    sigVoid = 'v', | ||
|  |    sigBool = 'b', | ||
|  |    sigInt = 'i', | ||
|  |    sigFloat = 'f', | ||
|  |    sigString = 's', | ||
|  |    sigObject = 'o', | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | struct AutoStack | ||
|  | { | ||
|  |    CppiaCtx *ctx; | ||
|  |    unsigned char *pointer; | ||
|  |    unsigned char *frame; | ||
|  | 
 | ||
|  |    AutoStack(CppiaCtx *inCtx) : ctx(inCtx) | ||
|  |    { | ||
|  |       frame = ctx->frame; | ||
|  |       pointer = ctx->pointer; | ||
|  |       ctx->frame = pointer; | ||
|  |    } | ||
|  |    AutoStack(CppiaCtx *inCtx,unsigned char *inPointer) : ctx(inCtx) | ||
|  |    { | ||
|  |       frame = ctx->frame; | ||
|  |       pointer = inPointer; | ||
|  |       ctx->frame = pointer; | ||
|  |    } | ||
|  | 
 | ||
|  |    ~AutoStack() | ||
|  |    { | ||
|  |       ctx->pointer = pointer; | ||
|  |       ctx->frame = frame; | ||
|  |    } | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | typedef hx::Object * (*ScriptableClassFactory)(void **inVTable,int inDataSize); | ||
|  | typedef hx::Object * (*ScriptableInterfaceFactory)(void **inVTable,::hx::Object *); | ||
|  | 
 | ||
|  | void ScriptableRegisterClass( String inName, int inBaseSize, ScriptNamedFunction *inFunctions, ScriptableClassFactory inFactory, ScriptFunction inConstruct); | ||
|  | 
 | ||
|  | 
 | ||
|  | #if (HXCPP_API_LEVEL >= 330)
 | ||
|  | void ScriptableRegisterInterface( String inName, ScriptNamedFunction *inFunctions, void *inInterfacePointers); | ||
|  | void ScriptableRegisterNameSlots(const char *inNames[], int inLength); | ||
|  | 
 | ||
|  | #else
 | ||
|  | void ScriptableRegisterInterface( String inName, ScriptNamedFunction *inFunctions,const hx::type_info *inType, ScriptableInterfaceFactory inFactory); | ||
|  | #endif
 | ||
|  | 
 | ||
|  | ::String ScriptableToString(void *); | ||
|  | hx::Class ScriptableGetClass(void *); | ||
|  | int ScriptableGetType(void *); | ||
|  | void ScriptableMark(void *, hx::Object *, HX_MARK_PARAMS); | ||
|  | void ScriptableVisit(void *, hx::Object *, HX_VISIT_PARAMS); | ||
|  | bool ScriptableField(hx::Object *, const ::String &,hx::PropertyAccess inCallProp,Dynamic &outResult); | ||
|  | bool ScriptableField(hx::Object *, int inName,hx::PropertyAccess inCallProp,Float &outResult); | ||
|  | bool ScriptableField(hx::Object *, int inName,hx::PropertyAccess inCallProp,Dynamic &outResult); | ||
|  | void ScriptableGetFields(hx::Object *inObject, Array< ::String> &outFields); | ||
|  | bool ScriptableSetField(hx::Object *, const ::String &, Dynamic inValue,hx::PropertyAccess inCallProp, Dynamic &outValue); | ||
|  | 
 | ||
|  | 
 | ||
|  | class CppiaLoadedModule_obj : public ::hx::Object | ||
|  | { | ||
|  | public: | ||
|  |    virtual void run() = 0; | ||
|  |    virtual void boot() = 0; | ||
|  |    virtual ::hx::Class resolveClass( ::String inName) = 0; | ||
|  | }; | ||
|  | typedef ::hx::ObjectPtr<CppiaLoadedModule_obj> CppiaLoadedModule; | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | } // End namespace hx
 | ||
|  | 
 | ||
|  | void __scriptable_load_neko(String inName); | ||
|  | void __scriptable_load_cppia(String inCode); | ||
|  | ::hx::CppiaLoadedModule __scriptable_cppia_from_string(String inCode); | ||
|  | ::hx::CppiaLoadedModule __scriptable_cppia_from_data(Array<unsigned char> inBytes); | ||
|  | void __scriptable_load_neko_bytes(Array<unsigned char> inBytes); | ||
|  | void __scriptable_load_abc(Array<unsigned char> inBytes); | ||
|  | 
 | ||
|  | #if (HXCPP_API_LEVEL >= 330)
 | ||
|  | 
 | ||
|  | #define HX_SCRIPTABLE_REGISTER_INTERFACE(name,class) \
 | ||
|  |     hx::ScriptableRegisterInterface( HX_CSTRING(name), __scriptableFunctions, & class##_scriptable ) | ||
|  | 
 | ||
|  | #else
 | ||
|  | 
 | ||
|  | #define HX_SCRIPTABLE_REGISTER_INTERFACE(name,class) \
 | ||
|  |     hx::ScriptableRegisterInterface( HX_CSTRING(name), __scriptableFunctions, &typeid(class), class##__scriptable::__script_create ) | ||
|  | 
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #define HX_SCRIPTABLE_REGISTER_CLASS(name,class) \
 | ||
|  |    hx::ScriptableRegisterClass( HX_CSTRING(name), (int)offsetof(class##__scriptable,__scriptVTable) + sizeof(void *), __scriptableFunctions, class##__scriptable::__script_create, class##__scriptable::__script_construct ) | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifdef HXCPP_VISIT_ALLOCS
 | ||
|  | #define SCRIPTABLE_VISIT_FUNCTION \
 | ||
|  | void __Visit(HX_VISIT_PARAMS) { super::__Visit(HX_VISIT_ARG); hx::ScriptableVisit(__scriptVTable[-1],this,HX_VISIT_ARG); } | ||
|  | #else
 | ||
|  | #define SCRIPTABLE_VISIT_FUNCTION
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #define HX_DEFINE_SCRIPTABLE(ARG_LIST) \
 | ||
|  |    inline void *operator new( size_t inSize, int inExtraDataSize ) \ | ||
|  |    { \ | ||
|  |       return hx::InternalNew(inSize + inExtraDataSize,true); \ | ||
|  |    } \ | ||
|  |    inline void operator delete(void *,int) {} \ | ||
|  |    public: \ | ||
|  |    void **__scriptVTable; \ | ||
|  |    static hx::Object *__script_create(void **inVTable, int inExtra) { \ | ||
|  |     __ME *result = new (inExtra) __ME(); \ | ||
|  |     result->__scriptVTable = inVTable; \ | ||
|  |    return result; } \ | ||
|  |    void ** __GetScriptVTable() { return __scriptVTable; } \ | ||
|  |    ::String toString() {  if (__scriptVTable[0] ) \ | ||
|  |      { hx::CppiaCtx *ctx = hx::CppiaCtx::getCurrent(); hx::AutoStack a(ctx); ctx->pushObject(this); return ctx->runString(__scriptVTable[0]); } \ | ||
|  |       else return __superString::toString(); } \ | ||
|  |    ::String __ToString() const { return hx::ScriptableToString(__scriptVTable[-1]); } \ | ||
|  |    hx::Class __GetClass() const { return hx::ScriptableGetClass(__scriptVTable[-1]); } \ | ||
|  |    int __GetType() const { return hx::ScriptableGetType(__scriptVTable[-1]); } \ | ||
|  |    void __Mark(HX_MARK_PARAMS) { super::__Mark(HX_MARK_ARG); hx::ScriptableMark(__scriptVTable[-1],this,HX_MARK_ARG); } \ | ||
|  |    SCRIPTABLE_VISIT_FUNCTION | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #define HX_DEFINE_SCRIPTABLE_INTERFACE \
 | ||
|  |    void **__scriptVTable; \ | ||
|  |    Dynamic mDelegate; \ | ||
|  |    hx::Object *__GetRealObject() { return mDelegate.mPtr; } \ | ||
|  |    SCRIPTABLE_VISIT_FUNCTION \ | ||
|  |    void ** __GetScriptVTable() { return __scriptVTable; } \ | ||
|  |    public: \ | ||
|  |    static hx::Object *__script_create(void **inVTable,hx::Object *inDelegate) { \ | ||
|  |     __ME *result = new __ME(); \ | ||
|  |     result->__scriptVTable = inVTable; \ | ||
|  |     result->mDelegate = inDelegate; \ | ||
|  |     return result; } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #define HX_DEFINE_SCRIPTABLE_DYNAMIC \
 | ||
|  |  \ | ||
|  | 	hx::Val __Field(const ::String &inName,hx::PropertyAccess inCallProp) \ | ||
|  |       { Dynamic result; if (hx::ScriptableField(this,inName,inCallProp,result)) return result; return super::__Field(inName,inCallProp); } \ | ||
|  | 	Float __INumField(int inFieldID) \ | ||
|  | 		{ Float result; if (hx::ScriptableField(this,inFieldID,hx::paccAlways,result)) return result; return super::__INumField(inFieldID); } \ | ||
|  | 	Dynamic __IField(int inFieldID) \ | ||
|  | 		{ Dynamic result; if (hx::ScriptableField(this,inFieldID,hx::paccAlways,result)) return result; return super::__IField(inFieldID); } \ | ||
|  |    hx::Val __SetField(const ::String &inName,const hx::Val &inValue,hx::PropertyAccess inCallProp) \ | ||
|  |    { \ | ||
|  |       Dynamic value; \ | ||
|  |       if (hx::ScriptableSetField(this, inName, inValue,inCallProp,value)) \ | ||
|  |          return value; \ | ||
|  | 		return super::__SetField(inName,inValue,inCallProp); \ | ||
|  |    } \ | ||
|  | 	void __GetFields(Array< ::String> &outFields) \ | ||
|  | 		{ super::__GetFields(outFields); hx::ScriptableGetFields(this,outFields); } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #endif
 |