OJaml / docsProject documentation

Reference

AST and Source Spans

Look up syntax, contracts, layouts, algorithms, and exact behavior.

The parser emits a purpose-built AST rather than preserving parser tokens as the executable representation. Program nodes contain declarations. Declaration nodes store the binding name, precise binding span, parameter names, parameter spans, body expression, and full declaration span. Module declarations store a module name and the qualified value, type, and nested module declarations inside its struct body. Expression nodes carry a kind-specific payload and a source span.

Program
  declarations: TopLevelDeclaration[]

TopLevelDeclaration
  Let | Type | Open | Module

Declaration
  kind: Let
  recursive: boolean
  name: string
  nameSpan: SourceSpan
  params: string[]
  paramSpans: SourceSpan[]
  value: Expr
  span: SourceSpan

TypeDeclaration
  kind: Type
  name: string
  params: TypeParameter[]
  body: RecordType | VariantType

OpenDeclaration
  kind: Open
  module: string

ModuleDeclaration
  kind: Module
  name: string
  declarations: Declaration[]

Expr
  Int | Float | String | Bool | Unit | Tuple | TupleAccess | Record | FieldAccess | Var
  Unary | Binary | Sequence | If | LetIn | Call | Fun | Match

LetIn
  recursive: boolean
  name: string
  value: Expr
  body: Expr

Pattern
  PInt | PFloat | PString | PBool | PUnit
  PTuple | PRecord | PArray | PSet | PMap | PConstructor
  PListNil | PListCons | PWildcard | PVar
AST shape. The AST mirrors the implemented language constructs, and binder spans are first-class data.
∀n∈AST,  0≤n.start≤n.end≤∣source∣\forall n \in AST,\; 0 \le n.start \le n.end \le |source|
Span invariant. Every diagnostic or hover range is an interval over the original source.

Spans are not cosmetic. They are part of the language service contract. Diagnostics use spans to mark errors; editor hovers use spans to identify exactly which token is being described; local binders and function parameters keep separate name spans so a hover over the binder reports the same inferred type as a hover over a later use.

This design keeps binding structure in the AST, so downstream passes do not need to re-tokenize source text to understand binding sites. The checker can annotate the program with symbol and token metadata after unification has resolved type variables.

  • Declaration name spans and parameter spans make top-level hovers precise.
  • Local let name spans make inferred local values hoverable at the binding site.
  • Function parameter spans make anonymous function parameters hoverable.
  • Pattern spans make variable catch-all and tuple-destructured bindings available to diagnostics and hovers.