Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5496 leency 1
 
2
#define __patterns_h__
3
4
 
5
/// Pattern matching code.
6
///
7
/// General idea: have a class that can match function parameters
8
/// to a pattern, check for predicates on the arguments, and return
9
/// whether there was a match.
10
///
11
/// First the pattern is mapped onto the arguments. Then local variables
12
/// are set. Then the predicates are called. If they all return true,
13
/// Then the pattern matches, and the locals can stay (the body is expected
14
/// to use these variables).
15
16
 
17
 
18
#include "lisptype.h"
19
#include "grower.h"
20
#include "lispenvironment.h"
21
22
 
23
 
24
class YacasParamMatcherBase : public YacasBase
25
{
26
public:
27
    /// Destructor.
28
    /// This function contains no code.
29
    virtual ~YacasParamMatcherBase();
30
31
 
32
    /// \param aEnvironment the underlying Lisp environment.
33
    /// \param aExpression the expression to test.
34
    /// \param arguments (input/output) actual values of the pattern
35
    /// variables for \a aExpression.
36
    virtual LispBoolean ArgumentMatches(LispEnvironment& aEnvironment,
37
                                        LispPtr& aExpression,
38
                                        LispPtr* arguments)=0;
39
};
40
41
 
42
class MatchAtom : public YacasParamMatcherBase
43
{
44
public:
45
    MatchAtom(LispString * aString);
46
    virtual LispBoolean ArgumentMatches(LispEnvironment& aEnvironment,
47
                                        LispPtr& aExpression,
48
                                        LispPtr* arguments);
49
protected:
50
    LispString * iString;
51
};
52
53
 
54
class MatchNumber : public YacasParamMatcherBase
55
{
56
public:
57
    MatchNumber(BigNumber* aNumber);
58
    virtual LispBoolean ArgumentMatches(LispEnvironment& aEnvironment,
59
                                        LispPtr& aExpression,
60
                                        LispPtr* arguments);
61
protected:
62
    RefPtr iNumber;
63
};
64
65
 
66
class MatchSubList : public YacasParamMatcherBase
67
{
68
public:
69
  MatchSubList(YacasParamMatcherBase** aMatchers, LispInt aNrMatchers);
70
  ~MatchSubList();
71
  virtual LispBoolean ArgumentMatches(LispEnvironment& aEnvironment,
72
                                      LispPtr& aExpression,
73
                                      LispPtr* arguments);
74
private:
75
  MatchSubList(const MatchSubList& aOther) : iMatchers(NULL),iNrMatchers(0)
76
  {
77
    // copy constructor not written yet, hence the assert
78
    LISPASSERT(0);
79
  }
80
  MatchSubList& operator=(const MatchSubList& aOther)
81
  {
82
    // copy constructor not written yet, hence the assert
83
    LISPASSERT(0);
84
    return *this;
85
  }
86
protected:
87
  YacasParamMatcherBase** iMatchers;
88
  LispInt iNrMatchers;
89
};
90
91
 
92
class MatchVariable : public YacasParamMatcherBase
93
{
94
public:
95
    MatchVariable(LispInt aVarIndex);
96
97
 
98
    /// \param aEnvironment the underlying Lisp environment.
99
    /// \param aExpression the expression to test.
100
    /// \param arguments (input/output) actual values of the pattern
101
    /// variables for \a aExpression.
102
    ///
103
    /// If entry #iVarIndex in \a arguments is still empty, the
104
    /// pattern matches and \a aExpression is stored in this
105
    /// entry. Otherwise, the pattern only matches if the entry equals
106
    /// \a aExpression.
107
    virtual LispBoolean ArgumentMatches(LispEnvironment& aEnvironment,
108
                                        LispPtr& aExpression,
109
                                        LispPtr* arguments);
110
protected:
111
    /// Index of variable in YacasPatternPredicateBase::iVariables.
112
    LispInt iVarIndex;
113
};
114
115
 
116
 
117
/// This class (specifically, the Matches() member function) can match
118
/// function parameters to a pattern, check for predicates on the
119
/// arguments, and return whether there was a match.
120
121
 
122
{
123
public:
124
    /// Constructor.
125
    /// \param aEnvironment the underlying Lisp environment
126
    /// \param aPattern Lisp expression containing the pattern
127
    /// \param aPostPredicate Lisp expression containing the
128
    /// postpredicate
129
    ///
130
    /// The function MakePatternMatcher() is called for every argument
131
    /// in \a aPattern, and the resulting pattern matchers are
132
    /// collected in #iParamMatchers. Additionally, \a aPostPredicate
133
    /// is copied, and the copy is added to #iPredicates.
134
    YacasPatternPredicateBase(LispEnvironment& aEnvironment,
135
                              LispPtr& aPattern,
136
                              LispPtr& aPostPredicate);
137
138
 
139
    /// This function contains no code.
140
    ~YacasPatternPredicateBase();
141
142
 
143
    /// First, every argument in \a aArguments is matched against the
144
    /// corresponding YacasParamMatcherBase in #iParamMatches. If any
145
    /// match fails, Matches() returns false. Otherwise, a temporary
146
    /// LispLocalFrame is constructed, then SetPatternVariables() and
147
    /// CheckPredicates() are called, and then the LispLocalFrame is
148
    /// immediately deleted. If CheckPredicates() returns false, this
149
    /// function also returns false. Otherwise, SetPatternVariables()
150
    /// is called again, but now in the current LispLocalFrame, and
151
    /// this function returns true.
152
    LispBoolean Matches(LispEnvironment& aEnvironment,
153
                        LispPtr& aArguments);
154
155
 
156
    /// This function does the same as Matches(LispEnvironment&,LispPtr&),
157
    /// but differs in the type of the arguments.
158
    LispBoolean Matches(LispEnvironment& aEnvironment,
159
                        LispPtr* aArguments);
160
161
 
162
    /// Construct a pattern matcher out of a Lisp expression.
163
    /// The result of this function depends on the value of \a aPattern:
164
    /// - If \a aPattern is a number, the corresponding MatchNumber is
165
    ///   constructed and returned.
166
    /// - If \a aPattern is an atom, the corresponding MatchAtom is
167
    ///   constructed and returned.
168
    /// - If \a aPattern is a list of the form ( _ var ),
169
    ///   where \c var is an atom, LookUp() is called on \c var. Then
170
    ///   the correspoding MatchVariable is constructed and returned.
171
    /// - If \a aPattern is a list of the form ( _ var expr ),
172
    ///   where \c var is an atom, LookUp() is called on \c var. Then,
173
    ///   \a expr is appended to #iPredicates. Finally, the
174
    ///   correspoding MatchVariable is constructed and returned.
175
    /// - If \a aPattern is a list of another form, this function
176
    ///   calls itself on any of the entries in this list. The
177
    ///   resulting YacasParamMatcherBase objects are collected in a
178
    ///   MatchSubList, which is returned.
179
    /// - Otherwise, this function returns #NULL.
180
    YacasParamMatcherBase* MakeParamMatcher(LispEnvironment& aEnvironment, LispObject* aPattern);
181
182
 
183
    /// \returns index in #iVariables array where \a aVariable
184
    /// appears.
185
    ///
186
    /// If \a aVariable is not in #iVariables, it is added.
187
    LispInt LookUp(LispString * aVariable);
188
189
 
190
    /// Set local variables corresponding to the pattern variables.
191
    /// This function goes through the #iVariables array. A local
192
    /// variable is made for every entry in the array, and the
193
    /// corresponding argument is assigned to it.
194
    void SetPatternVariables(LispEnvironment& aEnvironment, LispPtr* arguments);
195
196
 
197
    /// This function goes through all predicates in #iPredicates, and
198
    /// evaluates them. It returns #LispFalse if at least one
199
    /// of these results IsFalse(). An error is raised if any result
200
    /// neither IsTrue() nor IsFalse().
201
    LispBoolean CheckPredicates(LispEnvironment& aEnvironment);
202
203
 
204
    /// List of parameter matches, one for every parameter.
205
    CDeletingArrayGrower > iParamMatchers;
206
207
 
208
    CArrayGrower > iVariables;
209
210
 
211
    CArrayGrower > iPredicates;
212
};
213
214
 
215
 
216