kolibrios/contrib/media/updf/include/mathuserfunc.h
right-hearted 4f7ee97ec9 uPDF with buttons
git-svn-id: svn://kolibrios.org@4680 a494cfbc-eb01-0410-851d-a64ba20cac60
2014-03-22 21:00:40 +00:00

239 lines
7.5 KiB
C++

#ifndef __mathuserfunc_h__
#define __mathuserfunc_h__
#include "yacasbase.h"
#include "lispuserfunc.h"
#include "grower.h"
#include "patternclass.h"
/// A mathematical function defined by several rules.
/// This is the basic class which implements functions in Yacas.
/// Evaluation is done by consulting a set of rewriting rules. The
/// body of the first rule that matches, is evaluated and this gives
/// the result of evaluating the function.
class BranchingUserFunction : public LispArityUserFunction
{
public:
/// Structure containing name of parameter and whether it is put on hold.
class BranchParameter : public YacasBase
{
public:
BranchParameter(LispString * aParameter = NULL, LispInt aHold=LispFalse)
: iParameter(aParameter), iHold(aHold) {}
LispString * iParameter;
LispInt iHold;
};
/// Abstract base class for rules.
class BranchRuleBase : public YacasBase
{
public:
virtual ~BranchRuleBase();
virtual LispBoolean Matches(LispEnvironment& aEnvironment, LispPtr* aArguments) = 0;
virtual LispInt Precedence() const = 0;
virtual LispPtr& Body() = 0;
};
/// A rule with a predicate.
/// This rule matches if the predicate evaluates to #LispTrue.
class BranchRule : public BranchRuleBase
{
public:
virtual ~BranchRule();
BranchRule(LispInt aPrecedence,LispPtr& aPredicate,LispPtr& aBody) : iPrecedence(aPrecedence),iBody(aBody),iPredicate(aPredicate)
{
}
/// Return true if the rule matches.
/// #iPredicate is evaluated in \a Environment. If the result
/// IsTrue(), this function returns true.
virtual LispBoolean Matches(LispEnvironment& aEnvironment, LispPtr* aArguments);
/// Access #iPrecedence.
virtual LispInt Precedence() const;
/// Access #iBody.
virtual LispPtr& Body();
protected:
BranchRule() : iPrecedence(0),iBody(),iPredicate() {};
protected:
LispInt iPrecedence;
LispPtr iBody;
LispPtr iPredicate;
};
/// A rule that always matches.
class BranchRuleTruePredicate : public BranchRule
{
public:
BranchRuleTruePredicate(LispInt aPrecedence,LispPtr& aBody)
{
iPrecedence = aPrecedence;
iBody = (aBody);
}
/// Return #LispTrue, always.
virtual LispBoolean Matches(LispEnvironment& aEnvironment, LispPtr* aArguments);
};
/// A rule which matches if the corresponding PatternClass matches.
class BranchPattern : public BranchRuleBase
{
public:
/// Destructor.
/// This function contains no code.
virtual ~BranchPattern();
/// Constructor.
/// \param aPrecedence precedence of the rule
/// \param aPredicate generic object of type \c Pattern
/// \param aBody body of the rule
BranchPattern(LispInt aPrecedence,LispPtr& aPredicate,LispPtr& aBody) : iPrecedence(aPrecedence),iBody(aBody),iPredicate(aPredicate),iPatternClass(NULL)
{
GenericClass *gen = aPredicate->Generic();
DYNCAST(PatternClass,"\"Pattern\"",pat,gen)
Check(pat,KLispErrInvalidArg);
iPatternClass = pat;
}
/// Return true if the corresponding pattern matches.
virtual LispBoolean Matches(LispEnvironment& aEnvironment, LispPtr* aArguments);
/// Access #iPrecedence
virtual LispInt Precedence() const;
/// Access #iBody
virtual LispPtr& Body();
private:
BranchPattern(const BranchPattern& aOther) : iPrecedence(0),iBody(),iPredicate(),iPatternClass(NULL)
{
// copy constructor not written yet, hence the assert
LISPASSERT(0);
}
BranchPattern& operator=(const BranchPattern& aOther)
{
// copy constructor not written yet, hence the assert
LISPASSERT(0);
return *this;
}
protected:
/// The precedence of this rule.
LispInt iPrecedence;
/// The body of this rule.
LispPtr iBody;
/// Generic object of type \c Pattern containing #iPatternClass
LispPtr iPredicate;
/// The pattern that decides whether this rule matches.
PatternClass *iPatternClass;
};
/// Constructor.
/// \param aParameters linked list constaining the names of the arguments
///
/// #iParamList and #iParameters are set from \a aParameters.
BranchingUserFunction(LispPtr& aParameters);
/// Destructor.
/// There is no code inside this function.
virtual ~BranchingUserFunction();
/// Evaluate the function on given arguments.
/// \param aResult (on output) the result of the evaluation
/// \param aEnvironment the underlying Lisp environment
/// \param aArguments the arguments to the function
///
/// First, all arguments are evaluated by the evaluator associated
/// to \a aEnvironment, unless the \c iHold flag of the
/// corresponding parameter is true. Then a new LispLocalFrame is
/// constructed, in which the actual arguments are assigned to the
/// names of the formal arguments, as stored in \c iParameter. Then
/// all rules in #iRules are tried one by one. The body of the
/// first rule that matches is evaluated, and the result is put in
/// \a aResult. If no rule matches, \a aResult will recieve a new
/// expression with evaluated arguments.
virtual void Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment, LispPtr& aArguments);
/// Put an argument on hold.
/// \param aVariable name of argument to put un hold
///
/// The \c iHold flag of the corresponding argument is set. This
/// implies that this argument is not evaluated by Evaluate().
virtual void HoldArgument(LispString * aVariable);
/// Return true if the arity of the function equals \a aArity.
virtual LispInt IsArity(LispInt aArity) const;
/// Return the arity (number of arguments) of the function.
LispInt Arity() const;
/// Add a BranchRule to the list of rules.
/// \sa InsertRule()
virtual void DeclareRule(LispInt aPrecedence, LispPtr& aPredicate, LispPtr& aBody);
/// Add a BranchRuleTruePredicate to the list of rules.
/// \sa InsertRule()
virtual void DeclareRule(LispInt aPrecedence, LispPtr& aBody);
/// Add a BranchPattern to the list of rules.
/// \sa InsertRule()
void DeclarePattern(LispInt aPrecedence, LispPtr& aPredicate, LispPtr& aBody);
/// Insert any BranchRuleBase object in the list of rules.
/// This function does the real work for DeclareRule() and
/// DeclarePattern(): it inserts the rule in #iRules, while
/// keeping it sorted. The algorithm is \f$O(\log n)\f$, where
/// \f$n\f$ denotes the number of rules.
void InsertRule(LispInt aPrecedence,BranchRuleBase* newRule);
/// Return the argument list, stored in #iParamList
virtual LispPtr& ArgList();
protected:
/// List of arguments, with corresponding \c iHold property.
CArrayGrower<BranchParameter, ArrOpsPOD<BranchParameter> > iParameters;
/// List of rules, sorted on precedence.
CDeletingArrayGrower<BranchRuleBase*, ArrOpsDeletingPtr<BranchRuleBase> > iRules;
/// List of arguments
LispPtr iParamList;
};
class ListedBranchingUserFunction : public BranchingUserFunction
{
public:
ListedBranchingUserFunction(LispPtr& aParameters);
virtual LispInt IsArity(LispInt aArity) const;
virtual void Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment, LispPtr& aArguments);
};
class MacroUserFunction : public BranchingUserFunction
{
public:
MacroUserFunction(LispPtr& aParameters);
virtual void Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment, LispPtr& aArguments);
};
class ListedMacroUserFunction : public MacroUserFunction
{
public:
ListedMacroUserFunction(LispPtr& aParameters);
virtual LispInt IsArity(LispInt aArity) const;
virtual void Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment, LispPtr& aArguments);
};
#endif