Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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