コード例 #1
0
ファイル: description.cpp プロジェクト: Ace17/faust
void Description::addGroup(int level, Tree t)
{
  Tree label, elements, varname, sig;
  const char* groupnames[] =
  {
    "vgroup", "hgroup", "tgroup"
  };

  if(isUiFolder(t, label, elements))
  {
    const int orient = tree2int(left(label));

    addLayoutLine(level, subst("<group type=\"$0\">", groupnames[orient]));
    addLayoutLine(level + 1, subst("<label>$0</label>", checkNullLabel(t, xmlize(tree2str(right(label))), false)));

    while(!isNil(elements))
    {
      addGroup(level + 1, right(hd(elements)));
      elements = tl(elements);
    }

    addLayoutLine(level, "</group>");
  }
  else if(isUiWidget(t, label, varname, sig))
  {
    int w = addWidget(label, varname, sig);
    addLayoutLine(level, subst("<widgetref id=\"$0\" />", T(w)));
  }
  else
  {
    fprintf(stderr, "error in user interface generation 2\n");
    exit(1);
  }
}
コード例 #2
0
ファイル: boxes.cpp プロジェクト: EBone/Faust
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;
	}
}
コード例 #3
0
/**
 * retrieve the order annotation (between 0 and 3) of a signal.
 * (compute the order the first time). Orders have the following meanings
 *	0 : numbers
 *	1 : constants
 *	2 : user interface values
 *	3 : audio values
 * @param sig the signal we want to know the order
 * @return the order number
 */
int getSigOrder(Tree sig)
{
	Tree tt;
	if (getProperty(sig, ORDERPROP, tt)) { 
		return tree2int(tt); 
	} else {
		int order = infereSigOrder(sig);
		setProperty(sig, ORDERPROP, tree(order));
		return order;
	}
}	
コード例 #4
0
ファイル: compile.cpp プロジェクト: harryhaaren/faust
/**
 * Generate buildUserInterface C++ lines of code corresponding 
 * to user interface element t
 */
void Compiler::generateUserInterfaceTree(Tree t)
{
	Tree label, elements, varname, sig;
    
    
	if (isUiFolder(t, label, elements)) {
		const int orient = tree2int(left(label));
        // Empty labels will be renamed with a 0xABCD (address) kind of name that is ignored and not displayed by UI architectures
        const char* str = tree2str(right(label));  
        const char* model;
          
        // extract metadata from group label str resulting in a simplifiedLabel
		// and metadata declarations for fictive zone at address 0
        string  simplifiedLabel;
        map<string, set<string> >   metadata;
        extractMetadata(str, simplifiedLabel, metadata);

        // add metadata if any
        for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) {
            const string& key = i->first;
            const set<string>& values = i->second;
            for (set<string>::const_iterator j = values.begin(); j != values.end(); j++) {
                fClass->addUICode(subst("interface->declare($0, \"$1\", \"$2\");", "0", wdel(key) ,wdel(*j)));
                fJSON.declare(NULL, wdel(key).c_str(), wdel(*j).c_str());
            }
        }
        
        //-----------------
		switch (orient) {
			case 0 : model = "interface->openVerticalBox(\"$0\");"; fJSON.openVerticalBox(checkNullLabel(t, simplifiedLabel).c_str()); break;
			case 1 : model = "interface->openHorizontalBox(\"$0\");"; fJSON.openHorizontalBox(checkNullLabel(t, simplifiedLabel).c_str()); break;
			case 2 : model = "interface->openTabBox(\"$0\");"; fJSON.openTabBox(checkNullLabel(t, simplifiedLabel).c_str()); break;
			default :
                fprintf(stderr, "error in user interface generation 1\n");
				exit(1);
		}
        fClass->addUICode(subst(model, checkNullLabel(t, simplifiedLabel)));
		generateUserInterfaceElements(elements);
		fClass->addUICode("interface->closeBox();");
        fJSON.closeBox();

	} else if (isUiWidget(t, label, varname, sig)) {

		generateWidgetCode(label, varname, sig);

	} else {

		fprintf(stderr, "error in user interface generation 2\n");
		exit(1);

	}
}
コード例 #5
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);
	}
}
コード例 #6
0
ファイル: ppbox.cpp プロジェクト: OpenDAWN/Faust
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;
}
コード例 #7
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();
}