1
0
forked from Onek8/LNXSDK
Files
LNXSDK/Kha/Backends/Kinc-hxcpp/khacpp/src/hx/cppia/CppiaModule.cpp

661 lines
15 KiB
C++
Raw Normal View History

2025-01-22 16:18:30 +01:00
#include <hxcpp.h>
#include "Cppia.h"
#include "CppiaStream.h"
#include <stdlib.h>
namespace hx
{
static int sScriptId = 0;
const char **sgNativeNameSlots = 0;
int sgNativeNameSlotCount = 0;
Array<Dynamic> gAllCppiaModules;
std::vector<hx::Resource> scriptResources;
// --- CppiaModule ----
CppiaModule::CppiaModule()
{
main = 0;
layout = 0;
creatingClass = 0;
creatingFunction = 0;
scriptId = ++sScriptId;
strings = Array_obj<String>::__new(0,0);
if (sgNativeNameSlotCount>0)
for(int i=2;i<sgNativeNameSlotCount;i++)
interfaceSlots[sgNativeNameSlots[i]] = i;
}
void CppiaModule::setDebug(CppiaExpr *outExpr, int inFileId, int inLine)
{
#ifdef HXCPP_DEBUGGER
if (inFileId)
allFileIds.insert(inFileId);
#endif
outExpr->className = creatingClass;
outExpr->functionName = creatingFunction;
//outExpr->filename = cStrings[inFileId].c_str();
outExpr->filename = strings[inFileId].utf8_str();
outExpr->line = inLine;
}
// --- CppiaModule -------------------------
CppiaModule::~CppiaModule()
{
delete main;
for(int i=0;i<classes.size();i++)
delete classes[i];
}
void CppiaModule::link()
{
DBGLOG("Resolve registered - super\n");
HaxeNativeClass::link();
DBGLOG("Resolve typeIds\n");
for(int t=0;t<types.size();t++)
types[t]->link(*this);
DBGLOG("Resolve inherited atributes\n");
for(int i=0;i<classes.size();i++)
{
classes[i]->linkTypes();
}
for(int i=0;i<classes.size();i++)
{
linkingClass = classes[i];
classes[i]->link();
}
linkingClass = 0;
if (main)
main = (ScriptCallable *)main->link(*this);
}
#ifdef CPPIA_JIT
void CppiaModule::compile()
{
for(int i=0;i<classes.size();i++)
classes[i]->compile();
if (main)
main->compile();
}
#endif
void addScriptableClass(String inName);
void addScriptableFile(String inName);
void CppiaModule::registerDebugger()
{
#ifdef HXCPP_DEBUGGER
for(int i=0;i<classes.size();i++)
{
String scriptable(classes[i]->name.c_str());
addScriptableClass( scriptable.makePermanent().utf8_str() );
}
for(hx::UnorderedSet<int>::const_iterator i = allFileIds.begin(); i!=allFileIds.end(); ++i)
addScriptableFile(strings[*i]);
#endif
}
CppiaClassInfo *CppiaModule::findClass( ::String inName)
{
std::string stdName(inName.utf8_str());
for(int i=0;i<classes.size();i++)
if (classes[i]->name == stdName)
return classes[i];
return 0;
}
void CppiaModule::mark(hx::MarkContext *__inCtx)
{
DBGLOG(" --- MARK --- \n");
HX_MARK_MEMBER(strings);
for(int i=0;i<types.size();i++)
{
if (types[i]) /* May be partially constructed */
types[i]->mark(__inCtx);
}
for(int i=0;i<markable.size();i++)
{
markable[i]->mark(__inCtx);
}
for(int i=0;i<classes.size();i++)
if (classes[i])
{
classes[i]->mark(__inCtx);
}
}
#ifdef HXCPP_VISIT_ALLOCS
void CppiaModule::visit(hx::VisitContext *__inCtx)
{
HX_VISIT_MEMBER(strings);
for(int i=0;i<types.size();i++)
types[i]->visit(__inCtx);
for(int i=0;i<markable.size();i++)
markable[i]->visit(__inCtx);
for(int i=0;i<classes.size();i++)
if (classes[i])
classes[i]->visit(__inCtx);
}
#endif
void cppiaClassInit(CppiaClassInfo *inClass, CppiaCtx *ctx, int inPhase);
void CppiaModule::boot(CppiaCtx *ctx)
{
// boot (statics)
for(int i=0;i<classes.size();i++)
cppiaClassInit(classes[i],ctx,0);
// run __init__
for(int i=0;i<classes.size();i++)
cppiaClassInit(classes[i],ctx,1);
}
int CppiaModule::getInterfaceSlot(const std::string &inName)
{
InterfaceSlots::iterator it = interfaceSlots.find(inName);
if (it==interfaceSlots.end())
{
#if (HXCPP_API_LEVEL >= 330)
int result = interfaceSlots.size()+1;
#else
int result = interfaceSlots.size()+2;
#endif
interfaceSlots[inName] = result;
return result;
}
return it->second;
}
int CppiaModule::findInterfaceSlot(const std::string &inName)
{
InterfaceSlots::iterator it = interfaceSlots.find(inName);
if (it==interfaceSlots.end())
return -1;
return it->second;
}
void CppiaModule::where(CppiaExpr *e)
{
if (linkingClass && layout)
CPPIALOG(" in %s::%p\n", linkingClass->name.c_str(), layout);
CPPIALOG(" %s at %s:%d %s\n", e->getName(), e->filename, e->line, e->functionName);
}
void ScriptableRegisterNameSlots(const char *inNames[], int inLength)
{
sgNativeNameSlots = inNames;
sgNativeNameSlotCount = inLength;
}
// --- CppiaConst -------------------------------------------
CppiaConst::CppiaConst() : type(cNull), ival(0), dval(0) { }
void CppiaConst::fromStream(CppiaStream &stream)
{
std::string tok = stream.getToken();
if (tok[0]=='i')
{
type = cInt;
dval = ival = stream.getInt();
}
else if (tok=="true")
{
type = cInt;
dval = ival = 1;
}
else if (tok=="false")
{
type = cInt;
dval = ival = 0;
}
else if (tok[0]=='f')
{
type = cFloat;
int strIndex = stream.getInt();
String val = stream.module->strings[strIndex];
dval = atof(val.out_str());
ival = dval;
}
else if (tok[0]=='s')
{
type = cString;
ival = stream.getInt();
}
else if (tok=="NULL")
type = cNull;
else if (tok=="THIS")
type = cThis;
else if (tok=="SUPER")
type = cSuper;
else
throw "unknown const value";
}
// --- CppiaLoadedModule -------------------------------------------
// Cppia Object - manage
class CppiaObject : public hx::CppiaLoadedModule_obj
{
public:
CppiaModule *cppia;
bool booted;
CppiaObject(CppiaModule *inModule)
{
cppia = inModule;
GCSetFinalizer( this, onRelease );
}
static void onRelease(hx::Object *inObj)
{
delete ((CppiaObject *)inObj)->cppia;
}
void __Mark(hx::MarkContext *ctx) { cppia->mark(ctx); }
#ifdef HXCPP_VISIT_ALLOCS
void __Visit(hx::VisitContext *ctx) { cppia->visit(ctx); }
#endif
void boot()
{
if (booted)
return;
booted = true;
try
{
DBGLOG("--- Boot --------------------------------------------\n");
CppiaCtx *ctx = CppiaCtx::getCurrent();
cppia->boot(ctx);
}
catch(const char *errorString)
{
String error(errorString);
hx::Throw(error);
}
}
void run()
{
if (!booted)
boot();
if (cppia->main)
{
try
{
//__hxcpp_enable(false);
DBGLOG("--- Run --------------------------------------------\n");
CppiaCtx *ctx = CppiaCtx::getCurrent();
ctx->runVoid(cppia->main);
if (ctx->exception)
{
hx::Object *e = ctx->exception;
ctx->exception = 0;
hx::Throw( Dynamic(e) );
}
}
catch(const char *errorString)
{
String error(errorString);
hx::Throw(error);
}
}
}
::hx::Class resolveClass( ::String inName)
{
CppiaClassInfo *info = cppia->findClass(inName);
if (info)
return info->getClass();
return null();
}
};
CppiaLoadedModule LoadCppia(const unsigned char *inData, int inDataLength)
{
if (!gAllCppiaModules.mPtr)
{
gAllCppiaModules = Array_obj<Dynamic>::__new();
GCAddRoot( (hx::Object **)&gAllCppiaModules.mPtr );
}
CppiaModule *cppiaPtr = new CppiaModule();
CppiaLoadedModule loadedModule = new CppiaObject(cppiaPtr);
gAllCppiaModules->push(loadedModule);
CppiaModule &cppia = *cppiaPtr;
CppiaStream stream(cppiaPtr,inData, inDataLength);
String error;
try
{
std::string tok = stream.getAsciiToken();
if (tok!="CPPIA" && tok!="CPPIB")
throw "Bad magic";
stream.setBinary(tok=="CPPIB");
int stringCount = stream.getAsciiInt();
for(int s=0;s<stringCount;s++)
cppia.strings[s] = stream.readString();
int typeCount = stream.getAsciiInt();
cppia.types.resize(typeCount);
DBGLOG("Type count : %d\n", typeCount);
for(int t=0;t<typeCount;t++)
cppia.types[t] = new TypeData(stream.readString());
int classCount = stream.getAsciiInt();
DBGLOG("Class count : %d\n", classCount);
if (stream.binary)
{
int newLine = stream.getByte();
if (newLine!='\n')
throw "Missing new-line after class count";
}
cppia.classes.reserve(classCount);
for(int c=0;c<classCount;c++)
{
CppiaClassInfo *info = new CppiaClassInfo(cppia);
if (info->load(stream))
cppia.classes.push_back(info);
}
tok = stream.getToken();
if (tok=="MAIN")
{
DBGLOG("Main...\n");
cppia.main = new ScriptCallable(createCppiaExpr(stream));
cppia.main->className = "cppia";
cppia.main->functionName = "__cppia_main";
}
else if (tok!="NOMAIN")
throw "no main specified";
tok = stream.getToken();
if (tok=="RESOURCES")
{
int count = stream.getInt( );
scriptResources.resize(count+1);
for(int r=0;r<count;r++)
{
tok = stream.getToken();
if (tok!="RESO")
throw "no reso tag";
scriptResources[r].mName = cppia.strings[stream.getInt()];
scriptResources[r].mDataLength = stream.getInt();
}
if (!stream.binary)
stream.skipChar();
for(int r=0;r<count;r++)
{
int len = scriptResources[r].mDataLength;
unsigned char *buffer = (unsigned char *)malloc(len+5);
*(unsigned int *)buffer = HX_GC_CONST_ALLOC_BIT;
buffer[len+5-1] = '\0';
stream.readBytes(buffer+4, len);
#ifdef HX_SMART_STRINGS_1
unsigned char *p = (unsigned char *)buffer+4;
unsigned char *end = p + len;
while(!hasBig && p<end)
if (*p++>127)
{
*(unsigned int *)buffer |= HX_GC_STRING_CHAR16_T;
break;
}
#endif
scriptResources[r].mData = buffer + 4;
}
scriptResources[count].mDataLength = 0;
scriptResources[count].mData = 0;
scriptResources[count].mName = String();
RegisterResources(&scriptResources[0]);
}
else
throw "no resources tag";
}
catch(const char *errorString)
{
error = HX_CSTRING("Error reading file ") + String(errorString) +
HX_CSTRING(", line ") + String(stream.line) + HX_CSTRING(", char ") +
String(stream.pos);
}
if (!error.raw_ptr())
try
{
DBGLOG("Link...\n");
cppia.link();
}
catch(const char *errorString)
{
error = String(errorString);
}
if (gEnableJit)
{
#ifdef CPPIA_JIT
if (!error.raw_ptr())
try
{
DBGLOG("Compile...\n");
cppia.compile();
}
catch(const char *errorString)
{
error = String(errorString);
}
#endif
}
if (error.raw_ptr())
hx::Throw(error);
cppia.registerDebugger();
return loadedModule;
}
Array<String > gAllClasses;
Array<String > gAllFiles;
void addScriptableClass(String inName)
{
#ifdef HXCPP_DEBUGGER
if (!gAllClasses.mPtr)
{
gAllClasses = Array_obj<Dynamic>::__new();
GCAddRoot( (hx::Object **)&gAllClasses.mPtr );
}
if (gAllClasses->indexOf(inName)<0)
gAllClasses->push(inName);
#endif
}
void addScriptableFile(String inName)
{
#ifdef HXCPP_DEBUGGER
if (!gAllFiles.mPtr)
{
gAllFiles = Array_obj<Dynamic>::__new();
GCAddRoot( (hx::Object **)&gAllFiles.mPtr );
}
if (gAllFiles->indexOf(inName)<0)
gAllFiles->push(inName);
#endif
}
} // end namespace hx
#ifdef HXCPP_STACK_SCRIPTABLE
void __hxcpp_dbg_getScriptableVariables(hx::StackFrame *inFrame, ::Array<Dynamic> outNames)
{
hx::ScriptCallable *callable = inFrame->position->scriptCallable;
if (callable)
callable->getScriptableVariables((unsigned char *)inFrame, outNames);
}
bool __hxcpp_dbg_getScriptableValue(hx::StackFrame *inFrame, String inName, ::Dynamic &outValue)
{
hx::ScriptCallable *callable = inFrame->position->scriptCallable;
if (callable)
return callable->getScriptableValue((unsigned char *)inFrame, inName, outValue);
return false;
}
bool __hxcpp_dbg_setScriptableValue(hx::StackFrame *inFrame, String inName, ::Dynamic inValue)
{
hx::ScriptCallable *callable = inFrame->position->scriptCallable;
if (callable)
return callable->setScriptableValue((unsigned char *)inFrame, inName, inValue);
return false;
}
#endif
#ifdef HXCPP_DEBUGGER
void __hxcpp_dbg_getScriptableFiles( Array< ::String> ioPaths )
{
Array<String> merge = hx::gAllFiles;
if (merge.mPtr)
for(int i=0;i< merge->length; i++)
{
if (ioPaths->indexOf( merge[i] ) < 0)
ioPaths->push( merge[i] );
}
}
void __hxcpp_dbg_getScriptableFilesFullPath( Array< ::String> ioPaths )
{
__hxcpp_dbg_getScriptableFiles( ioPaths );
}
void __hxcpp_dbg_getScriptableClasses( Array< ::String> ioClasses )
{
Array<String> merge = hx::gAllClasses;
if (merge.mPtr)
for(int i=0;i< merge->length; i++)
{
if (ioClasses->indexOf( merge[i] ) < 0)
ioClasses->push( merge[i] );
}
}
#endif
::hx::CppiaLoadedModule __scriptable_cppia_from_string(String inCode)
{
const unsigned char *code = (const unsigned char *)inCode.raw_ptr();
int length = inCode.length;
#ifdef HX_SMART_STRINGS
if (inCode.isUTF16Encoded())
{
code = (const unsigned char *)inCode.utf8_str();
length = strlen( (const char *)code );
}
#endif
return hx::LoadCppia(code,length);
}
::hx::CppiaLoadedModule __scriptable_cppia_from_data(Array<unsigned char> inCode)
{
return hx::LoadCppia( (unsigned char *)inCode->GetBase() ,inCode->length);
}
void __scriptable_load_cppia(String inCode)
{
const unsigned char *code = (const unsigned char *)inCode.raw_ptr();
int length = inCode.length;
#ifdef HX_SMART_STRINGS
if (inCode.isUTF16Encoded())
{
code = (const unsigned char *)inCode.utf8_str();
length = strlen( (const char *)code );
}
#endif
::hx::CppiaLoadedModule module = hx::LoadCppia(code,length);
module->boot();
module->run();
}