Jazyk /ˈjazɪk/

English as a programming language.

A compiler that turns documentation → requirements → acceptance criteria → architecture → design → source code → tests. Every requirement gets a test.

An edit to the docs trickles down to the code, including migration, deployment, and rollback. A problem downstream trickles up to the docs as a warning or an error: a hole, an ambiguity, a contradiction.

Open the docs in an IDE. Each sentence links to its requirement, design, code, and tests. Warnings and errors show inline. The compiler runs on your own coding AI.

Open the editor Demo projects, or a folder on your computer. Runs in the browser.

Example

A sort utility. Two documents in, one program and its tests out.

1. Docs

docs/main.js.md, written by hand.

# Main.ts

This is a simple sorting algorithm CLI utility similar to the `sort` CLI command.

## CLI args

When invoked, `sort` allows the following CLI args:
- `-r` reverses sorting order to descending

## Execution

Read CLI arguments, keep track of:
- Reverse order with `-r`
Read in from STDIN line by line:
    For current line, strip out whitespace before and after
    If stripped line is empty string, continue to next line
    Add stripped line to lines
Sort lines ascending. Or descending if reverse order
Print all sorted lines delimited by newline

2. Requirements and acceptance criteria

One requirement per obligation, each with the sentence it came from. Under each, the criteria: one condition, one outcome, concrete values.

req:main-js-3
When invoked, the Sort CLI allows the -r CLI arg, which reverses the sorting order to descending.
Quote: - `-r` reverses sorting order to descending
crit:main-js-1
Given a, c, b on STDIN, sort -r prints c, b, a.
crit:main-js-2
Given a, c, b on STDIN and no -r, sort prints a, b, c.
req:main-js-8
If the stripped line is an empty string, the Sort CLI continues to the next line.
Quote: If stripped line is empty string, continue to next line
crit:main-js-3
Given b, an empty line, a line of three spaces, and a on STDIN, sort prints a, b.
crit:main-js-4
Given only empty and whitespace lines on STDIN, sort prints nothing.

3. Architecture

Diagrams rendered from the graph. The sort utility is one box, so these are from the ledger example, a shop across four documents: the top level, the classes under Checkout, and the Checkout flow. Every arrow is a sentence.

Component diagram of the ledger's top level: Ledger, Checkout, Orders, Platform, Shipping
Top level, component view
Class diagram of Checkout's children: Address, Funds, Receipt, Pricing, Order, Payment, Selection
Checkout, class view
Sequence diagram between Checkout and Orders, one arrow per requirement
Checkout, sequence view

4. Tests

code/test/main.test.js, generated. Each test is named for the requirement it covers and asserts its criteria.

test('req_main_js_5_d8e51eea', () => {
  // -r reverses sorting order to descending.
  assert.strictEqual(runCli(['-r'], 'a\nc\nb\n'), 'c\nb\na\n');
});

test('req_main_js_16_6c7e91df', () => {
  // Default sort order (no -r) is ascending.
  assert.strictEqual(runCli([], 'c\na\nb\n'), 'a\nb\nc\n');
  assert.deepStrictEqual(sortLines(['c', 'a', 'b'], false), ['a', 'b', 'c']);
});

test('req_main_js_11_2fea0114', () => {
  // Lines that are empty after stripping are skipped.
  assert.strictEqual(runCli([], 'b\n\n   \n\t\na\n'), 'a\nb\n');
});

test('req_main_js_12_881a9320', () => {
  // Every non-empty stripped line is added to the accumulated lines.
  assert.deepStrictEqual(processRawLines([' x ', '', 'y', '   ']), ['x', 'y']);
});

5. Code

code/main.js, generated.

#!/usr/bin/env node
'use strict';

function parseArgs(argv) {
  const reverse = argv.includes('-r');
  return { reverse };
}

function processRawLines(rawLines) {
  const lines = [];
  for (const rawLine of rawLines) {
    const stripped = rawLine.trim();
    if (stripped === '') continue;
    lines.push(stripped);
  }
  return lines;
}

function sortLines(lines, reverse) {
  const sorted = lines.slice().sort();
  if (reverse) sorted.reverse();
  return sorted;
}

function printLines(lines, out) {
  out.write(lines.join('\n') + (lines.length > 0 ? '\n' : ''));
}

async function main() {
  const { reverse } = parseArgs(process.argv.slice(2));
  const lines = await readStdinLines(process.stdin);
  printLines(sortLines(lines, reverse), process.stdout);
}

Try it

The editor runs in the browser. Open one of the demo projects, or a folder on your computer with a jazyk.toml in it, and read the documents, the requirements, the diagrams, and the diagnostics compiled from them.

jazyk.dev