BankLang

BankLang Architecture

1. Architecture overview

BankLang is a deterministic compiler toolchain.

BankTS source
  -> lexer/parser
  -> AST
  -> type checker
  -> semantic analyzer
  -> banking safety analyzer
  -> platform-independent IR
  -> COBOL-oriented IR
  -> backend emitters
  -> generated COBOL/copybooks/JCL/audit artifacts

The same source and the same configuration produce byte-identical artifacts. That is a property bankc verify checks rather than a goal.

An AI coding assistant helped write this repository, and nothing in the compiler is a model. No generated artifact depends on one, at build time or at run time. Every decision about what COBOL comes out is code somebody can read in packages/.

2. Core packages

packages/bankc-cli

Responsibilities:

Commands, as bankc itself lists them:

tests/architecture.test.ts compares that list against the CLI's own help text in both directions, so a command this page omits fails the build and so does one it invents.

packages/parser

Responsibilities:

Must not perform semantic checks beyond syntax validity.

packages/ast

Responsibilities:

packages/typechecker

Responsibilities:

packages/semantic-analyzer

Responsibilities:

packages/ir

Responsibilities:

IR must not be COBOL text. It must represent program meaning.

packages/cobol-ir

Responsibilities:

packages/cobol-backend

Responsibilities:

packages/compiler

The pipeline as one call. compile() runs parse, typecheck, semantic analysis, lowering and emission, and returns the diagnostics, the COBOL, the copybooks, the JCL and the source map together. The CLI, the playground and the tests all enter here, so there is one order of phases rather than three.

packages/copybook

Responsibilities:

Db2, CICS and VSAM do not have packages of their own. Each is a set of constructs spread across the phases that have to agree about it: the syntax in parser, the types and host-variable rules in typechecker, the required error handling in semantic-analyzer, the shape in ir, and the emitted EXEC SQL / EXEC CICS blocks and FILE-CONTROL / FD entries in cobol-backend. A package per subsystem would have to reach into all five.

packages/precompiler

Responsibilities:

packages/cobol-runtime

An interpreter for the COBOL this compiler emits: reference-format reader, tokenizer, statement parser, and a machine with the picture, packed-decimal and edited-field model behind it, plus files, cursors, the ledger and the audit log.

It exists to disagree. Every example is executed twice, once by cobc and once here, and a test fails on any difference — which is what catches a defect that compiles and passes every static check.

packages/verifier

Responsibilities:

The golden tests, decimal property tests and audit-schema checks are suites in tests/, not code in this package.

packages/conformance-lint

Checks generated COBOL and JCL against the target's rules rather than against a style: reserved words, intrinsic function names, reference-format columns, and the constraints in target conformance. This is what grades an example nothing local can compile.

packages/zos-lint

Rules over emitted COBOL that only matter on z/OS — commarea writes, CALL operands, statement-level conventions the compiler is expected to honour.

packages/zunit

Emits IBM zUnit test cases for a generated program, so the output can be tested by the target's own framework rather than only by this repository.

packages/migration-analysis

Reads COBOL you already have: paragraph graph, file use, SQL use, CICS use, an inventory, and which of COBOL's constructs each member contains. It states its own limits rather than guessing; see migration analysis.

packages/horizontal-validation

The other axis of validation. Everything else here is vertical — tests written for BankLang, measuring BankLang against what their author expected — and this is what measures the compiler against COBOL nobody wrote for it: independent corpora, their licences, the rules that decide what BankTS can represent, and the arithmetic that reports the answer with its denominator attached.

It reaches no network and fetches nothing. Corpora arrive in an ignored cache through tools/horizontal-fetch.ts, pinned by validation/corpus-lock.json; this package reads what is on disk. See horizontal validation.

packages/formatter

Formats BankTS. One canonical form, printed from the AST, so bankc fmt --check is a build step rather than a preference.

packages/diagnostics

Responsibilities:

No diagnostic can be emitted without a catalogue entry.

packages/config

The banklang.json model, its JSON Schema, and the loader. The schema and the accepted values are generated from one table, so a profile cannot be offered by the schema and rejected by the loader.

packages/language-server

An LSP server over stdio: diagnostics as you type, and the source-to-COBOL mapping the editor navigates by.

packages/vscode-extension

The editor client: BankTS syntax, the language server above, and the COBOL a line produced.

packages/playground

The whole compiler in a browser — no compile server, and nothing the reader writes is sent anywhere. Editors for BankTS and the emitted COBOL, the source map as a click-through between them, and Run over cobol-runtime.

packages/site

The static site: landing page, rendered documentation, blog, and the headers served with them.

3. Intermediate representation

The IR should model these concepts explicitly:

Example IR concept:

{
  "kind": "DecimalAdd",
  "left": "amount",
  "right": "fee",
  "precision": 18,
  "scale": 2,
  "rounding": "HALF_EVEN",
  "overflow": "DIAGNOSTIC"
}

The IR must preserve enough metadata to generate both COBOL and audit evidence.

4. Backend profiles

ibm-enterprise-cobol-zos

Primary target.

Expected output:

gnucobol-local

Local development target.

Expected output:

There are two profiles and no others. BACKEND_PROFILES in packages/config/src/index.ts is the list, and the JSON Schema is generated from it.

5. Determinism requirements

The same source files and same compiler version must produce the same output bytes.

Required controls:

6. Source mapping

Every generated COBOL paragraph, data item, copybook record and audit event maps back to the BankTS span that asked for it. bankc verify fails when one does not, which is what makes traceability a measurement rather than a claim.

Source map should include:

7. Error handling model

Errors must be explicit.

Compiler diagnostics have:

Example:

BANK-DEC-003 error
Amount decimal<18,4> assigned to decimal<18,2> without explicit rounding.
Use round(amount, scale: 2, mode: HALF_EVEN).

8. Build artifacts

A build may produce:

dist/
  cobol/
  copybooks/
  jcl/
  maps/
  audit/
  zunit/

dist is the default outDir; banklang.json and --out both move it.

The audit folder must be machine-readable and human-readable.

9. Dependency policy

Core packages carry as few dependencies as they can. A parser generator is allowed only where its output is deterministic and somebody can read it.

Compiler logic lives in this repository. Nothing that decides what COBOL is emitted sits behind a network call or in a service this repository does not contain.


Read this page as Markdown on GitHub →