1use std::io::{self, Write};
28use std::sync::{Arc, Mutex};
29
30use mumu::{
31 parser::interpreter::Interpreter,
32 parser::types::{FunctionValue, InkIteratorKind, Value},
33};
34
35fn to_printable(v: &Value) -> String {
38 match v {
39 Value::SingleString(s) => s.clone(),
40 Value::Int(i) => i.to_string(),
41 Value::Long(l) => l.to_string(),
42 Value::Float(f) => f.to_string(),
43 Value::Bool(b) => b.to_string(),
44 _ => format!("{:?}", v),
46 }
47}
48
49fn print_no_nl(interp: &mut Interpreter, s: &str) {
50 print!("{}", s);
51 let _ = io::stdout().flush();
52 interp.push_print(s);
53}
54
55fn print_with_nl(interp: &mut Interpreter, s: &str) {
56 println!("{}", s);
57 interp.push_print(&(s.to_string() + "\n"));
58}
59
60fn drain_ink_transform(
63 interp: &mut Interpreter,
64 f: &FunctionValue,
65 printer: &dyn Fn(&mut Interpreter, &str),
66) -> Result<(), String> {
67 match f {
68 FunctionValue::RustClosure(_desc, closure_arc, _arity) => {
69 loop {
70 let cb = closure_arc
72 .lock()
73 .map_err(|_| "std:put => closure poisoned".to_string())?;
74 let out = cb(interp, vec![]);
75 drop(cb);
76
77 match out {
78 Ok(item) => {
79 let s = to_printable(&item);
80 printer(interp, &s);
81 }
82 Err(e) if e == "NO_MORE_DATA" => break,
83 Err(e) => return Err(e),
84 }
85 }
86 Ok(())
87 }
88 _ => {
89 Ok(())
91 }
92 }
93}
94
95fn std_input_bridge(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
98 if args.len() > 1 {
99 return Err(format!(
100 "std:input => expected 0 or 1 arg (prompt), got {}",
101 args.len()
102 ));
103 }
104
105 if let Some(Value::SingleString(prompt)) = args.get(0) {
106 print!("{}", prompt);
107 let _ = io::stdout().flush();
108 }
109
110 let mut buf = String::new();
111 match io::stdin().read_line(&mut buf) {
112 Ok(0) => Ok(Value::SingleString(String::new())), Ok(_) => {
114 if buf.ends_with('\n') {
115 buf.pop();
116 if buf.ends_with('\r') {
117 buf.pop();
118 }
119 }
120 Ok(Value::SingleString(buf))
121 }
122 Err(e) => Err(format!("std:input => {}", e)),
123 }
124}
125
126fn std_input_iter_bridge(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
127 if !args.is_empty() {
128 return Err(format!(
129 "std:input_iter => expected 0 args, got {}",
130 args.len()
131 ));
132 }
133
134 let closure = Arc::new(Mutex::new(
137 move |_i: &mut Interpreter, _argv: Vec<Value>| -> Result<Value, String> {
138 let mut buf = String::new();
139 let n = io::stdin()
140 .read_line(&mut buf)
141 .map_err(|e| format!("std:input_iter => {}", e))?;
142 if n == 0 {
143 return Err("NO_MORE_DATA".into());
144 }
145 if buf.ends_with('\n') {
146 buf.pop();
147 if buf.ends_with('\r') {
148 buf.pop();
149 }
150 }
151 Ok(Value::SingleString(buf))
152 },
153 ));
154
155 Ok(Value::InkTransform(Box::new(FunctionValue::RustClosure(
156 "std:input_iter".to_string(),
157 closure,
158 0,
159 ))))
160}
161
162fn std_put_bridge(interp: &mut Interpreter, mut args: Vec<Value>) -> Result<Value, String> {
163 if args.len() != 1 {
164 return Err(format!(
165 "std:put => expected exactly 1 argument, got {}",
166 args.len()
167 ));
168 }
169 let val = args.remove(0);
170
171 let res: Result<(), String> = match &val {
174 Value::InkTransform(fb) => drain_ink_transform(interp, fb, &print_no_nl),
176
177 Value::InkIterator(handle) => match &handle.kind {
179 InkIteratorKind::Core(state_arc) => {
180 let mut guard = state_arc
181 .lock()
182 .map_err(|_| "std:put => iterator lock error".to_string())?;
183 while !guard.done && guard.current < guard.end {
184 let item = guard.current;
185 guard.current += 1;
186 if guard.current >= guard.end {
187 guard.done = true;
188 }
189 drop(guard);
190 print_no_nl(interp, &item.to_string());
191 guard = state_arc
192 .lock()
193 .map_err(|_| "std:put => iterator lock error".to_string())?;
194 }
195 Ok(())
196 }
197 InkIteratorKind::Plugin(plugin_arc) => {
198 let mut plugin = plugin_arc
199 .lock()
200 .map_err(|_| "std:put => plugin iterator lock error".to_string())?;
201 loop {
202 match plugin.next_value() {
203 Ok(item) => {
204 let s = to_printable(&item);
205 print_no_nl(interp, &s);
206 }
207 Err(e) if e == "NO_MORE_DATA" => break,
208 Err(e) => return Err(e),
209 }
210 }
211 Ok(())
212 }
213 },
214
215 other => {
217 let s = to_printable(other);
218 print_no_nl(interp, &s);
219 Ok(())
220 }
221 };
222
223 res?;
224 Ok(val)
225}
226
227fn std_log_bridge(interp: &mut Interpreter, mut args: Vec<Value>) -> Result<Value, String> {
228 if args.len() != 1 {
229 return Err(format!(
230 "std:log => expected exactly 1 argument, got {}",
231 args.len()
232 ));
233 }
234 let val = args.remove(0);
235
236 let res: Result<(), String> = match &val {
239 Value::InkTransform(fb) => drain_ink_transform(interp, fb, &print_with_nl),
240 Value::InkIterator(handle) => match &handle.kind {
241 InkIteratorKind::Core(state_arc) => {
242 let mut guard = state_arc
243 .lock()
244 .map_err(|_| "std:log => iterator lock error".to_string())?;
245 while !guard.done && guard.current < guard.end {
246 let item = guard.current;
247 guard.current += 1;
248 if guard.current >= guard.end {
249 guard.done = true;
250 }
251 drop(guard);
252 print_with_nl(interp, &item.to_string());
253 guard = state_arc
254 .lock()
255 .map_err(|_| "std:log => iterator lock error".to_string())?;
256 }
257 Ok(())
258 }
259 InkIteratorKind::Plugin(plugin_arc) => {
260 let mut plugin = plugin_arc
261 .lock()
262 .map_err(|_| "std:log => plugin iterator lock error".to_string())?;
263 loop {
264 match plugin.next_value() {
265 Ok(item) => {
266 let s = to_printable(&item);
267 print_with_nl(interp, &s);
268 }
269 Err(e) if e == "NO_MORE_DATA" => break,
270 Err(e) => return Err(e),
271 }
272 }
273 Ok(())
274 }
275 },
276 other => {
277 let s = to_printable(other);
278 print_with_nl(interp, &s);
279 Ok(())
280 }
281 };
282
283 res?;
284 Ok(val)
285}
286
287#[export_name = "Cargo_lock"]
290pub unsafe extern "C" fn cargo_lock(
291 interp_ptr: *mut std::ffi::c_void,
292 _extra: *const std::ffi::c_void,
293) -> i32 {
294 if interp_ptr.is_null() {
295 return 1;
296 }
297 let interp = &mut *(interp_ptr as *mut Interpreter);
298
299 let f_input = Arc::new(Mutex::new(std_input_bridge));
301 let f_iter = Arc::new(Mutex::new(std_input_iter_bridge));
302 let f_put = Arc::new(Mutex::new(std_put_bridge));
303 let f_log = Arc::new(Mutex::new(std_log_bridge));
304
305 interp.register_dynamic_function("std:input", f_input);
306 interp.register_dynamic_function("std:input_iter", f_iter);
307 interp.register_dynamic_function("std:put", f_put);
308 interp.register_dynamic_function("std:log", f_log);
309
310 interp.set_variable(
312 "std:input",
313 Value::Function(Box::new(FunctionValue::Named("std:input".into()))),
314 );
315 interp.set_variable(
316 "std:input_iter",
317 Value::Function(Box::new(FunctionValue::Named("std:input_iter".into()))),
318 );
319 interp.set_variable(
320 "std:put",
321 Value::Function(Box::new(FunctionValue::Named("std:put".into()))),
322 );
323 interp.set_variable(
324 "std:log",
325 Value::Function(Box::new(FunctionValue::Named("std:log".into()))),
326 );
327
328 0
329}