ostream& boxpp::print (ostream& fout) const { int i, 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, abstr, genv, vis, lenv, ldef, slot, ident, rules; const char* str; xtended* xt = (xtended*) getUserData(box); // primitive elements if (xt) fout << xt->name(); else if (isBoxInt(box, &i)) fout << i; else if (isBoxReal(box, &r)) fout << T(r); else if (isBoxCut(box)) fout << '!'; else if (isBoxWire(box)) fout << '_'; else if (isBoxIdent(box, &str)) fout << str; else if (isBoxPrim0(box, &p0)) fout << prim0name(p0); else if (isBoxPrim1(box, &p1)) fout << prim1name(p1); else if (isBoxPrim2(box, &p2)) fout << prim2name(p2); else if (isBoxPrim3(box, &p3)) fout << prim3name(p3); else if (isBoxPrim4(box, &p4)) fout << prim4name(p4); else if (isBoxPrim5(box, &p5)) fout << prim5name(p5); else if (isBoxAbstr(box,arg,body)) fout << "\\" << boxpp(arg) << ".(" << boxpp(body) << ")"; else if (isBoxAppl(box, fun, args)) fout << boxpp(fun) << boxpp(args) ; else if (isBoxWithLocalDef(box, body, ldef)) fout << boxpp(body) << " with { " << envpp(ldef) << " }"; // foreign elements else if (isBoxFFun(box, ff)) { fout << "ffunction(" << type2str(ffrestype(ff)); Tree namelist = nth(ffsignature(ff),1); char sep = ' '; for (int i = 0; i < gFloatSize; i++) { fout << sep << tree2str(nth(namelist,i)); sep = '|'; } sep = '('; for (int i = 0; i < ffarity(ff); i++) { fout << sep << type2str(ffargtype(ff, i)); sep = ','; } fout << ')'; fout << ',' << ffincfile(ff) << ',' << fflibfile(ff) << ')'; } else if (isBoxFConst(box, type, name, file)) fout << "fconstant(" << type2str(tree2int(type)) << ' ' << tree2str(name) << ", " << tree2str(file) << ')'; else if (isBoxFVar(box, type, name, file)) fout << "fvariable(" << type2str(tree2int(type)) << ' ' << tree2str(name) << ", " << tree2str(file) << ')'; // block diagram binary operator else if (isBoxSeq(box, t1, t2)) streambinop(fout, t1, " : ", t2, 1, priority); else if (isBoxSplit(box, t1, t2)) streambinop(fout, t1, "<:", t2, 1, priority); else if (isBoxMerge(box, t1, t2)) streambinop(fout, t1, ":>", t2, 1, priority); else if (isBoxPar(box, t1, t2)) streambinop(fout, t1,",",t2, 2, priority); else if (isBoxRec(box, t1, t2)) streambinop(fout, t1,"~",t2, 4, priority); // iterative block diagram construction else if (isBoxIPar(box, t1, t2, t3)) fout << "par(" << boxpp(t1) << ", " << boxpp(t2) << ") {" << boxpp(t3) << "}"; else if (isBoxISeq(box, t1, t2, t3)) fout << "seq(" << boxpp(t1) << ", " << boxpp(t2) << ") {" << boxpp(t3) << "}"; else if (isBoxISum(box, t1, t2, t3)) fout << "sum(" << boxpp(t1) << ", " << boxpp(t2) << ") {" << boxpp(t3) << "}"; else if (isBoxIProd(box, t1, t2, t3)) fout << "prod(" << boxpp(t1) << ", " << boxpp(t2) << ") {" << boxpp(t3) << "}"; else if (isBoxInputs(box, t1)) fout << "inputs(" << boxpp(t1) << ")"; else if (isBoxOutputs(box, t1)) fout << "outputs(" << boxpp(t1) << ")"; // user interface else if (isBoxButton(box, label)) fout << "button(" << tree2quotedstr(label) << ')'; else if (isBoxCheckbox(box, label)) fout << "checkbox(" << tree2quotedstr(label) << ')'; else if (isBoxVSlider(box, label, cur, min, max, step)) { fout << "vslider(" << tree2quotedstr(label) << ", " << boxpp(cur) << ", " << boxpp(min) << ", " << boxpp(max) << ", " << boxpp(step)<< ')'; } else if (isBoxHSlider(box, label, cur, min, max, step)) { fout << "hslider(" << tree2quotedstr(label) << ", " << boxpp(cur) << ", " << boxpp(min) << ", " << boxpp(max) << ", " << boxpp(step)<< ')'; } else if (isBoxVGroup(box, label, t1)) { fout << "vgroup(" << tree2quotedstr(label) << ", " << boxpp(t1, 0) << ')'; } else if (isBoxHGroup(box, label, t1)) { fout << "hgroup(" << tree2quotedstr(label) << ", " << boxpp(t1, 0) << ')'; } else if (isBoxTGroup(box, label, t1)) { fout << "tgroup(" << tree2quotedstr(label) << ", " << boxpp(t1, 0) << ')'; } else if (isBoxHBargraph(box, label, min, max)) { fout << "hbargraph(" << tree2quotedstr(label) << ", " << boxpp(min) << ", " << boxpp(max) << ')'; } else if (isBoxVBargraph(box, label, min, max)) { fout << "vbargraph(" << tree2quotedstr(label) << ", " << boxpp(min) << ", " << boxpp(max) << ')'; } else if (isBoxNumEntry(box, label, cur, min, max, step)) { fout << "nentry(" << tree2quotedstr(label) << ", " << boxpp(cur) << ", " << boxpp(min) << ", " << boxpp(max) << ", " << boxpp(step)<< ')'; } else if (isNil(box)) { fout << "()" ; } else if (isList(box)) { Tree l = box; char sep = '('; do { fout << sep << boxpp(hd(l)); sep = ','; l = tl(l); } while (isList(l)); fout << ')'; } else if (isBoxWaveform(box)) { fout << "waveform"; char sep = '{'; for (int i=0; i<box->arity(); i++) { fout << sep << boxpp(box->branch(i)); sep = ','; } fout << '}'; /* size_t n = box->arity(); if (n < 6) { // small waveform, print all data fout << "waveform"; char sep = '{'; for (size_t i=0; i<n; i++) { fout << sep << boxpp(box->branch(i)); sep = ','; } fout << '}'; } else { // large waveform print only first and last values fout << "waveform{" << box->branch(0) << ", ..<" << n-2 << ">..," << box->branch(n-1) << "}"; } */ } else if (isBoxEnvironment(box)) { fout << "environment"; } else if (isClosure(box, abstr, genv, vis, lenv)) { fout << "closure[" << boxpp(abstr) << ", genv = " << envpp(genv) << ", lenv = " << envpp(lenv) << "]"; } else if (isBoxComponent(box, label)) { fout << "component(" << tree2quotedstr(label) << ')'; } else if (isBoxAccess(box, t1, t2)) { fout << boxpp(t1) << '.' << boxpp(t2); } else if (isImportFile(box, label)) { fout << "import(" << tree2quotedstr(label) << ')'; } else if (isBoxSlot(box, &id)) { //fout << "#" << id; fout << "x" << id; } else if (isBoxSymbolic(box, slot, body)) { fout << "\\(" << boxpp(slot) << ").(" << boxpp(body) << ")"; } // Pattern Matching Extensions else if (isBoxCase(box, rules)) { fout << "case {"; while (!isNil(rules)) { printRule(fout, hd(rules)); rules = tl(rules); } fout << "}"; } #if 1 // more useful for debugging output else if (isBoxPatternVar(box, ident)) { fout << "<" << boxpp(ident) << ">"; } #else // beautify messages involving lhs patterns else if (isBoxPatternVar(box, ident)) { fout << boxpp(ident); } #endif else if (isBoxPatternMatcher(box)) { fout << "PM[" << box << "]"; } else if (isBoxError(box)) { fout << "ERROR"; } //else if (isImportFile(box, filename)) { // printf("filename %s\n", tree2str(filename)); // fout << tree2quotedstr(filename); //} // None of the previous tests succeded, then it is not a valid box else { cerr << "Error in box::print() : " << *box << " is not a valid box" << endl; exit(1); } return fout; }
/** * Apply a function to a list of arguments. * Apply a function F to a list of arguments (a,b,c,...). * F can be either a closure over an abstraction, or a * pattern matcher. If it is not the case then we have : * F(a,b,c,...) ==> (a,b,c,...):F * * @param fun the function to apply * @param larg the list of arguments * @return the resulting expression in normal form */ static Tree applyList (Tree fun, Tree larg) { Tree abstr; Tree globalDefEnv; Tree visited; Tree localValEnv; Tree envList; Tree originalRules; Tree revParamList; Tree id; Tree body; Automaton* automat; int state; prim2 p2; //cerr << "applyList (" << *fun << ", " << *larg << ")" << endl; if (isNil(larg)) return fun; if (isBoxError(fun) || isBoxError(larg)) { return boxError(); } if (isBoxPatternMatcher(fun, automat, state, envList, originalRules, revParamList)) { Tree result; int state2; vector<Tree> envVect; list2vec(envList, envVect); //cerr << "applyList/apply_pattern_matcher(" << automat << "," << state << "," << *hd(larg) << ")" << endl; state2 = apply_pattern_matcher(automat, state, hd(larg), result, envVect); //cerr << "state2 = " << state2 << "; result = " << *result << endl; if (state2 >= 0 && isNil(result)) { // we need to continue the pattern matching return applyList( boxPatternMatcher(automat, state2, vec2list(envVect), originalRules, cons(hd(larg),revParamList)), tl(larg) ); } else if (state2 < 0) { stringstream error; error << "ERROR : pattern matching failed, no rule of " << boxpp(boxCase(originalRules)) << " matches argument list " << boxpp(reverse(cons(hd(larg), revParamList))) << endl; throw faustexception(error.str()); } else { // Pattern Matching was succesful // the result is a closure that we need to evaluate. if (isClosure(result, body, globalDefEnv, visited, localValEnv)) { // why ??? return simplifyPattern(eval(body, nil, localValEnv)); //return eval(body, nil, localValEnv); return applyList(eval(body, gGlobal->nil, localValEnv), tl(larg)); } else { cerr << "wrong result from pattern matching (not a closure) : " << boxpp(result) << endl; return boxError(); } } } if (!isClosure(fun, abstr, globalDefEnv, visited, localValEnv)) { // principle : f(a,b,c,...) ==> (a,b,c,...):f int ins, outs; // check arity of function Tree efun = a2sb(fun); //cerr << "TRACEPOINT 1 : " << boxpp(efun) << endl; if (!getBoxType(efun, &ins, &outs)) { // on laisse comme ca pour le moment // we can't determine the input arity of the expression // hope for the best return boxSeq(larg2par(larg), fun); } // check arity of arg list if (!boxlistOutputs(larg, &outs)) { // we don't know yet the output arity of larg. Therefore we can't // do any arity checking nor add _ to reach the required number of arguments // cerr << "warning : can't infere the type of : " << boxpp(larg) << endl; return boxSeq(larg2par(larg), fun); } if (outs > ins) { stringstream error; error << "too much arguments : " << outs << ", instead of : " << ins << endl; error << "when applying : " << boxpp(fun) << endl << "to : " << boxpp(larg) << endl; throw faustexception(error.str()); } if ((outs == 1) && (( isBoxPrim2(fun, &p2) && (p2 != sigPrefix)) || (getUserData(fun) && ((xtended*)getUserData(fun))->isSpecialInfix()))) { // special case : /(3) ==> _,3 : / Tree larg2 = concat(nwires(ins-outs), larg); return boxSeq(larg2par(larg2), fun); } else { Tree larg2 = concat(larg, nwires(ins-outs)); return boxSeq(larg2par(larg2), fun); } } if (isBoxEnvironment(abstr)) { evalerrorbox(yyfilename, -1, "an environment can't be used as a function", fun); } if (!isBoxAbstr(abstr, id, body)) { evalerror(yyfilename, -1, "(internal) not an abstraction inside closure", fun); } // try to synthetise a name from the function name and the argument name { Tree arg = eval(hd(larg), visited, localValEnv); Tree narg; if ( isBoxNumeric(arg,narg) ) { arg = narg; } Tree f = eval(body, visited, pushValueDef(id, arg, localValEnv)); Tree fname; if (getDefNameProperty(fun, fname)) { stringstream s; s << tree2str(fname); if (!gGlobal->gSimpleNames) s << "(" << boxpp(arg) << ")"; setDefNameProperty(f, s.str()); } return applyList(f, tl(larg)); } }