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
|
* 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())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
// }
|
||||||
// }
|
// }
|
||||||
}
|
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue