コード例 #1
0
ファイル: eval.cpp プロジェクト: FlatIO/faudiostream
static bool isBoxNumeric (Tree in, Tree& out)
{
    int 	numInputs, numOutputs;
    double 	x;
    int		i;
    Tree 	v, abstr, genv, vis, lenv, var, body;

    if (isBoxInt(in, &i) || isBoxReal(in, &x)) {
        out = in;
        return true;
    } else if (isClosure(in, abstr, genv, vis, lenv) && isBoxAbstr(abstr, var, body)) {
        return false;
    } else {
        v = a2sb(in);
        if ( getBoxType(v, &numInputs, &numOutputs) && (numInputs == 0) && (numOutputs == 1) ) {
            // potential numerical expression
            Tree lsignals = boxPropagateSig(gGlobal->nil, v , makeSigInputList(numInputs) );
            Tree res = simplify(hd(lsignals));
            if (isSigReal(res, &x)) 	{
                out = boxReal(x);
                return true;
            }
            if (isSigInt(res, &i))  	{
                out = boxInt(i);
                return true;
            }
        }
        return false;
    }
}
コード例 #2
0
ファイル: eval.cpp プロジェクト: FlatIO/faudiostream
static bool boxlistOutputs(Tree boxlist, int* outputs)
{
    int ins, outs;

    *outputs = 0;
    while (!isNil(boxlist) && getBoxType(hd(boxlist), &ins, &outs)) {
            *outputs += outs;
            boxlist = tl(boxlist);
    }
    return isNil(boxlist);
}
コード例 #3
0
ファイル: eval.cpp プロジェクト: FlatIO/faudiostream
/**
 * Eval a block diagram to an int.
 *
 * Eval a block diagram that represent an integer constant. This function first eval
 * a block diagram to its normal form, then check it represent a numerical value (a
 * block diagram of type : 0->1) then do a symbolic propagation and try to convert the
 * resulting signal to an int.
 * @param exp the expression to evaluate
 * @param globalDefEnv the global environment
 * @param visited list of visited definition to detect recursive definitions
 * @param localValEnv the local environment
 * @return a block diagram in normal form
 */
static int eval2int (Tree exp, Tree visited, Tree localValEnv)
{
    Tree diagram = a2sb(eval(exp, visited, localValEnv));   // pour getBoxType()
	int numInputs, numOutputs;
	getBoxType(diagram, &numInputs, &numOutputs);
	if ( (numInputs > 0) || (numOutputs != 1) ) {
		evalerror(yyfilename, yylineno, "not a constant expression of type : (0->1)", exp);
		return 1;
	} else {
		Tree lsignals = boxPropagateSig(gGlobal->nil, diagram , makeSigInputList(numInputs) );
		Tree val = simplify(hd(lsignals));
		return tree2int(val);
	}
}
コード例 #4
0
ファイル: eval.cpp プロジェクト: FlatIO/faudiostream
static bool boxlistOutputs(Tree boxlist, int* outputs)
{
    int ins, outs;

    *outputs = 0;
    while (!isNil(boxlist))
    {
        Tree b = a2sb(hd(boxlist)); // for getBoxType, suppose list of evaluated boxes
        if (getBoxType(b, &ins, &outs)) {
            *outputs += outs;
      	} else {
      		// arbitrary output arity set to 1
      		// when can't be determined
      		*outputs += 1;
      	}
        boxlist = tl(boxlist);
    }
    return isNil(boxlist);
}
コード例 #5
0
ファイル: eval.cpp プロジェクト: FlatIO/faudiostream
/**
 * Try to do a numeric simplification of a block-diagram
 */
Tree numericBoxSimplification(Tree box)
{
    int     ins, outs;
    Tree    result;
    int     i;
    double  x;

    if (!getBoxType(box, &ins, &outs)) {
        stringstream error;
        error << "ERROR in file " << __FILE__ << ':' << __LINE__ << ", Can't compute the box type of : " << *box << endl;
        throw faustexception(error.str());
    }

    if (ins==0 && outs==1) {
        // this box can potentially denote a number
        if (isBoxInt(box, &i) || isBoxReal(box, &x)) {
           result = box;
        } else {
            // propagate signals to discover if it simplifies to a number
            int     i;
            double  x;
            Tree    lsignals = boxPropagateSig(gGlobal->nil, box , makeSigInputList(0));
            Tree    s = simplify(hd(lsignals));

            if (isSigReal(s, &x)) 	{
                result = boxReal(x);
            } else if (isSigInt(s, &i))  	{
                result = boxInt(i);
            } else {
                result = insideBoxSimplification(box);
            }
        }
    } else {
        // this box can't denote a number
        result = insideBoxSimplification(box);
    }
    return result;
}
コード例 #6
0
ファイル: SampleEntry.cpp プロジェクト: drkvogel/retrasst
void __fastcall TfrmRetrieveMain::btnSaveListClick( TObject *Sender ) {
	String error;
	try {
		LPDbBoxType * boxType = getBoxType( );
		if( boxType == NULL ) {
			return;
		}
		LCDbCryoJob * job = createJob( );
		if( job == NULL ) {
			return;
		}
		Screen->Cursor = crSQLWait;
		createBoxes( *job, *boxType );

	} catch( Exception & ex ) {
		error = ex.Message;
	}
	Screen->Cursor = crDefault;
	if( error.IsEmpty( ) ) {
		ModalResult = mrOk;
	} else {
		Application->MessageBox( error.c_str( ), NULL, MB_OK );
	}
}
コード例 #7
0
ファイル: eval.cpp プロジェクト: FlatIO/faudiostream
/**
 * 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));
	}
}
コード例 #8
0
ファイル: eval.cpp プロジェクト: FlatIO/faudiostream
static Tree realeval (Tree exp, Tree visited, Tree localValEnv)
{
	//Tree 	def;
	Tree 	fun;
	Tree 	arg;
	Tree	var, num, body, ldef;
	Tree 	label;
	Tree	cur, lo, hi, step;
	Tree	e1, e2, exp2, notused, visited2, lenv2;
	Tree	rules;
	Tree	id;

	//cerr << "EVAL " << *exp << " (visited : " << *visited << ")" << endl;
    //cerr << "REALEVAL of " << *exp << endl;
	
	xtended* xt = (xtended*) getUserData(exp);

	// constants
	//-----------
	
	if ( 	xt || 
			isBoxInt(exp) || isBoxReal(exp) || 
			isBoxWire(exp) || isBoxCut(exp) ||
			isBoxPrim0(exp) || isBoxPrim1(exp) || 
			isBoxPrim2(exp) || isBoxPrim3(exp) || 
			isBoxPrim4(exp) || isBoxPrim5(exp) ||
            isBoxFFun(exp) || isBoxFConst(exp) || isBoxFVar(exp) ||
            isBoxWaveform(exp)) {
		return exp;

	// block-diagram constructors
	//---------------------------
	
	} else if (isBoxSeq(exp, e1, e2)) {
		return boxSeq(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv));

	} else if (isBoxPar(exp, e1, e2)) {
		return boxPar(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv));

	} else if (isBoxRec(exp, e1, e2)) {
		return boxRec(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv));

	} else if (isBoxSplit(exp, e1, e2)) {
		return boxSplit(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv));

	} else if (isBoxMerge(exp, e1, e2)) {
		return boxMerge(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv));
		
	// Modules
	//--------

    } else if (isBoxAccess(exp, body, var)) {
        Tree val = eval(body, visited, localValEnv);
        if (isClosure(val, exp2, notused, visited2, lenv2)) {
            // it is a closure, we have an environment to access
            return eval(closure(var,notused,visited2,lenv2), visited, localValEnv);
        } else {
            evalerror(getDefFileProp(exp), getDefLineProp(exp), "no environment to access", exp);
        }

//////////////////////en chantier////////////////////////////

    } else if (isBoxModifLocalDef(exp, body, ldef)) {
        Tree val = eval(body, visited, localValEnv);
        if (isClosure(val, exp2, notused, visited2, lenv2)) {
            // we rebuild the closure using a copy of the original environment
            // modified with some new definitions
            Tree lenv3 = copyEnvReplaceDefs(lenv2, ldef, visited2, localValEnv);
            return eval(closure(exp2,notused,visited2,lenv3), visited, localValEnv);
        } else {
            evalerror(getDefFileProp(exp), getDefLineProp(exp), "not a closure", val);
            evalerror(getDefFileProp(exp), getDefLineProp(exp), "no environment to access", exp);
        }

///////////////////////////////////////////////////////////////////

    } else if (isBoxComponent(exp, label)) {
        string  fname   = tree2str(label);
        Tree    eqlst   = gGlobal->gReader.expandlist(gGlobal->gReader.getlist(fname));
        Tree    res     = closure(boxIdent("process"), gGlobal->nil, gGlobal->nil, pushMultiClosureDefs(eqlst, gGlobal->nil, gGlobal->nil));
        setDefNameProperty(res, label);
        //cerr << "component is " << boxpp(res) << endl;
        return res;

    } else if (isBoxLibrary(exp, label)) {
        string  fname   = tree2str(label);
        Tree    eqlst   = gGlobal->gReader.expandlist(gGlobal->gReader.getlist(fname));
        Tree    res     = closure(boxEnvironment(), gGlobal->nil, gGlobal->nil, pushMultiClosureDefs(eqlst, gGlobal->nil, gGlobal->nil));
        setDefNameProperty(res, label);
        //cerr << "component is " << boxpp(res) << endl;
        return res;

	// user interface elements
	//------------------------
	
	} else if (isBoxButton(exp, label)) {
		const char* l1 = tree2str(label);
     	const char* l2 = evalLabel(l1, visited, localValEnv);
		//cout << "button label : " << l1 << " become " << l2 << endl;
		return ((l1 == l2) ? exp : boxButton(tree(l2)));

	} else if (isBoxCheckbox(exp, label)) {
		const char* l1 = tree2str(label);
    	const char* l2 = evalLabel(l1, visited, localValEnv);
		//cout << "check box label : " << l1 << " become " << l2 << endl;
		return ((l1 == l2) ? exp : boxCheckbox(tree(l2)));

	} else if (isBoxVSlider(exp, label, cur, lo, hi, step)) {
		const char* l1 = tree2str(label);
        const char* l2 = evalLabel(l1, visited, localValEnv);
		return ( boxVSlider(tree(l2),
					tree(eval2double(cur, visited, localValEnv)),
					tree(eval2double(lo, visited, localValEnv)),
					tree(eval2double(hi, visited, localValEnv)),
					tree(eval2double(step, visited, localValEnv))));

	} else if (isBoxHSlider(exp, label, cur, lo, hi, step)) {
		const char* l1 = tree2str(label);
     	const char* l2 = evalLabel(l1, visited, localValEnv);
		return ( boxHSlider(tree(l2),
					tree(eval2double(cur, visited, localValEnv)),
					tree(eval2double(lo, visited, localValEnv)),
					tree(eval2double(hi, visited, localValEnv)),
					tree(eval2double(step, visited, localValEnv))));

	} else if (isBoxNumEntry(exp, label, cur, lo, hi, step)) {
		const char* l1 = tree2str(label);
      	const char* l2 = evalLabel(l1, visited, localValEnv);
		return (boxNumEntry(tree(l2),
					tree(eval2double(cur, visited, localValEnv)),
					tree(eval2double(lo, visited, localValEnv)),
					tree(eval2double(hi, visited, localValEnv)),
					tree(eval2double(step, visited, localValEnv))));

	} else if (isBoxVGroup(exp, label, arg)) {
		const char* l1 = tree2str(label);
        const char* l2 = evalLabel(l1, visited, localValEnv);
		return boxVGroup(tree(l2),	eval(arg, visited, localValEnv) );

	} else if (isBoxHGroup(exp, label, arg)) {
		const char* l1 = tree2str(label);
 		const char* l2 = evalLabel(l1, visited, localValEnv);
		return boxHGroup(tree(l2),	eval(arg, visited, localValEnv) );

	} else if (isBoxTGroup(exp, label, arg)) {
		const char* l1 = tree2str(label);
    	const char* l2 = evalLabel(l1, visited, localValEnv);
		return boxTGroup(tree(l2),	eval(arg, visited, localValEnv) );

	} else if (isBoxHBargraph(exp, label, lo, hi)) {
		const char* l1 = tree2str(label);
    	const char* l2 = evalLabel(l1, visited, localValEnv);
		return boxHBargraph(tree(l2),
					tree(eval2double(lo, visited, localValEnv)),
					tree(eval2double(hi, visited, localValEnv)));

	} else if (isBoxVBargraph(exp, label, lo, hi)) {
		const char* l1 = tree2str(label);
  		const char* l2 = evalLabel(l1, visited, localValEnv);
		return boxVBargraph(tree(l2),
					tree(eval2double(lo, visited, localValEnv)),
					tree(eval2double(hi, visited, localValEnv)));

	// lambda calculus
	//----------------
		
	} else if (isBoxIdent(exp)) {
		return evalIdDef(exp, visited, localValEnv);

	} else if (isBoxWithLocalDef(exp, body, ldef)) {
		return eval(body, visited, pushMultiClosureDefs(ldef, visited, localValEnv));
	
	} else if (isBoxAppl(exp, fun, arg)) {
        return applyList( eval(fun, visited, localValEnv),
						  revEvalList(arg, visited, localValEnv) );

    } else if (isBoxAbstr(exp)) {
        // it is an abstraction : return a closure
        return closure(exp, gGlobal->nil, visited, localValEnv);

    } else if (isBoxEnvironment(exp)) {
        // environment : return also a closure
        return closure(exp, gGlobal->nil, visited, localValEnv);

	} else if (isClosure(exp, exp2, notused, visited2, lenv2)) {

        if (isBoxAbstr(exp2)) {
            // a 'real' closure
            return closure(exp2, gGlobal->nil, setUnion(visited,visited2), lenv2);
        } else if (isBoxEnvironment(exp2)) {
            // a 'real' closure
            return closure(exp2, gGlobal->nil, setUnion(visited,visited2), lenv2);
        } else {
			// it was a suspended evaluation
			return eval(exp2, setUnion(visited,visited2), lenv2);
		}

	// Algorithmic constructions
	//--------------------------
	
	} else if (isBoxIPar(exp, var, num, body)) {
		int n = eval2int(num, visited, localValEnv);
		return iteratePar(var, n, body, visited, localValEnv);

	} else if (isBoxISeq(exp, var, num, body)) {
		int n = eval2int(num, visited, localValEnv);
		return iterateSeq(var, n, body, visited, localValEnv);

	} else if (isBoxISum(exp, var, num, body)) {
		int n = eval2int(num, visited, localValEnv);
		return iterateSum(var, n, body, visited, localValEnv);

    } else if (isBoxIProd(exp, var, num, body)) {
        int n = eval2int(num, visited, localValEnv);
        return iterateProd(var, n, body, visited, localValEnv);

    // static
    } else if (isBoxInputs(exp, body)) {
        int ins, outs;
        Tree b = a2sb(eval(body, visited, localValEnv));
        if (getBoxType (b, &ins, &outs)) {
            return boxInt(ins);
        } else {
            stringstream error;
            error << "ERROR : can't evaluate ' : " << *exp << endl;
            throw faustexception(error.str());
        }
  
    } else if (isBoxOutputs(exp, body)) {
        int ins, outs;
        Tree b = a2sb(eval(body, visited, localValEnv));
        if (getBoxType (b, &ins, &outs)) {
            return boxInt(outs);
        } else {
            stringstream error;
            error << "ERROR : can't evaluate ' : " << *exp << endl;
            throw faustexception(error.str());
        }

	} else if (isBoxSlot(exp)) 		{ 
		return exp; 
	
	} else if (isBoxSymbolic(exp)) 	{
	 	return exp;

	// Pattern matching extension
	//---------------------------
	
	} else if (isBoxCase(exp, rules)) {
        return evalCase(rules, localValEnv);

	} else if (isBoxPatternVar(exp, id)) {
		return exp;
		//return evalIdDef(id, visited, localValEnv);

	} else if (isBoxPatternMatcher(exp)) {
		return exp;

    } else {
        stringstream error;
        error << "ERROR : EVAL doesn't intercept : " << *exp << endl;
        throw faustexception(error.str());
    }
	return NULL;
}
コード例 #9
0
ファイル: propagate.cpp プロジェクト: EBone/Faust
siglist realPropagate (Tree slotenv, Tree path, Tree box, const siglist&  lsig)
{
	int		i;
	double	r;
	prim0	p0;
	prim1	p1;
	prim2	p2;
	prim3	p3;
	prim4	p4;
	prim5	p5;
	
    Tree	t1, t2, ff, label, cur, min, max, step, type, name, file, slot, body, chan;
    tvec    wf;
	
	
	xtended* xt = (xtended*)getUserData(box);
	
	// Extended Primitives
	
	if (xt)	{
		faustassert(lsig.size() == xt->arity());
		return makeList(xt->computeSigOutput(lsig));
	}
		
	// Numbers and Constants
	
	else if (isBoxInt(box, &i)) 	{ 
		faustassert(lsig.size()==0); 
		return makeList(sigInt(i)); 
	}
	else if (isBoxReal(box, &r)) 	{ 
		faustassert(lsig.size()==0); 
		return makeList(sigReal(r)); 
	}

    // A Waveform has two outputs it size and a period signal representing its content

    else if (isBoxWaveform(box)) 	{
        faustassert(lsig.size()==0);
        const tvec br = box->branches();
        return listConcat(makeList(sigInt(int(br.size()))), makeList(sigWaveform(br)));
    }

    else if (isBoxFConst(box, type, name, file))    { 
        faustassert(lsig.size()==0); 
        return makeList(sigFConst(type, name, file)); 
    }
    
    else if (isBoxFVar(box, type, name, file))    { 
        faustassert(lsig.size()==0); 
        return makeList(sigFVar(type, name, file)); 
    }
	
	// Wire and Cut
	
	else if (isBoxCut(box)) 				{ 
		faustassert(lsig.size()==1); 
		return siglist(); 
	}
	
	else if (isBoxWire(box)) 				{ 
		faustassert(lsig.size()==1); 
		return lsig;  
	}
	
	// Slots and Symbolic Boxes
	
	else if (isBoxSlot(box)) 				{ 
		Tree sig;
		faustassert(lsig.size()==0); 
		if (!searchEnv(box,sig,slotenv)) {
			// test YO simplification des diagrames
			//fprintf(stderr, "propagate : internal error (slot undefined)\n");
			sig = sigInput(++gGlobal->gDummyInput);
		}
		return makeList(sig);
	}
	
	else if (isBoxSymbolic(box, slot, body)) 				{ 
		faustassert(lsig.size()>0); 
		return propagate(pushEnv(slot,lsig[0],slotenv), path, body, listRange(lsig, 1, (int)lsig.size()));
	}
	
	// Primitives
	
	else if (isBoxPrim0(box, &p0)) 			{ 
		faustassert(lsig.size()==0); 
		return makeList(p0());
	}
	
	else if (isBoxPrim1(box, &p1)) 				{ 
		faustassert(lsig.size()==1); 
		return makeList(p1(lsig[0]));
	}
	
	else if (isBoxPrim2(box, &p2)) 				{ 
//		printf("prim2 recoit : "); print(lsig); printf("\n");
		faustassert(lsig.size()==2);
        if (p2 == &sigEnable) {
            if (gGlobal->gEnableFlag) {
                // special case for sigEnable that requires a transformation
                // enable(X,Y) -> sigEnable(X*Y, Y>0)
                return makeList(sigEnable( sigMul(lsig[0],lsig[1]), sigGT(lsig[1],sigReal(0.0))));
            } else {
                // We gEnableFlag is false we replace enable by a simple multiplication
                return makeList(sigMul(lsig[0],lsig[1]));
            }
        } else if (p2 == &sigControl) {
            if (gGlobal->gEnableFlag) {
                // special case for sigEnable that requires a transformation
                // enable(X,Y) -> sigEnable(X*Y, Y>0)
                return makeList(sigEnable( lsig[0], lsig[1]));
            } else {
                // We gEnableFlag is false we replace control by identity function
                return makeList(lsig[0]);
            }
        }
        return makeList( p2(lsig[0],lsig[1]) );
	}
	
	else if (isBoxPrim3(box, &p3)) 				{ 
		faustassert(lsig.size()==3); 
		return makeList(p3(lsig[0],lsig[1],lsig[2]));
	}
	
	else if (isBoxPrim4(box, &p4)) 				{ 
		faustassert(lsig.size()==4); 
		return makeList(p4(lsig[0],lsig[1],lsig[2],lsig[3]));
	}
	
	else if (isBoxPrim5(box, &p5)) 				{ 
		faustassert(lsig.size()==5); 
		return makeList(p5(lsig[0],lsig[1],lsig[2],lsig[3],lsig[4]));
	}
	
	else if (isBoxFFun(box, ff)) 				{ 
		//cerr << "propagate en boxFFun of arity " << ffarity(ff) << endl;
		faustassert(int(lsig.size())==ffarity(ff)); 
		return makeList(sigFFun(ff, listConvert(lsig)));  
	}
	
	// User Interface Widgets
	
	else if (isBoxButton(box, label)) 	{ 
		faustassert(lsig.size()==0); 
		return makeList(sigButton(normalizePath(cons(label, path)))); 
	}
	
	else if (isBoxCheckbox(box, label)) 	{ 
		faustassert(lsig.size()==0); 
		return makeList(sigCheckbox(normalizePath(cons(label, path)))); 
	}
	
	else if (isBoxVSlider(box, label, cur, min, max, step)) 	{ 
		faustassert(lsig.size()==0); 
		return makeList(sigVSlider(normalizePath(cons(label, path)), cur, min, max, step)); 
	}
	
	else if (isBoxHSlider(box, label, cur, min, max, step)) 	{ 
		faustassert(lsig.size()==0); 
		return makeList(sigHSlider(normalizePath(cons(label, path)), cur, min, max, step)); 
	}

	else if (isBoxNumEntry(box, label, cur, min, max, step)) 	{ 
		faustassert(lsig.size()==0); 
		return makeList(sigNumEntry(normalizePath(cons(label, path)), cur, min, max, step)); 
	}
	
	else if (isBoxVBargraph(box, label, min, max)) 	{ 
		faustassert(lsig.size()==1); 
		return makeList(sigVBargraph(normalizePath(cons(label, path)), min, max, lsig[0])); 
	}
	
	else if (isBoxHBargraph(box, label, min, max)) 	{ 
		faustassert(lsig.size()==1); 
		return makeList(sigHBargraph(normalizePath(cons(label, path)), min, max, lsig[0])); 
	}
	
	else if (isBoxSoundfile(box, label, chan)) 	{ 
		faustassert(lsig.size()==1);
        Tree fullpath = normalizePath(cons(label, path));
        Tree soundfile = sigSoundfile(fullpath);
        int c = tree2int(chan);
        siglist lsig2(c+3);
        lsig2[0] = sigSoundfileLength(soundfile);
        lsig2[1] = sigSoundfileRate(soundfile);
        lsig2[2] = sigSoundfileChannels(soundfile);

		// compute bound limited read index : int(max(0, min(ridx,length-1)))
		Tree ridx = sigIntCast(tree(gGlobal->gMaxPrim->symbol(), sigInt(0), tree(gGlobal->gMinPrim->symbol(), lsig[0], sigAdd(lsig2[0],sigInt(-1)))));
		for (int i = 0; i<c; i++) {
			lsig2[i+3] = sigSoundfileBuffer(soundfile, sigInt(i), ridx);
		}
		return lsig2; 
	}
	
	// User Interface Groups
	
	else if (isBoxVGroup(box, label, t1)) 	{ 
		return propagate(slotenv,cons(cons(tree(0),label), path), t1, lsig); 
	}
	
	else if (isBoxHGroup(box, label, t1)) 	{ 
		return propagate(slotenv, cons(cons(tree(1),label), path), t1, lsig); 
	}
	
	else if (isBoxTGroup(box, label, t1)) 	{ 
		return propagate(slotenv, cons(cons(tree(2),label), path), t1, lsig); 
	}
	
	// Block Diagram Composition Algebra
	
	else if (isBoxSeq(box, t1, t2)) 	{ 
		int in1, out1, in2, out2;
		getBoxType(t1, &in1, &out1);
		getBoxType(t2, &in2, &out2);

        faustassert(out1==in2);

		if (out1 == in2) {
			return propagate(slotenv, path, t2, propagate(slotenv, path,t1,lsig));
		} else if (out1 > in2) {
			siglist lr = propagate(slotenv, path, t1,lsig);
			return listConcat(propagate(slotenv, path, t2, listRange(lr, 0, in2)), listRange(lr, in2, out1));
		} else {
			return propagate(slotenv, path, t2, listConcat( propagate(slotenv, path, t1, listRange(lsig,0,in1)), listRange(lsig,in1,in1+in2-out1)));
		}
	}
	
	else if (isBoxPar(box, t1, t2)) 	{ 
		int in1, out1, in2, out2;
		getBoxType(t1, &in1, &out1);
		getBoxType(t2, &in2, &out2);
			
		return listConcat(propagate(slotenv, path, t1, listRange(lsig, 0,  in1)),
                          propagate(slotenv, path, t2, listRange(lsig, in1, in1+in2)));
	}
	
	else if (isBoxSplit(box, t1, t2)) 	{ 
		int in1, out1, in2, out2;
		getBoxType(t1, &in1, &out1);
		getBoxType(t2, &in2, &out2);
		
		siglist l1 = propagate(slotenv, path, t1, lsig);
		siglist l2 = split(l1, in2);
		return propagate(slotenv, path, t2, l2);
	}
	
	else if (isBoxMerge(box, t1, t2)) 	{ 
		int in1, out1, in2, out2;
		getBoxType(t1, &in1, &out1);
		getBoxType(t2, &in2, &out2);
		
		siglist l1 = propagate(slotenv, path, t1, lsig);
		siglist l2 = mix(l1, in2);
		return propagate(slotenv, path, t2, l2);
	}

    else if (isBoxRec(box, t1, t2)) 	{
        // Bug Corrected
        int in1, out1, in2, out2;
        getBoxType(t1, &in1, &out1);
        getBoxType(t2, &in2, &out2);

        Tree slotenv2 = lift(slotenv); // the environment must also be lifted

        siglist l0 = makeMemSigProjList(ref(1), in2);
        siglist l1 = propagate(slotenv2, path, t2, l0);
        siglist l2 = propagate(slotenv2, path, t1, listConcat(l1,listLift(lsig)));
		siglist l3 = (gGlobal->gFTZMode > 0) ? wrapWithFTZ(l2) : l2;
        Tree g = rec(listConvert(l3));
        return makeSigProjList(g, out1);
    }

    stringstream error;
    error << "ERROR in file " << __FILE__ << ':' << __LINE__ << ", unrecognised box expression : " << boxpp(box) << endl;
    throw faustexception(error.str());

	return siglist();
}