40 INPUT_DATA_ABSENT = 1 << 0,
41 INPUT_DATA_PRESENT = 1 << 1,
42 OUTPUT_DATA_ABSENT = 1 << 2,
43 OUTPUT_DATA_PRESENT = 1 << 3,
44 INPUT_EVENT_ABSENT = 1 << 4,
45 INPUT_EVENT_PRESENT = 1 << 5,
46 OUTPUT_EVENT_ABSENT = 1 << 6,
47 OUTPUT_EVENT_PRESENT = 1 << 7,
48 OUTPUT_TRIGGER_ABSENT = 1 << 8,
49 OUTPUT_TRIGGER_PRESENT = 1 << 9,
50 INSTANCE_DATA_ABSENT = 1 << 10,
51 INSTANCE_DATA_PRESENT = 1 << 11
62 instanceDataClass = NULL;
65 callbackStartFunction = NULL;
66 callbackUpdateFunction = NULL;
67 callbackStopFunction = NULL;
68 _isSubcomposition =
false;
81 compilerNodeClass->getBase()->getClassName(),
82 compilerNodeClass->getBase()->getRefreshPortClass(),
83 compilerNodeClass->getBase()->getInputPortClasses(),
84 compilerNodeClass->getBase()->getOutputPortClasses())),
94 setDependsOnPro(compilerNodeClass->dependsOnPro());
102 this->eventFunction = compilerNodeClass->eventFunction;
103 this->initFunction = compilerNodeClass->initFunction;
104 this->finiFunction = compilerNodeClass->finiFunction;
105 this->callbackStartFunction = compilerNodeClass->callbackStartFunction;
106 this->callbackUpdateFunction = compilerNodeClass->callbackUpdateFunction;
107 this->callbackStopFunction = compilerNodeClass->callbackStopFunction;
108 this->instanceDataClass = compilerNodeClass->instanceDataClass;
109 this->triggerDescriptions = compilerNodeClass->triggerDescriptions;
111 this->portsWithExplicitEventBlockingNone = compilerNodeClass->portsWithExplicitEventBlockingNone;
115 this->containedNodes = compilerNodeClass->containedNodes;
120 compilerNodeClass->instanceDataClass = NULL;
122 _isSubcomposition =
false;
123 updateSubcompositionStatus();
135 instanceDataClass = NULL;
136 eventFunction = NULL;
139 callbackStartFunction = NULL;
140 callbackUpdateFunction = NULL;
141 callbackStopFunction = NULL;
142 _isSubcomposition =
false;
150 delete instanceDataClass;
153 for (vector<VuoPortClass *>::iterator i = inputPortClasses.begin(); i != inputPortClasses.end(); ++i)
154 delete (*i)->getCompiler();
157 for (vector<VuoPortClass *>::iterator i = outputPortClasses.begin(); i != outputPortClasses.end(); ++i)
158 delete (*i)->getCompiler();
170 instantiateCompilerNode(n);
180 instantiateCompilerNode(n);
189void VuoCompilerNodeClass::instantiateCompilerNode(
VuoNode *node)
194 vector<VuoPort *> ports;
195 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
196 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
198 for (vector<VuoPort *>::iterator i = ports.begin(); i != ports.end(); ++i)
223 if (isNodeClass(module, nodeClassName))
226 if (specializedNodeClass)
227 return specializedNodeClass;
244bool VuoCompilerNodeClass::isNodeClass(Module *module,
string moduleKey)
253void VuoCompilerNodeClass::parse(
void)
257 parseEventFunction();
258 if (instanceDataClass)
262 parseCallbackStartFunction();
263 parseCallbackUpdateFunction();
264 parseCallbackStopFunction();
268 vector<VuoPortClass *> portClasses;
271 portClasses.insert(portClasses.end(), inputPortClasses.begin(), inputPortClasses.end());
272 portClasses.insert(portClasses.end(), outputPortClasses.begin(), outputPortClasses.end());
273 for (vector<VuoPortClass *>::iterator i = portClasses.begin(); i != portClasses.end(); ++i)
285 updateSubcompositionStatus();
291set<string> VuoCompilerNodeClass::globalsToRename(
void)
294 globals.insert(
"nodeEvent");
295 globals.insert(
"nodeInstanceEvent");
296 globals.insert(
"nodeInstanceInit");
297 globals.insert(
"nodeInstanceFini");
298 globals.insert(
"nodeInstanceTriggerStart");
299 globals.insert(
"nodeInstanceTriggerUpdate");
300 globals.insert(
"nodeInstanceTriggerStop");
307void VuoCompilerNodeClass::parseMetadata(
void)
311 json_object *nodeDetails = NULL;
312 if (json_object_object_get_ex(
moduleDetails,
"node", &nodeDetails))
321 json_object *triggersArray = NULL;
322 if (json_object_object_get_ex(nodeDetails,
"triggers", &triggersArray))
325 json_object *nodesObj = NULL;
326 if (json_object_object_get_ex(nodeDetails,
"nodes", &nodesObj))
328 json_object_object_foreach(nodesObj, nodeIdentifier, nodeClassNameObj)
330 string nodeClassName = json_object_get_string(nodeClassNameObj);
331 containedNodes.insert(make_pair(nodeIdentifier, nodeClassName));
343void VuoCompilerNodeClass::parseEventFunction(
void)
351 acceptsInstanceData = INSTANCE_DATA_PRESENT;
355 VUserLog(
"Error: Node class '%s' is missing function nodeEvent or nodeInstanceEvent.",
getBase()->getClassName().c_str());
360 parseParameters(eventFunction,
361 INPUT_DATA_ABSENT | INPUT_DATA_PRESENT |
362 OUTPUT_DATA_ABSENT | OUTPUT_DATA_PRESENT |
363 INPUT_EVENT_ABSENT | INPUT_EVENT_PRESENT |
364 OUTPUT_EVENT_ABSENT | OUTPUT_EVENT_PRESENT |
365 OUTPUT_TRIGGER_ABSENT | OUTPUT_TRIGGER_PRESENT |
366 acceptsInstanceData);
375void VuoCompilerNodeClass::parseInitFunction(
void)
381 parseParameters(initFunction,
382 INPUT_DATA_ABSENT | INPUT_DATA_PRESENT |
385 OUTPUT_EVENT_ABSENT |
386 OUTPUT_TRIGGER_ABSENT |
387 INSTANCE_DATA_ABSENT);
393void VuoCompilerNodeClass::parseFiniFunction(
void)
407void VuoCompilerNodeClass::parseCallbackStartFunction(
void)
410 if (! callbackStartFunction)
413 parseParameters(callbackStartFunction,
414 INPUT_DATA_ABSENT | INPUT_DATA_PRESENT |
417 OUTPUT_EVENT_ABSENT |
418 OUTPUT_TRIGGER_ABSENT | OUTPUT_TRIGGER_PRESENT |
419 INSTANCE_DATA_PRESENT);
431void VuoCompilerNodeClass::parseCallbackUpdateFunction(
void)
434 if (! callbackUpdateFunction)
437 parseParameters(callbackUpdateFunction,
438 INPUT_DATA_ABSENT | INPUT_DATA_PRESENT |
441 OUTPUT_EVENT_ABSENT |
442 OUTPUT_TRIGGER_ABSENT | OUTPUT_TRIGGER_PRESENT |
443 INSTANCE_DATA_PRESENT);
449void VuoCompilerNodeClass::parseCallbackStopFunction(
void)
452 if (! callbackStopFunction)
455 parseParameters(callbackStopFunction,
459 OUTPUT_EVENT_ABSENT |
460 OUTPUT_TRIGGER_ABSENT | OUTPUT_TRIGGER_PRESENT |
461 INSTANCE_DATA_PRESENT);
471void VuoCompilerNodeClass::parseParameters(Function *function,
unsigned long acceptanceFlags)
475 vector<VuoCompilerNodeArgumentClass *> inputArgumentClasses;
476 vector<VuoCompilerNodeArgumentClass *> outputArgumentClasses;
477 map<string, VuoType *> vuoTypeForArgumentName;
478 map<string, json_object *> detailsForArgumentName;
479 map<string, VuoCompilerPortClass *> portClassForArgumentName;
480 map<string, VuoCompilerDataClass *> dataClassForArgumentName;
482 bool sawInputData =
false;
483 bool sawOutputData =
false;
484 bool sawInputEvent =
false;
485 bool sawOutputEvent =
false;
486 bool sawOutputTrigger =
false;
487 bool sawInstanceData =
false;
490 for (vector<pair<Argument *, string> >::iterator i = annotatedArguments.begin(); i != annotatedArguments.end(); ++i)
492 Argument *argument = i->first;
493 string annotation = i->second;
498 json_object *details = NULL;
501 if ((argumentClass = parseInputDataParameter(annotation, argument)) != NULL)
503 existingPortClass = getExistingPortClass(argumentClass,
true);
504 if (! existingPortClass)
506 inputArgumentClasses.push_back(argumentClass);
512 else if ((argumentClass = parseOutputDataParameter(annotation, argument)) != NULL)
514 existingPortClass = getExistingPortClass(argumentClass,
false);
515 if (! existingPortClass)
517 outputArgumentClasses.push_back(argumentClass);
521 sawOutputData =
true;
523 else if ((argumentClass = parseInputEventParameter(annotation, argument)) != NULL)
525 existingPortClass = getExistingPortClass(argumentClass,
true);
526 if (! existingPortClass)
528 inputArgumentClasses.push_back(argumentClass);
532 sawInputEvent =
true;
534 else if ((argumentClass = parseOutputEventParameter(annotation, argument)) != NULL)
536 existingPortClass = getExistingPortClass(argumentClass,
false);
537 if (! existingPortClass)
539 outputArgumentClasses.push_back(argumentClass);
543 sawOutputEvent =
true;
545 else if ((argumentClass = parseTriggerParameter(annotation, argument)) != NULL)
547 existingPortClass = getExistingPortClass(argumentClass,
false);
548 if (! existingPortClass)
550 outputArgumentClasses.push_back(argumentClass);
554 sawOutputTrigger =
true;
556 else if ((argumentClass = parseInstanceDataParameter(annotation, argument)) != NULL)
558 if (instanceDataClass)
559 existingPortClass = instanceDataClass->
getBase();
563 sawInstanceData =
true;
565 else if ((type = parseTypeParameter(annotation)) != NULL)
567 vuoTypeForArgumentName[argumentName] = type;
569 else if ((details = parseDetailsParameter(annotation)) != NULL)
571 detailsForArgumentName[argumentName] = details;
575 if (argumentClassInNodeClass)
577 size_t argumentIndex = argument->getArgNo();
578 if (function == eventFunction)
580 else if (function == initFunction)
582 else if (function == callbackStartFunction)
584 else if (function == callbackUpdateFunction)
586 else if (function == callbackStopFunction)
590 if (existingPortClass)
591 delete argumentClass;
596 string functionName = function->getName().str();
597 string wronglyAbsentMessage =
" is required in " + functionName;
598 string wronglyPresentMessage =
" is not allowed in " + functionName;
600 if (sawInputData && ! (acceptanceFlags & INPUT_DATA_PRESENT))
601 VUserLog(
"Error: %s", (
"VuoInputData" + wronglyPresentMessage).c_str());
602 if (sawOutputData && ! (acceptanceFlags & OUTPUT_DATA_PRESENT))
603 VUserLog(
"Error: %s", (
"VuoOutputData" + wronglyPresentMessage).c_str());
604 if (sawInputEvent && ! (acceptanceFlags & INPUT_EVENT_PRESENT))
605 VUserLog(
"Error: %s", (
"VuoInputEvent" + wronglyPresentMessage).c_str());
606 if (sawOutputEvent && ! (acceptanceFlags & OUTPUT_EVENT_PRESENT))
607 VUserLog(
"Error: %s", (
"VuoOutputEvent" + wronglyPresentMessage).c_str());
608 if (sawOutputTrigger && ! (acceptanceFlags & OUTPUT_TRIGGER_PRESENT))
609 VUserLog(
"Error: %s", (
"VuoOutputTrigger" + wronglyPresentMessage).c_str());
610 if (sawInstanceData && ! (acceptanceFlags & INSTANCE_DATA_PRESENT))
611 VUserLog(
"Error: %s", (
"VuoInstanceData" + wronglyPresentMessage).c_str());
613 if (! sawInputData && ! (acceptanceFlags & INPUT_DATA_ABSENT))
614 VUserLog(
"Error: %s", (
"VuoInputData" + wronglyAbsentMessage).c_str());
615 if (! sawOutputData && ! (acceptanceFlags & OUTPUT_DATA_ABSENT))
616 VUserLog(
"Error: %s", (
"VuoOutputData" + wronglyAbsentMessage).c_str());
617 if (! sawInputEvent && ! (acceptanceFlags & INPUT_EVENT_ABSENT))
618 VUserLog(
"Error: %s", (
"VuoInputEvent" + wronglyAbsentMessage).c_str());
619 if (! sawOutputEvent && ! (acceptanceFlags & OUTPUT_EVENT_ABSENT))
620 VUserLog(
"Error: %s", (
"VuoOutputEvent" + wronglyAbsentMessage).c_str());
621 if (! sawOutputTrigger && ! (acceptanceFlags & OUTPUT_TRIGGER_ABSENT))
622 VUserLog(
"Error: %s", (
"VuoOutputTrigger" + wronglyAbsentMessage).c_str());
623 if (! sawInstanceData && ! (acceptanceFlags & INSTANCE_DATA_ABSENT))
624 VUserLog(
"Error: %s", (
"VuoInstanceData" + wronglyAbsentMessage).c_str());
628 map<string, VuoCompilerInputEventPortClass *> inputEventPortClassForDataClassName;
629 for (map<string, VuoCompilerPortClass *>::iterator i = portClassForArgumentName.begin(); i != portClassForArgumentName.end(); ++i)
631 string argumentName = i->first;
636 bool isDataInDetails =
false;
641 inputEventPortClassForDataClassName[dataPortName] = eventPortClass;
645 map<string, VuoCompilerOutputEventPortClass *> outputEventPortClassForDataClassName;
646 for (map<string, VuoCompilerPortClass *>::iterator i = portClassForArgumentName.begin(); i != portClassForArgumentName.end(); ++i)
648 string argumentName = i->first;
653 bool isDataInDetails =
false;
658 outputEventPortClassForDataClassName[dataPortName] = eventPortClass;
664 vector<VuoPortClass *> addedInputPortClasses;
665 for (vector<VuoCompilerNodeArgumentClass *>::iterator i = inputArgumentClasses.begin(); i != inputArgumentClasses.end(); ++i)
672 if (! eventPortClass)
676 addedInputPortClasses.push_back(eventPortClass->
getBase());
681 vector<VuoPortClass *>::iterator oldBase = find(addedInputPortClasses.begin(), addedInputPortClasses.end(), eventPortClass->
getBase());
683 if (oldBase != addedInputPortClasses.end())
685 addedInputPortClasses.insert(oldBase,eventPortClass->
getBase());
686 addedInputPortClasses.erase(oldBase);
693 vector<VuoPortClass *> addedOutputPortClasses;
694 for (vector<VuoCompilerNodeArgumentClass *>::iterator i = outputArgumentClasses.begin(); i != outputArgumentClasses.end(); ++i)
700 if (! eventPortClass)
704 addedOutputPortClasses.push_back(eventPortClass->
getBase());
709 vector<VuoPortClass *>::iterator oldBase = find(addedOutputPortClasses.begin(), addedOutputPortClasses.end(), eventPortClass->
getBase());
711 if (oldBase != addedOutputPortClasses.end())
713 addedOutputPortClasses.insert(oldBase,eventPortClass->
getBase());
714 addedOutputPortClasses.erase(oldBase);
723 if (!
getBase()->getRefreshPortClass()->hasCompiler())
729 inputPortClasses.erase(inputPortClasses.begin());
734 addedInputPortClasses.insert(addedInputPortClasses.begin(), refreshPortClass);
739 inputPortClasses.insert(inputPortClasses.end(), addedInputPortClasses.begin(), addedInputPortClasses.end());
742 outputPortClasses.insert(outputPortClasses.end(), addedOutputPortClasses.begin(), addedOutputPortClasses.end());
746 vector<VuoPortClass *> portClasses;
747 portClasses.insert(portClasses.end(), addedInputPortClasses.begin(), addedInputPortClasses.end());
748 portClasses.insert(portClasses.end(), addedOutputPortClasses.begin(), addedOutputPortClasses.end());
749 for (vector<VuoPortClass *>::iterator i = portClasses.begin(); i != portClasses.end(); ++i)
758 map<string, VuoType *>::iterator vuoTypeIter = vuoTypeForArgumentName.find(dataClassName);
759 if (vuoTypeIter != vuoTypeForArgumentName.end())
762 vuoTypeForArgumentName.erase(vuoTypeIter);
768 if (triggerPortClass)
771 map<string, VuoType *>::iterator vuoTypeIter = vuoTypeForArgumentName.find(triggerName);
772 if (vuoTypeIter != vuoTypeForArgumentName.end())
775 vuoTypeForArgumentName.erase(vuoTypeIter);
779 for (map<string, VuoType *>::iterator i = vuoTypeForArgumentName.begin(); i != vuoTypeForArgumentName.end(); ++i)
783 for (map<string, json_object *>::iterator i = detailsForArgumentName.begin(); i != detailsForArgumentName.end(); ++i)
785 string argumentName = i->first;
786 json_object *details = i->second;
800 for (vector<VuoPortClass *>::iterator i = addedInputPortClasses.begin(); i != addedInputPortClasses.end(); ++i)
803 bool isEventBlockingInDetails =
false;
805 if (isEventBlockingInDetails)
808 if (eventBlockingStr ==
"none")
810 else if (eventBlockingStr ==
"door")
812 else if (eventBlockingStr ==
"wall")
816 VUserLog(
"Error: Unknown option for \"eventBlocking\": %s", eventBlockingStr.c_str());
822 portsWithExplicitEventBlockingNone.insert(eventPortClass);
827 for (vector<VuoPortClass *>::iterator i = addedOutputPortClasses.begin(); i != addedOutputPortClasses.end(); ++i)
830 if (triggerPortClass)
832 bool isEventThrottlingInDetails =
false;
834 if (isEventThrottlingInDetails)
837 if (eventThrottlingStr ==
"enqueue")
839 else if (eventThrottlingStr ==
"drop")
843 VUserLog(
"Error: Unknown option for \"throttling\": %s", eventThrottlingStr.c_str());
852 for (vector<VuoPortClass *>::iterator i = inputPortClasses.begin(); i != inputPortClasses.end(); ++i)
858 bool isPortActionInDetails =
false;
861 if (isPortActionInDetails)
864 portsWithExplicitEventBlockingNone.find(eventPortClass) != portsWithExplicitEventBlockingNone.end())
877 if (function == eventFunction)
882 else if (function == initFunction)
884 Type *firstParameterType = function->getFunctionType()->getParamType( dataClass->
getIndexInInitFunction() );
887 else if (function == callbackStartFunction)
892 else if (function == callbackUpdateFunction)
897 else if (function == callbackStopFunction)
911 if (annotation !=
"vuoInputData")
923 if (annotation !=
"vuoOutputData")
927 if (! a->getType()->isPointerTy())
929 VUserLog(
"Error: Output port data %s must be a pointer.", argumentName.c_str());
958 if (! a->getType()->isPointerTy())
960 VUserLog(
"Error: Output port %s must be a pointer.", argumentName.c_str());
976 if (! a->getType()->isPointerTy())
978 VUserLog(
"Error: Output trigger %s must be a pointer.", argumentName.c_str());
990 if (annotation !=
"vuoInstanceData")
994 if (! a->getType()->isPointerTy())
996 VUserLog(
"Error: Node instance data %s must be a pointer.", argumentName.c_str());
1000 Type *instanceDataType =
static_cast<PointerType *
>(a->getType())->getElementType();
1007VuoType * VuoCompilerNodeClass::parseTypeParameter(
string annotation)
1015 if (typeName ==
"void")
1022 vector<string> compatibleTypes;
1027 vector<string> innermostCompatibleTypes = compatibleTypesIter->second;
1028 for (vector<string>::iterator i = innermostCompatibleTypes.begin(); i != innermostCompatibleTypes.end(); ++i)
1029 compatibleTypes.push_back(prefix + *i);
1044json_object * VuoCompilerNodeClass::parseDetailsParameter(
string annotation)
1049 json_object *detailsObj = NULL;
1051 if (details.find_first_not_of(
' ') != string::npos)
1053 detailsObj = json_tokener_parse(details.c_str());
1055 VUserLog(
"Error: Couldn't parse vuoDetails for `%s`: %s",
getBase()->getClassName().c_str(), details.c_str());
1069 if (existingInputPortClass || existingOutputPortClass)
1073 if (! existingOutputPortClass)
1076 else if ((isInput && existingOutputPortClass) || (! isInput && existingInputPortClass))
1078 VUserLog(
"Error: Port %s is declared as an input port in one function and an output port in another function.", argumentName.c_str());
1082 VuoPortClass *existingPortClass = (existingInputPortClass ? existingInputPortClass : existingOutputPortClass);
1086 return existingPortClass;
1111 return moduleKey +
".vuonode";
1145 return eventFunction;
1153 return initFunction;
1161 return finiFunction;
1169 return callbackStartFunction;
1177 return callbackUpdateFunction;
1185 return callbackStopFunction;
1225 return triggerDescriptions;
1234 for (vector<VuoPortClass *>::iterator i = inputPortClasses.begin(); i != inputPortClasses.end(); ++i)
1235 if ((*i)->getName() == portName)
1247 for (vector<VuoPortClass *>::iterator i = outputPortClasses.begin(); i != outputPortClasses.end(); ++i)
1248 if ((*i)->getName() == portName)
1259 return instanceDataClass;
1267 ostringstream documentation;
1269 documentation <<
"/**" << endl;
1274 if (!description.empty())
1276 documentation <<
" * " << description << endl;
1277 documentation <<
" * " << endl;
1283 vector< pair<string, VuoPortClass *> > portClasses;
1284 for (vector<VuoPortClass *>::iterator i = inputPortClasses.begin(); i != inputPortClasses.end(); ++i)
1286 portClasses.push_back( make_pair(
"in", *i) );
1288 for (vector<VuoPortClass *>::iterator i = outputPortClasses.begin(); i != outputPortClasses.end(); ++i)
1291 portClasses.push_back( make_pair(isTrigger ?
"gen" :
"out", *i) );
1294 for (vector< pair<string, VuoPortClass *> >::iterator i = portClasses.begin(); i != portClasses.end(); ++i)
1296 string portKind = i->first;
1300 string portTypeName = (portType ? portType->
getModuleKey() :
"event");
1301 string portClassName = portClass->
getName();
1302 documentation <<
" * @param[" << portKind <<
"] " << portTypeName <<
" " << portClassName << endl;
1305 documentation <<
" */";
1307 return documentation.str();
1318 return typeNameIter->second;
1331 vector<string> keywords;
1334 bool nodeHasTriggerPort =
false;
1336 for (vector<VuoPortClass *>::iterator i = outputPortClasses.begin(); i != outputPortClasses.end(); ++i)
1340 nodeHasTriggerPort =
true;
1345 if (nodeHasTriggerPort)
1347 keywords.push_back(
"bang");
1348 keywords.push_back(
"events");
1349 keywords.push_back(
"trigger");
1350 keywords.push_back(
"fire");
1356 if (nodeTitleBeginsWithSend || nodeTitleBeginsWithReceive)
1358 keywords.push_back(
"i/o");
1359 keywords.push_back(
"interface");
1361 if (nodeTitleBeginsWithSend)
1363 keywords.push_back(
"output");
1364 keywords.push_back(
"consumer");
1367 if (nodeTitleBeginsWithReceive)
1369 keywords.push_back(
"input");
1370 keywords.push_back(
"provider");
1375 keywords.push_back(
"conversion");
1378 keywords.push_back(
"subcomposition");
1381 keywords.push_back(
"filter");
1384 keywords.push_back(
"generator");
1387 keywords.push_back(
"transition");
1392 keywords.push_back(
"premium");
1393 keywords.push_back(
"pro");
1436 int imagePortCount = 0;
1441 string name = p->getName();
1442 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
1443 if (isInput && (name ==
"mask"))
1456 return imagePortCount;
1464 return (instanceDataClass != NULL);
1472 return _isSubcomposition;
1475void VuoCompilerNodeClass::updateSubcompositionStatus()
1485 string dir, file, ext;
1495 return containedNodes;