rlox/interpreter/src/runtime.rs

101 lines
2.5 KiB
Rust
Raw Normal View History

use std::collections::HashMap;
use std::fmt::Display;
use std::io::{stdin, stdout, Read, Write};
use crate::error::RuntimeError;
use super::lox_std::init_std;
use super::Value;
pub struct Runtime {
globals: HashMap<String, Value>,
in_stream: Box<dyn std::io::BufRead>,
out_stream: Box<dyn std::io::Write>,
}
impl Runtime {
pub fn new(in_stream: Box<dyn std::io::Read>, out_stream: Box<dyn std::io::Write>) -> Self {
let in_stream = Box::new(std::io::BufReader::new(in_stream));
let mut runtime = Runtime {
globals: HashMap::new(),
in_stream,
out_stream,
};
init_std(&mut runtime);
runtime
}
pub fn globals(&self) -> &HashMap<String, Value> {
&self.globals
}
pub fn get_global(&self, name: &str) -> Result<Value, RuntimeError> {
self.globals
.get(name)
.cloned()
.ok_or_else(|| RuntimeError::GlobalNotDefined { name: name.to_owned() })
}
pub fn define_global(&mut self, name: impl Into<String>, value: Value) {
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 {
Err(RuntimeError::GlobalNotDefined { name: name.to_owned() })
}
}
}
impl Default for Runtime {
fn default() -> Self {
Runtime::new(Box::new(std::io::BufReader::new(stdin())), Box::new(stdout()))
}
}
impl std::fmt::Debug for Runtime {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Runtime").field("globals", &self.globals).finish()
}
}
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) {
self.out_stream.flush().unwrap();
}
}
impl Read for Runtime {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.in_stream.read(buf)
}
}
impl Write for Runtime {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.out_stream.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.out_stream.flush()
}
}