@@ -3,6 +3,9 @@ use std::collections::HashMap;
33use std:: fmt;
44use std:: rc:: Rc ;
55use 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 ) ]
48180pub 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
65199impl 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