00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <stdio.h>
00033 #include <iostream>
00034 #include <sstream>
00035 #include <vector>
00036 #include <math.h>
00037
00038 #include "doc_compile.hh"
00039 #include "sigtype.hh"
00040 #include "floats.hh"
00041 #include "sigprint.hh"
00042 #include "sigtyperules.hh"
00043 #include "recursivness.hh"
00044 #include "simplify.hh"
00045 #include "privatise.hh"
00046 #include "prim2.hh"
00047 #include "xtended.hh"
00048 #include "compatibility.hh"
00049 #include "ppsig.hh"
00050 #include "names.hh"
00051 #include "doc.hh"
00052 #include "tlib.hh"
00053 #include "doc_notice.hh"
00054
00055
00056 extern bool gLessTempSwitch;
00057 extern int gMaxCopyDelay;
00058 extern map<string, string> gDocMathStringMap;
00059
00060 extern bool getSigListNickName(Tree t, Tree& id);
00061
00062 static void extractMetadata(const string& fulllabel, string& label, map<string, set<string> >& metadata);
00063 static string rmWhiteSpaces(const string& s);
00064
00065 static const unsigned int MAX_RIGHT_MEMBER = 20;
00066 static const unsigned int MAX_SUB_EXPR = 10;
00067
00068
00069
00070
00071
00072
00073 map<string, int> DocCompiler::fIDCounters;
00074
00075 string DocCompiler::getFreshID(const string& prefix)
00076 {
00077 if (fIDCounters.find(prefix) == fIDCounters.end()) {
00078 fIDCounters[prefix] = 1;
00079 }
00080 int n = fIDCounters[prefix];
00081 fIDCounters[prefix] = n+1;
00082
00083 return subst("$0_{$1}", prefix, docT(n));
00084 }
00085
00086
00087
00088
00089
00090
00091 Tree DocCompiler::annotate(Tree LS)
00092 {
00093 recursivnessAnnotation(LS);
00094 typeAnnotation(LS);
00095 sharingAnalysis(LS);
00096 fOccMarkup.mark(LS);
00097
00098 return LS;
00099 }
00100
00101
00102
00103
00104
00105 Lateq* DocCompiler::compileLateq (Tree L, Lateq* compiledEqn)
00106 {
00107
00108
00109 fLateq = compiledEqn;
00110 int priority = 0;
00111
00112 for (int i = 0; isList(L); L = tl(L), i++) {
00113 Tree sig = hd(L);
00114 Tree id;
00115 if(getSigNickname(sig, id)) {
00116
00117 fLateq->addOutputSigFormula(subst("$0(t) = $1", tree2str(id), CS(sig, priority), docT(i)));
00118 } else {
00119
00120 if (fLateq->outputs() == 1) {
00121 fLateq->addOutputSigFormula(subst("y(t) = $0", CS(sig, priority)));
00122 gDocNoticeFlagMap["outputsig"] = true;
00123 } else {
00124 fLateq->addOutputSigFormula(subst("$0(t) = $1", getFreshID("y"), CS(sig, priority)));
00125 gDocNoticeFlagMap["outputsigs"] = true;
00126 }
00127 }
00128 }
00129 return fLateq;
00130 }
00131
00132
00133
00134
00135
00136
00137
00144 bool DocCompiler::getCompiledExpression(Tree sig, string& cexp)
00145 {
00146 return fCompileProperty.get(sig, cexp);
00147 }
00148
00149
00156 string DocCompiler::setCompiledExpression(Tree sig, const string& cexp)
00157 {
00158 fCompileProperty.set(sig, cexp);
00159 return cexp;
00160 }
00161
00162
00168 string DocCompiler::CS (Tree sig, int priority)
00169 {
00170 string code;
00171
00172 if (!getCompiledExpression(sig, code)) {
00173 code = generateCode(sig, priority);
00174 setCompiledExpression(sig, code);
00175 }
00176 return code;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00196 string DocCompiler::generateCode (Tree sig, int priority)
00197 {
00198 int i;
00199 double r;
00200 Tree c, sel, x, y, z, u, label, ff, largs, type, name, file;
00201
00202 if ( getUserData(sig) ) { printGCCall(sig,"generateXtended"); return generateXtended (sig, priority); }
00203 else if ( isSigInt(sig, &i) ) { printGCCall(sig,"generateNumber"); return generateNumber (sig, docT(i)); }
00204 else if ( isSigReal(sig, &r) ) { printGCCall(sig,"generateNumber"); return generateNumber (sig, docT(r)); }
00205 else if ( isSigInput(sig, &i) ) { printGCCall(sig,"generateInput"); return generateInput (sig, docT(i+1)); }
00206 else if ( isSigOutput(sig, &i, x) ) { printGCCall(sig,"generateOutput"); return generateOutput (sig, docT(i+1), CS(x, priority)); }
00207
00208 else if ( isSigFixDelay(sig, x, y) ) { printGCCall(sig,"generateFixDelay"); return generateFixDelay (sig, x, y, priority); }
00209 else if ( isSigPrefix(sig, x, y) ) { printGCCall(sig,"generatePrefix"); return generatePrefix (sig, x, y, priority); }
00210 else if ( isSigIota(sig, x) ) { printGCCall(sig,"generateIota"); return generateIota (sig, x); }
00211
00212 else if ( isSigBinOp(sig, &i, x, y) ) { printGCCall(sig,"generateBinOp"); return generateBinOp (sig, i, x, y, priority); }
00213 else if ( isSigFFun(sig, ff, largs) ) { printGCCall(sig,"generateFFun"); return generateFFun (sig, ff, largs, priority); }
00214 else if ( isSigFConst(sig, type, name, file) ) { printGCCall(sig,"generateFConst"); return generateFConst (sig, tree2str(file), tree2str(name)); }
00215 else if ( isSigFVar(sig, type, name, file) ) { printGCCall(sig,"generateFVar"); return generateFVar (sig, tree2str(file), tree2str(name)); }
00216
00217
00218
00219 else if ( isSigDocConstantTbl(sig, x, y) ) { printGCCall(sig,"generateDocConstantTbl"); return generateDocConstantTbl (sig, x, y); }
00220 else if ( isSigDocWriteTbl(sig,x,y,z,u) ) { printGCCall(sig,"generateDocWriteTbl"); return generateDocWriteTbl (sig, x, y, z, u); }
00221 else if ( isSigDocAccessTbl(sig, x, y) ) { printGCCall(sig, "generateDocAccessTbl"); return generateDocAccessTbl(sig, x, y); }
00222
00223
00224 else if ( isSigSelect2(sig, sel, x, y) ) { printGCCall(sig,"generateSelect2"); return generateSelect2 (sig, sel, x, y, priority); }
00225 else if ( isSigSelect3(sig, sel, x, y, z) ) { printGCCall(sig,"generateSelect3"); return generateSelect3 (sig, sel, x, y, z, priority); }
00226
00227 else if ( isProj(sig, &i, x) ) { printGCCall(sig,"generateRecProj"); return generateRecProj (sig, x, i, priority); }
00228
00229 else if ( isSigIntCast(sig, x) ) { printGCCall(sig,"generateIntCast"); return generateIntCast (sig, x, priority); }
00230 else if ( isSigFloatCast(sig, x) ) { printGCCall(sig,"generateFloatCast"); return generateFloatCast(sig, x, priority); }
00231
00232 else if ( isSigButton(sig, label) ) { printGCCall(sig,"generateButton"); return generateButton (sig, label); }
00233 else if ( isSigCheckbox(sig, label) ) { printGCCall(sig,"generateCheckbox"); return generateCheckbox (sig, label); }
00234 else if ( isSigVSlider(sig, label,c,x,y,z) ) { printGCCall(sig,"generateVSlider"); return generateVSlider (sig, label, c,x,y,z); }
00235 else if ( isSigHSlider(sig, label,c,x,y,z) ) { printGCCall(sig,"generateHSlider"); return generateHSlider (sig, label, c,x,y,z); }
00236 else if ( isSigNumEntry(sig, label,c,x,y,z) ) { printGCCall(sig,"generateNumEntry"); return generateNumEntry (sig, label, c,x,y,z); }
00237
00238 else if ( isSigVBargraph(sig, label,x,y,z) ) { printGCCall(sig,"generateVBargraph"); return CS(z, priority);}
00239 else if ( isSigHBargraph(sig, label,x,y,z) ) { printGCCall(sig,"generateHBargraph"); return CS(z, priority);}
00240 else if ( isSigAttach(sig, x, y) ) { printGCCall(sig,"generateAttach"); return generateAttach (sig, x, y, priority); }
00241
00242 else {
00243 cerr << "Error in d signal, unrecognized signal : " << *sig << endl;
00244 exit(1);
00245 }
00246 assert(0);
00247 return "error in generate code";
00248 }
00249
00250
00257 void DocCompiler::printGCCall(Tree sig, const string& calledFunction)
00258 {
00259 bool printCalls = false;
00260 bool maskSigs = false;
00261
00262 if(printCalls) {
00263 cerr << " -> generateCode calls " << calledFunction;
00264 if(maskSigs) {
00265 cerr << endl;
00266 } else {
00267 cerr << " on " << ppsig(sig) << endl;
00268 }
00269 }
00270 }
00271
00272
00273
00274
00275
00276
00277
00278 string DocCompiler::generateNumber (Tree sig, const string& exp)
00279 {
00280 string ctype, vname;
00281 Occurences* o = fOccMarkup.retrieve(sig);
00282
00283
00284 if (o->getMaxDelay()>0) {
00285 getTypedNames(getSigType(sig), "r", ctype, vname);
00286 gDocNoticeFlagMap["recursigs"] = true;
00287
00288 generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay());
00289 }
00290 return exp;
00291 }
00292
00293
00294
00295
00296
00297
00298 string DocCompiler::generateFConst (Tree sig, const string& file, const string& exp)
00299 {
00300 string ctype, vname;
00301 Occurences* o = fOccMarkup.retrieve(sig);
00302
00303 if (o->getMaxDelay()>0) {
00304 getTypedNames(getSigType(sig), "r", ctype, vname);
00305 gDocNoticeFlagMap["recursigs"] = true;
00306
00307 generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay());
00308 }
00309
00310 if (exp == "fSamplingFreq") {
00311 gDocNoticeFlagMap["fsamp"] = true;
00312 return "f_S";
00313 }
00314
00315 return "\\mathrm{"+exp+"}";
00316 }
00317
00318
00319
00320
00321
00322
00323 string DocCompiler::generateFVar (Tree sig, const string& file, const string& exp)
00324 {
00325 string ctype, vname;
00326 Occurences* o = fOccMarkup.retrieve(sig);
00327
00328 if (o->getMaxDelay()>0) {
00329 getTypedNames(getSigType(sig), "r", ctype, vname);
00330 gDocNoticeFlagMap["recursigs"] = true;
00331
00332 setVectorNameProperty(sig, vname);
00333 generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay());
00334 }
00335 return generateCacheCode(sig, exp);
00336 }
00337
00338
00339
00340
00341
00342
00343
00344 string DocCompiler::generateInput (Tree sig, const string& idx)
00345 {
00346 if (fLateq->inputs() == 1) {
00347 setVectorNameProperty(sig, "x");
00348 fLateq->addInputSigFormula("x(t)");
00349 gDocNoticeFlagMap["inputsig"] = true;
00350 return generateCacheCode(sig, "x(t)");
00351 } else {
00352 setVectorNameProperty(sig, subst("x_{$0}", idx));
00353 fLateq->addInputSigFormula(subst("x_{$0}(t)", idx));
00354 gDocNoticeFlagMap["inputsigs"] = true;
00355 return generateCacheCode(sig, subst("x_{$0}(t)", idx));
00356 }
00357 }
00358
00359
00361 string DocCompiler::generateOutput (Tree sig, const string& idx, const string& arg)
00362 {
00363 string dst;
00364
00365 if (fLateq->outputs() == 1) {
00366 dst = subst("y(t)", idx);
00367 gDocNoticeFlagMap["outputsig"] = true;
00368 } else {
00369 dst = subst("y_{$0}(t)", idx);
00370 gDocNoticeFlagMap["outputsigs"] = true;
00371 }
00372
00373 fLateq->addOutputSigFormula(subst("$0 = $1", dst, arg));
00374 return dst;
00375 }
00376
00377
00378
00379
00380
00381
00398 string DocCompiler::generateBinOp(Tree sig, int opcode, Tree arg1, Tree arg2, int priority)
00399 {
00400 string s;
00401 int thisPriority = gBinOpLateqTable[opcode]->fPriority;
00402
00403
00404 string lpar = "";
00405 string rpar = "";
00406 if (thisPriority < priority) {
00407 lpar = " \\left(";
00408 rpar = "\\right) ";
00409 }
00410
00411 Type t1 = getSigType(arg1);
00412 Type t2 = getSigType(arg2);
00413 bool intOpDetected = false;
00414 if ( (t1->nature() == kInt) && (t2->nature() == kInt) ) {
00415 intOpDetected = true;
00416 }
00417
00418 string op;
00419 if(!intOpDetected) {
00420 op = gBinOpLateqTable[opcode]->fName;
00421 } else {
00422 switch (opcode) {
00423 case kAdd:
00424 op = "\\oplus";
00425 gDocNoticeFlagMap["intplus"] = true;
00426 break;
00427 case kSub:
00428 op = "\\ominus";
00429 gDocNoticeFlagMap["intminus"] = true;
00430 break;
00431 case kMul:
00432 op = "\\odot";
00433 gDocNoticeFlagMap["intmult"] = true;
00434 break;
00435 case kDiv:
00436 op = "\\oslash";
00437 gDocNoticeFlagMap["intdiv"] = true;
00438 break;
00439 default:
00440 op = gBinOpLateqTable[opcode]->fName;
00441 break;
00442 }
00443 }
00444
00445
00446 if ( (opcode == kDiv) && (!intOpDetected) ) {
00447 s = subst("$0\\frac{$1}{$2}$3", lpar, CS(arg1, 0), CS(arg2, 0), rpar);
00448 } else {
00449 s = subst("$0$1 $2 $3$4", lpar, CS(arg1, thisPriority), op, CS(arg2, thisPriority), rpar);
00450 }
00451
00452 if (opcode == kMul) {
00453 gDocNoticeFlagMap["cdot"] = true;
00454 }
00455
00456 return generateCacheCode(sig, s);
00457 }
00458
00459
00460
00461
00462
00463
00464 string DocCompiler::generateFFun(Tree sig, Tree ff, Tree largs, int priority)
00465 {
00466 string code = ffname(ff);
00467 code += '(';
00468 string sep = "";
00469 for (int i = 0; i< ffarity(ff); i++) {
00470 code += sep;
00471 code += CS(nth(largs, i), priority);
00472 sep = ", ";
00473 }
00474 code += ')';
00475
00476 gDocNoticeFlagMap["foreignfun"] = true;
00477
00478 return "\\mathrm{ff"+code+"}";
00479 }
00480
00481
00482
00483
00484
00485
00486 void DocCompiler::getTypedNames(Type t, const string& prefix, string& ctype, string& vname)
00487 {
00488 if (t->nature() == kInt) {
00489 ctype = "int"; vname = subst("$0", getFreshID(prefix));
00490 } else {
00491 ctype = ifloat(); vname = subst("$0", getFreshID(prefix));
00492 }
00493 }
00494
00495
00502 static bool isVerySimpleFormula(Tree sig)
00503 {
00504 int i;
00505 double r;
00506 Tree type, name, file, label, c, x, y, z;
00507
00508 return isSigInt(sig, &i)
00509 || isSigReal(sig, &r)
00510 || isSigInput(sig, &i)
00511 || isSigFConst(sig, type, name, file)
00512 || isSigButton(sig, label)
00513 || isSigCheckbox(sig, label)
00514 || isSigVSlider(sig, label,c,x,y,z)
00515 || isSigHSlider(sig, label,c,x,y,z)
00516 || isSigNumEntry(sig, label,c,x,y,z)
00517 ;
00518 }
00519
00520
00521 string DocCompiler::generateCacheCode(Tree sig, const string& exp)
00522 {
00523
00524
00525 string vname, ctype, code, vectorname;
00526
00527 int sharing = getSharingCount(sig);
00528 Occurences* o = fOccMarkup.retrieve(sig);
00529
00530
00531 if (getCompiledExpression(sig, code)) {
00532
00533 return code;
00534 }
00535
00536
00537 if (o->getMaxDelay()>0) {
00538 if (getVectorNameProperty(sig, vectorname)) {
00539 return exp;
00540 }
00541 getTypedNames(getSigType(sig), "r", ctype, vname);
00542 gDocNoticeFlagMap["recursigs"] = true;
00543
00544 if (sharing>1) {
00545
00546 return generateDelayVec(sig, generateVariableStore(sig,exp), ctype, vname, o->getMaxDelay());
00547 } else {
00548
00549 return generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay());
00550 }
00551 }
00552 else if (sharing == 1 || getVectorNameProperty(sig, vectorname) || isVerySimpleFormula(sig)) {
00553
00554 return exp;
00555 }
00556 else if (sharing > 1) {
00557
00558 return generateVariableStore(sig, exp);
00559 }
00560 else {
00561 cerr << "Error in sharing count (" << sharing << ") for " << *sig << endl;
00562 exit(1);
00563 }
00564
00565 return "Error in generateCacheCode";
00566 }
00567
00568
00569 string DocCompiler::generateVariableStore(Tree sig, const string& exp)
00570 {
00571 string vname, ctype;
00572 Type t = getSigType(sig);
00573
00574 switch (t->variability()) {
00575
00576 case kKonst :
00577 getTypedNames(t, "k", ctype, vname);
00578 fLateq->addConstSigFormula(subst("$0 = $1", vname, exp));
00579 gDocNoticeFlagMap["constsigs"] = true;
00580 return vname;
00581
00582 case kBlock :
00583 getTypedNames(t, "p", ctype, vname);
00584 fLateq->addParamSigFormula(subst("$0(t) = $1", vname, exp));
00585 gDocNoticeFlagMap["paramsigs"] = true;
00586 setVectorNameProperty(sig, vname);
00587 return subst("$0(t)", vname);
00588
00589 case kSamp :
00590 if(getVectorNameProperty(sig, vname)) {
00591 return subst("$0(t)", vname);
00592 } else {
00593 getTypedNames(t, "s", ctype, vname);
00594
00595 fLateq->addStoreSigFormula(subst("$0(t) = $1", vname, exp));
00596 gDocNoticeFlagMap["storedsigs"] = true;
00597 setVectorNameProperty(sig, vname);
00598 return subst("$0(t)", vname);
00599 }
00600
00601 default:
00602 assert(0);
00603 return "";
00604 }
00605 }
00606
00607
00608
00609
00610
00611
00612
00613 string DocCompiler::generateIntCast(Tree sig, Tree x, int priority)
00614 {
00615 gDocNoticeFlagMap["intcast"] = true;
00616
00617 return generateCacheCode(sig, subst("\\mathrm{int}\\left($0\\right)", CS(x, 0)));
00618 }
00619
00620
00628 string DocCompiler::generateFloatCast (Tree sig, Tree x, int priority)
00629 {
00630 return generateCacheCode(sig, subst("$0", CS(x, priority)));
00631 }
00632
00633
00634
00635
00636
00637
00638 string DocCompiler::generateButton(Tree sig, Tree path)
00639 {
00640 string vname = getFreshID("{u_b}");
00641 string varname = vname + "(t)";
00642 fLateq->addUISigFormula(getUIDir(path), prepareBinaryUI(varname, path));
00643 gDocNoticeFlagMap["buttonsigs"] = true;
00644 return generateCacheCode(sig, varname);
00645 }
00646
00647 string DocCompiler::generateCheckbox(Tree sig, Tree path)
00648 {
00649 string vname = getFreshID("{u_c}");
00650 string varname = vname + "(t)";
00651 fLateq->addUISigFormula(getUIDir(path), prepareBinaryUI(varname, path));
00652 gDocNoticeFlagMap["checkboxsigs"] = true;
00653 return generateCacheCode(sig, varname);
00654 }
00655
00656 string DocCompiler::generateVSlider(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step)
00657 {
00658 string varname = getFreshID("{u_s}") + "(t)";
00659 fLateq->addUISigFormula(getUIDir(path), prepareIntervallicUI(varname, path, cur, min, max));
00660 gDocNoticeFlagMap["slidersigs"] = true;
00661 return generateCacheCode(sig, varname);
00662 }
00663
00664 string DocCompiler::generateHSlider(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step)
00665 {
00666 string varname = getFreshID("{u_s}") + "(t)";
00667 fLateq->addUISigFormula(getUIDir(path), prepareIntervallicUI(varname, path, cur, min, max));
00668 gDocNoticeFlagMap["slidersigs"] = true;
00669 return generateCacheCode(sig, varname);
00670 }
00671
00672 string DocCompiler::generateNumEntry(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step)
00673 {
00674 string varname = getFreshID("{u_n}") + "(t)";
00675 fLateq->addUISigFormula(getUIDir(path), prepareIntervallicUI(varname, path, cur, min, max));
00676 gDocNoticeFlagMap["nentrysigs"] = true;
00677 return generateCacheCode(sig, varname);
00678 }
00679
00680
00681 string DocCompiler::generateVBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp)
00682 {
00683 string varname = getFreshID("{u_g}");
00684
00685 Type t = getSigType(sig);
00686 switch (t->variability()) {
00687
00688 case kKonst :
00689 break;
00690
00691 case kBlock :
00692 break;
00693
00694 case kSamp :
00695 break;
00696 }
00697 return generateCacheCode(sig, varname);
00698 }
00699
00700
00701 string DocCompiler::generateHBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp)
00702 {
00703 string varname = getFreshID("{u_g}");
00704
00705 Type t = getSigType(sig);
00706 switch (t->variability()) {
00707
00708 case kKonst :
00709 break;
00710
00711 case kBlock :
00712 break;
00713
00714 case kSamp :
00715 break;
00716 }
00717 return generateCacheCode(sig, varname);
00718 }
00719
00720
00721 string DocCompiler::generateAttach (Tree sig, Tree x, Tree y, int priority)
00722 {
00723 string vname;
00724 string exp;
00725
00726 CS(y, priority);
00727 exp = CS(x, priority);
00728
00729 if(getVectorNameProperty(x, vname)) {
00730 setVectorNameProperty(sig, vname);
00731 }
00732
00733 return generateCacheCode(sig, exp);
00734 }
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00749 string DocCompiler::generateDocConstantTbl (Tree , Tree size, Tree isig)
00750 {
00751 string vname, ctype;
00752 string init = CS(isig,0);
00753
00754 int n;
00755 if (!isSigInt(size, &n)) {
00756 cerr << "error in DocCompiler::generateDocConstantTbl() : "
00757 << *size
00758 << " is not an integer expression and can't be used as a table size' "
00759 << endl;
00760 }
00761
00762
00763 getTypedNames(getSigType(isig), "v", ctype, vname);
00764
00765
00766 gDocNoticeFlagMap["tablesigs"] = true;
00767
00768
00769 fLateq->addRDTblSigFormula(subst("$0[t] = $1 \\condition{when $$t \\in [0,$2]$$} ", vname, init, T(n-1)));
00770
00771
00772 return vname;
00773 }
00774
00775
00779 static bool isSeparator(char c)
00780 {
00781 bool w = ( ((c >= 'a') && (c <='z'))
00782 || ((c >= 'A') && (c <='Z'))
00783 || ((c >= '0') && (c <='9'))
00784 );
00785
00786 return ! w;
00787 }
00788
00789
00793 static string replaceTimeBy(const string& src, char r)
00794 {
00795 string dst;
00796 char pre = 0;
00797 for (size_t i=0; i < src.size(); i++)
00798 {
00799 char x = src[i];
00800 if ((x=='t') && isSeparator(pre) && ((i == src.size()-1) || isSeparator(src[i+1]))) {
00801 dst.push_back(r);
00802 } else {
00803 dst.push_back(x);
00804 }
00805 pre = x;
00806 }
00807 return dst;
00808 }
00809
00814 string DocCompiler::generateDocWriteTbl (Tree , Tree size, Tree isig, Tree widx, Tree wsig)
00815 {
00816 string vname, ctype;
00817 string init = CS(isig,0);
00818 int n;
00819 if (!isSigInt(size, &n)) {
00820 cerr << "error in DocCompiler::generateDocWriteTbl() : "
00821 << *size
00822 << " is not an integer expression and can't be used as a table size' "
00823 << endl;
00824 }
00825
00826
00827
00828 getTypedNames(getSigType(isig), "w", ctype, vname);
00829
00830
00831 gDocNoticeFlagMap["tablesigs"] = true;
00832
00833
00834 string ltqRWTableDef;
00835 ltqRWTableDef += subst("$0(t)[i] = \n", vname);
00836 ltqRWTableDef += "\\left\\{\\begin{array}{ll}\n";
00837 ltqRWTableDef += subst("$0 & \\mbox{if \\,} t < 0 \\mbox{\\, and \\,} i \\in [0,$1] \\\\\n", replaceTimeBy(init,'i'), T(n-1));
00838 ltqRWTableDef += subst("$0 & \\mbox{if \\,} i = $1 \\\\\n", CS(wsig,0), CS(widx,0));
00839 ltqRWTableDef += subst("$0(t\\!-\\!1)[i] & \\mbox{otherwise} \\\\\n", vname);
00840 ltqRWTableDef += "\\end{array}\\right.";
00841
00842
00843 fLateq->addRWTblSigFormula(ltqRWTableDef);
00844
00845
00846 return vname;
00847 }
00848
00849
00854 string DocCompiler::generateDocAccessTbl (Tree sig, Tree tbl, Tree ridx)
00855 {
00856
00857 string vname = CS(tbl, 0);
00858 string result = subst("$0[$1]", vname, CS(ridx,0) );
00859
00860 return generateCacheCode(sig, result);
00861 }
00862
00863 bool DocCompiler::isShortEnough(string& s, unsigned int max)
00864 {
00865 return (s.length() <= max);
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00878 string DocCompiler::generateRecProj(Tree sig, Tree r, int i, int priority)
00879 {
00880 string vname;
00881 Tree var, le;
00882
00883
00884
00885 if ( ! getVectorNameProperty(sig, vname)) {
00886 assert(isRec(r, var, le));
00887
00888
00889 generateRec(r, var, le, priority);
00890 assert(getVectorNameProperty(sig, vname));
00891
00892 } else {
00893
00894 }
00895 return subst("$0(t)", vname);
00896 }
00897
00898
00902 void DocCompiler::generateRec(Tree sig, Tree var, Tree le, int priority)
00903 {
00904 int N = len(le);
00905
00906 vector<bool> used(N);
00907 vector<int> delay(N);
00908 vector<string> vname(N);
00909 vector<string> ctype(N);
00910
00911
00912 for (int i=0; i<N; i++) {
00913 Tree e = sigProj(i,sig);
00914 if (fOccMarkup.retrieve(e)) {
00915
00916 used[i] = true;
00917
00918 getTypedNames(getSigType(e), "r", ctype[i], vname[i]);
00919 gDocNoticeFlagMap["recursigs"] = true;
00920
00921 setVectorNameProperty(e, vname[i]);
00922 delay[i] = fOccMarkup.retrieve(e)->getMaxDelay();
00923 } else {
00924
00925
00926 used[i] = false;
00927
00928 }
00929 }
00930
00931
00932 for (int i=0; i<N; i++) {
00933 if (used[i]) {
00934 generateDelayLine(ctype[i], vname[i], delay[i], CS(nth(le,i), priority));
00935 }
00936 }
00937 }
00938
00939
00940
00941
00942
00943
00954 string DocCompiler::generatePrefix (Tree sig, Tree x, Tree e, int priority)
00955 {
00956 string var = getFreshID("m");
00957 string exp0 = CS(x, priority);
00958 string exp1 = CS(e, priority);
00959 string vecname;
00960
00961 if (! getVectorNameProperty(e, vecname)) {
00962 cerr << "No vector name for : " << ppsig(e) << endl;
00963 assert(0);
00964 }
00965
00966 string ltqPrefixDef;
00967 ltqPrefixDef += subst("$0(t) = \n", var);
00968 ltqPrefixDef += "\\left\\{\\begin{array}{ll}\n";
00969 ltqPrefixDef += subst("$0 & \\mbox{, when \\,} t = 0\\\\\n", exp0);
00970 ltqPrefixDef += subst("$0 & \\mbox{, when \\,} t > 0\n", subst("$0(t\\!-\\!1)", vecname));
00971 ltqPrefixDef += "\\end{array}\\right.";
00972
00973 fLateq->addPrefixSigFormula(ltqPrefixDef);
00974 gDocNoticeFlagMap["prefixsigs"] = true;
00975
00976 return generateCacheCode(sig, subst("$0(t)", var));
00977 }
00978
00979
00980
00981
00982
00983
00987 string DocCompiler::generateIota (Tree sig, Tree n)
00988 {
00989 int size;
00990 if (!isSigInt(n, &size)) { fprintf(stderr, "error in generateIota\n"); exit(1); }
00991
00992 return subst(" t \\bmod{$0} ", docT(size));
00993 }
00994
00995
00996
00997
00998
00999
01003 string DocCompiler::generateSelect2 (Tree sig, Tree sel, Tree s1, Tree s2, int priority)
01004 {
01005 string var = getFreshID("q");
01006 string expsel = CS(sel, 0);
01007 string exps1 = CS(s1, 0);
01008 string exps2 = CS(s2, 0);
01009
01010 string ltqSelDef;
01011 ltqSelDef += subst("$0(t) = \n", var);
01012 ltqSelDef += "\\left\\{\\begin{array}{ll}\n";
01013 ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 0\\\\\n", exps1, expsel);
01014 ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 1\n", exps2, expsel);
01015 ltqSelDef += "\\end{array}\\right.";
01016
01017 fLateq->addSelectSigFormula(ltqSelDef);
01018 gDocNoticeFlagMap["selectionsigs"] = true;
01019
01020
01021 setVectorNameProperty(sig, var);
01022 return subst("$0(t)", var);
01023 }
01024
01025
01029 string DocCompiler::generateSelect3 (Tree sig, Tree sel, Tree s1, Tree s2, Tree s3, int priority)
01030 {
01031 string var = getFreshID("q");
01032 string expsel = CS(sel, 0);
01033 string exps1 = CS(s1, 0);
01034 string exps2 = CS(s2, 0);
01035 string exps3 = CS(s3, 0);
01036
01037 string ltqSelDef;
01038 ltqSelDef += subst("$0(t) = \n", var);
01039 ltqSelDef += "\\left\\{\\begin{array}{ll}\n";
01040 ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 0\\\\\n", generateVariableStore(s1, exps1), expsel);
01041 ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 1\\\\\n", generateVariableStore(s2, exps2), expsel);
01042 ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 2\n", generateVariableStore(s3, exps3), expsel);
01043 ltqSelDef += "\\end{array}\\right.";
01044
01045 fLateq->addSelectSigFormula(ltqSelDef);
01046 gDocNoticeFlagMap["selectionsigs"] = true;
01047
01048
01049 setVectorNameProperty(sig, var);
01050 return subst("$0(t)", var);
01051 }
01052
01053
01058 string DocCompiler::generateXtended (Tree sig, int priority)
01059 {
01060 xtended* p = (xtended*) getUserData(sig);
01061 vector<string> args;
01062 vector<Type> types;
01063
01064 for (int i=0; i<sig->arity(); i++) {
01065 args.push_back(CS(sig->branch(i), 0));
01066 types.push_back(getSigType(sig->branch(i)));
01067 }
01068
01069 if (p->needCache()) {
01070
01071 return generateCacheCode(sig, p->generateLateq(fLateq, args, types));
01072 } else {
01073
01074 return p->generateLateq(fLateq, args, types);
01075 }
01076 }
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01094 void DocCompiler::setVectorNameProperty(Tree sig, const string& vecname)
01095 {
01096 fVectorProperty.set(sig, vecname);
01097 }
01098
01099
01108 bool DocCompiler::getVectorNameProperty(Tree sig, string& vecname)
01109 {
01110 return fVectorProperty.get(sig, vecname);
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01143 string DocCompiler::generateFixDelay (Tree sig, Tree exp, Tree delay, int priority)
01144 {
01145 int d;
01146 string vecname;
01147
01148 CS(exp, 0);
01149
01150 if (! getVectorNameProperty(exp, vecname)) {
01151 cerr << "No vector name for : " << ppsig(exp) << endl;
01152 assert(0);
01153 }
01154
01155 if (isSigInt(delay, &d) && (d == 0)) {
01156
01157 return subst("$0(t)", vecname);
01158 } else {
01159
01160 return subst("$0(t\\!-\\!$1)", vecname, CS(delay, 7));
01161 }
01162 }
01163
01164
01169 string DocCompiler::generateDelayVec(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd)
01170 {
01171 string s = generateDelayVecNoTemp(sig, exp, ctype, vname, mxd);
01172 if (getSigType(sig)->variability() < kSamp) {
01173 return exp;
01174 } else {
01175 return s;
01176 }
01177 }
01178
01179
01183 string DocCompiler::generateDelayVecNoTemp(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd)
01184 {
01185 assert(mxd > 0);
01186
01187
01188
01189 string vectorname;
01190
01191
01192 if(getVectorNameProperty(sig, vectorname)) {
01193 return subst("$0(t)", vectorname);
01194 } else {
01195 fLateq->addRecurSigFormula(subst("$0(t) = $1", vname, exp));
01196 setVectorNameProperty(sig, vname);
01197 return subst("$0(t)", vname);
01198 }
01199 }
01200
01201
01205 void DocCompiler::generateDelayLine(const string& ctype, const string& vname, int mxd, const string& exp)
01206 {
01207
01208 if (mxd == 0) {
01209 fLateq->addRecurSigFormula(subst("$0(t) = $1", vname, exp));
01210 } else {
01211 fLateq->addRecurSigFormula(subst("$0(t) = $1", vname, exp));
01212 }
01213 }
01214
01215
01216
01217
01218
01219
01220
01221
01222
01235 string DocCompiler::getUIDir(Tree pathname)
01236 {
01237
01238 string s;
01239 Tree dir = reverse(tl(pathname));
01240 while (!isNil(dir)) {
01241 string tmp = tree2str(tl(hd(dir)));
01242 if ( (tmp[0] != '[') && (!tmp.empty()) ) {
01243 s += tmp + '/';
01244 }
01245 dir = tl(dir);
01246 }
01247 return s;
01248 }
01249
01250
01263 string DocCompiler::prepareBinaryUI(const string& name, Tree path)
01264 {
01265 string label, unit;
01266 getUIDocInfos(path, label, unit);
01267 string s = "";
01268 label = (label.size()>0) ? ("\\textsf{\""+label+"\"} :") : "";
01269 unit = (unit.size()>0) ? ("\\,\\mathrm{"+unit+"}") : "";
01270 s += label;
01271 s += " & $" + name + "$";
01272 s += " & $\\in$ & $\\left\\{\\,0" + unit + ", 1" + unit +"\\,\\right\\}$";
01273 s += " & $(\\mbox{" + gDocMathStringMap["defaultvalue"] + "} = 0" + unit + ")$\\\\";
01274 return s;
01275 }
01276
01277
01293 string DocCompiler::prepareIntervallicUI(const string& name, Tree path, Tree tcur, Tree tmin, Tree tmax)
01294 {
01295 string label, unit, cur, min, max;
01296 getUIDocInfos(path, label, unit);
01297 cur = docT(tree2float(tcur));
01298 min = docT(tree2float(tmin));
01299 max = docT(tree2float(tmax));
01300
01301 string s = "";
01302 label = (label.size()>0) ? ("\\textsf{\""+label+"\"} :") : "";
01303 unit = (unit.size()>0) ? ("\\,\\mathrm{"+unit+"}") : "";
01304 s += label;
01305 s += " & $" + name + "$";
01306 s += " & $\\in$ & $\\left[\\," + min + unit + ", " + max + unit +"\\,\\right]$";
01307 s += " & $(\\mbox{" + gDocMathStringMap["defaultvalue"] + "} = " + cur + unit + ")$\\\\";
01308 return s;
01309 }
01310
01311
01319 void DocCompiler::getUIDocInfos(Tree path, string& label, string& unit)
01320 {
01321 label = "";
01322 unit = "";
01323
01324 map<string, set<string> > metadata;
01325 extractMetadata(tree2str(hd(path)), label, metadata);
01326
01327 set<string> myunits = metadata["unit"];
01328
01329
01330
01331 for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) {
01332 const string& key = i->first;
01333 const set<string>& values = i->second;
01334 for (set<string>::iterator j = values.begin(); j != values.end(); j++) {
01335 if(key == "unit") unit += *j;
01336 }
01337 }
01338 }
01339
01340
01344 static void extractMetadata(const string& fulllabel, string& label, map<string, set<string> >& metadata)
01345 {
01346 enum {kLabel, kEscape1, kEscape2, kEscape3, kKey, kValue};
01347 int state = kLabel; int deep = 0;
01348 string key, value;
01349
01350 for (unsigned int i=0; i < fulllabel.size(); i++) {
01351 char c = fulllabel[i];
01352 switch (state) {
01353 case kLabel :
01354 assert (deep == 0);
01355 switch (c) {
01356 case '\\' : state = kEscape1; break;
01357 case '[' : state = kKey; deep++; break;
01358 default : label += c;
01359 }
01360 break;
01361
01362 case kEscape1 :
01363 label += c;
01364 state = kLabel;
01365 break;
01366
01367 case kEscape2 :
01368 key += c;
01369 state = kKey;
01370 break;
01371
01372 case kEscape3 :
01373 value += c;
01374 state = kValue;
01375 break;
01376
01377 case kKey :
01378 assert (deep > 0);
01379 switch (c) {
01380 case '\\' : state = kEscape2;
01381 break;
01382
01383 case '[' : deep++;
01384 key += c;
01385 break;
01386
01387 case ':' : if (deep == 1) {
01388 state = kValue;
01389 } else {
01390 key += c;
01391 }
01392 break;
01393 case ']' : deep--;
01394 if (deep < 1) {
01395 metadata[rmWhiteSpaces(key)].insert("");
01396 state = kLabel;
01397 key="";
01398 value="";
01399 } else {
01400 key += c;
01401 }
01402 break;
01403 default : key += c;
01404 }
01405 break;
01406
01407 case kValue :
01408 assert (deep > 0);
01409 switch (c) {
01410 case '\\' : state = kEscape3;
01411 break;
01412
01413 case '[' : deep++;
01414 value += c;
01415 break;
01416
01417 case ']' : deep--;
01418 if (deep < 1) {
01419 metadata[rmWhiteSpaces(key)].insert(rmWhiteSpaces(value));
01420 state = kLabel;
01421 key="";
01422 value="";
01423 } else {
01424 value += c;
01425 }
01426 break;
01427 default : value += c;
01428 }
01429 break;
01430
01431 default :
01432 cerr << "ERROR unrecognized state (in extractMetadata) : " << state << endl;
01433 }
01434 }
01435 label = rmWhiteSpaces(label);
01436 }
01437
01438
01443 static string rmWhiteSpaces(const string& s)
01444 {
01445 size_t i = s.find_first_not_of(" \t");
01446 size_t j = s.find_last_not_of(" \t");
01447
01448 if ( (i != string::npos) & (j != string::npos) ) {
01449 return s.substr(i, 1+j-i);
01450 } else {
01451 return "";
01452 }
01453 }
01454
01455