repl i guess

repl
Avril 4 years ago
parent 5169227499
commit 784f3f2c10
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -7,7 +7,9 @@ use std::io;
use rustyline::error::ReadlineError; use rustyline::error::ReadlineError;
use rustyline::Editor; use rustyline::Editor;
mod env;
mod command; mod command;
mod opcodes;
/// Default history file name /// Default history file name
/// ///

@ -1,103 +1,8 @@
//! Repl commands //! Repl commands
use super::*; use super::*;
use std::str::FromStr; use std::str::FromStr;
use std::collections::{BTreeMap, HashMap};
#[derive(Debug)] use super::env::*;
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();
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Context<'a> pub struct Context<'a>
@ -106,14 +11,6 @@ pub struct Context<'a>
env: &'a mut Lexenv, env: &'a mut Lexenv,
} }
#[derive(Debug)]
pub enum Value
{
String(String),
Symbol(String),
List(Vec<Value>),
}
/// Trait for commands. /// Trait for commands.
/// ///
/// # Defining commands /// # Defining commands
@ -130,7 +27,7 @@ pub trait Command: fmt::Debug
pub struct IR pub struct IR
{ {
op: String, op: String,
params: Vec<String>, params: Vec<Value>,
} }
impl FromStr for IR impl FromStr for IR

@ -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…
Cancel
Save