]> AND Private Git Repository - blast.git/blob - BlockImplementation.cpp
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
started to include patterns in implementation
[blast.git] / BlockImplementation.cpp
1 #include "BlockImplementation.h"\r
2 \r
3 #include "FunctionalBlock.h"\r
4 #include "ReferenceBlock.h"\r
5 #include "ReferenceInterface.h"\r
6 #include "FunctionalInterface.h"\r
7 #include "BlockParameter.h"\r
8 \r
9 \r
10 BlockImplementation::BlockImplementation(const QString& _xmlFile) {\r
11   xmlFile = _xmlFile;  \r
12 \r
13   evaluator = new ArithmeticEvaluator;\r
14   evaluator->setVariableMarkers("@$");\r
15 }\r
16 \r
17 BlockImplementation::BlockImplementation(const QString& _xmlFile, const QString &_referenceXml, const QString &_referenceMd5) {\r
18   xmlFile = _xmlFile;  \r
19   referenceXml = _referenceXml;\r
20   referenceMd5 = _referenceMd5;\r
21 }\r
22 \r
23 void BlockImplementation::assignPatterns(FunctionalBlock *_block) throw(Exception) {\r
24   \r
25   block = _block;\r
26 \r
27   QFile implFile(xmlFile);\r
28 \r
29   // reading in into QDomDocument\r
30   QDomDocument document("implFile");\r
31 \r
32   if (!implFile.open(QIODevice::ReadOnly)) {\r
33     throw(Exception(IMPLFILE_NOACCESS));\r
34   }\r
35   if (!document.setContent(&implFile)) {\r
36     implFile.close();\r
37     throw(Exception(IMPLFILE_NOACCESS));\r
38   }\r
39   implFile.close();\r
40   QDomElement impl = document.documentElement();\r
41   QDomNodeList patternNode = impl.elementsByTagName("patterns");\r
42   if (patternNode.isEmpty()) return;\r
43   QDomElement patternElt = patternNode.at(0).toElement();\r
44   \r
45 }\r
46 \r
47 void BlockImplementation::generateVHDL(FunctionalBlock* _block, const QString &path) throw(Exception) {\r
48 \r
49   block = _block;\r
50 \r
51   QFile implFile(xmlFile);\r
52 \r
53   // reading in into QDomDocument\r
54   QDomDocument document("implFile");\r
55 \r
56   if (!implFile.open(QIODevice::ReadOnly)) {\r
57     throw(Exception(IMPLFILE_NOACCESS));\r
58   }\r
59   if (!document.setContent(&implFile)) {\r
60     implFile.close();\r
61     throw(Exception(IMPLFILE_NOACCESS));\r
62   }\r
63   implFile.close();\r
64 \r
65   bool genController = false;\r
66   QString coreFile = "";\r
67   QString controllerFile = "";\r
68 \r
69   if (reference->isWBConfigurable()) {\r
70     genController = true;\r
71     controllerFile = path;\r
72     controllerFile.append(block->getName());\r
73     controllerFile.append("_ctrl.vhd");    \r
74   }\r
75   else {\r
76     controllerFile = "nofile.vhd";    \r
77   }\r
78   coreFile = path;\r
79   coreFile.append(block->getName());\r
80   coreFile.append(".vhd");\r
81 \r
82   QFile vhdlCore(coreFile);\r
83   QFile vhdlController(controllerFile);\r
84 \r
85   if (!vhdlCore.open(QIODevice::WriteOnly)) {\r
86     throw(Exception(VHDLFILE_NOACCESS));\r
87   }\r
88 \r
89   if (genController) {\r
90     if (!vhdlController.open(QIODevice::WriteOnly)) {\r
91       throw(Exception(VHDLFILE_NOACCESS));\r
92     }\r
93   }\r
94   QTextStream outCore(&vhdlCore);\r
95   QTextStream outController;\r
96   if (genController) {\r
97     outController.setDevice(&vhdlController);\r
98   }\r
99 \r
100   try {\r
101 \r
102 \r
103     //Get the root element\r
104     QDomElement impl = document.documentElement();\r
105     QDomElement eltComments = impl.firstChildElement("comments");\r
106     generateComments(eltComments, coreFile, outCore);\r
107     QDomElement eltLibs = eltComments.nextSiblingElement("libraries");\r
108     generateLibraries(eltLibs, outCore);\r
109     generateEntity(outCore, genController);\r
110     QDomElement eltArch = eltLibs.nextSiblingElement("architecture");\r
111     generateArchitecture(eltArch, outCore);\r
112     if (genController) {\r
113       generateController(outController);\r
114     }\r
115   }\r
116   catch(Exception err) {\r
117     throw(err);\r
118   }\r
119 \r
120   vhdlCore.close();\r
121   vhdlController.close();\r
122 }\r
123 \r
124 // This function generates the comments part of the VHDL document\r
125 void BlockImplementation::generateComments(QDomElement &elt, QString coreFile, QTextStream& out) throw(Exception) {\r
126 \r
127   for(int i = 0; i < 50; i++) {\r
128     out << "--";\r
129   }\r
130   out << "\n--\n";\r
131   QString fileName = coreFile;\r
132   out << "--  File        : " << fileName << "\n";\r
133   out << "--\n";\r
134   QDomElement eltAuthor = elt.firstChildElement("author");\r
135   QString firstName = eltAuthor.attribute("firstname","");\r
136   QString lastName = eltAuthor.attribute("lastname","");\r
137   QString mail = eltAuthor.attribute("mail","");\r
138   out << "--  Author(s)   : "<<firstName+" "<<lastName<<" ("<<mail<<")\n";\r
139   out << "--\n";\r
140   QDomElement eltDate = eltAuthor.nextSiblingElement("date");\r
141   QString crea = eltDate.attribute("creation","");\r
142   out << "--  Creation Date   : "<<crea<<"\n";\r
143   out << "--\n";\r
144   QDomElement eltRelated = eltDate.nextSiblingElement("related_files");\r
145   QString relateds = eltRelated.attribute("list","");\r
146   out << "--  Related files   :\n"<<relateds<<"\n";\r
147   out << "--\n";\r
148   QDomElement eltDesc = eltRelated.nextSiblingElement("description");\r
149   QDomElement desc = eltDesc.firstChildElement();\r
150   QString descTxt = desc.text();\r
151   out << "--  Decription      :\n"<<descTxt<<"\n";\r
152   out << "--\n";\r
153   QDomElement eltNote = eltDesc.nextSiblingElement("description");\r
154   QDomElement note = eltNote.firstChildElement();\r
155   QString noteTxt = note.text();\r
156   out << "--  Note          :\n"<<noteTxt<<"\n";\r
157   out << "--\n";\r
158   for(int i = 0; i < 50; i++) {\r
159     out << "--";\r
160   }\r
161   out << "\n\n";\r
162 }\r
163 \r
164 // This function generates the library part of the VHDL document\r
165 void BlockImplementation::generateLibraries(QDomElement &elt, QTextStream& out) throw(Exception) {\r
166 \r
167   QDomNodeList listLib = elt.elementsByTagName("library");\r
168   for(int i = 0; i < listLib.length(); i++) {\r
169     QDomNode nodeLib = listLib.item(i);\r
170     QDomElement eltLib = nodeLib.toElement();\r
171     QString nameLib = eltLib.attribute("name", "");\r
172     out << "library " << nameLib << ";\n";\r
173     QDomNodeList listPack = eltLib.elementsByTagName("package");\r
174     for(int j = 0; j < listPack.length(); j++) {\r
175       QDomNode nodePack = listPack.item(j);\r
176       QDomElement eltPack = nodePack.toElement();\r
177       QString namePack = eltPack.attribute("name", "");\r
178       QString usePack = elt.attribute("use","");\r
179       out << "use " << nameLib << "." << namePack << "." << usePack << ";\n";\r
180     }\r
181     out << "\n";\r
182   }\r
183 }\r
184 \r
185 // This function generates the entity part of the VHDL document\r
186 void BlockImplementation::generateEntity(QTextStream& out, bool hasController) throw(Exception) {\r
187 \r
188   int i=0;\r
189   nameEnt = reference->getName();\r
190   //QList<BlockParameter*> listParams = reference->getParameters();\r
191   QList<AbstractInterface*> listInputs = reference->getInputs();\r
192   QList<AbstractInterface*> listOutputs = reference->getOutputs();\r
193   QList<AbstractInterface*> listBidirs = reference->getBidirs();\r
194   QString typePort, namePort;\r
195 \r
196   out << "entity " << nameEnt << " is\n";\r
197 \r
198 \r
199   /* TODO : rewrite the generation to take into acocunt the new object hierarchy */\r
200 \r
201   // Generation of the generics\r
202   QList<BlockParameter*> listGenerics = reference->getGenericParameters();\r
203   if ((!listGenerics.isEmpty()) || (hasController)) {\r
204     out << "  generic (" << endl;\r
205     if (hasController) {\r
206       out << "    wb_data_width : integer = 16;" << endl;\r
207       out << "    wb_addr_width : integer = 12";\r
208       if (!listGenerics.isEmpty()) out << ";";\r
209       out << endl;\r
210     }\r
211     for(i=0;i<listGenerics.size()-1;i++) {\r
212       out << "    " << listGenerics.at(i)->toVHDL(BlockParameter::Entity, 0);\r
213     }\r
214     out << "    " << listGenerics.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma);\r
215 \r
216     out << "    );" << endl;\r
217   }\r
218 \r
219   out << "  port (" << endl;\r
220 \r
221   // Generation of the clk & rst signals\r
222   out << "    -- clk/rst" << endl;\r
223   for(int i = 0; i < listInputs.size(); i++) {\r
224     if(listInputs.at(i)->getPurpose() == AbstractInterface::Clock || listInputs.at(i)->getPurpose() == AbstractInterface::Reset) {\r
225       out << "    " << listInputs.at(i)->getName() << " : in std_logic;" << endl;\r
226     }\r
227   }\r
228 \r
229   if (hasController) {\r
230     // Generation of the wishbone signals\r
231     out << "    -- registers r/w via wishbone" << endl;\r
232     QList<BlockParameter*> listWB = reference->getWishboneParameters();\r
233     for(i=0;i<listWB.size()-1;i++) {\r
234       out << "    " << listWB.at(i)->toVHDL(BlockParameter::Entity, 0);\r
235     }\r
236     out << "    " << listWB.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma);\r
237   }\r
238 \r
239 \r
240   // Generation of the data signals\r
241   out << "-- data ports\n";\r
242   for(int i = 0; i < listInputs.size(); i++) {\r
243     namePort = getIfaceUserName(reference->AbstractBlock::getIfaceFromName(listInputs.at(i)->getName()));\r
244     if(listInputs.at(i)->getWidth().compare("1"))\r
245       typePort = "std_logic";\r
246     else\r
247       typePort = calculateWidth(listInputs.at(i)->getWidth());\r
248     if(listInputs.at(i)->getPurpose() == 1)\r
249       out << namePort << " : in std_logic_vector(" << typePort << " -1 downto 0) ;\n";\r
250   }\r
251 \r
252   for(int i = 0; i < listOutputs.size(); i++) {\r
253     namePort = getIfaceUserName(reference->AbstractBlock::getIfaceFromName(listOutputs.at(i)->getName()));\r
254     if(listOutputs.at(i)->getWidth().compare("1"))\r
255       typePort = "std_logic";\r
256     else\r
257       typePort = calculateWidth(listOutputs.at(i)->getWidth());\r
258     if(listOutputs.at(i)->getPurpose() == 1)\r
259       out << namePort << " : out std_logic_vector(" << typePort << " -1 downto 0) ;\n";\r
260   }\r
261 \r
262   for(int i = 0; i < listBidirs.size(); i++) {\r
263     namePort = getIfaceUserName(reference->AbstractBlock::getIfaceFromName(listBidirs.at(i)->getName()));\r
264     if(listBidirs.at(i)->getWidth().compare(("1")))\r
265       typePort = "std_logic";\r
266     else\r
267       typePort = calculateWidth((listBidirs.at(i)->getWidth()));\r
268     if(listBidirs.at(i)->getPurpose() == 1)\r
269       out << namePort << " : inout std_logic_vector(" << typePort << " -1 downto 0) ;\n";\r
270   }\r
271 }\r
272 \r
273 // This function generates the architecture part of the VHDL document\r
274 void BlockImplementation::generateArchitecture(QDomElement &elt, QTextStream& out) throw(Exception) {\r
275 \r
276   QString expr;\r
277   QDomElement eltArch = elt.nextSiblingElement("architecture");\r
278   out << "architecture " << nameEnt <<"_1 of " << nameEnt << "is\n";\r
279   QString implText = eltArch.text();\r
280   QStringList listLine = implText.split("\n");\r
281   for(int i =0; i < listLine.size(); i++) {\r
282     if(listLine.at(i).contains(QRegularExpression("@foreach{")) != -1) {\r
283       while(listLine.at(i).compare("@endforeach") != -1) {\r
284         expr = expr + listLine.at(i) + '\n';\r
285         i++;\r
286       }\r
287       expr = expr + listLine.at(i);\r
288       out << evalComplex(expr, 1) << '\n';\r
289     }\r
290     if(listLine.at(i).contains(QRegularExpression("@caseeach{")) != -1) {\r
291       while(listLine.at(i).compare("@endcaseeach") != -1) {\r
292         expr = expr + listLine.at(i) + '\n';\r
293         i++;\r
294       }\r
295       expr = expr + listLine.at(i);\r
296       out << evalComplex(expr, 2) << '\n';\r
297     }\r
298 \r
299     if(listLine.at(i).contains('@') == -1)\r
300       out << listLine.at(i) << "\n";\r
301     else\r
302       out << eval(listLine.at(i), out) << "\n";\r
303   }\r
304 }\r
305 \r
306 void BlockImplementation::generateController(QTextStream &out) throw(Exception) {\r
307 }\r
308 \r
309 QString BlockImplementation::eval(QString line, QTextStream& out) {\r
310   QString res, s, begLine, endLine, expr;\r
311   evaluator->setExpression(line);\r
312   QRegExp *rxString = new QRegExp("(.*)@{(.*)}(.*)");\r
313   QRegExp *rxValue = new QRegExp("(.*)@val{(.*)}(.*)");\r
314   QRegExp *rxExpr = new QRegExp(".*@eval{(.*)}.*");\r
315 \r
316   int nbAt = line.count('@');\r
317   while(nbAt != 0) {\r
318     for(int i = 0; i < line.size(); i++) {\r
319       if(rxString->indexIn(line)) {\r
320         begLine = rxString->cap(1);\r
321         s = rxString->cap(2);\r
322         endLine = rxString->cap(3);\r
323         res = begLine + evalString(s) + endLine + '\n';\r
324         nbAt --;\r
325       }\r
326     }\r
327     for(int i = 0; i < line.size(); i++) {\r
328       if(rxValue->indexIn(line)) {\r
329         begLine = rxValue->cap(1);\r
330         s = rxValue->cap(2);\r
331         endLine = rxValue->cap(3);\r
332         res = begLine + evalValue(s) + endLine + '\n';\r
333         nbAt --;\r
334       }\r
335     }\r
336     for(int i = 0; i < line.size(); i++) {\r
337       if(rxExpr->indexIn(line)) {\r
338         expr = rxExpr->cap(1);\r
339         if(expr.count('@') == 0) {\r
340           evaluator->setExpression(expr);\r
341           s = QString::number(evaluator->evaluate());\r
342         }\r
343         res = begLine + s + endLine + '\n';\r
344         nbAt --;\r
345       }\r
346     }\r
347   }\r
348   return res;\r
349 }\r
350 \r
351 QString BlockImplementation::evalComplex(QString line, int id) {\r
352   QString res, s, begLine, endLine, expr;\r
353   QRegExp *rxString = new QRegExp("(.*)@{(.*)}(.*)");\r
354   QRegExp *rxValue = new QRegExp("(.*)@val{(.*)}(.*)");\r
355   QRegExp *rxExpr = new QRegExp(".*@eval{(.*)}.*");\r
356   QRegExp *rxFor = new QRegExp("@foreach{.*}(@{.*})(.*)@endforeach");\r
357   QRegExp *rxCase = new QRegExp("@caseeach{.*,(.*),(.*)}(@{.*})(.*)@endcaseeach");\r
358   QRegExp *rxCaseDown = new QRegExp("@#-:(.*)");\r
359   QRegExp *rxCaseUp = new QRegExp("@#:(.*)");\r
360   evaluator->setExpression(line);\r
361 \r
362   int nbAt = line.count('@') - 2;\r
363   while(nbAt != 0) {\r
364     for(int i = 0; i < line.size(); i++) {\r
365       if(rxString->indexIn(line)) {\r
366         begLine = rxString->cap(1);\r
367         s = rxString->cap(2);\r
368         endLine = rxString->cap(3);\r
369         if(evalStringComplex(s)->size() == 0)\r
370           line = begLine + evalString(s) + endLine;\r
371         nbAt --;\r
372       }\r
373     }\r
374     for(int i = 0; i < line.size(); i++) {\r
375       if(rxValue->indexIn(line)) {\r
376         begLine = rxValue->cap(1);\r
377         s = rxValue->cap(2);\r
378         endLine = rxValue->cap(3);\r
379         line = begLine + evalValue(s) + endLine;\r
380         nbAt --;\r
381       }\r
382     }\r
383     for(int i = 0; i < line.size(); i++) {\r
384       if(rxExpr->indexIn(line)) {\r
385         expr = rxExpr->cap(1);\r
386         if(expr.count('@') == 0) {\r
387           evaluator->setExpression(expr);\r
388           s = QString::number(evaluator->evaluate());\r
389         }\r
390         res = begLine + s + endLine + '\n';\r
391         nbAt --;\r
392       }\r
393     }\r
394   }\r
395 \r
396   if(id == 1) {\r
397     if(rxFor->indexIn(line)) {\r
398       QString intName, instruc;\r
399       intName = rxFor->cap(1);\r
400       instruc = rxFor->cap(2);\r
401       QList<AbstractInterface*> *intList = evalStringComplex(intName);\r
402       if(intList->size() != 0) {\r
403         for(int i = 0; i < intList->size(); i++) {\r
404           res = intList->at(i)->getName() + instruc + '\n';\r
405         }\r
406       }\r
407     }\r
408   }\r
409 \r
410   else if(id == 2) {\r
411     if(rxCase->indexIn(line)) {\r
412       QString intName, sigName, cases, instruc;\r
413       int number;\r
414       sigName = rxCase->cap(1);\r
415       cases = rxCase->cap(2);\r
416       intName = rxCase->cap(3);\r
417       instruc = rxCase->cap(4);\r
418       QList<AbstractInterface*> *intList = evalStringComplex(intName);\r
419       int listSize = intList->count();\r
420       res = "case " + sigName + " is\n";\r
421       if(rxCaseUp->indexIn(cases)) {\r
422         number = rxCaseUp->cap(1).toInt();\r
423         for(int j = number; j < listSize; j++) {\r
424           if(listSize > 0) {\r
425             for(int i = 0; i < listSize; i++) {\r
426               res += "\twhen " + QString::number(number) + " " + intList->at(i)->getName() + instruc + "\n";\r
427             }\r
428           }\r
429           else\r
430             res += "\twhen " + number + ' ' + intName + instruc + "\n";\r
431           number++;\r
432         }\r
433       }\r
434       if(rxCaseDown->indexIn(cases)) {\r
435         number = rxCaseDown->cap(1).toInt();\r
436         for(int j = number; j < listSize; j++) {\r
437           if(listSize > 0) {\r
438             for(int i = 0; i < listSize; i++) {\r
439               res += "\twhen " + QString::number(number) + " " + intList->at(i)->getName() + instruc + "\n";\r
440             }\r
441           }\r
442           else\r
443             res += "\twhen " + number + ' ' + intName + instruc + "\n";\r
444           number--;\r
445         }\r
446         res += "end case ;\n";\r
447       }\r
448     }\r
449   }\r
450   return res;\r
451 }\r
452 \r
453 QString BlockImplementation::evalString(QString s) {\r
454 \r
455   QString name = getIfaceUserName(block->AbstractBlock::getIfaceFromName(s));\r
456   return name;\r
457 }\r
458 \r
459 QList<AbstractInterface*>* BlockImplementation::evalStringComplex(QString s) {\r
460 \r
461   int j = 0;\r
462   QList<AbstractInterface*> *listInterfaces = new QList<AbstractInterface*>();\r
463   AbstractInterface *inter = block->AbstractBlock::getIfaceFromName(s);\r
464   QList<AbstractInterface*> listIntBlock = block->getInterfaces();\r
465   for(int i = 0; i < listIntBlock.size(); i++) {\r
466     if(inter->getName().compare(listIntBlock.at(i)->getName()) < -1) {\r
467       listInterfaces->insert(j, inter);\r
468       j ++;\r
469     }\r
470   }\r
471   return listInterfaces;\r
472 }\r
473 \r
474 QString BlockImplementation::evalValue(QString s) {\r
475 \r
476   QString val = "";\r
477   if(paramMap.contains(s))\r
478     val = paramMap.value(s);\r
479   return val;\r
480 }\r
481 \r
482 QString BlockImplementation::getIfaceUserName(AbstractInterface* refIface) {\r
483 \r
484   if (! refIface->isReferenceInterface()) return "";\r
485 \r
486   AbstractInterface* funcIface = NULL;\r
487 \r
488   if (refIface->getDirection() == AbstractInterface::Input) {\r
489     foreach(AbstractInterface* iface, block->getInputs()) {\r
490       FunctionalInterface* fi = (FunctionalInterface*)iface;\r
491       if (fi->getReference() == refIface) {\r
492         funcIface = iface;\r
493         break;\r
494       }\r
495     }\r
496   }\r
497   else if (refIface->getDirection() == AbstractInterface::Output) {\r
498     foreach(AbstractInterface* iface, block->getOutputs()) {\r
499       FunctionalInterface* fi = (FunctionalInterface*)iface;\r
500       if (fi->getReference() == refIface) {\r
501         funcIface = iface;\r
502         break;\r
503       }\r
504     }\r
505   }\r
506   else if (refIface->getDirection() == AbstractInterface::InOut) {\r
507     foreach(AbstractInterface* iface, block->getBidirs()) {\r
508       FunctionalInterface* fi = (FunctionalInterface*)iface;\r
509       if (fi->getReference() == refIface) {\r
510         funcIface = iface;\r
511         break;\r
512       }\r
513     }\r
514   }\r
515   if (funcIface == NULL) return "";\r
516 \r
517   return funcIface->getName();\r
518 }\r
519 \r
520 QDataStream& operator<<(QDataStream &out, const BlockImplementation &impl) {\r
521 \r
522   out.setVersion(QDataStream::Qt_5_0);\r
523 \r
524   QByteArray blockData;\r
525   QDataStream toWrite(&blockData, QIODevice::WriteOnly);\r
526 \r
527   toWrite << impl.xmlFile;\r
528   toWrite << impl.referenceXml;\r
529   toWrite << impl.referenceMd5;\r
530 \r
531   out << blockData;\r
532 \r
533   return out;\r
534 }\r
535 \r
536 QDataStream& operator>>(QDataStream &in, BlockImplementation &impl) {\r
537 \r
538   quint32 blockSize;\r
539 \r
540   in.setVersion(QDataStream::Qt_5_0);\r
541 \r
542   in >> blockSize;\r
543 \r
544   in >> impl.xmlFile;\r
545   in >> impl.referenceXml;\r
546   in >> impl.referenceMd5;\r
547 \r
548   return in;\r
549 }\r
550 \r
551 QString BlockImplementation::calculateWidth(QString s){\r
552   QRegExp *rxWidth = new QRegExp("$*([a-zA-Z0-9_-]*)");\r
553   QStringList matchList = s.split(" ");\r
554   int pos = 0;\r
555   QString res, line;\r
556   QList<BlockParameter*> listParams = reference->getParameters();\r
557 \r
558   while ((pos = rxWidth->indexIn(s, pos)) != -1) {\r
559     matchList << rxWidth->cap(1);\r
560     pos += rxWidth->matchedLength();\r
561   }\r
562 \r
563   for (int i = 0; i < matchList.size(); i++) {\r
564     QString match = matchList.at(i);\r
565     if(rxWidth->indexIn(match)) {\r
566       for(int j = 0; j < listParams.size(); j++) {\r
567         if(match.compare(listParams.at(j)->getName())) {\r
568           BlockParameter *param = listParams.at(i);\r
569           if(param->getContext() == "generic") {\r
570             match = match.remove('$');\r
571           }\r
572           else {\r
573             match = param->getValue().toString();\r
574           }\r
575         }\r
576       }\r
577     }\r
578   }\r
579   line = matchList.join(' ');\r
580   evaluator->setExpression(line);\r
581   res = evaluator->evaluate();\r
582   return res;\r
583 }\r
584 \r