Skip to content

Commit 97d374d

Browse files
Claude/add academic proofs mg s2z (#31)
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
1 parent fed38f9 commit 97d374d

5 files changed

Lines changed: 415 additions & 1 deletion

File tree

src/interpreter/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
mod value;
22

3-
pub use value::{CapturedEnv, Closure, Value};
3+
pub use value::{CapturedEnv, ChannelHandle, Closure, Value};
44

55
use crate::ast::*;
66
use std::cell::RefCell;

src/interpreter/value.rs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ use std::collections::HashMap;
33
use std::fmt;
44
use std::rc::Rc;
55
use std::cell::RefCell;
6+
use std::sync::mpsc::{self, Receiver, RecvTimeoutError, Sender, TryRecvError};
7+
use std::sync::{Arc, Mutex};
8+
use std::time::Duration;
69

710
/// Captured environment for closures
811
#[derive(Debug, Clone)]
@@ -43,6 +46,135 @@ impl PartialEq for Closure {
4346
}
4447
}
4548

49+
/// Channel handle for Go-style channels
50+
/// Channels allow typed, thread-safe communication between concurrent tasks
51+
#[derive(Clone)]
52+
pub struct ChannelHandle {
53+
/// Sender side
54+
sender: Sender<Value>,
55+
/// Receiver side (wrapped in Arc<Mutex> for sharing)
56+
receiver: Arc<Mutex<Receiver<Value>>>,
57+
/// Channel name (optional, for debugging)
58+
pub name: Option<String>,
59+
/// Whether the channel is closed
60+
closed: Arc<Mutex<bool>>,
61+
/// Buffer capacity (0 = unbuffered/sync)
62+
pub capacity: usize,
63+
}
64+
65+
impl std::fmt::Debug for ChannelHandle {
66+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67+
f.debug_struct("Channel")
68+
.field("name", &self.name)
69+
.field("capacity", &self.capacity)
70+
.field("closed", &*self.closed.lock().unwrap())
71+
.finish()
72+
}
73+
}
74+
75+
impl PartialEq for ChannelHandle {
76+
fn eq(&self, _other: &Self) -> bool {
77+
// Channels are never equal (identity comparison would need Arc pointer comparison)
78+
false
79+
}
80+
}
81+
82+
impl ChannelHandle {
83+
/// Create a new unbuffered channel
84+
pub fn new() -> Self {
85+
let (sender, receiver) = mpsc::channel();
86+
Self {
87+
sender,
88+
receiver: Arc::new(Mutex::new(receiver)),
89+
name: None,
90+
closed: Arc::new(Mutex::new(false)),
91+
capacity: 0,
92+
}
93+
}
94+
95+
/// Create a new unbuffered channel with a name
96+
pub fn with_name(name: String) -> Self {
97+
let mut ch = Self::new();
98+
ch.name = Some(name);
99+
ch
100+
}
101+
102+
/// Create a buffered channel
103+
pub fn buffered(capacity: usize) -> Self {
104+
let (sender, receiver) = mpsc::channel();
105+
Self {
106+
sender,
107+
receiver: Arc::new(Mutex::new(receiver)),
108+
name: None,
109+
closed: Arc::new(Mutex::new(false)),
110+
capacity,
111+
}
112+
}
113+
114+
/// Send a value through the channel
115+
pub fn send(&self, value: Value) -> Result<(), String> {
116+
if *self.closed.lock().unwrap() {
117+
return Err("cannot send on closed channel".to_string());
118+
}
119+
self.sender
120+
.send(value)
121+
.map_err(|_| "channel send failed: receiver dropped".to_string())
122+
}
123+
124+
/// Receive a value from the channel (blocking)
125+
pub fn recv(&self) -> Result<Value, String> {
126+
if *self.closed.lock().unwrap() {
127+
return Err("cannot receive on closed channel".to_string());
128+
}
129+
let receiver = self.receiver.lock().unwrap();
130+
receiver
131+
.recv()
132+
.map_err(|_| "channel receive failed: sender dropped".to_string())
133+
}
134+
135+
/// Try to receive a value (non-blocking)
136+
pub fn try_recv(&self) -> Result<Option<Value>, String> {
137+
if *self.closed.lock().unwrap() {
138+
return Ok(None);
139+
}
140+
let receiver = self.receiver.lock().unwrap();
141+
match receiver.try_recv() {
142+
Ok(value) => Ok(Some(value)),
143+
Err(TryRecvError::Empty) => Ok(None),
144+
Err(TryRecvError::Disconnected) => Err("channel disconnected".to_string()),
145+
}
146+
}
147+
148+
/// Receive with timeout
149+
pub fn recv_timeout(&self, timeout_ms: u64) -> Result<Option<Value>, String> {
150+
if *self.closed.lock().unwrap() {
151+
return Ok(None);
152+
}
153+
let receiver = self.receiver.lock().unwrap();
154+
match receiver.recv_timeout(Duration::from_millis(timeout_ms)) {
155+
Ok(value) => Ok(Some(value)),
156+
Err(RecvTimeoutError::Timeout) => Ok(None),
157+
Err(RecvTimeoutError::Disconnected) => Err("channel disconnected".to_string()),
158+
}
159+
}
160+
161+
/// Close the channel
162+
pub fn close(&self) {
163+
*self.closed.lock().unwrap() = true;
164+
}
165+
166+
/// Check if the channel is closed
167+
pub fn is_closed(&self) -> bool {
168+
*self.closed.lock().unwrap()
169+
}
170+
}
171+
172+
impl Default for ChannelHandle {
173+
fn default() -> Self {
174+
Self::new()
175+
}
176+
}
177+
46178
/// Runtime value in WokeLang
47179
#[derive(Debug, Clone, PartialEq)]
48180
pub enum Value {
@@ -60,6 +192,8 @@ pub enum Value {
60192
Oops(String),
61193
/// First-class function/closure
62194
Function(Closure),
195+
/// Go-style channel for concurrent communication
196+
Channel(ChannelHandle),
63197
}
64198

65199
impl Value {
@@ -76,6 +210,7 @@ impl Value {
76210
Value::Okay(_) => true,
77211
Value::Oops(_) => false,
78212
Value::Function(_) => true,
213+
Value::Channel(ch) => !ch.is_closed(),
79214
}
80215
}
81216

@@ -133,6 +268,13 @@ impl fmt::Display for Value {
133268
let param_names: Vec<_> = closure.params.iter().map(|p| p.name.as_str()).collect();
134269
write!(f, "|{}| -> <closure>", param_names.join(", "))
135270
}
271+
Value::Channel(ch) => {
272+
let status = if ch.is_closed() { "closed" } else { "open" };
273+
match &ch.name {
274+
Some(name) => write!(f, "<chan:{} {}>", name, status),
275+
None => write!(f, "<chan {}>", status),
276+
}
277+
}
136278
}
137279
}
138280
}

0 commit comments

Comments
 (0)