321 lines
10 KiB
Objective-C
321 lines
10 KiB
Objective-C
//
|
|
// MPFunction.h
|
|
// MathPad
|
|
//
|
|
// Created by Kim Wittenburg on 18.04.14.
|
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
|
//
|
|
|
|
#import "MPExpressionElement.h"
|
|
|
|
|
|
|
|
/* Use this macro to implement a custom setter for children of custom MPFunction
|
|
* subclasses. This is necessary to maintain the consistency of the expression
|
|
* tree. Not implementing a custom setter using this macro or a similar custom
|
|
* method will lead to unexpected behaviour.
|
|
*/
|
|
#define MPFunctionAccessorImplementation(Accessor, variableName) \
|
|
- (void)set##Accessor:(MPExpression *)value \
|
|
{ \
|
|
variableName.parent = nil; \
|
|
variableName = value; \
|
|
variableName.parent = self; \
|
|
[self didChangeChildAtIndex:[self indexOfChild:variableName]]; \
|
|
}
|
|
|
|
|
|
|
|
@class MPFunction, MPExpression, MPRangePath;
|
|
@protocol MPExpressionElement;
|
|
|
|
|
|
/*!
|
|
@class MPFunction
|
|
@brief The @c MPFunction class represents a mathematical function.
|
|
|
|
@discussion A mathematical function can be anything that exceeds the
|
|
graphical capability of text.
|
|
*/
|
|
@interface MPFunction : NSObject <NSCoding, NSCopying, MPExpressionElement>
|
|
|
|
#pragma mark Properties
|
|
/* Subclasses should define readwrite properties for all child expressions they
|
|
* can have. In the implementation file the property setter should be overridden
|
|
* using the @c MPFunctionAccessorImplementation macro. The macro takes two
|
|
* parameters: The capitalized name of the property and the name of the
|
|
* property's backing variable (usually the property's name prefixed with an
|
|
* underscore.
|
|
*
|
|
* Note that none of the children may be nil at any time.
|
|
*/
|
|
|
|
|
|
#pragma mark Working With the Expression Tree
|
|
/*!
|
|
@methodgroup Working With the Expression Tree
|
|
*/
|
|
|
|
|
|
/*!
|
|
@property parent
|
|
@brief The receiver's parent.
|
|
|
|
@discussion Expressions and functions are organized in a tree-like structure.
|
|
Through this property a function's containing expression can be
|
|
accessed.
|
|
@warning Do not set this property manually. It will automatically be set
|
|
when the function is added to an expression.
|
|
@note If you need to know when a function is added to or removed from
|
|
an expression you can observe this property.
|
|
|
|
@return The parent of the receiver or @c nil if the receiver does not
|
|
have a parent.
|
|
*/
|
|
@property (nonatomic, weak) MPExpression *parent;
|
|
|
|
|
|
/*!
|
|
@method rootExpression
|
|
@brief Returns the root expression from the receiver's expression tree.
|
|
|
|
@discussion The root expression is the ultimate parent of all expressions and
|
|
functions in the expression tree. A root expression does not have
|
|
a parent.
|
|
|
|
@return The root expression from the receiver's expression tree or @c nil
|
|
if this function does not have a parent.
|
|
*/
|
|
- (MPExpression *)rootExpression;
|
|
|
|
|
|
/*!
|
|
@method indexPath
|
|
@brief Returns the index path of the receiver in the expression tree.
|
|
|
|
@discussion The index path is calculated by going up the expression tree
|
|
collecting the respective index of the receiver. The indexes are
|
|
expressed in the element reference frame. If any of the indexes
|
|
exceed the respective receiver's bounds a @c NSRangeException is
|
|
raised.
|
|
|
|
@return The index path of the receiver in the expression tree or @c nil
|
|
if this function does not have a parent.
|
|
*/
|
|
- (NSIndexPath *)indexPath;
|
|
|
|
|
|
/*!
|
|
@method numberOfChildren
|
|
@brief Returns the number of children the receiver has.
|
|
|
|
@discussion The number of children must be equal to the number of child
|
|
accessors as determined by the @c -childrenAccessors method.
|
|
|
|
@return The number of children of the receiving function.
|
|
*/
|
|
- (NSUInteger)numberOfChildren;
|
|
|
|
|
|
/*!
|
|
@method childAtIndex:
|
|
@brief Returns the child at the given index.
|
|
|
|
@discussion The ordering of children is determined by the order of the
|
|
children returned from the @c -childrenAccessors method.
|
|
|
|
@param index
|
|
The index of the requested child.
|
|
|
|
@return The expression that corresponds to the child at @c index.
|
|
*/
|
|
- (MPExpression *)childAtIndex:(NSUInteger)index;
|
|
|
|
|
|
/*!
|
|
@method setChild:atIndex:
|
|
@brief Sets the child at the specified index.
|
|
|
|
@discussion Although this method does @b not call the respective accessor
|
|
methods it behaves exactly as the setter method implemented using
|
|
the @c MPFunctionAccessorImplementation macro.
|
|
|
|
@param child
|
|
The child that should replace the previous one.
|
|
|
|
@param index
|
|
The index of the child to be replaced.
|
|
*/
|
|
- (void)setChild:(MPExpression *)child
|
|
atIndex:(NSUInteger)index;
|
|
|
|
|
|
/*!
|
|
@method children
|
|
@brief Returns the receiver's children.
|
|
|
|
@discussion The ordering of the children is the same as in the array returned
|
|
from @c -childrenAccessors.
|
|
|
|
@return An array containing all the function's children.
|
|
*/
|
|
- (NSArray *)children;
|
|
|
|
|
|
/*!
|
|
@method indexOfChild:
|
|
@brief Returns the index of @c child in the receiver.
|
|
|
|
@param child
|
|
The child to be searched.
|
|
|
|
@return The index of @c child or @c NSNotFound if none of the receiver's
|
|
children is equal to @c child.
|
|
*/
|
|
- (NSUInteger)indexOfChild:(MPExpression *)child;
|
|
|
|
|
|
/*!
|
|
@method elementAtIndexPath:
|
|
@brief Returns the element at the specified index path.
|
|
|
|
@discussion This method @em walks down the expression tree (including other
|
|
functions) using the specified index path and finds the
|
|
corresponding element. The returned object can be an @c NSString,
|
|
a @c MPFunction or an @c MPExpression depending on the element @c
|
|
indexPath points to. If any of the indexes exceed the bounds of
|
|
the respective receiver an @c NSRangeException is raised.
|
|
|
|
If the index path does not contain any indexes the receiver
|
|
itself is returned.
|
|
|
|
@param indexPath
|
|
The index path the required object is located at. The indexes are
|
|
expressed in the element reference frame.
|
|
|
|
@return The element located at @c indexPath. The element is not copied
|
|
before it is returned. Be aware of the fact that any mutations
|
|
made to the returned object are reflected in the receiver.
|
|
*/
|
|
- (id)elementAtIndexPath:(NSIndexPath *)indexPath;
|
|
|
|
|
|
#pragma mark Notifications
|
|
/*!
|
|
@methodgroup Notifications
|
|
*/
|
|
|
|
|
|
/*!
|
|
@method didChangeElementsInRangePath:replacementLength:
|
|
@brief Notification method that is called if one of the children was
|
|
mutated.
|
|
|
|
@discussion This method is also called when one of the children is changed
|
|
via one of the accessor methods.
|
|
|
|
@param rangePath
|
|
The location of the change that happened. Because it may have
|
|
happened somewhere deep down in the expression tree a range path
|
|
is used.
|
|
|
|
@param replacementLength
|
|
The number of elements that replaced the elements addressed by
|
|
the range path.
|
|
*/
|
|
- (void)didChangeElementsInRangePath:(MPRangePath *)rangePath
|
|
replacementLength:(NSUInteger)replacementLength;
|
|
|
|
|
|
/*!
|
|
@method didChangeChildAtIndex:
|
|
@brief Convenience method that calls @c
|
|
-didChangeElementsInRangePath:replacementLength:
|
|
|
|
@discussion This method is automatically called when one of the children is
|
|
changed using one of the accessor methods or @c
|
|
-setChild:atIndex:.
|
|
|
|
@param index
|
|
The index of the child that was changed.
|
|
*/
|
|
- (void)didChangeChildAtIndex:(NSUInteger)index;
|
|
|
|
@end
|
|
|
|
|
|
|
|
/*!
|
|
@category MPFunction (MPSubcalssOverride)
|
|
@brief The methods in this category must be implemented by any concrete
|
|
subclasses of @c MPFunction.
|
|
|
|
@discussion @c MPFunction does not implement the functions itself but calls
|
|
them at various points. If a subclass does not provide
|
|
implementations your app will most likely crash.
|
|
*/
|
|
@interface MPFunction (MPSubclassOverride)
|
|
|
|
#pragma mark Working With the Expression Tree
|
|
/*!
|
|
@methodgroup Working With the Expression Tree
|
|
*/
|
|
|
|
|
|
/*!
|
|
@method childrenAccessors
|
|
@brief Returns the names of the children properties.
|
|
|
|
@discussion A @c MPFunction subclass should declare a public propertiy for
|
|
every child it can have. This method should return the names as
|
|
they would be used for key-value-coding.
|
|
|
|
@return An array of strings describing the names of children a function
|
|
has.
|
|
*/
|
|
- (NSArray *)childrenAccessors;
|
|
|
|
|
|
#pragma mark Evaluating Functions
|
|
/*!
|
|
@methodgroup Evaluating Functions
|
|
*/
|
|
|
|
|
|
/*!
|
|
@method validate:
|
|
@brief Validates the function and all its children for syntax errors.
|
|
|
|
@param error
|
|
If the validation fails this parameter should be set to an
|
|
appropriate value.
|
|
|
|
@return @c YES if the validation was successful, @c NO otherwise.
|
|
*/
|
|
- (BOOL)validate:(NSError *__autoreleasing *)error;
|
|
|
|
|
|
/*!
|
|
@method evaluate:
|
|
@brief Evaluates the function.
|
|
|
|
@discussion Function evaluation should actually perform math. Also the
|
|
implementation of this method assumes that the function and all
|
|
children are valid (as determined by the @c -validate: method).
|
|
|
|
@param error
|
|
If a mathematical error occurs it is reflected in this parameter.
|
|
Depending on the error this method then either returns @c nil or
|
|
@c NaN.
|
|
|
|
@return The result of the evaluation or @c nil or @c NaN if an evaluation
|
|
error occured (such as a division by @c 0).
|
|
*/
|
|
- (NSDecimalNumber *)evaluate:(NSError *__autoreleasing *)error;
|
|
|
|
/* In Addition to the above methods MPFunction subclasses should also override
|
|
* the NSObject methods -description and -hash.
|
|
*/
|
|
|
|
@end
|