202 lines
7.6 KiB
Objective-C
202 lines
7.6 KiB
Objective-C
//
|
|
// MPTerm.h
|
|
// MathPad
|
|
//
|
|
// Created by Kim Wittenburg on 11.11.14.
|
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
|
//
|
|
|
|
|
|
/*!
|
|
@header
|
|
This file contains the <code>MPTerm</code> class.
|
|
|
|
The <code>MPTerm</code> class is used to evaluate a mathematical expression. A
|
|
term is a purely mathematical representation of a part of an expression. A term
|
|
can be defined with three rules:
|
|
|
|
1. A number is a term.
|
|
2. A variable is a term.
|
|
3. A connection of terms with zero or more symbols is also a term.
|
|
|
|
Every mathematical operation (term) is defined in terms of a concrete subclass
|
|
of <code>MPTerm</code> and sub-terms (children). For example the expression
|
|
<code>2+3⋅4</code> would be a @link //apple_ref/occ/cl/MPSumTerm sum term@/link
|
|
with two children: A @link //apple_ref/occ/cl/MPNumber number@/link and a @link
|
|
//apple_ref/occ/cl/MPProductTerm product term@/link. The product term in turn
|
|
has two children which are both numbers.
|
|
|
|
Subclasses should do the following:
|
|
1. Subclasses must implement the <code>@link doEvaluation:@/link</code> method.
|
|
2. Subclasses should be immutable and thus define <code>readonly</code>
|
|
accessors for any children as well as an <code>init</code> method that
|
|
supplies the necessary values.
|
|
|
|
If a term has children that define variables to be used in one or more of the
|
|
other children <code>MPTerm</code> offers methods for defining, accessing and
|
|
undefining variable values. Because a term can not define variables that are
|
|
accessible in any of its sibling or parent terms all variables defined in a term
|
|
are automatically undefined when the term is finished evaluating.
|
|
*/
|
|
|
|
|
|
/*!
|
|
@define ReturnIfNil
|
|
@abstract This macro returns a <code>value</code> if a <code>test</code>
|
|
object is <code>nil</code>.
|
|
|
|
@param test
|
|
The object to be tested. If this parameter is <code>nil</code>
|
|
the macro returns <code>value</code>.
|
|
|
|
@param value
|
|
The value to be returned if <code>test</code> is
|
|
<code>nil</code>.
|
|
*/
|
|
#define ReturnIfNil(test, value) if (test == nil) return value
|
|
|
|
|
|
/*!
|
|
@define ReturnNilIfNil
|
|
@abstract This macro returns <code>nil</code> if a <code>test</code> object
|
|
is <code>nil</code>.
|
|
|
|
@param test
|
|
The object to be tested. If this parameter is <code>nil</code>
|
|
the macro returns <code>nil</code>.
|
|
*/
|
|
#define ReturnNilIfNil(test) if (test == nil) return nil
|
|
|
|
|
|
|
|
@class MPTerm;
|
|
|
|
|
|
/*!
|
|
@class MPTerm
|
|
@abstract <code>MPTerm</code> is a half abstract class that is the base
|
|
class for representing an evaluatable mathematical expression.
|
|
|
|
@discussion <code>MPTerm</code> should not be instanciated directly. Instead
|
|
one of the concrete subclasses should be used.
|
|
*/
|
|
@interface MPTerm : NSObject
|
|
|
|
/*!
|
|
@method evaluate:
|
|
@abstract Evaluates the receiver.
|
|
|
|
@discussion The result of the evaluation is up to the concrete subclass of
|
|
<code>MPTerm</code>. Note however that subclasses should
|
|
<b>not</b> override this method. To implement the custom
|
|
evaluation behaviour implement the <code>@link
|
|
doEvaluation:@/link</code> method. To evaluate a term (including
|
|
children of terms) do use this method.
|
|
|
|
@param error
|
|
If an error occurs during evaluation it is indirecly returned
|
|
through this parameter. If you are not interested in errors, pass
|
|
<code>NULL</code>.
|
|
|
|
@return A <code>NSDecimalNumber</code> containing the result of the
|
|
evaluation. Depending on the term this should be double precision
|
|
or higher.
|
|
*/
|
|
- (NSDecimalNumber *)evaluate:(NSError *__autoreleasing *)error;
|
|
|
|
|
|
/*!
|
|
@method doEvaluation:
|
|
@abstract Performs the actual evaluation of the receiver.
|
|
|
|
@discussion This method must be implemented by subclasses but should never be
|
|
called directly. Call <code>@link evaluate:@/link</code> instead.
|
|
|
|
@param error
|
|
If an error occurs during evaluation it is indirecly returned
|
|
through this parameter. If you are not interested in errors, pass
|
|
<code>NULL</code>.
|
|
|
|
@return A <code>NSDecimalNumber</code> containing the result of the
|
|
evaluation. Depending on the term this should be double precision
|
|
or higher.
|
|
*/
|
|
- (NSDecimalNumber *)doEvaluation:(NSError *__autoreleasing *)error;
|
|
|
|
|
|
/*!
|
|
@method defineVariable:value:error:
|
|
@abstract Defines a variable in the shared evaluation context.
|
|
|
|
@discussion A defined variable is available until it is either undefined or
|
|
the end of the <code>@link doEvaluation:@/link</code> method is
|
|
reached at which point all variables defined in that method are
|
|
undefined automatically. If the <code>variableName</code> has
|
|
already been defined in the same method this method overwrites
|
|
the value for the variable. If it has been defined in the
|
|
evaluation method of a parent term this method fails and returns
|
|
<code>NO</code>.
|
|
|
|
@param variableName
|
|
The variable to be defined.
|
|
|
|
@param value
|
|
The value for the variable.
|
|
|
|
@param error
|
|
If <code>variableName</code> has already been defined in a parent
|
|
term this parameter is set to an error object that informs the
|
|
user about a variable redefinition. If you are not interested in
|
|
errors, pass <code>NULL</code>.
|
|
|
|
@return <code>YES</code> if the variable could be defined,
|
|
<code>NO</code> if it has previously been declared in a parent
|
|
term of the currently evaluated one.
|
|
*/
|
|
- (BOOL)defineVariable:(NSString *)variableName
|
|
value:(NSDecimalNumber *)value
|
|
error:(NSError *__autoreleasing *)error;
|
|
|
|
|
|
/*!
|
|
@method valueForVariable:
|
|
@abstract Returns the value for a variable from the shared evaluation
|
|
context.
|
|
|
|
@discussion If <code>variableName</code> is not defined this method returns
|
|
<code>nil</code>. Normally you do not need to call this method
|
|
yourself.
|
|
|
|
@param variableName
|
|
The variable whose value is requested.
|
|
|
|
@param error
|
|
If <code>variableName</code> is not defined this parameter is set
|
|
to an error object that informs the user about an undefined
|
|
variable. If you are not interested in errors, pass
|
|
<code>NULL</code>.
|
|
|
|
@return The value associated with <code>variableName</code> or
|
|
<code>nil</code> if it is undefined.
|
|
*/
|
|
- (NSDecimalNumber *)valueForVariable:(NSString *)variableName
|
|
error:(NSError *__autoreleasing *)error;
|
|
|
|
|
|
/*!
|
|
@method undefineVariable:
|
|
@abstract Removes <code>variableName</code> from the shared evaluation
|
|
context.
|
|
|
|
@discussion The variable is only removed if it exists and was defined in the
|
|
same evaluation method. Variables defined by parent terms can not
|
|
be undefined. Normally you do not need to call this method
|
|
yourself since all variables defined during the evaluation of a
|
|
term are automatically undefined afterwards.
|
|
|
|
@param variableName
|
|
The name of the variable to be undefined.
|
|
*/
|
|
- (void)undefineVariable:(NSString *)variableName;
|
|
|
|
@end |