diff --git a/klang/src/parser/structs.rs b/klang/src/parser/structs.rs index b96a50d..41d92df 100644 --- a/klang/src/parser/structs.rs +++ b/klang/src/parser/structs.rs @@ -44,6 +44,22 @@ impl Node { result.push('\n'); result } + + pub fn to_list(&self) -> Vec> { + if self.children.is_empty() { + vec![vec![self.text.clone()]] + } else { + self.children + .iter() + .flat_map(|child| { + child.to_list().into_iter().map(|mut line| { + line.push(self.text.clone()); + line + }) + }) + .collect() + } + } } pub struct KlangProgram { @@ -93,6 +109,13 @@ impl KlangProgram { .collect::>() .join("\n") } + + pub fn to_list(&self) -> Vec> { + self.program + .iter() + .flat_map(|node| node.to_list()) + .collect() + } } impl std::fmt::Display for KlangProgram { diff --git a/pyklang/Cargo.toml b/pyklang/Cargo.toml index 9fce556..d19cead 100644 --- a/pyklang/Cargo.toml +++ b/pyklang/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "pyklang" +name = "bindings" version.workspace = true edition.workspace = true @@ -12,7 +12,7 @@ readme.workspace = true [lib] -name = "pyklang" +name = "bindings" crate-type = ["cdylib", "rlib"] [dependencies] diff --git a/pyklang/bindings.pyi b/pyklang/bindings.pyi index 2e072c6..a95d726 100644 --- a/pyklang/bindings.pyi +++ b/pyklang/bindings.pyi @@ -16,6 +16,9 @@ class PyKlangProgram: def load_binary(path:str) -> PyKlangProgram: ... + def to_list(self) -> list[list[str]]: + ... + def get_version() -> str: ... diff --git a/pyklang/kompile.py b/pyklang/kompile.py index 74fed95..eff21f1 100644 --- a/pyklang/kompile.py +++ b/pyklang/kompile.py @@ -1,28 +1,34 @@ """Defines the PyKlang CLI.""" -import argparse from pathlib import Path +import click + from pyklang.bindings import parse_file -def main() -> None: - parser = argparse.ArgumentParser(description="Kompile a Klang program.") - parser.add_argument("input", help="The input file to compile.") - parser.add_argument("-o", "--output", help="The output file to compile.") - parser.add_argument("-t", "--text", action="store_true", help="Output the text representation of the program.") - args = parser.parse_args() +@click.command() +@click.argument("input_file") +@click.option("-o", "--output", help="The output file to compile.") +@click.option("-i", "--inplace", is_flag=True, help="Overwrite the input file.") +@click.option("-t", "--text", is_flag=True, help="Output the text representation of the program.") +def main(input_file: str, output: str | None, inplace: bool, text: bool) -> None: + """Kompile a Klang program.""" + program = parse_file(input_file) - program = parse_file(args.input) + if inplace: + if output is not None: + raise click.UsageError("Cannot specify both -o and -i") + output = Path(input_file).with_suffix(".ko").as_posix() - if args.output is None: - print(program) + if output is None: + click.echo(program) else: - Path(args.output).parent.mkdir(parents=True, exist_ok=True) - if args.text: - program.save_text(args.output) + Path(output).parent.mkdir(parents=True, exist_ok=True) + if text: + program.save_text(output) else: - program.save_binary(args.output) + program.save_binary(output) if __name__ == "__main__": diff --git a/pyklang/requirements.txt b/pyklang/requirements.txt index ca088be..5f4afbf 100644 --- a/pyklang/requirements.txt +++ b/pyklang/requirements.txt @@ -1 +1,4 @@ # requirements.txt + +# CLI +click diff --git a/pyklang/src/bin/stub_gen.rs b/pyklang/src/bin/stub_gen.rs index 8ced490..ceb1044 100644 --- a/pyklang/src/bin/stub_gen.rs +++ b/pyklang/src/bin/stub_gen.rs @@ -1,7 +1,7 @@ use pyo3_stub_gen::Result; fn main() -> Result<()> { - let stub = pyklang::stub_info()?; + let stub = bindings::stub_info()?; stub.generate()?; Ok(()) } diff --git a/pyklang/src/lib.rs b/pyklang/src/lib.rs index d04a3ee..d9b8178 100644 --- a/pyklang/src/lib.rs +++ b/pyklang/src/lib.rs @@ -66,6 +66,10 @@ impl PyKlangProgram { .map_err(|e| PyValueError::new_err(e.to_string()))?; Ok(PyKlangProgram { inner: program }) } + + fn to_list(&self) -> PyResult>> { + Ok(self.inner.to_list().clone()) + } } #[pyclass]