Skip to main content

forterp

Tests PyPI Python versions License: MIT

Software Architecture, Design & Engineering by Nicholas J. Kisseberth.
Code Synthesized via Anthropic Claude Code / Opus 4.8.
Automated Code Review via OpenAI Codex / ChatGPT 5.5.

A configurable FORTRAN-66 interpreter in Python: the machine value model and the front-end dialect are both pluggable, so one core runs FORTRAN against whatever representation you select.

The value model is a Target — integer word width and overflow, the logical-truth convention, and how characters pack into words. Two ship:

  • NATIVE (the default) — a clean 64-bit host machine for running standard FORTRAN-66 portably: 64-bit two's-complement integers, 8-bit ASCII, .TRUE.=1 with boolean logical operators. import forterp; forterp.run_source(...) uses this.
  • PDP10 — the DEC FORTRAN-10 model: 36-bit two's-complement words, 5×7-bit packed character storage, .TRUE.=−1 with bit-wise logicals. Select with Engine(..., target=forterp.PDP10).

The PDP-10 target was extracted from an interpreter built to run real 1970s DEC FORTRAN unmodified, so it is exercised against real period code — not just toy snippets — and validated against the DEC FORTRAN-10 V5 manual and the FCVS conformance corpus.

Install

pip install forterp          # (once published)
# or, from a checkout:
pip install -e .

Quick start

import forterp

# The default dialect is strict ANSI F66; FORTRAN10 enables the DEC niceties
# (here the quoted-string FORMAT -- F66 itself uses Hollerith nH). Note fixed form:
# the statement label sits in columns 1-5 and the body starts in column 7.
eng = forterp.run_source('''      PROGRAM HELLO
      WRITE(6,10)
   10 FORMAT(' HELLO, WORLD')
      END
''', dialect=forterp.FORTRAN10, printer=print)

Lower-level building blocks (the expert surface lives under forterp.runtime):

units = forterp.parse_source(src)              # {name: ProgramUnit}
eng   = forterp.runtime.make_engine(units)     # Engine with the FORTRAN-10 runtime installed
eng.run_program("MAIN")                         # or run_program() for the first unit

The package root exposes only the focused names above; the rest is organized into namespaces: forterp.runtime (the Engine and builders), forterp.frontend (lexer/parser stages), forterp.format (the FORMAT engine), forterp.ast (AST nodes), forterp.hostlib (host-builtin marshalling), and forterp.debug (the interactive tracer/profiler and the out-of-bounds census — forterp.debug.oob_census() counts or logs the faithful unchecked-array accesses without changing them).

Command line

Installing puts three commands on your PATH — thin dialect front-ends over the engine (like g77/gfortran over gcc):

pyf66 prog.for              # run as strict ANSI FORTRAN-66 (rejects DEC extensions)
pyfortran10 prog.for        # run as DEC FORTRAN-10 (the superset: octal, IMPLICIT, '...', …)
forterp --std fortran10 prog.for   # general driver; --std f66|fortran10 (default: f66)

--target native|pdp10|vax selects the value model and --program NAME picks the main unit. --check parses and lists every diagnostic without running (a compile-check) — so pyf66 --check prog.for is a strict-ANSI-F66 conformance linter. --version prints the version, --help the usage. Before install, use python -m forterp ….

Pass several source files and they are linked together by unit name, the way a compiler links separately-compiled units — so a driver and a separately-held library run as one program:

forterp main.for lib.for           # main.for's PROGRAM calls SUBROUTINEs in lib.for

Launched with no file, each command drops into an interactive command processor (a small, FORTRAN-focused descendant of the TOPS-10 . prompt — it operates on whole source files, not a statement REPL, since F66 has no incremental-execution model):

f66> RUN prog.for            # compile + run (alias EXECUTE); CHECK = parse-only
f66> SET STD fortran10       # switch dialect, target, or main unit between runs
f10> LOAD prog.for           # parse into the session; START runs it
f10> SHOW /BLOCK/            # inspect a COMMON block after a run; SHOW = settings
f10> !cmd   @file   HELP   EXIT

The command set is identical across the three commands; only the starting dialect differs (pyf66 → f66, pyfortran10 → fortran10), and SET STD flips it.

IMMEDIATE (alias REPL) drops into interactive FORTRAN — statements run as you type, a DO loop is collected across lines, and a bare expression is evaluated (so typing a name inspects it). After a LOAD, the REPL can call straight into the program:

f66* NFAC = 1
f66* DO 10 I=1,5
cont> NFAC = NFAC * I
cont> 10 CONTINUE
f66* NFAC                    # -> 120
f66* ISQ(9)                  # call a function from the LOADed program -> 81
f66* 2 + 3 * 4               # calculator -> 14

(COMMON/EQUIVALENCE need a full program unit — put those in a file and LOAD it; F66 has no incremental model for control flow, so the unit of work is a statement or a DO block, never a bare GOTO.)

The command processor also debugs and profiles a RUN/START. BREAK <line> + STEP drop into a (dbg) prompt where you step (step/next/cont), backtrace (where), and inspect any expression by typing it; TRACE echoes each statement; PROFILE/COVERAGE report per-line execution counts and which lines were reached. The profiler counts statements (deterministic), not wall-clock seconds. All of it rides one off-by-default hook, so a plain run pays nothing:

f66> BREAK 6
f66> RUN fac.for
-- stopped at FAC:6 (Assign)
(dbg) NF                     # inspect a variable by name -> 1
(dbg) where                  # backtrace -> #0 FAC:6
(dbg) cont
f66> PROFILE                 #    5  FAC:6   (the loop body ran 5 times)

What's pluggable

  • Machine targetforterp.Target(word_bits, chars_per_word, logical_true, bitwise_logic, bits_per_char, little_endian, truth) fixes the value model. forterp.NATIVE (64-bit, 8-bit ASCII, boolean logicals) is the default; forterp.PDP10 (36-bit, 5×7-bit packed, .TRUE.=−1, bit-wise logicals) is the DEC target; forterp.VAX (32-bit, little-endian, low-bit logical) is a provisional, unvalidated guess. Pass Engine(..., target=...).
  • Front-end dialectforterp.FORTRAN10 (DEC extensions on) vs forterp.F66 (ANSI). Threaded through the source reader and lexer.
  • OPEN deviceseng.register_device(name, handler) plugs in special devices.
  • Unformatted I/O codecforterp.runtime.install_runtime(eng) wires the FOROTS binary-record + DEC-10 float codec used by binary READ/WRITE.

Supported language

Standard FORTRAN-66 (arithmetic/logical/relational expressions, the full control-flow set, DO loops with F66 one-trip semantics, COMMON/EQUIVALENCE storage association, DATA, subprograms + ENTRY, statement functions), formatted + list-directed + unformatted I/O with the complete FORMAT edit-descriptor set, ENCODE/DECODE, and the DEC FORTRAN-10 extensions (octal literals, Hollerith, IAND/IOR/shift intrinsics, tab-format source, random-access READ(u'r)). See docs/.

Examples & demos

Two directories of runnable material:

  • examples/ — short Python scripts showing how to use forterp as a library: running source and capturing output, choosing a dialect or target, feeding input via readline, and reading results back out of COMMON. Start with examples/run_and_capture.py.
  • demos/ — genuine 1970s FORTRAN to run through the interpreter: verbatim netlib numerical libraries (EISPACK, LINPACK, FFT, RKF45) each with a small driver, DECsystem-10 sources recovered from DECUS tapes, and a 1971 Game of Life. Every one is real period source, run as-is — the corpus that flushes out interpreter gaps.

Tests & lint

pip install -e ".[dev]"
pytest
ruff check           # lint (config in pyproject.toml)
ruff format --check  # formatting — run `ruff format` to apply

The suite is the interpreter's unit tests plus the FCVS (FORTRAN Compiler Validation System) conformance corpus — the standard-conformance audits — exercised through the real source-reader → lexer → parser → engine pipeline.

Security & trust model

forterp is an interpreter, not a sandbox. A program it runs executes with the full privileges of the invoking process: FORTRAN OPEN/READ/WRITE reach the real filesystem, and an absolute path or one containing .. reads or writes files outside the save_root base directory. There is no network access, Python eval, or subprocess reachable from a FORTRAN program — but file access alone means you should not run untrusted source expecting containment. To run code you don't trust, confine the process at the OS level (an unprivileged user, a container, a read-only filesystem, seccomp).

Two guards keep an accidental or hostile program from taking down the host, each raising a clean error rather than hanging or OOM-ing: a statement budget (eng.max_steps, default 50M) bounds execution, and max_array_words (default 50M, settable on the Engine / make_engine) bounds array/COMMON allocation — including DATA repetition counts and EQUIVALENCE extension, not just a bare DIMENSION. INCLUDE resolves only within its base directory (the CLI uses the source file's own directory; the library default is the current directory), and its 'FILE/SWITCH' target is split on /, so it cannot escape via an absolute or .. path. These bound resource use; they are not a security sandbox — file access via OPEN is unrestricted, so still confine genuinely untrusted source at the OS level.

The interactive command processor additionally offers a ! shell escape and @file command scripts (not reachable from a running FORTRAN program); these run with your shell's privileges, so treat a command script as trusted input and don't wire the command processor to an untrusted source.

Authorship & attribution

  • Software Architecture, Design & Engineering by Nicholas J. Kisseberth.
  • Code Synthesized via Anthropic Claude Code / Opus 4.8.
  • Automated Code Review via OpenAI Codex / ChatGPT 5.5.

License

© 2026 Nicholas J. Kisseberth · forterp is MIT-licensed.

Release files for forterp 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for forterp 0.1.0
File Size Uploaded
forterp-0.1.0.tar.gz 585.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for forterp 0.1.0
File Interpreter ABI Platform
forterp-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 707.2 kB

Release files / forterp-0.1.0.tar.gz

Download URL forterp-0.1.0.tar.gz
Size 585.7 kB
Tags Source
SHA-256 checksum
How to use checksums
ccad8a4aef626c229cd9ccd2f77eb5fe63ef9633bd2081c8be138a3ba7710469
BLAKE2b-256 checksum
How to use checksums
87ae4e1dda995df2664467b34cf021568cea2a1edf0a338bcaac62d88ba4dc09
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 24, 2026.

Transparency log

Release files / forterp-0.1.0-py3-none-any.whl

Download URL forterp-0.1.0-py3-none-any.whl
Size 121.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5c071f3a19a6ec33c77baaac779854e91ca0ff50807814fe556fa0be2d892979
BLAKE2b-256 checksum
How to use checksums
cce76be01231fba9e21af83b46a7eaa44ea938a948c18e079587a0a014a3a7e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page