From 4227d48f30771f3aa937b3155eb15f24a7e1d6fb Mon Sep 17 00:00:00 2001 From: KeshavAnandCode Date: Wed, 20 May 2026 22:11:25 -0500 Subject: [PATCH 1/5] added index and getting started --- docs/getting-started.md | 134 ++++++++++++++++++++++++++++++++++++++++ docs/index.md | 41 ++++++++++++ 2 files changed, 175 insertions(+) diff --git a/docs/getting-started.md b/docs/getting-started.md index bad5562..db01472 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1 +1,135 @@ # Getting Started + +## Requirements + +- Python 3.9 or later +- A language pack (`pip install foreignthon-xx`) + +--- + +## Installation + +```bash +pip install foreignthon +``` + +For global CLI access across projects, use `pipx`: + +```bash +pipx install foreignthon +``` + +--- + +## Create a project + +```bash +fpy new myproject --lang +cd myproject +``` + +This scaffolds: + +``` +myproject/ +├── .foreignthon.toml # project config +├── .gitignore +├── README.md +└── src/ + └── main..py # hello world in your language +``` + +The `.foreignthon.toml` stores your language and any local pack overrides: + +```toml +[foreignthon] +lang = "es" +# custom_pack = "custom.json" +``` + +--- + +## File naming + +ForeignThon detects the language from the file extension: + +``` +script.es.py → Spanish +script.ta.py → Tamil +script.fr.py → French +``` + +You can also declare the language at the top of the file: + +```python +# foreignthon: es +``` + +Or override it at runtime: + +```bash +fpy run script.py --lang es +``` + +--- + +## Run + +```bash +fpy run src/main.es.py +``` + +--- + +## Compile + +```bash +fpy compile src/main.es.py +# → src/main.compiled.py +``` + +```bash +fpy compile src/main.es.py -o dist/ +# → dist/main.compiled.py +``` + +The compiled file is standard Python. Commit it alongside your source — anyone can run it without ForeignThon installed. + +--- + +## Validate + +```bash +fpy check src/main.es.py +# ✓ main.es.py looks good. +``` + +Checks syntax without running — useful in CI. + +--- + +## Errors + +When something goes wrong, ForeignThon shows the error in your language first, then English: + +``` +[ES] ErrorDeDivisionCero: Error división por cero +[EN] ZeroDivisionError: division by zero + File "src/main.es.py", line 8 +``` + +Tracebacks point to your original source file, not any intermediate. + +--- + +## Variable names + +Variable names are completely optional — English names work alongside foreign keywords with no issues. Only keywords and builtins are ever swapped. + +--- + +## Next steps + +- [CLI Reference](cli-reference.md) — all commands and flags +- [Language Packs](language-packs/index.md) — available languages +- [Custom Packs](custom-packs.md) — extend or override a pack locally diff --git a/docs/index.md b/docs/index.md index c247de7..6f552ed 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1 +1,42 @@ # ForeignThon + +Write Python in any human language. + +ForeignThon is a transpiler that converts `.xx.py` files into standard Python — keywords, builtins, and exceptions all translated into your language. The compiled output runs anywhere without ForeignThon installed. + +--- + +## How it works + +``` +source.es.py → fpy → source.compiled.py → Python +``` + +ForeignThon uses Python's `tokenize` module to swap `NAME` tokens. Strings, comments, and f-strings are never touched. The result is identical, valid Python. + +--- + +## Install + +```bash +pip install foreignthon +pip install foreignthon-es # or any other language pack +``` + +--- + +## At a glance + +| Feature | Description | +|---|---| +| Transpiler | Tokenizer-based, safe, unicode-aware | +| File format | `.xx.py` where `xx` is the language code | +| Errors | Shown in your language first, English below | +| Postfix syntax | `@@` operator for SOV languages | +| Custom packs | Local JSON override, no PyPI needed | +| CLI | `fpy run`, `fpy compile`, `fpy decompile`, `fpy new` | + +--- + +[Get started →](getting-started.md){ .md-button .md-button--primary } +[CLI Reference →](cli-reference.md){ .md-button } -- 2.43.0 From 4436ddb8f3617c55de12108890d10dfb754533e3 Mon Sep 17 00:00:00 2001 From: KeshavAnandCode Date: Wed, 20 May 2026 22:12:04 -0500 Subject: [PATCH 2/5] added cli reference --- docs/cli-reference.md | 116 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/docs/cli-reference.md b/docs/cli-reference.md index c31a0bc..f8ebc6f 100644 --- a/docs/cli-reference.md +++ b/docs/cli-reference.md @@ -1 +1,117 @@ # CLI Reference + +All commands support `-h` / `--help`. + +--- + +## `fpy new` + +Scaffold a new ForeignThon project. + +```bash +fpy new --lang # create in new directory +fpy new --lang # initialize current directory (must be empty) +fpy new --lang --no-git +fpy new --lang custom # scaffold a blank language pack +``` + +| Flag | Description | +|---|---| +| `--lang`, `-l` | Language code — required | +| `--no-git` | Skip `git init` and initial commit | + +!!! note "Using `--lang custom`" + Prompts for a language code, English name, and native name. Creates a `custom.json` with all Python keywords pre-filled as stubs and wires it up in `.foreignthon.toml` automatically. + +--- + +## `fpy run` + +Transpile and run a source file. + +```bash +fpy run script.es.py +fpy run script.py --lang es # override language detection +fpy run script.es.py --keep # also write the compiled .py to disk +``` + +| Flag | Description | +|---|---| +| `--lang`, `-l` | Override language detection | +| `--keep` | Write `.compiled.py` alongside source after running | + +--- + +## `fpy compile` + +Transpile to standard Python without running. + +```bash +fpy compile script.es.py # → script.compiled.py (same directory) +fpy compile script.es.py -o dist/ # → dist/script.compiled.py +fpy compile script.es.py -o output.py # → output.py +``` + +| Flag | Description | +|---|---| +| `--output`, `-o` | Output file or directory | + +--- + +## `fpy decompile` + +Convert standard Python back to a foreign language. Keywords and builtins are translated — variable names are untouched. + +```bash +fpy decompile script.py --lang es +fpy decompile script.py --lang es --postfix +fpy decompile script.py --lang es -o out/ +``` + +| Flag | Description | +|---|---| +| `--lang`, `-l` | Target language — required | +| `--postfix` | Rewrite conditionals to `@@` postfix style | +| `--output`, `-o` | Output file or directory | + +!!! note + Decompile is lossy — variable names and comments are not translated back. It is useful for bootstrapping a foreign-language version of an existing Python file, not as a perfect round-trip. + +--- + +## `fpy check` + +Validate syntax without running. + +```bash +fpy check script.es.py +# ✓ script.es.py looks good. +# or +# ✗ Syntax error: invalid syntax (script.es.py, line 4) +``` + +Exits with code `1` on failure — useful in CI pipelines. + +--- + +## `fpy pack` + +Validate a language pack JSON file against the required schema. + +```bash +fpy pack mylang.json +# ✓ Pack 'Russian' is valid. +# or +# ✗ Missing sections: {'error_messages'} +``` + +--- + +## Language detection order + +When running a file, ForeignThon resolves the language in this order: + +1. `--lang` flag (highest priority) +2. Shebang comment: `# foreignthon: es` +3. File extension: `.es.py` → `es` +4. `.foreignthon.toml` in the project root -- 2.43.0 From ff9f0e1e144474ab4f1271af84423a23b534747d Mon Sep 17 00:00:00 2001 From: KeshavAnandCode Date: Wed, 20 May 2026 22:12:32 -0500 Subject: [PATCH 3/5] added postfix syntax --- docs/postfix-syntax.md | 88 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/docs/postfix-syntax.md b/docs/postfix-syntax.md index eeeca72..d8d230a 100644 --- a/docs/postfix-syntax.md +++ b/docs/postfix-syntax.md @@ -1 +1,87 @@ -# Postfix Syntax +## Postfix Syntax + +Some languages are SOV — subject-object-verb — meaning the condition naturally comes before the keyword rather than after it. ForeignThon supports this with the `@@` operator. + +--- + +## The problem + +In English-order Python, the keyword always comes first: + +```python +if condition: + ... +``` + +In many languages, the natural order is the opposite — the condition is stated first, then the action. Forcing English word order on these languages makes the code feel unnatural. + +--- + +## The solution + +The `@@` operator lets you put any keyword after its expression: + +``` +condition @@keyword: + body +``` + +This is equivalent to: + +``` +keyword condition: + body +``` + +Both produce identical compiled Python. `@@` is purely a source-level syntax — it is processed before tokenization and never appears in the output. + +--- + +## Rules + +- `@@` rewrites only the line it appears on — nothing else changes +- Indentation follows standard Python rules, unchanged +- Prefix and postfix can be mixed freely in the same file +- Works for any keyword in any language pack +- `@@` is not valid Python syntax, so it never conflicts with existing code + +--- + +## Supported constructs + +| Construct | Prefix | Postfix | +|---|---|---| +| if | `keyword condition:` | `condition @@keyword:` | +| elif | `keyword condition:` | `condition @@keyword:` | +| while | `keyword condition:` | `condition @@keyword:` | +| def | `keyword name(args):` | `name(args) @@keyword:` | +| class | `keyword Name:` | `Name @@keyword:` | +| for | `keyword var in iter:` | `var @@in_kw iter @@for_kw:` | + +!!! note + `for` loops with postfix require two `@@` operators and can be complex. Most users keep `for` in prefix style. + +--- + +## Decompile with postfix + +When converting Python back to a foreign language, pass `--postfix`: + +```bash +fpy decompile script.py --lang --postfix +``` + +Which keywords get rewritten is controlled by the `postfix_keywords` list in the language pack JSON. A language that uses SVO order sets this to `[]` — postfix output is never forced on languages that don't need it. + +```json +"postfix_keywords": ["if", "elif", "while", "def", "class"] +``` + +--- + +## Input vs output + +| Direction | Mechanism | Controlled by | +|---|---|---| +| Input (writing `.xx.py`) | `@@` in source | Always available for any keyword | +| Output (`fpy decompile --postfix`) | Pack's `postfix_keywords` | Language pack author | Postfix Syntax -- 2.43.0 From bd53d1c0f504e9f5df18c29b4e2c88bd063c485f Mon Sep 17 00:00:00 2001 From: KeshavAnandCode Date: Wed, 20 May 2026 22:12:47 -0500 Subject: [PATCH 4/5] added custom opacks md --- docs/custom-packs.md | 96 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/docs/custom-packs.md b/docs/custom-packs.md index 666aeda..9a671ac 100644 --- a/docs/custom-packs.md +++ b/docs/custom-packs.md @@ -1 +1,95 @@ -# Custom Packs +## Custom Packs + +ForeignThon lets you extend or override any installed language pack locally — no PyPI account, no new package required. You can also scaffold a completely new language from scratch. + +--- + +## Local override + +Create a `custom.json` in your project root with only the keys you want to change: + +```json +{ + "builtins": { + "show": "print" + }, + "keywords": { + "when": "if" + } +} +``` + +Then reference it in `.foreignthon.toml`: + +```toml +[foreignthon] +lang = "es" +custom_pack = "custom.json" +``` + +Custom keys are merged on top of the installed pack. Installed pack keys are preserved — only the keys you define in `custom.json` are overridden. + +!!! tip + ForeignThon walks up the directory tree to find `.foreignthon.toml`, so you can place it at the project root and run `fpy` from any subdirectory. + +--- + +## Scaffold a new language + +If no pack exists for your language yet: + +```bash +fpy new myproject --lang custom +``` + +You will be prompted for: + +- Language code (e.g. `ru`, `fr`, `ar`) +- English name (e.g. `Russian`) +- Native name (e.g. `Русский`) + +This generates a `custom.json` based on the official template — every Python keyword, builtin, exception, and stdlib module is listed with the English value as a placeholder. Replace the **keys** with your language's words. + +```json +{ + "keywords": { + "if": "if", ← replace the key, keep the value + "for": "for", + "def": "def", + ... + } +} +``` + +The `.foreignthon.toml` is automatically wired to use this file. + +--- + +## Pack schema + +A standalone pack must have these top-level sections: + +| Section | Purpose | +|---|---| +| `meta` | Name, code, version, authors | +| `keywords` | Python reserved words | +| `builtins` | Built-in functions | +| `exceptions` | Built-in exception classes | +| `error_messages` | Translations for bilingual error output | +| `stdlib` | Common standard library module names | +| `postfix_keywords` | English keywords to rewrite in `--postfix` output | + +Validate your pack at any time: + +```bash +fpy pack custom.json +# ✓ Pack 'Russian' is valid. +``` + +--- + +## Publishing + +Once your `custom.json` is complete and working, you can turn it into a proper `foreignthon-xx` package on PyPI so others can install it with `pip install foreignthon-xx`. + +See [Contributing → Language Packs](contributing/language-packs.md) for the full guide. Custom Packs -- 2.43.0 From 6ec5f9afbb896f9ee6a0db7976fb8b78a7828b30 Mon Sep 17 00:00:00 2001 From: KeshavAnandCode Date: Wed, 20 May 2026 22:13:21 -0500 Subject: [PATCH 5/5] added language packs ghome --- docs/language-packs/index.md | 54 ++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/docs/language-packs/index.md b/docs/language-packs/index.md index 40c029e..7869825 100644 --- a/docs/language-packs/index.md +++ b/docs/language-packs/index.md @@ -1 +1,55 @@ # Language Packs + +Language packs are separate PyPI packages that define keyword, builtin, and exception mappings for a specific human language. Each is installed independently and discovered automatically by ForeignThon. + +--- + +## Install a pack + +```bash +pip install foreignthon- +``` + +Multiple packs can coexist — install as many as you need. + +--- + +## Available packs + +| Language | Code | Install | +|---|---|---| +| Spanish | `es` | `pip install foreignthon-es` | +| Tamil | `ta` | `pip install foreignthon-ta` | + +--- + +## How discovery works + +ForeignThon uses Python [entry points](https://packaging.python.org/en/latest/specifications/entry-points/) to discover installed packs. Installing a pack is sufficient — no configuration required. + +```toml +# Each pack registers itself in its pyproject.toml: +[project.entry-points."foreignthon.langs"] +es = "foreignthon_es" +``` + +--- + +## What a pack covers + +| Section | Examples | +|---|---| +| Keywords | `if`, `for`, `def`, `class`, `return` … | +| Builtins | `print`, `range`, `len`, `type` … | +| Exceptions | `ValueError`, `TypeError`, `KeyError` … | +| Error messages | Bilingual error output translations | +| Stdlib | `math`, `sys`, `os`, `random` … | +| Postfix keywords | Which keywords to rewrite with `@@` on decompile | + +Third-party library names (numpy, pandas, etc.) are intentionally out of scope. + +--- + +## Don't see your language? + +Anyone can publish a `foreignthon-xx` pack — no core access required. See [Contributing → Language Packs](../contributing/language-packs.md) to get started, or use a [local custom pack](../custom-packs.md) in the meantime. -- 2.43.0