Skip to content
lingo

Calculations

Evaluate mixed unit math without turning lingo into a CAS.

Prefer the live demos? Open this section in the interactive docs.

Arithmetic over quantities lives in @pascal-app/lingo/calc. lingo() never evaluates expressions — mixed-unit compounds like 2 ft + 3 in stay compounds, 5-10 kg stays a range, and 2+3 kg is trailing input rather than a silent 2–3 kg range. calc() is a closed calculator: no variables, no functions, no dimensional algebra.

import { calc } from "@pascal-app/lingo/calc"
import { quantityField } from "@pascal-app/lingo/ai"
import { completions } from "@pascal-app/lingo/complete"

const million = calc("7m*2")
million.ok && million.value                         // 14000000
million.ok && million.format({ style: "words" })    // "14 million"
million.ok && million.format({ style: "grouped" })  // "14,000,000"
million.ok && million.format({ style: "scientific" }) // "14e6"
million.ok && million.format({ style: "compact" })  // "14m"
million.ok && million.expression                    // "7e6 × 2"
million.ok && million.latex                         // "7 \\times 10^{6} \\times 2"

const duration = calc("9min x 4")
duration.ok && duration.format()                    // "36 min"
duration.ok && duration.format({ unit: "h" })       // "0.6 h"

calc("half of 56kg+1700g")                          // 28.85 kg

quantityField({ kind: "mass", unit: "kg", calc }).parse("12 * 0.75 kg") // 9
completions("=2+3 kg", { calc: (text) => calc(text, { trigger: "=" }) })

Glued m/M at an operator boundary is million (7m*2 → 14 million) unless kind is length or duration; spaced 7 m is meters; 1m80 stays 1.80 m. Compact "14m" round-trips through calc(), not lingo(). Same-kind q / q cancels to a dimensionless ratio; q * q is SCALAR_EXPECTED. Additive affine units warn AFFINE_DELTA_ASSUMED and delta-convert. formatExpression is two-way infix; formatLatex is display-only.

Inject calc into completions({ calc }) and quantityField({ calc }) so =2+3 kg and 12 * 0.75 kg evaluate without bundling the calculator into those entries. Completions only fire on a leading =, so 5-10 kg is not stolen. rangeField stays range-first.