Stephane, Yann, Can I suggest another feature? The patch is not for inclusion yet, but I'd like to discuss the idea / implementation.
It adds the new keyword `meta` which returns the environment with 2 primitives (so far): 1. serial(sig) - returns sig->serial() 2. order(sig) - getSigOrder(sig) Note that they compute the returned value at compile time. Why the environment? Because this way it is very easy to add more primitives (e.g. typeof(sig) which returns kBool / kInt / kReal) using a single keyword. Why do we want this feature? Well, I certainly do ;) but I do not have a simple and convincing example. ------------------------------------------------------------------------------- But let me provide a basic example even if it is not convincing. Consider: process(x,y) = atan2(x,x), atan2(x,y); it compiles to float fTemp0 = float(input0[i0]); output0[i0] = FAUSTFLOAT(std::atan2(fTemp0, fTemp0)); output1[i0] = FAUSTFLOAT(std::atan2(fTemp0, float(input1[i0]))); note that atan2(fTemp0, fTemp0) == %pi/4 (lets ignore the fTemp0 == 0 case for the sake of simplicity), so this code is suboptimal. Let's try to improve this code: my_atan2(a,b) = select2(a == b, atan2(a,b), ma.PI/4); process(x,y) = my_atan2(x,x), my_atan2(x,y); result: float fTemp0 = float(input0[i0]); output0[i0] = FAUSTFLOAT(((fTemp0 == fTemp0) ? 0.7853982f : std::atan2(fTemp0, fTemp0))); float fTemp1 = float(input1[i0]); output1[i0] = FAUSTFLOAT(((fTemp0 == fTemp1) ? 0.7853982f : std::atan2(fTemp0, fTemp1))); doesn't look very good although the compiler will optimize out the 1st `fTemp0 == fTemp0` check. Now let's use meta.serial: same_signal(a,b) = meta.serial(a) == meta.serial(b); my_atan2(a,b) = select2(same_signal(a,b), atan2(a,b), ma.PI/4); process(x,y) = my_atan2(x,x), my_atan2(x,y); result: output0[i0] = FAUSTFLOAT(0.7853982f); output1[i0] = FAUSTFLOAT(std::atan2(float(input0[i0]), float(input1[i0]))); Oleg. --- compiler/extended/metaprim.hh | 94 +++++++++++++++++++++++++++++++++++ compiler/global.cpp | 3 ++ compiler/global.hh | 2 + compiler/parser/faustlexer.l | 2 + compiler/parser/faustparser.y | 3 ++ 5 files changed, 104 insertions(+) create mode 100644 compiler/extended/metaprim.hh diff --git a/compiler/extended/metaprim.hh b/compiler/extended/metaprim.hh new file mode 100644 index 000000000..20cc5982e --- /dev/null +++ b/compiler/extended/metaprim.hh @@ -0,0 +1,94 @@ +/************************************************************************ + ************************************************************************ + 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 Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ************************************************************************ + ************************************************************************/ + +#include "xtended.hh" +#include "simplify.hh" +#include "sigorderrules.hh" + +class MetaPrim : public xtended { + private: + int fOp; + public: + MetaPrim(int op, const char *name) : xtended(name), fOp(op) {} + + virtual unsigned int arity() { return 1; } + + virtual bool needCache() { return true; } + + virtual int infereSigOrder(const std::vector<int>& args) { return 0; } + + virtual Tree computeSigOutput(const std::vector<Tree>& args) + { + Tree sig = simplify(args[0]); + int ret = -1; + + switch (fOp) { + case 0: + ret = sig->serial(); + break; + case 1: + ret = getSigOrder(sig); + break; + default: + faustassert(false); + } + + return tree(ret); + } + + virtual ::Type infereSigType(ConstTypes args) + { + faustassert(false); return 0; + } + + virtual ValueInst* generateCode(CodeContainer* container, Values& args, ::Type result, ConstTypes types) + { + faustassert(false); return 0; + } + + virtual std::string generateCode(Klass* klass, const std::vector<std::string>& args, ConstTypes types) + { + faustassert(false); return 0; + } + + virtual std::string generateLateq(Lateq* lateq, const std::vector<std::string>& args, ConstTypes types) + { + return "TODO"; + } +}; + +static Tree add_meta_def(Tree defs, int op, const char *d_n) +{ + Tree id = boxIdent(d_n); + std::string x_n = std::string("meta_") + d_n; + MetaPrim *meta = new MetaPrim(op, x_n.c_str()); + return cons(cons(id, meta->box()), defs); +} + +static Tree mkMetaEnv() +{ + Tree defs = gGlobal->nil; + + defs = add_meta_def(defs, 0, "serial"); + defs = add_meta_def(defs, 1, "order"); + + return boxWithLocalDef(boxEnvironment(), defs); +} diff --git a/compiler/global.cpp b/compiler/global.cpp index 29af5eb9d..6636eac92 100644 --- a/compiler/global.cpp +++ b/compiler/global.cpp @@ -48,6 +48,7 @@ #include "sourcereader.hh" #include "sqrtprim.hh" #include "tanprim.hh" +#include "metaprim.hh" #include "tree.hh" #include "occur.hh" #include "enrobage.hh" @@ -592,6 +593,8 @@ void global::init() // Predefined nil tree nil = tree(NIL); + gMetaEnv = mkMetaEnv(); + PROCESS = symbol("process"); BOXTYPEPROP = tree(symbol("boxTypeProp")); diff --git a/compiler/global.hh b/compiler/global.hh index e8ced28c8..dbb001e7c 100644 --- a/compiler/global.hh +++ b/compiler/global.hh @@ -322,6 +322,8 @@ struct global { xtended* gAtan2Prim; xtended* gAsinPrim; + Tree gMetaEnv; + // Signals Sym BOXIDENT; Sym BOXCUT; diff --git a/compiler/parser/faustlexer.l b/compiler/parser/faustlexer.l index c92210cb5..c9342848f 100644 --- a/compiler/parser/faustlexer.l +++ b/compiler/parser/faustlexer.l @@ -198,6 +198,8 @@ NSID {ID}("::"{ID})* "sum" return ISUM; "prod" return IPROD; +"meta" return META; + "inputs" return INPUTS; "outputs" return OUTPUTS; diff --git a/compiler/parser/faustparser.y b/compiler/parser/faustparser.y index 0f29d3403..5c9d49379 100644 --- a/compiler/parser/faustparser.y +++ b/compiler/parser/faustparser.y @@ -217,6 +217,8 @@ inline Tree unquote(char* str) %token ISUM %token IPROD +%token META + %token INPUTS %token OUTPUTS @@ -587,6 +589,7 @@ primitive : INT { $$ = boxInt(str2int(FAUSTtext) | ffunction { $$ = boxFFun($1); } | fconst { $$ = $1; } | fvariable { $$ = $1; } + | META { $$ = gGlobal->gMetaEnv; } | COMPONENT LPAR uqstring RPAR { $$ = boxComponent($3); } | LIBRARY LPAR uqstring RPAR { $$ = boxLibrary($3); } | ENVIRONMENT LBRAQ stmtlist RBRAQ { $$ = boxWithLocalDef(boxEnvironment(),formatDefinitions($3)); } -- 2.39.2 _______________________________________________ Faudiostream-devel mailing list Faudiostream-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/faudiostream-devel