From ff9f0e1e144474ab4f1271af84423a23b534747d Mon Sep 17 00:00:00 2001 From: KeshavAnandCode Date: Wed, 20 May 2026 22:12:32 -0500 Subject: [PATCH] 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