Skip to content

Commit

Permalink
add CLI functionality for a given runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
tertsdiepraam committed Feb 28, 2025
1 parent 0edcec3 commit 4698233
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 26 deletions.
101 changes: 101 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use std::path::PathBuf;

use clap::{Parser, Subcommand};

use crate::{FileTree, Runtime};

#[derive(Parser)]
#[command(version, about, long_about = None)]
#[command(propagate_version = true)]
struct Cli {
#[command(subcommand)]
command: Command,
}

#[derive(Subcommand)]
enum Command {
/// Generate documentation for the runtime
Doc,
/// Type check a script
Check {
#[arg()]
file: PathBuf,
},
/// Test a script
Test {
#[arg()]
file: PathBuf,
},
/// Run a script
Run {
#[arg()]
file: PathBuf,
},
}

/// Run a basic CLI for a given runtime
///
/// This is useful for providing users to check their scripts or run their tests
/// with the runtime the host application provides.
///
/// This CLI provides the following subcommands:
/// - `doc`: generate documentation
/// - `check`: type check a script
/// - `test`: run tests for a script
/// - `run`: run the main function of a script
pub fn cli(rt: Runtime) {
match cli_inner(rt) {
Ok(()) => std::process::exit(0),
Err(err) => {
eprintln!("{err}");
std::process::exit(1);
}
}
}

fn cli_inner(rt: Runtime) -> Result<(), String> {
let cli = Cli::parse();

match &cli.command {
Command::Doc => {
rt.print_documentation();
}
Command::Check { file } => {
FileTree::read(file)
.parse()
.map_err(|r| r.to_string())?
.typecheck(rt, usize::BITS / 8)
.map_err(|r| r.to_string())?;
println!("All ok!")
}
Command::Test { file } => {
let mut p = FileTree::read(file)
.parse()
.map_err(|r| r.to_string())?
.typecheck(rt, usize::BITS / 8)
.map_err(|r| r.to_string())?
.lower()
.codegen();

if let Err(()) = p.run_tests(()) {
return Err("tests failed".into());
}
}
Command::Run { file } => {
let mut p = FileTree::read(file)
.parse()
.map_err(|r| r.to_string())?
.typecheck(rt, usize::BITS / 8)
.map_err(|r| r.to_string())?
.lower()
.codegen();

let f = p
.get_function::<(), (), ()>("main")
.map_err(|e| e.to_string())?;

f.call(&mut ())
}
}
Ok(())
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ extern crate self as roto;

mod ast;

mod cli;
mod codegen;
mod file_tree;
mod lower;
Expand All @@ -12,6 +13,7 @@ mod pipeline;
mod runtime;
mod typechecker;

pub use cli::cli;
pub use codegen::TypedFunc;
pub use file_tree::{FileTree, SourceFile};
pub use lower::eval::Memory;
Expand Down
28 changes: 2 additions & 26 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::path::Path;

use clap::Parser;
use roto::{IrValue, Memory, Runtime};
use roto::{cli, Runtime};

#[derive(Parser)]
struct Cli {
Expand All @@ -16,27 +14,5 @@ fn main() {
.format_target(false)
.init();

let settings = Cli::parse();

let args = match settings.rx.as_ref().map(AsRef::as_ref) {
Some("true") => vec![IrValue::Bool(true)],
Some("false") => vec![IrValue::Bool(false)],
Some(x) => vec![IrValue::U32(x.parse().unwrap())],
_ => vec![],
};

let mut mem = Memory::new();

let ptr = mem.allocate(0);
let result = roto::interpret(
Runtime::new(),
Path::new(&settings.file),
&mut mem,
IrValue::Pointer(ptr),
args,
);
match result {
Ok(_) => println!("Ok!"),
Err(e) => eprintln!("{e}"),
}
cli(Runtime::new());
}

0 comments on commit 4698233

Please sign in to comment.