370 lines
13 KiB
Objective-C
370 lines
13 KiB
Objective-C
//
|
|
// MPFunction.h
|
|
// MathKit
|
|
//
|
|
// Created by Kim Wittenburg on 18.04.14.
|
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
|
//
|
|
|
|
#import "MPExpression.h"
|
|
|
|
|
|
/*!
|
|
@header
|
|
This file contains the <code>MPFunction</code> class.
|
|
|
|
<code>MPFunction</code> is a half abstract class that is designed to be
|
|
subclassed. Subclasses of the <code>MPFunction</code> class (subsequently called
|
|
<i>functions</i>) need to regard the following guidelines:
|
|
|
|
1. In their header file functions should declare <code>readwrite,
|
|
nonatomic</code> properties for every child (subexpression) they have.
|
|
2. For every public child accessor there should be one use of the
|
|
<code>@link MPFunctionAccessorImplementation@/link</code> macro in the
|
|
implementation file. See the documentation on the macro for details.
|
|
3. Functions must override the <code>@link childrenAccessors@/link</code> method
|
|
returning the KVC compatible names of the publicly declared property accessors
|
|
4. Functions must also override the <code>@link functionTermClass@/link</code>
|
|
method returning a <code>Class</code> that can evaluate the function. See the
|
|
documentation on that method for details.
|
|
5. Optionally functions can implement
|
|
<code>@link expectsVariableDefinitionInChildAtIndex:@/link</code> if one of
|
|
its children is supposed to contain a variable definition.
|
|
6. Functions should also override the <code>NSObject</code> method
|
|
<code>description</code>. Although this is not a requirement it
|
|
is strongly recommended.
|
|
|
|
Functions play an important role in the <i>expression tree</i>. For details on
|
|
the that subject see the documentation for <code>@link
|
|
MPExpression@/link</code>.
|
|
|
|
@note
|
|
None of the children of a function may be <code>nil</code> at any time.
|
|
*/
|
|
|
|
|
|
/*!
|
|
@define MPFunctionAccessorImplementation
|
|
@abstract This macro implements the setter of a previously declared
|
|
property of a <code>MPFunction</code> subclass.
|
|
|
|
@discussion Overriding the default setter implementation 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. If you need to implement additional
|
|
custom behaviour in a property setter it is recommended that you
|
|
copy the content of the macro.
|
|
|
|
@param Accessor
|
|
The capitalized name of the property to be implemented. This is
|
|
used for the name of the method: <code>set...</code>.
|
|
|
|
@param variableName
|
|
The name of the instance variable that backs the property.
|
|
Normally this is the same as the name of the property prefixed
|
|
with an underscore.
|
|
*/
|
|
#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
|
|
@abstract The <code>MPFunction</code> class represents a mathematical function.
|
|
|
|
@discussion A mathematical function can be anything that exceeds the
|
|
graphical capability of text. Functions like <code>sin</code>,
|
|
<code>cos</code> or <code>ln</code> are not considered functions
|
|
in this context because they can be represented by text.
|
|
*/
|
|
@interface MPFunction : NSObject <NSCoding, NSCopying, MPExpressionElement>
|
|
|
|
#pragma mark Working With the Expression Tree
|
|
/*!
|
|
@methodgroup Working With the Expression Tree
|
|
*/
|
|
|
|
|
|
/*!
|
|
@property parent
|
|
@abstract 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 or removed from an expression.
|
|
@note If you need to know when a function is added to or removed from
|
|
an expression you can observe this property using KVO.
|
|
|
|
@return The parent of the receiver or <code>nil</code> if the receiver
|
|
does not have a parent.
|
|
*/
|
|
@property (nonatomic, weak) MPExpression *parent;
|
|
|
|
|
|
/*!
|
|
@method rootExpression
|
|
@abstract 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
|
|
<code>nil</code> if this function does not have a parent.
|
|
*/
|
|
- (MPExpression *)rootExpression;
|
|
|
|
|
|
/*!
|
|
@method indexPath
|
|
@abstract Returns the index path of the receiver in the expression tree.
|
|
|
|
@discussion The index path contains the indexes (starting from the root
|
|
expression of the receiver's expression tree) that lead to the
|
|
receiver. The indexes are expressed in the element reference
|
|
frame.
|
|
|
|
@return The index path of the receiver in the expression tree or
|
|
<code>nil</code> if this function does not have a parent.
|
|
*/
|
|
- (NSIndexPath *)indexPath;
|
|
|
|
|
|
/*!
|
|
@method numberOfChildren
|
|
@abstract Returns the number of children the receiver has.
|
|
|
|
@return The number of children the receiving function has.
|
|
*/
|
|
- (NSUInteger)numberOfChildren;
|
|
|
|
|
|
/*!
|
|
@method childAtIndex:
|
|
@abstract Returns the child at the specified index.
|
|
|
|
@discussion The ordering of children is determined by the order of the
|
|
child accessors as returned from the
|
|
<code>@link childrenAccessors@/link</code> method.
|
|
|
|
@param index
|
|
The index of the requested child.
|
|
|
|
@return The expression that corresponds to the child at
|
|
<code>index</code>.
|
|
*/
|
|
- (MPExpression *)childAtIndex:(NSUInteger)index;
|
|
|
|
|
|
/*!
|
|
@method setChild:atIndex:
|
|
@abstract Sets the child at the specified index.
|
|
|
|
@discussion Although this method does <b>not</b> call the respective accessor
|
|
methods it behaves exactly as the setter method implemented using
|
|
the <code>@link MPFunctionAccessorImplementation@/link</code>
|
|
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
|
|
@abstract Returns the receiver's children.
|
|
|
|
@discussion The ordering of the children is the same as in the array returned
|
|
from <code>@link childrenAccessors@/link</code>.
|
|
|
|
@return An array containing all the function's children.
|
|
*/
|
|
- (NSArray *)children;
|
|
|
|
|
|
/*!
|
|
@method indexOfChild:
|
|
@abstract Returns the index of <code>child</code> in the receiver.
|
|
|
|
@param child
|
|
The child to be searched.
|
|
|
|
@return The index of <code>child</code> or <code>NSNotFound</code> if
|
|
none of the receiver's children is equal to <code>child</code>.
|
|
*/
|
|
- (NSUInteger)indexOfChild:(MPExpression *)child;
|
|
|
|
|
|
/*!
|
|
@method elementAtIndexPath:
|
|
@abstract Returns the element at the specified index path.
|
|
|
|
@discussion This method finds the elements at the respective indexes starting
|
|
at the root expression from the receiver's expression tree.
|
|
The returned object can be a <code>NSString</code>, a
|
|
<code>MPFunction</code> or a <code>@link
|
|
MPExpression@/link</code> instance depending on the specified
|
|
<code>indexPath</code>. If any of the indexes exceed the bounds
|
|
of the respective receiver a <code>NSRangeException</code> 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 <code>indexPath</code>. The element is not
|
|
copied before it is returned. Be aware of the fact that any
|
|
mutations made to the returned object will update the receiver's
|
|
expression tree to reflect the change.
|
|
*/
|
|
- (id)elementAtIndexPath:(NSIndexPath *)indexPath;
|
|
|
|
|
|
#pragma mark Notifications
|
|
/*!
|
|
@methodgroup Notifications
|
|
*/
|
|
|
|
|
|
/*!
|
|
@method didChangeElementsInRangePath:replacementLength:
|
|
@abstract This Notification message is sent automatically from the receiver
|
|
to itself if one of its children was mutated or changed.
|
|
|
|
@discussion This method should also be 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:
|
|
@abstract Convenience method that calls
|
|
<code>@link
|
|
didChangeElementsInRangePath:replacementLength:@/link</code>
|
|
|
|
@discussion This method is automatically called when one of the children is
|
|
changed using one of the accessor methods or
|
|
<code>@link setChild:atIndex:@/link</code>.
|
|
|
|
@param index
|
|
The index of the child that was changed.
|
|
*/
|
|
- (void)didChangeChildAtIndex:(NSUInteger)index;
|
|
|
|
|
|
#pragma mark Evaluating Functions
|
|
/*!
|
|
@methodgroup Evaluating Functions
|
|
*/
|
|
|
|
|
|
/*!
|
|
@method expectsVariableDefinitionInChildAtIndex:
|
|
@abstract Returns whether the child at <code>anIndex</code> is supposed to
|
|
contain a variable definition.
|
|
|
|
@discussion This method is automatically called during the parsing process.
|
|
You can override this method to opt into the default behaviour.
|
|
If you override this method you do not need to call super.
|
|
|
|
The default implementation just returns <code>NO</code> for every
|
|
index.
|
|
|
|
@param anIndex
|
|
The index of the child to check.
|
|
|
|
@return <code>YES</code> if the child at <code>anIndex</code> is supposed
|
|
to contain a variable definition, <code>NO</code> otherwise.
|
|
*/
|
|
- (BOOL)expectsVariableDefinitionInChildAtIndex:(NSUInteger)anIndex;
|
|
|
|
@end
|
|
|
|
|
|
|
|
/*!
|
|
@category MPFunction (MPSubclassOverride)
|
|
@abstract The methods in this category must be implemented by any concrete
|
|
subclasses of <code>MPFunction</code>.
|
|
|
|
@discussion <code>MPFunction</code> 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
|
|
@abstract Returns the names of the children properties as strings.
|
|
|
|
@discussion All objects in the returned array must be strings.
|
|
|
|
@return An array of strings describing the names of children a function
|
|
has.
|
|
*/
|
|
- (NSArray *)childrenAccessors;
|
|
|
|
|
|
#pragma mark Evaluating Functions
|
|
/*!
|
|
@methodgroup Evaluating Functions
|
|
*/
|
|
|
|
|
|
/*!
|
|
@method functionTermClass
|
|
@abstract Returns the class that represents the receiver's evaluation
|
|
behaviour.
|
|
|
|
@discussion Subclasses of <code>MPFunction</code> can (like
|
|
<code>@link MPExpression@/link</code>) not evaluate themselves.
|
|
Instead this method is called on every function. The returned
|
|
class must be a valid subclass of <code>@link
|
|
//apple_ref/occ/cl/MPFunctionTerm@/link</code>. It will be
|
|
instanciated using the <code>init</code> method.
|
|
|
|
@return The <code>@link //apple_ref/occ/cl/MPFunctionTerm@/link</code>
|
|
subclass that can evaluate instances of the receiver's class.
|
|
*/
|
|
- (Class)functionTermClass;
|
|
|
|
@end
|