Compare commits
14 Commits
main
...
159197c68e
| Author | SHA1 | Date | |
|---|---|---|---|
| 159197c68e | |||
| 1d124d29d4 | |||
| 31cc276643 | |||
| 5124f6d543 | |||
| 071acedcc0 | |||
| 25b652c052 | |||
| 4ee33c5eaf | |||
| c2cda3f619 | |||
| c760a98e60 | |||
| 3067141e5d | |||
| 1952bf50d9 | |||
| 14c95ee3d1 | |||
| b06bfe7727 | |||
| 89b4523895 |
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal 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
102
INSTALL.md
Normal 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
27
Makefile
Normal 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
|
||||
82
README.md
82
README.md
@@ -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
|
||||
|
||||
@@ -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
2
pytest.ini
Normal file
@@ -0,0 +1,2 @@
|
||||
[pytest]
|
||||
pythonpath = src
|
||||
@@ -0,0 +1,2 @@
|
||||
"""Tampy package."""
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
"""Tampy CLI entry point."""
|
||||
|
||||
from tampy.cli import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -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
|
||||
|
||||
@@ -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
6
tests/test.tampy
Normal 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
43
tests/test_cli.py
Normal 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
81
tests/test_transpiler.py
Normal 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")
|
||||
Reference in New Issue
Block a user