FAUST compiler  0.9.9.6b8
node.hh
Go to the documentation of this file.
00001 /************************************************************************
00002  ************************************************************************
00003     FAUST compiler
00004     Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
00005     ---------------------------------------------------------------------
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  ************************************************************************
00020  ************************************************************************/
00021 
00022 
00023 
00024 /*****************************************************************************
00025 ******************************************************************************/
00026 
00049 /******************************************************************************
00050 *****************************************************************************/
00051 
00052 
00053 #ifndef     __NODE__
00054 #define     __NODE__
00055 
00056 #include <iostream>
00057 #include "symbol.hh"
00058 
00059 using namespace std;
00060 
00064 enum { kIntNode, kDoubleNode, kSymNode, kPointerNode };
00065 
00066 
00070 class Node
00071 {
00072     int     fType;
00073     union {
00074         int     i;
00075         double  f;
00076         Sym     s;
00077         void*   p;
00078     } fData;
00079 
00080  public:
00081     // constructeurs (assume size of field f is the biggest)
00082     Node (int x)                : fType(kIntNode)       { fData.f = 0; fData.i = x; }
00083     Node (double x)             : fType(kDoubleNode)    { fData.f = x; }
00084     Node (const char* name)     : fType(kSymNode)       { fData.f = 0; fData.s = symbol(name); }
00085     Node (const string& name)   : fType(kSymNode)       { fData.f = 0; fData.s = symbol(name); }
00086     Node (Sym x)                : fType(kSymNode)       { fData.f = 0; fData.s = x; }
00087     Node (void* x)              : fType(kPointerNode)   { fData.f = 0; fData.p = x; }
00088 
00089     Node (const Node& n)        : fType(n.fType)        { fData = n.fData; }
00090 
00091     // predicats
00092     bool operator == (const Node& n) const { return fType == n.fType && fData.f == n.fData.f; }
00093     bool operator != (const Node& n) const { return fType != n.fType || fData.f != n.fData.f; }
00094 
00095     // accessors
00096     int     type()      const   { return fType; }
00097 
00098     int     getInt()        const   { return fData.i; }
00099     double  getDouble()     const   { return fData.f; }
00100     Sym     getSym()        const   { return fData.s; }
00101     void*   getPointer()    const   { return fData.p; }
00102 
00103     // conversions and promotion for numbers
00104     operator int()   const      { return (fType == kIntNode) ? fData.i : (fType == kDoubleNode) ? int(fData.f) : 0 ; }
00105     operator double() const     { return (fType == kIntNode) ? double(fData.i) : (fType == kDoubleNode) ? fData.f : 0.0 ; }
00106 
00107     ostream&    print (ostream& fout) const;                    
00108 };
00109 
00110 //printing
00111 inline ostream& operator << (ostream& s, const Node& n) { return n.print(s); }
00112 
00113 
00114 
00115 //-------------------------------------------------------------------------
00116 // Perdicates and pattern matching
00117 //-------------------------------------------------------------------------
00118 
00119 // integers
00120 inline bool isInt (const Node& n)
00121 {
00122     return (n.type() == kIntNode);
00123 }
00124 
00125 inline bool isInt (const Node& n, int* x)
00126 {
00127     if (n.type() == kIntNode) {
00128         *x = n.getInt();
00129         return true;
00130     } else {
00131         return false;
00132     }
00133 }
00134 
00135 
00136 // floats
00137 inline bool isDouble (const Node& n)
00138 {
00139     return (n.type() == kDoubleNode);
00140 }
00141 
00142 inline bool isDouble (const Node& n, double* x)
00143 {
00144     if (n.type() == kDoubleNode) {
00145         *x = n.getDouble();
00146         return true;
00147     } else {
00148         return false;
00149     }
00150 }
00151 
00152 
00153 
00154 inline bool isZero (const Node& n)
00155 {
00156     return (n.type() == kDoubleNode) && (n.getDouble() == 0.0)
00157         || (n.type() == kIntNode) && (n.getInt() == 0);
00158 }
00159 
00160 inline bool isGEZero (const Node& n)
00161 {
00162     return (n.type() == kDoubleNode) && (n.getDouble() >= 0.0)
00163         || (n.type() == kIntNode) && (n.getInt() >= 0);
00164 }
00165 
00166 inline bool isGTZero (const Node& n)
00167 {
00168     return (n.type() == kDoubleNode) && (n.getDouble() > 0.0)
00169         || (n.type() == kIntNode) && (n.getInt() > 0);
00170 }
00171 
00172 inline bool isOne (const Node& n)
00173 {
00174     return (n.type() == kDoubleNode) && (n.getDouble() == 1.0)
00175         || (n.type() == kIntNode) && (n.getInt() == 1);
00176 }
00177 
00178 inline bool isMinusOne (const Node& n)
00179 {
00180     return (n.type() == kDoubleNode) && (n.getDouble() == -1.0)
00181         || (n.type() == kIntNode) && (n.getInt() == -1);
00182 }
00183 
00184 
00185 // numbers in general
00186 inline bool isNum (const Node& n)
00187 {
00188     return isInt(n)||isDouble(n);
00189 }
00190 
00191 
00192 // symbols
00193 inline bool isSym (const Node& n)
00194 {
00195     return (n.type() == kSymNode);
00196 }
00197 
00198 inline bool isSym (const Node& n, Sym* x)
00199 {
00200     if (n.type() == kSymNode) {
00201         *x = n.getSym();
00202         return true;
00203     } else {
00204         return false;
00205     }
00206 }
00207 
00208 
00209 // void pointer
00210 inline bool isPointer (const Node& n)
00211 {
00212     return (n.type() == kPointerNode);
00213 }
00214 
00215 inline bool isPointer (const Node& n, void** x)
00216 {
00217     if (n.type() == kPointerNode) {
00218         *x = n.getPointer();
00219         return true;
00220     } else {
00221         return false;
00222     }
00223 }
00224 
00225 
00226 
00227 
00228 //-------------------------------------------------------------------------
00229 // Mathematical operations on nodes
00230 //-------------------------------------------------------------------------
00231 
00232 
00233 // arithmetic operations
00234 
00235 inline const Node addNode (const Node& x, const Node& y)
00236     { return (isDouble(x)||isDouble(y)) ? Node(double(x)+double(y)) : Node(int(x)+int(y)); }
00237 
00238 inline const Node subNode (const Node& x, const Node& y)
00239     { return (isDouble(x)||isDouble(y)) ? Node(double(x)-double(y)) : Node(int(x)-int(y)); }
00240 
00241 inline const Node mulNode (const Node& x, const Node& y)
00242     { return (isDouble(x)||isDouble(y)) ? Node(double(x)*double(y)) : Node(int(x)*int(y)); }
00243 
00244 inline const Node divNode (const Node& x, const Node& y)
00245     { return (isDouble(x)||isDouble(y)) ? Node(double(x)/double(y)) : Node(int(x)/int(y)); }
00246 
00247 inline const Node divExtendedNode (const Node& x, const Node& y)
00248     { return  (isDouble(x)||isDouble(y)) ? Node(double(x)/double(y))
00249             : (double(int(x)/int(y))==double(x)/double(y)) ? Node(int(x)/int(y))
00250             : Node(double(x)/double(y)); }
00251 
00252 inline const Node remNode (const Node& x, const Node& y)
00253     { return Node(int(x)%int(y)); }
00254 
00255 // inverse functions
00256 
00257 inline const Node minusNode (const Node& x)
00258     { return subNode(0, x); }
00259 
00260 inline const Node inverseNode (const Node& x)
00261     { return divNode(1.0f, x); }
00262 
00263 
00264 // bit shifting operations
00265 
00266 inline const Node lshNode (const Node& x, const Node& y)
00267     { return Node(int(x)<<int(y)); }
00268 
00269 inline const Node rshNode (const Node& x, const Node& y)
00270     { return Node(int(x)>>int(y)); }
00271 
00272 
00273 // boolean operations on bits
00274 
00275 inline const Node andNode (const Node& x, const Node& y)
00276     { return Node(int(x)&int(y)); }
00277 
00278 inline const Node orNode (const Node& x, const Node& y)
00279     { return Node(int(x)|int(y)); }
00280 
00281 inline const Node xorNode (const Node& x, const Node& y)
00282     { return Node(int(x)^int(y)); }
00283 
00284 
00285 // compare operations
00286 
00287 inline const Node gtNode (const Node& x, const Node& y)
00288     { return (isDouble(x)||isDouble(y)) ? Node(double(x)>double(y)) : Node(int(x)>int(y)); }
00289 
00290 inline const Node ltNode (const Node& x, const Node& y)
00291     { return (isDouble(x)||isDouble(y)) ? Node(double(x)<double(y)) : Node(int(x)<int(y)); }
00292 
00293 inline const Node geNode (const Node& x, const Node& y)
00294     { return (isDouble(x)||isDouble(y)) ? Node(double(x)>=double(y)) : Node(int(x)>=int(y)); }
00295 
00296 inline const Node leNode (const Node& x, const Node& y)
00297     { return (isDouble(x)||isDouble(y)) ? Node(double(x)<=double(y)) : Node(int(x)<=int(y)); }
00298 #if 1
00299 inline const Node eqNode (const Node& x, const Node& y)
00300     { return (isDouble(x)||isDouble(y)) ? Node(double(x)==double(y)) : Node(int(x)==int(y)); }
00301 
00302 inline const Node neNode (const Node& x, const Node& y)
00303     { return (isDouble(x)||isDouble(y)) ? Node(double(x)!=double(y)) : Node(int(x)!=int(y)); }
00304 #endif
00305 
00306 
00307 
00308 #endif