diff --git a/src/builtins/def.rs b/src/builtins/def.rs index e9c06d6..0d4e739 100644 --- a/src/builtins/def.rs +++ b/src/builtins/def.rs @@ -14,27 +14,26 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -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()) } diff --git a/src/reader.rs b/src/reader.rs index fcc45e9..c35e8e6 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -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); diff --git a/src/types/collections/core.rs b/src/types/collections/core.rs index c67fe34..f95afd8 100644 --- a/src/types/collections/core.rs +++ b/src/types/collections/core.rs @@ -15,26 +15,25 @@ * along with this program. If not, see . */ +/// Seq trait describes a seqable collection. Please note that `first` +/// and `rest` return a copy of the data not the reference! pub trait Seq { - fn first(&self) -> &T; - fn rest(&self) -> Option<&Self>; + type Coll; + + fn first(&self) -> Option; + fn rest(&self) -> Self::Coll; } -pub fn first<'a, T, S: Seq>(coll: impl Into>) -> 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>(coll: impl Into>) -> Option<&'a T> +// where +// S: 'a, +// { +// coll.into().and_then(first) +// } -pub fn rest<'a, T, S: Seq>(coll: impl Into>) -> Option<&'a S> { - coll.into().and_then(rest) - // match coll.into() { - // Some(v) => v.rest(), - // None => None, - // } -} +// pub fn rest<'a, T, S: Seq>(coll: impl Into>) -> S { +// match coll.into() { +// Some(e) => e.rest(), +// None => +// } +// } diff --git a/src/types/collections/list.rs b/src/types/collections/list.rs index 2d001e2..74138c3 100644 --- a/src/types/collections/list.rs +++ b/src/types/collections/list.rs @@ -40,33 +40,43 @@ impl List { self.elements.push(elem) } - // pub fn new(first: T, rest: List) -> List { - // 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 for List { -// fn first<'a>(&'a self) -> &'a Expr { -// &self.car -// } +impl Seq 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 { + 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() + } + } +} diff --git a/src/types/symbol.rs b/src/types/symbol.rs index 82a7221..b8e9557 100644 --- a/src/types/symbol.rs +++ b/src/types/symbol.rs @@ -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" + } }