Skip to content

Commit 3c42155

Browse files
committed
arch: free functions
1 parent 8b22e22 commit 3c42155

9 files changed

Lines changed: 238 additions & 456 deletions

File tree

README.md

Lines changed: 29 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -26,87 +26,38 @@ $ npm install --save @cortex-js/compute-engine
2626

2727
### Basic Parsing and Evaluation
2828

29-
```js
30-
import { ComputeEngine } from "@cortex-js/compute-engine";
31-
32-
const ce = new ComputeEngine();
33-
34-
// Parse LaTeX and evaluate
35-
const result = ce.parse("2^{11}-1").evaluate();
36-
console.log(result.toString());
37-
// ➔ 2047
38-
39-
// Check properties
40-
ce.parse("2^{11}-1 \\in \\Z").evaluate().print();
41-
// ➔ True
42-
```
43-
44-
### Workflow Helpers (Parse + Transform)
45-
46-
For common app flows, you can use the high-level workflow helpers:
29+
No setup required:
4730

4831
```js
49-
import { ComputeEngine } from "@cortex-js/compute-engine";
32+
import { parse, simplify, evaluate, N, assign } from "@cortex-js/compute-engine";
5033

51-
const ce = new ComputeEngine();
52-
53-
// Parse then simplify
54-
ce.parseSimplify("x + x + 1").print();
34+
simplify("x + x + 1").print();
5535
// ➔ 2x + 1
5636

57-
// Select simplification strategy presets
58-
ce.parseSimplify("2\\sin(x)\\cos(x)", { simplifyMode: "trigonometric" }).print();
59-
// ➔ sin(2x)
60-
61-
// Parse then evaluate (using current context)
62-
ce.assign("x", 3);
63-
ce.parseEvaluate("x + 2").print();
64-
// ➔ 5
37+
evaluate("2^{11} - 1").print();
38+
// ➔ 2047
6539

66-
// Parse then compute numeric approximation
67-
ce.parseNumeric("\\sqrt{2}").print();
40+
N("\\sqrt{2}").print();
6841
// ➔ 1.414213562...
6942

70-
// Use permissive parsing for plain function names such as sin(x)
71-
ce.parseSimplify("sin(x)", { parseMode: "permissive" }).print();
72-
// ➔ sin(x)
73-
74-
// Choose exact or numeric evaluation behavior
75-
ce.parseEvaluate("\\sqrt{2}", { evaluateMode: "exact" }).print();
76-
// ➔ sqrt(2)
77-
ce.parseEvaluate("\\sqrt{2}", { evaluateMode: "numeric" }).print();
78-
// ➔ 1.414213562...
43+
assign("x", 3);
44+
evaluate("x + 2").print();
45+
// ➔ 5
7946
```
8047

81-
These methods return `null` when the input LaTeX is `null`.
82-
When both a preset and explicit options are provided, explicit `parse`/`evaluate`
83-
options take precedence. Likewise, explicit `simplify.strategy` takes precedence
84-
over `simplifyMode`.
85-
86-
### Extension Contracts
87-
88-
Plugin-facing extension points now enforce runtime contracts:
89-
90-
- `ce.registerCompilationTarget(name, target)` validates target names and
91-
required `LanguageTarget` methods (`getOperators()`, `getFunctions()`,
92-
`createTarget()`, `compile()`).
93-
- Custom libraries passed with `new ComputeEngine({ libraries: [...] })` are
94-
validated for `name`, `requires`, `definitions`, and `latexDictionary` shape.
95-
- Rule replacement callbacks must return a boxed expression or a valid rule step.
96-
97-
Architecture snapshot: [docs/architecture/CURRENT-ARCHITECTURE.md](docs/architecture/CURRENT-ARCHITECTURE.md)
48+
These functions use a shared `ComputeEngine` instance created on first use. Use
49+
`getDefaultEngine()` to configure it, or create your own instance for isolated
50+
configurations.
9851

9952
### Working with Numbers (Type-Safe)
10053

10154
Use type guards to safely access specialized properties:
10255

10356
```js
104-
import { ComputeEngine, isBoxedNumber } from "@cortex-js/compute-engine";
57+
import { evaluate, isBoxedNumber } from "@cortex-js/compute-engine";
10558

106-
const ce = new ComputeEngine();
107-
const expr = ce.parse("\\frac{5}{2}").evaluate();
59+
const expr = evaluate("\\frac{5}{2}");
10860

109-
// ✓ Modern approach with type guards
11061
if (isBoxedNumber(expr)) {
11162
console.log(expr.numericValue); // 2.5 (type-safe access)
11263
console.log(expr.isInteger); // false
@@ -116,18 +67,17 @@ if (isBoxedNumber(expr)) {
11667
### Working with Symbols
11768

11869
```js
119-
import { ComputeEngine, isBoxedSymbol, sym } from "@cortex-js/compute-engine";
70+
import { parse, isBoxedSymbol, sym } from "@cortex-js/compute-engine";
12071

121-
const ce = new ComputeEngine();
122-
const expr = ce.parse("x + 1");
72+
const expr = parse("x + 1");
12373

12474
// Check if expression is a specific symbol
12575
if (sym(expr) === "x") {
12676
console.log("This is the variable x");
12777
}
12878

12979
// Or use full type guard for more access
130-
const variable = ce.parse("y");
80+
const variable = parse("y");
13181
if (isBoxedSymbol(variable)) {
13282
console.log(variable.symbol); // "y"
13383
}
@@ -136,10 +86,9 @@ if (isBoxedSymbol(variable)) {
13686
### Working with Functions
13787

13888
```js
139-
import { ComputeEngine, isBoxedFunction } from "@cortex-js/compute-engine";
89+
import { parse, isBoxedFunction } from "@cortex-js/compute-engine";
14090

141-
const ce = new ComputeEngine();
142-
const expr = ce.parse("2x + 3y");
91+
const expr = parse("2x + 3y");
14392

14493
// Access function structure safely
14594
if (isBoxedFunction(expr)) {
@@ -156,44 +105,44 @@ if (isBoxedFunction(expr)) {
156105
### Simplification and Manipulation
157106

158107
```js
159-
import { ComputeEngine, expand } from "@cortex-js/compute-engine";
108+
import { parse, simplify, expand } from "@cortex-js/compute-engine";
160109

161-
const ce = new ComputeEngine();
162110

163111
// Simplify expressions
164-
ce.parse("x + x").simplify().print();
112+
simplify("x + x").print();
165113
// ➔ 2x
166114

167115
// Expand expressions (free function)
168-
const expr = ce.parse("(x + 1)^2");
116+
const expr = parse("(x + 1)^2");
169117
expand(expr).print();
170118
// ➔ x^2 + 2x + 1
171119

172120
// Substitute values
173-
const expr2 = ce.parse("x^2 + 2x + 1");
121+
const expr2 = parse("x^2 + 2x + 1");
174122
expr2.subs({ x: 3 }).evaluate().print();
175123
// ➔ 16
176124
```
177125

178126
### Solving Equations
179127

180128
```js
181-
const ce = new ComputeEngine();
182129

183130
// Solve linear system
184-
const system = ce.parse("\\begin{cases}x+y=5\\\\x-y=1\\end{cases}");
131+
const system = parse("\\begin{cases}x+y=5\\\\x-y=1\\end{cases}");
185132
const solution = system.solve(["x", "y"]);
186133

187134
console.log(solution.x.json); // 3
188135
console.log(solution.y.json); // 2
189136
```
190137

191138
**💡 Best Practices:**
192-
- Always use type guards (`isBoxedNumber`, `isBoxedSymbol`, `isBoxedFunction`) before accessing specialized properties
193-
- Import type guards from `@cortex-js/compute-engine` alongside `ComputeEngine`
139+
140+
- Always use type guards (`isBoxedNumber`, `isBoxedSymbol`, `isBoxedFunction`)
141+
before accessing specialized properties
194142
- Use the `sym()` helper for quick symbol name checks
195143

196-
**📚 Learn More:** [Full documentation and guides](https://cortexjs.io/compute-engine/)
144+
**📚 Learn More:**
145+
[Full documentation and guides](https://cortexjs.io/compute-engine/)
197146

198147
## FAQ
199148

docs/README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Compute Engine Docs Guide
2+
3+
This directory contains both user-facing guides and internal engineering
4+
snapshots.
5+
6+
## Start Here
7+
8+
For installation, quick-start examples, and the main public API entrypoints,
9+
read the repository [`README.md`](../README.md).
10+
11+
## Documentation Map
12+
13+
| Goal | Recommended doc |
14+
| --- | --- |
15+
| Learn package usage quickly | [`../README.md`](../README.md) |
16+
| Use parse-and-transform helper methods | This file (Workflow Helpers section) |
17+
| Understand simplification behavior snapshots | [`SIMPLIFY.md`](./SIMPLIFY.md), [`SIMPLIFICATIONS.md`](./SIMPLIFICATIONS.md) |
18+
| Review playground sample outcomes | [`PLAYGROUND.md`](./PLAYGROUND.md) |
19+
| Review internal architecture boundaries | [`architecture/README.md`](./architecture/README.md) |
20+
21+
## Workflow Helpers
22+
23+
High-level workflow entrypoints:
24+
25+
- `ce.parseSimplify(latex, options?)`
26+
- `ce.parseEvaluate(latex, options?)`
27+
- `ce.parseNumeric(latex, options?)`
28+
29+
Policy presets:
30+
31+
- Parse policy: `parseMode: 'strict' | 'permissive'`
32+
- Evaluation policy: `evaluateMode: 'exact' | 'numeric'` (`parseEvaluate`)
33+
- Simplification policy: `simplifyMode: 'default' | 'trigonometric'` (`parseSimplify`)
34+
35+
Option precedence (explicit low-level options win):
36+
37+
- `parse.strict` overrides `parseMode`
38+
- `evaluate.numericApproximation` overrides `evaluateMode`
39+
- `simplify.strategy` overrides `simplifyMode`
40+
41+
## Extension Contracts
42+
43+
Runtime contract checks are enforced for extension points:
44+
45+
- `registerCompilationTarget(name, target)` validates target name format and required `LanguageTarget` methods (`getOperators()`, `getFunctions()`, `createTarget()`, `compile()`).
46+
- `new ComputeEngine({ libraries: [...] })` validates custom library shape (`name`, `requires`, `definitions`, `latexDictionary`).
47+
- `compile(expr, options)` validates extension-facing payload shape (`to`, `target`, `operators`, `functions`, `vars`, `imports`, `preamble`, `fallback`).
48+
49+
## Snapshot Reports
50+
51+
These files are useful implementation snapshots, but they are not a canonical
52+
API reference:
53+
54+
- [`PLAYGROUND.md`](./PLAYGROUND.md)
55+
- [`SIMPLIFICATIONS.md`](./SIMPLIFICATIONS.md)
56+
- [`SIMPLIFY.md`](./SIMPLIFY.md)

docs/architecture/CURRENT-ARCHITECTURE.md

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ This document captures the implemented architecture after the recent modularizat
6060
| `engine-library-bootstrap.ts` | Resolves library entries, topological sort, loads definitions, collects LaTeX dictionaries |
6161
| `engine-common-symbols.ts` | Initializes well-known symbol bindings (True, False, Pi, E, Nothing) |
6262

63-
### Parsing & Workflows
63+
### Parsing & Free Functions
6464
| File | Responsibility |
6565
|------|---------------|
6666
| `engine-parse-entrypoint.ts` | Engine-specific parse defaults, symbol type resolution, boxing of parse results |
67-
| `engine-workflow-entrypoints.ts` | High-level `parseSimplify/parseEvaluate/parseNumeric` combining parse + operation |
67+
| `free-functions.ts` | Top-level free functions (`parse`, `simplify`, `evaluate`, `N`, `assign`) backed by a lazy global engine |
6868

6969
### Validation & Errors
7070
| File | Responsibility |
@@ -101,25 +101,18 @@ This document captures the implemented architecture after the recent modularizat
101101
| `engine-compilation-targets.ts` | Registry for named compilation targets (JavaScript, GLSL, etc.) |
102102
| `engine-type-resolver.ts` | Type resolution callback for parser integration |
103103

104-
## Public Workflow API Policy
105-
106-
- `parseSimplify()`
107-
- Parse presets: `parseMode = strict | permissive`
108-
- Simplify presets: `simplifyMode = default | trigonometric`
109-
- `parseEvaluate()`
110-
- Parse presets: `parseMode = strict | permissive`
111-
- Evaluate presets: `evaluateMode = exact | numeric`
112-
- `parseNumeric()`
113-
- Parse presets: `parseMode = strict | permissive`
114-
115-
Precedence rule across workflow helpers:
116-
- Explicit low-level options always win over presets.
117-
- `parse.strict` overrides `parseMode`
118-
- `evaluate.numericApproximation` overrides `evaluateMode`
119-
- `simplify.strategy` overrides `simplifyMode`
120-
- This is implemented via object spread: the preset sets a default, then `...options.parse` overwrites it.
121-
122-
Note: `simplifyMode: 'trigonometric'` maps to the internal `strategy: 'fu'` (the Fu algorithm for trigonometric simplification, named after Fu, Zhong, and Zeng).
104+
## Free Functions & Lazy Global Engine
105+
106+
Top-level free functions (`parse`, `simplify`, `evaluate`, `N`, `assign`) are exported from `index.ts` via `free-functions.ts`. They are backed by a lazily-instantiated global `ComputeEngine` accessible via `getDefaultEngine()`.
107+
108+
- `parse(latex)` — parse a LaTeX string
109+
- `simplify(latex | expr)` — simplify a LaTeX string or BoxedExpression
110+
- `evaluate(latex | expr)` — evaluate a LaTeX string or BoxedExpression
111+
- `N(latex | expr)` — numeric approximation
112+
- `assign(id, value)` / `assign({...})` — assign values in the global engine
113+
- `getDefaultEngine()` — access the shared engine instance for configuration
114+
115+
The global engine is created on first call to any free function, using a dynamic `require('./index')` inside `getDefaultEngine()` to avoid circular dependency (since `index.ts` re-exports `free-functions.ts`).
123116

124117
## Extension Contracts (Runtime Guards)
125118

src/compute-engine.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ export { BaseCompiler } from './compute-engine/compilation/base-compiler';
3232
export { expand } from './compute-engine/boxed-expression/expand';
3333
export { compile } from './compute-engine/compilation/compile-expression';
3434

35+
// Free functions backed by a lazily-instantiated global engine
36+
export {
37+
parse,
38+
simplify,
39+
evaluate,
40+
N,
41+
assign,
42+
getDefaultEngine,
43+
} from './compute-engine/free-functions';
44+
3545
export {
3646
isBoxedExpression,
3747
isBoxedNumber,

0 commit comments

Comments
 (0)