Skip to main content

Gandora

Gandora is the project for gan, a compiler for an Elixir-flavored language that produces readable Python. You write Elixir-style modules, pattern matching, pipelines, and hygienic defmacro macros; deployment is ordinary Python managed by uv with the standard .venv layout. Where Elixir reaches its host platform through :erlang atom calls, Gandora reaches Python the same way: :math.sqrt(2.0) compiles to import math plus math.sqrt(2.0) with no wrapper code.

defmodule App.Mathy do
  @moduledoc "Math helpers showing patterns and interop."

  def fact(0), do: 1
  def fact(n) when n > 0, do: n * fact(n - 1)

  def norm(xs) do
    xs
    |> sum_squares()
    |> then_sqrt()
  end

  defp sum_squares(xs) do
    :functools.reduce(fn acc, x -> acc + x * x end, xs, 0)
  end

  defp then_sqrt(x), do: :math.sqrt(x)
end

compiles to plain Python with multi-clause dispatch as a match statement, private functions as _-prefixed functions, and the interop as direct imports — no Gandora runtime is needed to execute the output.

The practical guide is the language manual (中文版). Design decisions are recorded as Gandora Enhancement Proposals in geps/:

  • GEP-0000 — the proposal process and translation policy (中文)
  • GEP-0001 — language identity, surface syntax, module naming, configuration, and the gan CLI (中文)
  • GEP-0002 — the hygienic macro system (中文)
  • GEP-0003 — Python interop (中文)
  • GEP-0004 — structs (frozen dataclasses) and module attributes (中文)
  • GEP-0005 — sigils (~w, ~s, ~r, and the raw embedded-Python ~python) (中文)
  • GEP-0006 — publishing packages as ordinary PyPI wheels, with macros shipped as source and zero runtime (中文)
  • GEP-0007 — Markdown @doc with locale variants, doctests compiled to native Python doctests, gan doc / gan test (中文)
  • GEP-0008 — definition-generating macros, use/__using__, and the defattr/@on_definition attribute system (中文)
  • GEP-0009 — the ~<lang> embedded-language family (~sql, ~markdown, ...) with EEx-style <%= %> splices (中文)
  • GEP-0010 — the standard library (std/): Enum, String, Map, List, Keyword as an ordinary package (中文)
  • GEP-0011 — multi-arity name groups and \\ default parameters (中文)

English GEPs are normative; the synchronized Chinese translations are generated with scripts/translate-gep.py (a DeepSeek-backed translator configured by .env) and human-reviewed per GEP-0000-R030.

Requirements

  • Rust 1.85 or newer (to build the compiler)
  • Python 3.11 or newer
  • uv for Python development (optional but recommended)

Quick start

cargo build --release
export PATH="$PWD/target/release:$PATH"

gan init my-app
cd my-app
gan run src/main.gan

gan init creates a uv-compatible project: pyproject.toml owns Python metadata and dependencies, gandora.jsonc owns the compiler configuration, and sources live under src/. gan run compiles into .gandora/cache/ and executes with .venv/bin/python, uv run python, or python3 — whichever is available first.

gan check              # parse, expand, analyze; no output written
gan build              # compile every module into dist/
gan expand src/x.gan   # show a module after macro expansion
gan compile src/x.gan --out build/

The v0 surface

Modules (defmodule, one per file, path-derived names), def/defp with multi-clause pattern dispatch and when guards, defmacro with quote/unquote/unquote_splicing and default hygiene (var! escapes), atoms, strings with #{} interpolation, lists, tuples, maps, keyword lists, ranges, the |> pipe, if/unless/case/cond/with, anonymous functions and captures (&Mod.fun/1, &(&1 + 1)), destructuring =, alias/import/require, the interop forms of GEP-0003 (:module calls, pyimport, postfix expr.name(...), @decorate), and the GEP-0004 data declarations: defstruct (a frozen @dataclass with %Mod{...} literals, patterns, and %Mod{s | f: v} updates) plus module attributes (@app :flask.Flask("__main__") compiles to a module-level binding, so @decorate @app.route("/") works like hand-written Python). GEP-0005 adds sigils: ~w(a b c) word lists, ~s(...) strings, ~r/\d+/ compiled Python regexes, and ~python(sum(i*i for i in range(n))) — a raw sigil that splices one verbatim Python expression into the output, Gandora's rendering of Osiris's embedded-language sigils.

Anything outside the surface produces a diagnostic naming the construct (GEP-0001-R007) rather than a silent mistranslation. See examples/tour for a working multi-module program.

Publishing a package

A Gandora package is an ordinary PyPI wheel (GEP-0006):

gan init --package acme-text
cd acme-text            # write modules under src/acme_text/
gan build               # compiles into pkg/, emits marker + .gan sources
uv build && uv publish  # standard hatchling wheel, standard PyPI

A live example is gandora-text, installable straight from GitHub with uv add git+https://github.com/mjason/gandora-text. Consumers then use it from Gandora:

require AcmeText.Core     # macros: expanded at compile time from the
alias AcmeText.Core       #         .gan sources shipped in the wheel
Core.hello("world")       # functions: a plain `import acme_text.core`

The wheel introduces no runtime: its .py modules are self-contained, Python-only consumers can use them without knowing Gandora exists, and macro expansion leaves nothing behind at runtime. The compiler discovers installed packages by reading their gandora.toml markers from .venv — it never imports or executes package code.

Data mapping

Gandora Python
:atom "atom" (interned string)
nil / true / false None / True / False
list / tuple / map list / tuple / dict
keyword list [a: 1] [("a", 1)]
a..b range(a, b + 1)

Only false and nil are falsy (Elixir semantics); the generated code inserts explicit truthiness checks where needed.

Repository layout

  • src/ — the Rust compiler (lexer, parser, expander, codegen, project, CLI in main.rs)
  • docs/ — the language manual (+ docs/local/zh/ translations)
  • geps/ — Gandora Enhancement Proposals (+ geps/local/zh/ translations)
  • examples/tour — a runnable multi-module example
  • tests/e2e.rs — end-to-end tests driving the real binary
  • scripts/translate-gep.py — the GEP translation tool
cargo test             # unit + end-to-end tests

Status

v0.1.0: GEP-0001..0011 are implemented and tested — the language and CLI, hygienic macros with the full metaprogramming surface (definition-generating macros, use/__using__, defattr/ @on_definition), structs, sigils and embedded languages with <%= %> splices, wheel-based package publication, bilingual docs with native doctests, multi-arity functions with \\ defaults, and the standard library (std/, uv add "git+https://github.com/mjason/gandora#subdirectory=std"). Deferred: protocols, comprehensions, try/rescue, binaries, a formatter, an LSP.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gandora_lang-0.1.0.tar.gz (834.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gandora_lang-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (625.9 kB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

File details

Details for the file gandora_lang-0.1.0.tar.gz.

File metadata

  • Download URL: gandora_lang-0.1.0.tar.gz
  • Upload date:
  • Size: 834.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for gandora_lang-0.1.0.tar.gz
Algorithm Hash digest
SHA256 31a8ddc4cd15cec1e6a3f1693b3e3ca965ad19104490e12f807b86587e583261
MD5 5e48758d041127c114a577193d9bb588
BLAKE2b-256 8eeb99932e11b61e5b7aec32aa1f55ed1e66b5056d33370ea16b6613e5d0c6d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for gandora_lang-0.1.0.tar.gz:

Publisher: release.yml on mjason/gandora

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gandora_lang-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for gandora_lang-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 525418f145dbc9542b60e7b4f316d51868b4e38eba0c2fd0d63c82c94ba62161
MD5 70402fbca36909c0448971797cd4008a
BLAKE2b-256 953055d2432b6b03de08c7870a5a93f55efc408df0ade7fd97969f850a468080

See more details on using hashes here.

Provenance

The following attestation bundles were made for gandora_lang-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on mjason/gandora

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.20.1

1 file

0.20.0

1 file

0.19.0

1 file

0.18.8

1 file

0.18.7

1 file

0.18.6

1 file

0.18.5

1 file

0.18.4

1 file

0.18.3

1 file

0.18.2

1 file

0.18.1

1 file

0.18.0

1 file

0.17.1

1 file

0.17.0

1 file

0.16.1

1 file

0.16.0

1 file

0.15.1

1 file

0.15.0

1 file

0.14.1

1 file

0.14.0

1 file

0.13.0

1 file

0.12.0

1 file

0.11.2

1 file

0.11.1

1 file

0.11.0

1 file

0.10.4

1 file

0.10.3

1 file

0.10.2

1 file

0.10.1

1 file

0.10.0

1 file

0.9.3

1 file

0.9.2

1 file

0.9.1

1 file

0.9.0

1 file

0.8.0

1 file

0.7.1

1 file

0.7.0

1 file

0.6.2

1 file

0.6.1

1 file

0.6.0

1 file

0.5.2

1 file

0.5.1

1 file

0.5.0

1 file

0.4.2

1 file

0.4.1

1 file

0.4.0

1 file

0.3.0

1 file

0.2.4

1 file

0.2.3

1 file

0.2.2

1 file

0.2.1

1 file

0.2.0

1 file

This release

0.1.0 This release

2 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