1 /***************************************************************************\
2 |* Function Parser for C++ v4.5.2                                          *|
3 |*-------------------------------------------------------------------------*|
4 |* Copyright: Juha Nieminen, Joel Yliluoma                                 *|
5 |*                                                                         *|
6 |* This library is distributed under the terms of the                      *|
7 |* GNU Lesser General Public License version 3.                            *|
8 |* (See lgpl.txt and gpl.txt for the license text.)                        *|
9 \***************************************************************************/
10 
11 // NOTE:
12 // This file contains only internal types for the function parser library.
13 // You don't need to include this file in your code. Include "fparser.hh"
14 // only.
15 
16 #ifndef ONCE_FPARSER_TYPES_H_
17 #define ONCE_FPARSER_TYPES_H_
18 
19 #include "../fpconfig.hh"
20 #include <cstring>
21 
22 #ifdef ONCE_FPARSER_H_
23 #include <map>
24 #endif
25 
26 namespace FUNCTIONPARSERTYPES
27 {
28     enum OPCODE
29     {
30 // The order of opcodes in the function list must
31 // match that which is in the Functions[] array.
32         cAbs,
33         cAcos, cAcosh,
34         cArg,   /* get the phase angle of a complex value */
35         cAsin, cAsinh,
36         cAtan, cAtan2, cAtanh,
37         cCbrt, cCeil,
38         cConj,  /* get the complex conjugate of a complex value */
39         cCos, cCosh, cCot, cCsc, cCsd,
40         cExp, cExp2, cFloor, cHypot,
41         cIf,
42         cImag,  /* get imaginary part of a complex value */
43         cInt, cLog, cLog10, cLog2, cMax, cMin,
44         cPolar, /* create a complex number from polar coordinates */
45         cPow, cPsh,
46         cReal, /* get real part of a complex value */
47         cSec, cSin, cSinh, cSqrt, cTan, cTanh,
48         cTrunc,
49 
50 // These do not need any ordering:
51 // Except that if you change the order of {eq,neq,lt,le,gt,ge}, you
52 // must also change the order in ConstantFolding_ComparisonOperations().
53         cImmed, cJump,
54         cNeg, cAdd, cSub, cMul, cDiv, cMod,
55         cEqual, cNEqual, cLess, cLessOrEq, cGreater, cGreaterOrEq,
56         cNot, cAnd, cOr,
57         cNotNot, /* Protects the double-not sequence from optimizations */
58 
59         cDeg, cRad, /* Multiplication and division by 180 / pi */
60 
61         cFCall, cPCall,
62 
63 #ifdef FP_SUPPORT_OPTIMIZER
64         cPopNMov, /* cPopNMov(x,y) moves [y] to [x] and deletes anything
65                    * above [x]. Used for disposing of temporaries.
66                    */
67         cLog2by, /* log2by(x,y) = log2(x) * y */
68         cNop,    /* Used by fpoptimizer internally; should not occur in bytecode */
69 #endif
70         cSinCos,   /* sin(x) followed by cos(x) (two values are pushed to stack) */
71         cSinhCosh, /* hyperbolic equivalent of sincos */
72         cAbsAnd,    /* As cAnd,       but assume both operands are absolute values */
73         cAbsOr,     /* As cOr,        but assume both operands are absolute values */
74         cAbsNot,    /* As cAbsNot,    but assume the operand is an absolute value */
75         cAbsNotNot, /* As cAbsNotNot, but assume the operand is an absolute value */
76         cAbsIf,     /* As cAbsIf,     but assume the 1st operand is an absolute value */
77 
78         cDup,   /* Duplicates the last value in the stack: Push [Stacktop] */
79         cFetch, /* Same as Dup, except with absolute index
80                  * (next value is index) */
81         cInv,   /* Inverts the last value in the stack (x = 1/x) */
82         cSqr,   /* squares the last operand in the stack, no push/pop */
83         cRDiv,  /* reverse division (not x/y, but y/x) */
84         cRSub,  /* reverse subtraction (not x-y, but y-x) */
85         cRSqrt, /* inverse square-root (1/sqrt(x)) */
86 
87         VarBegin
88     };
89 
90 #ifdef ONCE_FPARSER_H_
91     struct FuncDefinition
92     {
93         enum FunctionFlags
94         {
95             Enabled     = 0x01,
96             AngleIn     = 0x02,
97             AngleOut    = 0x04,
98             OkForInt    = 0x08,
99             ComplexOnly = 0x10
100         };
101 
102 #ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
103         const char name[8];
104 #endif
105         unsigned params : 8;
106         unsigned flags  : 8;
107 
okForIntFUNCTIONPARSERTYPES::FuncDefinition108         inline bool okForInt() const { return (flags & OkForInt) != 0; }
complexOnlyFUNCTIONPARSERTYPES::FuncDefinition109         inline bool complexOnly() const { return (flags & ComplexOnly) != 0; }
110     };
111 
112 #ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
113 # define FP_FNAME(n) n,
114 #else
115 # define FP_FNAME(n)
116 #endif
117 // This list must be in the same order as that in OPCODE enum,
118 // because the opcode value is used to index this array, and
119 // the pointer to array element is used for generating the opcode.
120     const FuncDefinition Functions[]=
121     {
122         /*cAbs  */ { FP_FNAME("abs")   1, FuncDefinition::OkForInt },
123         /*cAcos */ { FP_FNAME("acos")  1, FuncDefinition::AngleOut },
124         /*cAcosh*/ { FP_FNAME("acosh") 1, FuncDefinition::AngleOut },
125         /*cArg */  { FP_FNAME("arg")   1, FuncDefinition::AngleOut | FuncDefinition::ComplexOnly },
126         /*cAsin */ { FP_FNAME("asin")  1, FuncDefinition::AngleOut },
127         /*cAsinh*/ { FP_FNAME("asinh") 1, FuncDefinition::AngleOut },
128         /*cAtan */ { FP_FNAME("atan")  1, FuncDefinition::AngleOut },
129         /*cAtan2*/ { FP_FNAME("atan2") 2, FuncDefinition::AngleOut },
130         /*cAtanh*/ { FP_FNAME("atanh") 1, 0 },
131         /*cCbrt */ { FP_FNAME("cbrt")  1, 0 },
132         /*cCeil */ { FP_FNAME("ceil")  1, 0 },
133         /*cConj */ { FP_FNAME("conj")  1, FuncDefinition::ComplexOnly },
134         /*cCos  */ { FP_FNAME("cos")   1, FuncDefinition::AngleIn },
135         /*cCosh */ { FP_FNAME("cosh")  1, FuncDefinition::AngleIn },
136         /*cCot  */ { FP_FNAME("cot")   1, FuncDefinition::AngleIn },
137         /*cCsc  */ { FP_FNAME("csc")   1, FuncDefinition::AngleIn },
138         /*cExp  */ { FP_FNAME("exp")   1, 0 },
139         /*cExp2 */ { FP_FNAME("exp2")  1, 0 },
140         /*cFloor*/ { FP_FNAME("floor") 1, 0 },
141         /*cGet  */ { FP_FNAME("get")   1, 0 },
142         /*cHypot*/ { FP_FNAME("hypot") 2, 0 },
143         /*cIf   */ { FP_FNAME("if")    0, FuncDefinition::OkForInt },
144         /*cImag */ { FP_FNAME("imag")  1, FuncDefinition::ComplexOnly },
145         /*cInt  */ { FP_FNAME("int")   1, 0 },
146         /*cLog  */ { FP_FNAME("log")   1, 0 },
147         /*cLog10*/ { FP_FNAME("log10") 1, 0 },
148         /*cLog2 */ { FP_FNAME("log2")  1, 0 },
149         /*cMax  */ { FP_FNAME("max")   2, FuncDefinition::OkForInt },
150         /*cMin  */ { FP_FNAME("min")   2, FuncDefinition::OkForInt },
151         /*cPolar */{ FP_FNAME("polar") 2, FuncDefinition::ComplexOnly | FuncDefinition::AngleIn },
152         /*cPow  */ { FP_FNAME("pow")   2, 0 },
153         /*cPsh  */ { FP_FNAME("psh")   2, 0 },
154         /*cReal */ { FP_FNAME("real")  1, FuncDefinition::ComplexOnly },
155         /*cSec  */ { FP_FNAME("sec")   1, FuncDefinition::AngleIn },
156         /*cSin  */ { FP_FNAME("sin")   1, FuncDefinition::AngleIn },
157         /*cSinh */ { FP_FNAME("sinh")  1, FuncDefinition::AngleIn },
158         /*cSqrt */ { FP_FNAME("sqrt")  1, 0 },
159         /*cTan  */ { FP_FNAME("tan")   1, FuncDefinition::AngleIn },
160         /*cTanh */ { FP_FNAME("tanh")  1, FuncDefinition::AngleIn },
161         /*cTrunc*/ { FP_FNAME("trunc") 1, 0 }
162     };
163 #undef FP_FNAME
164 
165     struct NamePtr
166     {
167         const char* name;
168         unsigned nameLength;
169 
NamePtrFUNCTIONPARSERTYPES::NamePtr170         NamePtr(const char* n, unsigned l): name(n), nameLength(l) {}
171 
operator ==FUNCTIONPARSERTYPES::NamePtr172         inline bool operator==(const NamePtr& rhs) const
173         {
174             return nameLength == rhs.nameLength
175                 && std::memcmp(name, rhs.name, nameLength) == 0;
176         }
operator <FUNCTIONPARSERTYPES::NamePtr177         inline bool operator<(const NamePtr& rhs) const
178         {
179             for(unsigned i = 0; i < nameLength; ++i)
180             {
181                 if(i == rhs.nameLength) return false;
182                 const char c1 = name[i], c2 = rhs.name[i];
183                 if(c1 < c2) return true;
184                 if(c2 < c1) return false;
185             }
186             return nameLength < rhs.nameLength;
187         }
188     };
189 
190     template<typename Value_t>
191     struct NameData
192     {
193         enum DataType { CONSTANT, UNIT, FUNC_PTR, PARSER_PTR, VARIABLE };
194         DataType type;
195         unsigned index;
196         Value_t value;
197 
NameDataFUNCTIONPARSERTYPES::NameData198         NameData(DataType t, unsigned v) : type(t), index(v), value() { }
NameDataFUNCTIONPARSERTYPES::NameData199         NameData(DataType t, Value_t v) : type(t), index(), value(v) { }
NameDataFUNCTIONPARSERTYPES::NameData200         NameData() { }
201     };
202 
203     template<typename Value_t>
204     class NamePtrsMap: public
205     std::map<FUNCTIONPARSERTYPES::NamePtr,
206              FUNCTIONPARSERTYPES::NameData<Value_t> >
207     {
208     };
209 
210     const unsigned FUNC_AMOUNT = sizeof(Functions)/sizeof(Functions[0]);
211 #endif // ONCE_FPARSER_H_
212 }
213 
214 #ifdef ONCE_FPARSER_H_
215 #include <vector>
216 
217 template<typename Value_t>
218 struct FunctionParserBase<Value_t>::Data
219 {
220     unsigned mReferenceCounter;
221 
222     char mDelimiterChar;
223     ParseErrorType mParseErrorType;
224     int mEvalErrorType;
225     bool mUseDegreeConversion;
226     bool mHasByteCodeFlags;
227     const char* mErrorLocation;
228 
229     unsigned mVariablesAmount;
230     std::string mVariablesString;
231     FUNCTIONPARSERTYPES::NamePtrsMap<Value_t> mNamePtrs;
232 
233     struct InlineVariable
234     {
235         FUNCTIONPARSERTYPES::NamePtr mName;
236         unsigned mFetchIndex;
237     };
238 
239     typedef std::vector<InlineVariable> InlineVarNamesContainer;
240     InlineVarNamesContainer mInlineVarNames;
241 
242     struct FuncWrapperPtrData
243     {
244         /* Only one of the pointers will point to a function, the other
245            will be null. (The raw function pointer could be implemented
246            as a FunctionWrapper specialization, but it's done like this
247            for efficiency.) */
248         FunctionPtr mRawFuncPtr;
249         FunctionWrapper* mFuncWrapperPtr;
250         unsigned mParams;
251 
252         FuncWrapperPtrData();
253         ~FuncWrapperPtrData();
254         FuncWrapperPtrData(const FuncWrapperPtrData&);
255         FuncWrapperPtrData& operator=(const FuncWrapperPtrData&);
256     };
257 
258     struct FuncParserPtrData
259     {
260         FunctionParserBase<Value_t>* mParserPtr;
261         unsigned mParams;
262     };
263 
264     std::vector<FuncWrapperPtrData> mFuncPtrs;
265     std::vector<FuncParserPtrData> mFuncParsers;
266 
267     std::vector<unsigned> mByteCode;
268     std::vector<Value_t> mImmed;
269 
270 #if !defined(FP_USE_THREAD_SAFE_EVAL) && \
271     !defined(FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA)
272     std::vector<Value_t> mStack;
273     std::vector<Value_t> mStacki;
274     std::vector<Value_t> mStackSave;
275     // Note: When mStack exists,
276     //       mStack.size() and mStackSize are mutually redundant.
277 #endif
278 
279     unsigned mStackSize;
280 
281     Data();
282     Data(const Data&);
283     Data& operator=(const Data&); // not implemented on purpose
284     ~Data();
285 };
286 #endif
287 
288 //#include "fpaux.hh"
289 
290 #endif
291