852 lines
27 KiB
C++
852 lines
27 KiB
C++
//
|
|
// Copyright (c) 2008-2021 the Urho3D project.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
//
|
|
|
|
#include "ASUtils.h"
|
|
#include "Tuning.h"
|
|
#include "Utils.h"
|
|
#include "XmlAnalyzer.h"
|
|
#include "XmlSourceData.h"
|
|
|
|
#include <cassert>
|
|
#include <regex>
|
|
|
|
namespace ASBindingGenerator
|
|
{
|
|
|
|
// https://www.angelcode.com/angelscript/sdk/docs/manual/doc_datatypes_primitives.html
|
|
// https://en.cppreference.com/w/cpp/language/types
|
|
string CppPrimitiveTypeToAS(const string& cppType)
|
|
{
|
|
if (cppType == "bool")
|
|
return "bool";
|
|
|
|
if (cppType == "char" || cppType == "signed char")
|
|
return "int8";
|
|
|
|
if (cppType == "unsigned char")
|
|
return "uint8";
|
|
|
|
if (cppType == "short")
|
|
return "int16";
|
|
|
|
if (cppType == "unsigned short")
|
|
return "uint16";
|
|
|
|
if (cppType == "int")
|
|
return "int";
|
|
|
|
if (cppType == "unsigned" || cppType == "unsigned int")
|
|
return "uint";
|
|
|
|
if (cppType == "long long")
|
|
return "int64";
|
|
|
|
if (cppType == "unsigned long long")
|
|
return "uint64";
|
|
|
|
if (cppType == "float")
|
|
return "float";
|
|
|
|
if (cppType == "double")
|
|
return "double";
|
|
|
|
// Types below are registered in Manual.cpp
|
|
|
|
if (cppType == "long")
|
|
return "long";
|
|
|
|
if (cppType == "unsigned long")
|
|
return "ulong";
|
|
|
|
if (cppType == "size_t")
|
|
return "size_t";
|
|
|
|
if (cppType == "SDL_JoystickID")
|
|
return "SDL_JoystickID";
|
|
|
|
throw Exception(cppType + " not a primitive type");
|
|
}
|
|
|
|
string JoinASDeclarations(const vector<ConvertedVariable>& vars)
|
|
{
|
|
string result;
|
|
|
|
for (const ConvertedVariable& var : vars)
|
|
{
|
|
if (!var.asDeclaration_.empty())
|
|
{
|
|
if (!result.empty())
|
|
result += ", ";
|
|
|
|
result += var.asDeclaration_;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
string JoinCppDeclarations(const string& firstCppDeclaration, const vector<ConvertedVariable>& vars)
|
|
{
|
|
string result = firstCppDeclaration;
|
|
|
|
for (const ConvertedVariable& var : vars)
|
|
{
|
|
if (!var.cppDeclaration_.empty())
|
|
{
|
|
if (!result.empty())
|
|
result += ", ";
|
|
|
|
result += var.cppDeclaration_;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
string JoinCppDeclarations(const vector<ConvertedVariable>& vars)
|
|
{
|
|
return JoinCppDeclarations("", vars);
|
|
}
|
|
|
|
shared_ptr<EnumAnalyzer> FindEnum(const string& name)
|
|
{
|
|
NamespaceAnalyzer namespaceAnalyzer(SourceData::namespaceUrho3D_);
|
|
vector<EnumAnalyzer> enumAnalyzers = namespaceAnalyzer.GetEnums();
|
|
|
|
for (const EnumAnalyzer& enumAnalyzer : enumAnalyzers)
|
|
{
|
|
if (enumAnalyzer.GetTypeName() == name)
|
|
return make_shared<EnumAnalyzer>(enumAnalyzer);
|
|
}
|
|
|
|
return shared_ptr<EnumAnalyzer>();
|
|
}
|
|
|
|
static bool IsUsing(const string& identifier)
|
|
{
|
|
for (xml_node memberdef : SourceData::usings_)
|
|
{
|
|
UsingAnalyzer usingAnalyzer(memberdef);
|
|
|
|
if (usingAnalyzer.GetName() == identifier)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool IsKnownCppType(const string& name)
|
|
{
|
|
static vector<string> _knownTypes = {
|
|
"void",
|
|
"bool",
|
|
"size_t",
|
|
"char",
|
|
"signed char",
|
|
"unsigned char",
|
|
"short",
|
|
"unsigned short",
|
|
"int",
|
|
"long",
|
|
"unsigned",
|
|
"unsigned int",
|
|
"unsigned long",
|
|
"long long",
|
|
"unsigned long long",
|
|
"float",
|
|
"double",
|
|
"SDL_JoystickID",
|
|
|
|
// TODO: Remove
|
|
"VariantMap",
|
|
};
|
|
|
|
if (CONTAINS(_knownTypes, name))
|
|
return true;
|
|
|
|
if (SourceData::classesByName_.find(name) != SourceData::classesByName_.end())
|
|
return true;
|
|
|
|
if (SourceData::enums_.find(name) != SourceData::enums_.end())
|
|
return true;
|
|
|
|
if (EndsWith(name, "Flags"))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
shared_ptr<ClassAnalyzer> FindClassByName(const string& name)
|
|
{
|
|
auto it = SourceData::classesByName_.find(name);
|
|
if (it != SourceData::classesByName_.end())
|
|
{
|
|
xml_node compounddef = it->second;
|
|
return make_shared<ClassAnalyzer>(compounddef);
|
|
}
|
|
|
|
// using VariantVector = Vector<Variant>
|
|
|
|
return shared_ptr<ClassAnalyzer>();
|
|
}
|
|
|
|
shared_ptr<ClassAnalyzer> FindClassByID(const string& id)
|
|
{
|
|
auto it = SourceData::classesByID_.find(id);
|
|
if (it != SourceData::classesByID_.end())
|
|
{
|
|
xml_node compounddef = it->second;
|
|
return make_shared<ClassAnalyzer>(compounddef);
|
|
}
|
|
|
|
// using VariantVector = Vector<Variant>
|
|
|
|
return shared_ptr<ClassAnalyzer>();
|
|
}
|
|
|
|
// Variable name can be empty for function return type
|
|
ConvertedVariable CppVariableToAS(const TypeAnalyzer& type, VariableUsage usage, const string& name, const string& defaultValue)
|
|
{
|
|
ConvertedVariable result;
|
|
|
|
if (type.IsRvalueReference() || type.IsDoublePointer() || type.IsRefToPointer())
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
|
|
string cppTypeName = type.GetNameWithTemplateParams();
|
|
|
|
if (cppTypeName == "void")
|
|
{
|
|
if (usage == VariableUsage::FunctionReturn && !type.IsPointer())
|
|
{
|
|
result.asDeclaration_ = "void";
|
|
result.cppDeclaration_ = "void";
|
|
return result;
|
|
}
|
|
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
}
|
|
|
|
if (cppTypeName == "Context")
|
|
{
|
|
if (usage == VariableUsage::FunctionParameter && type.IsPointer())
|
|
{
|
|
result.glue_ = " " + type.ToString() + " " + name + " = GetScriptContext();\n";
|
|
return result;
|
|
}
|
|
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can used only as function parameter");
|
|
}
|
|
|
|
// Works with both Vector<String> and Vector<String>&
|
|
if (cppTypeName == "Vector<String>" || cppTypeName == "StringVector")
|
|
{
|
|
// Works with both Vector<String> and Vector<String>&
|
|
if (usage == VariableUsage::FunctionReturn && !type.IsPointer())
|
|
{
|
|
result.asDeclaration_ = "Array<String>@";
|
|
result.cppDeclaration_ = "CScriptArray*";
|
|
result.glue_ = "return VectorToArray<String>(result, \"Array<String>\");\n";
|
|
return result;
|
|
}
|
|
|
|
if (usage == VariableUsage::FunctionParameter && type.IsConst() && type.IsReference())
|
|
{
|
|
string newCppVarName = name + "_conv";
|
|
|
|
//result->asDecl_ = "String[]&";
|
|
result.asDeclaration_ = "Array<String>@+";
|
|
result.cppDeclaration_ = "CScriptArray* " + newCppVarName;
|
|
result.glue_ = " " + cppTypeName + " " + name + " = ArrayToVector<String>(" + newCppVarName + ");\n";
|
|
|
|
if (!defaultValue.empty())
|
|
{
|
|
assert(defaultValue == "Vector< String >()");
|
|
//result->asDecl_ += " = Array<String>()";
|
|
result.asDeclaration_ += " = null";
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
}
|
|
|
|
smatch match;
|
|
|
|
regex_match(cppTypeName, match, regex("SharedPtr<(\\w+)>"));
|
|
if (!match.empty())
|
|
{
|
|
string cppSubtypeName = match[1].str();
|
|
|
|
string asSubtypeName;
|
|
|
|
try
|
|
{
|
|
asSubtypeName = CppPrimitiveTypeToAS(cppSubtypeName);
|
|
}
|
|
catch (...)
|
|
{
|
|
asSubtypeName = cppSubtypeName;
|
|
}
|
|
|
|
if (cppSubtypeName == "WorkItem") // TODO autodetect
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
|
|
if (usage == VariableUsage::FunctionReturn)
|
|
{
|
|
result.asDeclaration_ = asSubtypeName + "@+";
|
|
result.cppDeclaration_ = cppSubtypeName + "*";
|
|
result.glue_ = "return result.Detach();\n";
|
|
return result;
|
|
}
|
|
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
}
|
|
|
|
regex_match(cppTypeName, match, regex("Vector<SharedPtr<(\\w+)>>"));
|
|
if (!match.empty())
|
|
{
|
|
string cppSubtypeName = match[1].str();
|
|
|
|
string asSubtypeName;
|
|
|
|
try
|
|
{
|
|
asSubtypeName = CppPrimitiveTypeToAS(cppSubtypeName);
|
|
}
|
|
catch (...)
|
|
{
|
|
asSubtypeName = cppSubtypeName;
|
|
}
|
|
|
|
if (cppSubtypeName == "WorkItem") // TODO autodetect
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
|
|
if (usage == VariableUsage::FunctionReturn)
|
|
{
|
|
result.asDeclaration_ = "Array<" + asSubtypeName + "@>@";
|
|
result.cppDeclaration_ = "CScriptArray*";
|
|
|
|
// Which variant is correct/better?
|
|
#if 0
|
|
result->glueResult_ = "return VectorToArray<SharedPtr<" + cppTypeName + ">>(result, \"Array<" + asTypeName + "@>@\");\n";
|
|
#else
|
|
result.glue_ = "return VectorToHandleArray(result, \"Array<" + asSubtypeName + "@>\");\n";
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
if (usage == VariableUsage::FunctionParameter && type.IsConst() && type.IsReference())
|
|
{
|
|
string newCppVarName = name + "_conv";
|
|
result.asDeclaration_ = "Array<" + asSubtypeName + "@>@+";
|
|
result.cppDeclaration_ = "CScriptArray* " + newCppVarName;
|
|
result.glue_ = " " + cppTypeName + " " + name + " = HandleArrayToVector<" + cppSubtypeName + ">(" + newCppVarName + ");\n";
|
|
|
|
assert(defaultValue.empty()); // TODO: make
|
|
|
|
return result;
|
|
}
|
|
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
}
|
|
|
|
regex_match(cppTypeName, match, regex("PODVector<(\\w+)\\*>"));
|
|
if (!match.empty())
|
|
{
|
|
string cppSubtypeName = match[1].str();
|
|
|
|
string asSubtypeName;
|
|
|
|
try
|
|
{
|
|
asSubtypeName = CppPrimitiveTypeToAS(cppSubtypeName);
|
|
}
|
|
catch (...)
|
|
{
|
|
asSubtypeName = cppSubtypeName;
|
|
}
|
|
|
|
if (usage == VariableUsage::FunctionReturn)
|
|
{
|
|
result.asDeclaration_ = "Array<" + asSubtypeName + "@>@";
|
|
result.cppDeclaration_ = "CScriptArray*";
|
|
result.glue_ = "return VectorToHandleArray(result, \"Array<" + asSubtypeName + "@>\");\n";
|
|
return result;
|
|
}
|
|
|
|
if (usage == VariableUsage::FunctionParameter && type.IsConst() && type.IsReference())
|
|
{
|
|
string newCppVarName = name + "_conv";
|
|
result.asDeclaration_ = "Array<" + asSubtypeName + "@>@";
|
|
result.cppDeclaration_ = "CScriptArray* " + newCppVarName;
|
|
result.glue_ = " " + cppTypeName + " " + name + " = ArrayToPODVector<" + cppSubtypeName + "*>(" + newCppVarName + ");\n";
|
|
|
|
assert(defaultValue.empty()); // TODO: make
|
|
|
|
return result;
|
|
}
|
|
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
}
|
|
|
|
regex_match(cppTypeName, match, regex("PODVector<(\\w+)>"));
|
|
if (!match.empty())
|
|
{
|
|
string cppSubtypeName = match[1].str();
|
|
|
|
string asSubtypeName;
|
|
|
|
try
|
|
{
|
|
asSubtypeName = CppPrimitiveTypeToAS(cppSubtypeName);
|
|
}
|
|
catch (...)
|
|
{
|
|
asSubtypeName = cppSubtypeName;
|
|
}
|
|
|
|
if (usage == VariableUsage::FunctionReturn && type.IsConst() == type.IsReference())
|
|
{
|
|
result.asDeclaration_ = "Array<" + asSubtypeName + ">@";
|
|
result.cppDeclaration_ = "CScriptArray*";
|
|
result.glue_ = "return VectorToArray(result, \"Array<" + asSubtypeName + ">\");\n";
|
|
return result;
|
|
}
|
|
|
|
if (usage == VariableUsage::FunctionParameter && type.IsConst() && type.IsReference())
|
|
{
|
|
string newCppVarName = name + "_conv";
|
|
result.asDeclaration_ = "Array<" + asSubtypeName + ">@+";
|
|
result.cppDeclaration_ = "CScriptArray* " + newCppVarName;
|
|
result.glue_ = " " + cppTypeName + " " + name + " = ArrayToPODVector<" + cppSubtypeName + ">(" + newCppVarName + ");\n";
|
|
|
|
assert(defaultValue.empty()); // TODO: make
|
|
|
|
return result;
|
|
}
|
|
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
}
|
|
|
|
if (!IsKnownCppType(cppTypeName))
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
|
|
shared_ptr<ClassAnalyzer> analyzer = FindClassByName(cppTypeName);
|
|
if (analyzer && analyzer->IsInternal())
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind bacause internal");
|
|
|
|
if (analyzer && Contains(analyzer->GetComment(), "NO_BIND"))
|
|
throw Exception("Error: type \"" + cppTypeName + "\" can not automatically bind bacause have @nobind mark");
|
|
|
|
if (analyzer && analyzer->IsAbstract() && !(analyzer->IsRefCounted() || analyzer->IsNoCount()))
|
|
throw Exception("Error: type \"" + cppTypeName + "\" can not bind bacause abstract value");
|
|
|
|
// analyzer can be null for simple types (int, float) or if type "using VariantVector = Vector<Variant>"
|
|
// TODO add to type info "IsUsing"
|
|
// TODO add description to TypeAnalyzer::GetClass()
|
|
|
|
if (IsUsing(cppTypeName) && cppTypeName != "VariantMap")
|
|
throw Exception("Using \"" + cppTypeName + "\" can not automatically bind");
|
|
|
|
string asTypeName;
|
|
|
|
try
|
|
{
|
|
asTypeName = CppPrimitiveTypeToAS(cppTypeName);
|
|
}
|
|
catch (...)
|
|
{
|
|
asTypeName = cppTypeName;
|
|
}
|
|
|
|
if (Contains(asTypeName, '<'))
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
|
|
if (Contains(type.ToString(), "::"))
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind bacause internal");
|
|
|
|
if (usage == VariableUsage::FunctionParameter && type.IsConst() && type.IsReference())
|
|
{
|
|
result.asDeclaration_ = "const " + asTypeName + "&in";
|
|
result.cppDeclaration_ = type.ToString();
|
|
|
|
if (!name.empty())
|
|
result.cppDeclaration_ += " " + name;
|
|
|
|
if (!defaultValue.empty())
|
|
{
|
|
string asDefaultValue = CppValueToAS(defaultValue);
|
|
asDefaultValue = ReplaceAll(asDefaultValue, "\"", "\\\"");
|
|
result.asDeclaration_ += " = " + asDefaultValue;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
result.asDeclaration_ = asTypeName;
|
|
|
|
if (type.IsReference())
|
|
{
|
|
result.asDeclaration_ += "&";
|
|
}
|
|
else if (type.IsPointer())
|
|
{
|
|
shared_ptr<ClassAnalyzer> analyzer = FindClassByName(cppTypeName);
|
|
|
|
if (analyzer && (analyzer->IsRefCounted() || analyzer->IsNoCount()))
|
|
result.asDeclaration_ = result.asDeclaration_ + "@" + (analyzer->IsNoCount() ? "" : "+");
|
|
else
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
}
|
|
|
|
result.cppDeclaration_ = type.ToString();
|
|
|
|
if (!name.empty())
|
|
result.cppDeclaration_ += " " + name;
|
|
|
|
if (usage == VariableUsage::FunctionReturn && type.IsConst() && !type.IsPointer())
|
|
result.asDeclaration_ = "const " + result.asDeclaration_;
|
|
|
|
if (!defaultValue.empty())
|
|
{
|
|
string asDefaultValue = CppValueToAS(defaultValue);
|
|
asDefaultValue = ReplaceAll(asDefaultValue, "\"", "\\\"");
|
|
result.asDeclaration_ += " = " + asDefaultValue;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
string CppTypeToAS(const TypeAnalyzer& type, TypeUsage typeUsage)
|
|
{
|
|
if (type.IsRvalueReference() || type.IsDoublePointer() || type.IsRefToPointer())
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
|
|
string cppTypeName = type.GetNameWithTemplateParams();
|
|
|
|
if (cppTypeName == "Context" && typeUsage == TypeUsage::FunctionReturn)
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not be returned");
|
|
|
|
if (!IsKnownCppType(type.GetNameWithTemplateParams()))
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
|
|
shared_ptr<ClassAnalyzer> analyzer = FindClassByName(type.GetNameWithTemplateParams());
|
|
if (analyzer && analyzer->IsInternal())
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind bacause internal");
|
|
|
|
if (analyzer && Contains(analyzer->GetComment(), "NO_BIND"))
|
|
throw Exception("Error: type \"" + cppTypeName + "\" can not automatically bind bacause have @nobind mark");
|
|
|
|
// analyzer can be null for simple types (int, float) or if type "using VariantVector = Vector<Variant>"
|
|
// TODO add to type info "IsUsing"
|
|
// TODO add description to TypeAnalyzer::GetClass()
|
|
|
|
if (IsUsing(cppTypeName) && cppTypeName != "VariantMap")
|
|
throw Exception("Using \"" + cppTypeName + "\" can not automatically bind");
|
|
|
|
string asTypeName;
|
|
|
|
try
|
|
{
|
|
asTypeName = CppPrimitiveTypeToAS(cppTypeName);
|
|
}
|
|
catch (...)
|
|
{
|
|
asTypeName = cppTypeName;
|
|
}
|
|
|
|
if (asTypeName == "void" && type.IsPointer())
|
|
throw Exception("Error: type \"void*\" can not automatically bind");
|
|
|
|
if (Contains(asTypeName, '<'))
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
|
|
if (Contains(type.ToString(), "::"))
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind bacause internal");
|
|
|
|
if (type.IsConst() && type.IsReference() && typeUsage == TypeUsage::FunctionParameter)
|
|
return "const " + asTypeName + "&in";
|
|
|
|
string result = asTypeName;
|
|
|
|
if (type.IsReference())
|
|
{
|
|
result += "&";
|
|
}
|
|
else if (type.IsPointer())
|
|
{
|
|
shared_ptr<ClassAnalyzer> analyzer = FindClassByName(type.GetNameWithTemplateParams());
|
|
|
|
if (analyzer && (analyzer->IsRefCounted() || analyzer->IsNoCount()))
|
|
result = result + "@" + (analyzer->IsNoCount() ? "" : "+");
|
|
else
|
|
throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
|
|
}
|
|
|
|
if (typeUsage == TypeUsage::FunctionReturn && type.IsConst() && !type.IsPointer())
|
|
result = "const " + result;
|
|
|
|
return result;
|
|
}
|
|
|
|
string CppValueToAS(const string& cppValue)
|
|
{
|
|
if (cppValue == "nullptr")
|
|
return "null";
|
|
|
|
if (cppValue == "Variant::emptyVariantMap")
|
|
return "VariantMap()";
|
|
|
|
if (cppValue == "NPOS")
|
|
return "String::NPOS";
|
|
|
|
return cppValue;
|
|
}
|
|
|
|
// =================================================================================
|
|
|
|
static string GenerateFunctionWrapperName(xml_node memberdef)
|
|
{
|
|
TypeAnalyzer returnType = ExtractType(memberdef);
|
|
string result = ExtractType(memberdef).ToString() + "_" + ExtractName(memberdef);
|
|
vector<ParamAnalyzer> params = ExtractParams(memberdef);
|
|
|
|
if (params.size() == 0)
|
|
{
|
|
result += "_void";
|
|
}
|
|
else
|
|
{
|
|
for (ParamAnalyzer param : params)
|
|
{
|
|
result += "_" + param.GetType().ToString();
|
|
}
|
|
}
|
|
|
|
result = ReplaceAll(result, "=", "eq");
|
|
result = ReplaceAll(result, "<", "les");
|
|
result = ReplaceAll(result, ">", "gre");
|
|
result = ReplaceAll(result, "*", "star");
|
|
result = ReplaceAll(result, "/", "div");
|
|
result = ReplaceAll(result, "+", "plus");
|
|
result = ReplaceAll(result, "-", "min");
|
|
result = ReplaceAll(result, "[", "lbr");
|
|
result = ReplaceAll(result, "]", "rbr");
|
|
result = ReplaceAll(result, ":", "col");
|
|
result = ReplaceAll(result, " ", "sp");
|
|
result = ReplaceAll(result, "&", "amp");
|
|
|
|
return result;
|
|
}
|
|
|
|
string GenerateWrapperName(const GlobalFunctionAnalyzer& functionAnalyzer)
|
|
{
|
|
return GenerateFunctionWrapperName(functionAnalyzer.GetMemberdef());
|
|
}
|
|
|
|
string GenerateWrapperName(const ClassStaticFunctionAnalyzer& functionAnalyzer)
|
|
{
|
|
return functionAnalyzer.GetClassName() + "_" + GenerateFunctionWrapperName(functionAnalyzer.GetMemberdef());
|
|
}
|
|
|
|
string GenerateWrapperName(const MethodAnalyzer& methodAnalyzer, bool templateVersion)
|
|
{
|
|
if (templateVersion)
|
|
return methodAnalyzer.GetClassName() + "_" + GenerateFunctionWrapperName(methodAnalyzer.GetMemberdef()) + "_template";
|
|
else
|
|
return methodAnalyzer.GetClassName() + "_" + GenerateFunctionWrapperName(methodAnalyzer.GetMemberdef());
|
|
}
|
|
|
|
// =================================================================================
|
|
|
|
string GenerateWrapper(const GlobalFunctionAnalyzer& functionAnalyzer, const vector<ConvertedVariable>& convertedParams, const ConvertedVariable& convertedReturn)
|
|
{
|
|
string result;
|
|
|
|
string glueReturnType = convertedReturn.cppDeclaration_;
|
|
|
|
result =
|
|
"static " + glueReturnType + " " + GenerateWrapperName(functionAnalyzer) + "(" + JoinCppDeclarations(convertedParams) + ")\n"
|
|
"{\n";
|
|
|
|
for (size_t i = 0; i < convertedParams.size(); i++)
|
|
result += convertedParams[i].glue_;
|
|
|
|
if (glueReturnType != "void")
|
|
result += " " + functionAnalyzer.GetReturnType().ToString() + " result = ";
|
|
else
|
|
result += " ";
|
|
|
|
result += functionAnalyzer.GetName() + "(" + functionAnalyzer.JoinParamsNames() + ");\n";
|
|
|
|
if (!convertedReturn.glue_.empty())
|
|
result += " " + convertedReturn.glue_;
|
|
else if (glueReturnType != "void")
|
|
result += " return result;\n";
|
|
|
|
result += "}";
|
|
|
|
return result;
|
|
}
|
|
|
|
string GenerateWrapper(const ClassStaticFunctionAnalyzer& functionAnalyzer, bool templateVersion, const vector<ConvertedVariable>& convertedParams, const ConvertedVariable& convertedReturn)
|
|
{
|
|
string result = templateVersion ? "template <class T> " : "static ";
|
|
string className = templateVersion ? "T" : functionAnalyzer.GetClassName();
|
|
|
|
string glueReturnType = convertedReturn.cppDeclaration_;
|
|
|
|
result +=
|
|
glueReturnType + " " + GenerateWrapperName(functionAnalyzer) + "(" + JoinCppDeclarations(convertedParams) + ")\n"
|
|
"{\n";
|
|
|
|
for (size_t i = 0; i < convertedParams.size(); i++)
|
|
result += convertedParams[i].glue_;
|
|
|
|
if (glueReturnType != "void")
|
|
result += " " + functionAnalyzer.GetReturnType().ToString() + " result = ";
|
|
else
|
|
result += " ";
|
|
|
|
result += className + "::" + functionAnalyzer.GetName() + "(" + functionAnalyzer.JoinParamsNames() + ");\n";
|
|
|
|
if (!convertedReturn.glue_.empty())
|
|
result += " " + convertedReturn.glue_;
|
|
else if (glueReturnType != "void")
|
|
result += " return result;\n";
|
|
|
|
result += "}\n";
|
|
|
|
return result;
|
|
}
|
|
|
|
string GenerateWrapper(const MethodAnalyzer& methodAnalyzer, bool templateVersion, const vector<ConvertedVariable>& convertedParams, const ConvertedVariable& convertedReturn)
|
|
{
|
|
string result = templateVersion ? "template <class T> " : "static ";
|
|
string className = templateVersion ? "T" : methodAnalyzer.GetClassName();
|
|
|
|
string glueReturnType = convertedReturn.cppDeclaration_;
|
|
|
|
result +=
|
|
glueReturnType + " " + GenerateWrapperName(methodAnalyzer, templateVersion) + "(" + JoinCppDeclarations(className + "* _ptr", convertedParams) + ")\n"
|
|
"{\n";
|
|
|
|
for (size_t i = 0; i < convertedParams.size(); i++)
|
|
result += convertedParams[i].glue_;
|
|
|
|
if (glueReturnType != "void")
|
|
result += " " + methodAnalyzer.GetReturnType().ToString() + " result = ";
|
|
else
|
|
result += " ";
|
|
|
|
result += "_ptr->" + methodAnalyzer.GetName() + "(" + methodAnalyzer.JoinParamsNames() + ");\n";
|
|
|
|
if (!convertedReturn.glue_.empty())
|
|
result += " " + convertedReturn.glue_;
|
|
else if (glueReturnType != "void")
|
|
result += " return result;\n";
|
|
|
|
result += "}\n";
|
|
|
|
return result;
|
|
}
|
|
|
|
string GenerateConstructorWrapper(const MethodAnalyzer& methodAnalyzer, const vector<ConvertedVariable>& convertedParams)
|
|
{
|
|
string className = methodAnalyzer.GetClassName();
|
|
|
|
string result =
|
|
"static void " + GenerateWrapperName(methodAnalyzer) + "(" + JoinCppDeclarations(className + "* _ptr", convertedParams) + ")\n"
|
|
"{\n";
|
|
|
|
for (size_t i = 0; i < convertedParams.size(); i++)
|
|
result += convertedParams[i].glue_;
|
|
|
|
result +=
|
|
" new(_ptr) " + className + "(" + methodAnalyzer.JoinParamsNames() + ");\n"
|
|
"}\n";
|
|
|
|
return result;
|
|
}
|
|
|
|
string GenerateFactoryWrapper(const MethodAnalyzer& methodAnalyzer, const vector<ConvertedVariable>& convertedParams)
|
|
{
|
|
string className = methodAnalyzer.GetClassName();
|
|
|
|
string result =
|
|
"static " + className + "* " + GenerateWrapperName(methodAnalyzer) + "(" + JoinCppDeclarations(convertedParams) + ")\n"
|
|
"{\n";
|
|
|
|
for (size_t i = 0; i < convertedParams.size(); i++)
|
|
result += convertedParams[i].glue_;
|
|
|
|
result +=
|
|
" return new " + className + "(" + methodAnalyzer.JoinParamsNames() + ");\n"
|
|
"}\n";
|
|
|
|
return result;
|
|
}
|
|
|
|
// =================================================================================
|
|
|
|
string Generate_asFUNCTIONPR(const GlobalFunctionAnalyzer& functionAnalyzer)
|
|
{
|
|
string functionName = functionAnalyzer.GetName();
|
|
string cppParams = "(" + JoinParamsTypes(functionAnalyzer.GetMemberdef(), functionAnalyzer.GetSpecialization()) + ")";
|
|
string returnType = functionAnalyzer.GetReturnType().ToString();
|
|
return "AS_FUNCTIONPR(" + functionName + ", " + cppParams + ", " + returnType + ")";
|
|
}
|
|
|
|
string Generate_asFUNCTIONPR(const ClassStaticFunctionAnalyzer& functionAnalyzer, bool templateVersion)
|
|
{
|
|
string className = functionAnalyzer.GetClassName();
|
|
string functionName = functionAnalyzer.GetName();
|
|
string cppParams = "(" + JoinParamsTypes(functionAnalyzer.GetMemberdef(), functionAnalyzer.GetSpecialization()) + ")";
|
|
string returnType = functionAnalyzer.GetReturnType().ToString();
|
|
|
|
if (templateVersion)
|
|
return "AS_FUNCTIONPR(T::" + functionName + ", " + cppParams + ", " + returnType + ")";
|
|
else
|
|
return "AS_FUNCTIONPR(" + className + "::" + functionName + ", " + cppParams + ", " + returnType + ")";
|
|
}
|
|
|
|
string Generate_asMETHODPR(const MethodAnalyzer& methodAnalyzer, bool templateVersion)
|
|
{
|
|
string className = methodAnalyzer.GetClassName();
|
|
string functionName = methodAnalyzer.GetName();
|
|
|
|
string cppParams = "(" + JoinParamsTypes(methodAnalyzer.GetMemberdef(), methodAnalyzer.GetSpecialization()) + ")";
|
|
|
|
if (methodAnalyzer.IsConst())
|
|
cppParams += " const";
|
|
|
|
string returnType = methodAnalyzer.GetReturnType().ToString();
|
|
|
|
if (templateVersion)
|
|
return "AS_METHODPR(T, " + functionName + ", " + cppParams + ", " + returnType + ")";
|
|
else
|
|
return "AS_METHODPR(" + className + ", " + functionName + ", " + cppParams + ", " + returnType + ")";
|
|
}
|
|
|
|
} // namespace ASBindingGenerator
|