diff --git a/Cargo.lock b/Cargo.lock index 68302da..4d8d030 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2566,9 +2566,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550" +checksum = "5f194e49f310034b11c03c4b3d8b20c4793d01c984538178390208fef74e982f" dependencies = [ "ab_glyph", "log", diff --git a/src/regex.rs b/src/regex.rs index b36d280..ba09f5f 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -3,7 +3,7 @@ use std::hash::Hash; use std::ops::Deref; use kempt::Map; -use refuse::{CollectionGuard, ContainsNoRefs}; +use refuse::{CollectionGuard, ContainsNoRefs, Trace}; use regex::{Captures, Regex}; use crate::string::MuseString; @@ -151,7 +151,7 @@ impl Display for MuseRegex { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Trace)] pub struct MuseCaptures { matches: Vec, by_name: Map, @@ -244,9 +244,7 @@ impl CustomType for MuseCaptures { } } -impl ContainsNoRefs for MuseCaptures {} - -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Trace)] pub struct MuseMatch { pub content: AnyDynamic, pub start: usize, @@ -283,5 +281,3 @@ impl CustomType for MuseMatch { &TYPE } } - -impl ContainsNoRefs for MuseMatch {} diff --git a/src/value.rs b/src/value.rs index 80144ff..5f87a8b 100644 --- a/src/value.rs +++ b/src/value.rs @@ -77,6 +77,17 @@ impl Value { } } + #[must_use] + pub fn as_u16(&self) -> Option { + match self { + Value::Int(value) => u16::try_from(*value).ok(), + Value::UInt(value) => u16::try_from(*value).ok(), + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + Value::Float(value) => Some(*value as u16), + _ => None, + } + } + #[must_use] pub fn as_usize(&self) -> Option { match self { diff --git a/src/vm.rs b/src/vm.rs index d22a2b9..a6a8fb2 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -404,9 +404,11 @@ impl<'context, 'guard> VmContext<'context, 'guard> { module_declarations = module_dynamic.declarations(); } else { drop(module_declarations); - return decl - .call(self, arity) - .map_err(|err| ExecutionError::new(err, self)); + return match decl.call(self, arity) { + Ok(result) => Ok(result), + Err(Fault::FrameChanged | Fault::Waiting) => self.resume(), + Err(other) => Err(ExecutionError::new(other, self)), + }; } } return Err(ExecutionError::new(Fault::UnknownSymbol, self)); @@ -923,6 +925,10 @@ impl<'a, 'guard> VmContext<'a, 'guard> { self.check_timeout() } } + + pub fn while_unlocked(&mut self, func: impl FnOnce(&mut CollectionGuard<'_>) -> R) -> R { + MutexGuard::unlocked(&mut self.vm, || func(self.guard)) + } } impl<'guard> AsRef> for VmContext<'_, 'guard> { @@ -999,7 +1005,7 @@ impl VmContext<'_, '_> { Ordering::Equal => return Ok(StepResult::Complete), Ordering::Greater => return Err(Fault::InvalidInstructionAddress), }; - // println!("Executing {instruction:?}"); + println!("Executing {instruction:?}"); let next_instruction = StepResult::from(address.checked_add(1)); let result = match instruction { LoadedOp::Return => return Ok(StepResult::Complete), @@ -1215,6 +1221,7 @@ impl VmContext<'_, '_> { vm.frames[vm.current_frame].module = module_index.get(); vm.frames[executing_frame].loading_module = Some(module_index); let _init_result = self.resume_async_inner(self.current_frame)?; + self.frames[executing_frame].loading_module = None; module_index }; @@ -2239,7 +2246,6 @@ impl Trace for Module { const MAY_CONTAIN_REFERENCES: bool = true; fn trace(&self, tracer: &mut refuse::Tracer) { - println!("Tracing module {:?}", self as *const Self); if let Some(parent) = self.parent { tracer.mark(parent); } diff --git a/tests/cases/mod.rsn b/tests/cases/mod.rsn index e3cdbff..a060960 100644 --- a/tests/cases/mod.rsn +++ b/tests/cases/mod.rsn @@ -129,4 +129,20 @@ sigil_root: { foo.bar.baz() "#, output: Int(42), +} + +mod_multi: { + src: r#" + pub mod a { + pub fn test() => 0; + }; + + pub mod b { + pub fn test() => 42; + }; + + let 0 = a.test(); + b.test() + "#, + output: Int(42), } \ No newline at end of file diff --git a/tests/harness.rs b/tests/harness.rs index 54ddb5f..0f5c20d 100644 --- a/tests/harness.rs +++ b/tests/harness.rs @@ -19,7 +19,7 @@ use serde::Deserialize; fn main() { let filter = std::env::args().nth(1).unwrap_or_default(); - // let filter = String::from("regex_captures"); + // let filter = String::from("mod_multi"); for entry in std::fs::read_dir("tests/cases").unwrap() { let entry = entry.unwrap().path(); if entry.extension().map_or(false, |ext| ext == "rsn") { diff --git a/tests/hosted.rs b/tests/hosted.rs index 7c95cb5..f78b696 100644 --- a/tests/hosted.rs +++ b/tests/hosted.rs @@ -102,21 +102,22 @@ fn run_test_cases(path: &Path, filter: &str) { .to_string(vm)? .try_upgrade(vm.guard())?; - let code = - Compiler::compile(&SourceCode::anonymous(&code), vm.guard()).unwrap(); - let sandbox = Vm::new(vm.guard()); - match sandbox.execute(&code, vm.guard_mut()) { - Ok(result) => Ok(result), - Err(err) => Err(Fault::Exception(Value::dynamic( - TestError { - err, - name, - offset, - source, - }, - vm.guard(), - ))), - } + vm.while_unlocked(|guard| { + let code = Compiler::compile(&SourceCode::anonymous(&code), guard).unwrap(); + let sandbox = Vm::new(guard); + match sandbox.execute(&code, guard) { + Ok(result) => Ok(result), + Err(err) => Err(Fault::Exception(Value::dynamic( + TestError { + err, + name, + offset, + source, + }, + guard, + ))), + } + }) }), context.guard(), ),