Finialize the Seq trait to return a copy of data instead of reference
This commit is contained in:
parent
298dc89025
commit
fe1724ce22
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 =>
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue