Merge branch 'OOP' of https://scm.cri.ensmp.fr/git/Faustine into OOP
[Faustine.git] / interpretor / faust-0.9.47mr3 / compiler / headers / node.hh
1 /************************************************************************
2 ************************************************************************
3 FAUST compiler
4 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
21
22
23
24 /*****************************************************************************
25 ******************************************************************************/
26
27 /** \file node.hh
28 * A Node is a tagged unions of int, double, symbol and void* used in the implementation of CTrees.
29 * Nodes are completly described by the node.h file, there is no node.cpp file.
30 *
31 * <b>API:</b>
32 *
33 * Node(symbol("abcd")); : node with symbol content
34 * Node(10); : node with int content
35 * Node(3.14159); : node with double content
36 *
37 * n->type(); : kIntNode or kDoubleNode or kSymNode
38 *
39 * n->getInt(); : int content of n
40 * n->getDouble(); : double content of n
41 * n->getSym(); : symbol content of n
42 *
43 * if (isInt(n, &i)) ... : int i = int content of n
44 * if (isDouble(n, &f)) ... : double f = double content of n
45 * if (isSym(n, &s)) ... : Sym s = Sym content of n
46 *
47 */
48
49 /******************************************************************************
50 *****************************************************************************/
51
52
53 #ifndef __NODE__
54 #define __NODE__
55
56 #include <iostream>
57 #include "symbol.hh"
58
59 using namespace std;
60
61 /**
62 * Tags used to define the type of a Node
63 */
64 enum { kIntNode, kDoubleNode, kSymNode, kPointerNode };
65
66
67 /**
68 * Class Node = (type x (int + double + Sym + void*))
69 */
70 class Node
71 {
72 int fType;
73 union {
74 int i;
75 double f;
76 Sym s;
77 void* p;
78 } fData;
79
80 public:
81 // constructeurs (assume size of field f is the biggest)
82 Node (int x) : fType(kIntNode) { fData.f = 0; fData.i = x; }
83 Node (double x) : fType(kDoubleNode) { fData.f = x; }
84 Node (const char* name) : fType(kSymNode) { fData.f = 0; fData.s = symbol(name); }
85 Node (const string& name) : fType(kSymNode) { fData.f = 0; fData.s = symbol(name); }
86 Node (Sym x) : fType(kSymNode) { fData.f = 0; fData.s = x; }
87 Node (void* x) : fType(kPointerNode) { fData.f = 0; fData.p = x; }
88
89 Node (const Node& n) : fType(n.fType) { fData = n.fData; }
90
91 // predicats
92 bool operator == (const Node& n) const { return fType == n.fType && fData.f == n.fData.f; }
93 bool operator != (const Node& n) const { return fType != n.fType || fData.f != n.fData.f; }
94
95 // accessors
96 int type() const { return fType; }
97
98 int getInt() const { return fData.i; }
99 double getDouble() const { return fData.f; }
100 Sym getSym() const { return fData.s; }
101 void* getPointer() const { return fData.p; }
102
103 // conversions and promotion for numbers
104 operator int() const { return (fType == kIntNode) ? fData.i : (fType == kDoubleNode) ? int(fData.f) : 0 ; }
105 operator double() const { return (fType == kIntNode) ? double(fData.i) : (fType == kDoubleNode) ? fData.f : 0.0 ; }
106
107 ostream& print (ostream& fout) const; ///< print a node on a stream
108 };
109
110 //printing
111 inline ostream& operator << (ostream& s, const Node& n) { return n.print(s); }
112
113
114
115 //-------------------------------------------------------------------------
116 // Perdicates and pattern matching
117 //-------------------------------------------------------------------------
118
119 // integers
120 inline bool isInt (const Node& n)
121 {
122 return (n.type() == kIntNode);
123 }
124
125 inline bool isInt (const Node& n, int* x)
126 {
127 if (n.type() == kIntNode) {
128 *x = n.getInt();
129 return true;
130 } else {
131 return false;
132 }
133 }
134
135
136 // floats
137 inline bool isDouble (const Node& n)
138 {
139 return (n.type() == kDoubleNode);
140 }
141
142 inline bool isDouble (const Node& n, double* x)
143 {
144 if (n.type() == kDoubleNode) {
145 *x = n.getDouble();
146 return true;
147 } else {
148 return false;
149 }
150 }
151
152
153
154 inline bool isZero (const Node& n)
155 {
156 return (n.type() == kDoubleNode) && (n.getDouble() == 0.0)
157 || (n.type() == kIntNode) && (n.getInt() == 0);
158 }
159
160 inline bool isGEZero (const Node& n)
161 {
162 return (n.type() == kDoubleNode) && (n.getDouble() >= 0.0)
163 || (n.type() == kIntNode) && (n.getInt() >= 0);
164 }
165
166 inline bool isGTZero (const Node& n)
167 {
168 return (n.type() == kDoubleNode) && (n.getDouble() > 0.0)
169 || (n.type() == kIntNode) && (n.getInt() > 0);
170 }
171
172 inline bool isOne (const Node& n)
173 {
174 return (n.type() == kDoubleNode) && (n.getDouble() == 1.0)
175 || (n.type() == kIntNode) && (n.getInt() == 1);
176 }
177
178 inline bool isMinusOne (const Node& n)
179 {
180 return (n.type() == kDoubleNode) && (n.getDouble() == -1.0)
181 || (n.type() == kIntNode) && (n.getInt() == -1);
182 }
183
184
185 // numbers in general
186 inline bool isNum (const Node& n)
187 {
188 return isInt(n)||isDouble(n);
189 }
190
191
192 // symbols
193 inline bool isSym (const Node& n)
194 {
195 return (n.type() == kSymNode);
196 }
197
198 inline bool isSym (const Node& n, Sym* x)
199 {
200 if (n.type() == kSymNode) {
201 *x = n.getSym();
202 return true;
203 } else {
204 return false;
205 }
206 }
207
208
209 // void pointer
210 inline bool isPointer (const Node& n)
211 {
212 return (n.type() == kPointerNode);
213 }
214
215 inline bool isPointer (const Node& n, void** x)
216 {
217 if (n.type() == kPointerNode) {
218 *x = n.getPointer();
219 return true;
220 } else {
221 return false;
222 }
223 }
224
225
226
227
228 //-------------------------------------------------------------------------
229 // Mathematical operations on nodes
230 //-------------------------------------------------------------------------
231
232
233 // arithmetic operations
234
235 inline const Node addNode (const Node& x, const Node& y)
236 { return (isDouble(x)||isDouble(y)) ? Node(double(x)+double(y)) : Node(int(x)+int(y)); }
237
238 inline const Node subNode (const Node& x, const Node& y)
239 { return (isDouble(x)||isDouble(y)) ? Node(double(x)-double(y)) : Node(int(x)-int(y)); }
240
241 inline const Node mulNode (const Node& x, const Node& y)
242 { return (isDouble(x)||isDouble(y)) ? Node(double(x)*double(y)) : Node(int(x)*int(y)); }
243
244 inline const Node divNode (const Node& x, const Node& y)
245 { return (isDouble(x)||isDouble(y)) ? Node(double(x)/double(y)) : Node(int(x)/int(y)); }
246
247 inline const Node divExtendedNode (const Node& x, const Node& y)
248 { return (isDouble(x)||isDouble(y)) ? Node(double(x)/double(y))
249 : (double(int(x)/int(y))==double(x)/double(y)) ? Node(int(x)/int(y))
250 : Node(double(x)/double(y)); }
251
252 inline const Node remNode (const Node& x, const Node& y)
253 { return Node(int(x)%int(y)); }
254
255 // inverse functions
256
257 inline const Node minusNode (const Node& x)
258 { return subNode(0, x); }
259
260 inline const Node inverseNode (const Node& x)
261 { return divNode(1.0f, x); }
262
263
264 // bit shifting operations
265
266 inline const Node lshNode (const Node& x, const Node& y)
267 { return Node(int(x)<<int(y)); }
268
269 inline const Node rshNode (const Node& x, const Node& y)
270 { return Node(int(x)>>int(y)); }
271
272
273 // boolean operations on bits
274
275 inline const Node andNode (const Node& x, const Node& y)
276 { return Node(int(x)&int(y)); }
277
278 inline const Node orNode (const Node& x, const Node& y)
279 { return Node(int(x)|int(y)); }
280
281 inline const Node xorNode (const Node& x, const Node& y)
282 { return Node(int(x)^int(y)); }
283
284
285 // compare operations
286
287 inline const Node gtNode (const Node& x, const Node& y)
288 { return (isDouble(x)||isDouble(y)) ? Node(double(x)>double(y)) : Node(int(x)>int(y)); }
289
290 inline const Node ltNode (const Node& x, const Node& y)
291 { return (isDouble(x)||isDouble(y)) ? Node(double(x)<double(y)) : Node(int(x)<int(y)); }
292
293 inline const Node geNode (const Node& x, const Node& y)
294 { return (isDouble(x)||isDouble(y)) ? Node(double(x)>=double(y)) : Node(int(x)>=int(y)); }
295
296 inline const Node leNode (const Node& x, const Node& y)
297 { return (isDouble(x)||isDouble(y)) ? Node(double(x)<=double(y)) : Node(int(x)<=int(y)); }
298 #if 1
299 inline const Node eqNode (const Node& x, const Node& y)
300 { return (isDouble(x)||isDouble(y)) ? Node(double(x)==double(y)) : Node(int(x)==int(y)); }
301
302 inline const Node neNode (const Node& x, const Node& y)
303 { return (isDouble(x)||isDouble(y)) ? Node(double(x)!=double(y)) : Node(int(x)!=int(y)); }
304 #endif
305
306
307
308 #endif