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
* 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::collections::core::Seq;
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
// 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() != 2 {
// 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 = args.first();
let value = args.rest().first();
// println!("<<<< {:?}", name);
// // TODO: make sure that `def_` is a symbol and its name is "def"
println!("<<<< {:?} \n {:?}", name, value);
// TODO: make sure that `def_` is a symbol and its name is "def"
Err("Is not completed".to_string())
}

View File

@ -126,15 +126,13 @@ impl ExprReader {
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::list_to_cons(result)),
_ => return Err(e),
},
};
loop {
let next = match self.get_char(reader, true) {
match self.get_char(reader, true) {
Some(')') => return Ok(Expr::list_to_cons(result)),
Some(e) => {
self.unget_char(e);

View File

@ -15,26 +15,25 @@
* 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> {
fn first(&self) -> &T;
fn rest(&self) -> Option<&Self>;
type Coll;
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>
where
S: 'a,
{
coll.into().and_then(first)
// match coll.into() {
// Some(v) => Some(v.first()),
// None => None,
// }
}
// pub fn first<'a, T, S: Seq<T>>(coll: impl Into<Option<&'a S>>) -> Option<&'a T>
// where
// S: 'a,
// {
// coll.into().and_then(first)
// }
pub fn rest<'a, T, S: Seq<T>>(coll: impl Into<Option<&'a S>>) -> Option<&'a S> {
coll.into().and_then(rest)
// match coll.into() {
// Some(v) => v.rest(),
// None => None,
// }
}
// pub fn rest<'a, T, S: Seq<T>>(coll: impl Into<Option<&'a S>>) -> S {
// match coll.into() {
// Some(e) => e.rest(),
// None =>
// }
// }

View File

@ -40,33 +40,43 @@ impl List {
self.elements.push(elem)
}
// pub fn new(first: T, rest: List<T>) -> List<T> {
// List::Cons(first, Box::new(rest))
// }
pub fn length(&self) -> usize {
self.elements.len()
}
}
impl Expression for List {
fn eval() {}
fn code_gen<'ctx>(&self, compiler: &'ctx Compiler) -> ExprResult<'ctx> {
// match &self.car {
// Expr::Sym(s) => def(compiler, self),
// _ => ,
// }
//def(compiler, self);
Err("Not implemented on list".to_string())
match self.first() {
Some(e) => match e {
Expr::Sym(s) if s.is_def() => def(compiler, self.rest()),
_ => 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> {
// fn first<'a>(&'a self) -> &'a Expr {
// &self.car
// }
impl Seq<Expr> for List {
type Coll = List;
// 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 first(&self) -> Option<Expr> {
match self.elements.first() {
Some(e) => Some(e.clone()),
None => None,
}
}
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)]
pub struct Symbol {
name: String,
pub name: String,
}
impl PartialEq for Symbol {
@ -49,4 +49,8 @@ impl Symbol {
pub fn new(name: String) -> Self {
Symbol { name }
}
pub fn is_def(&self) -> bool {
self.name == "def"
}
}