uf90: Unicode mathematical notation for portable Fortran
uf90 lets you write mathematical Unicode identifiers in Fortran projects.
It translates *.f90u files into ordinary ASCII *.f90 files, which are then
compiled by fpm and your existing Fortran compiler.
The project is at an early stage (0.1.x). It is a source-to-source translator,
not a compiler or a Fortran language extension.
Quick start with fpm
Install the version published on PyPI with
pipx:
pipx install uf90
If your shell cannot find uf90 or fpm-uf90 after installation, run
pipx ensurepath and open a new terminal.
The installation provides both the uf90 command and the fpm-uf90 plugin.
With fpm and fpm-uf90 available on PATH, run the plugin from a project
containing an fpm.toml file:
fpm uf90 build
fpm uf90 run
fpm uf90 test
The plugin finds *.f90u files in the project, updates their corresponding
*.f90 files, and forwards the command to fpm. Additional arguments are
forwarded as well:
fpm uf90 build --profile release
In practice, this:
fpm uf90 build
is equivalent to:
uf90 sync
fpm build
Minimal example
Write source files in the directories recognized by fpm, using the .f90u
extension. This example rotates the point (x₀, y₀) by an angle θ and stores
the result in (x₁, y₁):
! app/main.f90u
program rotation
implicit none
real :: π, θ
real :: x₀, y₀, x₁, y₁
π = acos(-1.0)
θ = π / 4.0
x₀ = 1.0
y₀ = 0.0
x₁ = cos(θ) * x₀ - sin(θ) * y₀
y₁ = sin(θ) * x₀ + cos(θ) * y₀
print *, x₁, y₁
end program rotation
Running fpm uf90 run generates:
! app/main.f90
program rotation
implicit none
real :: uc_pi, uc_theta
real :: x_0, y_0, x_1, y_1
uc_pi = acos(-1.0)
uc_theta = uc_pi / 4.0
x_0 = 1.0
y_0 = 0.0
x_1 = cos(uc_theta) * x_0 - sin(uc_theta) * y_0
y_1 = sin(uc_theta) * x_0 + cos(uc_theta) * y_0
print *, x_1, y_1
end program rotation
Strings and comments are preserved. The .f90 file is generated output; edit
the corresponding .f90u source instead.
Supported notation
- Greek letters:
α→uc_alpha,Δt→uc_deltat; - calculus prefixes:
∂x→partial_x,∇φ→nabla_phi; - numeric subscripts:
T₁₀₀→T_100; - alphanumeric subscripts:
Eₙ→E_n,Aᵢⱼ→A_ij; - superscripts:
c²→c_p2.
With uf90-ls, type a LaTeX-style symbol name such as \alpha, \partial,
or \nabla and accept the completion to insert α, ∂, or ∇. This works
in both VS Code and Neovim; the generated Neovim setup also maps Ctrl+Space
to manual completion.
Subscripts use familiar LaTeX-style input: accepting completion for x_n,
T_{100}, or A_ij produces xₙ, T₁₀₀, or Aᵢⱼ. The menu opens after
_, and closing } triggers braced-sequence completion. Only characters with
real Unicode subscript forms are offered.
Unicode does not provide subscript forms for every letter. The current set
includes ₐ ₑ ₕ ᵢ ⱼ ₖ ₗ ₘ ₙ ₒ ₚ ᵣ ₛ ₜ ᵤ ᵥ ₓ, ₔ, digits, and the Greek forms
ᵦ ᵧ ᵨ ᵩ ᵪ.
Commands without fpm
For direct use or integration with other workflows:
uf90 sync [directory]
uf90 check [directory]
uf90 translate source.f90u [-o source.f90]
uf90 fortls-config [directory]
uf90 editor-config {vscode,neovim} [-o file]
uf90 sync uses .uf90-manifest.json as an incremental cache. uf90 check
does not modify files and returns a non-zero status when generated output needs
to be updated.
Editors
The experimental 0.2 uf90-ls proxy lets fortls analyze generated .f90
files while editors continue displaying .f90u. Setup guides are available
for VS Code
and Neovim.
The design document
tracks the architecture, acceptance criteria, and remaining scope.
From a 0.2 development checkout, install the proxy and its tested fortls in one
isolated environment with pipx install --force --editable '.[lsp]'. Then use
uf90 editor-config vscode or uf90 editor-config neovim to generate a ready
configuration.
Project status and scope
The current version is intended for experimenting with the notation in fpm
projects and for finding translation cases that are not covered yet. The
interface and mappings may change while the project remains below version
1.0.
uf90 currently:
- translates identifiers without changing text inside strings and comments;
- generates ASCII Fortran that continues through the regular
fpmworkflow; - runs automated tests on Linux, macOS, and Windows with Python 3.10 through 3.14.
It does not validate program semantics, replace the Fortran compiler, or depend on LLVM or MLIR.
Examples and development
The examples directory
contains six progressive fpm projects. To run them from a repository clone:
python3 -m pip install -e '.[test]'
python3 -m pytest
python3 examples/run_all.py
The maintainer release procedure is documented in
docs/RELEASING.md.
Metadata
Release files for uf90 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| uf90-0.2.1.tar.gz | 58.4 kB | With provenance | Details for uf90-0.2.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| uf90-0.2.1-py3-none-any.whl | Python 3 | none | any | Details for uf90-0.2.1-py3-none-any.whl |
Total release size: 83.4 kB
Release files / uf90-0.2.1.tar.gz
| Download URL | uf90-0.2.1.tar.gz |
|---|---|
| Size | 58.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7c76e966c12dd76a9ebb5eb145cef0d316d020350aa4eeaf3c8da0a5cde20942
|
|
BLAKE2b-256 checksum How to use checksums |
a4c35daf20b6d980452ee794b88d3d3c53bdc2b9f5f3e15811ffb6e7ff73f8da
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 10, 2026.
Transparency logRelease files / uf90-0.2.1-py3-none-any.whl
| Download URL | uf90-0.2.1-py3-none-any.whl |
|---|---|
| Size | 25.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
57c5a11439f0540a319b6af07da7bb4bf0a39ffb4220fc7bee2a1fa76ac98029
|
|
BLAKE2b-256 checksum How to use checksums |
8f238d68e05bd390b5ce57a00c7f7ed50c084c872d77feefd08699772f2f2dfa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 10, 2026.
Transparency logSecurity for uf90 0.2.1
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for uf90-0.2.1.tar.gz
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 Aug 10, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.