File size: 7,954 Bytes
5d61448 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | """
TD Lang CLI β Command-line interface for .td files.
Usage:
python -m td_lang run examples/demo_merge.td # Compile + execute
python -m td_lang compile examples/demo_merge.td # Compile only (outputs .py)
python -m td_lang check examples/demo_merge.td # Syntax check only
python -m td_lang info examples/demo_merge.td # Show plan without compiling
python -m td_lang --version # Show version
"""
import argparse
import sys
from . import __version__
from .executor import TDExecutor
from .errors import TDLangError
from .grammar import parse_td_file
from .ast_nodes import (
LoadCmd, MergeCmd, HealCmd, EvalCmd, CommitCmd,
SynthCmd, TrainCmd, DebateCmd, DiagnoseCmd,
ForkCmd, ResetCmd, PruneCmd, EditCmd,
FuseCmd, AbsorbCmd, RepeatBlock, IfBlock,
NotifyCmd, SaveCmd, ScheduleCmd,
DownloadCmd, LogBlock, CompareCmd, VerifyCmd,
VoteCmd, PromptBlock, DistillCmd, RollbackCmd,
CurriculumCmd, StarCmd, BestOfCmd, ExploitCmd, ArenaCmd, ResearchArenaCmd,
SnapshotCmd, ReportCmd,
)
# Phase labels for info command
_PHASE_MAP = {
LoadCmd: ("1", "load"),
MergeCmd: ("1", "merge"),
HealCmd: ("1", "heal"),
EvalCmd: ("1", "eval"),
CommitCmd: ("1", "commit"),
SynthCmd: ("2", "synth"),
TrainCmd: ("2", "train"),
DebateCmd: ("2", "debate"),
DiagnoseCmd: ("2", "diagnose"),
ForkCmd: ("3", "fork"),
ResetCmd: ("3", "reset"),
PruneCmd: ("3", "prune"),
EditCmd: ("3", "edit"),
FuseCmd: ("6", "fuse"),
AbsorbCmd: ("6", "absorb"),
RepeatBlock: ("7", "repeat"),
IfBlock: ("7", "if"),
NotifyCmd: ("8", "notify"),
SaveCmd: ("8", "save"),
SnapshotCmd: ("4", "snapshot"),
ReportCmd: ("4", "report"),
ScheduleCmd: ("9", "schedule"),
DownloadCmd: ("10", "download"),
CompareCmd: ("10", "compare"),
VerifyCmd: ("10", "verify"),
VoteCmd: ("11", "vote"),
PromptBlock: ("11", "prompt"),
DistillCmd: ("11", "distill"),
RollbackCmd: ("11", "rollback"),
CurriculumCmd: ("12", "curriculum"),
StarCmd: ("12", "star"),
BestOfCmd: ("12", "best_of"),
ExploitCmd: ("12", "exploit"),
ArenaCmd: ("13", "arena"),
ResearchArenaCmd: ("13", "research_arena"),
}
def parse_args() -> argparse.Namespace:
"""Parse command-line arguments."""
parser = argparse.ArgumentParser(
description="TD Lang β compile and run .td files for Time Dilation",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python -m td_lang check examples/demo_merge.td # Check syntax
python -m td_lang compile examples/demo_merge.td # Compile to .py
python -m td_lang run examples/demo_merge.td # Compile + run
python -m td_lang run examples/demo_merge.td --dry # Compile only
python -m td_lang info examples/demo_merge.td # Show plan summary
""",
)
parser.add_argument(
"--version",
action="version",
version=f"td_lang {__version__}",
)
parser.add_argument(
"action",
choices=["check", "compile", "run", "info"],
help="What to do: check (syntax), compile (.py), run (compile+execute), info (show plan)",
)
parser.add_argument(
"file",
type=str,
help="Path to the .td file",
)
parser.add_argument(
"--output",
type=str,
default="td_lang_outputs",
help="Output directory (default: td_lang_outputs)",
)
parser.add_argument(
"--dry",
action="store_true",
help="With 'run': compile but don't execute",
)
parser.add_argument(
"--verbose", "-v",
action="store_true",
help="Show extra detail (compiled Python, full AST, etc.)",
)
return parser.parse_args()
def print_banner():
"""Print the td_lang banner."""
banner = f"""
βββββββββββββββββββββββββββββββββββββββββ
β β
β ββββββββββββββββ βββ ββββββββ
β βββββββββββββββββ βββ βββββββββ
β βββ βββ βββ βββ βββ ββββ
β βββ βββ βββ βββ βββ βββ
β βββ ββββββββ βββββββ ββββββββββ
β βββ βββββββ βββββββ ββββββββ
β β
β TD Lang v{__version__} β .td file compiler β
β β
βββββββββββββββββββββββββββββββββββββββββ
"""
print(banner)
def print_info(filepath: str) -> None:
"""Show what a .td file does without compiling β human-readable plan summary."""
program = parse_td_file(filepath)
print(f"\n File: {filepath}")
print(f" Commands: {len(program.commands)}")
if program.gates:
print(f" Gates: {', '.join(program.gates.must_pass)}")
if program.budget:
parts = []
if program.budget.max_gpu_hours is not None:
parts.append(f"{program.budget.max_gpu_hours} GPU hrs")
if program.budget.max_cost is not None:
parts.append(f"${program.budget.max_cost}")
print(f" Budget: {', '.join(parts)}")
if program.data_contract:
print(f" Data contract: fields={program.data_contract.required_fields}")
if program.reward_contract:
print(f" Reward contract: verifiers={program.reward_contract.verifiers}")
print("\n Plan:")
for i, cmd in enumerate(program.commands, 1):
phase, name = _PHASE_MAP.get(type(cmd), ("?", type(cmd).__name__))
target = getattr(cmd, 'target', getattr(cmd, 'alias', ''))
detail = ""
if hasattr(cmd, 'method'):
detail += f" method={cmd.method}"
if hasattr(cmd, 'source') and name in ("merge", "synth"):
detail += f" from={cmd.source}"
if hasattr(cmd, 'layers') and cmd.layers != "all":
detail += f" layers={cmd.layers}"
if hasattr(cmd, 'output') and cmd.output:
detail += f" -> {cmd.output}"
print(f" {i}. [P{phase}] {name} {target}{detail}")
print()
def main():
"""Main entry point for td_lang CLI."""
args = parse_args()
print_banner()
executor = TDExecutor(output_dir=args.output)
try:
if args.action == "info":
print_info(args.file)
elif args.action == "check":
program = executor.check(args.file)
print("\n[td_lang] File is valid!")
elif args.action == "compile":
py_path = executor.compile(args.file)
print(f"\n[td_lang] Generated: {py_path}")
print("[td_lang] You can run it with: python", py_path)
if args.verbose:
print("\n--- Generated Python ---")
print(py_path.read_text())
print("--- End ---")
elif args.action == "run":
result = executor.run(args.file, dry_run=args.dry)
if result["status"] == "success":
sys.exit(0)
elif result["status"] == "dry_run":
sys.exit(0)
else:
sys.exit(1)
except TDLangError as e:
print(f"\n[td_lang] ERROR: {e}")
sys.exit(1)
except FileNotFoundError:
print(f"\n[td_lang] ERROR: File not found: {args.file}")
print("[td_lang] Check the path and try again.")
sys.exit(1)
except KeyboardInterrupt:
print("\n[td_lang] Interrupted.")
sys.exit(130)
|