Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

291 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BankLang

banklang.mwhassan.com — the compiler runs in your browser at /playground/.

A deterministic compiler from a small banking language to readable IBM Enterprise COBOL — with banking safety rules enforced at compile time.

CI License: MIT Node

BankLang compiles BankTS into COBOL a mainframe engineer can read and review. Its types are TypeScript's; its statements — transaction, file, cursor, queue — are its own. Everything it emits is decided by code you can read: no model is involved, and the same input always produces byte-identical output.

Translation is the ordinary part. What the compiler does beyond it is refuse to build unsafe programs.

transaction postTransfer(request: TransferRequest) {
  debit(request.debitAccount, request.amount);
  credit(request.creditAccount, request.fee); // ← a different amount
}
BANK-TXN-001  Transaction postTransfer has no idempotency key.
BANK-AUD-001  Transaction postTransfer does not emit an audit event.
BANK-LED-001  Transaction postTransfer does not balance:
              debited request.amount against credited request.fee.

Each is a compile error rather than a production incident.

Validated with GnuCOBOL, not IBM. Every example compiles in CI under a GnuCOBOL configuration shaped to Enterprise COBOL 6.4 and under GnuCOBOL's own default. No IBM Enterprise COBOL validation is claimed.

Built with AI assistance. The design and the decisions are the author's; much of the implementation was written with an AI coding assistant under review. That describes how the compiler was built. Nothing inside it is a model, at build time or at run time.

Read this first → · If you have to accept the output → · What it does not do →


Try it

Open the playground — nothing to install, and nothing you write is sent anywhere.

Click a line of BankTS and the COBOL it produced lights up, from the source map. Fill in the entry record or dataset on Input, then Run executes it against the reference runtime in runtime/ and shows what it posted. Locally: pnpm install && pnpm playground:dev.

What it generates

From one BankTS module, bankc build emits a COBOL program, a copybook per record, the JCL to build and run it, a source map, and an audit bundle.

Interest accrual, in full:

function accrue(balance: MoneyBDT, rate: Rate): MoneyBDT {
  return round(balance * rate, "HALF_EVEN");
}

MoneyBDT is decimal<18, 2> and Rate is decimal<9, 4>, so the product has scale 6. Storing it as money discards four digits, which the compiler will not do silently: round with an explicit mode is required.

Enterprise COBOL has one rounding phrase, and ROUNDED is half-up away from zero. Banker's rounding is arithmetic this compiler writes out:

           EVALUATE TRUE
               WHEN FUNCTION ABS (BANK-RND-1-EXCESS) > 0.005
                   ADD BANK-RND-1-STEP TO BANK-RND-1-VALUE
               WHEN FUNCTION ABS (BANK-RND-1-EXCESS) = 0.005
                   IF FUNCTION MOD (BANK-RND-1-UNITS, 2) = 1
                       ADD BANK-RND-1-STEP TO BANK-RND-1-VALUE
                   END-IF
           END-EVALUATE

That sequence is executed against exact arithmetic over every boundary case, for a product and a quotient, in all seven modes. The numeric model →

Safety rules the compiler enforces

Diagnostic Rule
BANK-TXN-001 A transaction must carry an idempotency key
BANK-AUD-001 A transaction must emit at least one audit event
BANK-LED-001 Debits and credits must balance
BANK-DEC-003 A division must state its rounding mode
BANK-SQL-007 A SQLCODE test must separate an error from a missing row
BANK-CICS-004 A CICS response must be tested against its condition name
BANK-AUD-002 A sensitive field must not reach an audit event or ledger

bankc explain BANK-LED-001 prints any of them, and no diagnostic can be emitted without a catalogue entry. The full catalogue →

Quick start

Node.js 24+ and pnpm 11.7.0. GnuCOBOL is optional locally.

pnpm bankc init    my-service                 # scaffold a project
pnpm bankc check   examples/account-posting   # diagnostics only
pnpm bankc build   examples/account-posting   # full artifact bundle
pnpm bankc verify  examples/account-posting   # determinism + coverage
pnpm bankc test    examples/account-posting   # the above, plus cobc
pnpm bankc job     examples/end-of-day-settlement  # several programs, one job
pnpm bankc explain BANK-LED-001               # explain a diagnostic

pnpm bankc analyse  legacy/                   # what your COBOL contains
pnpm bankc copybook import ACCTMAST.cpy       # your record, as BankTS

Add --watch to any command that reads a project to rerun it on save. The rest refuse the flag and name the ones that take it. The whole toolchain →

Examples

Each with a checked-in evidence bundle: its artifacts and the report over them.

The language

Example Demonstrates
account-transfer Records, decimal aliases, a validator
account-posting Transactions, ledger postings, audit events
account-file-batch Sequential files, FILE-CONTROL and FD
batch-interest-accrual Locals, exact decimal arithmetic, if/else
withdrawal-with-recovery Inheritance, raise / on failure, run
statement-generation Indexed files, enums, tables, nullables
interest-posting-batch Rounding, tiered rates, a fee that can refuse
amortisation-schedule Recursion as a RECURSIVE program
rounding-conformance All seven rounding modes, both signs
payment-feed-import lineSequential text from off the mainframe
settlement-bill-file Header, detail and trailer in one output file
zunit-tested-posting A test beside the program it covers

The subsystems

Example Demonstrates
online-enquiry CICS, commarea, Db2, three-outcome SQL
branch-accrual-cursor WITH HOLD, checkpoint in a loop, run
vsam-browse START / READ NEXT on an alternate index
mq-request-reply A queue drained under syncpoint
report-with-controls Report Writer: control breaks and totals

When it goes wrong, and a night

Example Demonstrates
failed-open File status 35, 37 and 39 named apart
full-disk A WRITE out of extents, halfway through
deadlock-retry Db2 -911 and -913, bounded retry
high-volume-master A file bigger than the loop bound
parm-driven-batch The PARM convention, restart and checkpoint
end-of-day-settlement Three programs and a sort in one JCL stream

And five conversionsconversions/ — existing COBOL beside the BankTS it becomes.

Every example is run, not only compiled. Three have hand-written expected balances; the rest are executed twice — by cobc and by an interpreter written against the same output — and a test fails on any disagreement. That is what catches a defect that compiles: the bounds guard once clamped an out-of-range subscript instead of refusing it, and every static check passed.

That lane covers 27 of the 31 COBOL verbs the backend emits. The other four are a generated zUnit test case's entry points and a Report Writer section, neither of which has anywhere local to run. The grades →

Documentation

Start here

Document Contents
Getting started Thirty minutes from clone to reading COBOL
For mainframe engineers The generated COBOL, construct by construct
For the person deciding The risk, and what it would cost to find out
Status and honest limits What this is not
Comparison Against converters, Micro Focus, and by hand

The output

Document Contents
Generated code standards The house style, as a contract
Target conformance The rules it obeys, with manual citations
Divergences Where GnuCOBOL and Enterprise COBOL disagree
Numeric model Precision, scale, intermediates, rounding
Error handling Return codes, file status, SQLCODE, RESP
JCL model The generated job, and what to change
COBOL backend Emission rules

The language and the compiler

Document Contents
Grammar Every production, in EBNF
Language stability What is settled and what is not
Diagnostics The full catalogue
Architecture Pipeline, packages, compile()
Verification Testing and evidence strategy
Security and data sensitive, PII, dumps
Toolchain CLI, formatter, CI, editors
Migration analysis Reading COBOL you have
Glossary Compiler and mainframe terms
Roadmap What is planned

Language reference

Document Contents
Contents Which page holds which rule
Every construct Records, files, SQL, CICS, MQ

Decisions

Document Contents
ADRs Why the compiler is as it is

Status

A working compiler for a deliberately narrow subset, not a production mainframe toolchain. It has never run against a real ledger.

The full list, with what each limit costs →

Contributing

See CONTRIBUTING.md: small changes, real tests, no silent golden updates, and never claim validation that did not happen.

License

MIT

About

A deterministic compiler from BankTS, a small banking language with TypeScript's type syntax, to readable IBM Enterprise COBOL — with banking safety rules enforced at compile time.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages