Create a new list implementation based on vectors

This commit is contained in:
Sameer Rahmani 2020-09-19 00:28:40 +01:00
parent bb83142ffd
commit 298dc89025
4 changed files with 76 additions and 78 deletions

View File

@ -25,14 +25,22 @@ pub enum Expr {
Num(Number), Num(Number),
Comment, Comment,
Error(String), Error(String),
List(Box<collections::List>), Cons(Box<collections::List>),
Nil, Nil,
NoMatch, NoMatch,
} }
impl Expr { impl Expr {
pub fn make_list(first: Expr, rest: Expr) -> Expr { pub fn make_list(elements: &[Expr]) -> Expr {
Expr::List(Box::new(collections::List::new(first, rest))) Expr::Cons(Box::new(collections::List::new(elements)))
}
pub fn list_to_cons(l: collections::List) -> Expr {
Expr::Cons(Box::new(l))
}
pub fn make_empty_list() -> collections::List {
collections::List::new_empty()
} }
pub fn make_symbol(v: String) -> Expr { pub fn make_symbol(v: String) -> Expr {

View File

@ -14,26 +14,27 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
use crate::ast::Expr;
use crate::compiler::Compiler; use crate::compiler::Compiler;
use crate::types::collections::core::{first, rest}; use crate::types::collections::core::{first, rest};
use crate::types::{ExprResult, List}; use crate::types::{ExprResult, List};
pub fn def<'a>(compiler: &'a Compiler, args: &'a List) -> ExprResult<'a> { pub fn def<'a>(compiler: &'a Compiler, args: &'a List) -> ExprResult<'a> {
// TODO: We need to support docstrings for def // TODO: We need to support docstrings for def
if args.length != 3 { // if args.length != 3 {
// TODO: Raise a meaningful error by including the location // // TODO: Raise a meaningful error by including the location
panic!(format!( // panic!(format!(
"`def` expects 2 parameters, '{}' given.", // "`def` expects 2 parameters, '{}' given.",
args.length // args.length
)); // ));
} // }
//let def_ = &args.first;1 // //let def_ = &args.first;1
let name = first(rest(args)); // let name = first(rest(args));
//let value = first(rest(rest(args))); // //let value = first(rest(rest(args)));
println!("<<<< {:?}", name); // println!("<<<< {:?}", name);
// TODO: make sure that `def_` is a symbol and its name is "def" // // TODO: make sure that `def_` is a symbol and its name is "def"
Err("Is not completed".to_string()) Err("Is not completed".to_string())
} }

View File

@ -91,10 +91,9 @@ impl ExprReader {
fn read_quoted_expr<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult { fn read_quoted_expr<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult {
let rest = self.read_expr(reader)?; let rest = self.read_expr(reader)?;
Ok(Expr::make_list( let elements = vec![Expr::make_symbol("quote".to_string()), rest];
Expr::make_symbol("quote".to_string()),
rest, Ok(Expr::make_list(&elements))
))
} }
fn read_unquoted_expr<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult { fn read_unquoted_expr<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult {
@ -103,50 +102,47 @@ impl ExprReader {
// Move forward in the buffer since we peeked it // Move forward in the buffer since we peeked it
let _ = self.get_char(reader, true); let _ = self.get_char(reader, true);
let rest = self.read_expr(reader)?; let rest = self.read_expr(reader)?;
Ok(Expr::make_list( let elements = vec![Expr::make_symbol("unquote-splicing".to_string()), rest];
Expr::make_symbol("unquote-splicing".to_string()), Ok(Expr::make_list(&elements))
rest,
))
} }
_ => { _ => {
let rest = self.read_expr(reader)?; let rest = self.read_expr(reader)?;
Ok(Expr::make_list( let elements = vec![Expr::make_symbol("unquote".to_string()), rest];
Expr::make_symbol("unquote".to_string()), Ok(Expr::make_list(&elements))
rest,
))
} }
} }
} }
fn read_quasiquoted_expr<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult { fn read_quasiquoted_expr<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult {
let rest = self.read_expr(reader)?; let rest = self.read_expr(reader)?;
Ok(Expr::make_list( let elements = vec![Expr::make_symbol("quasiquote".to_string()), rest];
Expr::make_symbol("quasiquote".to_string()), Ok(Expr::make_list(&elements))
rest,
))
} }
// TODO: We might want to replace Cons with an actual List struct // TODO: We might want to replace Cons with an actual List struct
fn read_list<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult { fn read_list<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult {
let first = match self.read_expr(reader) { let mut result = Expr::make_empty_list();
Ok(value) => value,
match self.read_expr(reader) {
Ok(value) => result.push(value),
Err(e) => match self.get_char(reader, true) { Err(e) => match self.get_char(reader, true) {
// is it an empty list ? // is it an empty list ?
// TODO: we might want to return an actual empty list here // TODO: we might want to return an actual empty list here
Some(')') => return Ok(Expr::Nil), Some(')') => return Ok(Expr::list_to_cons(result)),
_ => return Err(e), _ => return Err(e),
}, },
}; };
let rest = match self.get_char(reader, true) { loop {
Some(e) => { let next = match self.get_char(reader, true) {
self.unget_char(e); Some(')') => return Ok(Expr::list_to_cons(result)),
self.read_list(reader)? Some(e) => {
} self.unget_char(e);
None => return Err("Unexpected EOF while parsing a list.".to_string()), result.push(self.read_expr(reader)?)
}; }
None => return Err("Unexpected EOF while parsing a list.".to_string()),
Ok(Expr::make_list(first, rest)) };
}
} }
fn is_valid_for_identifier(&self, c: char) -> bool { fn is_valid_for_identifier(&self, c: char) -> bool {

View File

@ -22,34 +22,27 @@ use crate::types::core::{ExprResult, Expression};
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]
pub struct List { pub struct List {
pub car: Expr, elements: Vec<Expr>,
pub cdr: Expr,
pub length: u64,
} }
//pub enum List<T> { Nil, Cons(T, Box<List<T>>) }
impl List { impl List {
pub fn new(first: Expr, rest: Expr) -> List { pub fn new_empty() -> List {
// The order of field definition is important here. List { elements: vec![] }
// If we move the `length` after `rest` we're going }
// to break the ownership rule of rust because `rest: rest`
// is going to move it to the new list and we can not pub fn new(elems: &[Expr]) -> List {
// borrow it afterward.
List { List {
length: match &rest { elements: elems.to_vec(),
Expr::Cons(v) => v.length + 1,
_ => {
if let Expr::Nil = first {
0
} else {
1
}
}
},
car: first,
cdr: rest,
} }
} }
pub fn push(&mut self, elem: Expr) {
self.elements.push(elem)
}
// pub fn new(first: T, rest: List<T>) -> List<T> {
// List::Cons(first, Box::new(rest))
// }
} }
impl Expression for List { impl Expression for List {
@ -59,21 +52,21 @@ impl Expression for List {
// Expr::Sym(s) => def(compiler, self), // Expr::Sym(s) => def(compiler, self),
// _ => , // _ => ,
// } // }
def(compiler, self); //def(compiler, self);
Err("Not implemented on list".to_string()) Err("Not implemented on list".to_string())
} }
} }
impl Seq<Expr> for List { // impl Seq<Expr> for List<T> {
fn first<'a>(&'a self) -> &'a Expr { // fn first<'a>(&'a self) -> &'a Expr {
&self.car // &self.car
} // }
fn rest<'a>(&'a self) -> Option<&'a List> { // fn rest<'a>(&'a self) -> Option<&'a List> {
match &self.cdr { // match &self.cdr {
Expr::Nil => None, // Expr::Nil => None,
Expr::Cons(v) => Some(v), // Expr::Cons(v) => Some(v),
_ => panic!("'rest' should not match anything else!"), // _ => panic!("'rest' should not match anything else!"),
} // }
} // }
} // }