Skip to content

refactor/feat: changes and additions to ReplaceOptions ('form', 'direction')#305

Open
samueltlg wants to merge 5 commits into
cortex-js:mainfrom
samueltlg:pr/replace-options-split
Open

refactor/feat: changes and additions to ReplaceOptions ('form', 'direction')#305
samueltlg wants to merge 5 commits into
cortex-js:mainfrom
samueltlg:pr/replace-options-split

Conversation

@samueltlg
Copy link
Copy Markdown
Contributor

@samueltlg samueltlg commented May 17, 2026

(This is all-ready [-and slightly improved])

Summary

This PR breaks out ReplaceOptions-related work into smaller, reviewable commits.

  • feat: add ReplaceOptions.direction (from 6e116c1)
  • refactor: transition ReplaceOptions from canonical to form while retaining deprecated canonical alias for compatibility
  • fix: split out replacement-sameness behavior so expression form differences are considered in replacement success checks
  • fix (workaround): canonical/non-canonical match-pattern variant comparison during rule application (from 57ce573)
  • docs: add Upcoming changes notes to CHANGELOG under Added, Fixed, and Changes

Notes

  • ReplaceOptions.canonical is retained as a deprecated alias to avoid immediate API breakage; form is preferred.
  • Validation rejects specifying both form and canonical together.
  • Form application is scoped to replacements, while eager upward form propagation remains when replacement branches fully satisfy the target form.

@samueltlg samueltlg force-pushed the pr/replace-options-split branch from e1e8898 to 5a82c5a Compare May 18, 2026 00:27
samueltlg added 4 commits May 18, 2026 17:34
Retain canonical as a deprecated alias, accept both option names for one release, and keep the replacement-form transition separate from the replacement-sameness change.
…ssion 'form'

Treat form changes as meaningful during recursive replace iteration so eager form propagation can surface even when structural equality stays the same. This keeps the replacement-form behavior separate from the ReplaceOptions API transition.
…attern variant comparison (rule application)

(this change is marked as a *workaround* rather than a 'fix' per se, since the issue it tackles instead likely has its root in the current behaviour regarding the binding of 'wildcard' symbol variants (-outside the context of pattern matching / replacement.
(See the closing of this message for a further remark on this point.))

Explanation:
- Currently, because canonicalization of expresssions involves wildcard  binding as part of symbol binding (this may be undesirable / a bug), it is presently necessary that a new scope be created upon 'match' pattern canonicalization (performed for optimization purposes) in rule application:  with this otherwise running the risk of present wildcard symbols being bound to definitions in the current scope...

For example, before this change:
```
ce.expr(['Add', 'x', 3]).replace({ match: ['_', '__'], replace: 'y'});

// →Expectedly captures wildcards, and replaces
// top-level expression.
// *However*, the canonical-request of the 'match' expression within 'applyRule'
// results in symbol/wildcard '_' being attributed a function-definition
// (type='function'): within the scope in which this 'expr.replace()' was called

// Consequently, a subsequent replace call involving a universal wildcard
ce.expr(['Add', 'x', 3]).replace({ match: ['Add', 'x', '_')], replace: 5 });

// → Returns 'null'... (assuming this call made with an unmodified/same scope as the previous)
// Ultimately because the same point-of-canonicalization results in the Universal
// Wildcard in this instance uptaking the previous, 'function' definition, resulting
// in a MathJson-internal type-error for the canonicalized match-pattern variant
// in this instance, resulting in an absent wildcard in the canonical variant,
// and leading to an early exit from rule-application 'applyRule()'

//For illustration, the canonical-variant of the initial, non-canonically boxed
// `['Add', 'x', 3]` pattern results in the canonical-variant as:

[ "Add", "x", [ "Error", [ "ErrorCode", "'incompatible-type'", "number", "function", ], ], ]
```

*Note*:
- This 'fix' may no longer be necessary, if canonicalization of wildcard-containing expressions were to no longer perform name-binding on these (this may be unintentional?)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant