Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add subcommands to CLI to run the full Mun pipeline from the command-line #6

Merged
merged 4 commits into from
Oct 6, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/mun/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ edition = "2018"
failure = "0.1.5"
clap = "2.33.0"
mun_compiler = { path = "../mun_compiler" }
mun_compiler_daemon = { path = "../mun_compiler_daemon" }
mun_runtime = { path = "../mun_runtime" }

[build-dependencies]
lazy_static = "1.4.0"
Expand Down
92 changes: 70 additions & 22 deletions crates/mun/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#[macro_use]
extern crate failure;

use std::time::Duration;

use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
use mun_runtime::invoke_fn;

fn main() -> Result<(), failure::Error> {
let matches = App::new("mun")
Expand All @@ -17,6 +20,10 @@ fn main() -> Result<(), failure::Error> {
.required(true)
.index(1),
)
.arg(Arg::with_name("watch").long("watch").help(
"Run the compiler in watch mode.
Watch input files and trigger recompilation on changes.",
))
.arg(
Arg::with_name("opt-level")
.short("O")
Expand All @@ -32,38 +39,79 @@ fn main() -> Result<(), failure::Error> {
)
.about("Compiles a local Mun file into a module"),
)
.subcommand(
SubCommand::with_name("start")
.arg(
Arg::with_name("LIBRARY")
.help("Sets the library to use")
.required(true)
.index(1),
)
.arg(
Arg::with_name("entry")
.long("entry")
.takes_value(true)
.help("the function entry point to call on startup"),
)
.arg(
Arg::with_name("delay")
baszalmstra marked this conversation as resolved.
Show resolved Hide resolved
.long("delay")
.required(true)
.takes_value(true)
.help("how much to delay received filesystem events (in ms). This allows bundling of identical events, e.g. when several writes to the same file are detected. A high delay will make hot reloading less responsive."),
),
)
.get_matches();

match matches.subcommand() {
("build", Some(matches)) => {
let optimization_lvl = match matches.value_of("opt-level") {
Some("0") => mun_compiler::OptimizationLevel::None,
Some("1") => mun_compiler::OptimizationLevel::Less,
None | Some("2") => mun_compiler::OptimizationLevel::Default,
Some("3") => mun_compiler::OptimizationLevel::Aggressive,
_ => return Err(format_err!("Only optimization levels 0-3 are supported")),
};

let target = matches.value_of("target").map(|t| t.to_string());

build(matches, optimization_lvl, target)?
}
("build", Some(matches)) => build(matches)?,
("start", Some(matches)) => start(matches)?,
_ => unreachable!(),
}

Ok(())
}

/// Build the source file specified
fn build(
matches: &ArgMatches,
optimization_lvl: mun_compiler::OptimizationLevel,
target: Option<String>,
) -> Result<(), failure::Error> {
let options = mun_compiler::CompilerOptions {
fn build(matches: &ArgMatches) -> Result<(), failure::Error> {
let options = compiler_options(matches)?;
if matches.is_present("watch") {
mun_compiler_daemon::main(&options)
} else {
mun_compiler::main(&options)
}
}

/// Starts the runtime with the specified library and invokes function `entry`.
fn start(matches: &ArgMatches) -> Result<(), failure::Error> {
let runtime_options = runtime_options(matches)?;
let mut runtime = mun_runtime::MunRuntime::new(runtime_options)?;

let entry_point = matches.value_of("entry").unwrap_or("main");
Ok(invoke_fn!(runtime, entry_point))
}

fn compiler_options(matches: &ArgMatches) -> Result<mun_compiler::CompilerOptions, failure::Error> {
let optimization_lvl = match matches.value_of("opt-level") {
Some("0") => mun_compiler::OptimizationLevel::None,
Some("1") => mun_compiler::OptimizationLevel::Less,
None | Some("2") => mun_compiler::OptimizationLevel::Default,
Some("3") => mun_compiler::OptimizationLevel::Aggressive,
_ => return Err(format_err!("Only optimization levels 0-3 are supported")),
};

Ok(mun_compiler::CompilerOptions {
input: matches.value_of("INPUT").unwrap().into(), // Safe because its a required arg
target,
target: matches.value_of("target").map(|t| t.to_string()),
optimization_lvl,
};
mun_compiler::main(options)
})
}

fn runtime_options(matches: &ArgMatches) -> Result<mun_runtime::RuntimeOptions, failure::Error> {
let delay: u64 = matches.value_of("delay").unwrap().parse()?;

Ok(mun_runtime::RuntimeOptions {
library_path: matches.value_of("LIBRARY").unwrap().into(), // Safe because its a required arg
delay: Duration::from_millis(delay),
})
}
2 changes: 1 addition & 1 deletion crates/mun/test/main.mun
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ fn multiply(a:float, b:float):float {

fn main():int {
5
}
}
4 changes: 2 additions & 2 deletions crates/mun_compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,10 @@ fn diagnostics(db: &CompilerDatabase, file_id: FileId) -> Vec<Diagnostic> {
result.into_inner()
}

pub fn main(options: CompilerOptions) -> Result<(), failure::Error> {
pub fn main(options: &CompilerOptions) -> Result<(), failure::Error> {
let (mut db, file_id) = CompilerDatabase::from_file(&options.input)?;
db.set_optimization_lvl(options.optimization_lvl);
if let Some(target) = options.target {
if let Some(ref target) = options.target {
baszalmstra marked this conversation as resolved.
Show resolved Hide resolved
db.set_target(spec::Target::search(&target).unwrap());
}

Expand Down
10 changes: 10 additions & 0 deletions crates/mun_compiler_daemon/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "mun_compiler_daemon"
version = "0.1.0"
authors = ["Wodann <wodannson@gmail.com>"]
edition = "2018"

[dependencies]
failure = "0.1.5"
mun_compiler = { path = "../mun_compiler" }
notify = "4.0.12"
34 changes: 34 additions & 0 deletions crates/mun_compiler_daemon/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use std::sync::mpsc::channel;
use std::time::Duration;

use failure::Error;
use mun_compiler::CompilerOptions;
use notify::{RecommendedWatcher, RecursiveMode, Watcher};

pub fn main(options: &CompilerOptions) -> Result<(), Error> {
Wodann marked this conversation as resolved.
Show resolved Hide resolved
// Need to canonicalize path to do comparisons
let input_path = options.input.canonicalize()?;

// Compile at least once
mun_compiler::main(&options)?;

let (tx, rx) = channel();

let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_millis(10))?;
watcher.watch(&input_path, RecursiveMode::NonRecursive)?;

loop {
use notify::DebouncedEvent::*;
match rx.recv() {
Ok(Write(ref path)) => {
// TODO: Check whether file contents changed (using sha hash?)
if *path == input_path {
mun_compiler::main(&options)?;
println!("Compiled: {}", path.to_string_lossy());
}
}
Ok(_) => (),
Err(e) => eprintln!("Watcher error: {:?}", e),
}
}
}
6 changes: 3 additions & 3 deletions crates/mun_runtime/src/assembly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use crate::error::*;
use crate::library::Library;
use failure::Error;
use mun_abi::FunctionInfo;

const LIB_DIR: &str = "tmp";
Expand All @@ -18,7 +18,7 @@ pub struct Assembly {

impl Assembly {
/// Loads an assembly for the library at `library_path` and its dependencies.
pub fn load(library_path: &Path) -> Result<Self> {
pub fn load(library_path: &Path) -> Result<Self, Error> {
let library_name = library_path.file_name().ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidInput, "Incorrect library path.")
})?;
Expand All @@ -41,7 +41,7 @@ impl Assembly {
})
}

pub fn swap(&mut self, library_path: &Path) -> Result<()> {
pub fn swap(&mut self, library_path: &Path) -> Result<(), Error> {
let library_path = library_path.canonicalize()?;
let library_name = library_path.file_name().ok_or(io::Error::new(
io::ErrorKind::InvalidInput,
Expand Down
37 changes: 0 additions & 37 deletions crates/mun_runtime/src/error.rs

This file was deleted.

Loading