From 240cdcd773eb0cf909b6b8eba1c03004acffd544 Mon Sep 17 00:00:00 2001 From: Fergal Walsh Date: Thu, 25 Apr 2024 15:49:48 +0100 Subject: [PATCH] Add inspect command to cli --- tealish/__init__.py | 25 +++++++++++++++++++++++ tealish/cli.py | 49 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/tealish/__init__.py b/tealish/__init__.py index 8114827..a9ac390 100644 --- a/tealish/__init__.py +++ b/tealish/__init__.py @@ -3,6 +3,7 @@ from .base import BaseNode from .nodes import Node, Program from .utils import TealishMap +from .types import _structs class TealWriter: @@ -154,6 +155,9 @@ def get_map(self) -> TealishMap: map.errors = dict(self.error_messages) return map + def get_structs(self): + return dict(_structs) + def compile_program(source: str) -> Tuple[List[str], TealishMap]: source_lines = source.split("\n") @@ -168,3 +172,24 @@ def reformat_program(source: str) -> str: output = compiler.reformat() output = output.strip() + "\n" return output + + +def inspect_program(source: str): + source_lines = source.split("\n") + compiler = TealishCompiler(source_lines) + compiler.compile() + structs = compiler.get_structs() + structs_output = {} + for s in structs: + fields = [(name, structs[s].fields[name]) for name in structs[s].fields] + structs_output[s] = { + "size": structs[s].size, + "fields": { + name: {"type": str(f.tealish_type), "size": f.size, "offset": f.offset} + for name, f in fields + }, + } + output = { + "structs": structs_output, + } + return output diff --git a/tealish/cli.py b/tealish/cli.py index e5b9668..12ccefb 100644 --- a/tealish/cli.py +++ b/tealish/cli.py @@ -2,7 +2,7 @@ import pathlib import click from typing import List, Optional, Tuple, IO -from tealish import compile_program, reformat_program +from tealish import compile_program, inspect_program, reformat_program from tealish.errors import CompileError, ParseError from tealish.langspec import ( fetch_langspec, @@ -151,6 +151,19 @@ def format(ctx: click.Context, tealish_file: IO) -> None: tealish_file.truncate() +@click.command() +@click.argument("tealish_file", type=click.File("r")) +@click.pass_context +def inspect(ctx: click.Context, tealish_file: IO) -> None: + """Inspect a tealish program""" + input = tealish_file.read() + try: + output = inspect_program(input) + except ParseError as e: + raise click.ClickException(str(e)) + print(json.dumps(output, indent=2)) + + @click.group() def langspec() -> None: """Tools to support new Teal versions by updating the langspec file""" @@ -214,6 +227,38 @@ def langspec_diff(url: str) -> None: click.echo(f"{sig}") +@click.command() +@click.argument("path", type=click.Path(exists=True, path_type=pathlib.Path)) +@click.pass_context +def stats(ctx: click.Context, path: pathlib.Path) -> None: + """Stats for a .tl file""" + paths = [] + if path.is_dir(): + paths = ( + list(path.glob("*.tl")) + + list(path.glob("*/*.tl")) + + list(path.glob("*/build/*.teal")) + ) + else: + paths = [path] + for path in paths: + # click.echo(f"Compiling {path} to {teal_filename}") + tealish = open(path).readlines() + n = 0 + for line in tealish: + line = line.strip() + if line.startswith("#"): + continue + if line.startswith("//"): + continue + if not line: + continue + if line == "end": + continue + n += 1 + click.echo(f"{path}: {n} lines") + + langspec.add_command(langspec_update, "update") langspec.add_command(langspec_fetch, "fetch") langspec.add_command(langspec_diff, "diff") @@ -222,3 +267,5 @@ def langspec_diff(url: str) -> None: cli.add_command(build) cli.add_command(format) cli.add_command(langspec) +cli.add_command(stats) +cli.add_command(inspect)