From 784f3f2c10e6e5778121006071d17596a17696e5 Mon Sep 17 00:00:00 2001 From: Avril Date: Sun, 7 Mar 2021 21:14:59 +0000 Subject: [PATCH] repl i guess --- src/info/repl.rs | 2 + src/info/repl/command.rs | 107 +---------------- src/info/repl/env.rs | 242 +++++++++++++++++++++++++++++++++++++++ src/info/repl/opcodes.rs | 13 +++ 4 files changed, 259 insertions(+), 105 deletions(-) create mode 100644 src/info/repl/env.rs create mode 100644 src/info/repl/opcodes.rs diff --git a/src/info/repl.rs b/src/info/repl.rs index 727741a..dbe86e8 100644 --- a/src/info/repl.rs +++ b/src/info/repl.rs @@ -7,7 +7,9 @@ use std::io; use rustyline::error::ReadlineError; use rustyline::Editor; +mod env; mod command; +mod opcodes; /// Default history file name /// diff --git a/src/info/repl/command.rs b/src/info/repl/command.rs index 5ff7aee..5b5adf5 100644 --- a/src/info/repl/command.rs +++ b/src/info/repl/command.rs @@ -1,103 +1,8 @@ //! Repl commands 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>, - /// 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 + '_ - { - 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 + '_ - { - 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 - { - 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(); - } - } -} +use super::env::*; #[derive(Debug)] pub struct Context<'a> @@ -106,14 +11,6 @@ pub struct Context<'a> env: &'a mut Lexenv, } -#[derive(Debug)] -pub enum Value -{ - String(String), - Symbol(String), - List(Vec), -} - /// Trait for commands. /// /// # Defining commands @@ -130,7 +27,7 @@ pub trait Command: fmt::Debug pub struct IR { op: String, - params: Vec, + params: Vec, } impl FromStr for IR diff --git a/src/info/repl/env.rs b/src/info/repl/env.rs new file mode 100644 index 0000000..dd69586 --- /dev/null +++ b/src/info/repl/env.rs @@ -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>, + /// 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 + '_ + { + 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 + '_ + { + 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 + { + 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), +} + +impl Value +{ + /// Parse from an iterator of `char`s. + pub fn parse_chars(ch: &mut T) -> Result + where T: Iterator + { + + 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::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"), + } + } +} diff --git a/src/info/repl/opcodes.rs b/src/info/repl/opcodes.rs new file mode 100644 index 0000000..2e468da --- /dev/null +++ b/src/info/repl/opcodes.rs @@ -0,0 +1,13 @@ +//! Defined commands +use super::*; + +use env::*; +use command::*; + +/// Contains all operations +#[derive(Debug, Clone)] +pub struct Operations +{ + +} +