readmes and mds plus fixed ruff

This commit is contained in:
2026-05-15 19:06:09 -05:00
parent 1d20c602e7
commit 7286ba6ea9
5 changed files with 153 additions and 5 deletions

View File

@@ -0,0 +1,51 @@
# Contributing to ForeignThon
## Project structure
foreignthon/
├── packages/
│ ├── foreignthon/ # core engine + fpy CLI
│ │ ├── src/foreignthon/
│ │ │ ├── cli.py # fpy commands
│ │ │ ├── transpiler.py # tokenizer-based transpiler
│ │ │ ├── pack.py # language pack loader
│ │ │ └── errors.py # bilingual error hook
│ │ └── tests/
│ └── langs/
│ └── es/ # Spanish language pack
│ └── src/foreignthon_es/es.json
## Setting up
```bash
python -m venv .venv && source .venv/bin/activate
pip install -e "packages/foreignthon[dev]"
pip install -e packages/langs/es
```
## Running tests
```bash
pytest packages/foreignthon/tests/ -v
```
## Adding a new language pack
1. Copy `packages/langs/es/` to `packages/langs/<code>/`
2. Rename `foreignthon_es``foreignthon_<code>` throughout
3. Fill in `<code>.json` following the same schema as `es.json`
4. Validate it: `fpy pack packages/langs/<code>/src/foreignthon_<code>/<code>.json`
5. Add tests if the language has tricky characters or edge cases
6. Open a PR or publish independently as `foreignthon-<code>` on PyPI
## Language pack schema
Every pack must have these top-level keys:
`meta`, `keywords`, `builtins`, `exceptions`, `error_messages`, `stdlib`
See `packages/langs/es/src/foreignthon_es/es.json` as the reference.
## Code style
```bash
ruff check packages/foreignthon/src
```

View File

@@ -0,0 +1,89 @@
DME.md << 'EOF'
# ForeignThon
Write Python in any human language. ForeignThon transpiles `.es.py`, `.ta.py` (and more) files into standard Python — keywords, builtins, exceptions, all of it.
```python
# hola.es.py
definir saludar(nombre):
retornar f"Hola, {nombre}!"
para i en rango(3):
imprimir(saludar(f"mundo {i}"))
```
```bash
fpy run hola.es.py
# Hola, mundo 0!
# Hola, mundo 1!
# Hola, mundo 2!
```
## Installation
```bash
pip install foreignthon
pip install foreignthon-es # Spanish
pip install foreignthon-ta # Tamil
```
## Usage
```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
fpy pack mylang.json # validate a language pack
```
### Language override
```python
# foreignthon: es
# ^ overrides the file extension
```
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
## Language Packs
A language pack is a JSON file + a tiny Python wrapper published as `foreignthon-xx` on PyPI.
See `packages/langs/es/` for the reference implementation.
The JSON covers:
- **keywords** — `si → if`, `para → for`, `definir → def`
- **builtins** — `imprimir → print`, `rango → range`
- **exceptions** — `ErrorDeValor → ValueError`
- **error_messages** — bilingual error output
- **stdlib** — `matematicas → math`
Validate your pack before publishing:
```bash
fpy pack mylang.json
```
## Development
```bash
git clone <your-repo>
cd foreignthon
python -m venv .venv && source .venv/bin/activate
pip install -e "packages/foreignthon[dev]"
pip install -e packages/langs/es
pytest packages/foreignthon/tests/ -v
```
## License
GPL

View File

@@ -52,3 +52,7 @@ src = ["src"]
[tool.ruff.lint]
select = ["E", "F", "I"]
ignore = ["E501"]
[tool.ruff.lint.per-file-ignores]
"pack.py" = ["E501"]

View File

@@ -7,7 +7,7 @@ import click
from . import __version__
from .errors import activate
from .transpiler import transpile_file, run_transpiled
from .transpiler import run_transpiled, transpile_file
@click.group()
@@ -20,7 +20,7 @@ def main():
@main.command()
@click.argument("file", type=click.Path(exists=True, path_type=Path))
@click.option("--lang", "-l", default=None, help="Override language code (e.g. es, ta)")
@click.option("--keep", is_flag=True, help="Keep the compiled .py file alongside the source")
@click.option("--keep", is_flag=True, help="Keep the compiled .py alongside the source")
def run(file: Path, lang: str | None, keep: bool):
"""Transpile and run a foreign-language Python file."""
if lang:
@@ -44,12 +44,15 @@ def run(file: Path, lang: str | None, keep: bool):
@main.command()
@click.argument("file", type=click.Path(exists=True, path_type=Path))
@click.option("--output", "-o", default=None, help="Output path (default: same dir as source)")
@click.option("--output", "-o", default=None, help="Output path (default: beside source)")
def compile(file: Path, output: str | None):
"""Transpile a file to standard Python without running it."""
transpiled = transpile_file(file)
out_path = Path(output) if output else file.with_suffix("").with_suffix(".compiled.py")
out_path = (
Path(output) if output
else file.with_suffix("").with_suffix(".compiled.py")
)
out_path.write_text(transpiled, encoding="utf-8")
click.echo(f"Compiled: {out_path}")
@@ -77,6 +80,7 @@ def check(file: Path):
def validate_pack(json_file: Path):
"""Validate a language pack JSON file."""
import json
from .pack import REQUIRED_SECTIONS
with open(json_file, encoding="utf-8") as f:

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
import sys
import traceback
from .pack import load_pack, PackNotFoundError
from .pack import PackNotFoundError, load_pack
_active_lang: str | None = None