summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock11
-rw-r--r--matrix/src/vm.rs36
2 files changed, 44 insertions, 3 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8a03761..6b4762f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -139,6 +139,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
+name = "ctrlc"
+version = "3.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b"
+dependencies = [
+ "nix",
+ "windows-sys",
+]
+
+[[package]]
name = "endian-type"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -219,6 +229,7 @@ name = "matrix-bin"
version = "0.1.0"
dependencies = [
"clap",
+ "ctrlc",
"matrix",
"matrix-stdlib",
"rustyline",
diff --git a/matrix/src/vm.rs b/matrix/src/vm.rs
index 4c6618d..dc6931f 100644
--- a/matrix/src/vm.rs
+++ b/matrix/src/vm.rs
@@ -1,4 +1,4 @@
-use std::{rc::Rc, fmt::{Debug, Display}, usize, ops::{Index, IndexMut}, collections::HashMap, cell::RefCell};
+use std::{rc::Rc, fmt::{Debug, Display}, usize, ops::{Index, IndexMut}, collections::HashMap, cell::RefCell, sync::{atomic::{AtomicUsize, Ordering}, Arc}};
use crate::{value::{Value, self, ValueMap}, gc::Gc, chunk::{Function, Instruction, Chunk, InnerFunction}, Result, compiler::NamesTable};
#[derive(Debug)]
@@ -108,6 +108,10 @@ impl StackFrame {
}
}
+pub enum Interupt {
+ KeyboardInterupt = 1
+}
+
pub struct Vm {
stack: Stack<Value>,
locals: Stack<Value>,
@@ -115,6 +119,7 @@ pub struct Vm {
globals: HashMap<u16, Value>,
names: NamesTable,
global_names: NamesTable,
+ interupt: Arc<AtomicUsize>,
}
impl Vm {
@@ -135,6 +140,10 @@ impl Vm {
self.global_names.clone()
}
+ pub fn interupt(&self) -> Arc<AtomicUsize> {
+ self.interupt.clone()
+ }
+
pub fn new() -> Self {
Self {
stack: Stack::new(),
@@ -142,7 +151,8 @@ impl Vm {
frames: Vec::new(),
globals: HashMap::new(),
names: Rc::new(RefCell::new(Vec::new())),
- global_names: Rc::new(RefCell::new(Vec::new()))
+ global_names: Rc::new(RefCell::new(Vec::new())),
+ interupt: Arc::new(AtomicUsize::new(0)),
}
}
@@ -164,8 +174,14 @@ impl Vm {
))
}
+ fn check_interupt(&self) -> bool {
+ self.interupt.load(Ordering::Relaxed) != 0
+ }
+
pub fn run(&mut self, fun: Rc<Function>) -> Result<Value> {
let mut frame = self.init_frame(fun)?;
+ self.interupt.store(0, Ordering::SeqCst);
+
loop {
use Instruction::*;
let ins = frame.body.code[frame.ip].clone();
@@ -223,13 +239,24 @@ impl Vm {
let domain = list.len() / codomain;
self.push(Value::Matrix(Gc::new((domain, codomain, list.inner))));
}
- Jump(idx) => frame.ip = idx as usize,
+ Jump(idx) => {
+ if self.check_interupt() {
+ return Ok(Value::Nil)
+ }
+ frame.ip = idx as usize;
+ }
JumpTrue(idx) => {
+ if self.check_interupt() {
+ return Ok(Value::Nil)
+ }
if !!self.pop() {
frame.ip = idx as usize;
}
},
JumpFalse(idx) => {
+ if self.check_interupt() {
+ return Ok(Value::Nil)
+ }
if !self.pop() {
frame.ip = idx as usize;
}
@@ -268,6 +295,9 @@ impl Vm {
}
},
Return => {
+ if self.check_interupt() {
+ return Ok(Value::Nil)
+ }
let Some(prev_frame) = self.frames.pop() else {
break;
};