diff --git a/Cargo.lock b/Cargo.lock index 957e1a0..76ef783 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -498,7 +498,7 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" [[package]] name = "curlywas" version = "0.1.0" -source = "git+https://github.com/exoticorn/curlywas.git?rev=cda3eb868bc1aaa837c4d36898d0e885ee8fce59#cda3eb868bc1aaa837c4d36898d0e885ee8fce59" +source = "git+https://github.com/exoticorn/curlywas.git?rev=89638565#896385654ab2c089200920b6dea4abec641c88d6" dependencies = [ "anyhow", "ariadne", diff --git a/Cargo.toml b/Cargo.toml index df4789c..3d5d44e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ anyhow = "1" minifb = { version = "0.20", default-features = false, features = ["x11"] } notify = "4" pico-args = "0.4" -curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "cda3eb868bc1aaa837c4d36898d0e885ee8fce59" } +curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "89638565" } wat = "1" uw8-tool = { path = "uw8-tool" } same-file = "1" diff --git a/examples/curlywas/tunnel.cwa b/examples/curlywas/tunnel.cwa index e25a4b0..7a93a71 100644 --- a/examples/curlywas/tunnel.cwa +++ b/examples/curlywas/tunnel.cwa @@ -9,7 +9,7 @@ export fn upd() { let inline d = 40000 as f32 / sqrt(x * x + y * y); let inline u = atan2(x, y) * (512.0 / 3.141); let inline c = ((i32.trunc_sat_f32_s(d + t * 2 as f32) ^ i32.trunc_sat_f32_s(u + t)) & 255) >> 4; - i?120 = c; + i?FRAMEBUFFER = c; branch_if (i := i + 1) < 320*240: pixels; } diff --git a/src/filewatcher.rs b/src/filewatcher.rs index afe8317..eaac912 100644 --- a/src/filewatcher.rs +++ b/src/filewatcher.rs @@ -1,23 +1,38 @@ -use anyhow::{bail, Result}; -use notify::{DebouncedEvent, Watcher, RecommendedWatcher}; -use std::{ - collections::BTreeSet, - path::{Path, PathBuf}, - sync::mpsc, - time::Duration, -}; +use anyhow::{anyhow, bail, Result}; +use notify::{DebouncedEvent, RecommendedWatcher, Watcher}; +use std::{collections::BTreeSet, path::PathBuf, sync::mpsc, time::Duration}; pub struct FileWatcher { - _watcher: RecommendedWatcher, + watcher: RecommendedWatcher, watched_files: BTreeSet, + directories: BTreeSet, rx: mpsc::Receiver, } -pub struct FileWatcherBuilder(BTreeSet); - impl FileWatcher { - pub fn builder() -> FileWatcherBuilder { - FileWatcherBuilder(BTreeSet::new()) + pub fn new() -> Result { + let (tx, rx) = mpsc::channel(); + let watcher = notify::watcher(tx, Duration::from_millis(100))?; + Ok(FileWatcher { + watcher, + watched_files: BTreeSet::new(), + directories: BTreeSet::new(), + rx, + }) + } + + pub fn add_file>(&mut self, path: P) -> Result<()> { + let path = path.into(); + let parent = path.parent().ok_or_else(|| anyhow!("File has no parent"))?; + + if !self.directories.contains(parent) { + self.watcher + .watch(parent, notify::RecursiveMode::NonRecursive)?; + self.directories.insert(parent.to_path_buf()); + } + + self.watched_files.insert(path); + Ok(()) } pub fn poll_changed_file(&self) -> Result> { @@ -38,33 +53,3 @@ impl FileWatcher { Ok(None) } } - -impl FileWatcherBuilder { - pub fn add_file>(&mut self, path: P) -> &mut Self { - self.0.insert(path.into()); - self - } - - pub fn build(self) -> Result { - let mut directories: BTreeSet<&Path> = BTreeSet::new(); - - for file in &self.0 { - if let Some(directory) = file.parent() { - directories.insert(directory); - } - } - - let (tx, rx) = mpsc::channel(); - let mut watcher = notify::watcher(tx, Duration::from_millis(100))?; - - for directory in directories { - watcher.watch(directory, notify::RecursiveMode::NonRecursive)?; - } - - Ok(FileWatcher { - _watcher: watcher, - watched_files: self.0, - rx, - }) - } -} diff --git a/src/main.rs b/src/main.rs index b4f86a7..bde7202 100644 --- a/src/main.rs +++ b/src/main.rs @@ -77,13 +77,7 @@ fn run(mut args: Arguments) -> Result<()> { let filename = args.free_from_os_str::(|s| Ok(s.into()))?; - let mut watcher = uw8::FileWatcher::builder(); - - if watch_mode { - watcher.add_file(&filename); - } - - let watcher = watcher.build()?; + let mut watcher = uw8::FileWatcher::new()?; use std::process::exit; @@ -103,18 +97,26 @@ fn run(mut args: Arguments) -> Result<()> { runtime.set_timeout(timeout); } - if let Err(err) = start_cart(&filename, &mut *runtime, &config) { - eprintln!("Load error: {}", err); - if !watch_mode { - exit(1); - } - } + let mut first_run = true; while runtime.is_open() { - if watcher.poll_changed_file()?.is_some() { - if let Err(err) = start_cart(&filename, &mut *runtime, &config) { - eprintln!("Load error: {}", err); + if first_run || watcher.poll_changed_file()?.is_some() { + match start_cart(&filename, &mut *runtime, &config) { + Ok(dependencies) => { + if watch_mode { + for dep in dependencies { + watcher.add_file(dep)?; + } + } + } + Err(err) => { + eprintln!("Load error: {}", err); + if !watch_mode { + exit(1); + } + } } + first_run = false; } if let Err(err) = runtime.run_frame() { @@ -134,15 +136,25 @@ struct Config { output_path: Option, } -fn load_cart(filename: &Path, config: &Config) -> Result> { +fn load_cart(filename: &Path, config: &Config) -> Result<(Vec, Vec)> { + let mut dependencies = Vec::new(); let mut cart = match SourceType::of_file(filename)? { SourceType::Binary => { let mut cart = vec![]; File::open(filename)?.read_to_end(&mut cart)?; + dependencies.push(filename.to_path_buf()); cart } - SourceType::Wat => wat::parse_file(filename)?, - SourceType::CurlyWas => curlywas::compile_file(filename, curlywas::Options::default())?, + SourceType::Wat => { + let cart = wat::parse_file(filename)?; + dependencies.push(filename.to_path_buf()); + cart + } + SourceType::CurlyWas => { + let module = curlywas::compile_file(filename, curlywas::Options::default())?; + dependencies = module.dependencies; + module.wasm + } }; if let Some(ref pack_config) = config.pack { @@ -154,7 +166,7 @@ fn load_cart(filename: &Path, config: &Config) -> Result> { File::create(path)?.write_all(&cart)?; } - Ok(cart) + Ok((cart, dependencies)) } enum SourceType { @@ -193,14 +205,14 @@ impl SourceType { } #[cfg(any(feature = "native", feature = "browser"))] -fn start_cart(filename: &Path, runtime: &mut dyn Runtime, config: &Config) -> Result<()> { +fn start_cart(filename: &Path, runtime: &mut dyn Runtime, config: &Config) -> Result> { let cart = load_cart(filename, config)?; - if let Err(err) = runtime.load(&cart) { + if let Err(err) = runtime.load(&cart.0) { eprintln!("Load error: {}", err); Err(err) } else { - Ok(()) + Ok(cart.1) } } @@ -219,7 +231,7 @@ fn pack(mut args: Arguments) -> Result<()> { let out_file = args.free_from_os_str::(|s| Ok(s.into()))?; - let cart = load_cart( + let (cart, _) = load_cart( &in_file, &Config { pack: Some(pack_config), @@ -249,7 +261,7 @@ fn compile(mut args: Arguments) -> Result<()> { let out_file = args.free_from_os_str::(|s| Ok(s.into()))?; let module = curlywas::compile_file(in_file, options)?; - File::create(out_file)?.write_all(&module)?; + File::create(out_file)?.write_all(&module.wasm)?; Ok(()) }