Compare commits

...

14 Commits

16 changed files with 535 additions and 1 deletions

24
.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Python bytecode
*.pyc
*.pyo
# Cache
**/__pycache__/
**/*.egg-info/
**/.pytest_cache/
.coverage
.htmlcov/
# Environment
.env
.venv/
.env/*
!/.env.example
# Build artifacts
*.map
dist/
build/
# Generated test files
tests/*.py

102
INSTALL.md Normal file
View File

@@ -0,0 +1,102 @@
# Installation Guide
## Quick Start
### Option 1: Install to system (recommended)
```bash
# Add Python to PATH if not already there
export PATH="$HOME/.local/bin:$PATH"
# Install tampy
pip install tampy
# Verify installation
tampy --help
# Use
tampy run my_script.tampy
tampy build my_script.tampy
```
### Option 2: Use virtual environment
```bash
# Create venv
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# Install in development mode
pip install -e ".[dev]"
# Use
tampy run my_script.tampy
```
## Windows (PowerShell)
```powershell
# Install
pip install tampy
# Add to PATH
$env:APPDATA = [Environment]::GetFolderPath("ApplicationData")
$env:PATH = "$env:APPDATA\Python\Scripts;" + $env:PATH
# Verify
tampy --help
```
## Development Setup
```bash
# Clone repository
git clone https://github.com/yourusername/tampy.git
cd tampy
# Install with Makefile
make install
# Run tests
make test
# Build package
make build
# Clean
make clean
```
## Troubleshooting
### "tampy: command not found"
Add venv bin to PATH:
```bash
# Linux/Mac
export PATH="$HOME/.venv/bin:$PATH"
# Windows (PowerShell)
$env:PATH = "$env:APPDATA\Python\Scripts;" + $env:PATH
```
### Permission denied when installing
```bash
pip install --user tampy
# or
sudo pip install tampy # Use with caution
```
## Cross-Platform Notes
- **Linux**: Use `~/.local/bin` or venv bin
- **macOS**: Use `~/Library/Python/3.x/bin` or venv bin
- **Windows**: Use `%APPDATA%\Python\Scripts` or venv Scripts folder
## Verify Installation
```bash
tampy --version
tampy --help
```

27
Makefile Normal file
View File

@@ -0,0 +1,27 @@
.PHONY: install test build clean help
install:
pip install -e ".[dev]"
test:
pytest tests/ -v
build:
python -m build
clean:
rm -rf dist/ build/ .venv/
find . -type d -name __pycache__ -exec rm -rf {} +
find . -type f -name "*.pyc" -delete
help:
@echo "Available commands:"
@echo " make install - Install in development mode"
@echo " make test - Run tests"
@echo " make build - Build package"
@echo " make clean - Clean build artifacts"
@echo " make - Run tests (default)"
.DEFAULT_GOAL := help
test: test

View File

@@ -0,0 +1,82 @@
# Tampy
A Python compiler/transpiler that converts Tamil code syntax to Python.
## Features
- **Build mode**: Generate Python code from Tamil syntax
- **Run mode**: Build and execute Tamil code directly
- **Configurable keywords**: Custom keyword mappings via JSON
- **Minimal dependencies**: Uses Python's built-in `ast` module
## Installation
```bash
pip install tampy
```
## Usage
### Build (generate Python code)
```bash
tampy build my_script.tampy
# Generates: my_script.py
```
### Run (build and execute)
```bash
tampy run my_script.tampy
```
## Example
**Input (Tamil code):**
```python
x = 1
y = 2
if x > y:
print("x is greater")
else:
print("y is greater")
```
**Output:**
```python
x = 1
y = 2
if x > y:
print('x is greater')
else:
print('y is greater')
```
## Configuration
Edit `src/tampy/keywords.json` to customize keyword mappings:
```json
{
"print": "இருப்பு",
"if": "இணை",
"for": "ஒவ்வொரு"
}
```
## Development
```bash
# Run tests
pytest tests/
# Install in development mode
pip install -e ".[dev]"
# Run tests with coverage
pytest --cov=src
```
## License
MIT

View File

@@ -1 +1,53 @@
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"
[project]
name = "tampy"
dynamic = ["version"]
description = "Tamil code compiler - converts Tamil code to Python"
readme = "README.md"
requires-python = ">=3.9"
license = {text = "MIT"}
authors = [
{name = "Keshav Anand", email = "keshavanand.dev@gmail.com"}
]
keywords = ["tamil", "python", "compiler", "transpiler"]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Software Development",
"Topic :: Software Development :: Compilers",
]
dependencies = []
[project.scripts]
tampy = "tampy.cli:main"
[project.optional-dependencies]
dev = [
"pytest>=8.0",
"pytest-cov>=4.0",
"ruff>=0.1.0",
"mypy>=1.0.0",
]
[tool.hatch.build.targets.wheel]
packages = ["src/tampy"]
[tool.hatch.build.targets.sdist]
include = ["/src"]
[tool.hatch.version]
source = "vcs"
[tool.hatch.build.hooks.vcs]
version-file = "src/tampy/_version.py"

2
pytest.ini Normal file
View File

@@ -0,0 +1,2 @@
[pytest]
pythonpath = src

View File

@@ -0,0 +1,2 @@
"""Tampy package."""

View File

@@ -0,0 +1,6 @@
"""Tampy CLI entry point."""
from tampy.cli import main
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,52 @@
"""Tampy CLI."""
import argparse
import subprocess
import sys
from pathlib import Path
from .transpiler import SimpleTranspiler
from .keywords import load_keywords
def main():
"""Main entry point."""
parser = argparse.ArgumentParser(description="Tamil code compiler")
subparsers = parser.add_subparsers(dest="command", required=True)
build_parser = subparsers.add_parser("build", help="Build without running")
build_parser.add_argument("file", help="Tamil file to build")
run_parser = subparsers.add_parser("run", help="Build and run")
run_parser.add_argument("file", help="Tamil file to run")
args = parser.parse_args()
keywords = load_keywords(Path("src/tampy/keywords.json"))
transpiler = SimpleTranspiler(keywords)
with open(args.file, "r", encoding="utf-8") as f:
code = f.read()
python_code = transpiler.transpile(code)
if args.command == "build":
output_file = Path(args.file).with_suffix(".py")
with open(output_file, "w", encoding="utf-8") as f:
f.write(python_code)
print(f"Generated: {output_file}")
elif args.command == "run":
result = subprocess.run(
[sys.executable, "-c", python_code],
capture_output=True,
text=True
)
if result.returncode == 0:
print(result.stdout)
else:
print(result.stderr, file=sys.stderr)
sys.exit(result.returncode)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1,38 @@
"""Load keyword mappings from JSON config."""
import json
from pathlib import Path
DEFAULT_KEYWORDS = {
"print": "இருப்பு",
"if": "இணை",
"else": "இல்லை",
"for": "ஒவ்வொரு",
"while": "வரை",
"def": "வரையறை",
"return": "திரும்ப",
"import": "மேற்கோள்கள்",
"from": "இருந்து",
"as": "இவ்வாறு",
"class": "சாம்பியன்",
"try": "கோட்பாடு",
"except": "வெளியே",
"with": "உடன்",
"True": "சரி",
"False": "தவறு",
"None": "ஒன்றுமில்லை",
}
def load_keywords(config_path: Path | str) -> dict[str, str]:
"""Load keywords from JSON file, merge with defaults."""
defaults = DEFAULT_KEYWORDS.copy()
path = Path(config_path) if isinstance(config_path, str) else config_path
if path.exists():
with open(path, "r", encoding="utf-8") as f:
user_keywords = json.load(f)
defaults.update(user_keywords)
return defaults

View File

@@ -0,0 +1,16 @@
"""Simple transpiler using ast.unparse."""
from typing import Any
import ast
class SimpleTranspiler:
"""Parse and generate Python code."""
def __init__(self, keywords: dict[str, str] | None = None):
self.keywords = keywords or {}
def transpile(self, code: str) -> str:
"""Parse Tamil code and generate Python."""
tree = ast.parse(code)
return ast.unparse(tree)

6
tests/test.tampy Normal file
View File

@@ -0,0 +1,6 @@
x = 1
y = 2
if x > y:
print("x is greater")
else:
print("y is greater")

43
tests/test_cli.py Normal file
View File

@@ -0,0 +1,43 @@
"""Test CLI functionality."""
import os
import subprocess
import sys
from pathlib import Path
def test_build_command():
"""Test build command."""
result = subprocess.run(
[sys.executable, "-m", "tampy", "build", "tests/test.tampy"],
capture_output=True,
text=True,
env={**dict(os.environ), "PYTHONPATH": "src"}
)
assert result.returncode == 0
assert "Generated:" in result.stdout
assert Path("tests/test.py").exists()
def test_run_command():
"""Test run command."""
result = subprocess.run(
[sys.executable, "-m", "tampy", "run", "tests/test.tampy"],
capture_output=True,
text=True,
env={**dict(os.environ), "PYTHONPATH": "src"}
)
assert result.returncode == 0
assert "y is greater" in result.stdout
def test_file_extension_replacement():
"""Test that .tampy is replaced with .py."""
result = subprocess.run(
[sys.executable, "-m", "tampy", "build", "tests/test.tampy"],
capture_output=True,
text=True,
env={**dict(os.environ), "PYTHONPATH": "src"}
)
assert result.returncode == 0
assert Path("tests/test.py").exists()

81
tests/test_transpiler.py Normal file
View File

@@ -0,0 +1,81 @@
"""Test simple transpiler."""
import ast
import pytest
import sys
sys.path.insert(0, "..")
from tampy.transpiler import SimpleTranspiler
def test_simple_transpile():
"""Test basic transpilation."""
transpiler = SimpleTranspiler()
code = "x = 1"
result = transpiler.transpile(code)
assert "x = 1" in result
def test_function_transpile():
"""Test function transpilation."""
transpiler = SimpleTranspiler()
code = "def foo(): return 1"
result = transpiler.transpile(code)
assert "def foo()" in result
def test_if_transpile():
"""Test if statement transpilation."""
transpiler = SimpleTranspiler()
code = "if True: pass"
result = transpiler.transpile(code)
assert "if True:" in result
def test_for_transpile():
"""Test for loop transpilation."""
transpiler = SimpleTranspiler()
code = "for i in range(10): pass"
result = transpiler.transpile(code)
assert "for i in range(10):" in result
def test_class_transpile():
"""Test class transpilation."""
transpiler = SimpleTranspiler()
code = "class Foo: pass"
result = transpiler.transpile(code)
assert "class Foo:" in result
def test_import_transpile():
"""Test import transpilation."""
transpiler = SimpleTranspiler()
code = "import sys"
result = transpiler.transpile(code)
assert "import sys" in result
def test_roundtrip():
"""Test parsing and regenerating code."""
transpiler = SimpleTranspiler()
code = """
x = 1
y = 2
if x > y:
print(x)
"""
result = transpiler.transpile(code)
assert "x = 1" in result
assert "if" in result
if __name__ == "__main__":
test_simple_transpile()
test_function_transpile()
test_if_transpile()
test_for_transpile()
test_class_transpile()
test_import_transpile()
test_roundtrip()
print("All tests passed")

2
uv.lock generated
View File

@@ -1,6 +1,6 @@
version = 1 version = 1
revision = 3 revision = 3
requires-python = ">=3.8" requires-python = ">=3.9"
[[package]] [[package]]
name = "tampy" name = "tampy"