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

Function replace

src/compute-engine/boxed-expression/rules.ts:1249–1416  ·  view source on GitHub ↗
(
  expr: Expression,
  rules: Rule | (Rule | BoxedRule)[] | BoxedRuleSet,
  options?: Partial<ReplaceOptions>
)

Source from the content-addressed store, hash-verified

1247 return {
1248 ...result,
1249 value: computeValue(result.value),
1250 purpose: result.purpose ?? purpose,
1251 };
1252 }
1253
1254 if (!isExpression(result)) {
1255 throw new Error(
1256 'Invalid rule replacement result: expected a Expression or RuleStep'
1257 );
1258 }
1259
1260 return stepOf(computeValue(result));
1261}
1262
1263/**
1264 * Apply the rules in the ruleset and return a modified expression
1265 * and the set of rules that were applied.
1266 *
1267 * The `replace` function can be used to apply a rule to a non-canonical
1268 * expression.
1269 *
1270 * **Error handling contract.** A single misbehaving rule never aborts the
1271 * whole pass. An exception thrown while checking a rule's `condition` or while
1272 * running its `replace` function is logged and that one rule is skipped; the
1273 * remaining rules are still tried (see `applyRule`). Only a
1274 * `CancellationError` (deadline/interrupt) propagates out, so timeouts are not
1275 * swallowed as "the rule failed".
1276 *
1277 * **Ordering contract** (SYMBOLIC P3-14). Rules are tried in declaration
1278 * order. Within a pass, after rule *k* fires, only rules with ordinal > k
1279 * are tried on the result — earlier rules do not see later rules' output
1280 * unless another iteration runs. The default `iterationLimit` is **1**, so
1281 * by default there is a single pass; pass a larger `iterationLimit` (or use
1282 * `simplify()`, which iterates to a fixed point with its own guards) when
1283 * rules are meant to feed each other.
1284 *
1285 * **Capture convention** (SYMBOLIC P3-13). When several distinct bindings
1286 * of a pattern's sequence wildcards would match, which one is produced is
1287 * operator-dependent: the commutative-anchor path and the plain
1288 * argument-list path resolve greedy-vs-lazy differently. Both results are
1289 * valid matches; replacements built from captures should not rely on a
1290 * specific split.
1291 */
1292export function replace(
1293 expr: Expression,
1294 rules: Rule | (Rule | BoxedRule)[] | BoxedRuleSet,
1295 options?: Partial<ReplaceOptions>
1296): RuleSteps {
1297 if (!rules) throw new Error('replace(): Expected one or more rules');
1298
1299 const iterationLimit = options?.iterationLimit ?? 1;
1300 let iterationCount = 0;
1301 const once = options?.once ?? false;
1302 normalizeReplaceForm(options);
1303
1304 // Normalize the ruleset
1305 let ruleSet: ReadonlyArray<BoxedRule>;
1306 if (typeof rules === 'object' && 'rules' in rules) ruleSet = rules.rules;

Callers 9

finalValueFunction · 0.90
trailingBecauseFunction · 0.90
replaceMethod · 0.90
replaceMethod · 0.90
replaceMethod · 0.90
simplifyExpressionFunction · 0.90
applyRuleFunction · 0.70

Calls 7

getRuleIndexFunction · 0.90
candidateRulesFunction · 0.90
normalizeReplaceFormFunction · 0.85
stepOfFunction · 0.85
rulesMethod · 0.65
isSameMethod · 0.65
nextMethod · 0.45

Tested by 2

finalValueFunction · 0.72
trailingBecauseFunction · 0.72