Create a new list implementation based on vectors
This commit is contained in:
parent
bb83142ffd
commit
298dc89025
14
src/ast.rs
14
src/ast.rs
|
@ -25,14 +25,22 @@ pub enum Expr {
|
|||
Num(Number),
|
||||
Comment,
|
||||
Error(String),
|
||||
List(Box<collections::List>),
|
||||
Cons(Box<collections::List>),
|
||||
Nil,
|
||||
NoMatch,
|
||||
}
|
||||
|
||||
impl Expr {
|
||||
pub fn make_list(first: Expr, rest: Expr) -> Expr {
|
||||
Expr::List(Box::new(collections::List::new(first, rest)))
|
||||
pub fn make_list(elements: &[Expr]) -> Expr {
|
||||
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 {
|
||||
|
|
|
@ -14,26 +14,27 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
use crate::ast::Expr;
|
||||
use crate::compiler::Compiler;
|
||||
use crate::types::collections::core::{first, rest};
|
||||
use crate::types::{ExprResult, List};
|
||||
|
||||
pub fn def<'a>(compiler: &'a Compiler, args: &'a List) -> ExprResult<'a> {
|
||||
// TODO: We need to support docstrings for def
|
||||
if args.length != 3 {
|
||||
// TODO: Raise a meaningful error by including the location
|
||||
panic!(format!(
|
||||
"`def` expects 2 parameters, '{}' given.",
|
||||
args.length
|
||||
));
|
||||
}
|
||||
// if args.length != 3 {
|
||||
// // TODO: Raise a meaningful error by including the location
|
||||
// panic!(format!(
|
||||
// "`def` expects 2 parameters, '{}' given.",
|
||||
// args.length
|
||||
// ));
|
||||
// }
|
||||
|
||||
//let def_ = &args.first;1
|
||||
let name = first(rest(args));
|
||||
//let value = first(rest(rest(args)));
|
||||
// //let def_ = &args.first;1
|
||||
// let name = first(rest(args));
|
||||
// //let value = first(rest(rest(args)));
|
||||
|
||||
println!("<<<< {:?}", name);
|
||||
// TODO: make sure that `def_` is a symbol and its name is "def"
|
||||
// println!("<<<< {:?}", name);
|
||||
// // TODO: make sure that `def_` is a symbol and its name is "def"
|
||||
|
||||
Err("Is not completed".to_string())
|
||||
}
|
||||
|
|
|
@ -91,10 +91,9 @@ impl ExprReader {
|
|||
|
||||
fn read_quoted_expr<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult {
|
||||
let rest = self.read_expr(reader)?;
|
||||
Ok(Expr::make_list(
|
||||
Expr::make_symbol("quote".to_string()),
|
||||
rest,
|
||||
))
|
||||
let elements = vec![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 {
|
||||
|
@ -103,50 +102,47 @@ impl ExprReader {
|
|||
// Move forward in the buffer since we peeked it
|
||||
let _ = self.get_char(reader, true);
|
||||
let rest = self.read_expr(reader)?;
|
||||
Ok(Expr::make_list(
|
||||
Expr::make_symbol("unquote-splicing".to_string()),
|
||||
rest,
|
||||
))
|
||||
let elements = vec![Expr::make_symbol("unquote-splicing".to_string()), rest];
|
||||
Ok(Expr::make_list(&elements))
|
||||
}
|
||||
_ => {
|
||||
let rest = self.read_expr(reader)?;
|
||||
Ok(Expr::make_list(
|
||||
Expr::make_symbol("unquote".to_string()),
|
||||
rest,
|
||||
))
|
||||
let elements = vec![Expr::make_symbol("unquote".to_string()), rest];
|
||||
Ok(Expr::make_list(&elements))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_quasiquoted_expr<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult {
|
||||
let rest = self.read_expr(reader)?;
|
||||
Ok(Expr::make_list(
|
||||
Expr::make_symbol("quasiquote".to_string()),
|
||||
rest,
|
||||
))
|
||||
let elements = vec![Expr::make_symbol("quasiquote".to_string()), rest];
|
||||
Ok(Expr::make_list(&elements))
|
||||
}
|
||||
|
||||
// TODO: We might want to replace Cons with an actual List struct
|
||||
fn read_list<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult {
|
||||
let first = match self.read_expr(reader) {
|
||||
Ok(value) => value,
|
||||
let mut result = Expr::make_empty_list();
|
||||
|
||||
match self.read_expr(reader) {
|
||||
Ok(value) => result.push(value),
|
||||
Err(e) => match self.get_char(reader, true) {
|
||||
// is it an empty list ?
|
||||
// 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),
|
||||
},
|
||||
};
|
||||
|
||||
let rest = match self.get_char(reader, true) {
|
||||
Some(e) => {
|
||||
self.unget_char(e);
|
||||
self.read_list(reader)?
|
||||
}
|
||||
None => return Err("Unexpected EOF while parsing a list.".to_string()),
|
||||
};
|
||||
|
||||
Ok(Expr::make_list(first, rest))
|
||||
loop {
|
||||
let next = match self.get_char(reader, true) {
|
||||
Some(')') => return Ok(Expr::list_to_cons(result)),
|
||||
Some(e) => {
|
||||
self.unget_char(e);
|
||||
result.push(self.read_expr(reader)?)
|
||||
}
|
||||
None => return Err("Unexpected EOF while parsing a list.".to_string()),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn is_valid_for_identifier(&self, c: char) -> bool {
|
||||
|
|
|
@ -22,34 +22,27 @@ use crate::types::core::{ExprResult, Expression};
|
|||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub struct List {
|
||||
pub car: Expr,
|
||||
pub cdr: Expr,
|
||||
pub length: u64,
|
||||
elements: Vec<Expr>,
|
||||
}
|
||||
//pub enum List<T> { Nil, Cons(T, Box<List<T>>) }
|
||||
|
||||
impl List {
|
||||
pub fn new(first: Expr, rest: Expr) -> List {
|
||||
// The order of field definition is important here.
|
||||
// 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
|
||||
// borrow it afterward.
|
||||
pub fn new_empty() -> List {
|
||||
List { elements: vec![] }
|
||||
}
|
||||
|
||||
pub fn new(elems: &[Expr]) -> List {
|
||||
List {
|
||||
length: match &rest {
|
||||
Expr::Cons(v) => v.length + 1,
|
||||
_ => {
|
||||
if let Expr::Nil = first {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
},
|
||||
car: first,
|
||||
cdr: rest,
|
||||
elements: elems.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -59,21 +52,21 @@ impl Expression for List {
|
|||
// Expr::Sym(s) => def(compiler, self),
|
||||
// _ => ,
|
||||
// }
|
||||
def(compiler, self);
|
||||
//def(compiler, self);
|
||||
Err("Not implemented on list".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl Seq<Expr> for List {
|
||||
fn first<'a>(&'a self) -> &'a Expr {
|
||||
&self.car
|
||||
}
|
||||
// impl Seq<Expr> for List<T> {
|
||||
// fn first<'a>(&'a self) -> &'a Expr {
|
||||
// &self.car
|
||||
// }
|
||||
|
||||
fn rest<'a>(&'a self) -> Option<&'a List> {
|
||||
match &self.cdr {
|
||||
Expr::Nil => None,
|
||||
Expr::Cons(v) => Some(v),
|
||||
_ => panic!("'rest' should not match anything else!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
// fn rest<'a>(&'a self) -> Option<&'a List> {
|
||||
// match &self.cdr {
|
||||
// Expr::Nil => None,
|
||||
// Expr::Cons(v) => Some(v),
|
||||
// _ => panic!("'rest' should not match anything else!"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
Loading…
Reference in New Issue