BsScriptScriptCode.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #include "BsScriptScriptCode.h"
  2. #include "BsScriptResourceManager.h"
  3. #include "BsScriptMeta.h"
  4. #include "BsMonoField.h"
  5. #include "BsMonoClass.h"
  6. #include "BsMonoManager.h"
  7. #include "BsMonoUtil.h"
  8. #include "BsScriptAssemblyManager.h"
  9. #include "BsManagedSerializableObjectInfo.h"
  10. #include <regex>
  11. using namespace std::placeholders;
  12. namespace BansheeEngine
  13. {
  14. ScriptScriptCode::ScriptScriptCode(MonoObject* instance, const HScriptCode& scriptCode)
  15. :ScriptObject(instance), mScriptCode(scriptCode)
  16. {
  17. }
  18. void ScriptScriptCode::initRuntimeData()
  19. {
  20. metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptScriptCode::internal_createInstance);
  21. metaData.scriptClass->addInternalCall("Internal_GetText", &ScriptScriptCode::internal_getText);
  22. metaData.scriptClass->addInternalCall("Internal_SetText", &ScriptScriptCode::internal_setText);
  23. metaData.scriptClass->addInternalCall("Internal_GetTypes", &ScriptScriptCode::internal_getTypes);
  24. }
  25. void ScriptScriptCode::internal_createInstance(MonoObject* instance, MonoString* text)
  26. {
  27. WString strText = MonoUtil::monoToWString(text);
  28. HScriptCode scriptCode = ScriptCode::create(strText);
  29. ScriptScriptCode* scriptInstance;
  30. ScriptResourceManager::instance().createScriptResource(instance, scriptCode, &scriptInstance);
  31. }
  32. MonoString* ScriptScriptCode::internal_getText(ScriptScriptCode* thisPtr)
  33. {
  34. HScriptCode scriptCode = thisPtr->mScriptCode;
  35. return MonoUtil::wstringToMono(MonoManager::instance().getDomain(), scriptCode->getString());
  36. }
  37. void ScriptScriptCode::internal_setText(ScriptScriptCode* thisPtr, MonoString* text)
  38. {
  39. HScriptCode scriptCode = thisPtr->mScriptCode;
  40. scriptCode->setString(MonoUtil::monoToWString(text));
  41. }
  42. MonoArray* ScriptScriptCode::internal_getTypes(ScriptScriptCode* thisPtr)
  43. {
  44. Vector<FullTypeName> types;
  45. if (thisPtr->getScriptCodeHandle().isLoaded())
  46. types = parseTypes(thisPtr->getScriptCodeHandle()->getString());
  47. Vector<MonoReflectionType*> validTypes;
  48. for (auto& type : types)
  49. {
  50. ManagedSerializableObjectInfoPtr objInfo;
  51. if (ScriptAssemblyManager::instance().getSerializableObjectInfo(toString(type.first), toString(type.second), objInfo))
  52. {
  53. MonoType* monoType = mono_class_get_type(objInfo->mTypeInfo->getMonoClass());
  54. validTypes.push_back(mono_type_get_object(MonoManager::instance().getDomain(), monoType));
  55. }
  56. }
  57. UINT32 numValidTypes = (UINT32)validTypes.size();
  58. MonoClass* typeClass = ScriptAssemblyManager::instance().getSystemTypeClass();
  59. MonoArray* output = mono_array_new(MonoManager::instance().getDomain(), typeClass->_getInternalClass(), numValidTypes);
  60. for (UINT32 i = 0; i < numValidTypes; i++)
  61. mono_array_set(output, MonoReflectionType*, i, validTypes[i]);
  62. return output;
  63. }
  64. void ScriptScriptCode::_onManagedInstanceDeleted()
  65. {
  66. mManagedInstance = nullptr;
  67. if (!mRefreshInProgress)
  68. ScriptResourceManager::instance().destroyScriptResource(this);
  69. }
  70. void ScriptScriptCode::setNativeHandle(const HResource& resource)
  71. {
  72. mScriptCode = static_resource_cast<ScriptCode>(resource);
  73. }
  74. Vector<ScriptScriptCode::FullTypeName> ScriptScriptCode::parseTypes(const WString& code)
  75. {
  76. struct NamespaceData
  77. {
  78. WString ns;
  79. INT32 bracketIdx;
  80. };
  81. Vector<FullTypeName> output;
  82. Stack<NamespaceData> namespaces;
  83. // Note: Won't match unicode escape sequences
  84. WString identifierPattern = LR"([_@a-zA-Z][\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\p{Cf}]*)";
  85. std::wregex identifierRegex(identifierPattern, std::regex_constants::ECMAScript | std::regex_constants::icase);
  86. WString nsToken = L"namespace";
  87. WString classToken = L"class";
  88. UINT32 idx = 0;
  89. INT32 bracketIdx = 0;
  90. for (auto iter = code.begin(); iter != code.end(); ++iter)
  91. {
  92. wchar_t ch = *iter;
  93. if (code.compare(idx, classToken.size(), classToken))
  94. {
  95. std::wsmatch results;
  96. if (std::regex_match(iter + classToken.size(), code.end(), results, identifierRegex))
  97. {
  98. WString ns = L"";
  99. if (!namespaces.empty())
  100. ns = namespaces.top().ns;
  101. std::wstring tempStr = results[0];
  102. WString typeName = tempStr.c_str();
  103. output.push_back(FullTypeName());
  104. FullTypeName& nsTypePair = output.back();
  105. nsTypePair.first = ns;
  106. nsTypePair.second = typeName;
  107. }
  108. }
  109. else if (code.compare(idx, nsToken.size(), nsToken))
  110. {
  111. std::wsmatch results;
  112. if (std::regex_match(iter + nsToken.size(), code.end(), results, identifierRegex))
  113. {
  114. std::wstring tempStr = results[0];
  115. WString ns = tempStr.c_str();
  116. namespaces.push({ ns, bracketIdx + 1 });
  117. }
  118. }
  119. else if (ch == '{')
  120. {
  121. bracketIdx++;
  122. }
  123. else if (ch == '}')
  124. {
  125. bracketIdx--;
  126. }
  127. idx++;
  128. }
  129. return output;
  130. }
  131. }