# 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`