/************************************************************************ ************************************************************************ FAUST compiler Copyright (C) 2003-2018 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. ************************************************************************ ************************************************************************/ /***************************************************************************** ****************************************************************************** The Box Language ****************************************************************************** *****************************************************************************/ /**\file boxes.cpp * \author Yann Orlarey * \version 1.0 * \date 2003 * \brief Implementation of block diagram expressions. * Boxes are created using five main connection operations : sequential (:), * parallel (,), split (<:), merge (:>), and recursive (~). */ #include "boxes.hh" #include #include #include "exception.hh" #include "global.hh" #include "ppbox.hh" #include "prim2.hh" #include "xtended.hh" /***************************************************************************** Identifiers *****************************************************************************/ Tree boxIdent(const char* name) { return tree(gGlobal->BOXIDENT, tree(symbol(name))); } bool isBoxIdent(Tree t) { return t->node() == Node(gGlobal->BOXIDENT); } bool isBoxIdent(Tree t0, const char** str) { Tree t1; Sym s; if (isTree(t0, gGlobal->BOXIDENT, t1) && isSym(t1->node(), &s)) { *str = name(s); return true; } else { return false; } } /***************************************************************************** Numbers *****************************************************************************/ EXPORT Tree boxInt(int n) { return tree(n); } EXPORT Tree boxReal(double n) { return tree(n); } bool isBoxInt(Tree t) { return isInt(t->node()); } bool isBoxReal(Tree t) { return isDouble(t->node()); } bool isBoxInt(Tree t, int* i) { return isInt(t->node(), i); } bool isBoxReal(Tree t, double* r) { return isDouble(t->node(), r); } /***************************************************************************** Waveform *****************************************************************************/ EXPORT Tree boxWaveform(const tvec& br) { return tree(gGlobal->BOXWAVEFORM, br); } bool isBoxWaveform(Tree s) { return isTree(s, gGlobal->BOXWAVEFORM); } /***************************************************************************** Route *****************************************************************************/ EXPORT Tree boxRoute(Tree n, Tree m, Tree r) { return tree(gGlobal->BOXROUTE, n, m, r); } bool isBoxRoute(Tree s, Tree& n, Tree& m, Tree& r) { return isTree(s, gGlobal->BOXROUTE, n, m, r); } /***************************************************************************** Wire and Cut *****************************************************************************/ EXPORT Tree boxCut() { return tree(gGlobal->BOXCUT); } bool isBoxCut(Tree t) { return isTree(t, gGlobal->BOXCUT); } EXPORT Tree boxWire() { return tree(gGlobal->BOXWIRE); } bool isBoxWire(Tree t) { return isTree(t, gGlobal->BOXWIRE); } /***************************************************************************** Symbolic Boxes with symbolic slots *****************************************************************************/ Tree boxSlot(int id) { return tree(gGlobal->BOXSLOT, tree(id)); } bool isBoxSlot(Tree t) { Tree w; return isTree(t, gGlobal->BOXSLOT, w); } bool isBoxSlot(Tree t, int* id) { Tree w; return isTree(t, gGlobal->BOXSLOT, w) && isInt(w->node(), id); } Tree boxSymbolic(Tree slot, Tree body) { return tree(gGlobal->BOXSYMBOLIC, slot, body); } bool isBoxSymbolic(Tree t) { Tree slot, body; return isTree(t, gGlobal->BOXSYMBOLIC, slot, body); } bool isBoxSymbolic(Tree t, Tree& slot, Tree& body) { return isTree(t, gGlobal->BOXSYMBOLIC, slot, body); } /***************************************************************************** Composition of Boxes *****************************************************************************/ EXPORT Tree boxSeq(Tree x, Tree y) { return tree(gGlobal->BOXSEQ, x, y); } bool isBoxSeq(Tree t, Tree& x, Tree& y) { return isTree(t, gGlobal->BOXSEQ, x, y); } EXPORT Tree boxPar(Tree x, Tree y) { return tree(gGlobal->BOXPAR, x, y); } bool isBoxPar(Tree t, Tree& x, Tree& y) { return isTree(t, gGlobal->BOXPAR, x, y); } EXPORT Tree boxRec(Tree x, Tree y) { return tree(gGlobal->BOXREC, x, y); } bool isBoxRec(Tree t, Tree& x, Tree& y) { return isTree(t, gGlobal->BOXREC, x, y); } EXPORT Tree boxSplit(Tree x, Tree y) { return tree(gGlobal->BOXSPLIT, x, y); } bool isBoxSplit(Tree t, Tree& x, Tree& y) { return isTree(t, gGlobal->BOXSPLIT, x, y); } EXPORT Tree boxMerge(Tree x, Tree y) { return tree(gGlobal->BOXMERGE, x, y); } bool isBoxMerge(Tree t, Tree& x, Tree& y) { return isTree(t, gGlobal->BOXMERGE, x, y); } /***************************************************************************** Algorithmic Composition of Boxes *****************************************************************************/ Tree boxIPar(Tree x, Tree y, Tree z) { return tree(gGlobal->BOXIPAR, x, y, z); } Tree boxISeq(Tree x, Tree y, Tree z) { return tree(gGlobal->BOXISEQ, x, y, z); } Tree boxISum(Tree x, Tree y, Tree z) { return tree(gGlobal->BOXISUM, x, y, z); } Tree boxIProd(Tree x, Tree y, Tree z) { return tree(gGlobal->BOXIPROD, x, y, z); } bool isBoxIPar(Tree t, Tree& x, Tree& y, Tree& z) { return isTree(t, gGlobal->BOXIPAR, x, y, z); } bool isBoxISeq(Tree t, Tree& x, Tree& y, Tree& z) { return isTree(t, gGlobal->BOXISEQ, x, y, z); } bool isBoxISum(Tree t, Tree& x, Tree& y, Tree& z) { return isTree(t, gGlobal->BOXISUM, x, y, z); } bool isBoxIProd(Tree t, Tree& x, Tree& y, Tree& z) { return isTree(t, gGlobal->BOXIPROD, x, y, z); } /***************************************************************************** Static information on Boxes *****************************************************************************/ Tree boxInputs(Tree x) { return tree(gGlobal->BOXINPUTS, x); } Tree boxOutputs(Tree x) { return tree(gGlobal->BOXOUTPUTS, x); } bool isBoxInputs(Tree t, Tree& x) { return isTree(t, gGlobal->BOXINPUTS, x); } bool isBoxOutputs(Tree t, Tree& x) { return isTree(t, gGlobal->BOXOUTPUTS, x); } /***************************************************************************** Lambda-Calculus of Boxes *****************************************************************************/ Tree boxAbstr(Tree x, Tree y) { return tree(gGlobal->BOXABSTR, x, y); } Tree boxAppl(Tree x, Tree y) { return tree(gGlobal->BOXAPPL, x, y); } bool isBoxAbstr(Tree t) { return t->node() == Node(gGlobal->BOXABSTR); } bool isBoxAppl(Tree t) { return t->node() == Node(gGlobal->BOXAPPL); } bool isBoxAbstr(Tree t, Tree& x, Tree& y) { return isTree(t, gGlobal->BOXABSTR, x, y); } bool isBoxAppl(Tree t, Tree& x, Tree& y) { return isTree(t, gGlobal->BOXAPPL, x, y); } Tree buildBoxAbstr(Tree largs, Tree body) { if (isNil(largs)) { return body; } else { return buildBoxAbstr(tl(largs), boxAbstr(hd(largs), body)); } } #if 0 Tree buildBoxAppl(Tree fun, Tree revarglist) { if (isNil(revarglist)) { return fun; } else { return boxAppl(buildBoxAppl(fun, tl(revarglist)), hd(revarglist)); } } #else Tree buildBoxAppl(Tree fun, Tree revarglist) { if (isNil(revarglist)) { // TO CHECK !!!!!! throw faustexception("ERROR : buildBoxAppl called with null revarglist\n"); } return boxAppl(fun, revarglist); } #endif Tree closure(Tree abstr, Tree genv, Tree vis, Tree lenv) { return tree(gGlobal->CLOSURE, abstr, genv, vis, lenv); } bool isClosure(Tree t, Tree& abstr, Tree& genv, Tree& vis, Tree& lenv) { return isTree(t, gGlobal->CLOSURE, abstr, genv, vis, lenv); } Tree boxError() { return tree(gGlobal->BOXERROR); } bool isBoxError(Tree t) { return isTree(t, gGlobal->BOXERROR); } Tree boxAccess(Tree exp, Tree id) { return tree(gGlobal->BOXACCESS, exp, id); } bool isBoxAccess(Tree t, Tree& exp, Tree& id) { return isTree(t, gGlobal->BOXACCESS, exp, id); } /***************************************************************************** Boxes with local definitions *****************************************************************************/ Tree boxWithLocalDef(Tree body, Tree ldef) { return tree(gGlobal->BOXWITHLOCALDEF, body, ldef); } bool isBoxWithLocalDef(Tree t, Tree& body, Tree& ldef) { return isTree(t, gGlobal->BOXWITHLOCALDEF, body, ldef); } /***************************************************************************** Boxes with recursive definitions *****************************************************************************/ // def2names transforms a liste of definition (name.expression) into a list of name static Tree def2names(Tree ldef) { if (isNil(ldef)) { return gGlobal->nil; } else { Tree def = hd(ldef); return cons(hd(def), def2names(tl(ldef))); } } // def2exp transforms a list of definition (name.expression) into a list of expressions static Tree def2exp(Tree ldef) { if (isNil(ldef)) { return gGlobal->nil; } else { Tree def = hd(ldef); return cons(tl(def), def2exp(tl(ldef))); } } // makeBus(3) => "_,_,_" static Tree makeBus(int n) { return (n <= 1) ? boxWire() : boxPar(boxWire(), makeBus(n - 1)); } // makeParList((a,b,d)) => "a,b,c" static Tree makeParList(Tree lexp) { Tree l2 = tl(lexp); if (isNil(l2)) { return hd(lexp); } else { return boxPar(hd(lexp), makeParList(l2)); } } // makeBoxAbstr(largs,body) => \(lnames).(body) static Tree makeBoxAbstr(Tree largs, Tree body) { if (isNil(largs)) { return body; } else { return boxAbstr(hd(largs), makeBoxAbstr(tl(largs), body)); } } // makeSelector(5,2) => "!,!,_,!,!" static Tree makeSelector(int n, int i) { Tree op = (i == 0) ? boxWire() : boxCut(); return (n == 1) ? op : boxPar(op, makeSelector(n - 1, i - 1)); } // defines each symbol si of lnames as => "si = RECURSIVEBODY : select(n,i);" static Tree makeRecProjectionsList(int n, int i, Tree lnames, Tree ldef) { if (i == n) { return ldef; } else { Tree sel = boxSeq(gGlobal->LETRECBODY, makeSelector(n, i)); return cons(cons(hd(lnames), sel), makeRecProjectionsList(n, i + 1, tl(lnames), ldef)); } } // buildRecursiveBodyDef(n,lnames,lexp) => "RECURSIVEBODY = \(lnames).(lexp) ~ bus(n);" static Tree buildRecursiveBodyDef(int n, Tree lnames, Tree lexp) { return cons(gGlobal->LETRECBODY, boxRec(makeBoxAbstr(lnames, makeParList(lexp)), makeBus(n))); } //---------------------------------------------------------------------------- // Transform a letrec expression into a with expression //---------------------------------------------------------------------------- Tree boxWithRecDef(Tree body, Tree ldef) { // cout << "list of recursive definitions : " << *ldef << endl; Tree lnames = def2names(ldef); Tree lexp = def2exp(ldef); int n = len(ldef); Tree rdef = buildRecursiveBodyDef(n, lnames, lexp); Tree lrp = makeRecProjectionsList(n, 0, lnames, gGlobal->nil); Tree w = boxWithLocalDef(body, cons(rdef, lrp)); // cerr << "boxWithRecDef(" << boxpp(body) << ',' << *ldef << ") -> " << boxpp(w) << endl; return w; } /***************************************************************************** Boxes modif local definitions *****************************************************************************/ Tree boxModifLocalDef(Tree body, Tree ldef) { return tree(gGlobal->BOXMODIFLOCALDEF, body, ldef); } bool isBoxModifLocalDef(Tree t, Tree& body, Tree& ldef) { return isTree(t, gGlobal->BOXMODIFLOCALDEF, body, ldef); } /***************************************************************************** Modules *****************************************************************************/ Tree boxEnvironment() { return tree(gGlobal->BOXENVIRONMENT); } bool isBoxEnvironment(Tree s) { return isTree(s, gGlobal->BOXENVIRONMENT); } Tree boxComponent(Tree filename) { return tree(gGlobal->BOXCOMPONENT, filename); } bool isBoxComponent(Tree s, Tree& filename) { return isTree(s, gGlobal->BOXCOMPONENT, filename); } Tree boxLibrary(Tree filename) { return tree(gGlobal->BOXLIBRARY, filename); } bool isBoxLibrary(Tree s, Tree& filename) { return isTree(s, gGlobal->BOXLIBRARY, filename); } Tree importFile(Tree filename) { return tree(gGlobal->IMPORTFILE, filename); } bool isImportFile(Tree s, Tree& filename) { return isTree(s, gGlobal->IMPORTFILE, filename); } /***************************************************************************** External Primitive Boxes (n -> 1) *****************************************************************************/ Tree boxPrim0(prim0 foo) { return tree(gGlobal->BOXPRIM0, tree((void*)foo)); } bool isBoxPrim0(Tree s) { Tree t; return isTree(s, gGlobal->BOXPRIM0, t); } bool isBoxPrim0(Tree s, prim0* p) { Tree t; return isTree(s, gGlobal->BOXPRIM0, t) && isPointer(t->node(), (void**)p); } Tree boxPrim1(prim1 foo) { return tree(gGlobal->BOXPRIM1, tree((void*)foo)); } bool isBoxPrim1(Tree s) { Tree t; return isTree(s, gGlobal->BOXPRIM1, t); } bool isBoxPrim1(Tree s, prim1* p) { Tree t; return isTree(s, gGlobal->BOXPRIM1, t) && isPointer(t->node(), (void**)p); } Tree boxPrim2(prim2 foo) { return tree(gGlobal->BOXPRIM2, tree((void*)foo)); } bool isBoxPrim2(Tree s) { Tree t; return isTree(s, gGlobal->BOXPRIM2, t); } bool isBoxPrim2(Tree s, prim2* p) { Tree t; return isTree(s, gGlobal->BOXPRIM2, t) && isPointer(t->node(), (void**)p); } Tree boxPrim3(prim3 foo) { return tree(gGlobal->BOXPRIM3, tree((void*)foo)); } bool isBoxPrim3(Tree s) { Tree t; return isTree(s, gGlobal->BOXPRIM3, t); } bool isBoxPrim3(Tree s, prim3* p) { Tree t; return isTree(s, gGlobal->BOXPRIM3, t) && isPointer(t->node(), (void**)p); } Tree boxPrim4(prim4 foo) { return tree(gGlobal->BOXPRIM4, tree((void*)foo)); } bool isBoxPrim4(Tree s) { Tree t; return isTree(s, gGlobal->BOXPRIM4, t); } bool isBoxPrim4(Tree s, prim4* p) { Tree t; return isTree(s, gGlobal->BOXPRIM4, t) && isPointer(t->node(), (void**)p); } Tree boxPrim5(prim5 foo) { return tree(gGlobal->BOXPRIM5, tree((void*)foo)); } bool isBoxPrim5(Tree s) { Tree t; return isTree(s, gGlobal->BOXPRIM5, t); } bool isBoxPrim5(Tree s, prim5* p) { Tree t; return isTree(s, gGlobal->BOXPRIM5, t) && isPointer(t->node(), (void**)p); } /***************************************************************************** Foreign Functions *****************************************************************************/ EXPORT Tree boxFFun(Tree ff) { return tree(gGlobal->BOXFFUN, ff); } bool isBoxFFun(Tree s) { Tree ff; return isTree(s, gGlobal->BOXFFUN, ff); } bool isBoxFFun(Tree s, Tree& ff) { return isTree(s, gGlobal->BOXFFUN, ff); } EXPORT Tree boxFConst(Tree type, Tree name, Tree file) { return tree(gGlobal->BOXFCONST, type, name, file); } bool isBoxFConst(Tree s) { Tree t, n, f; return isTree(s, gGlobal->BOXFCONST, t, n, f); } bool isBoxFConst(Tree s, Tree& type, Tree& name, Tree& file) { return isTree(s, gGlobal->BOXFCONST, type, name, file); } EXPORT Tree boxFVar(Tree type, Tree name, Tree file) { return tree(gGlobal->BOXFVAR, type, name, file); } bool isBoxFVar(Tree s) { Tree t, n, f; return isTree(s, gGlobal->BOXFVAR, t, n, f); } bool isBoxFVar(Tree s, Tree& type, Tree& name, Tree& file) { return isTree(s, gGlobal->BOXFVAR, type, name, file); } /***************************************************************************** User Interface Elements *****************************************************************************/ EXPORT Tree boxButton(Tree lbl) { return tree(gGlobal->BOXBUTTON, lbl); } bool isBoxButton(Tree s) { Tree lbl; return isTree(s, gGlobal->BOXBUTTON, lbl); } bool isBoxButton(Tree s, Tree& lbl) { return isTree(s, gGlobal->BOXBUTTON, lbl); } EXPORT Tree boxCheckbox(Tree lbl) { return tree(gGlobal->BOXCHECKBOX, lbl); } bool isBoxCheckbox(Tree s) { Tree lbl; return isTree(s, gGlobal->BOXCHECKBOX, lbl); } bool isBoxCheckbox(Tree s, Tree& lbl) { return isTree(s, gGlobal->BOXCHECKBOX, lbl); } EXPORT Tree boxHSlider(Tree lbl, Tree cur, Tree min, Tree max, Tree step) { return tree(gGlobal->BOXHSLIDER, lbl, list4(cur, min, max, step)); } bool isBoxHSlider(Tree s) { Tree lbl, params; return isTree(s, gGlobal->BOXHSLIDER, lbl, params); } bool isBoxHSlider(Tree s, Tree& lbl, Tree& cur, Tree& min, Tree& max, Tree& step) { Tree params; if (isTree(s, gGlobal->BOXHSLIDER, lbl, params)) { cur = nth(params, 0); min = nth(params, 1); max = nth(params, 2); step = nth(params, 3); return true; } else { return false; } } EXPORT Tree boxVSlider(Tree lbl, Tree cur, Tree min, Tree max, Tree step) { return tree(gGlobal->BOXVSLIDER, lbl, list4(cur, min, max, step)); } bool isBoxVSlider(Tree s) { Tree lbl, params; return isTree(s, gGlobal->BOXVSLIDER, lbl, params); } bool isBoxVSlider(Tree s, Tree& lbl, Tree& cur, Tree& min, Tree& max, Tree& step) { Tree params; if (isTree(s, gGlobal->BOXVSLIDER, lbl, params)) { cur = nth(params, 0); min = nth(params, 1); max = nth(params, 2); step = nth(params, 3); return true; } else { return false; } } EXPORT Tree boxNumEntry(Tree lbl, Tree cur, Tree min, Tree max, Tree step) { return tree(gGlobal->BOXNUMENTRY, lbl, list4(cur, min, max, step)); } bool isBoxNumEntry(Tree s) { Tree lbl, params; return isTree(s, gGlobal->BOXNUMENTRY, lbl, params); } bool isBoxNumEntry(Tree s, Tree& lbl, Tree& cur, Tree& min, Tree& max, Tree& step) { Tree params; if (isTree(s, gGlobal->BOXNUMENTRY, lbl, params)) { cur = nth(params, 0); min = nth(params, 1); max = nth(params, 2); step = nth(params, 3); return true; } else { return false; } } Tree boxHGroup(Tree lbl, Tree x) { return tree(gGlobal->BOXHGROUP, lbl, x); } bool isBoxHGroup(Tree s) { Tree lbl, x; return isTree(s, gGlobal->BOXHGROUP, lbl, x); } bool isBoxHGroup(Tree s, Tree& lbl, Tree& x) { return isTree(s, gGlobal->BOXHGROUP, lbl, x); } Tree boxVGroup(Tree lbl, Tree x) { return tree(gGlobal->BOXVGROUP, lbl, x); } bool isBoxVGroup(Tree s) { Tree lbl, x; return isTree(s, gGlobal->BOXVGROUP, lbl, x); } bool isBoxVGroup(Tree s, Tree& lbl, Tree& x) { return isTree(s, gGlobal->BOXVGROUP, lbl, x); } Tree boxTGroup(Tree lbl, Tree x) { return tree(gGlobal->BOXTGROUP, lbl, x); } bool isBoxTGroup(Tree s) { Tree lbl, x; return isTree(s, gGlobal->BOXTGROUP, lbl, x); } bool isBoxTGroup(Tree s, Tree& lbl, Tree& x) { return isTree(s, gGlobal->BOXTGROUP, lbl, x); } EXPORT Tree boxHBargraph(Tree lbl, Tree min, Tree max) { return tree(gGlobal->BOXHBARGRAPH, lbl, min, max); } bool isBoxHBargraph(Tree s) { Tree lbl, min, max; return isTree(s, gGlobal->BOXHBARGRAPH, lbl, min, max); } bool isBoxHBargraph(Tree s, Tree& lbl, Tree& min, Tree& max) { return isTree(s, gGlobal->BOXHBARGRAPH, lbl, min, max); } EXPORT Tree boxVBargraph(Tree lbl, Tree min, Tree max) { return tree(gGlobal->BOXVBARGRAPH, lbl, min, max); } bool isBoxVBargraph(Tree s) { Tree lbl, min, max; return isTree(s, gGlobal->BOXVBARGRAPH, lbl, min, max); } bool isBoxVBargraph(Tree s, Tree& lbl, Tree& min, Tree& max) { return isTree(s, gGlobal->BOXVBARGRAPH, lbl, min, max); } EXPORT Tree boxSoundfile(Tree lbl, Tree chan) { return tree(gGlobal->BOXSOUNDFILE, lbl, chan); } bool isBoxSoundfile(Tree s) { Tree label; Tree chan; return isTree(s, gGlobal->BOXSOUNDFILE, label, chan); } bool isBoxSoundfile(Tree s, Tree& label, Tree& chan) { return isTree(s, gGlobal->BOXSOUNDFILE, label, chan); } /***************************************************************************** metadata (pattern matching) *****************************************************************************/ Tree boxMetadata(Tree exp, Tree mdlist) { return tree(gGlobal->BOXMETADATA, exp, mdlist); } bool isBoxMetadata(Tree s, Tree& exp, Tree& mdlist) { return isTree(s, gGlobal->BOXMETADATA, exp, mdlist); } /***************************************************************************** pattern matching case *****************************************************************************/ /** * Prepare a "pattern" by replacing variables x by special * pattern variables ?x. * * P[x] -> ?x * P[x(e)] -> x(P[e]) * P[e(f)] -> P[e](P[f]) * P[e:f] -> P[e]:P[f] * etc. */ static Tree preparePattern(Tree box) { // cerr << "preparePattern(" << boxpp(box) << ")" << endl; int id; double r; prim0 p0; prim1 p1; prim2 p2; prim3 p3; prim4 p4; prim5 p5; Tree t1, t2, t3, ff, label, cur, min, max, step, type, name, file, arg, body, fun, args, ldef, slot, ident, rules; xtended* xt = (xtended*)getUserData(box); // Primitive elements if (xt) return box; else if (isBoxIdent(box)) return boxPatternVar(box); else if (isBoxAppl(box, fun, args)) { if (isBoxIdent(fun)) return boxAppl(fun, lmap(preparePattern, args)); else return boxAppl(preparePattern(fun), lmap(preparePattern, args)); } else if (isBoxAbstr(box, arg, body)) return box; else if (isBoxInt(box)) return box; else if (isBoxReal(box, &r)) return box; else if (isBoxWaveform(box)) return box; else if (isBoxCut(box)) return box; else if (isBoxWire(box)) return box; else if (isBoxPrim0(box, &p0)) return box; else if (isBoxPrim1(box, &p1)) return box; else if (isBoxPrim2(box, &p2)) return box; else if (isBoxPrim3(box, &p3)) return box; else if (isBoxPrim4(box, &p4)) return box; else if (isBoxPrim5(box, &p5)) return box; else if (isBoxWithLocalDef(box, body, ldef)) return boxWithLocalDef(preparePattern(body), ldef); // Foreign elements else if (isBoxFFun(box, ff)) return box; else if (isBoxFConst(box, type, name, file)) return box; else if (isBoxFVar(box, type, name, file)) return box; // Block diagram binary operator else if (isBoxSeq(box, t1, t2)) return boxSeq(preparePattern(t1), preparePattern(t2)); else if (isBoxSplit(box, t1, t2)) return boxSplit(preparePattern(t1), preparePattern(t2)); else if (isBoxMerge(box, t1, t2)) return boxMerge(preparePattern(t1), preparePattern(t2)); else if (isBoxPar(box, t1, t2)) return boxPar(preparePattern(t1), preparePattern(t2)); else if (isBoxRec(box, t1, t2)) return boxRec(preparePattern(t1), preparePattern(t2)); // Iterative block diagram construction else if (isBoxIPar(box, t1, t2, t3)) return boxIPar(t1, t2, preparePattern(t3)); else if (isBoxISeq(box, t1, t2, t3)) return boxISeq(t1, t2, preparePattern(t3)); else if (isBoxISum(box, t1, t2, t3)) return boxISum(t1, t2, preparePattern(t3)); else if (isBoxIProd(box, t1, t2, t3)) return boxIProd(t1, t2, preparePattern(t3)); // Static information else if (isBoxInputs(box, t1)) return boxInputs(preparePattern(t1)); else if (isBoxOutputs(box, t1)) return boxOutputs(preparePattern(t1)); // User interface else if (isBoxButton(box, label)) return box; else if (isBoxCheckbox(box, label)) return box; else if (isBoxVSlider(box, label, cur, min, max, step)) return box; else if (isBoxHSlider(box, label, cur, min, max, step)) return box; else if (isBoxVGroup(box, label, t1)) return boxVGroup(label, preparePattern(t1)); else if (isBoxHGroup(box, label, t1)) return boxHGroup(label, preparePattern(t1)); else if (isBoxTGroup(box, label, t1)) return boxTGroup(label, preparePattern(t1)); else if (isBoxHBargraph(box, label, min, max)) return box; else if (isBoxVBargraph(box, label, min, max)) return box; else if (isBoxNumEntry(box, label, cur, min, max, step)) return box; else if (isNil(box)) return box; else if (isList(box)) return lmap(preparePattern, box); else if (isBoxEnvironment(box)) return box; /* not expected else if (isClosure(box, abstr, genv, vis, lenv)) { fout << "closure[" << boxpp(abstr) << ", genv = " << envpp(genv) << ", lenv = " << envpp(lenv) << "]"; } */ else if (isBoxComponent(box, label)) return box; else if (isBoxAccess(box, t1, t2)) return box; /* not expected else if (isImportFile(box, label)) { fout << "import(" << tree2str(label) << ')'; } */ else if (isBoxSlot(box, &id)) return box; else if (isBoxSymbolic(box, slot, body)) return box; // Pattern Matching Extensions else if (isBoxCase(box, rules)) return box; else if (isBoxPatternVar(box, ident)) return box; // None of the previous tests succeded, then it is not a valid box else { stringstream error; error << "ERROR in preparePattern() : " << *box << " is not a valid box" << endl; throw faustexception(error.str()); } return box; } static Tree prepareRule(Tree rule) { return cons(lmap(preparePattern, hd(rule)), tl(rule)); } static Tree prepareRules(Tree rules) { return lmap(prepareRule, rules); } Tree boxCaseInternal(Tree rules) { return tree(gGlobal->BOXCASE, rules); } Tree boxCase(Tree rules) { return boxCaseInternal(prepareRules(rules)); } bool isBoxCase(Tree s) { Tree rules; return isTree(s, gGlobal->BOXCASE, rules); } bool isBoxCase(Tree s, Tree& rules) { return isTree(s, gGlobal->BOXCASE, rules); } Tree boxPatternVar(Tree id) { return tree(gGlobal->BOXPATVAR, id); } bool isBoxPatternVar(Tree s, Tree& id) { return isTree(s, gGlobal->BOXPATVAR, id); } Tree boxPatternMatcher(Automaton* a, int state, Tree env, Tree origRules, Tree revParamList) { return tree(gGlobal->BOXPATMATCHER, tree((void*)a), tree(state), env, origRules, revParamList); } bool isBoxPatternMatcher(Tree s) { Tree ta, ts, env, orig, rpl; return isTree(s, gGlobal->BOXPATMATCHER, ta, ts, env, orig, rpl); } bool isBoxPatternMatcher(Tree s, Automaton*& a, int& state, Tree& env, Tree& origRules, Tree& revParamList) { Tree ta, ts; if (isTree(s, gGlobal->BOXPATMATCHER, ta, ts, env, origRules, revParamList)) { a = (Automaton*)tree2ptr(ta); state = tree2int(ts); return true; } else { return false; } }