diff --git a/src/backend/vm.rs b/src/backend/vm.rs index 4ef18b5c..d8c92d61 100644 --- a/src/backend/vm.rs +++ b/src/backend/vm.rs @@ -751,14 +751,14 @@ impl VM { if let Some(array_box) = box_value.as_any().downcast_ref::() { match method { "length" | "len" => { - let items = array_box.items.lock().unwrap(); + let items = array_box.items.read().unwrap(); return Ok(Box::new(IntegerBox::new(items.len() as i64))); }, "get" => { // get(index) - get element at index if let Some(index_box) = _args.get(0) { if let Some(index_int) = index_box.as_any().downcast_ref::() { - let items = array_box.items.lock().unwrap(); + let items = array_box.items.read().unwrap(); let index = index_int.value as usize; if index < items.len() { return Ok(items[index].clone_box()); diff --git a/src/box_trait.rs b/src/box_trait.rs index 844c475e..752b041a 100644 --- a/src/box_trait.rs +++ b/src/box_trait.rs @@ -176,7 +176,7 @@ impl StringBox { /// Join array elements using this string as delimiter pub fn join(&self, array_box: Box) -> Box { if let Some(array) = array_box.as_any().downcast_ref::() { - let strings: Vec = array.items.lock().unwrap() + let strings: Vec = array.items.read().unwrap() .iter() .map(|element| element.to_string_box().value) .collect(); diff --git a/src/boxes/array/mod.rs b/src/boxes/array/mod.rs index 33853490..8566ea37 100644 --- a/src/boxes/array/mod.rs +++ b/src/boxes/array/mod.rs @@ -299,8 +299,8 @@ impl NyashBox for ArrayBox { fn equals(&self, other: &dyn NyashBox) -> BoolBox { if let Some(other_array) = other.as_any().downcast_ref::() { - let self_items = self.items.lock().unwrap(); - let other_items = other_array.items.lock().unwrap(); + let self_items = self.items.read().unwrap(); + let other_items = other_array.items.read().unwrap(); if self_items.len() != other_items.len() { return BoolBox::new(false); @@ -318,3 +318,14 @@ impl NyashBox for ArrayBox { } } } + +// Debug implementation for ArrayBox +impl std::fmt::Debug for ArrayBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let items = self.items.read().unwrap(); + f.debug_struct("ArrayBox") + .field("id", &self.base.id) + .field("length", &items.len()) + .finish() + } +} diff --git a/src/boxes/buffer/mod.rs b/src/boxes/buffer/mod.rs index 70788be1..4fa21ec5 100644 --- a/src/boxes/buffer/mod.rs +++ b/src/boxes/buffer/mod.rs @@ -216,3 +216,14 @@ impl NyashBox for BufferBox { } } } + +// Debug implementation for BufferBox +impl std::fmt::Debug for BufferBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let data = self.data.read().unwrap(); + f.debug_struct("BufferBox") + .field("id", &self.base.id) + .field("length", &data.len()) + .finish() + } +} diff --git a/src/boxes/debug_box.rs b/src/boxes/debug_box.rs index 30e0abfd..caa4e627 100644 --- a/src/boxes/debug_box.rs +++ b/src/boxes/debug_box.rs @@ -100,7 +100,7 @@ */ use std::collections::HashMap; -use std::sync::{Arc, Mutex}; +use std::sync::RwLock; use chrono::Local; use crate::box_trait::{BoxCore, BoxBase, next_box_id, NyashBox, StringBox, BoolBox, VoidBox}; use crate::interpreter::RuntimeError; @@ -110,10 +110,10 @@ use std::any::Any; #[derive(Debug, Clone)] pub struct DebugBox { base: BoxBase, - tracking_enabled: Arc>, - tracked_boxes: Arc>>, - breakpoints: Arc>>, - call_stack: Arc>>, + tracking_enabled: RwLock, + tracked_boxes: RwLock>, + breakpoints: RwLock>, + call_stack: RwLock>, } #[derive(Debug, Clone)] @@ -135,34 +135,34 @@ impl DebugBox { pub fn new() -> Self { DebugBox { base: BoxBase::new(), - tracking_enabled: Arc::new(Mutex::new(false)), - tracked_boxes: Arc::new(Mutex::new(HashMap::new())), - breakpoints: Arc::new(Mutex::new(Vec::new())), - call_stack: Arc::new(Mutex::new(Vec::new())), + tracking_enabled: RwLock::new(false), + tracked_boxes: RwLock::new(HashMap::new()), + breakpoints: RwLock::new(Vec::new()), + call_stack: RwLock::new(Vec::new()), } } pub fn start_tracking(&self) -> Result, RuntimeError> { - let mut enabled = self.tracking_enabled.lock().unwrap(); + let mut enabled = self.tracking_enabled.write().unwrap(); *enabled = true; println!("[DEBUG] Tracking started"); Ok(Box::new(VoidBox::new())) } pub fn stop_tracking(&self) -> Result, RuntimeError> { - let mut enabled = self.tracking_enabled.lock().unwrap(); + let mut enabled = self.tracking_enabled.write().unwrap(); *enabled = false; println!("[DEBUG] Tracking stopped"); Ok(Box::new(VoidBox::new())) } pub fn track_box(&self, box_value: &dyn NyashBox, name: &str) -> Result, RuntimeError> { - let enabled = self.tracking_enabled.lock().unwrap(); + let enabled = self.tracking_enabled.read().unwrap(); if !*enabled { return Ok(Box::new(VoidBox::new())); } - let mut tracked = self.tracked_boxes.lock().unwrap(); + let mut tracked = self.tracked_boxes.write().unwrap(); let info = TrackedBoxInfo { box_type: box_value.type_name().to_string(), @@ -298,7 +298,7 @@ impl DebugBox { } pub fn is_tracking(&self) -> Result, RuntimeError> { - let enabled = self.tracking_enabled.lock().unwrap(); + let enabled = self.tracking_enabled.read().unwrap(); Ok(Box::new(BoolBox::new(*enabled))) } diff --git a/src/boxes/json/mod.rs b/src/boxes/json/mod.rs index c8d31647..c7d86180 100644 --- a/src/boxes/json/mod.rs +++ b/src/boxes/json/mod.rs @@ -242,14 +242,14 @@ fn nyash_box_to_json_value(value: Box) -> Value { } else if let Some(string_box) = value.as_any().downcast_ref::() { Value::String(string_box.value.clone()) } else if let Some(array_box) = value.as_any().downcast_ref::() { - let items = array_box.items.lock().unwrap(); + let items = array_box.items.read().unwrap(); let arr: Vec = items.iter() .map(|item| nyash_box_to_json_value(item.clone_box())) .collect(); Value::Array(arr) } else if let Some(map_box) = value.as_any().downcast_ref::() { let data = map_box.get_data(); - let map = data.lock().unwrap(); + let map = data.read().unwrap(); let mut obj = serde_json::Map::new(); for (key, val) in map.iter() { obj.insert(key.clone(), nyash_box_to_json_value(val.clone_box())); diff --git a/src/boxes/stream/mod.rs b/src/boxes/stream/mod.rs index 32d0f73e..c7ae4292 100644 --- a/src/boxes/stream/mod.rs +++ b/src/boxes/stream/mod.rs @@ -6,36 +6,35 @@ use crate::box_trait::{NyashBox, StringBox, BoolBox, IntegerBox, BoxCore, BoxBas use crate::boxes::buffer::BufferBox; use crate::boxes::array::ArrayBox; use std::any::Any; -use std::sync::{Arc, Mutex}; +use std::sync::RwLock; use std::io::{Read, Write, Result}; -#[derive(Debug, Clone)] pub struct NyashStreamBox { - buffer: Arc>>, - position: Arc>, + buffer: RwLock>, + position: RwLock, base: BoxBase, } impl NyashStreamBox { pub fn new() -> Self { NyashStreamBox { - buffer: Arc::new(Mutex::new(Vec::new())), - position: Arc::new(Mutex::new(0)), + buffer: RwLock::new(Vec::new()), + position: RwLock::new(0), base: BoxBase::new(), } } pub fn from_data(data: Vec) -> Self { NyashStreamBox { - buffer: Arc::new(Mutex::new(data)), - position: Arc::new(Mutex::new(0)), + buffer: RwLock::new(data), + position: RwLock::new(0), base: BoxBase::new(), } } pub fn read(&self, buf: &mut [u8]) -> Result { - let buffer = self.buffer.lock().unwrap(); - let mut position = self.position.lock().unwrap(); + let buffer = self.buffer.read().unwrap(); + let mut position = self.position.write().unwrap(); let available = buffer.len().saturating_sub(*position); let to_read = buf.len().min(available); @@ -50,21 +49,21 @@ impl NyashStreamBox { } pub fn write(&self, buf: &[u8]) -> Result<()> { - let mut buffer = self.buffer.lock().unwrap(); + let mut buffer = self.buffer.write().unwrap(); buffer.extend_from_slice(buf); Ok(()) } pub fn len(&self) -> usize { - self.buffer.lock().unwrap().len() + self.buffer.read().unwrap().len() } pub fn position(&self) -> usize { - *self.position.lock().unwrap() + *self.position.read().unwrap() } pub fn reset(&self) { - *self.position.lock().unwrap() = 0; + *self.position.write().unwrap() = 0; } /// ストリームに書き込み @@ -75,7 +74,7 @@ impl NyashStreamBox { let array_data = buffer_box.readAll(); // ArrayBoxをバイト配列に変換 if let Some(array_box) = array_data.as_any().downcast_ref::() { - let items = array_box.items.lock().unwrap(); + let items = array_box.items.read().unwrap(); let mut bytes = Vec::new(); for item in items.iter() { if let Some(int_box) = item.as_any().downcast_ref::() { @@ -142,8 +141,8 @@ impl NyashBox for NyashStreamBox { } fn to_string_box(&self) -> StringBox { - let buffer = self.buffer.lock().unwrap(); - let position = self.position.lock().unwrap(); + let buffer = self.buffer.read().unwrap(); + let position = self.position.read().unwrap(); StringBox::new(format!("NyashStreamBox({} bytes, pos: {})", buffer.len(), *position)) } @@ -155,10 +154,10 @@ impl NyashBox for NyashStreamBox { fn equals(&self, other: &dyn NyashBox) -> BoolBox { if let Some(other_stream) = other.as_any().downcast_ref::() { - let self_buffer = self.buffer.lock().unwrap(); - let self_position = self.position.lock().unwrap(); - let other_buffer = other_stream.buffer.lock().unwrap(); - let other_position = other_stream.position.lock().unwrap(); + let self_buffer = self.buffer.read().unwrap(); + let self_position = self.position.read().unwrap(); + let other_buffer = other_stream.buffer.read().unwrap(); + let other_position = other_stream.position.read().unwrap(); BoolBox::new(*self_buffer == *other_buffer && *self_position == *other_position) } else { BoolBox::new(false) @@ -176,8 +175,8 @@ impl BoxCore for NyashStreamBox { } fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let buffer = self.buffer.lock().unwrap(); - let position = self.position.lock().unwrap(); + let buffer = self.buffer.read().unwrap(); + let position = self.position.read().unwrap(); write!(f, "NyashStreamBox({} bytes, pos: {})", buffer.len(), *position) } @@ -190,6 +189,32 @@ impl BoxCore for NyashStreamBox { } } +// Clone implementation for NyashStreamBox (needed since RwLock doesn't auto-derive Clone) +impl Clone for NyashStreamBox { + fn clone(&self) -> Self { + let buffer = self.buffer.read().unwrap(); + let position = self.position.read().unwrap(); + NyashStreamBox { + buffer: RwLock::new(buffer.clone()), + position: RwLock::new(*position), + base: BoxBase::new(), + } + } +} + +// Debug implementation for NyashStreamBox +impl std::fmt::Debug for NyashStreamBox { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let buffer = self.buffer.read().unwrap(); + let position = self.position.read().unwrap(); + f.debug_struct("NyashStreamBox") + .field("id", &self.base.id) + .field("buffer_len", &buffer.len()) + .field("position", &position) + .finish() + } +} + impl std::fmt::Display for NyashStreamBox { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.fmt_box(f) diff --git a/src/boxes/string_box.rs b/src/boxes/string_box.rs index e9a401f0..da9b74ae 100644 --- a/src/boxes/string_box.rs +++ b/src/boxes/string_box.rs @@ -117,7 +117,7 @@ impl StringBox { pub fn join(&self, array_box: Box) -> Box { use crate::boxes::array::ArrayBox; if let Some(array) = array_box.as_any().downcast_ref::() { - let strings: Vec = array.items.lock().unwrap() + let strings: Vec = array.items.read().unwrap() .iter() .map(|element| element.to_string_box().value) .collect();