2024-12-10 01:34:53 -05:00
|
|
|
use std::io::{stdin, stdout, Write};
|
2024-12-17 07:10:47 -05:00
|
|
|
use std::ops::Range;
|
2024-12-10 01:34:53 -05:00
|
|
|
|
2024-12-17 07:10:47 -05:00
|
|
|
use crate::vm::{Register, ThreadSignal};
|
2024-12-17 03:22:44 -05:00
|
|
|
use crate::{vm::Record, ConcreteValue, NativeFunctionError, Value};
|
2024-12-10 01:34:53 -05:00
|
|
|
|
2024-12-17 03:22:44 -05:00
|
|
|
pub fn read_line(
|
|
|
|
record: &mut Record,
|
2024-12-17 07:10:47 -05:00
|
|
|
destination: Option<u8>,
|
|
|
|
_argument_range: Range<u8>,
|
|
|
|
) -> Result<ThreadSignal, NativeFunctionError> {
|
|
|
|
let destination = destination.unwrap();
|
2024-12-10 01:34:53 -05:00
|
|
|
let mut buffer = String::new();
|
|
|
|
|
|
|
|
match stdin().read_line(&mut buffer) {
|
|
|
|
Ok(_) => {
|
|
|
|
let length = buffer.len();
|
|
|
|
|
|
|
|
buffer.truncate(length.saturating_sub(1));
|
|
|
|
|
2024-12-17 07:10:47 -05:00
|
|
|
let register = Register::Value(Value::Concrete(ConcreteValue::string(buffer)));
|
|
|
|
|
|
|
|
record.set_register(destination, register);
|
|
|
|
}
|
|
|
|
Err(error) => {
|
|
|
|
return Err(NativeFunctionError::Io {
|
|
|
|
error: error.kind(),
|
|
|
|
position: record.current_position(),
|
|
|
|
})
|
2024-12-10 01:34:53 -05:00
|
|
|
}
|
|
|
|
}
|
2024-12-17 07:10:47 -05:00
|
|
|
|
|
|
|
Ok(ThreadSignal::Continue)
|
2024-12-10 01:34:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn write(
|
2024-12-17 03:22:44 -05:00
|
|
|
record: &mut Record,
|
2024-12-17 07:10:47 -05:00
|
|
|
_destination: Option<u8>,
|
|
|
|
argument_range: Range<u8>,
|
|
|
|
) -> Result<ThreadSignal, NativeFunctionError> {
|
2024-12-10 01:34:53 -05:00
|
|
|
let mut stdout = stdout();
|
|
|
|
|
2024-12-17 07:10:47 -05:00
|
|
|
for register_index in argument_range {
|
|
|
|
let value = record.open_register(register_index);
|
|
|
|
let string = value.display(record);
|
2024-12-10 01:34:53 -05:00
|
|
|
|
|
|
|
stdout
|
2024-12-17 07:10:47 -05:00
|
|
|
.write(string.as_bytes())
|
2024-12-10 01:34:53 -05:00
|
|
|
.map_err(|io_error| NativeFunctionError::Io {
|
|
|
|
error: io_error.kind(),
|
2024-12-17 07:10:47 -05:00
|
|
|
position: record.current_position(),
|
2024-12-10 01:34:53 -05:00
|
|
|
})?;
|
|
|
|
}
|
|
|
|
|
2024-12-17 07:10:47 -05:00
|
|
|
stdout.flush().map_err(|io_error| NativeFunctionError::Io {
|
|
|
|
error: io_error.kind(),
|
|
|
|
position: record.current_position(),
|
|
|
|
})?;
|
|
|
|
|
|
|
|
Ok(ThreadSignal::Continue)
|
2024-12-10 01:34:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn write_line(
|
2024-12-17 03:22:44 -05:00
|
|
|
record: &mut Record,
|
2024-12-17 07:10:47 -05:00
|
|
|
_destination: Option<u8>,
|
|
|
|
argument_range: Range<u8>,
|
|
|
|
) -> Result<ThreadSignal, NativeFunctionError> {
|
|
|
|
let mut stdout = stdout().lock();
|
2024-12-10 01:34:53 -05:00
|
|
|
|
2024-12-17 07:10:47 -05:00
|
|
|
for register_index in argument_range {
|
|
|
|
let value = record.open_register(register_index);
|
|
|
|
let string = value.display(record);
|
2024-12-10 01:34:53 -05:00
|
|
|
|
|
|
|
stdout
|
2024-12-17 07:10:47 -05:00
|
|
|
.write(string.as_bytes())
|
|
|
|
.map_err(|io_error| NativeFunctionError::Io {
|
|
|
|
error: io_error.kind(),
|
|
|
|
position: record.current_position(),
|
|
|
|
})?;
|
|
|
|
stdout
|
|
|
|
.write(b"\n")
|
2024-12-10 01:34:53 -05:00
|
|
|
.map_err(|io_error| NativeFunctionError::Io {
|
|
|
|
error: io_error.kind(),
|
2024-12-17 07:10:47 -05:00
|
|
|
position: record.current_position(),
|
2024-12-10 01:34:53 -05:00
|
|
|
})?;
|
|
|
|
}
|
|
|
|
|
2024-12-17 07:10:47 -05:00
|
|
|
stdout.flush().map_err(|io_error| NativeFunctionError::Io {
|
|
|
|
error: io_error.kind(),
|
|
|
|
position: record.current_position(),
|
|
|
|
})?;
|
2024-12-10 01:34:53 -05:00
|
|
|
|
2024-12-17 07:10:47 -05:00
|
|
|
Ok(ThreadSignal::Continue)
|
2024-12-10 01:34:53 -05:00
|
|
|
}
|