62 void VuoCompilerSpecializedNodeClass::initialize(
void)
64 genericNodeClass = NULL;
65 backingNodeClass = NULL;
81 if (nodeClassName.find(
".") == string::npos)
85 if (makeListNodeClass)
86 return makeListNodeClass;
89 if (publishedInputNodeClass)
90 return publishedInputNodeClass;
93 if (publishedOutputNodeClass)
94 return publishedOutputNodeClass;
101 for (
int j = parts.size() - 1; j >= 1; --j)
103 string newLastPart = parts[j];
104 if (! compiler->
getType(newLastPart))
107 vector<string> firstParts(parts.begin(), parts.begin() + j);
110 potentialGenericNodeClass = compiler->
getNodeClass(potentialGenericNodeClassName);
111 if (potentialGenericNodeClass)
116 vector<string> genericTypeNames;
117 if (potentialGenericNodeClass)
119 vector<string> potentialGenericTypeNames = getGenericTypeNamesFromPorts(potentialGenericNodeClass);
120 string expectedGenericNodeClassName = extractGenericNodeClassName(nodeClassName, potentialGenericTypeNames.size());
123 genericNodeClass = potentialGenericNodeClass;
124 genericTypeNames = potentialGenericTypeNames;
128 if (! genericNodeClass)
135 vector<string> specializedTypeNames(nodeClassNameParts.begin() + nodeClassNameParts.size() - genericTypeNames.size(), nodeClassNameParts.end());
138 bool _isFullySpecialized =
true;
139 for (
size_t i = 0; i < genericTypeNames.size(); ++i)
142 _isFullySpecialized =
false;
143 else if (! compiler->
getType( specializedTypeNames[i] ))
152 if (_isFullySpecialized)
160 if (genericImplementation.empty())
163 "Missing source code",
164 "%module uses generic types, but its source code isn't included in its node set. "
165 "If you are the author of this node, see the API documentation section \"Generic port types\" "
166 "under \"Developing a node class\" (https://api.vuo.org/latest/group___developing_node_classes.html). "
167 "Otherwise, contact the author of this node.");
177 string tmpNodeClassImplementationFile = tmpDir +
"/" + nodeClassName +
".c";
178 string tmpNodeClassCompiledFile = tmpDir +
"/" + nodeClassName +
".vuonode";
182 set<VuoNodeSet *> nodeSetDependencies;
186 nodeSetDependencies.insert(genericNodeSet);
188 for (vector<string>::iterator i = specializedTypeNames.begin(); i != specializedTypeNames.end(); ++i)
190 string specializedTypeName = *i;
197 nodeSetDependencies.insert(typeNodeSet);
199 set<string> tmpHeaders;
200 for (set<VuoNodeSet *>::iterator i = nodeSetDependencies.begin(); i != nodeSetDependencies.end(); ++i)
204 for (vector<string>::iterator j = headerFileNames.begin(); j != headerFileNames.end(); ++j)
206 string headerFileName = *j;
208 string tmpHeaderFile = tmpDir +
"/" + headerFileName;
210 tmpHeaders.insert(tmpHeaderFile);
213 vector<string> includeDirs;
214 includeDirs.push_back(tmpDir);
216 compiler->
compileModule(tmpNodeClassImplementationFile, tmpNodeClassCompiledFile, includeDirs);
217 Module *
module = compiler->readModuleFromBitcode(tmpNodeClassCompiledFile, compiler->
getArch());
219 for (set<string>::iterator i = tmpHeaders.begin(); i != tmpHeaders.end(); ++i)
220 remove((*i).c_str());
221 remove(tmpNodeClassImplementationFile.c_str());
222 remove(tmpNodeClassCompiledFile.c_str());
223 remove(tmpDir.c_str());
231 delete dummyNodeClass;
239 vector<VuoPortClass *> inputPortClasses;
240 for (
VuoPortClass *modelPortClass : modelInputPortClasses)
243 inputPortClasses.push_back(portClass);
247 vector<VuoPortClass *> outputPortClasses;
248 for (
VuoPortClass *modelPortClass : modelOutputPortClasses)
251 outputPortClasses.push_back(portClass);
254 vector<VuoPortClass *> modelPortClasses;
255 modelPortClasses.insert(modelPortClasses.end(), modelInputPortClasses.begin(), modelInputPortClasses.end());
256 modelPortClasses.insert(modelPortClasses.end(), modelOutputPortClasses.begin(), modelOutputPortClasses.end());
257 vector<VuoPortClass *> portClasses;
258 portClasses.insert(portClasses.end(), inputPortClasses.begin(), inputPortClasses.end());
259 portClasses.insert(portClasses.end(), outputPortClasses.begin(), outputPortClasses.end());
260 for (
size_t i = 0; i < modelPortClasses.size(); ++i)
267 string modelPortTypeName = modelPortType->
getModuleKey();
272 string innermostSpecializedTypeName = specializedTypeNameIter->second;
273 if (innermostSpecializedTypeName != innermostModelPortTypeName)
283 VuoPortClass *refreshPortClass = inputPortClasses.front();
285 VuoNodeClass *baseNodeClass =
new VuoNodeClass(nodeClassName, refreshPortClass, inputPortClasses, outputPortClasses);
296 for (vector<string>::iterator i = genericTypeNames.begin(); i != genericTypeNames.end(); ++i)
298 string genericTypeName = *i;
300 if (! defaultSpecializedTypeName.empty())
301 nodeClass->defaultSpecializedForGenericTypeName[genericTypeName] = defaultSpecializedTypeName;
306 nodeClass->backingNodeClass = genericNodeClass;
309 nodeClass->genericNodeClass = genericNodeClass;
312 nodeClass->setBuiltIn( genericNodeClass->
isBuiltIn() );
314 return nodeClass->getBase();
322 string name = modelPortClass->
getName();
332 portClass = inputPortClass;
345 portClass = outputPortClass;
356 portClass = triggerPortClass;
366 json_object_get(dataDetails);
374 json_object_get(details);
396 vector<string> genericTypes = getGenericTypeNamesFromPorts(origNodeClass);
397 if (! genericTypes.empty())
400 if (specializedNodeClass)
407 string rawGenericNodeClassNameWithSuffixes = createSpecializedNodeClassName(rawGenericNodeClassName, genericTypes);
410 string genericNodeClassName = rawGenericNodeClass->createDefaultSpecializedNodeClassName();
415 return origNodeClass;
424 vector<string> genericTypesFromGeneric = getGenericTypeNamesFromPorts(potentialGenericNodeClass);
425 if (genericTypesFromGeneric.empty())
428 string genericNodeClassNameFromSpecialized = extractGenericNodeClassName(potentialSpecializedNodeClassName, genericTypesFromGeneric.size());
429 return genericNodeClassNameFromSpecialized == potentialGenericNodeClass->
getBase()->
getClassName();
438 string backingNodeClassName = createFullySpecializedNodeClassName(nodeToBack);
439 if (backingNodeClassName ==
getBase()->getClassName() ||
449 vector<VuoPort *> inputPortsOnReplacementNode = replacementCompilerNode->
getBase()->
getInputPorts();
450 vector<VuoPort *> inputPortsOnNodeToBack = nodeToBack->
getInputPorts();
451 vector<VuoPort *> outputPortsOnReplacementNode = replacementCompilerNode->
getBase()->
getOutputPorts();
452 vector<VuoPort *> outputPortsOnNodeToBack = nodeToBack->
getOutputPorts();
453 vector<VuoPort *> portsOnReplacementNode;
454 vector<VuoPort *> portsOnNodeToBack;
455 portsOnReplacementNode.insert(portsOnReplacementNode.end(), inputPortsOnReplacementNode.begin(), inputPortsOnReplacementNode.end());
456 portsOnReplacementNode.insert(portsOnReplacementNode.end(), outputPortsOnReplacementNode.begin(), outputPortsOnReplacementNode.end());
457 portsOnNodeToBack.insert(portsOnNodeToBack.end(), inputPortsOnNodeToBack.begin(), inputPortsOnNodeToBack.end());
458 portsOnNodeToBack.insert(portsOnNodeToBack.end(), outputPortsOnNodeToBack.begin(), outputPortsOnNodeToBack.end());
459 for (
int i = 0; i < inputPortsOnReplacementNode.size(); ++i)
466 for (
int i = 0; i < portsOnReplacementNode.size(); ++i)
468 VuoPort *baseToKeep = portsOnNodeToBack[i];
473 compilerPortToKeep->
setBase(baseToKeep);
481 replacementCompilerNode->
setBase(nodeToBack);
482 delete baseToDiscard;
483 delete compilerToDiscard;
494 "Couldn't get backing node class.",
495 "'" + backingNodeClassName +
"' uses generic types, but it couldn't be compiled. "
496 "Check the macOS Console for details."));
504 void VuoCompilerSpecializedNodeClass::replaceGenericTypesWithSpecialized(
string &nodeClassSource, map<string, string> specializedForGenericTypeName)
506 set<string> replacementTypeNames;
509 string genericTypeName = i->first;
510 string replacementTypeName = i->second;
512 if (replacementTypeName != genericTypeName)
518 replacementTypeNames.insert(innermostTypeName);
522 string includesToAdd;
523 for (set<string>::iterator i = replacementTypeNames.begin(); i != replacementTypeNames.end(); ++i)
525 string replacementTypeName = *i;
526 includesToAdd +=
"#include \"" + replacementTypeName +
".h\"\n";
532 size_t insertionPos = nodeClassSource.find(
"VuoModuleMetadata");
533 if (insertionPos == string::npos)
535 nodeClassSource.insert(insertionPos, includesToAdd);
543 size_t insertionPos = nodeClassSource.find(
"VuoModuleMetadata");
544 if (insertionPos == string::npos)
547 map<string, vector<string> > compatibleTypesForGeneric;
550 size_t metadataStartPos = nodeClassSource.find(
"(", insertionPos) + 1;
551 if (metadataStartPos == string::npos)
553 size_t metadataEndPos = nodeClassSource.find(
");\n", metadataStartPos);
554 if (metadataEndPos == string::npos)
556 string moduleMetadataString = nodeClassSource.substr(metadataStartPos, metadataEndPos - metadataStartPos);
557 json_object *moduleMetadata = json_tokener_parse(moduleMetadataString.c_str());
558 if (! moduleMetadata)
560 map<string, string> defaultTypeForGeneric;
562 json_object_put(moduleMetadata);
564 set<string> genericTypeIdentifiers;
566 string genericTypeName;
569 size_t endPos = startPos + genericTypeName.length();
574 genericTypeIdentifiers.insert(genericTypeName);
575 startPos += genericTypeName.length();
582 compatibleTypesForGeneric[innermostTypeName]);
584 nodeClassSource.replace(startPos, genericTypeName.length(), backingTypeName);
585 startPos += backingTypeName.length();
590 string typedefsToAdd;
591 map<string, bool> typeNamesSeen;
592 for (set<string>::iterator i = genericTypeIdentifiers.begin(); i != genericTypeIdentifiers.end(); ++i)
594 string genericTypeName = *i;
598 compatibleTypesForGeneric[innermostTypeName]);
599 if (! typeNamesSeen[innermostTypeName])
601 typeNamesSeen[innermostTypeName] =
true;
603 string replacementTypeName = innermostBackingTypeName;
604 typedefsToAdd +=
"typedef " + replacementTypeName +
" " + innermostTypeName +
";\n";
607 if (! typeNamesSeen[genericTypeName])
609 typeNamesSeen[genericTypeName] =
true;
612 typedefsToAdd +=
"typedef " + replacementCollectionTypeName +
" " + genericTypeName +
";\n";
615 nodeClassSource.insert(insertionPos, typedefsToAdd);
623 return getGenericTypeNamesFromPorts(
this).empty();
631 return ! getGenericTypeNamesFromPorts(nodeClass).empty();
637 vector<string> VuoCompilerSpecializedNodeClass::getGenericTypeNamesFromPorts(
VuoCompilerNodeClass *nodeClass)
639 set<string> genericTypeNames;
642 vector<VuoPortClass *> portClasses;
643 portClasses.insert(portClasses.end(), inputPortClasses.begin(), inputPortClasses.end());
644 portClasses.insert(portClasses.end(), outputPortClasses.begin(), outputPortClasses.end());
645 for (vector<VuoPortClass *>::iterator i = portClasses.begin(); i != portClasses.end(); ++i)
652 genericTypeNames.insert(innermostTypeName);
656 vector<string> sortedGenericTypeNames(genericTypeNames.begin(), genericTypeNames.end());
658 return sortedGenericTypeNames;
667 map<string, string> VuoCompilerSpecializedNodeClass::getBackingTypeNamesFromPorts(
VuoNode *node)
669 map<string, string> backingTypeForPort;
673 vector<VuoPort *> ports;
674 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
675 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
676 for (vector<VuoPort *>::iterator i = ports.begin(); i != ports.end(); ++i)
684 if (! genericTypeForPort)
693 backingTypeForPort[innermostGenericTypeName] = innermostBackingTypeName;
696 return backingTypeForPort;
705 for (
auto specializedPortClass :
getBase()->getInputPortClasses())
707 if (specializedPortClass == portClass)
715 if (specializedPortClass == portClass)
752 set<string> genericTypeNames;
753 for (set<VuoPortClass *>::iterator i = portClassesToUnspecialize.begin(); i != portClassesToUnspecialize.end(); ++i)
760 genericTypeNames.insert(innermostGenericTypeName);
764 vector<string> specializedTypeNames;
765 vector<string> origGenericTypeNames = getGenericTypeNamesFromPorts(genericNodeClass);
766 for (vector<string>::iterator i = origGenericTypeNames.begin(); i != origGenericTypeNames.end(); ++i)
770 specializedTypeNames.push_back(s);
773 string genericNodeClassName = extractGenericNodeClassName(
getBase()->getClassName(), origGenericTypeNames.size());
774 return createSpecializedNodeClassName(genericNodeClassName, specializedTypeNames);
783 vector<string> specializedTypeNames;
784 vector<string> origGenericTypeNames = getGenericTypeNamesFromPorts(genericNodeClass);
785 for (vector<string>::iterator i = origGenericTypeNames.begin(); i != origGenericTypeNames.end(); ++i)
789 specializedTypeNames.push_back(s);
792 string genericNodeClassName = extractGenericNodeClassName(
getBase()->getClassName(), origGenericTypeNames.size());
793 return createSpecializedNodeClassName(genericNodeClassName, specializedTypeNames);
800 string VuoCompilerSpecializedNodeClass::createDefaultSpecializedNodeClassName(
void)
802 vector<string> sortedGenericTypeNames = getGenericTypeNamesFromPorts(
this);
803 vector<string> sortedSpecializedTypeNames;
804 for (vector<string>::iterator i = sortedGenericTypeNames.begin(); i != sortedGenericTypeNames.end(); ++i)
806 string genericTypeName = *i;
809 defaultTypeNameIter->second : genericTypeName);
810 sortedSpecializedTypeNames.push_back(specializedTypeName);
813 string genericNodeClassName = extractGenericNodeClassName(
getBase()->getClassName(), sortedGenericTypeNames.size());
814 return createSpecializedNodeClassName(genericNodeClassName, sortedSpecializedTypeNames);
821 string VuoCompilerSpecializedNodeClass::createFullySpecializedNodeClassName(
VuoNode *nodeToBack)
823 map<string, string> backingForGeneric = getBackingTypeNamesFromPorts(nodeToBack);
826 for (
int i = 1; i < nodeClassNameParts.size(); ++i)
829 if (backingIter != backingForGeneric.end())
839 string VuoCompilerSpecializedNodeClass::extractGenericNodeClassName(
string specializedNodeClassName,
size_t genericTypeCount)
842 if (specializedNameParts.size() < 2 + genericTypeCount)
845 vector<string> genericNameParts(specializedNameParts.begin(), specializedNameParts.begin() + specializedNameParts.size() - genericTypeCount);
852 string VuoCompilerSpecializedNodeClass::createSpecializedNodeClassName(
string genericNodeClassName, vector<string> specializedTypeNames)
861 string VuoCompilerSpecializedNodeClass::getClassIdentifier(
void)
864 Function * VuoCompilerSpecializedNodeClass::getEventFunction(
void)
867 Function * VuoCompilerSpecializedNodeClass::getInitFunction(
void)
870 Function * VuoCompilerSpecializedNodeClass::getFiniFunction(
void)
873 Function * VuoCompilerSpecializedNodeClass::getCallbackStartFunction(
void)
876 Function * VuoCompilerSpecializedNodeClass::getCallbackUpdateFunction(
void)
879 Function * VuoCompilerSpecializedNodeClass::getCallbackStopFunction(
void)
882 Function * VuoCompilerSpecializedNodeClass::getCompositionAddNodeMetadataFunction(
void)
885 Function * VuoCompilerSpecializedNodeClass::getCompositionPerformDataOnlyTransmissionsFunction(
void)
888 Function * VuoCompilerSpecializedNodeClass::getCompositionSetPublishedInputPortValueFunction(
void)
891 Function * VuoCompilerSpecializedNodeClass::getTriggerWorkerFunction(
string portIdentifier)
894 vector<VuoCompilerTriggerDescription *> VuoCompilerSpecializedNodeClass::getTriggerDescriptions(
void)
900 string VuoCompilerSpecializedNodeClass::getDoxygenDocumentation(
void)
903 string VuoCompilerSpecializedNodeClass::getDefaultSpecializedTypeName(
string genericTypeName)
906 vector<string> VuoCompilerSpecializedNodeClass::getAutomaticKeywords(
void)
912 bool VuoCompilerSpecializedNodeClass::isStateful(
void)
923 if (genericNodeClass)