import { MathConcept } from './math-concept.js'
import { LogicConcept } from './logic-concept.js'
import { Environment } from './environment.js'
/**
* An Expression is a type of {@link LogicConcept}. (For the other types, see
* the documentation of that class.) Expressions are mathematical statements
* and their sub-parts, in the usual manner of organizing into tree form what
* many mathematicians informally call "mathematical expressions" as trees.
*
* For instance, $3+k=9$ and $\frac{58}{1+x}<e$ are two mathematical
* expressions. Their subexpressions are also expressions, including, for
* example, $9$, $3+k$, $1+x$, and $\frac{58}{1+x}$. Even $+$ and $=$ are
* subexpressions; they are functions that are being applied to arguments.
*
* When we speak of "tree form," we refer to the idea that every expression
* can be organized into a tree by following the order of operations. For
* example, $3+k=9$ might have $=$ at the root, with right child $9$ and left
* child a subtree with $+$ over $3$ and $k$. Although that is one way to
* organize expressions into trees, we actually choose a slightly different
* means of applying functions/operators to arguments, which is covered in the
* documentation for the {@link Application} class.
*
* Expressions are analogous to what mathematicians typically write inside
* `$...$` or `$$...$$` math mode in LaTeX. This distinguishes them from
* larger structures that appear in mathematical writing, such as a proof,
* or a section, or an axiom, or an exercise.
*
* There are three types of Expressions:
*
* 1. Atomic expressions, also called {@link Symbol Symbols}, which can
* represent any mathematical symbol, such as $x$, $5$, $e$, $\pi$, $B_4$,
* $\in$, $\int$, etc. (Note that notation here is in math form just for
* the documentation; actual symbols may use a different style, such as
* `B_4`.)
* 2. {@link Application Applications}, which represent the application of a
* function or operator to zero or more arguments, as in the example of
* $3 + k$, above, which applies $+$ to the arguments $3$ and $k$.
* 3. {@link BindingExpression Binding Expressions}, which represent the use
* of a dummy variable in an expression. Specifically, if you have an
* expression such as $\exists x,(x^2=2)$ or $\int_a^b f(x)\;dx$, the $x$
* is used as a "dummy" or "bound" variable in each case, and thus has a
* limited scope one cannot express with a mere function
* {@link Application Application}. See the documentation for the
* {@link BindingExpression Binding Expression class} for details on how to
* represent expressions like those examples.
*
* We do not define these cases further here; see the documentation of each of
* the classes linked to above for details. The Expression class is an
* abstract base class, and every instance should be an instance of one of
* those three subclasses.
*/
export class Expression extends LogicConcept {
static className = MathConcept.addSubclass( 'Expression', Expression )
/**
* Constructs an Expression from the given list of children, which may
* be empty. All children must also be instances of Expression; those
* that are not are filtered out.
*
* @param {...Expression} children child Expressions to be added to
* this one (as in the constructors for {@link MathConcept} and
* {@link LogicConcept})
*/
constructor ( ...children ) {
super( ...children.filter( child => child instanceof Expression ) )
}
/**
* If this Expression has an Expression parent, then it is not the
* outermost expression in the hierarchy. However, if it has a parent
* that is some other kind of {@link MathConcept} or
* {@link LogicConcept}, then it is the outermost Expression in the
* hierarchy. If it has no parent, it is the outermost.
*
* @returns {boolean} Whether this expression is the outermost
* Expression in the {@link MathConcept} hierarchy in which it sits
* @see {@link Expression#getOutermost getOutermost()}
*/
isOutermost () {
return this._parent === null
|| !( this._parent instanceof Expression )
}
/**
* This function walks up the {@link MathConcept} hierarchy containing
* this Expression until it finds an ancestor satisfying
* {@link Expression#isOutermost isOutermost()}, and then it returns that
* Expression.
*
* @returns {Expression} the outermost Expression ancestor of this
* Expression
*/
getOutermost () {
return this.isOutermost() ? this : this._parent.getOutermost()
}
/**
* Based on the definition given in the
* {@link Environment#conclusions conclusions()} function, an Expression
* will be a conclusion in one of its ancestors if all of the following
* are true.
*
* * it is not marked with the "given" attribute
* * its parent is an {@link Environment}
* * neither that parent nor any other ancestor (up to and including the
* one specified as parameter) are marked with the "given" attribute
*
* If no ancestor is provided, then the top-level {@link MathConcept}
* ancestor is used instead.
*
* @param {MathConcept} ancestor - the context in which this query is
* being made
* @returns {boolean} whether this expression is a conclusion in the given
* `ancestor`
*
* @see {@link LogicConcept#hasOnlyClaimAncestors hasOnlyClaimAncestors()}
*/
isAConclusionIn ( ancestor ) {
if ( !( this.parent() instanceof Environment ) ) return false
return this.hasOnlyClaimAncestors( ancestor )
}
/**
* Many mathematical expressions have standard interpretations. We permit
* Expression instances to be marked with an attribute indicating that
* they have a standard interpretation, and what that interpretation is.
* This function looks for such attributes and applies them, computing the
* value of the Expression, if it has one, and returning undefined if it
* does not.
*
* An Expression that has a value will have an attribute whose key is the
* string `"evaluate as"` and whose value is a string such as `"integer"`
* or `"integer base 2"` or `"string"` or `"ordered pair"` or any of a
* wide variety of other ways to evaluate the Expression's content.
*
* It is intended that this list can grow over time, and this function be
* updated to support new types of simple mathematical values as they are
* needed. It is not intended that every kind of possible interpretation
* should show up on this list, but rather just those types that are
* common/standard across enough of mathematics that they will be used in
* any kind of mathematics software.
*
* This initial implementation provides support for *none* of the types of
* valuation described above, because each is best implemented in one of
* this class's subclasses ({@link Symbol} or {@link Application}) instead.
* A stub is implemented here as a pure virtual method, to guarantee that
* the function exists for all Expression instances and returns undefined by
* default.
*
* @returns {*} any basic JavaScript value representing this Expression,
* or undefined if it there is no such value
*/
value () { }
}
source