rl_lang/interpreter/stdlib/io/
input.rs1use crate::{
2 interpreter::{evaluator::Evaluator, values::Value},
3 utils::{errors::Error, span::Span},
4};
5use std::io::{self, Write};
6
7fn input(prompt: Option<Value>, eval: &mut Evaluator, span: Span) -> Result<Value, Error> {
8 match prompt {
9 None => read_line(eval, span),
10 Some(p) => {
11 let prompt = match p {
12 Value::Integer(i) => i.to_string(),
13 Value::Float(f) => f.to_string(),
14 Value::String(s) => s,
15 Value::Char(c) => c.to_string(),
16 Value::Bool(b) => b.to_string(),
17 Value::Null => "null".to_string(),
18 _ => "".to_string(),
19 };
20 print!("{}", prompt);
21 io::stdout().flush().ok();
22 read_line(eval, span)
23 }
24 }
25}
26
27fn read_line(eval: &mut Evaluator, span: Span) -> Result<Value, Error> {
28 let mut input = String::new();
29 io::stdin()
30 .read_line(&mut input)
31 .map_err(|e| eval.err(format!("read(): failed to read line: {}", e), span))?;
32 Ok(Value::String(input.trim().to_string()))
33}
34
35pub fn std_read(eval: &mut Evaluator, args: Vec<Value>, span: Span) -> Result<Value, Error> {
36 let len = args.len();
37 let mut args = args.into_iter();
38
39 match len {
40 0 => input(None, eval, span),
41 1 => input(args.next(), eval, span),
42 n => Err(eval.err(
43 format!("read() expects 0 or 1 argument(s), got {}", n),
44 span,
45 )),
46 }
47}
48
49pub fn std_read_int(eval: &mut Evaluator, args: Vec<Value>, span: Span) -> Result<Value, Error> {
51 let len = args.len();
52 let mut args = args.into_iter();
53
54 let value = match len {
55 0 => input(None, eval, span),
56 1 => input(args.next(), eval, span),
57 n => Err(eval.err(
58 format!("read_int() expects 0 or 1 argument(s), got {}", n),
59 span,
60 )),
61 }?;
62
63 match value {
64 Value::String(s) => s.parse::<i64>().map(Value::Integer).map_err(|_| {
65 eval.err(
66 format!("read_int(): \"{}\" is not a valid integer", s),
67 span,
68 )
69 }),
70 Value::Integer(i) => Ok(Value::Integer(i)),
72 Value::Float(f) => Ok(Value::Integer(f as i64)),
73 other => Err(eval.err(
74 format!(
75 "read_int(): found unsupported type from input, got {}",
76 other.type_name()
77 ),
78 span,
79 )),
80 }
81}
82
83pub fn std_read_float(eval: &mut Evaluator, args: Vec<Value>, span: Span) -> Result<Value, Error> {
85 let len = args.len();
86 let mut args = args.into_iter();
87
88 let value = match len {
89 0 => input(None, eval, span),
90 1 => input(args.next(), eval, span),
91 n => Err(eval.err(
92 format!("read_float() expects 0 or 1 argument(s), got {}", n),
93 span,
94 )),
95 }?;
96
97 match value {
98 Value::String(s) => s.parse::<f64>().map(Value::Float).map_err(|_| {
99 eval.err(
100 format!("read_float(): \"{}\" is not a valid float", s),
101 span,
102 )
103 }),
104 Value::Integer(i) => Ok(Value::Float(i as f64)),
106 Value::Float(f) => Ok(Value::Float(f)),
107 other => Err(eval.err(
108 format!(
109 "read_float(): found unsupported type from input, got {}",
110 other.type_name()
111 ),
112 span,
113 )),
114 }
115}