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
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 gDocNoticeFlagMap["intcast"] = true;
00439 break;
00440 default:
00441 op = gBinOpLateqTable[opcode]->fName;
00442 break;
00443 }
00444 }
00445
00446
00447 if ( (opcode == kDiv) && (!intOpDetected) ) {
00448 s = subst("$0\\frac{$1}{$2}$3", lpar, CS(arg1, 0), CS(arg2, 0), rpar);
00449 } else {
00450 s = subst("$0$1 $2 $3$4", lpar, CS(arg1, thisPriority), op, CS(arg2, thisPriority), rpar);
00451 }
00452
00453
00454
00455
00456
00457 return generateCacheCode(sig, s);
00458 }
00459
00460
00461
00462
00463
00464
00465 string DocCompiler::generateFFun(Tree sig, Tree ff, Tree largs, int priority)
00466 {
00467 string code = ffname(ff);
00468 code += '(';
00469 string sep = "";
00470 for (int i = 0; i< ffarity(ff); i++) {
00471 code += sep;
00472 code += CS(nth(largs, i), priority);
00473 sep = ", ";
00474 }
00475 code += ')';
00476
00477 gDocNoticeFlagMap["foreignfun"] = true;
00478
00479 return "\\mathrm{ff"+code+"}";
00480 }
00481
00482
00483
00484
00485
00486
00487 void DocCompiler::getTypedNames(Type t, const string& prefix, string& ctype, string& vname)
00488 {
00489 if (t->nature() == kInt) {
00490 ctype = "int"; vname = subst("$0", getFreshID(prefix));
00491 } else {
00492 ctype = ifloat(); vname = subst("$0", getFreshID(prefix));
00493 }
00494 }
00495
00496
00503 static bool isVerySimpleFormula(Tree sig)
00504 {
00505 int i;
00506 double r;
00507 Tree type, name, file, label, c, x, y, z;
00508
00509 return isSigInt(sig, &i)
00510 || isSigReal(sig, &r)
00511 || isSigInput(sig, &i)
00512 || isSigFConst(sig, type, name, file)
00513 || isSigButton(sig, label)
00514 || isSigCheckbox(sig, label)
00515 || isSigVSlider(sig, label,c,x,y,z)
00516 || isSigHSlider(sig, label,c,x,y,z)
00517 || isSigNumEntry(sig, label,c,x,y,z)
00518 ;
00519 }
00520
00521
00522 string DocCompiler::generateCacheCode(Tree sig, const string& exp)
00523 {
00524
00525
00526 string vname, ctype, code, vectorname;
00527
00528 int sharing = getSharingCount(sig);
00529 Occurences* o = fOccMarkup.retrieve(sig);
00530
00531
00532 if (getCompiledExpression(sig, code)) {
00533
00534 return code;
00535 }
00536
00537
00538 if (o->getMaxDelay()>0) {
00539 if (getVectorNameProperty(sig, vectorname)) {
00540 return exp;
00541 }
00542 getTypedNames(getSigType(sig), "r", ctype, vname);
00543 gDocNoticeFlagMap["recursigs"] = true;
00544
00545 if (sharing>1) {
00546
00547 return generateDelayVec(sig, generateVariableStore(sig,exp), ctype, vname, o->getMaxDelay());
00548 } else {
00549
00550 return generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay());
00551 }
00552 }
00553 else if (sharing == 1 || getVectorNameProperty(sig, vectorname) || isVerySimpleFormula(sig)) {
00554
00555 return exp;
00556 }
00557 else if (sharing > 1) {
00558
00559 return generateVariableStore(sig, exp);
00560 }
00561 else {
00562 cerr << "Error in sharing count (" << sharing << ") for " << *sig << endl;
00563 exit(1);
00564 }
00565
00566 return "Error in generateCacheCode";
00567 }
00568
00569
00570 string DocCompiler::generateVariableStore(Tree sig, const string& exp)
00571 {
00572 string vname, ctype;
00573 Type t = getSigType(sig);
00574
00575 switch (t->variability()) {
00576
00577 case kKonst :
00578 getTypedNames(t, "k", ctype, vname);
00579 fLateq->addConstSigFormula(subst("$0 = $1", vname, exp));
00580 gDocNoticeFlagMap["constsigs"] = true;
00581 return vname;
00582
00583 case kBlock :
00584 getTypedNames(t, "p", ctype, vname);
00585 fLateq->addParamSigFormula(subst("$0(t) = $1", vname, exp));
00586 gDocNoticeFlagMap["paramsigs"] = true;
00587 setVectorNameProperty(sig, vname);
00588 return subst("$0(t)", vname);
00589
00590 case kSamp :
00591 if(getVectorNameProperty(sig, vname)) {
00592 return subst("$0(t)", vname);
00593 } else {
00594 getTypedNames(t, "s", ctype, vname);
00595
00596 fLateq->addStoreSigFormula(subst("$0(t) = $1", vname, exp));
00597 gDocNoticeFlagMap["storedsigs"] = true;
00598 setVectorNameProperty(sig, vname);
00599 return subst("$0(t)", vname);
00600 }
00601
00602 default:
00603 assert(0);
00604 return "";
00605 }
00606 }
00607
00608
00609
00610
00611
00612
00613
00614 string DocCompiler::generateIntCast(Tree sig, Tree x, int priority)
00615 {
00616 gDocNoticeFlagMap["intcast"] = true;
00617
00618 return generateCacheCode(sig, subst("\\mathrm{int}\\left($0\\right)", CS(x, 0)));
00619 }
00620
00621
00629 string DocCompiler::generateFloatCast (Tree sig, Tree x, int priority)
00630 {
00631 return generateCacheCode(sig, subst("$0", CS(x, priority)));
00632 }
00633
00634
00635
00636
00637
00638
00639 string DocCompiler::generateButton(Tree sig, Tree path)
00640 {
00641 string vname = getFreshID("{u_b}");
00642 string varname = vname + "(t)";
00643 fLateq->addUISigFormula(getUIDir(path), prepareBinaryUI(varname, path));
00644 gDocNoticeFlagMap["buttonsigs"] = true;
00645 return generateCacheCode(sig, varname);
00646 }
00647
00648 string DocCompiler::generateCheckbox(Tree sig, Tree path)
00649 {
00650 string vname = getFreshID("{u_c}");
00651 string varname = vname + "(t)";
00652 fLateq->addUISigFormula(getUIDir(path), prepareBinaryUI(varname, path));
00653 gDocNoticeFlagMap["checkboxsigs"] = true;
00654 return generateCacheCode(sig, varname);
00655 }
00656
00657 string DocCompiler::generateVSlider(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step)
00658 {
00659 string varname = getFreshID("{u_s}") + "(t)";
00660 fLateq->addUISigFormula(getUIDir(path), prepareIntervallicUI(varname, path, cur, min, max));
00661 gDocNoticeFlagMap["slidersigs"] = true;
00662 return generateCacheCode(sig, varname);
00663 }
00664
00665 string DocCompiler::generateHSlider(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step)
00666 {
00667 string varname = getFreshID("{u_s}") + "(t)";
00668 fLateq->addUISigFormula(getUIDir(path), prepareIntervallicUI(varname, path, cur, min, max));
00669 gDocNoticeFlagMap["slidersigs"] = true;
00670 return generateCacheCode(sig, varname);
00671 }
00672
00673 string DocCompiler::generateNumEntry(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step)
00674 {
00675 string varname = getFreshID("{u_n}") + "(t)";
00676 fLateq->addUISigFormula(getUIDir(path), prepareIntervallicUI(varname, path, cur, min, max));
00677 gDocNoticeFlagMap["nentrysigs"] = true;
00678 return generateCacheCode(sig, varname);
00679 }
00680
00681
00682 string DocCompiler::generateVBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp)
00683 {
00684 string varname = getFreshID("{u_g}");
00685
00686 Type t = getSigType(sig);
00687 switch (t->variability()) {
00688
00689 case kKonst :
00690 break;
00691
00692 case kBlock :
00693 break;
00694
00695 case kSamp :
00696 break;
00697 }
00698 return generateCacheCode(sig, varname);
00699 }
00700
00701
00702 string DocCompiler::generateHBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp)
00703 {
00704 string varname = getFreshID("{u_g}");
00705
00706 Type t = getSigType(sig);
00707 switch (t->variability()) {
00708
00709 case kKonst :
00710 break;
00711
00712 case kBlock :
00713 break;
00714
00715 case kSamp :
00716 break;
00717 }
00718 return generateCacheCode(sig, varname);
00719 }
00720
00721
00722 string DocCompiler::generateAttach (Tree sig, Tree x, Tree y, int priority)
00723 {
00724 string vname;
00725 string exp;
00726
00727 CS(y, priority);
00728 exp = CS(x, priority);
00729
00730 if(getVectorNameProperty(x, vname)) {
00731 setVectorNameProperty(sig, vname);
00732 }
00733
00734 return generateCacheCode(sig, exp);
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00750 string DocCompiler::generateDocConstantTbl (Tree , Tree size, Tree isig)
00751 {
00752 string vname, ctype;
00753 string init = CS(isig,0);
00754
00755 int n;
00756 if (!isSigInt(size, &n)) {
00757 cerr << "error in DocCompiler::generateDocConstantTbl() : "
00758 << *size
00759 << " is not an integer expression and can't be used as a table size' "
00760 << endl;
00761 }
00762
00763
00764 getTypedNames(getSigType(isig), "v", ctype, vname);
00765
00766
00767 gDocNoticeFlagMap["tablesigs"] = true;
00768
00769
00770 fLateq->addRDTblSigFormula(subst("$0[t] = $1 \\condition{when $$t \\in [0,$2]$$} ", vname, init, T(n-1)));
00771
00772
00773 return vname;
00774 }
00775
00776
00780 static bool isSeparator(char c)
00781 {
00782 bool w = ( ((c >= 'a') && (c <='z'))
00783 || ((c >= 'A') && (c <='Z'))
00784 || ((c >= '0') && (c <='9'))
00785 );
00786
00787 return ! w;
00788 }
00789
00790
00794 static string replaceTimeBy(const string& src, char r)
00795 {
00796 string dst;
00797 char pre = 0;
00798 for (size_t i=0; i < src.size(); i++)
00799 {
00800 char x = src[i];
00801 if ((x=='t') && isSeparator(pre) && ((i == src.size()-1) || isSeparator(src[i+1]))) {
00802 dst.push_back(r);
00803 } else {
00804 dst.push_back(x);
00805 }
00806 pre = x;
00807 }
00808 return dst;
00809 }
00810
00815 string DocCompiler::generateDocWriteTbl (Tree , Tree size, Tree isig, Tree widx, Tree wsig)
00816 {
00817 string vname, ctype;
00818 string init = CS(isig,0);
00819 int n;
00820 if (!isSigInt(size, &n)) {
00821 cerr << "error in DocCompiler::generateDocWriteTbl() : "
00822 << *size
00823 << " is not an integer expression and can't be used as a table size' "
00824 << endl;
00825 }
00826
00827
00828
00829 getTypedNames(getSigType(isig), "w", ctype, vname);
00830
00831
00832 gDocNoticeFlagMap["tablesigs"] = true;
00833
00834
00835 string ltqRWTableDef;
00836 ltqRWTableDef += subst("$0(t)[i] = \n", vname);
00837 ltqRWTableDef += "\\left\\{\\begin{array}{ll}\n";
00838 ltqRWTableDef += subst("$0 & \\mbox{if \\,} t < 0 \\mbox{\\, and \\,} i \\in [0,$1] \\\\\n", replaceTimeBy(init,'i'), T(n-1));
00839 ltqRWTableDef += subst("$0 & \\mbox{if \\,} i = $1 \\\\\n", CS(wsig,0), CS(widx,0));
00840 ltqRWTableDef += subst("$0(t\\!-\\!1)[i] & \\mbox{otherwise} \\\\\n", vname);
00841 ltqRWTableDef += "\\end{array}\\right.";
00842
00843
00844 fLateq->addRWTblSigFormula(ltqRWTableDef);
00845
00846
00847 return vname;
00848 }
00849
00850
00855 string DocCompiler::generateDocAccessTbl (Tree sig, Tree tbl, Tree ridx)
00856 {
00857
00858 string vname = CS(tbl, 0);
00859 string result = subst("$0[$1]", vname, CS(ridx,0) );
00860
00861 return generateCacheCode(sig, result);
00862 }
00863
00864 bool DocCompiler::isShortEnough(string& s, unsigned int max)
00865 {
00866 return (s.length() <= max);
00867 }
00868
00869
00870
00871
00872
00873
00874
00875
00879 string DocCompiler::generateRecProj(Tree sig, Tree r, int i, int priority)
00880 {
00881 string vname;
00882 Tree var, le;
00883
00884
00885
00886 if ( ! getVectorNameProperty(sig, vname)) {
00887 assert(isRec(r, var, le));
00888
00889
00890 generateRec(r, var, le, priority);
00891 assert(getVectorNameProperty(sig, vname));
00892
00893 } else {
00894
00895 }
00896 return subst("$0(t)", vname);
00897 }
00898
00899
00903 void DocCompiler::generateRec(Tree sig, Tree var, Tree le, int priority)
00904 {
00905 int N = len(le);
00906
00907 vector<bool> used(N);
00908 vector<int> delay(N);
00909 vector<string> vname(N);
00910 vector<string> ctype(N);
00911
00912
00913 for (int i=0; i<N; i++) {
00914 Tree e = sigProj(i,sig);
00915 if (fOccMarkup.retrieve(e)) {
00916
00917 used[i] = true;
00918
00919 getTypedNames(getSigType(e), "r", ctype[i], vname[i]);
00920 gDocNoticeFlagMap["recursigs"] = true;
00921
00922 setVectorNameProperty(e, vname[i]);
00923 delay[i] = fOccMarkup.retrieve(e)->getMaxDelay();
00924 } else {
00925
00926
00927 used[i] = false;
00928
00929 }
00930 }
00931
00932
00933 for (int i=0; i<N; i++) {
00934 if (used[i]) {
00935 generateDelayLine(ctype[i], vname[i], delay[i], CS(nth(le,i), priority));
00936 }
00937 }
00938 }
00939
00940
00941
00942
00943
00944
00955 string DocCompiler::generatePrefix (Tree sig, Tree x, Tree e, int priority)
00956 {
00957 string var = getFreshID("m");
00958 string exp0 = CS(x, priority);
00959 string exp1 = CS(e, priority);
00960 string vecname;
00961
00962 if (! getVectorNameProperty(e, vecname)) {
00963 cerr << "No vector name for : " << ppsig(e) << endl;
00964 assert(0);
00965 }
00966
00967 string ltqPrefixDef;
00968 ltqPrefixDef += subst("$0(t) = \n", var);
00969 ltqPrefixDef += "\\left\\{\\begin{array}{ll}\n";
00970 ltqPrefixDef += subst("$0 & \\mbox{, when \\,} t = 0\\\\\n", exp0);
00971 ltqPrefixDef += subst("$0 & \\mbox{, when \\,} t > 0\n", subst("$0(t\\!-\\!1)", vecname));
00972 ltqPrefixDef += "\\end{array}\\right.";
00973
00974 fLateq->addPrefixSigFormula(ltqPrefixDef);
00975 gDocNoticeFlagMap["prefixsigs"] = true;
00976
00977 return generateCacheCode(sig, subst("$0(t)", var));
00978 }
00979
00980
00981
00982
00983
00984
00988 string DocCompiler::generateIota (Tree sig, Tree n)
00989 {
00990 int size;
00991 if (!isSigInt(n, &size)) { fprintf(stderr, "error in generateIota\n"); exit(1); }
00992
00993 return subst(" t \\bmod{$0} ", docT(size));
00994 }
00995
00996
00997
00998
00999
01000
01004 string DocCompiler::generateSelect2 (Tree sig, Tree sel, Tree s1, Tree s2, int priority)
01005 {
01006 string var = getFreshID("q");
01007 string expsel = CS(sel, 0);
01008 string exps1 = CS(s1, 0);
01009 string exps2 = CS(s2, 0);
01010
01011 string ltqSelDef;
01012 ltqSelDef += subst("$0(t) = \n", var);
01013 ltqSelDef += "\\left\\{\\begin{array}{ll}\n";
01014 ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 0\\\\\n", exps1, expsel);
01015 ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 1\n", exps2, expsel);
01016 ltqSelDef += "\\end{array}\\right.";
01017
01018 fLateq->addSelectSigFormula(ltqSelDef);
01019 gDocNoticeFlagMap["selectionsigs"] = true;
01020
01021
01022 setVectorNameProperty(sig, var);
01023 return subst("$0(t)", var);
01024 }
01025
01026
01030 string DocCompiler::generateSelect3 (Tree sig, Tree sel, Tree s1, Tree s2, Tree s3, int priority)
01031 {
01032 string var = getFreshID("q");
01033 string expsel = CS(sel, 0);
01034 string exps1 = CS(s1, 0);
01035 string exps2 = CS(s2, 0);
01036 string exps3 = CS(s3, 0);
01037
01038 string ltqSelDef;
01039 ltqSelDef += subst("$0(t) = \n", var);
01040 ltqSelDef += "\\left\\{\\begin{array}{ll}\n";
01041 ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 0\\\\\n", generateVariableStore(s1, exps1), expsel);
01042 ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 1\\\\\n", generateVariableStore(s2, exps2), expsel);
01043 ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 2\n", generateVariableStore(s3, exps3), expsel);
01044 ltqSelDef += "\\end{array}\\right.";
01045
01046 fLateq->addSelectSigFormula(ltqSelDef);
01047 gDocNoticeFlagMap["selectionsigs"] = true;
01048
01049
01050 setVectorNameProperty(sig, var);
01051 return subst("$0(t)", var);
01052 }
01053
01054
01059 string DocCompiler::generateXtended (Tree sig, int priority)
01060 {
01061 xtended* p = (xtended*) getUserData(sig);
01062 vector<string> args;
01063 vector<Type> types;
01064
01065 for (int i=0; i<sig->arity(); i++) {
01066 args.push_back(CS(sig->branch(i), 0));
01067 types.push_back(getSigType(sig->branch(i)));
01068 }
01069
01070 if (p->needCache()) {
01071
01072 return generateCacheCode(sig, p->generateLateq(fLateq, args, types));
01073 } else {
01074
01075 return p->generateLateq(fLateq, args, types);
01076 }
01077 }
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01095 void DocCompiler::setVectorNameProperty(Tree sig, const string& vecname)
01096 {
01097 fVectorProperty.set(sig, vecname);
01098 }
01099
01100
01109 bool DocCompiler::getVectorNameProperty(Tree sig, string& vecname)
01110 {
01111 return fVectorProperty.get(sig, vecname);
01112 }
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01144 string DocCompiler::generateFixDelay (Tree sig, Tree exp, Tree delay, int priority)
01145 {
01146 int d;
01147 string vecname;
01148
01149 CS(exp, 0);
01150
01151 if (! getVectorNameProperty(exp, vecname)) {
01152 cerr << "No vector name for : " << ppsig(exp) << endl;
01153 assert(0);
01154 }
01155
01156 if (isSigInt(delay, &d) && (d == 0)) {
01157
01158 return subst("$0(t)", vecname);
01159 } else {
01160
01161 return subst("$0(t\\!-\\!$1)", vecname, CS(delay, 7));
01162 }
01163 }
01164
01165
01170 string DocCompiler::generateDelayVec(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd)
01171 {
01172 string s = generateDelayVecNoTemp(sig, exp, ctype, vname, mxd);
01173 if (getSigType(sig)->variability() < kSamp) {
01174 return exp;
01175 } else {
01176 return s;
01177 }
01178 }
01179
01180
01184 string DocCompiler::generateDelayVecNoTemp(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd)
01185 {
01186 assert(mxd > 0);
01187
01188
01189
01190 string vectorname;
01191
01192
01193 if(getVectorNameProperty(sig, vectorname)) {
01194 return subst("$0(t)", vectorname);
01195 } else {
01196 fLateq->addRecurSigFormula(subst("$0(t) = $1", vname, exp));
01197 setVectorNameProperty(sig, vname);
01198 return subst("$0(t)", vname);
01199 }
01200 }
01201
01202
01206 void DocCompiler::generateDelayLine(const string& ctype, const string& vname, int mxd, const string& exp)
01207 {
01208
01209 if (mxd == 0) {
01210 fLateq->addRecurSigFormula(subst("$0(t) = $1", vname, exp));
01211 } else {
01212 fLateq->addRecurSigFormula(subst("$0(t) = $1", vname, exp));
01213 }
01214 }
01215
01216
01217
01218
01219
01220
01221
01222
01223
01236 string DocCompiler::getUIDir(Tree pathname)
01237 {
01238
01239 string s;
01240 Tree dir = reverse(tl(pathname));
01241 while (!isNil(dir)) {
01242 string tmp = tree2str(tl(hd(dir)));
01243 if ( (tmp[0] != '[') && (!tmp.empty()) ) {
01244 s += tmp + '/';
01245 }
01246 dir = tl(dir);
01247 }
01248 return s;
01249 }
01250
01251
01264 string DocCompiler::prepareBinaryUI(const string& name, Tree path)
01265 {
01266 string label, unit;
01267 getUIDocInfos(path, label, unit);
01268 string s = "";
01269 label = (label.size()>0) ? ("\\textsf{\""+label+"\"} ") : "";
01270 unit = (unit.size()>0) ? ("\\ ("+unit+")") : "";
01271 s += label + unit;
01272 s += " & $" + name + "$";
01273 s += " $\\in$ $\\left\\{\\,0, 1\\,\\right\\}$";
01274 s += " & $(\\mbox{" + gDocMathStringMap["defaultvalue"] + "} = 0)$\\\\";
01275 return s;
01276 }
01277
01278
01294 string DocCompiler::prepareIntervallicUI(const string& name, Tree path, Tree tcur, Tree tmin, Tree tmax)
01295 {
01296 string label, unit, cur, min, max;
01297 getUIDocInfos(path, label, unit);
01298 cur = docT(tree2float(tcur));
01299 min = docT(tree2float(tmin));
01300 max = docT(tree2float(tmax));
01301
01302 string s = "";
01303 label = (label.size()>0) ? ("\\textsf{\""+label+"\"} ") : "";
01304 unit = (unit.size()>0) ? ("\\ ("+unit+")") : "";
01305 s += label + unit;
01306 s += " & $" + name + "$";
01307 s += " $\\in$ $\\left[\\," + min + ", " + max + "\\,\\right]$";
01308 s += " & $(\\mbox{" + gDocMathStringMap["defaultvalue"] + "} = " + cur + ")$\\\\";
01309 return s;
01310 }
01311
01312
01320 void DocCompiler::getUIDocInfos(Tree path, string& label, string& unit)
01321 {
01322 label = "";
01323 unit = "";
01324
01325 map<string, set<string> > metadata;
01326 extractMetadata(tree2str(hd(path)), label, metadata);
01327
01328 set<string> myunits = metadata["unit"];
01329
01330
01331
01332 for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) {
01333 const string& key = i->first;
01334 const set<string>& values = i->second;
01335 for (set<string>::const_iterator j = values.begin(); j != values.end(); j++) {
01336 if(key == "unit") unit += *j;
01337 }
01338 }
01339 }
01340
01341
01345 static void extractMetadata(const string& fulllabel, string& label, map<string, set<string> >& metadata)
01346 {
01347 enum {kLabel, kEscape1, kEscape2, kEscape3, kKey, kValue};
01348 int state = kLabel; int deep = 0;
01349 string key, value;
01350
01351 for (unsigned int i=0; i < fulllabel.size(); i++) {
01352 char c = fulllabel[i];
01353 switch (state) {
01354 case kLabel :
01355 assert (deep == 0);
01356 switch (c) {
01357 case '\\' : state = kEscape1; break;
01358 case '[' : state = kKey; deep++; break;
01359 default : label += c;
01360 }
01361 break;
01362
01363 case kEscape1 :
01364 label += c;
01365 state = kLabel;
01366 break;
01367
01368 case kEscape2 :
01369 key += c;
01370 state = kKey;
01371 break;
01372
01373 case kEscape3 :
01374 value += c;
01375 state = kValue;
01376 break;
01377
01378 case kKey :
01379 assert (deep > 0);
01380 switch (c) {
01381 case '\\' : state = kEscape2;
01382 break;
01383
01384 case '[' : deep++;
01385 key += c;
01386 break;
01387
01388 case ':' : if (deep == 1) {
01389 state = kValue;
01390 } else {
01391 key += c;
01392 }
01393 break;
01394 case ']' : deep--;
01395 if (deep < 1) {
01396 metadata[rmWhiteSpaces(key)].insert("");
01397 state = kLabel;
01398 key="";
01399 value="";
01400 } else {
01401 key += c;
01402 }
01403 break;
01404 default : key += c;
01405 }
01406 break;
01407
01408 case kValue :
01409 assert (deep > 0);
01410 switch (c) {
01411 case '\\' : state = kEscape3;
01412 break;
01413
01414 case '[' : deep++;
01415 value += c;
01416 break;
01417
01418 case ']' : deep--;
01419 if (deep < 1) {
01420 metadata[rmWhiteSpaces(key)].insert(rmWhiteSpaces(value));
01421 state = kLabel;
01422 key="";
01423 value="";
01424 } else {
01425 value += c;
01426 }
01427 break;
01428 default : value += c;
01429 }
01430 break;
01431
01432 default :
01433 cerr << "ERROR unrecognized state (in extractMetadata) : " << state << endl;
01434 }
01435 }
01436 label = rmWhiteSpaces(label);
01437 }
01438
01439
01444 static string rmWhiteSpaces(const string& s)
01445 {
01446 size_t i = s.find_first_not_of(" \t");
01447 size_t j = s.find_last_not_of(" \t");
01448
01449 if ( (i != string::npos) & (j != string::npos) ) {
01450 return s.substr(i, 1+j-i);
01451 } else {
01452 return "";
01453 }
01454 }
01455
01456