Compare commits

...

6 Commits

20 changed files with 289 additions and 2 deletions

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
*.pyc
__pycache__/
*.egg-info/
.pytest_cache/
*.map
.env
.venv/

View File

@@ -1 +1,13 @@
[project]
name = "tampy"
version = "0.1.0"
description = "Tamil code compiler"
requires-python = ">=3.9"
dependencies = []
[project.scripts]
tampy = "tampy.cli:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

View File

@@ -0,0 +1,5 @@
Metadata-Version: 2.4
Name: tampy
Version: 0.0.0
License-File: LICENSE
Dynamic: license-file

View File

@@ -0,0 +1,13 @@
LICENSE
README.md
pyproject.toml
src/tampy/__init__.py
src/tampy/__main__.py
src/tampy/cli.py
src/tampy/keywords.py
src/tampy/transpiler.py
src/tampy.egg-info/PKG-INFO
src/tampy.egg-info/SOURCES.txt
src/tampy.egg-info/dependency_links.txt
src/tampy.egg-info/top_level.txt
tests/test.generated.py

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@
tampy

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()

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,52 @@
"""Tampy CLI."""
import argparse
import subprocess
import sys
from pathlib import Path
from src.tampy.transpiler import SimpleTranspiler
from src.tampy.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 = args.file.replace(".tampy", ".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
test.py Normal file
View File

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

6
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")

42
tests/test_cli.py Normal file
View File

@@ -0,0 +1,42 @@
"""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", "test.tampy"],
capture_output=True,
text=True,
env={**dict(os.environ), "PYTHONPATH": "src"}
)
assert result.returncode == 0
assert "Generated:" in result.stdout
def test_run_command():
"""Test run command."""
result = subprocess.run(
[sys.executable, "-m", "tampy", "run", "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", "test.tampy"],
capture_output=True,
text=True,
env={**dict(os.environ), "PYTHONPATH": "src"}
)
assert result.returncode == 0
assert Path("test.py").exists()

79
tests/test_transpiler.py Normal file
View File

@@ -0,0 +1,79 @@
"""Test simple transpiler."""
import ast
import pytest
from src.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")

4
uv.lock generated
View File

@@ -1,8 +1,8 @@
version = 1
revision = 3
requires-python = ">=3.8"
requires-python = ">=3.9"
[[package]]
name = "tampy"
version = "0.1.0"
source = { editable = "." }
source = { virtual = "." }