2024-09-01 19:16:30 +02:00
|
|
|
use std::cell::RefCell;
|
2023-01-28 01:11:55 +01:00
|
|
|
use std::fmt::Display;
|
|
|
|
|
use std::io::{stdin, stdout, Read, Write};
|
2024-09-01 19:16:30 +02:00
|
|
|
use std::rc::Rc;
|
2023-01-28 01:11:55 +01:00
|
|
|
|
2023-01-30 17:41:48 +01:00
|
|
|
use rustc_hash::FxHashMap;
|
2024-09-02 05:19:30 +02:00
|
|
|
use smol_str::SmolStr;
|
2023-01-30 17:41:48 +01:00
|
|
|
|
2023-01-28 01:11:55 +01:00
|
|
|
use super::lox_std::init_std;
|
|
|
|
|
use super::Value;
|
2024-09-03 16:48:00 +02:00
|
|
|
use crate::error::RuntimeError;
|
2023-01-28 01:11:55 +01:00
|
|
|
|
|
|
|
|
pub struct Runtime {
|
2024-09-02 05:19:30 +02:00
|
|
|
globals: FxHashMap<SmolStr, Value>,
|
2023-01-28 01:11:55 +01:00
|
|
|
|
2024-09-01 19:16:30 +02:00
|
|
|
in_stream: Rc<RefCell<dyn std::io::Read>>,
|
|
|
|
|
out_stream: Rc<RefCell<dyn std::io::Write>>,
|
|
|
|
|
|
|
|
|
|
debug: bool,
|
2023-01-28 01:11:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Runtime {
|
2024-09-01 19:16:30 +02:00
|
|
|
pub fn new(
|
|
|
|
|
in_stream: Rc<RefCell<dyn std::io::Read>>,
|
|
|
|
|
out_stream: Rc<RefCell<dyn std::io::Write>>,
|
|
|
|
|
) -> Self {
|
2023-01-28 01:11:55 +01:00
|
|
|
let mut runtime = Runtime {
|
2023-01-30 17:41:48 +01:00
|
|
|
globals: FxHashMap::default(),
|
2023-01-28 01:11:55 +01:00
|
|
|
in_stream,
|
|
|
|
|
out_stream,
|
2024-09-01 19:16:30 +02:00
|
|
|
debug: false,
|
2023-01-28 01:11:55 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
init_std(&mut runtime);
|
|
|
|
|
|
|
|
|
|
runtime
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-01 19:16:30 +02:00
|
|
|
pub fn set_debug(&mut self, debug: bool) {
|
|
|
|
|
self.debug = debug;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-01 23:15:36 +02:00
|
|
|
pub fn is_debug(&self) -> bool {
|
2024-09-01 19:16:30 +02:00
|
|
|
self.debug
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn in_stream(&mut self) -> std::cell::RefMut<dyn std::io::Read> {
|
|
|
|
|
self.in_stream.as_ref().borrow_mut()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn out_stream(&mut self) -> std::cell::RefMut<dyn std::io::Write> {
|
|
|
|
|
// &mut self.out_stream
|
|
|
|
|
self.out_stream.as_ref().borrow_mut()
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-02 05:19:30 +02:00
|
|
|
pub fn globals(&self) -> &FxHashMap<SmolStr, Value> {
|
2023-01-28 01:11:55 +01:00
|
|
|
&self.globals
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_global(&self, name: &str) -> Result<Value, RuntimeError> {
|
|
|
|
|
self.globals
|
|
|
|
|
.get(name)
|
|
|
|
|
.cloned()
|
2024-09-01 19:16:30 +02:00
|
|
|
.ok_or_else(|| RuntimeError::GlobalNotDefined {
|
|
|
|
|
name: name.to_owned(),
|
|
|
|
|
})
|
2023-01-28 01:11:55 +01:00
|
|
|
}
|
|
|
|
|
|
2024-09-02 05:19:30 +02:00
|
|
|
pub fn define_global(&mut self, name: impl Into<SmolStr>, value: Value) {
|
2023-01-28 01:11:55 +01:00
|
|
|
let name = name.into();
|
|
|
|
|
self.globals.insert(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn assign_global(&mut self, name: &str, value: Value) -> Result<(), RuntimeError> {
|
|
|
|
|
if let Some(old_value) = self.globals.get_mut(name) {
|
|
|
|
|
*old_value = value;
|
|
|
|
|
Ok(())
|
|
|
|
|
} else {
|
2024-09-01 23:15:36 +02:00
|
|
|
panic!("Global not defined not caught by resolver");
|
|
|
|
|
|
|
|
|
|
// Err(RuntimeError::GlobalNotDefined {
|
|
|
|
|
// name: name.to_owned(),
|
|
|
|
|
// })
|
2023-01-28 01:11:55 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for Runtime {
|
|
|
|
|
fn default() -> Self {
|
2024-09-01 19:16:30 +02:00
|
|
|
// let buf_reader = std::io::BufReader::new(stdin());
|
|
|
|
|
// let buf_reader_boxed = Box::new(&mut buf_reader);
|
|
|
|
|
|
|
|
|
|
let in_stream = Rc::new(RefCell::new(stdin()));
|
|
|
|
|
let out_stream = Rc::new(RefCell::new(stdout()));
|
|
|
|
|
|
|
|
|
|
Runtime::new(in_stream, out_stream)
|
2023-01-28 01:11:55 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Debug for Runtime {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
2024-09-01 19:16:30 +02:00
|
|
|
f.debug_struct("Runtime")
|
|
|
|
|
.field("globals", &self.globals)
|
|
|
|
|
.finish()
|
2023-01-28 01:11:55 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Display for Runtime {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
write!(f, "Globals:")?;
|
|
|
|
|
|
|
|
|
|
for (name, value) in self.globals.iter() {
|
|
|
|
|
write!(f, "\n\t{name} = {value}")?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Drop for Runtime {
|
|
|
|
|
fn drop(&mut self) {
|
2024-09-01 19:16:30 +02:00
|
|
|
self.out_stream().flush().unwrap();
|
2023-01-28 01:11:55 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Read for Runtime {
|
|
|
|
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
2024-09-01 19:16:30 +02:00
|
|
|
self.in_stream().read(buf)
|
2023-01-28 01:11:55 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Write for Runtime {
|
|
|
|
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
2024-09-01 19:16:30 +02:00
|
|
|
self.out_stream().write(buf)
|
2023-01-28 01:11:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn flush(&mut self) -> std::io::Result<()> {
|
2024-09-01 19:16:30 +02:00
|
|
|
self.out_stream().flush()
|
2023-01-28 01:11:55 +01:00
|
|
|
}
|
|
|
|
|
}
|