Files
LNXSDK/Kha/Backends/Kinc-hxcpp/khacpp/src/hx/cppia/CppiaClasses.cpp
2025-01-22 16:18:30 +01:00

1964 lines
54 KiB
C++

#include <hxcpp.h>
#include "Cppia.h"
#include "CppiaStream.h"
namespace hx
{
class CppiaEnumBase : public EnumBase_obj
{
public:
#if (HXCPP_API_LEVEL<330)
CppiaClassInfo *classInfo;
#endif
CppiaEnumBase(CppiaClassInfo *inInfo) { classInfo = inInfo; }
::hx::ObjectPtr<hx::Class_obj > __GetClass() const;
::String GetEnumName( ) const;
::String __ToString() const;
};
struct CppiaEnumConstructor
{
struct Arg
{
Arg(int inNameId, int inTypeId) : nameId(inNameId), typeId(inTypeId) { }
int nameId;
int typeId;
};
std::vector<Arg> args;
CppiaClassInfo *classInfo;
int nameId;
Dynamic value;
int index;
String name;
CppiaEnumConstructor(CppiaModule &inModule, CppiaStream &inStream, CppiaClassInfo *inClassInfo)
{
classInfo = inClassInfo;
nameId = inStream.getInt();
index = -1;
name = String();
int argCount = inStream.getInt();
for(int a=0;a<argCount;a++)
{
int nameId = inStream.getInt();
int typeId = inStream.getInt();
args.push_back( Arg(nameId,typeId) );
}
}
hx::Object *create( Array<Dynamic> inArgs )
{
bool ok = inArgs.mPtr ? (inArgs->length==args.size()) : args.size()==0;
if (!ok)
throw Dynamic(HX_CSTRING("Bad enum arg count"));
if (args.size()==0)
return value.mPtr;
#if (HXCPP_API_LEVEL >= 330)
EnumBase_obj *result = new ((int)args.size()*sizeof(cpp::Variant)) CppiaEnumBase(classInfo);
result->_hx_setIdentity(name, index, args.size());
for(int i=0;i<args.size();i++)
result->_hx_init( i, inArgs[i] );
#else
EnumBase_obj *result = new CppiaEnumBase(classInfo);
result->__Set(name, index, inArgs);
#endif
return result;
}
#ifdef CPPIA_JIT
static EnumBase_obj * SLJIT_CALL createEnumBase( CppiaEnumConstructor *enumCtor)
{
EnumBase_obj *result = new ((int)enumCtor->args.size()*sizeof(cpp::Variant)) CppiaEnumBase(enumCtor->classInfo);
result->_hx_setIdentity(enumCtor->name, enumCtor->index, enumCtor->args.size());
return result;
}
cpp::Variant::Type getVariantType(ExprType inType)
{
switch(inType)
{
case etVoid: return cpp::Variant::typeObject;
case etNull: return cpp::Variant::typeObject;
case etObject: return cpp::Variant::typeObject;
case etString: return cpp::Variant::typeString;
case etFloat: return cpp::Variant::typeDouble;
case etInt: return cpp::Variant::typeInt;
}
return cpp::Variant::typeObject;
}
void genCode(CppiaCompiler *compiler, Expressions &inArgs, const JitVal &inDest, ExprType destType)
{
bool ok = args.size() && args.size()==inArgs.size();
if (!ok)
printf("Bad enum arg count\n");
#if (HXCPP_API_LEVEL >= 330)
compiler->callNative( (void *)createEnumBase, (void *)this );
JitTemp result(compiler,jtPointer);
compiler->move(result, sJitReturnReg);
int offset = sizeof(EnumBase_obj);
for(int i=0;i<args.size();i++)
{
ExprType type = inArgs[i]->getType();
JitTemp val(compiler,getJitType(type));
inArgs[i]->genCode(compiler, val, inArgs[i]->getType());
compiler->move( sJitReturnReg.as(jtPointer), result );
if (type==etString)
{
compiler->move( sJitReturnReg.star(jtInt,offset + offsetof(cpp::Variant,valStringLen)), val.as(jtInt) );
compiler->move( sJitReturnReg.star(jtPointer,offset), val.as(jtPointer) + StringOffset::Ptr);
}
else
{
compiler->move( sJitReturnReg.star(type,offset), val );
}
compiler->move( sJitReturnReg.star(jtInt,offset + offsetof(cpp::Variant,type)), (int)getVariantType(type) );
offset += sizeof(cpp::Variant);
}
if (destType==etObject)
compiler->move(inDest, sJitReturnReg.as(jtPointer));
#endif
}
#endif
};
class EnumConstructorClosure : public hx::Object
{
public:
CppiaEnumConstructor &constructor;
EnumConstructorClosure(CppiaEnumConstructor &c) : constructor(c)
{
}
Dynamic __Run(const Array<Dynamic> &inArgs)
{
return constructor.create(inArgs);
}
int __GetType() const { return vtFunction; }
int __ArgCount() const { return constructor.args.size(); }
String toString() { return HX_CSTRING("#function(") + constructor.name + HX_CSTRING(")"); }
};
hx::Object *createEnumClosure(CppiaEnumConstructor &inContructor)
{
return new EnumConstructorClosure(inContructor);
}
#ifdef CPPIA_JIT
void SLJIT_CALL createEnum(hx::Class_obj *inClass, String *inName, int inArgs)
{
StackContext *ctx = StackContext::getCurrent();
// ctx.pointer points to end-of-args
unsigned char *oldPointer = ctx->pointer;
hx::Object **base = ((hx::Object **)(ctx->frame) );
Array<Dynamic> args = Array_obj<Dynamic>::__new(inArgs);
TRY_NATIVE
for(int i=0;i<inArgs;i++)
args[i] = Dynamic(base[i]);
base[0] = inClass->ConstructEnum(*inName, args).mPtr;
CATCH_NATIVE
ctx->pointer = oldPointer;
}
#endif
struct EnumField : public CppiaDynamicExpr
{
int enumId;
int fieldId;
CppiaEnumConstructor *value;
Expressions args;
// Mark class?
String enumName;
hx::Class enumClass;
Dynamic enumValue;
EnumField(CppiaStream &stream,bool inWithArgs)
{
enumId = stream.getInt();
fieldId = stream.getInt();
value= 0;
if (inWithArgs)
{
int argCount = stream.getInt();
for(int a=0;a<argCount;a++)
args.push_back( createCppiaExpr(stream) );
}
}
const char *getName() { return "EnumField"; }
CppiaExpr *link(CppiaModule &inModule)
{
TypeData *type = inModule.types[enumId];
if (type->cppiaClass)
{
if (!type->cppiaClass->isEnum)
throw "Field of non-enum";
value = type->cppiaClass->findEnum(fieldId);
}
else
{
enumClass = hx::Class_obj::Resolve(type->name);
if (!enumClass.mPtr)
{
printf("Could not find enum %s\n", type->name.out_str() );
throw "Bad enum";
}
enumName = inModule.strings[fieldId];
inModule.markable.push_back(this);
}
LinkExpressions(args,inModule);
return this;
}
hx::Object *getValue()
{
if (value)
return value->value.mPtr;
if (!enumValue.mPtr)
{
enumValue = enumClass->ConstructEnum(enumName,null());
}
return enumValue.mPtr;
}
hx::Object *runObject(CppiaCtx *ctx)
{
int s = args.size();
if (s==0)
return getValue();
Array<Dynamic> dynArgs = Array_obj<Dynamic>::__new(s,s);
for(int a=0;a<s;a++)
{
dynArgs[a] = args[a]->runObject(ctx);
BCR_CHECK;
}
return value ? value->create(dynArgs) : enumClass->ConstructEnum(enumName,dynArgs).mPtr;
}
void mark(hx::MarkContext *__inCtx)
{
HX_MARK_MEMBER(enumName);
HX_MARK_MEMBER(enumClass);
HX_MARK_MEMBER(enumValue);
}
#ifdef HXCPP_VISIT_ALLOCS
void visit(hx::VisitContext *__inCtx)
{
HX_VISIT_MEMBER(enumName);
HX_VISIT_MEMBER(enumClass);
HX_VISIT_MEMBER(enumValue);
}
#endif
#ifdef CPPIA_JIT
void genCode(CppiaCompiler *compiler, const JitVal &inDest, ExprType destType)
{
int s = args.size();
if (s==0)
{
// TODO GC pin
if (destType==etObject)
compiler->move(inDest, (void *)getValue());
}
else if (value)
{
value->genCode(compiler, args, inDest, destType);
}
else
{
{
AutoFramePos frame(compiler);
for(int a=0;a<s;a++)
{
args[a]->genCode(compiler, JitFramePos(compiler->getCurrentFrameSize(),etObject), etObject);
compiler->addFrame(etObject);
}
}
compiler->add(sJitCtxFrame, sJitFrame, compiler->getCurrentFrameSize());
compiler->callNative((void *)createEnum,(void *)enumClass.mPtr,(void *)&enumName,(int)args.size() );
if (destType!=etVoid && destType!=etNull)
compiler->convertResult( etObject, inDest, destType );
}
}
#endif
};
CppiaExpr *createEnumField(CppiaStream &stream,bool inWithArgs)
{
return new EnumField(stream, inWithArgs);
}
int getScriptId(hx::Class inClass);
void linkCppiaClass(hx::Class_obj *inClass, CppiaModule &cppia, String inName);
// Class Info...
CppiaClassInfo::CppiaClassInfo(CppiaModule &inCppia) : cppia(inCppia)
{
isLinked = false;
haxeBase = 0;
extraData = 0;
containsPointers = false;
classSize = 0;
newFunc = 0;
initExpr = 0;
enumMeta = 0;
isInterface = false;
interfaceSlotSize = 0;
superType = 0;
typeId = 0;
vtable = 0;
type = 0;
mClass.mPtr = 0;
dynamicMapOffset = 0;
haxeBaseVTable = 0;
}
/*
class CppiaClass *getCppiaClass()
{
return (class CppiaClass *)mClass.mPtr;
}
*/
hx::Object *CppiaClassInfo::createInstance(CppiaCtx *ctx,Expressions &inArgs, bool inCallNew)
{
hx::Object *obj = haxeBase->factory(vtable,extraData);
createDynamicFunctions(obj);
if (newFunc && inCallNew)
runFunExpr(ctx, newFunc->funExpr, obj, inArgs );
return obj;
}
hx::Object *CppiaClassInfo::createInstance(CppiaCtx *ctx,Array<Dynamic> &inArgs)
{
hx::Object *obj = haxeBase->factory(vtable,extraData);
createDynamicFunctions(obj);
if (newFunc)
runFunExprDynamicVoid(ctx, newFunc->funExpr, obj, inArgs );
return obj;
}
void *CppiaClassInfo::getHaxeBaseVTable()
{
if (!haxeBase || haxeBaseVTable)
return haxeBaseVTable;
hx::Object *temp = haxeBase->factory(vtable,extraData);
haxeBaseVTable = *(void **)temp;
if (!containsPointers && ( ((unsigned int *)temp)[-1] & IMMIX_ALLOC_IS_CONTAINER) )
containsPointers = true;
return haxeBaseVTable;
}
int CppiaClassInfo::getScriptVTableOffset()
{
return haxeBase ? (int)(haxeBase->mDataOffset - sizeof(void *)) : sizeof(hx::Object);
}
bool CppiaClassInfo::isNativeProperty(const String &inString)
{
return nativeProperties.find(inString) != nativeProperties.end();
}
int CppiaClassInfo::__GetType() { return isEnum ? vtEnum : vtClass; }
int CppiaClassInfo::getEnumIndex(String inName)
{
for(int i=0;i<enumConstructors.size();i++)
{
if (enumConstructors[i]->name==inName)
return i;
}
throw Dynamic(HX_CSTRING("Bad enum index"));
return 0;
}
bool CppiaClassInfo::implementsInterface(CppiaClassInfo *inInterface)
{
for(int i=0;i<implements.size();i++)
if (implements[i] == inInterface->typeId)
return true;
return false;
}
ScriptCallable *CppiaClassInfo::findFunction(bool inStatic,int inId)
{
Functions &funcs = inStatic ? staticFunctions : memberFunctions;
for(int i=0;i<funcs.size();i++)
{
if (funcs[i]->nameId == inId)
return funcs[i]->funExpr;
}
return 0;
}
CppiaFunction *CppiaClassInfo::findVTableFunction(int inId)
{
for(int i=0;i<memberFunctions.size();i++)
{
if (memberFunctions[i]->nameId == inId)
return memberFunctions[i];
}
return 0;
}
ScriptCallable *CppiaClassInfo::findInterfaceFunction(const std::string &inName)
{
Functions &funcs = memberFunctions;
for(int i=0;i<funcs.size();i++)
{
if ( cppia.strings[funcs[i]->nameId].utf8_str() == inName)
return funcs[i]->funExpr;
}
return 0;
}
ScriptCallable *CppiaClassInfo::findFunction(bool inStatic, const String &inName)
{
Functions &funcs = inStatic ? staticFunctions : memberFunctions;
for(int i=0;i<funcs.size();i++)
{
if ( cppia.strings[funcs[i]->nameId] == inName)
return funcs[i]->funExpr;
}
return 0;
}
inline ScriptCallable *CppiaClassInfo::findFunction(FunctionMap &inMap,const String &inName)
{
FunctionMap::iterator it = inMap.find(inName.utf8_str());
if (it!=inMap.end())
return it->second;
return 0;
}
bool CppiaClassInfo::getField(hx::Object *inThis, String inName, hx::PropertyAccess inCallProp, Dynamic &outValue)
{
if (inCallProp==paccDynamic)
inCallProp = isNativeProperty(inName) ? paccAlways : paccNever;
if (inCallProp)
{
ScriptCallable *getter = findMemberGetter(inName);
if (getter)
{
Array<Dynamic> empty;
outValue.mPtr = runFunExprDynamic(CppiaCtx::getCurrent(),getter,inThis, empty);
return true;
}
}
ScriptCallable *closure = findFunction(false,inName);
if (closure)
{
outValue.mPtr = createMemberClosure(inThis,closure);
return true;
}
// Look for dynamic function (variable)
for(int i=0;i<dynamicFunctions.size();i++)
{
if (cppia.strings[ dynamicFunctions[i]->nameId ]==inName)
{
CppiaVar *d = dynamicFunctions[i];
outValue = d->getValue(inThis);
return true;
}
}
for(int i=0;i<memberVars.size();i++)
{
CppiaVar &var = *memberVars[i];
if (var.name==inName)
{
outValue = var.getValue(inThis);
return true;
}
}
hx::FieldMap *map = dynamicMapOffset ? (hx::FieldMap *)( (char *)inThis + dynamicMapOffset ) :
inThis->__GetFieldMap();
if (map)
{
if (hx::FieldMapGet(map,inName,outValue))
return true;
}
//printf("Get field not found (%s) %s\n", inThis->toString().out_str(),inName.out_str());
return false;
}
bool CppiaClassInfo::setField(hx::Object *inThis, String inName, Dynamic inValue, hx::PropertyAccess inCallProp, Dynamic &outValue)
{
if (inCallProp==paccDynamic)
inCallProp = isNativeProperty(inName) ? paccAlways : paccNever;
if (inCallProp)
{
//printf("Set field %s %s = %s\n", inThis->toString().out_str(), inName.out_str(), inValue->toString().out_str());
ScriptCallable *setter = findMemberSetter(inName);
if (setter)
{
Array<Dynamic> args = Array_obj<Dynamic>::__new(1,1);
args[0] = inValue;
outValue.mPtr = runFunExprDynamic(CppiaCtx::getCurrent(),setter,inThis, args);
return true;
}
}
// Look for dynamic function (variable)
for(int i=0;i<dynamicFunctions.size();i++)
{
if (cppia.strings[ dynamicFunctions[i]->nameId ]==inName)
{
CppiaVar *d = dynamicFunctions[i];
outValue = d->setValue(inThis,inValue);
return true;
}
}
for(int i=0;i<memberVars.size();i++)
{
CppiaVar &var = *memberVars[i];
if (var.name==inName)
{
outValue = var.setValue(inThis, inValue);
return true;
}
}
hx::FieldMap *map = dynamicMapOffset ? (hx::FieldMap *)( (char *)inThis + dynamicMapOffset ) :
inThis->__GetFieldMap();
if (map)
{
#ifdef HXCPP_GC_GENERATIONAL
FieldMapSet(inThis,map, inName, inValue);
#else
FieldMapSet(map, inName, inValue);
#endif
outValue = inValue;
return true;
}
// Fall though to haxe base
//printf("Set field not found (%s) %s map=%p o=%d\n", inThis->toString().out_str(),inName.out_str(), map, dynamicMapOffset);
return false;
}
int CppiaClassInfo::findFunctionSlot(int inName)
{
for(int i=0;i<memberFunctions.size();i++)
if (memberFunctions[i]->nameId==inName)
return memberFunctions[i]->vtableSlot;
return -1;
}
ExprType CppiaClassInfo::findFunctionType(CppiaModule &inModule, int inName)
{
for(int i=0;i<memberFunctions.size();i++)
if (memberFunctions[i]->nameId==inName)
return inModule.types[ memberFunctions[i]->returnType ]->expressionType;
return etVoid;
}
CppiaVar *CppiaClassInfo::findVar(bool inStatic,int inId)
{
std::vector<CppiaVar *> &vars = inStatic ? staticVars : memberVars;
for(int i=0;i<vars.size();i++)
{
if (vars[i]->nameId == inId)
return vars[i];
}
std::vector<CppiaVar *> &dvars = inStatic ? staticDynamicFunctions : dynamicFunctions;
for(int i=0;i<dvars.size();i++)
{
if (dvars[i]->nameId == inId)
return dvars[i];
}
if (superType && superType->cppiaClass)
return superType->cppiaClass->findVar(inStatic,inId);
return 0;
}
void CppiaClassInfo::dumpVars(const char *inMessage, std::vector<CppiaVar *> &vars)
{
printf(" %s:\n", inMessage);
for(int i=0;i<vars.size();i++)
printf(" %d] %s (%d)\n", i, cppia.strings[ vars[i]->nameId ].out_str(), vars[i]->nameId );
}
void CppiaClassInfo::dumpFunctions(const char *inMessage, std::vector<CppiaFunction *> &funcs)
{
printf(" %s:\n", inMessage);
for(int i=0;i<funcs.size();i++)
printf(" %d] %s (%d)\n", i, cppia.strings[ funcs[i]->nameId ].out_str(), funcs[i]->nameId);
}
void CppiaClassInfo::dump()
{
printf("Class %s\n", name.c_str());
dumpFunctions("Member functions",memberFunctions);
dumpFunctions("Static functions",staticFunctions);
dumpVars("Member vars",memberVars);
dumpVars("Member dyns",dynamicFunctions);
dumpVars("Static vars",staticVars);
dumpVars("Static dyns",staticDynamicFunctions);
}
CppiaEnumConstructor *CppiaClassInfo::findEnum(int inFieldId)
{
for(int i=0;i<enumConstructors.size();i++)
if (enumConstructors[i]->nameId==inFieldId)
return enumConstructors[i];
return 0;
}
void CppiaClassInfo::mark(hx::MarkContext *__inCtx)
{
HX_MARK_MEMBER(mClass);
for(int i=0;i<enumConstructors.size();i++)
{
HX_MARK_MEMBER(enumConstructors[i]->value);
HX_MARK_MEMBER(enumConstructors[i]->name);
}
for(int i=0;i<staticVars.size();i++)
staticVars[i]->mark(__inCtx);
for(int i=0;i<staticDynamicFunctions.size();i++)
staticDynamicFunctions[i]->mark(__inCtx);
}
#ifdef HXCPP_VISIT_ALLOCS
void CppiaClassInfo::visit(hx::VisitContext *__inCtx)
{
HX_VISIT_MEMBER(mClass);
for(int i=0;i<enumConstructors.size();i++)
{
HX_VISIT_MEMBER(enumConstructors[i]->value);
HX_VISIT_MEMBER(enumConstructors[i]->name);
}
for(int i=0;i<staticVars.size();i++)
staticVars[i]->visit(__inCtx);
for(int i=0;i<staticDynamicFunctions.size();i++)
staticDynamicFunctions[i]->visit(__inCtx);
}
#endif
bool CppiaClassInfo::load(CppiaStream &inStream)
{
CppiaOp op = inStream.getOp();
isInterface = isEnum = false;
if (op==IaClass)
isInterface = false;
else if (op==IaInterface)
isInterface = true;
else if (op==IaEnum)
isEnum = true;
else
{
DBGLOG("Invalid class field op %d\n", op);
throw "Bad class type";
}
std::string tok;
typeId = inStream.getInt();
mClass.mPtr = createCppiaClass(this);
superId = isEnum ? 0 : inStream.getInt();
int implementCount = isEnum ? 0 : inStream.getInt();
implements.resize(implementCount);
for(int i=0;i<implementCount;i++)
implements[i] = inStream.getInt();
name = cppia.typeStr(typeId);
DBGLOG("Class %s %s\n", name.c_str(), isEnum ? "enum" : isInterface ? "interface" : "class" );
bool isNew = //(resolved == null() || !IsCppiaClass(resolved) ) &&
(!HaxeNativeClass::findClass(name) && !HaxeNativeInterface::findInterface(name) );
if (isNew && isEnum)
{
hx::Class cls = hx::Class_obj::Resolve(String(name.c_str()));
if (cls.mPtr && getScriptId(cls)==0)
{
DBGLOG("Found existing enum %s - ignore\n", name.c_str());
isNew = false;
}
}
if (isNew)
{
cppia.types[typeId]->cppiaClass = this;
}
else
{
DBGLOG("Already has registered %s - ignore\n",name.c_str());
}
inStream.module->creatingClass = name.c_str();
int fields = inStream.getInt();
for(int f=0;f<fields;f++)
{
if (isEnum)
{
CppiaEnumConstructor *enumConstructor = new CppiaEnumConstructor(cppia,inStream,this);
enumConstructors.push_back( enumConstructor );
}
else
{
tok = inStream.getToken();
if (tok=="FUNCTION")
{
bool isStatic = inStream.getStatic();
bool isDynamic = inStream.getInt();
CppiaFunction *func = new CppiaFunction(&cppia,isStatic,isDynamic);
func->load(inStream,!isInterface);
if (isDynamic)
{
if (isStatic)
staticDynamicFunctions.push_back( new CppiaVar(func) );
else
dynamicFunctions.push_back( new CppiaVar(func) );
}
else
{
if (isStatic)
staticFunctions.push_back(func);
else
{
memberFunctions.push_back(func);
}
}
}
else if (tok=="VAR")
{
bool isStatic = inStream.getStatic();
CppiaVar *var = new CppiaVar(isStatic);
if (isStatic)
staticVars.push_back(var);
else
memberVars.push_back(var);
var->load(inStream);
}
else if (tok=="IMPLDYNAMIC")
{
// Fill in later
dynamicMapOffset = -1;
}
else if (tok=="INLINE")
{
// OK
}
else
throw "unknown field type";
}
}
if (isEnum)
{
if (inStream.getBool())
enumMeta = createCppiaExpr(inStream);
}
inStream.module->creatingClass = 0;
return isNew;
}
#if (HXCPP_API_LEVEL<330)
void **CppiaClassInfo::createInterfaceVTable(int inTypeId)
{
std::vector<CppiaExpr *> vtable;
HaxeNativeInterface *interface = cppia.types[inTypeId]->interfaceBase;
// Native-defined interface...
if (interface)
{
vtable.push_back( findInterfaceFunction("toString") );
ScriptNamedFunction *functions = interface->functions;
if (functions != 0) {
for(ScriptNamedFunction *f = functions; f->name; f++)
if (strcmp(f->name,"toString"))
vtable.push_back( findInterfaceFunction(f->name) );
}
}
CppiaClassInfo *cls = cppia.types[inTypeId]->cppiaClass;
if (!cls && !interface)
throw "vtable for unknown class";
if (cls && !cls->isInterface)
throw "vtable for non-interface";
if (cls)
{
for(int i=0;i<cls->memberFunctions.size();i++)
{
CppiaFunction *func = cls->memberFunctions[i];
vtable.push_back( findFunction(false,func->nameId) );
}
}
void **result = new void *[ vtable.size() + 1];
result[0] = this;
result++;
memcpy(result, &vtable[0], sizeof(void *)*vtable.size());
return result;
}
#endif
hx::Class *CppiaClassInfo::getSuperClass()
{
DBGLOG("getSuperClass %s %d\n", name.c_str(), superId);
if (!superId)
return 0;
TypeData *superType = cppia.types[ superId ];
if (!superType)
throw "Unknown super type!";
if (superType->cppiaClass)
return &superType->cppiaClass->mClass;
if (!superType->haxeClass.mPtr)
{
printf("Invalid super class '%s' for '%s'.\n", superType->name.c_str(), name.c_str());
throw "Missing super class";
}
return &superType->haxeClass;
}
void CppiaClassInfo::addMemberFunction(Functions &ioCombined, CppiaFunction *inNewFunc)
{
for(int j=0;j<ioCombined.size();j++)
if (ioCombined[j]->name==inNewFunc->name)
{
ioCombined[j] = inNewFunc;
return;
}
ioCombined.push_back(inNewFunc);
}
void CppiaClassInfo::linkTypes()
{
if (isLinked)
return;
isLinked = true;
type = cppia.types[typeId];
mClass->mName = type->name;
superType = superId ? cppia.types[ superId ] : 0;
CppiaClassInfo *cppiaSuper = superType ? superType->cppiaClass : 0;
// Link super first
if (superType && superType->cppiaClass)
superType->cppiaClass->linkTypes();
// implemented interfaces before main class
for(int i=0;i<implements.size();i++)
if (cppia.types[ implements[i] ]->cppiaClass)
cppia.types[ implements[i] ]->cppiaClass->linkTypes();
// Add super interfaces ...
TypeData *extraInterfaces = cppia.types[ superId ];
while(extraInterfaces)
{
if (extraInterfaces->cppiaClass)
{
CppiaClassInfo &parent = *extraInterfaces->cppiaClass;
std::vector<int> &impl = parent.implements;
for(int i=0;i<impl.size();i++)
{
bool found = false;
for(int j=0;j<implements.size() && !found; j++)
found = implements[j] == impl[i];
if (!found)
implements.push_back(impl[i]);
}
extraInterfaces = cppia.types[ parent.superId ];
}
else
{
#if (HXCPP_API_LEVEL >= 330)
HaxeNativeInterface *native = HaxeNativeInterface::findInterface( extraInterfaces->name.utf8_str() );
if (native)
{
String hashName = extraInterfaces->name.split(HX_CSTRING(".")).mPtr->join(HX_CSTRING("::"));
interfaceScriptTables[hashName.hash()] = native->scriptTable;
ScriptNamedFunction *functions = native->functions;
for(ScriptNamedFunction *f = functions; f && f->name; f++)
{
nativeInterfaceFunctions.push_back(f);
int slot = cppia.getInterfaceSlot(f->name);
if (slot<0)
printf("Interface slot '%s' not found\n",f->name);
if (slot>interfaceSlotSize)
interfaceSlotSize = slot;
}
}
#endif
break;
}
}
DBGLOG(" Linking class '%s' ", type->name.out_str());
if (!superType)
{
DBGLOG("script base\n");
}
else if (cppiaSuper)
{
DBGLOG("extends script '%s'\n", superType->name.out_str());
}
else
{
DBGLOG("extends haxe '%s'\n", superType->name.out_str());
}
// Link class before we combine the function list...
linkCppiaClass(mClass.mPtr,cppia,type->name);
haxeBase = type->haxeBase;
if (!haxeBase && !isInterface)
throw "No base defined for non-interface";
classSize = haxeBase ? haxeBase->mDataOffset : 0;
// Combine member vars ...
if (cppiaSuper)
{
classSize = cppiaSuper->classSize;
containsPointers = cppiaSuper->containsPointers;
if (cppiaSuper->dynamicMapOffset!=0)
dynamicMapOffset = cppiaSuper->dynamicMapOffset;
std::vector<CppiaVar *> combinedVars(cppiaSuper->memberVars );
for(int i=0;i<memberVars.size();i++)
{
for(int j=0;j<combinedVars.size();j++)
if (combinedVars[j]->nameId==memberVars[i]->nameId)
printf("Warning duplicate member var %s\n", cppia.strings[memberVars[i]->nameId].out_str());
combinedVars.push_back(memberVars[i]);
}
memberVars.swap(combinedVars);
std::vector<CppiaVar *> combinedDynamics(cppiaSuper->dynamicFunctions );
for(int i=0;i<dynamicFunctions.size();i++)
{
bool found = false;
for(int j=0;j<combinedDynamics.size() && !found;j++)
if (dynamicFunctions[i]->nameId == combinedDynamics[j]->nameId)
{
// Overwrite
dynamicFunctions[i]->offset = combinedDynamics[j]->offset;
combinedDynamics[j] = dynamicFunctions[i];
found = true;
}
if (!found)
combinedDynamics.push_back(dynamicFunctions[i]);
}
dynamicFunctions.swap(combinedDynamics);
// Combine member functions ...
Functions combinedFunctions(cppiaSuper->memberFunctions );
if (isInterface)
{
// 'implements' interfaces are like extra super-classes for interfaces
// For non-interface classes, these function will show up in the members anyhow
for(int i=0;i<implements.size();i++)
{
CppiaClassInfo *cppiaInterface = cppia.types[implements[i]]->cppiaClass;
if (cppiaInterface)
{
Functions &intfFuncs = cppiaInterface->memberFunctions;
for(int j=0;j<intfFuncs.size();j++)
addMemberFunction(combinedFunctions, intfFuncs[j]);
}
}
}
for(int i=0;i<memberFunctions.size();i++)
addMemberFunction(combinedFunctions, memberFunctions[i]);
memberFunctions.swap(combinedFunctions);
}
// Non-interface classes will have haxeBase
if (haxeBase)
{
// Calculate table offsets...
DBGLOG(" base haxe size %s = %d\n", haxeBase->name.c_str(), classSize);
for(int i=0;i<memberVars.size();i++)
{
if (memberVars[i]->offset)
{
DBGLOG(" super var %s @ %d\n", cppia.identStr(memberVars[i]->nameId), memberVars[i]->offset);
}
else
{
DBGLOG(" link var %s @ %d\n", cppia.identStr(memberVars[i]->nameId), classSize);
memberVars[i]->linkVarTypes(cppia,classSize);
containsPointers = containsPointers || memberVars[i]->hasPointer();
}
}
for(int i=0;i<dynamicFunctions.size();i++)
{
containsPointers = true;
if (dynamicFunctions[i]->offset)
{
DBGLOG(" super dynamic function %s @ %d\n", cppia.identStr(dynamicFunctions[i]->nameId), dynamicFunctions[i]->offset);
}
else
{
DBGLOG(" link dynamic function %s @ %d\n", cppia.identStr(dynamicFunctions[i]->nameId), classSize);
dynamicFunctions[i]->linkVarTypes(cppia,classSize);
}
}
if (dynamicMapOffset==-1)
{
dynamicMapOffset = classSize;
classSize += sizeof( hx::FieldMap * );
containsPointers = true;
}
extraData = classSize - haxeBase->mDataOffset;
if (!containsPointers)
getHaxeBaseVTable();
}
DBGLOG(" script member vars size = %d\n", extraData);
for(int i=0;i<staticVars.size();i++)
{
DBGLOG(" link static var %s\n", cppia.identStr(staticVars[i]->nameId));
staticVars[i]->linkVarTypes(cppia);
}
for(int i=0;i<staticDynamicFunctions.size();i++)
{
DBGLOG(" link dynamic static var %s\n", cppia.identStr(staticDynamicFunctions[i]->nameId));
staticDynamicFunctions[i]->linkVarTypes(cppia);
}
// Combine vtable positions...
DBGLOG(" format haxe callable vtable (%d)....\n", (int)memberFunctions.size());
std::vector<std::string> table;
if (haxeBase)
haxeBase->addVtableEntries(table);
for(int i=0;i<table.size();i++)
DBGLOG(" base table[%d] = %s\n", i, table[i].c_str() );
int vtableSlot = table.size();
for(int i=0;i<memberFunctions.size();i++)
{
int idx = -1;
for(int j=0;j<table.size();j++)
if (table[j] == memberFunctions[i]->name)
{
idx = j;
break;
}
if (idx<0)
{
if (isInterface)
{
idx = cppia.getInterfaceSlot(memberFunctions[i]->name);
if (idx==-1)
throw "Missing function in interface";
if (idx>interfaceSlotSize)
interfaceSlotSize = idx;
idx = -idx;
DBGLOG("Using interface vtable[%d] = %s\n", idx, memberFunctions[i]->name.c_str() );
}
else
{
idx = vtableSlot++;
DBGLOG(" cppia slot [%d] = %s\n", idx, memberFunctions[i]->name.c_str() );
}
}
else
DBGLOG(" override slot [%d] = %s\n", idx, memberFunctions[i]->name.c_str() );
memberFunctions[i]->setVTableSlot(idx);
}
// Create interface vtables...
for(int i=0;i<implements.size();i++)
{
int id = implements[i];
#if (HXCPP_API_LEVEL < 330)
void **vtable = createInterfaceVTable(id);
#endif
while(id > 0)
{
TypeData *interface = cppia.types[id];
CppiaClassInfo *cppiaInterface = interface->cppiaClass;
#if (HXCPP_API_LEVEL >= 330)
HaxeNativeInterface *native = HaxeNativeInterface::findInterface( interface->name.utf8_str() );
if (native)
{
String hashName = interface->name.split(HX_CSTRING(".")).mPtr->join(HX_CSTRING("::"));
interfaceScriptTables[hashName.hash()] = native->scriptTable;
ScriptNamedFunction *functions = native->functions;
if (functions != 0)
{
for(ScriptNamedFunction *f = functions; f->name; f++)
{
nativeInterfaceFunctions.push_back(f);
int slot = cppia.getInterfaceSlot(f->name);
if (slot<0)
printf("Interface slot '%s' not found\n",f->name);
if (slot>interfaceSlotSize)
interfaceSlotSize = slot;
}
}
}
#else
interfaceVTables[ interface->name.utf8_str() ] = vtable;
#endif
if (!cppiaInterface)
break;
Functions &intfFuncs = cppiaInterface->memberFunctions;
for(int f=0;f<intfFuncs.size();f++)
{
int slot = cppia.getInterfaceSlot(intfFuncs[f]->name);
if (slot<0)
printf("Interface slot '%s' not found\n",intfFuncs[f]->name.c_str());
if (slot>interfaceSlotSize)
interfaceSlotSize = slot;
}
id = cppiaInterface->superId;
}
}
if (interfaceSlotSize)
interfaceSlotSize++;
vtable = new void*[vtableSlot + 2 + interfaceSlotSize];
memset(vtable, 0, sizeof(void *)*(vtableSlot+2+interfaceSlotSize));
vtable += interfaceSlotSize;
*vtable++ = this;
DBGLOG(" vtable size %d -> %p\n", vtableSlot, vtable);
// Extract special function ...
for(int i=0;i<staticFunctions.size(); )
{
if (staticFunctions[i]->name == "new")
{
newFunc = staticFunctions[i];
staticFunctions.erase( staticFunctions.begin() + i);
}
else if (staticFunctions[i]->name == "__init__")
{
initExpr = staticFunctions[i]->funExpr;
staticFunctions.erase( staticFunctions.begin() + i);
}
else
i++;
}
for(int i=0;i<enumConstructors.size();i++)
{
CppiaEnumConstructor &e = *enumConstructors[i];
e.name = cppia.strings[e.nameId];
if (e.args.size()==0)
{
EnumBase base = new CppiaEnumBase(this);
e.value = base;
#if (HXCPP_API_LEVEL>=330)
base->_hx_setIdentity(cppia.strings[e.nameId],i,0);
#else
base->__Set( cppia.strings[e.nameId],i,null() );
#endif
}
else
{
e.index = i;
e.value = createEnumClosure(e);
}
}
if (!newFunc && cppiaSuper && cppiaSuper->newFunc)
{
//throw "No chaining constructor";
newFunc = cppiaSuper->newFunc;
}
DBGLOG(" this constructor %p\n", newFunc);
}
#ifdef CPPIA_JIT
void CppiaClassInfo::compile()
{
for(int i=0;i<staticFunctions.size();i++)
{
DBGLOG(" Compile %s::%s\n", name.c_str(), staticFunctions[i]->name.c_str() );
staticFunctions[i]->compile();
}
if (newFunc)
newFunc->compile();
// Functions
for(int i=0;i<memberFunctions.size();i++)
{
DBGLOG(" Compile member %s::%s\n", name.c_str(), memberFunctions[i]->name.c_str() );
memberFunctions[i]->compile();
}
}
#endif
void CppiaClassInfo::link()
{
int newPos = -1;
for(int i=0;i<staticFunctions.size();i++)
{
DBGLOG(" Link %s::%s\n", name.c_str(), staticFunctions[i]->name.c_str() );
staticFunctions[i]->link();
}
if (newFunc)
newFunc->link();
if (initExpr)
initExpr = initExpr->link(cppia);
// Functions
for(int i=0;i<memberFunctions.size();i++)
{
DBGLOG(" Link member %s::%s\n", name.c_str(), memberFunctions[i]->name.c_str() );
memberFunctions[i]->link();
}
for(int i=0;i<staticDynamicFunctions.size();i++)
staticDynamicFunctions[i]->link(cppia);
for(int i=0;i<dynamicFunctions.size();i++)
dynamicFunctions[i]->link(cppia);
for(int i=0;i<memberFunctions.size();i++)
{
vtable[ memberFunctions[i]->vtableSlot ] = memberFunctions[i]->funExpr;
if (interfaceSlotSize)
{
int interfaceSlot = cppia.findInterfaceSlot( memberFunctions[i]->name );
DBGLOG("Set %s : %s to %d @%p\n", name.c_str(), memberFunctions[i]->name.c_str(), interfaceSlot, vtable);
if (interfaceSlot>0 && interfaceSlot<interfaceSlotSize)
vtable[ -interfaceSlot ] = memberFunctions[i]->funExpr;
}
}
// Find interface functions that are not implemented in client, but rely on host fallback...
#if (HXCPP_API_LEVEL >= 330)
if (!isInterface)
{
std::vector<ScriptNamedFunction *> &nativeInterfaceFuncs = type->cppiaClass->nativeInterfaceFunctions;
for(int i=0;i<nativeInterfaceFuncs.size();i++)
{
int interfaceSlot = cppia.findInterfaceSlot( nativeInterfaceFuncs[i]->name);
if (!vtable[-interfaceSlot])
vtable[-interfaceSlot] = new ScriptCallable(cppia,nativeInterfaceFuncs[i]);
}
}
#endif
// Vars ...
if (!isInterface)
{
for(int i=0;i<memberVars.size();i++)
{
CppiaVar &var = *memberVars[i];
var.link(cppia);
if (var.readAccess == CppiaVar::accCall || var.readAccess==CppiaVar::accCallNative)
{
ScriptCallable *getter = findFunction(false,HX_CSTRING("get_") + var.name);
if (!getter)
{
dump();
throw Dynamic(HX_CSTRING("Could not find getter for ") + var.name);
}
DBGLOG(" found getter for %s.%s\n", name.c_str(), var.name.out_str());
memberGetters[var.name.utf8_str()] = getter;
}
if (var.writeAccess == CppiaVar::accCall || var.writeAccess==CppiaVar::accCallNative)
{
ScriptCallable *setter = findFunction(false,HX_CSTRING("set_") + var.name);
if (!setter)
throw Dynamic(HX_CSTRING("Could not find setter for ") + var.name);
DBGLOG(" found setter for %s.%s\n", name.c_str(), var.name.out_str());
memberSetters[var.name.utf8_str()] = setter;
}
if (var.readAccess == CppiaVar::accCallNative || var.writeAccess == CppiaVar::accCallNative)
nativeProperties.insert( var.name );
}
}
for(int i=0;i<staticVars.size();i++)
{
CppiaVar &var = *staticVars[i];
var.link(cppia);
if (var.readAccess == CppiaVar::accCall || var.readAccess == CppiaVar::accCallNative)
{
ScriptCallable *getter = findFunction(true,HX_CSTRING("get_") + var.name);
if (!getter)
throw Dynamic(HX_CSTRING("Could not find getter for ") + var.name);
DBGLOG(" found getter for %s.%s\n", name.c_str(), var.name.out_str());
staticGetters[var.name.utf8_str()] = getter;
}
if (var.writeAccess == CppiaVar::accCall || var.writeAccess == CppiaVar::accCallNative)
{
ScriptCallable *setter = findFunction(true,HX_CSTRING("set_") + var.name);
if (!setter)
throw Dynamic(HX_CSTRING("Could not find setter for ") + var.name);
DBGLOG(" found setter for %s.%s\n", name.c_str(), var.name.out_str());
staticSetters[var.name.utf8_str()] = setter;
}
if (var.readAccess == CppiaVar::accCallNative || var.writeAccess == CppiaVar::accCallNative)
nativeProperties.insert( var.name );
}
if (enumMeta)
enumMeta = enumMeta->link(cppia);
//printf("Found haxeBase %s = %p / %d\n", cppia.types[typeId]->name.out_str(), haxeBase, dataSize );
}
void CppiaClassInfo::init(CppiaCtx *ctx, int inPhase)
{
unsigned char *pointer = ctx->pointer;
ctx->push( (hx::Object *) 0 ); // this
AutoStack save(ctx,pointer);
if (inPhase==0)
{
for(int i=0;i<staticVars.size();i++)
{
staticVars[i]->runInit(ctx);
if (staticVars[i]->name==HX_CSTRING("__meta__"))
{
// Todo - delete/clean value
mClass->__meta__ = staticVars[i]->objVal;
staticVars.erase( staticVars.begin() + i );
i--;
}
}
if (enumMeta)
mClass->__meta__ = enumMeta->runObject(ctx);
for(int i=0;i<staticDynamicFunctions.size();i++)
staticDynamicFunctions[i]->runInit(ctx);
}
else if (inPhase==1)
{
if (initExpr)
initExpr->runVoid(ctx);
}
}
Dynamic CppiaClassInfo::getStaticValue(const String &inName,hx::PropertyAccess inCallProp)
{
if (inCallProp==paccDynamic)
inCallProp = isNativeProperty(inName) ? paccAlways : paccNever;
if (inCallProp)
{
ScriptCallable *getter = findStaticGetter(inName);
if (getter)
{
Array<Dynamic> empty;
return runFunExprDynamic(CppiaCtx::getCurrent(),getter,0, empty);
}
}
CppiaExpr *closure = findFunction(true,inName);
if (closure)
return createMemberClosure(0,(ScriptCallable*)closure);
// Look for dynamic function (variable)
for(int i=0;i<staticDynamicFunctions.size();i++)
{
if (cppia.strings[ staticDynamicFunctions[i]->nameId ]==inName)
{
CppiaVar *d = staticDynamicFunctions[i];
return d->getStaticValue();
}
}
for(int i=0;i<staticVars.size();i++)
{
CppiaVar &var = *staticVars[i];
if (var.name==inName)
return var.getStaticValue();
}
printf("Get static field not found (%s) %s\n", name.c_str(),inName.out_str());
return null();
}
bool CppiaClassInfo::hasStaticValue(const String &inName)
{
if (findStaticGetter(inName))
return true;
CppiaExpr *closure = findFunction(true,inName);
if (closure)
return true;
// Look for dynamic function (variable)
for(int i=0;i<staticDynamicFunctions.size();i++)
if (cppia.strings[ staticDynamicFunctions[i]->nameId ]==inName)
return true;
for(int i=0;i<staticVars.size();i++)
{
CppiaVar &var = *staticVars[i];
if (var.name==inName)
return true;
}
return false;
}
Dynamic CppiaClassInfo::setStaticValue(const String &inName,const Dynamic &inValue ,hx::PropertyAccess inCallProp)
{
if (inCallProp==paccDynamic)
inCallProp = isNativeProperty(inName) ? paccAlways : paccNever;
if (inCallProp)
{
ScriptCallable *setter = findStaticSetter(inName);
if (setter)
{
Array<Dynamic> args = Array_obj<Dynamic>::__new(1,1);
args[0] = inValue;
return runFunExprDynamic(CppiaCtx::getCurrent(),setter,0, args);
}
}
// Look for dynamic function (variable)
for(int i=0;i<staticDynamicFunctions.size();i++)
{
if (cppia.strings[ staticDynamicFunctions[i]->nameId ]==inName)
{
CppiaVar *d = staticDynamicFunctions[i];
return d->setStaticValue(inValue);
}
}
for(int i=0;i<staticVars.size();i++)
{
CppiaVar &var = *staticVars[i];
if (var.name==inName)
{
return var.setStaticValue(inValue);
}
}
printf("Set static field not found (%s) %s\n", name.c_str(), inName.out_str());
return null();
}
void CppiaClassInfo::GetInstanceFields(hx::Object *inObject, Array<String> &ioFields)
{
for(int i=0;i<memberVars.size();i++)
{
CppiaVar &var = *memberVars[i];
ioFields->push(var.name);
}
if (inObject)
{
hx::FieldMap *map = inObject->__GetFieldMap();
if (map)
FieldMapAppendFields(map, ioFields);
}
}
Array<String> CppiaClassInfo::GetClassFields()
{
Array<String> result = Array_obj<String>::__new();
if (isEnum)
{
for(int i=0;i<enumConstructors.size();i++)
result->push(enumConstructors[i]->name);
}
else
{
for(int i=0;i<staticVars.size();i++)
{
CppiaVar &var = *staticVars[i];
if (var.isVirtual)
continue;
result->push(var.name);
}
for(int i=0;i<staticDynamicFunctions.size();i++)
{
CppiaVar &var = *staticDynamicFunctions[i];
if (var.isVirtual)
continue;
result->push(var.name);
}
for(int i=0;i<staticFunctions.size();i++)
{
CppiaFunction &func = *staticFunctions[i];
result->push(func.getName());
}
}
return result;
}
void CppiaClassInfo::markInstance(hx::Object *inThis, hx::MarkContext *__inCtx)
{
if (dynamicMapOffset)
HX_MARK_MEMBER(getFieldMap(inThis));
for(int i=0;i<dynamicFunctions.size();i++)
dynamicFunctions[i]->mark(inThis, __inCtx);
// Only script members?
for(int i=0;i<memberVars.size();i++)
memberVars[i]->mark(inThis, __inCtx);
}
#ifdef HXCPP_VISIT_ALLOCS
void CppiaClassInfo::visitInstance(hx::Object *inThis, hx::VisitContext *__inCtx)
{
if (dynamicMapOffset)
HX_VISIT_MEMBER(getFieldMap(inThis));
for(int i=0;i<dynamicFunctions.size();i++)
dynamicFunctions[i]->visit(inThis, __inCtx);
for(int i=0;i<memberVars.size();i++)
memberVars[i]->visit(inThis, __inCtx);
}
#endif
// --- CppiaClass --------
class CppiaClass : public hx::Class_obj
{
public:
CppiaClassInfo *info;
CppiaClass(CppiaClassInfo *inInfo)
{
info = inInfo;
}
Array<String> GetClassFields()
{
return info->GetClassFields();
}
Array<String> GetInstanceFields()
{
Array<String> members = mSuper ? (*mSuper)->GetInstanceFields() : Array_obj<String>::__new(0,0);
for(int i=0;i<info->memberFunctions.size();i++)
{
CppiaFunction *func = info->memberFunctions[i];
String name = func->getName();
if (members->Find(name)<0)
members->push(name);
}
CppiaModule &module = info->cppia;
for(int i=0;i<info->memberVars.size();i++)
{
CppiaVar *var = info->memberVars[i];
if (var->isVirtual)
continue;
String name = module.strings[var->nameId];
if (members->Find(name)<0)
members->push( name );
}
for(int i=0;i<info->dynamicFunctions.size();i++)
{
CppiaVar *var = info->dynamicFunctions[i];
if (var->isVirtual)
continue;
String name = module.strings[var->nameId];
if (members->Find(name)<0)
members->push(name);
}
return members;
}
void linkClass(CppiaModule &inModule,String inName)
{
mName = inName;
mSuper = info->getSuperClass();
DBGLOG("LINK %p ########################### %s -> %p\n", this, mName.out_str(), mSuper );
//mStatics = Array_obj<String>::__new(0,0);
bool overwrite = false;
hx::Class old = hx::Class_obj::Resolve(inName);
// Overwrite cppia classes
if (old.mPtr && dynamic_cast<CppiaClass *>( old.mPtr ) )
overwrite = true;
registerScriptable(overwrite);
}
Dynamic ConstructEmpty()
{
if (info->isEnum)
return Dynamic();
Expressions none;
return info->createInstance(CppiaCtx::getCurrent(),none,false);
}
Dynamic ConstructArgs(hx::DynamicArray inArgs)
{
return info->createInstance(CppiaCtx::getCurrent(),inArgs);
}
bool __IsEnum() { return info->isEnum; }
Dynamic ConstructEnum(String inName,hx::DynamicArray inArgs)
{
if (!info->isEnum)
return Dynamic();
int index = info->getEnumIndex(inName);
return info->enumConstructors[index]->create(inArgs);
}
bool VCanCast(hx::Object *inPtr)
{
if (!inPtr)
return false;
hx::Class c = inPtr->__GetClass();
if (!c.mPtr)
return false;
if (info->isInterface)
{
// Can only be this cppia interface if it is a cppia class...
CppiaClass *cppiaClass = dynamic_cast<CppiaClass *>(c.mPtr);
if (!cppiaClass)
return false;
return cppiaClass->info->implementsInterface(info);
}
hx::Class_obj *classPtr = c.mPtr;
while(classPtr)
{
if (classPtr==this)
return true;
if (info->isEnum)
return false;
classPtr = classPtr->GetSuper().mPtr;
}
return false;
}
hx::Val __Field(const String &inName,hx::PropertyAccess inCallProp)
{
if (inName==HX_CSTRING("__meta__"))
return __meta__;
return info->getStaticValue(inName,inCallProp);
}
hx::Val __SetField(const String &inName,const hx::Val &inValue ,hx::PropertyAccess inCallProp)
{
return info->setStaticValue(inName,inValue,inCallProp);
}
bool __HasField(const String &inName)
{
if (inName==HX_CSTRING("__meta__"))
return __meta__!=null();
return info->hasStaticValue(inName);
}
};
hx::Class_obj *createCppiaClass(CppiaClassInfo *inInfo) { return new CppiaClass(inInfo); }
// --- Enum Base ---
::hx::ObjectPtr<hx::Class_obj > CppiaEnumBase::__GetClass() const
{
return classInfo->getClass();
}
::String CppiaEnumBase::GetEnumName( ) const
{
return classInfo->getClass()->mName;
}
::String CppiaEnumBase::__ToString() const
{
#if (HXCPP_API_LEVEL>=330)
return classInfo->getClass()->mName + HX_CSTRING(".") + _hx_tag;
#else
return classInfo->getClass()->mName + HX_CSTRING(".") + tag;
#endif
}
void cppiaClassInit(CppiaClassInfo *inClass, CppiaCtx *ctx, int inPhase)
{
inClass->init(ctx,inPhase);
}
void cppiaClassMark(CppiaClassInfo *inClass,hx::MarkContext *__inCtx)
{
inClass->mark(__inCtx);
}
#ifdef HXCPP_VISIT_ALLOCS
void cppiaClassVisit(CppiaClassInfo *inClass,hx::VisitContext *__inCtx)
{
inClass->visit(__inCtx);
}
#endif
void linkCppiaClass(hx::Class_obj *inClass, CppiaModule &cppia, String inName)
{
((CppiaClass *)inClass)->linkClass(cppia,inName);
}
int getScriptId(hx::Class inClass)
{
hx::Class_obj *ptr = inClass.mPtr;
if (!ptr)
return 0;
CppiaClass *cls = dynamic_cast<CppiaClass *>(ptr);
if (!cls)
return 0;
return cls->info->cppia.scriptId;
}
::String ScriptableToString(void *inClass)
{
CppiaClassInfo *info = (CppiaClassInfo *)inClass;
return info->getClass()->toString();
}
int ScriptableGetType(void *inClass)
{
CppiaClassInfo *info = (CppiaClassInfo *)inClass;
return info->__GetType();
}
hx::Class ScriptableGetClass(void *inClass)
{
CppiaClassInfo *info = (CppiaClassInfo *)inClass;
return info->getClass();
}
// Called by haxe generated code ...
void ScriptableMark(void *inClass, hx::Object *inThis, hx::MarkContext *__inCtx)
{
((CppiaClassInfo *)inClass)->markInstance(inThis, __inCtx);
}
#ifdef HXCPP_VISIT_ALLOCS
void ScriptableVisit(void *inClass, hx::Object *inThis, hx::VisitContext *__inCtx)
{
((CppiaClassInfo *)inClass)->visitInstance(inThis, __inCtx);
}
#endif
bool ScriptableField(hx::Object *inObj, const ::String &inName,hx::PropertyAccess inCallProp,Dynamic &outResult)
{
void **vtable = inObj->__GetScriptVTable();
return ((CppiaClassInfo *)vtable[-1])->getField(inObj,inName,inCallProp,outResult);
}
bool ScriptableField(hx::Object *inObj, int inName,hx::PropertyAccess inCallProp,Float &outResult)
{
void **vtable = inObj->__GetScriptVTable();
Dynamic result;
if ( ((CppiaClassInfo *)vtable[-1])->getField(inObj,__hxcpp_field_from_id(inName),inCallProp,result) )
{
//CPPIA_CHECK(result);
if (result.mPtr)
outResult = result->__ToDouble();
else
outResult = 0;
return true;
}
return false;
}
bool ScriptableField(hx::Object *inObj, int inName,hx::PropertyAccess inCallProp,Dynamic &outResult)
{
void **vtable = inObj->__GetScriptVTable();
return ((CppiaClassInfo *)vtable[-1])->getField(inObj,__hxcpp_field_from_id(inName),inCallProp,outResult);
}
void ScriptableGetFields(hx::Object *inObject, Array< ::String> &outFields)
{
void **vtable = inObject->__GetScriptVTable();
return ((CppiaClassInfo *)vtable[-1])->GetInstanceFields(inObject,outFields);
}
bool ScriptableSetField(hx::Object *inObj, const ::String &inName, Dynamic inValue,hx::PropertyAccess inCallProp, Dynamic &outResult)
{
void **vtable = inObj->__GetScriptVTable();
return ((CppiaClassInfo *)vtable[-1])->setField(inObj,inName,inValue,inCallProp,outResult);
}
#if (HXCPP_API_LEVEL >= 330)
void *hx::Object::_hx_getInterface(int inId)
{
void **vtable = __GetScriptVTable();
if (!vtable)
return 0;
CppiaClassInfo *info = ((CppiaClassInfo *)vtable[-1]);
void *result = info->interfaceScriptTables[inId];
return info->interfaceScriptTables[inId];
}
#endif
} // end namespace hx