Contributors · Internals

Expression model

Expression is the library's primary symbolic scalar representation. Rather than thinking of it as a generic AST node, it is better understood as a typed internal value: each expression has a required type and value, with additional fields present only when that form of expression needs them.

Groups describe storage and canonicalization. The categories NUM, VAR, EXP, FUN, GRP, PRD, SUM, and INF reflect how expressions are represented and canonicalized internally. They are implementation details rather than a general classification of mathematical objects.

Anatomy of an Expression

type and value identify the stored node. Other fields are representation-dependent. In particular, multiplier and power can be absent from storage even though getMultiplier() and getPower() still provide the effective values algorithms should use.

Always stored Conditional / optional storage
multiplierOuter exact coefficient when explicitly stored, normally a Rational.Optional storage
type + valueThe internal group code and canonical key identifying the node.Always stored
powerOuter symbolic exponent when explicitly stored.Optional storage
elementsKeyed child expressions used by aggregate groups such as sums and products.By group
args / nameFunction name and arguments for FUN nodes.FUN only
baseExplicit base stored by EXP nodes.EXP only
Representative node relationshipsSolid = always stored · dashed = conditional
flowchart LR E["Expression"] --> T["type / value"] E -.-> M["multiplier: Rational"] E -.-> P["power: Expression"] E -.-> C["elements: child Expressions"] E -.-> A["args: function arguments"] E -.-> B["base: EXP base"] E -.-> N["name: function name"] T --> G["NUM · VAR · EXP · FUN · GRP · PRD · SUM · INF"]

Why the multiplier matters

Numeric coefficients are usually kept outside the symbolic child structure. That is why a contributor should not picture 2*x simply as a product node containing the children 2 and x.

Input2*x

Ordinary mathematical notation.

Core representationmultiplier = 2value = xpower = 1

The numeric coefficient can live on the symbolic node.

Benefitlike terms combine structurally

Arithmetic can reason about the symbolic base separately from its coefficient.

The expression groups

The type field identifies how an Expression is represented internally. These groups are organizational categories used by Nerdamer's canonicalization logic; they are not general mathematical classifications.

NUM

Plain numeric value

Stores plain numeric values.

3/2
VAR

Variable representation

Stores symbols or variables whose powers fit the variable representation.

x^2
EXP

Separate exponential node

Stores bases with powers that require a separate exponential node. It is not the same thing as the function exp(...).

x^y
FUN

Function call

Stores function calls and their argument expressions.

sin(x)
GRP

Common-base sum

Stores sums with a common base but differing powers.

x + x^ycos(x) - 3*cos(x)^2
PRD

Symbolic product

Stores products of non-numeric symbolic factors. Numeric coefficients are normally moved to the outer multiplier during parsing.

x*y
SUM

Other sums

Stores sums that do not fit the common-base grouping. For example, 1 + x + x^2 contains a numeric term and a grouped polynomial-like component.

1 + x + x^2
INF

Infinite value

Stores infinite values.

Infinity

A node is canonical structure, not source text

Parsing normalizes expressions. Ordering, grouping, multipliers, and powers are chosen to make later symbolic operations predictable, so the tree is not intended to preserve the exact spelling of the input. That is why text() should be read as the canonical representation rather than a source-code round trip.

const expression = Expression.create('2*x + 1');

expression.text();                    // "1+2*x"

expression.evaluate({ x: 3 }).text(); // "7"

Expression is only one parser result type

Most scalar mathematics lands here, but the parser's result union is wider. Algorithms that require an Expression should narrow or convert explicitly rather than assume every parsed value is scalar.

Expressionsymbolic scalar
EquationLHS / RHS structure
Vectorordered values
Matrixtwo-dimensional values
Collectionordered aggregate
ValuesSetfinite set
Dictionarykey/value aggregate
Primary source

The class documentation in Expression.ts describes the group meanings and representation fields directly.

src/core/classes/expression/Expression.ts
Next stop

The parser page explains how source notation is turned into these objects in the first place.

Parser internals