X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/blobdiff_plain/1059e1cc0c2ecfa237406949aa26155b6a5b9154..66f23d4fabf89ad09adbd4dfc15ac6b5b2b7da83:/interpretor/preprocessor/faust-0.9.47mr3/compiler/documentator/doc_compile.cpp diff --git a/interpretor/preprocessor/faust-0.9.47mr3/compiler/documentator/doc_compile.cpp b/interpretor/preprocessor/faust-0.9.47mr3/compiler/documentator/doc_compile.cpp deleted file mode 100644 index a713eb7..0000000 --- a/interpretor/preprocessor/faust-0.9.47mr3/compiler/documentator/doc_compile.cpp +++ /dev/null @@ -1,1349 +0,0 @@ -/************************************************************************ - ************************************************************************ - FAUST compiler - Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale - --------------------------------------------------------------------- - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - ************************************************************************ - ************************************************************************/ - -/***************************************************************************** - HISTORY - 22/01/05 : corrected bug on bool signals cached in float variables - 2009-08-16 : First "doc" version (kb) - 2009-11-22 : Some clean up (kb) -*****************************************************************************/ - - - - -#include -#include -#include -#include -#include - -#include "doc_compile.hh" -#include "sigtype.hh" -#include "floats.hh" -#include "sigprint.hh" -#include "sigtyperules.hh" -#include "recursivness.hh" -#include "simplify.hh" -#include "privatise.hh" -#include "prim2.hh" -#include "xtended.hh" -#include "compatibility.hh" -#include "ppsig.hh" -#include "names.hh" -#include "doc.hh" -#include "tlib.hh" -#include "doc_notice.hh" - - -extern bool gLessTempSwitch; -extern int gMaxCopyDelay; -extern map gDocMathStringMap; - -extern bool getSigListNickName(Tree t, Tree& id); - -static const unsigned int MAX_RIGHT_MEMBER = 20; -static const unsigned int MAX_SUB_EXPR = 10; - - -/***************************************************************************** - getFreshID -*****************************************************************************/ - -map DocCompiler::fIDCounters; - -string DocCompiler::getFreshID(const string& prefix) -{ - if (fIDCounters.find(prefix) == fIDCounters.end()) { - fIDCounters[prefix] = 1; - } - int n = fIDCounters[prefix]; - fIDCounters[prefix] = n+1; - - return subst("$0_{$1}", prefix, docT(n)); -} - - -/***************************************************************************** - prepare -*****************************************************************************/ - -Tree DocCompiler::annotate(Tree LS) -{ - recursivnessAnnotation(LS); // Annotate LS with recursivness information - typeAnnotation(LS); // Annotate LS with type information - sharingAnalysis(LS); // annotate LS with sharing count - fOccMarkup.mark(LS); // annotate LS with occurences analysis - - return LS; -} - -/***************************************************************************** - compileLateq -*****************************************************************************/ - -Lateq* DocCompiler::compileLateq (Tree L, Lateq* compiledEqn) -{ - //cerr << "Documentator : compileLateq : L = "; printSignal(L, stdout, 0); cerr << endl; - - fLateq = compiledEqn; ///< Dynamic field ! - int priority = 0; - - for (int i = 0; isList(L); L = tl(L), i++) { - Tree sig = hd(L); - Tree id; - if(getSigNickname(sig, id)) { - //cerr << "Documentator : compileLateq : NICKNAMEPROPERTY = " << tree2str(id) << endl; - fLateq->addOutputSigFormula(subst("$0(t) = $1", tree2str(id), CS(sig, priority), docT(i))); - } else { - //cerr << "Documentator : compileLateq : NO NICKNAMEPROPERTY" << endl; - if (fLateq->outputs() == 1) { - fLateq->addOutputSigFormula(subst("y(t) = $0", CS(sig, priority))); - gDocNoticeFlagMap["outputsig"] = true; - } else { - fLateq->addOutputSigFormula(subst("$0(t) = $1", getFreshID("y"), CS(sig, priority))); - gDocNoticeFlagMap["outputsigs"] = true; - } - } - } - return fLateq; -} - - - -/***************************************************************************** - CS : compile a signal -*****************************************************************************/ - -/** - * Test if a signal is already compiled - * @param sig the signal expression to compile. - * @param name the string representing the compiled expression. - * @return true is already compiled - */ -bool DocCompiler::getCompiledExpression(Tree sig, string& cexp) -{ - return fCompileProperty.get(sig, cexp); -} - - -/** - * Set the string of a compiled expression is already compiled - * @param sig the signal expression to compile. - * @param cexp the string representing the compiled expression. - * @return the cexp (for commodity) - */ -string DocCompiler::setCompiledExpression(Tree sig, const string& cexp) -{ - fCompileProperty.set(sig, cexp); - return cexp; -} - - -/** - * Compile a signal - * @param sig the signal expression to compile. - * @return the C code translation of sig as a string - */ -string DocCompiler::CS (Tree sig, int priority) -{ - string code; - - if (!getCompiledExpression(sig, code)) { // not compiled yet. - code = generateCode(sig, priority); - setCompiledExpression(sig, code); - } - return code; -} - - - -/***************************************************************************** - generateCode : dispatch according to signal -*****************************************************************************/ - - -/** - * @brief Main code generator dispatch. - * - * According to the type of the input signal, generateCode calls - * the appropriate generator with appropriate arguments. - * - * @param sig The signal expression to compile. - * @param priority The environment priority of the expression. - * @return The LaTeX code translation of the signal. - */ -string DocCompiler::generateCode (Tree sig, int priority) -{ - int i; - double r; - Tree c, sel, x, y, z, u, label, ff, largs, type, name, file; - - if ( getUserData(sig) ) { printGCCall(sig,"generateXtended"); return generateXtended (sig, priority); } - else if ( isSigInt(sig, &i) ) { printGCCall(sig,"generateNumber"); return generateNumber (sig, docT(i)); } - else if ( isSigReal(sig, &r) ) { printGCCall(sig,"generateNumber"); return generateNumber (sig, docT(r)); } - else if ( isSigInput(sig, &i) ) { printGCCall(sig,"generateInput"); return generateInput (sig, docT(i+1)); } - else if ( isSigOutput(sig, &i, x) ) { printGCCall(sig,"generateOutput"); return generateOutput (sig, docT(i+1), CS(x, priority)); } - - else if ( isSigFixDelay(sig, x, y) ) { printGCCall(sig,"generateFixDelay"); return generateFixDelay (sig, x, y, priority); } - else if ( isSigPrefix(sig, x, y) ) { printGCCall(sig,"generatePrefix"); return generatePrefix (sig, x, y, priority); } - else if ( isSigIota(sig, x) ) { printGCCall(sig,"generateIota"); return generateIota (sig, x); } - - else if ( isSigBinOp(sig, &i, x, y) ) { printGCCall(sig,"generateBinOp"); return generateBinOp (sig, i, x, y, priority); } - else if ( isSigFFun(sig, ff, largs) ) { printGCCall(sig,"generateFFun"); return generateFFun (sig, ff, largs, priority); } - else if ( isSigFConst(sig, type, name, file) ) { printGCCall(sig,"generateFConst"); return generateFConst (sig, tree2str(file), tree2str(name)); } - else if ( isSigFVar(sig, type, name, file) ) { printGCCall(sig,"generateFVar"); return generateFVar (sig, tree2str(file), tree2str(name)); } - - // new special tables for documentation purposes - - else if ( isSigDocConstantTbl(sig, x, y) ) { printGCCall(sig,"generateDocConstantTbl"); return generateDocConstantTbl (sig, x, y); } - else if ( isSigDocWriteTbl(sig,x,y,z,u) ) { printGCCall(sig,"generateDocWriteTbl"); return generateDocWriteTbl (sig, x, y, z, u); } - else if ( isSigDocAccessTbl(sig, x, y) ) { printGCCall(sig, "generateDocAccessTbl"); return generateDocAccessTbl(sig, x, y); } - - - else if ( isSigSelect2(sig, sel, x, y) ) { printGCCall(sig,"generateSelect2"); return generateSelect2 (sig, sel, x, y, priority); } - else if ( isSigSelect3(sig, sel, x, y, z) ) { printGCCall(sig,"generateSelect3"); return generateSelect3 (sig, sel, x, y, z, priority); } - - else if ( isProj(sig, &i, x) ) { printGCCall(sig,"generateRecProj"); return generateRecProj (sig, x, i, priority); } - - else if ( isSigIntCast(sig, x) ) { printGCCall(sig,"generateIntCast"); return generateIntCast (sig, x, priority); } - else if ( isSigFloatCast(sig, x) ) { printGCCall(sig,"generateFloatCast"); return generateFloatCast(sig, x, priority); } - - else if ( isSigButton(sig, label) ) { printGCCall(sig,"generateButton"); return generateButton (sig, label); } - else if ( isSigCheckbox(sig, label) ) { printGCCall(sig,"generateCheckbox"); return generateCheckbox (sig, label); } - else if ( isSigVSlider(sig, label,c,x,y,z) ) { printGCCall(sig,"generateVSlider"); return generateVSlider (sig, label, c,x,y,z); } - else if ( isSigHSlider(sig, label,c,x,y,z) ) { printGCCall(sig,"generateHSlider"); return generateHSlider (sig, label, c,x,y,z); } - else if ( isSigNumEntry(sig, label,c,x,y,z) ) { printGCCall(sig,"generateNumEntry"); return generateNumEntry (sig, label, c,x,y,z); } - - else if ( isSigVBargraph(sig, label,x,y,z) ) { printGCCall(sig,"generateVBargraph"); return CS(z, priority);}//generateVBargraph (sig, label, x, y, CS(z, priority)); } - else if ( isSigHBargraph(sig, label,x,y,z) ) { printGCCall(sig,"generateHBargraph"); return CS(z, priority);}//generateHBargraph (sig, label, x, y, CS(z, priority)); } - else if ( isSigAttach(sig, x, y) ) { printGCCall(sig,"generateAttach"); return generateAttach (sig, x, y, priority); } - - else { - cerr << "Error in d signal, unrecognized signal : " << *sig << endl; - exit(1); - } - assert(0); - return "error in generate code"; -} - - -/** - * Print calling information of generateCode, for debug purposes. - * - * @remark - * To turn printing on, turn the 'printCalls' boolean to true. - */ -void DocCompiler::printGCCall(Tree sig, const string& calledFunction) -{ - bool printCalls = false; - bool maskSigs = false; - - if(printCalls) { - cerr << " -> generateCode calls " << calledFunction; - if(maskSigs) { - cerr << endl; - } else { - cerr << " on " << ppsig(sig) << endl; - } - } -} - - -/***************************************************************************** - NUMBERS -*****************************************************************************/ - - -string DocCompiler::generateNumber (Tree sig, const string& exp) -{ - string ctype, vname; - Occurences* o = fOccMarkup.retrieve(sig); - - // check for number occuring in delays - if (o->getMaxDelay()>0) { - getTypedNames(getCertifiedSigType(sig), "r", ctype, vname); - gDocNoticeFlagMap["recursigs"] = true; - //cerr << "- r : generateNumber : \"" << vname << "\"" << endl; - generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); - } - return exp; -} - -/***************************************************************************** - FOREIGN CONSTANTS -*****************************************************************************/ - - -string DocCompiler::generateFConst (Tree sig, const string& file, const string& exp) -{ - string ctype, vname; - Occurences* o = fOccMarkup.retrieve(sig); - - if (o->getMaxDelay()>0) { - getTypedNames(getCertifiedSigType(sig), "r", ctype, vname); - gDocNoticeFlagMap["recursigs"] = true; - //cerr << "- r : generateFConst : \"" << vname << "\"" << endl; - generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); - } - - if (exp == "fSamplingFreq") { - //gDocNoticeFlagMap["fsamp"] = true; - return "f_S"; - } - - return "\\mathrm{"+exp+"}"; -} - -/***************************************************************************** - FOREIGN VARIABLES -*****************************************************************************/ - - -string DocCompiler::generateFVar (Tree sig, const string& file, const string& exp) -{ - string ctype, vname; - Occurences* o = fOccMarkup.retrieve(sig); - - if (o->getMaxDelay()>0) { - getTypedNames(getCertifiedSigType(sig), "r", ctype, vname); - gDocNoticeFlagMap["recursigs"] = true; - //cerr << "- r : generateFVar : \"" << vname << "\"" << endl; - setVectorNameProperty(sig, vname); - generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); - } - return generateCacheCode(sig, exp); -} - - -/***************************************************************************** - INPUTS - OUTPUTS -*****************************************************************************/ - - -string DocCompiler::generateInput (Tree sig, const string& idx) -{ - if (fLateq->inputs() == 1) { - setVectorNameProperty(sig, "x"); - fLateq->addInputSigFormula("x(t)"); - gDocNoticeFlagMap["inputsig"] = true; - return generateCacheCode(sig, "x(t)"); - } else { - setVectorNameProperty(sig, subst("x_{$0}", idx)); - fLateq->addInputSigFormula(subst("x_{$0}(t)", idx)); - gDocNoticeFlagMap["inputsigs"] = true; - return generateCacheCode(sig, subst("x_{$0}(t)", idx)); - } -} - - -/** Unused for the moment ! */ -string DocCompiler::generateOutput (Tree sig, const string& idx, const string& arg) -{ - string dst; - - if (fLateq->outputs() == 1) { - dst = subst("y(t)", idx); - gDocNoticeFlagMap["outputsig"] = true; - } else { - dst = subst("y_{$0}(t)", idx); - gDocNoticeFlagMap["outputsigs"] = true; - } - - fLateq->addOutputSigFormula(subst("$0 = $1", dst, arg)); - return dst; -} - - -/***************************************************************************** - BINARY OPERATION -*****************************************************************************/ - -/** - * Generate binary operations, managing priority parenthesis. - * ((a*b)+c) can be written (a*b+c) if priority(*) > priority(+) - * ((a*b)*c) can be writteb (a*b*c) if * is associative - * Associative operation should have a distinc priority from other operations. - * Non associative operations can share the same priority. - * - * @param sig The signal expression to treat. - * @param opcode The operation code, as described in gBinOpLateqTable. - * @param arg1 The first operand. - * @param arg2 The second operand. - * @param priority The priority of the environment of the expression. - * - * @return The LaTeX code translation of the signal, cached. - * - * @remark The case of LaTeX frac{}{} is special. - * - * @todo Handle integer arithmetics, by testing arguments type, - * and printing dedicated operators (\oplus, \odot, \ominus, \oslash). - */ - -/// associative operations are + * | & xor -static bool associative (int opcode) { - return (opcode == kAdd) || (opcode == kMul) || (opcode == kAND) || (opcode == kOR) || (opcode == kXOR); -} - -string DocCompiler::generateBinOp(Tree sig, int opcode, Tree arg1, Tree arg2, int priority) -{ - string s; - int thisPriority = gBinOpLateqTable[opcode]->fPriority; - - /* Priority parenthesis handling. */ - string lpar = ""; - string rpar = ""; - if ( (thisPriority < priority) || ((thisPriority == priority) && !associative(opcode)) ) { - // (a+b)*c or (a/b)/c need parenthesis - lpar = " \\left("; - rpar = "\\right) "; - } - - Type t1 = getCertifiedSigType(arg1); - Type t2 = getCertifiedSigType(arg2); - bool intOpDetected = false; - if ( (t1->nature() == kInt) && (t2->nature() == kInt) ) { - intOpDetected = true; - } - - string op; - if(!intOpDetected) { - op = gBinOpLateqTable[opcode]->fName; - } else { - switch (opcode) { - case kAdd: - op = "\\oplus"; - gDocNoticeFlagMap["intplus"] = true; - break; - case kSub: - op = "\\ominus"; - gDocNoticeFlagMap["intminus"] = true; - break; - case kMul: - op = "\\odot"; - gDocNoticeFlagMap["intmult"] = true; - break; - case kDiv: - op = "\\oslash"; - gDocNoticeFlagMap["intdiv"] = true; - gDocNoticeFlagMap["intcast"] = true; // "$normalize(int(i/j))$" in the notice. - break; - default: - op = gBinOpLateqTable[opcode]->fName; - break; - } - } - - /* LaTeX frac{}{} handling VS general case. */ - if ( (opcode == kDiv) && (!intOpDetected) ) { - s = subst("$0\\frac{$1}{$2}$3", lpar, CS(arg1, 0), CS(arg2, 0), rpar); - } else { - s = subst("$0$1 $2 $3$4", lpar, CS(arg1, thisPriority), op, CS(arg2, thisPriority), rpar); - } - -// if (opcode == kMul) { -// gDocNoticeFlagMap["cdot"] = true; -// } - - return generateCacheCode(sig, s); -} - - -/***************************************************************************** - Primitive Operations -*****************************************************************************/ - -string DocCompiler::generateFFun(Tree sig, Tree ff, Tree largs, int priority) -{ - string code = ffname(ff); - code += '('; - string sep = ""; - for (int i = 0; i< ffarity(ff); i++) { - code += sep; - code += CS(nth(largs, i), priority); - sep = ", "; - } - code += ')'; - - gDocNoticeFlagMap["foreignfun"] = true; - - return "\\mathrm{ff"+code+"}"; -} - - -/***************************************************************************** - CACHE CODE -*****************************************************************************/ - -void DocCompiler::getTypedNames(Type t, const string& prefix, string& ctype, string& vname) -{ - if (t->nature() == kInt) { - ctype = "int"; vname = subst("$0", getFreshID(prefix)); - } else { - ctype = ifloat(); vname = subst("$0", getFreshID(prefix)); - } -} - - -/** - * Test if exp is very simple that is it - * can't be considered a real component - * @param exp the signal we want to test - * @return true if it a very simple signal - */ -static bool isVerySimpleFormula(Tree sig) -{ - int i; - double r; - Tree type, name, file, label, c, x, y, z; - - return isSigInt(sig, &i) - || isSigReal(sig, &r) - || isSigInput(sig, &i) - || isSigFConst(sig, type, name, file) - || isSigButton(sig, label) - || isSigCheckbox(sig, label) - || isSigVSlider(sig, label,c,x,y,z) - || isSigHSlider(sig, label,c,x,y,z) - || isSigNumEntry(sig, label,c,x,y,z) - ; -} - - -string DocCompiler::generateCacheCode(Tree sig, const string& exp) -{ - //cerr << "!! entering generateCacheCode with sig=\"" << ppsig(sig) << "\"" << endl; - - string vname, ctype, code, vectorname; - - int sharing = getSharingCount(sig); - Occurences* o = fOccMarkup.retrieve(sig); - - // check reentrance - if (getCompiledExpression(sig, code)) { - //cerr << "!! generateCacheCode called a true getCompiledExpression" << endl; - return code; - } - - // check for expression occuring in delays - if (o->getMaxDelay()>0) { - if (getVectorNameProperty(sig, vectorname)) { - return exp; - } - getTypedNames(getCertifiedSigType(sig), "r", ctype, vname); - gDocNoticeFlagMap["recursigs"] = true; - //cerr << "- r : generateCacheCode : vame=\"" << vname << "\", for sig=\"" << ppsig(sig) << "\"" << endl; - if (sharing>1) { - //cerr << " generateCacheCode calls generateDelayVec(generateVariableStore) on vame=\"" << vname << "\"" << endl; - return generateDelayVec(sig, generateVariableStore(sig,exp), ctype, vname, o->getMaxDelay()); - } else { - //cerr << " generateCacheCode calls generateDelayVec(exp) on vame=\"" << vname << "\"" << endl; - return generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); - } - } - else if (sharing == 1 || getVectorNameProperty(sig, vectorname) || isVerySimpleFormula(sig)) { - //cerr << "! generateCacheCode : sharing == 1 : return \"" << exp << "\"" << endl; - return exp; - } - else if (sharing > 1) { - //cerr << "! generateCacheCode : sharing > 1 : return \"" << exp << "\"" << endl; - return generateVariableStore(sig, exp); - } - else { - cerr << "Error in sharing count (" << sharing << ") for " << *sig << endl; - exit(1); - } - - return "Error in generateCacheCode"; -} - - -string DocCompiler::generateVariableStore(Tree sig, const string& exp) -{ - string vname, ctype; - Type t = getCertifiedSigType(sig); - - switch (t->variability()) { - - case kKonst : - getTypedNames(t, "k", ctype, vname); ///< "k" for constants. - fLateq->addConstSigFormula(subst("$0 = $1", vname, exp)); - gDocNoticeFlagMap["constsigs"] = true; - return vname; - - case kBlock : - getTypedNames(t, "p", ctype, vname); ///< "p" for "parameter". - fLateq->addParamSigFormula(subst("$0(t) = $1", vname, exp)); - gDocNoticeFlagMap["paramsigs"] = true; - setVectorNameProperty(sig, vname); - return subst("$0(t)", vname); - - case kSamp : - if(getVectorNameProperty(sig, vname)) { - return subst("$0(t)", vname); - } else { - getTypedNames(t, "s", ctype, vname); - //cerr << "- generateVariableStore : \"" << subst("$0(t) = $1", vname, exp) << "\"" << endl; - fLateq->addStoreSigFormula(subst("$0(t) = $1", vname, exp)); - gDocNoticeFlagMap["storedsigs"] = true; - setVectorNameProperty(sig, vname); - return subst("$0(t)", vname); - } - - default: - assert(0); - return ""; - } -} - - -/***************************************************************************** - CASTING -*****************************************************************************/ - - -string DocCompiler::generateIntCast(Tree sig, Tree x, int priority) -{ - gDocNoticeFlagMap["intcast"] = true; - - return generateCacheCode(sig, subst("\\mathrm{int}\\left($0\\right)", CS(x, 0))); -} - - -/** - * @brief Don't generate float cast ! - * - * It is just a kind of redirection. - * Calling generateCacheCode ensures to create a new - * variable name if the input signal expression is shared. - */ -string DocCompiler::generateFloatCast (Tree sig, Tree x, int priority) -{ - return generateCacheCode(sig, subst("$0", CS(x, priority))); -} - - -/***************************************************************************** - user interface elements -*****************************************************************************/ - -string DocCompiler::generateButton(Tree sig, Tree path) -{ - string vname = getFreshID("{u_b}"); - string varname = vname + "(t)"; - fLateq->addUISigFormula(getUIDir(path), prepareBinaryUI(varname, path)); - gDocNoticeFlagMap["buttonsigs"] = true; - return generateCacheCode(sig, varname); -} - -string DocCompiler::generateCheckbox(Tree sig, Tree path) -{ - string vname = getFreshID("{u_c}"); - string varname = vname + "(t)"; - fLateq->addUISigFormula(getUIDir(path), prepareBinaryUI(varname, path)); - gDocNoticeFlagMap["checkboxsigs"] = true; - return generateCacheCode(sig, varname); -} - -string DocCompiler::generateVSlider(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step) -{ - string varname = getFreshID("{u_s}") + "(t)"; - fLateq->addUISigFormula(getUIDir(path), prepareIntervallicUI(varname, path, cur, min, max)); - gDocNoticeFlagMap["slidersigs"] = true; - return generateCacheCode(sig, varname); -} - -string DocCompiler::generateHSlider(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step) -{ - string varname = getFreshID("{u_s}") + "(t)"; - fLateq->addUISigFormula(getUIDir(path), prepareIntervallicUI(varname, path, cur, min, max)); - gDocNoticeFlagMap["slidersigs"] = true; - return generateCacheCode(sig, varname); -} - -string DocCompiler::generateNumEntry(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step) -{ - string varname = getFreshID("{u_n}") + "(t)"; - fLateq->addUISigFormula(getUIDir(path), prepareIntervallicUI(varname, path, cur, min, max)); - gDocNoticeFlagMap["nentrysigs"] = true; - return generateCacheCode(sig, varname); -} - - -string DocCompiler::generateVBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp) -{ - string varname = getFreshID("{u_g}"); - - Type t = getCertifiedSigType(sig); - switch (t->variability()) { - - case kKonst : - break; - - case kBlock : - break; - - case kSamp : - break; - } - return generateCacheCode(sig, varname); -} - - -string DocCompiler::generateHBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp) -{ - string varname = getFreshID("{u_g}"); - - Type t = getCertifiedSigType(sig); - switch (t->variability()) { - - case kKonst : - break; - - case kBlock : - break; - - case kSamp : - break; - } - return generateCacheCode(sig, varname); -} - - -string DocCompiler::generateAttach (Tree sig, Tree x, Tree y, int priority) -{ - string vname; - string exp; - - CS(y, priority); - exp = CS(x, priority); - - if(getVectorNameProperty(x, vname)) { - setVectorNameProperty(sig, vname); - } - - return generateCacheCode(sig, exp); -} - - - - -/***************************************************************************** - TABLES - (note : tables here are siplified versions different from the ones used to - generate c++ code) -*****************************************************************************/ - -/** - * Generate the equation of a constant table (its content is time constant). - * Returns the name of the table - */ -string DocCompiler::generateDocConstantTbl (Tree /*tbl*/, Tree size, Tree isig) -{ - string vname, ctype; - string init = CS(isig,0); - - int n; - if (!isSigInt(size, &n)) { - cerr << "error in DocCompiler::generateDocConstantTbl() : " - << *size - << " is not an integer expression and can't be used as a table size' " - << endl; - } - - // allocate a name v_i for the table - getTypedNames(getCertifiedSigType(isig), "v", ctype, vname); - - // add a comment on tables in the notice - gDocNoticeFlagMap["tablesigs"] = true; - - // add equation v[t] = isig(t) - fLateq->addRDTblSigFormula(subst("$0[t] = $1 \\condition{when $$t \\in [0,$2]$$} ", vname, init, T(n-1))); - - // note that the name of the table can never be used outside an sigDocTableAccess - return vname; -} - - -/** - * tests if a charactere is a word separator - */ -static bool isSeparator(char c) -{ - bool w = ( ((c >= 'a') && (c <='z')) - || ((c >= 'A') && (c <='Z')) - || ((c >= '0') && (c <='9')) - ); - - return ! w; -} - - -/** - * Replaces the occurences of 't' in a formula with another character - */ -static string replaceTimeBy(const string& src, char r) -{ - string dst; - char pre = 0; - for (size_t i=0; i < src.size(); i++) - { - char x = src[i]; - if ((x=='t') && isSeparator(pre) && ((i == src.size()-1) || isSeparator(src[i+1]))) { - dst.push_back(r); - } else { - dst.push_back(x); - } - pre = x; - } - return dst; -} - -/** - * Generate the equation of a write table, which content is time dependent. - * It is basically a signal of vectors. - */ -string DocCompiler::generateDocWriteTbl (Tree /*tbl*/, Tree size, Tree isig, Tree widx, Tree wsig) -{ - string vname, ctype; - string init = CS(isig,0); - int n; - if (!isSigInt(size, &n)) { - cerr << "error in DocCompiler::generateDocWriteTbl() : " - << *size - << " is not an integer expression and can't be used as a table size' " - << endl; - } - - - // allocate a name w_i for the table - getTypedNames(getCertifiedSigType(isig), "w", ctype, vname); - - // add a comment on tables in the notice - gDocNoticeFlagMap["tablesigs"] = true; - - // describe the table equation - string ltqRWTableDef; - ltqRWTableDef += subst("$0(t)[i] = \n", vname); - ltqRWTableDef += "\\left\\{\\begin{array}{ll}\n"; - ltqRWTableDef += subst("$0 & \\mbox{if \\,} t < 0 \\mbox{\\, and \\,} i \\in [0,$1] \\\\\n", replaceTimeBy(init,'i'), T(n-1)); - ltqRWTableDef += subst("$0 & \\mbox{if \\,} i = $1 \\\\\n", CS(wsig,0), CS(widx,0)); - ltqRWTableDef += subst("$0(t\\!-\\!1)[i] & \\mbox{otherwise} \\\\\n", vname); - ltqRWTableDef += "\\end{array}\\right."; - - // add the table equation - fLateq->addRWTblSigFormula(ltqRWTableDef); //w(t) = initsig(t) - - // note that the name of the table can never be used outside an sigDocTableAccess - return vname; -} - - -/** - * Generate the equation of a write table, which content is time dependent. - * It is basically a signal of vectors. - */ -string DocCompiler::generateDocAccessTbl (Tree sig, Tree tbl, Tree ridx) -{ - // the compilation of a table always returns its name - string vname = CS(tbl, 0); - string result = subst("$0[$1]", vname, CS(ridx,0) ); - - return generateCacheCode(sig, result); -} - -bool DocCompiler::isShortEnough(string& s, unsigned int max) -{ - return (s.length() <= max); -} - - - -/***************************************************************************** - RECURSIONS -*****************************************************************************/ - - -/** - * Generate code for a projection of a group of mutually recursive definitions - */ -string DocCompiler::generateRecProj(Tree sig, Tree r, int i, int priority) -{ - string vname; - Tree var, le; - - //cerr << "*** generateRecProj sig : \"" << ppsig(sig) << "\"" << endl; - - if ( ! getVectorNameProperty(sig, vname)) { - assert(isRec(r, var, le)); - //cerr << " generateRecProj has NOT YET a vname : " << endl; - //cerr << "--> generateRecProj calls generateRec on \"" << ppsig(sig) << "\"" << endl; - generateRec(r, var, le, priority); - assert(getVectorNameProperty(sig, vname)); - //cerr << "<-- generateRecProj vname : \"" << subst("$0(t)", vname) << "\"" << endl; - } else { - //cerr << "(generateRecProj has already a vname : \"" << subst("$0(t)", vname) << "\")" << endl; - } - return subst("$0(t)", vname); -} - - -/** - * Generate code for a group of mutually recursive definitions - */ -void DocCompiler::generateRec(Tree sig, Tree var, Tree le, int priority) -{ - int N = len(le); - - vector used(N); - vector delay(N); - vector vname(N); - vector ctype(N); - - // prepare each element of a recursive definition - for (int i=0; igetMaxDelay(); - } else { - // this projection is not used therefore - // we should not generate code for it - used[i] = false; - //cerr << "generateRec : used[" << i << "] = false" << endl; - } - } - - // generate delayline for each element of a recursive definition - for (int i=0; i The LaTeX code translation of the signal, cached. - */ -string DocCompiler::generatePrefix (Tree sig, Tree x, Tree e, int priority) -{ - string var = getFreshID("m"); - string exp0 = CS(x, priority); - string exp1 = CS(e, priority); // ensure exp1 is compiled to have a vector name - string vecname; - - if (! getVectorNameProperty(e, vecname)) { - cerr << "No vector name for : " << ppsig(e) << endl; - assert(0); - } - - string ltqPrefixDef; - ltqPrefixDef += subst("$0(t) = \n", var); - ltqPrefixDef += "\\left\\{\\begin{array}{ll}\n"; - ltqPrefixDef += subst("$0 & \\mbox{, when \\,} t = 0\\\\\n", exp0); - ltqPrefixDef += subst("$0 & \\mbox{, when \\,} t > 0\n", subst("$0(t\\!-\\!1)", vecname)); - ltqPrefixDef += "\\end{array}\\right."; - - fLateq->addPrefixSigFormula(ltqPrefixDef); - gDocNoticeFlagMap["prefixsigs"] = true; - - return generateCacheCode(sig, subst("$0(t)", var)); -} - - -/***************************************************************************** - IOTA(n) -*****************************************************************************/ - -/** - * Generate a "iota" time function, n-cyclical. - */ -string DocCompiler::generateIota (Tree sig, Tree n) -{ - int size; - if (!isSigInt(n, &size)) { fprintf(stderr, "error in generateIota\n"); exit(1); } - //cout << "iota !" << endl; - return subst(" t \\bmod{$0} ", docT(size)); -} - - - -// a revoir en utilisant la lecture de table et en partageant la construction de la paire de valeurs - - -/** - * Generate a select2 code - */ -string DocCompiler::generateSelect2 (Tree sig, Tree sel, Tree s1, Tree s2, int priority) -{ - string var = getFreshID("q"); - string expsel = CS(sel, 0); - string exps1 = CS(s1, 0); - string exps2 = CS(s2, 0); - - string ltqSelDef; - ltqSelDef += subst("$0(t) = \n", var); - ltqSelDef += "\\left\\{\\begin{array}{ll}\n"; - ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 0\\\\\n", exps1, expsel); - ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 1\n", exps2, expsel); - ltqSelDef += "\\end{array}\\right."; - - fLateq->addSelectSigFormula(ltqSelDef); - gDocNoticeFlagMap["selectionsigs"] = true; - - //return generateCacheCode(sig, subst("$0(t)", var)); - setVectorNameProperty(sig, var); - return subst("$0(t)", var); -} - - -/** - * Generate a select3 code - */ -string DocCompiler::generateSelect3 (Tree sig, Tree sel, Tree s1, Tree s2, Tree s3, int priority) -{ - string var = getFreshID("q"); - string expsel = CS(sel, 0); - string exps1 = CS(s1, 0); - string exps2 = CS(s2, 0); - string exps3 = CS(s3, 0); - - string ltqSelDef; - ltqSelDef += subst("$0(t) = \n", var); - ltqSelDef += "\\left\\{\\begin{array}{ll}\n"; - ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 0\\\\\n", generateVariableStore(s1, exps1), expsel); - ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 1\\\\\n", generateVariableStore(s2, exps2), expsel); - ltqSelDef += subst("$0 & \\mbox{if \\,} $1 = 2\n", generateVariableStore(s3, exps3), expsel); - ltqSelDef += "\\end{array}\\right."; - - fLateq->addSelectSigFormula(ltqSelDef); - gDocNoticeFlagMap["selectionsigs"] = true; - - //return generateCacheCode(sig, subst("$0(t)", var)); - setVectorNameProperty(sig, var); - return subst("$0(t)", var); -} - - -/** - * retrieve the type annotation of sig - * @param sig the signal we want to know the type - */ -string DocCompiler::generateXtended (Tree sig, int priority) -{ - xtended* p = (xtended*) getUserData(sig); - vector args; - vector types; - - for (int i=0; iarity(); i++) { - args.push_back(CS(sig->branch(i), 0)); - types.push_back(getCertifiedSigType(sig->branch(i))); - } - - if (p->needCache()) { - //cerr << "!! generateXtended : : calls generateCacheCode(sig, p->generateLateq(fLateq, args, types))" << endl; - return generateCacheCode(sig, p->generateLateq(fLateq, args, types)); - } else { - //cerr << "!! generateXtended : : calls p->generateLateq(fLateq, args, types)" << endl; - return p->generateLateq(fLateq, args, types); - } -} - - - -//------------------------------------------------------------------------------------------------ - - -/***************************************************************************** - vector name property -*****************************************************************************/ - -/** - * Set the vector name property of a signal, the name of the vector used to - * store the previous values of the signal to implement a delay. - * @param sig the signal expression. - * @param vecname the string representing the vector name. - * @return true is already compiled - */ -void DocCompiler::setVectorNameProperty(Tree sig, const string& vecname) -{ - fVectorProperty.set(sig, vecname); -} - - -/** - * Get the vector name property of a signal, the name of the vector used to - * store the previous values of the signal to implement a delay. - * @param sig the signal expression. - * @param vecname the string where to store the vector name. - * @return true if the signal has this property, false otherwise - */ - -bool DocCompiler::getVectorNameProperty(Tree sig, string& vecname) -{ - return fVectorProperty.get(sig, vecname); -} - - - -/***************************************************************************** - N-SAMPLE FIXED DELAY : sig = exp@delay - - case 1-sample max delay : - Y(t-0) Y(t-1) - Temp Var gLessTempSwitch = false - V[0] V[1] gLessTempSwitch = true - - case max delay < gMaxCopyDelay : - Y(t-0) Y(t-1) Y(t-2) ... - Temp V[0] V[1] ... gLessTempSwitch = false - V[0] V[1] V[2] ... gLessTempSwitch = true - - case max delay >= gMaxCopyDelay : - Y(t-0) Y(t-1) Y(t-2) ... - Temp V[0] V[1] ... - V[0] V[1] V[2] ... - - -*****************************************************************************/ - -/** - * Generate code for accessing a delayed signal. The generated code depend of - * the maximum delay attached to exp and the gLessTempSwitch. - * - * @todo Priorités à revoir pour le parenthésage (associativité de - et /), - * avec gBinOpLateqTable dans binop.cpp. - */ -string DocCompiler::generateFixDelay (Tree sig, Tree exp, Tree delay, int priority) -{ - int d; - string vecname; - - CS(exp, 0); // ensure exp is compiled to have a vector name - - if (! getVectorNameProperty(exp, vecname)) { - cerr << "No vector name for : " << ppsig(exp) << endl; - assert(0); - } - - if (isSigInt(delay, &d) && (d == 0)) { - //cerr << "@ generateFixDelay : d = " << d << endl; - return subst("$0(t)", vecname); - } else { - //cerr << "@ generateFixDelay : d = " << d << endl; - return subst("$0(t\\!-\\!$1)", vecname, CS(delay, 7)); - } -} - - -/** - * Generate code for the delay mecchanism. The generated code depend of the - * maximum delay attached to exp and the "less temporaries" switch - */ -string DocCompiler::generateDelayVec(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd) -{ - string s = generateDelayVecNoTemp(sig, exp, ctype, vname, mxd); - if (getCertifiedSigType(sig)->variability() < kSamp) { - return exp; - } else { - return s; - } -} - - -/** - * Generate code for the delay mecchanism without using temporary variables - */ -string DocCompiler::generateDelayVecNoTemp(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd) -{ - assert(mxd > 0); - - //cerr << " entering generateDelayVecNoTemp" << endl; - - string vectorname; - - // if generateVariableStore has already tagged sig, no definition is needed. - if(getVectorNameProperty(sig, vectorname)) { - return subst("$0(t)", vectorname); - } else { - fLateq->addRecurSigFormula(subst("$0(t) = $1", vname, exp)); - setVectorNameProperty(sig, vname); - return subst("$0(t)", vname); - } -} - - -/** - * Generate code for the delay mecchanism without using temporary variables - */ -void DocCompiler::generateDelayLine(const string& ctype, const string& vname, int mxd, const string& exp) -{ - //assert(mxd > 0); - if (mxd == 0) { - fLateq->addRecurSigFormula(subst("$0(t) = $1", vname, exp)); - } else { - fLateq->addRecurSigFormula(subst("$0(t) = $1", vname, exp)); - } -} - - - - -/**************************************************************** - User interface element utilities. - *****************************************************************/ - - -/** - * @brief Get the directory of a user interface element. - * - * Convert the input reversed path tree into a string. - * The name of the UI is stripped (the head of the path tree), - * the rest of the tree is a list of pointed pairs, where the names - * are contained by the tail of these pointed pairs. - * Metadatas (begining by '[') are stripped. - * - * @param[in] pathname The path tree to convert. - * @return A directory-like string. - */ -string DocCompiler::getUIDir(Tree pathname) -{ - //cerr << "Documentator : getUIDir : print(pathname, stdout) = "; print(pathname, stdout); cerr << endl; - string s; - Tree dir = reverse(tl(pathname)); - while (!isNil(dir)) { - string tmp = tree2str(tl(hd(dir))); - if ( (tmp[0] != '[') && (!tmp.empty()) ) { - s += tmp + '/'; - } - dir = tl(dir); - } - return s; -} - - -/** - * @brief Prepare binary user interface elements (button, checkbox). - * - * - Format a LaTeX output string as a supertabular row with 3 columns : - * "\begin{supertabular}{lll}". @see Lateq::printHierarchy - * - The UI range is only a set of two values : {0, 1}. - * - The UI current value is automatically 0. - * - * @param[in] name The LaTeX name of the UI signal (eg. "{u_b}_{i}(t)"). - * @param[in] path The path tree to parse. - * @return The LaTeX output string. - */ -string DocCompiler::prepareBinaryUI(const string& name, Tree path) -{ - string label, unit; - getUIDocInfos(path, label, unit); - string s = ""; - label = (label.size()>0) ? ("\\textsf{\""+label+"\"} ") : ""; - unit = (unit.size()>0) ? ("\\ ("+unit+")") : ""; - s += label + unit; - s += " & $" + name + "$"; - s += " $\\in$ $\\left\\{\\,0, 1\\,\\right\\}$"; - s += " & $(\\mbox{" + gDocMathStringMap["defaultvalue"] + "} = 0)$\\\\"; - return s; -} - - -/** - * @brief Prepare "intervallic" user interface elements (sliders, nentry). - * - * - Format a LaTeX output string as a supertabular row with 3 columns : - * "\begin{supertabular}{lll}". @see Lateq::printHierarchy - * - The UI range is an bounded interval : [tmin, tmax]. - * - The UI current value is tcur. - * - * @param[in] name The LaTeX name of the UI signal (eg. "{u_s}_{i}(t)"). - * @param[in] path The path tree to parse. - * @param[in] tcur The current UI value tree to convert. - * @param[in] tmin The minimum UI value tree to convert. - * @param[in] tmax The maximum UI value tree to convert. - * @return The LaTeX output string. - */ -string DocCompiler::prepareIntervallicUI(const string& name, Tree path, Tree tcur, Tree tmin, Tree tmax) -{ - string label, unit, cur, min, max; - getUIDocInfos(path, label, unit); - cur = docT(tree2float(tcur)); - min = docT(tree2float(tmin)); - max = docT(tree2float(tmax)); - - string s = ""; - label = (label.size()>0) ? ("\\textsf{\""+label+"\"} ") : ""; - unit = (unit.size()>0) ? ("\\ ("+unit+")") : ""; - s += label + unit; - s += " & $" + name + "$"; - s += " $\\in$ $\\left[\\," + min + ", " + max + "\\,\\right]$"; - s += " & $(\\mbox{" + gDocMathStringMap["defaultvalue"] + "} = " + cur + ")$\\\\"; - return s; -} - - -/** - * Get information on a user interface element for documentation. - * - * @param[in] path The UI full pathname to parse. - * @param[out] label The place to store the UI name. - * @param[out] unit The place to store the UI unit. - */ -void DocCompiler::getUIDocInfos(Tree path, string& label, string& unit) -{ - label = ""; - unit = ""; - - map > metadata; - extractMetadata(tree2str(hd(path)), label, metadata); - - set myunits = metadata["unit"]; -// for (set::iterator i = myunits.begin(); i != myunits.end(); i++) { -// cerr << "Documentator : getUIDocInfos : metadata[\"unit\"] = " << *i << endl; -// } - for (map >::iterator i = metadata.begin(); i != metadata.end(); i++) { - const string& key = i->first; - const set& values = i->second; - for (set::const_iterator j = values.begin(); j != values.end(); j++) { - if(key == "unit") unit += *j; - } - } -} - -