parent
5169227499
commit
784f3f2c10
@ -0,0 +1,242 @@
|
||||
//! Execution environment for repl
|
||||
use super::*;
|
||||
use std::str::FromStr;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Lexenv
|
||||
{
|
||||
/// Maps symbol name to value in generations.
|
||||
kvstack: BTreeMap<usize, HashMap<String, Value>>,
|
||||
/// Current generation of the satck
|
||||
current_generation: usize,
|
||||
}
|
||||
impl Lexenv
|
||||
{
|
||||
/// The generation number of the current level.
|
||||
pub fn depth(&self) -> usize
|
||||
{
|
||||
self.current_generation
|
||||
}
|
||||
/// Create a new empty lexenv
|
||||
pub fn new() -> Self
|
||||
{
|
||||
Self {
|
||||
kvstack: BTreeMap::new(),
|
||||
current_generation: 0,
|
||||
}
|
||||
}
|
||||
/// All valid symbols at this level.
|
||||
///
|
||||
/// # Ordering
|
||||
/// Each symbol's level will appear in the order from level 0 to the current level, however the order of intra-level symbols is undefined.
|
||||
pub fn symbols(&self) -> impl Iterator<Item = &'_ Value> + '_
|
||||
{
|
||||
self.kvstack.range(0..=self.current_generation).flat_map(|(_, v)| v.values())
|
||||
}
|
||||
|
||||
/// All valid symbols **in** this level.
|
||||
pub fn symbols_local(&self) -> impl Iterator<Item = &'_ Value> + '_
|
||||
{
|
||||
OptionIterator::from(self.kvstack.get(&self.current_generation).map(|x| x.values()))
|
||||
}
|
||||
|
||||
/// Remove the current level, but leave its memory allocated for further use.
|
||||
pub fn pop(&mut self)
|
||||
{
|
||||
self.kvstack.entry(self.current_generation).or_insert_with(|| HashMap::new()).clear();
|
||||
if self.current_generation > 0 {
|
||||
self.current_generation-=1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove a symbol from the **current** level.
|
||||
pub fn remove(&mut self, name: &str) -> Option<Value>
|
||||
{
|
||||
self.kvstack.entry(self.current_generation).or_insert_with(|| HashMap::new()).remove(name)
|
||||
}
|
||||
|
||||
/// Insert a new value mapping into the current level.
|
||||
pub fn insert(&mut self, name: String, value: Value)
|
||||
{
|
||||
self.kvstack.entry(self.current_generation).or_insert_with(|| HashMap::new()).insert(name, value);
|
||||
}
|
||||
|
||||
/// Look up a symbol in this or any of the above levels.
|
||||
pub fn lookup(&self, name: &str) -> Option<&Value>
|
||||
{
|
||||
for (_, lvmap) in self.kvstack.range(0..=self.current_generation).rev()
|
||||
{
|
||||
let m = lvmap.get(name);
|
||||
if m.is_some() {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Look up a symbol in this level.
|
||||
pub fn lookup_local(&self, name: &str) -> Option<&Value>
|
||||
{
|
||||
self.kvstack.get(&self.current_generation).map(|map| map.get(name)).flatten()
|
||||
}
|
||||
|
||||
/// Create a new, empty level.
|
||||
pub fn push(&mut self)
|
||||
{
|
||||
self.current_generation+=1;
|
||||
}
|
||||
|
||||
/// Remove the current level, deallocating any memory it was using.
|
||||
pub fn pop_clear(&mut self)
|
||||
{
|
||||
if self.current_generation > 0 {
|
||||
self.kvstack.remove(&self.current_generation);
|
||||
self.current_generation -=1;
|
||||
} else {
|
||||
self.kvstack.entry(0).or_insert_with(|| HashMap::new()).clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The value type
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum Value
|
||||
{
|
||||
String(String),
|
||||
Symbol(String),
|
||||
List(Vec<Value>),
|
||||
}
|
||||
|
||||
impl Value
|
||||
{
|
||||
/// Parse from an iterator of `char`s.
|
||||
pub fn parse_chars<T>(ch: &mut T) -> Result<Self, ValueParseError>
|
||||
where T: Iterator<Item = char>
|
||||
{
|
||||
|
||||
match ch.next()
|
||||
{
|
||||
Some('(') => {
|
||||
todo!("list");
|
||||
},
|
||||
Some('"') => {
|
||||
todo!("string");
|
||||
},
|
||||
Some(first_chr) => {
|
||||
todo!("symbol");
|
||||
},
|
||||
_ => Err(ValueParseError(String::default())),
|
||||
}
|
||||
}
|
||||
/// Parse a `Value` from this string and then return the rest of the string.
|
||||
#[deprecated]
|
||||
pub fn parse_running(s: &str) -> Result<(Self, &'_ str), ValueParseError>
|
||||
{
|
||||
match s.trim().as_bytes()
|
||||
{
|
||||
& [b'(', ..] => {
|
||||
todo!("list");
|
||||
},
|
||||
& [b'"', ..] => {
|
||||
todo!("string");
|
||||
},
|
||||
_ => {
|
||||
todo!("shmbol");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Value
|
||||
{
|
||||
type Err = ValueParseError;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Self::parse_running(s).map(|(x, _)| x)
|
||||
}
|
||||
}
|
||||
|
||||
impl Value
|
||||
{
|
||||
pub fn try_as_symbol(&self) -> Result<&str, ValueTypeError>
|
||||
{
|
||||
match self {
|
||||
Self::Symbol(s) => Ok(&s[..]),
|
||||
_ => Err(ValueTypeError::Symbol),
|
||||
}
|
||||
}
|
||||
pub fn try_as_string(&self) -> Result<&str, ValueTypeError>
|
||||
{
|
||||
match self {
|
||||
Self::Symbol(s) |
|
||||
Self::String(s) => Ok(&s[..]),
|
||||
_ => Err(ValueTypeError::String),
|
||||
}
|
||||
}
|
||||
pub fn try_as_list(&self) -> Result<&[Value], ValueTypeError>
|
||||
{
|
||||
match self {
|
||||
Self::List(l) => Ok(&l[..]),
|
||||
_ => Err(ValueTypeError::List),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_symbol(&self) -> Option<&str>
|
||||
{
|
||||
match self {
|
||||
Self::Symbol(s) => Some(&s[..]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn as_string(&self) -> Option<&str>
|
||||
{
|
||||
match self {
|
||||
Self::Symbol(s) |
|
||||
Self::String(s) => Some(&s[..]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn as_list(&self) -> Option<&[Value]>
|
||||
{
|
||||
match self {
|
||||
Self::List(l) => Some(&l[..]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Error when using `try_as_*` functions on `Value`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
|
||||
pub enum ValueTypeError
|
||||
{
|
||||
Symbol,
|
||||
String,
|
||||
List,
|
||||
}
|
||||
|
||||
/// Error when parsing a `Value` from a stirng.
|
||||
#[derive(Debug)]
|
||||
pub struct ValueParseError(String);
|
||||
|
||||
impl error::Error for ValueParseError{}
|
||||
impl fmt::Display for ValueParseError
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||
{
|
||||
write!(f, "cannot parse {:?}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for ValueTypeError{}
|
||||
impl fmt::Display for ValueTypeError
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||
{
|
||||
write!(f, "type error: expected ")?;
|
||||
match self {
|
||||
Self::Symbol => write!(f, "symbol"),
|
||||
Self::String => write!(f, "string"),
|
||||
Self::List => write!(f, "list"),
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
//! Defined commands
|
||||
use super::*;
|
||||
|
||||
use env::*;
|
||||
use command::*;
|
||||
|
||||
/// Contains all operations
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Operations
|
||||
{
|
||||
|
||||
}
|
||||
|
Loading…
Reference in new issue