Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4680 | right-hear | 1 | |
2 | #define __mathuserfunc_h__ |
||
3 | |||
4 | |||
5 | #include "lispuserfunc.h" |
||
6 | #include "grower.h" |
||
7 | |||
8 | |||
9 | |||
10 | |||
11 | /// This is the basic class which implements functions in Yacas. |
||
12 | /// Evaluation is done by consulting a set of rewriting rules. The |
||
13 | /// body of the first rule that matches, is evaluated and this gives |
||
14 | /// the result of evaluating the function. |
||
15 | |||
16 | |||
17 | { |
||
18 | public: |
||
19 | /// Structure containing name of parameter and whether it is put on hold. |
||
20 | class BranchParameter : public YacasBase |
||
21 | { |
||
22 | public: |
||
23 | BranchParameter(LispString * aParameter = NULL, LispInt aHold=LispFalse) |
||
24 | : iParameter(aParameter), iHold(aHold) {} |
||
25 | LispString * iParameter; |
||
26 | LispInt iHold; |
||
27 | }; |
||
28 | |||
29 | |||
30 | class BranchRuleBase : public YacasBase |
||
31 | { |
||
32 | public: |
||
33 | virtual ~BranchRuleBase(); |
||
34 | virtual LispBoolean Matches(LispEnvironment& aEnvironment, LispPtr* aArguments) = 0; |
||
35 | virtual LispInt Precedence() const = 0; |
||
36 | virtual LispPtr& Body() = 0; |
||
37 | }; |
||
38 | |||
39 | |||
40 | /// This rule matches if the predicate evaluates to #LispTrue. |
||
41 | class BranchRule : public BranchRuleBase |
||
42 | { |
||
43 | public: |
||
44 | virtual ~BranchRule(); |
||
45 | BranchRule(LispInt aPrecedence,LispPtr& aPredicate,LispPtr& aBody) : iPrecedence(aPrecedence),iBody(aBody),iPredicate(aPredicate) |
||
46 | { |
||
47 | } |
||
48 | |||
49 | |||
50 | /// #iPredicate is evaluated in \a Environment. If the result |
||
51 | /// IsTrue(), this function returns true. |
||
52 | virtual LispBoolean Matches(LispEnvironment& aEnvironment, LispPtr* aArguments); |
||
53 | |||
54 | |||
55 | virtual LispInt Precedence() const; |
||
56 | |||
57 | |||
58 | virtual LispPtr& Body(); |
||
59 | protected: |
||
60 | BranchRule() : iPrecedence(0),iBody(),iPredicate() {}; |
||
61 | protected: |
||
62 | LispInt iPrecedence; |
||
63 | LispPtr iBody; |
||
64 | LispPtr iPredicate; |
||
65 | }; |
||
66 | |||
67 | |||
68 | class BranchRuleTruePredicate : public BranchRule |
||
69 | { |
||
70 | public: |
||
71 | BranchRuleTruePredicate(LispInt aPrecedence,LispPtr& aBody) |
||
72 | { |
||
73 | iPrecedence = aPrecedence; |
||
74 | iBody = (aBody); |
||
75 | } |
||
76 | /// Return #LispTrue, always. |
||
77 | virtual LispBoolean Matches(LispEnvironment& aEnvironment, LispPtr* aArguments); |
||
78 | }; |
||
79 | |||
80 | |||
81 | class BranchPattern : public BranchRuleBase |
||
82 | { |
||
83 | public: |
||
84 | /// Destructor. |
||
85 | /// This function contains no code. |
||
86 | virtual ~BranchPattern(); |
||
87 | |||
88 | |||
89 | /// \param aPrecedence precedence of the rule |
||
90 | /// \param aPredicate generic object of type \c Pattern |
||
91 | /// \param aBody body of the rule |
||
92 | BranchPattern(LispInt aPrecedence,LispPtr& aPredicate,LispPtr& aBody) : iPrecedence(aPrecedence),iBody(aBody),iPredicate(aPredicate),iPatternClass(NULL) |
||
93 | { |
||
94 | GenericClass *gen = aPredicate->Generic(); |
||
95 | DYNCAST(PatternClass,"\"Pattern\"",pat,gen) |
||
96 | Check(pat,KLispErrInvalidArg); |
||
97 | iPatternClass = pat; |
||
98 | } |
||
99 | |||
100 | |||
101 | virtual LispBoolean Matches(LispEnvironment& aEnvironment, LispPtr* aArguments); |
||
102 | |||
103 | |||
104 | virtual LispInt Precedence() const; |
||
105 | |||
106 | |||
107 | virtual LispPtr& Body(); |
||
108 | |||
109 | |||
110 | BranchPattern(const BranchPattern& aOther) : iPrecedence(0),iBody(),iPredicate(),iPatternClass(NULL) |
||
111 | { |
||
112 | // copy constructor not written yet, hence the assert |
||
113 | LISPASSERT(0); |
||
114 | } |
||
115 | BranchPattern& operator=(const BranchPattern& aOther) |
||
116 | { |
||
117 | // copy constructor not written yet, hence the assert |
||
118 | LISPASSERT(0); |
||
119 | return *this; |
||
120 | } |
||
121 | |||
122 | |||
123 | /// The precedence of this rule. |
||
124 | LispInt iPrecedence; |
||
125 | |||
126 | |||
127 | LispPtr iBody; |
||
128 | |||
129 | |||
130 | LispPtr iPredicate; |
||
131 | |||
132 | |||
133 | PatternClass *iPatternClass; |
||
134 | }; |
||
135 | |||
136 | |||
137 | /// \param aParameters linked list constaining the names of the arguments |
||
138 | /// |
||
139 | /// #iParamList and #iParameters are set from \a aParameters. |
||
140 | BranchingUserFunction(LispPtr& aParameters); |
||
141 | |||
142 | |||
143 | /// There is no code inside this function. |
||
144 | virtual ~BranchingUserFunction(); |
||
145 | |||
146 | |||
147 | /// \param aResult (on output) the result of the evaluation |
||
148 | /// \param aEnvironment the underlying Lisp environment |
||
149 | /// \param aArguments the arguments to the function |
||
150 | /// |
||
151 | /// First, all arguments are evaluated by the evaluator associated |
||
152 | /// to \a aEnvironment, unless the \c iHold flag of the |
||
153 | /// corresponding parameter is true. Then a new LispLocalFrame is |
||
154 | /// constructed, in which the actual arguments are assigned to the |
||
155 | /// names of the formal arguments, as stored in \c iParameter. Then |
||
156 | /// all rules in #iRules are tried one by one. The body of the |
||
157 | /// first rule that matches is evaluated, and the result is put in |
||
158 | /// \a aResult. If no rule matches, \a aResult will recieve a new |
||
159 | /// expression with evaluated arguments. |
||
160 | virtual void Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment, LispPtr& aArguments); |
||
161 | |||
162 | |||
163 | /// \param aVariable name of argument to put un hold |
||
164 | /// |
||
165 | /// The \c iHold flag of the corresponding argument is set. This |
||
166 | /// implies that this argument is not evaluated by Evaluate(). |
||
167 | virtual void HoldArgument(LispString * aVariable); |
||
168 | |||
169 | |||
170 | virtual LispInt IsArity(LispInt aArity) const; |
||
171 | |||
172 | |||
173 | LispInt Arity() const; |
||
174 | |||
175 | |||
176 | /// \sa InsertRule() |
||
177 | virtual void DeclareRule(LispInt aPrecedence, LispPtr& aPredicate, LispPtr& aBody); |
||
178 | |||
179 | |||
180 | /// \sa InsertRule() |
||
181 | virtual void DeclareRule(LispInt aPrecedence, LispPtr& aBody); |
||
182 | |||
183 | |||
184 | /// \sa InsertRule() |
||
185 | void DeclarePattern(LispInt aPrecedence, LispPtr& aPredicate, LispPtr& aBody); |
||
186 | |||
187 | |||
188 | /// This function does the real work for DeclareRule() and |
||
189 | /// DeclarePattern(): it inserts the rule in #iRules, while |
||
190 | /// keeping it sorted. The algorithm is \f$O(\log n)\f$, where |
||
191 | /// \f$n\f$ denotes the number of rules. |
||
192 | void InsertRule(LispInt aPrecedence,BranchRuleBase* newRule); |
||
193 | |||
194 | |||
195 | virtual LispPtr& ArgList(); |
||
196 | |||
197 | |||
198 | /// List of arguments, with corresponding \c iHold property. |
||
199 | CArrayGrower |
||
200 | |||
201 | |||
202 | CDeletingArrayGrower |
||
203 | |||
204 | |||
205 | LispPtr iParamList; |
||
206 | }; |
||
207 | |||
208 | |||
209 | { |
||
210 | public: |
||
211 | ListedBranchingUserFunction(LispPtr& aParameters); |
||
212 | virtual LispInt IsArity(LispInt aArity) const; |
||
213 | virtual void Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment, LispPtr& aArguments); |
||
214 | }; |
||
215 | |||
216 | |||
217 | |||
218 | { |
||
219 | public: |
||
220 | MacroUserFunction(LispPtr& aParameters); |
||
221 | virtual void Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment, LispPtr& aArguments); |
||
222 | }; |
||
223 | |||
224 | |||
225 | |||
226 | { |
||
227 | public: |
||
228 | ListedMacroUserFunction(LispPtr& aParameters); |
||
229 | virtual LispInt IsArity(LispInt aArity) const; |
||
230 | virtual void Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment, LispPtr& aArguments); |
||
231 | }; |
||
232 | |||
233 | |||
234 | |||
235 | |||
236 | |||
237 |