move docs to docs/ folder, rewrite readme and contributing
This commit is contained in:
63
docs/contributing.md
Normal file
63
docs/contributing.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Contributing
|
||||
|
||||
## Project structure
|
||||
```
|
||||
foreignthon/
|
||||
├── packages/
|
||||
│ ├── foreignthon/ # core engine + fpy CLI
|
||||
│ │ ├── src/foreignthon/
|
||||
│ │ │ ├── cli.py # fpy commands
|
||||
│ │ │ ├── transpiler.py # tokenizer-based transpiler + @@ pre-pass
|
||||
│ │ │ ├── pack.py # language pack loader + entry point discovery
|
||||
│ │ │ └── errors.py # bilingual error hook
|
||||
│ │ └── tests/
|
||||
│ └── langs/
|
||||
│ ├── es/ # foreignthon-es (Spanish)
|
||||
│ └── ta/ # foreignthon-ta (Tamil)
|
||||
├── docs/
|
||||
└── .gitea/workflows/
|
||||
├── ci.yml # runs tests + lint on every push
|
||||
└── publish.yml # builds + publishes to PyPI on git tag
|
||||
```
|
||||
|
||||
## How the transpiler works
|
||||
|
||||
1. **Pre-pass** — scans for `@@keyword` postfix syntax and rewrites lines to prefix form
|
||||
2. **Tokenizer** — uses Python's `tokenize` module to swap `NAME` tokens. Strings and comments are never touched.
|
||||
3. **Runner** — compiles with the original filename so tracebacks point to your `.es.py` file, not a temp file
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
python -m venv .venv && source .venv/bin/activate
|
||||
pip install -e "packages/foreignthon[dev]"
|
||||
pip install -e packages/langs/es
|
||||
pip install -e packages/langs/ta
|
||||
```
|
||||
|
||||
## Running tests
|
||||
|
||||
```bash
|
||||
pytest packages/foreignthon/tests/ -v
|
||||
```
|
||||
|
||||
## Linting
|
||||
|
||||
```bash
|
||||
ruff check packages/foreignthon/src
|
||||
```
|
||||
|
||||
## Adding a language pack
|
||||
|
||||
See [language-packs.md](language-packs.md) for the full guide.
|
||||
|
||||
## CI
|
||||
|
||||
Every push to `main` runs tests and lint (non-blocking). Releases are triggered by pushing a git tag — see [releasing.md](releasing.md).
|
||||
|
||||
## Submitting changes
|
||||
|
||||
1. Fork the repo
|
||||
2. Create a branch
|
||||
3. Make your changes + add tests if relevant
|
||||
4. Open a pull request against `main`
|
||||
80
docs/getting-started.md
Normal file
80
docs/getting-started.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Getting Started
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install foreignthon
|
||||
pip install foreignthon-es # add Spanish
|
||||
pip install foreignthon-ta # add Tamil
|
||||
```
|
||||
|
||||
For CLI use across projects, prefer pipx:
|
||||
|
||||
```bash
|
||||
pipx install foreignthon
|
||||
```
|
||||
|
||||
## Writing a file
|
||||
|
||||
Name your file `script.<lang>.py` — the extension tells ForeignThon which language pack to use.
|
||||
|
||||
```python
|
||||
# script.es.py
|
||||
definir sumar(a, b):
|
||||
retornar a + b
|
||||
|
||||
para i en rango(5):
|
||||
imprimir(sumar(i, 1))
|
||||
```
|
||||
|
||||
## Running
|
||||
|
||||
```bash
|
||||
fpy run script.es.py # transpile and run
|
||||
fpy compile script.es.py # output a .compiled.py file
|
||||
fpy check script.es.py # validate without running
|
||||
```
|
||||
|
||||
## Overriding the language
|
||||
|
||||
Via shebang comment at the top of the file:
|
||||
|
||||
```python
|
||||
# foreignthon: es
|
||||
```
|
||||
|
||||
Or via CLI flag:
|
||||
|
||||
```bash
|
||||
fpy run script.py --lang es
|
||||
```
|
||||
|
||||
## Errors
|
||||
|
||||
Errors are shown in your language first, English below:
|
||||
[ES] ErrorDeDivisionCero: Error: división por cero
|
||||
[EN] ZeroDivisionError: division by zero
|
||||
File "script.es.py", line 3
|
||||
|
||||
## Variable names
|
||||
|
||||
Variable names are optional — you can use English or your language freely:
|
||||
|
||||
```python
|
||||
# both work fine in the same file
|
||||
definir calculate(anchura, altura):
|
||||
area = anchura * altura
|
||||
retornar area
|
||||
```
|
||||
|
||||
## Local dev setup
|
||||
|
||||
```bash
|
||||
git clone <repo>
|
||||
cd foreignthon
|
||||
python -m venv .venv && source .venv/bin/activate
|
||||
pip install -e "packages/foreignthon[dev]"
|
||||
pip install -e packages/langs/es
|
||||
pip install -e packages/langs/ta
|
||||
pytest packages/foreignthon/tests/ -v
|
||||
```
|
||||
69
docs/language-packs.md
Normal file
69
docs/language-packs.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Language Packs
|
||||
|
||||
A language pack is a JSON file that maps foreign tokens to Python equivalents, published as `foreignthon-<code>` on PyPI.
|
||||
|
||||
## Available packs
|
||||
|
||||
| Package | Language | Install |
|
||||
|---|---|---|
|
||||
| `foreignthon-es` | Spanish | `pip install foreignthon-es` |
|
||||
| `foreignthon-ta` | Tamil | `pip install foreignthon-ta` |
|
||||
|
||||
## JSON schema
|
||||
|
||||
Every pack must have these top-level keys:
|
||||
|
||||
```json
|
||||
{
|
||||
"meta": {
|
||||
"name": "Spanish",
|
||||
"native_name": "Español",
|
||||
"code": "es",
|
||||
"version": "0.1.0",
|
||||
"authors": []
|
||||
},
|
||||
"keywords": { "si": "if", "para": "for", ... },
|
||||
"builtins": { "imprimir": "print", "rango": "range", ... },
|
||||
"exceptions": { "ErrorDeValor": "ValueError", ... },
|
||||
"error_messages":{ "ValueError": "Error de valor", ... },
|
||||
"stdlib": { "matematicas": "math", ... }
|
||||
}
|
||||
```
|
||||
|
||||
- **keywords** — Python reserved words (`if`, `for`, `def`, `class` …)
|
||||
- **builtins** — built-in functions (`print`, `range`, `len` …)
|
||||
- **exceptions** — built-in exception names (`ValueError`, `TypeError` …)
|
||||
- **error_messages** — translations for bilingual error output
|
||||
- **stdlib** — common standard library module names (`math`, `sys` …)
|
||||
|
||||
Third-party library names (numpy, pandas etc.) are out of scope.
|
||||
|
||||
## Creating a pack
|
||||
|
||||
1. Copy `packages/langs/es/` to `packages/langs/<code>/`
|
||||
2. Rename every `foreignthon_es` → `foreignthon_<code>`
|
||||
3. Fill in `<code>.json` following the schema above
|
||||
4. Validate: `fpy pack packages/langs/<code>/src/foreignthon_<code>/<code>.json`
|
||||
5. Install locally: `pip install -e packages/langs/<code>`
|
||||
6. Test: `fpy run myscript.<code>.py`
|
||||
|
||||
## Publishing a pack
|
||||
|
||||
```bash
|
||||
python -m build packages/langs/<code>
|
||||
twine upload packages/langs/<code>/dist/*
|
||||
```
|
||||
|
||||
Anyone can publish an independent `foreignthon-<code>` pack — you don't need to be a core maintainer.
|
||||
|
||||
## How discovery works
|
||||
|
||||
Packs register themselves via Python entry points:
|
||||
|
||||
```toml
|
||||
# in the pack's pyproject.toml
|
||||
[project.entry-points."foreignthon.langs"]
|
||||
es = "foreignthon_es"
|
||||
```
|
||||
|
||||
The core finds all installed packs automatically — no config needed.
|
||||
49
docs/postfix-syntax.md
Normal file
49
docs/postfix-syntax.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Postfix Syntax
|
||||
|
||||
Some languages (like Tamil) are grammatically SOV — the condition comes before the keyword, not after. ForeignThon supports this with the `@@` operator.
|
||||
|
||||
## How it works
|
||||
|
||||
```python
|
||||
# Standard prefix (works in every language)
|
||||
si x > 0:
|
||||
imprimir(x)
|
||||
|
||||
# Postfix with @@
|
||||
x > 0 @@si:
|
||||
imprimir(x)
|
||||
```
|
||||
|
||||
Both produce identical Python: `if x > 0:`. The `@@` means "take whatever is to my left, put the keyword first".
|
||||
|
||||
## Rules
|
||||
|
||||
- `@@` only rewrites the line it appears on — nothing else changes
|
||||
- Indentation rules are identical to normal Python
|
||||
- Prefix and postfix can be mixed freely in the same file
|
||||
- Works for any keyword in any language pack
|
||||
|
||||
## Examples
|
||||
|
||||
```python
|
||||
# if / else
|
||||
x > 0 @@si:
|
||||
imprimir(x)
|
||||
sino:
|
||||
pasar
|
||||
|
||||
# while
|
||||
contador < 10 @@mientras:
|
||||
contador += 1
|
||||
|
||||
# inside a function — indentation unchanged
|
||||
definir comprobar(x):
|
||||
x > 0 @@si:
|
||||
imprimir("positivo")
|
||||
sino:
|
||||
imprimir("negativo")
|
||||
```
|
||||
|
||||
## Why @@
|
||||
|
||||
`@@` is not valid Python syntax so it never conflicts with existing code. Single `@` is used for decorators and matrix multiplication, so it was ruled out.
|
||||
Reference in New Issue
Block a user