Finialize the Seq trait to return a copy of data instead of reference

This commit is contained in:
Sameer Rahmani 2020-09-19 01:23:33 +01:00
parent 298dc89025
commit fe1724ce22
5 changed files with 69 additions and 59 deletions

View File

@ -14,27 +14,26 @@
* 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::Seq;
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: 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() != 2 {
// // 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 = args.first();
// //let value = first(rest(rest(args))); let value = args.rest().first();
// println!("<<<< {:?}", name); println!("<<<< {:?} \n {:?}", name, value);
// // 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

@ -126,15 +126,13 @@ impl ExprReader {
match self.read_expr(reader) { match self.read_expr(reader) {
Ok(value) => result.push(value), 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 ?
// TODO: we might want to return an actual empty list here
Some(')') => return Ok(Expr::list_to_cons(result)), Some(')') => return Ok(Expr::list_to_cons(result)),
_ => return Err(e), _ => return Err(e),
}, },
}; };
loop { loop {
let next = match self.get_char(reader, true) { match self.get_char(reader, true) {
Some(')') => return Ok(Expr::list_to_cons(result)), Some(')') => return Ok(Expr::list_to_cons(result)),
Some(e) => { Some(e) => {
self.unget_char(e); self.unget_char(e);

View File

@ -15,26 +15,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/// Seq trait describes a seqable collection. Please note that `first`
/// and `rest` return a copy of the data not the reference!
pub trait Seq<T> { pub trait Seq<T> {
fn first(&self) -> &T; type Coll;
fn rest(&self) -> Option<&Self>;
fn first(&self) -> Option<T>;
fn rest(&self) -> Self::Coll;
} }
pub fn first<'a, T, S: Seq<T>>(coll: impl Into<Option<&'a S>>) -> Option<&'a T> // pub fn first<'a, T, S: Seq<T>>(coll: impl Into<Option<&'a S>>) -> Option<&'a T>
where // where
S: 'a, // S: 'a,
{ // {
coll.into().and_then(first) // coll.into().and_then(first)
// match coll.into() { // }
// Some(v) => Some(v.first()),
// None => None,
// }
}
pub fn rest<'a, T, S: Seq<T>>(coll: impl Into<Option<&'a S>>) -> Option<&'a S> { // pub fn rest<'a, T, S: Seq<T>>(coll: impl Into<Option<&'a S>>) -> S {
coll.into().and_then(rest) // match coll.into() {
// match coll.into() { // Some(e) => e.rest(),
// Some(v) => v.rest(), // None =>
// None => None, // }
// } // }
}

View File

@ -40,33 +40,43 @@ impl List {
self.elements.push(elem) self.elements.push(elem)
} }
// pub fn new(first: T, rest: List<T>) -> List<T> { pub fn length(&self) -> usize {
// List::Cons(first, Box::new(rest)) self.elements.len()
// } }
} }
impl Expression for List { impl Expression for List {
fn eval() {} fn eval() {}
fn code_gen<'ctx>(&self, compiler: &'ctx Compiler) -> ExprResult<'ctx> { fn code_gen<'ctx>(&self, compiler: &'ctx Compiler) -> ExprResult<'ctx> {
// match &self.car { match self.first() {
// Expr::Sym(s) => def(compiler, self), Some(e) => match e {
// _ => , Expr::Sym(s) if s.is_def() => def(compiler, self.rest()),
// } _ => Err("Not implemented on list".to_string()),
//def(compiler, self); },
Err("Not implemented on list".to_string())
// TODO: We need to return an empty list here
None => Err("Can't not evaluate empty list".to_string()),
}
// def(compiler, self);
// Err("Not implemented on list".to_string())
} }
} }
// impl Seq<Expr> for List<T> { impl Seq<Expr> for List {
// fn first<'a>(&'a self) -> &'a Expr { type Coll = List;
// &self.car
// }
// fn rest<'a>(&'a self) -> Option<&'a List> { fn first(&self) -> Option<Expr> {
// match &self.cdr { match self.elements.first() {
// Expr::Nil => None, Some(e) => Some(e.clone()),
// Expr::Cons(v) => Some(v), None => None,
// _ => panic!("'rest' should not match anything else!"), }
// } }
// }
// } fn rest(&self) -> List {
if self.length() > 0 {
List::new(&self.elements[1..])
} else {
List::new_empty()
}
}
}

View File

@ -20,7 +20,7 @@ use inkwell::values::AnyValueEnum;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Symbol { pub struct Symbol {
name: String, pub name: String,
} }
impl PartialEq for Symbol { impl PartialEq for Symbol {
@ -49,4 +49,8 @@ impl Symbol {
pub fn new(name: String) -> Self { pub fn new(name: String) -> Self {
Symbol { name } Symbol { name }
} }
pub fn is_def(&self) -> bool {
self.name == "def"
}
} }