Compare commits
6 Commits
23af363dfb
...
c760a98e60
| Author | SHA1 | Date | |
|---|---|---|---|
| c760a98e60 | |||
| 3067141e5d | |||
| 1952bf50d9 | |||
| 14c95ee3d1 | |||
| b06bfe7727 | |||
| 89b4523895 |
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
*.pyc
|
||||||
|
__pycache__/
|
||||||
|
*.egg-info/
|
||||||
|
.pytest_cache/
|
||||||
|
*.map
|
||||||
|
.env
|
||||||
|
.venv/
|
||||||
@@ -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"
|
||||||
|
|||||||
5
src/tampy.egg-info/PKG-INFO
Normal file
5
src/tampy.egg-info/PKG-INFO
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Metadata-Version: 2.4
|
||||||
|
Name: tampy
|
||||||
|
Version: 0.0.0
|
||||||
|
License-File: LICENSE
|
||||||
|
Dynamic: license-file
|
||||||
13
src/tampy.egg-info/SOURCES.txt
Normal file
13
src/tampy.egg-info/SOURCES.txt
Normal 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
|
||||||
1
src/tampy.egg-info/dependency_links.txt
Normal file
1
src/tampy.egg-info/dependency_links.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
1
src/tampy.egg-info/top_level.txt
Normal file
1
src/tampy.egg-info/top_level.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
tampy
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
"""Tampy package."""
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
"""Tampy CLI entry point."""
|
||||||
|
|
||||||
|
from tampy.cli import main
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|||||||
BIN
src/tampy/__pycache__/__init__.cpython-314.pyc
Normal file
BIN
src/tampy/__pycache__/__init__.cpython-314.pyc
Normal file
Binary file not shown.
BIN
src/tampy/__pycache__/cli.cpython-314.pyc
Normal file
BIN
src/tampy/__pycache__/cli.cpython-314.pyc
Normal file
Binary file not shown.
BIN
src/tampy/__pycache__/transpiler.cpython-314.pyc
Normal file
BIN
src/tampy/__pycache__/transpiler.cpython-314.pyc
Normal file
Binary file not shown.
@@ -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()
|
||||||
|
|||||||
@@ -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
test.py
Normal file
6
test.py
Normal 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
6
test.tampy
Normal 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
42
tests/test_cli.py
Normal 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
79
tests/test_transpiler.py
Normal 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")
|
||||||
Reference in New Issue
Block a user