MCPcopy Create free account
hub / github.com/cortex-js/compute-engine / eq

Function eq

src/compute-engine/boxed-expression/compare.ts:136–258  ·  view source on GitHub ↗
(
  a: Expression,
  inputB: number | Expression
)

Source from the content-addressed store, hash-verified

134 // The lenient form — either side unbound ⇒ equal — was not merely "outside
135 // the relation for raw expressions": a CANONICAL expression can CONTAIN raw
136 // operands, because a lazy operator holds them un-canonicalized. So a
137 // canonical `Map(…)` holding a raw `q` compared equal to canonical `Map(…)`s
138 // from two different scopes that were themselves unequal — the transitivity
139 // bridge sat inside the domain every dedup key uses.
140 //
141 // A caller that legitimately compares a TEMPLATE against a bound subject
142 // asks for it explicitly (`sameSyntactic`) rather than relying on
143 // unboundness as an implicit signal.
144 return false;
145}
146
147/**
148 * Is `def` the standard-library definition of `sym.symbol`?
149 *
150 * The engine's ROOT scope (the end of the parent chain) holds exactly the
151 * standard library; every user declaration — including a top-level one —
152 * lands in a child scope. Only reached when the two sides' definitions
153 * already differ in identity, so the chain walk is off the hot path.
154 */
155function isLibraryBinding(
156 sym: Expression & { symbol: string },
157 def: BoxedBaseDefinition
158): boolean {
159 let scope = sym.engine.context?.lexicalScope;
160 if (scope === undefined) return false;
161 // Loose check: the chain terminates with `null` OR `undefined` depending on
162 // how the root context was built.
163 while (scope.parent != null) scope = scope.parent;
164 const binding = scope.bindings.get(sym.symbol);
165 if (binding === undefined) return false;
166 // A scope binding is a tagged record; `baseDefinition` unwraps it, so
167 // compare against both halves. (Inline — `isValueDef`/`isOperatorDef` live
168 // in `utils.ts`, whose import would close the cycle `binders.ts` broke.)
169 return (
170 ('value' in binding && binding.value === def) ||
171 ('operator' in binding && binding.operator === def)
172 );
173}
174
175/**
176 * Structural equality that compares symbols by NAME, ignoring bindings.
177 *
178 * For comparing a TEMPLATE against a subject: a rule pattern is parsed raw so
179 * canonicalization cannot collapse its structure or mangle its wildcards,
180 * which leaves its literal symbols unbound — the `\pi` of `\pi + a -> 2a`
181 * must still match a canonical `π`. That is a question about syntax, not
182 * about which binding a symbol denotes, so it gets its own entry point.
183 */
184export function sameSyntactic(a: Expression, b: Expression): boolean {
185 return same(a, b, undefined, undefined, true);
186}
187
188/** What a node binds: name → its definition, or `null` when the binder names
189 * the variable without owning its definition. See `boundVariableBindings`. */
190type BinderMap = ReadonlyMap<string, BoxedValueDefinition | null>;
191
192/**
193 * Does an occurrence denote the enclosing binder?

Callers 5

isEqualFunction · 0.90
isSymmetricFunction · 0.85
isSkewSymmetricFunction · 0.85
equalsFunction · 0.85

Calls 13

isFunctionFunction · 0.90
stochasticEqualFunction · 0.90
isSymbolFunction · 0.90
isNumberFunction · 0.90
isZeroWithToleranceFunction · 0.70
sameFunction · 0.70
exprMethod · 0.65
NMethod · 0.65
isSameMethod · 0.65
subMethod · 0.65
simplifyMethod · 0.65
askMethod · 0.65

Tested by

no test coverage detected