Refactor some part of code generation into specific functions

This commit is contained in:
Florian Rival
2018-09-03 23:35:55 +01:00
parent 09095a257a
commit b79ab3c829
4 changed files with 143 additions and 152 deletions

View File

@@ -76,7 +76,8 @@
"iomanip": "cpp",
"cstdint": "cpp",
"forward_list": "cpp",
"mutex": "cpp"
"mutex": "cpp",
"__hash": "cpp"
},
"files.exclude": {
"Binaries/*build*": true,

View File

@@ -223,7 +223,7 @@ class GD_CORE_API EventsCodeGenerator {
* \brief Add a declaration which will be inserted after includes
*/
void AddGlobalDeclaration(gd::String declaration) {
customGlobalDeclaration.insert(declaration);
customGlobalDeclarations.insert(declaration);
};
/**
@@ -255,7 +255,7 @@ class GD_CORE_API EventsCodeGenerator {
/** \brief Get the custom declaration to be inserted after includes.
*/
const std::set<gd::String>& GetCustomGlobalDeclaration() const {
return customGlobalDeclaration;
return customGlobalDeclarations;
}
/**
@@ -652,7 +652,7 @@ class GD_CORE_API EventsCodeGenerator {
gd::String customCodeInMain; ///< Custom code inserted before events ( in
///< main function )
std::set<gd::String>
customGlobalDeclaration; ///< Custom global C++ declarations inserted
customGlobalDeclarations; ///< Custom global C++ declarations inserted
///< after includes
size_t maxCustomConditionsDepth; ///< The maximum depth value for all the
///< custom conditions created.

View File

@@ -33,9 +33,6 @@ gd::String EventsCodeGenerator::GenerateSceneEventsCompleteCode(
const gd::EventsList& events,
std::set<gd::String>& includeFiles,
bool compilationForRuntime) {
// Preprocessing then code generation can make changes to the events, so we
// need to do the work on a copy of the events.
gd::EventsList generatedEvents = events;
// Prepare the global context
unsigned int maxDepthLevelReached = 0;
@@ -43,90 +40,41 @@ gd::String EventsCodeGenerator::GenerateSceneEventsCompleteCode(
EventsCodeGenerator codeGenerator(project, scene);
// Generate whole events code
gd::String output = codeGenerator.GetCodeNamespace() + " = {};\n";
// Preprocessing then code generation can make changes to the events, so we
// need to do the work on a copy of the events.
gd::EventsList generatedEvents = events;
codeGenerator.SetGenerateCodeForRuntime(compilationForRuntime);
codeGenerator.PreprocessEventList(generatedEvents);
gd::String wholeEventsCode =
codeGenerator.GenerateEventsListCode(generatedEvents, context);
// Extra declarations needed by events
for (set<gd::String>::iterator declaration =
codeGenerator.GetCustomGlobalDeclaration().begin();
declaration != codeGenerator.GetCustomGlobalDeclaration().end();
++declaration)
output += *declaration + "\n";
gd::String globalDeclarations;
for (auto& declaration : codeGenerator.GetCustomGlobalDeclaration())
globalDeclarations += declaration + "\n";
// Global objects lists
auto generateDeclarations = [&project, &scene, &codeGenerator](
const gd::Object& object,
unsigned int maxDepth,
gd::String& globalObjectLists,
gd::String& globalObjectListsReset) {
gd::String type = gd::GetTypeOfObject(project, scene, object.GetName());
const gd::ObjectMetadata& metadata =
gd::MetadataProvider::GetObjectMetadata(JsPlatform::Get(), type);
codeGenerator.AddIncludeFiles(metadata.includeFiles);
auto allObjectsDeclarationsAndResets =
codeGenerator.GenerateAllObjectsDeclarationsAndResets(
maxDepthLevelReached);
gd::String globalObjectLists = allObjectsDeclarationsAndResets.first;
gd::String globalObjectListsReset = allObjectsDeclarationsAndResets.second;
// Ensure needed files are included.
std::vector<gd::String> behaviors = object.GetAllBehaviorNames();
for (std::size_t j = 0; j < behaviors.size(); ++j) {
const gd::BehaviorMetadata& metadata =
gd::MetadataProvider::GetBehaviorMetadata(
JsPlatform::Get(),
object.GetBehavior(behaviors[j]).GetTypeName());
codeGenerator.AddIncludeFiles(metadata.includeFiles);
}
codeGenerator.AddAllObjectsIncludeFiles();
// Generate declarations for the objects lists
for (unsigned int j = 1; j <= maxDepth; ++j) {
globalObjectLists += codeGenerator.GetCodeNamespaceAccessor() +
ManObjListName(object.GetName()) +
gd::String::From(j) + "= [];\n";
globalObjectListsReset += codeGenerator.GetCodeNamespaceAccessor() +
ManObjListName(object.GetName()) +
gd::String::From(j) + ".length = 0;\n";
}
};
// "Booleans" used by conditions
gd::String globalConditionsBooleans =
codeGenerator.GenerateAllConditionsBooleanDeclarations();
gd::String globalObjectLists;
gd::String globalObjectListsReset;
// TODO: Surely use ClassWithObjects
for (std::size_t i = 0; i < project.GetObjectsCount(); ++i)
generateDeclarations(project.GetObject(i),
maxDepthLevelReached,
globalObjectLists,
globalObjectListsReset);
for (std::size_t i = 0; i < scene.GetObjectsCount(); ++i)
generateDeclarations(scene.GetObject(i),
maxDepthLevelReached,
globalObjectLists,
globalObjectListsReset);
// Condition global booleans
gd::String globalConditionsBooleans;
for (unsigned int i = 0; i <= codeGenerator.GetMaxCustomConditionsDepth();
++i) {
globalConditionsBooleans += codeGenerator.GetCodeNamespaceAccessor() +
"conditionTrue_" + gd::String::From(i) +
" = {val:false};\n";
for (std::size_t j = 0; j <= codeGenerator.GetMaxConditionsListsSize();
++j) {
globalConditionsBooleans += codeGenerator.GetCodeNamespaceAccessor() +
"condition" + gd::String::From(j) +
"IsTrue_" + gd::String::From(i) +
" = {val:false};\n";
}
}
output += globalObjectLists + "\n" + globalConditionsBooleans + "\n\n" +
codeGenerator.GetCustomCodeOutsideMain() + "\n\n" +
codeGenerator.GetCodeNamespaceAccessor() +
"func = function(runtimeScene, context) {\n" +
"context.startNewFrame();\n" + globalObjectListsReset + "\n" +
codeGenerator.GetCustomCodeInMain() + wholeEventsCode +
"return;\n" + "}\n";
gd::String output = codeGenerator.GetCodeNamespace() + " = {};\n" +
globalDeclarations + globalObjectLists + "\n" +
globalConditionsBooleans + "\n\n" +
codeGenerator.GetCustomCodeOutsideMain() + "\n\n" +
codeGenerator.GetCodeNamespaceAccessor() +
"func = function(runtimeScene, context) {\n" +
"context.startNewFrame();\n" + globalObjectListsReset +
"\n" + codeGenerator.GetCustomCodeInMain() +
wholeEventsCode + "return;\n" + "}\n";
// Export the symbols to avoid them being stripped by the Closure Compiler:
output += "gdjs['" +
@@ -146,11 +94,6 @@ gd::String EventsCodeGenerator::GenerateEventsFunctionCode(
emptyObjectsAndGroups; // As opposed to layout events, we don't have
// objects in the "outer" scope.
// TODO: Factor with other Generate method.
// Preprocessing then code generation can make changes to the events, so we
// need to do the work on a copy of the events.
gd::EventsList generatedEvents = events;
// Prepare the global context
unsigned int maxDepthLevelReached = 0;
@@ -158,96 +101,118 @@ gd::String EventsCodeGenerator::GenerateEventsFunctionCode(
EventsCodeGenerator codeGenerator(emptyObjectsAndGroups, objectsAndGroups);
// Generate whole events code
gd::String output = codeGenerator.GetCodeNamespace() + " = {};\n";
// Preprocessing then code generation can make changes to the events, so we
// need to do the work on a copy of the events.
gd::EventsList generatedEvents = events;
codeGenerator.SetGenerateCodeForRuntime(compilationForRuntime);
codeGenerator.PreprocessEventList(generatedEvents);
gd::String wholeEventsCode =
codeGenerator.GenerateEventsListCode(generatedEvents, context);
// Extra declarations needed by events
for (set<gd::String>::iterator declaration =
codeGenerator.GetCustomGlobalDeclaration().begin();
declaration != codeGenerator.GetCustomGlobalDeclaration().end();
++declaration)
output += *declaration + "\n";
gd::String globalDeclarations;
for (auto& declaration : codeGenerator.GetCustomGlobalDeclaration())
globalDeclarations += declaration + "\n";
// Global objects lists
auto allObjectsDeclarationsAndResets =
codeGenerator.GenerateAllObjectsDeclarationsAndResets(
maxDepthLevelReached);
gd::String globalObjectLists = allObjectsDeclarationsAndResets.first;
gd::String globalObjectListsReset = allObjectsDeclarationsAndResets.second;
codeGenerator.AddAllObjectsIncludeFiles();
// "Booleans" used by conditions
gd::String globalConditionsBooleans =
codeGenerator.GenerateAllConditionsBooleanDeclarations();
gd::String output = codeGenerator.GetCodeNamespace() + " = {};\n" +
globalDeclarations + globalObjectLists + "\n" +
globalConditionsBooleans + "\n\n" +
codeGenerator.GetCustomCodeOutsideMain() + "\n\n" +
codeGenerator.GetCodeNamespaceAccessor() +
"func = function(runtimeScene, context) {\n" +
"context.startNewFrame();\n" + globalObjectListsReset +
"\n" + codeGenerator.GetCustomCodeInMain() +
wholeEventsCode + "return;\n" + "}\n";
// includeFiles.insert(codeGenerator.GetIncludeFiles().begin(),
// codeGenerator.GetIncludeFiles().end());
return output;
}
std::pair<gd::String, gd::String>
EventsCodeGenerator::GenerateAllObjectsDeclarationsAndResets(
unsigned int maxDepthLevelReached) {
gd::String globalObjectLists;
gd::String globalObjectListsReset;
auto generateDeclarations =
[&emptyObjectsAndGroups, &objectsAndGroups, &codeGenerator](
const gd::Object& object,
unsigned int maxDepth,
gd::String& globalObjectLists,
gd::String& globalObjectListsReset) {
gd::String type = gd::GetTypeOfObject(
emptyObjectsAndGroups, objectsAndGroups, object.GetName());
const gd::ObjectMetadata& metadata =
gd::MetadataProvider::GetObjectMetadata(JsPlatform::Get(), type);
codeGenerator.AddIncludeFiles(metadata.includeFiles);
// Ensure needed files are included.
std::vector<gd::String> behaviors = object.GetAllBehaviorNames();
for (std::size_t j = 0; j < behaviors.size(); ++j) {
const gd::BehaviorMetadata& metadata =
gd::MetadataProvider::GetBehaviorMetadata(
JsPlatform::Get(),
object.GetBehavior(behaviors[j]).GetTypeName());
codeGenerator.AddIncludeFiles(metadata.includeFiles);
}
[this,
&maxDepthLevelReached,
&globalObjectLists,
&globalObjectListsReset](const gd::Object& object) {
// Generate declarations for the objects lists
for (unsigned int j = 1; j <= maxDepth; ++j) {
globalObjectLists += codeGenerator.GetCodeNamespaceAccessor() +
for (unsigned int j = 1; j <= maxDepthLevelReached; ++j) {
globalObjectLists += GetCodeNamespaceAccessor() +
ManObjListName(object.GetName()) +
gd::String::From(j) + "= [];\n";
globalObjectListsReset += codeGenerator.GetCodeNamespaceAccessor() +
globalObjectListsReset += GetCodeNamespaceAccessor() +
ManObjListName(object.GetName()) +
gd::String::From(j) + ".length = 0;\n";
}
};
gd::String globalObjectLists;
gd::String globalObjectListsReset;
// TODO: Surely use ClassWithObjects
for (std::size_t i = 0; i < emptyObjectsAndGroups.GetObjectsCount(); ++i)
generateDeclarations(emptyObjectsAndGroups.GetObject(i),
maxDepthLevelReached,
globalObjectLists,
globalObjectListsReset);
for (std::size_t i = 0; i < globalObjectsAndGroups.GetObjectsCount(); ++i)
generateDeclarations(globalObjectsAndGroups.GetObject(i));
for (std::size_t i = 0; i < objectsAndGroups.GetObjectsCount(); ++i)
generateDeclarations(objectsAndGroups.GetObject(i),
maxDepthLevelReached,
globalObjectLists,
globalObjectListsReset);
generateDeclarations(objectsAndGroups.GetObject(i));
// Condition global booleans
return std::make_pair(globalObjectLists, globalObjectListsReset);
}
void EventsCodeGenerator::AddAllObjectsIncludeFiles() {
auto addIncludeFiles = [this](const gd::Object& object) {
gd::String type = gd::GetTypeOfObject(
GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), object.GetName());
// Ensure needed files are included for the object type and its behaviors.
const gd::ObjectMetadata& metadata =
gd::MetadataProvider::GetObjectMetadata(JsPlatform::Get(), type);
AddIncludeFiles(metadata.includeFiles);
std::vector<gd::String> behaviors = object.GetAllBehaviorNames();
for (std::size_t j = 0; j < behaviors.size(); ++j) {
const gd::BehaviorMetadata& metadata =
gd::MetadataProvider::GetBehaviorMetadata(
JsPlatform::Get(),
object.GetBehavior(behaviors[j]).GetTypeName());
AddIncludeFiles(metadata.includeFiles);
}
};
for (std::size_t i = 0; i < globalObjectsAndGroups.GetObjectsCount(); ++i)
addIncludeFiles(globalObjectsAndGroups.GetObject(i));
for (std::size_t i = 0; i < objectsAndGroups.GetObjectsCount(); ++i)
addIncludeFiles(objectsAndGroups.GetObject(i));
}
gd::String EventsCodeGenerator::GenerateAllConditionsBooleanDeclarations() {
gd::String globalConditionsBooleans;
for (unsigned int i = 0; i <= codeGenerator.GetMaxCustomConditionsDepth();
++i) {
globalConditionsBooleans += codeGenerator.GetCodeNamespaceAccessor() +
"conditionTrue_" + gd::String::From(i) +
" = {val:false};\n";
for (std::size_t j = 0; j <= codeGenerator.GetMaxConditionsListsSize();
++j) {
globalConditionsBooleans += codeGenerator.GetCodeNamespaceAccessor() +
"condition" + gd::String::From(j) +
"IsTrue_" + gd::String::From(i) +
" = {val:false};\n";
for (unsigned int i = 0; i <= GetMaxCustomConditionsDepth(); ++i) {
globalConditionsBooleans += GetCodeNamespaceAccessor() + "conditionTrue_" +
gd::String::From(i) + " = {val:false};\n";
for (std::size_t j = 0; j <= GetMaxConditionsListsSize(); ++j) {
globalConditionsBooleans += GetCodeNamespaceAccessor() + "condition" +
gd::String::From(j) + "IsTrue_" +
gd::String::From(i) + " = {val:false};\n";
}
}
output += globalObjectLists + "\n" + globalConditionsBooleans + "\n\n" +
codeGenerator.GetCustomCodeOutsideMain() + "\n\n" +
codeGenerator.GetCodeNamespaceAccessor() +
"func = function(runtimeScene, context) {\n" +
"context.startNewFrame();\n" + globalObjectListsReset + "\n" +
codeGenerator.GetCustomCodeInMain() + wholeEventsCode +
"return;\n" + "}\n";
// includeFiles.insert(codeGenerator.GetIncludeFiles().begin(),
// codeGenerator.GetIncludeFiles().end());
return output;
return globalConditionsBooleans;
}
gd::String EventsCodeGenerator::GenerateObjectFunctionCall(

View File

@@ -213,11 +213,36 @@ class EventsCodeGenerator : public gd::EventsCodeGenerator {
virtual gd::String GenerateObjectsDeclarationCode(
gd::EventsCodeGenerationContext& context);
virtual gd::String GenerateAllInstancesGetter(gd::String & objectName);
virtual gd::String GenerateAllInstancesGetter(gd::String& objectName);
virtual gd::String GenerateProfilerSectionBegin(const gd::String& section);
virtual gd::String GenerateProfilerSectionEnd(const gd::String& section);
private:
/**
* \brief Generate the declarations of all the booleans required to run
* events.
*
* This should be called after generating events list code, so that the code
* generator knows all the booleans to be declared.
*/
gd::String GenerateAllConditionsBooleanDeclarations();
/**
* \brief Generate the declarations of all the objects list arrays.
*
* This should be called after generating events list code, with the maximum
* depth reached by events.
*/
std::pair<gd::String, gd::String> GenerateAllObjectsDeclarationsAndResets(
unsigned int maxDepthLevelReached);
/**
* \brief Add to include files all the files required by the object and their
* behaviors.
*/
void AddAllObjectsIncludeFiles();
/**
* \brief Construct a code generator for the specified project and layout.
*/