FS FormScript
Package@formscript/analyzer
Specification2.3, 10.6, 12.6, 14
Depends onast, cost, errors, scope, types

@formscript/analyzer

Static analysis of a FormScript document — the commitment of §2.3 of the specification.

The analyzer answers one question: can this document ever be compiled? It runs before any evaluation and reports every error the specification requires a conforming runtime to catch at compile time.

What it detects

Class Codes
Undefined and duplicated names E-REF-01, E-REF-02
Unknown or misplaced properties E-PROP-01, E-PROP-02, E-PROP-07
Conflicting declarations E-CONFLICT-01 … E-CONFLICT-06
Static type errors E-TYPE-01, E-TYPE-02, E-TYPE-05, E-TYPE-06, E-TYPE-07, E-TYPE-08
Computed cycles E-CYCLE-01
Malformed relations, no acyclic causality E-REL-01, E-REL-03
Unresolved output paths E-OUT-01
Unknown profile E-PROF-01
Statically contradictory constraints E-BOUND-01, E-BOUND-02, E-BOUND-03, E-BOUND-05, E-SAT-01
Over-budget or unbounded expressions E-COST-01
Warnings W-BUILTIN-01, W-TEXT-01, W-VAL-01

Usage

ts
import { analyze } from '@formscript/analyzer';

const result = analyze(document, { file: 'application.forms' });

if (!result.ok) {
  for (const error of result.errors) {
    console.error(`${error.code} ${error.location?.line}:${error.location?.column} ${error.message}`);
  }
}

analyze returns every diagnostic it produced in diagnostics, and the reported set in reported: the errors of the earliest non-empty stage, plus every warning. The stage of a diagnostic is the class of its code in the catalogue of §14, and the stage order is the order of that catalogue's sections. See applyDiagnosticOrder, which applies the same rule to the lexer's and the parser's diagnostics.

Notes

  • The analyzer never evaluates an expression. Tier A1 satisfiability (§10.6.1) works on the AST and the type lattice alone.
  • A value of type any suppresses every type error, because the type system cannot prove anything about it. The runtime checks it instead.
  • The two-planes rule (§12.6) is checked over the operands a computation consumes, so a ternary branch or a coalesce operand — which is an alternative, not an operand — may carry a display value: it is the expression's own result, and a custom constraint may use it as its message (Spec-12.9).
  • A choice declares an enum type and nothing else (Spec-7.13): options and optionsFrom on a choice are E-PROP-02, and a choice whose type is not an enum is E-TYPE-02.

Public API

32 exported symbols.

ALL_PROPERTY_NAMES re-export
AnalysisOptions interface
AnalysisResult interface
analyze function

Runs the static analysis of §2.3 over a parsed document.

Analyzer class
applyDiagnosticOrder function

Applies the stage order of Spec-2.5 to a set of diagnostics. Errors of the earliest non-empty stage are kept; every later error is suppressed. Warnings are a…

BUILTINS const
builtinSignature function
BuiltinSignature interface
checkPattern function
compatible re-export
DIAGNOSTIC_STAGES const

The diagnostic stages, in the order of the catalogue's sections (§14). Spec-2.5 requires that every error of the earliest non-empty stage is reported and tha…

EntityKind type
findCycle function

Finds a cycle by depth-first search with a colouring scheme (Spec-9.4).

Graph type
inferType re-export
isDisplay function
isNumeric function
isPropertyKnown re-export
isTemporal function
isTextual function
iterationResolver function

The declared maximum size of an iterated collection (Spec-6.46).

ParamSpec interface
PatternVerdict type
propertiesFor re-export
PropertyDefinition interface
readPaths function

The declaration paths an expression reads.

referencePath function

The path of a reference expression, or `null` when it is not a plain path.

requiredPropertiesFor re-export
resolvePath function

Resolves a reference path, falling back to an object's declared members.

stageOf function
TypeContext interface