diff --git a/src/ast.rs b/src/ast.rs index a2f91f1..ab89faa 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,3 +1,6 @@ +use crate::collections::list; +use crate::expr::Expression; + // Note: I kept the number implementation simple for now // but we need to decide on our approach to numbers, are // we going to only support the 64bit variants? or should @@ -27,19 +30,26 @@ impl Eq for Number {} #[derive(Debug, Eq, PartialEq, Clone)] pub enum Expr { - List(Box), + //List(list::List), Symbol(String), Str(String), Quote(Box), Num(Number), Comment, Error(String), - Cons(Box, Box), + // Cons(Box, Box), + Cons(list::List), Nil, NoMatch, } -#[derive(Debug, Eq, PartialEq, Clone)] -pub enum Error { - SyntaxError, +impl Expr { + pub fn make_list(first: Expr, rest: Expr) -> Expr { + Expr::Cons(list::List::::new(Box::new(first), Box::new(rest))) + } +} + +impl Expression for Expr { + fn eval() {} + fn code_gen() {} } diff --git a/src/collections/list.rs b/src/collections/list.rs index 690ee66..07b438f 100644 --- a/src/collections/list.rs +++ b/src/collections/list.rs @@ -1,7 +1,18 @@ -pub struct List {} +use crate::expr::Expression; -impl List { - pub fn h() { - println!("Uo") +#[derive(Debug, Eq, PartialEq, Clone)] +pub struct List { + first: Box, + rest: Box, +} + +impl List { + pub fn new(first: Box, rest: Box) -> List { + List { first, rest } } } + +impl Expression for List { + fn eval() {} + fn code_gen() {} +} diff --git a/src/expr.rs b/src/expr.rs new file mode 100644 index 0000000..4b94c62 --- /dev/null +++ b/src/expr.rs @@ -0,0 +1,4 @@ +pub trait Expression { + fn eval(); + fn code_gen(); +} diff --git a/src/main.rs b/src/main.rs index df6ccc2..5fc18c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use std::string::String; pub mod ast; pub mod collections; +pub mod expr; pub mod reader; fn main() -> io::Result<()> { diff --git a/src/reader.rs b/src/reader.rs index 2e6d11b..065b762 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -1,4 +1,8 @@ use crate::ast::{Expr, Number}; +// Lst::List is the actual list implementation while +// ast::Expr::List is a variant holding the actual +// implementation. +use crate::collections::list as lst; use std::io::{BufReader, Read}; pub type ReadResult = Result; @@ -74,10 +78,10 @@ impl ExprReader { fn read_quoted_expr(&mut self, reader: &mut BufReader) -> ReadResult { let rest = self.read_expr(reader)?; - Ok(Expr::Cons( + Ok(Expr::Cons(lst::List::::new( Box::new(Expr::Symbol("quote".to_string())), Box::new(rest), - )) + ))) } fn read_unquoted_expr(&mut self, reader: &mut BufReader) -> ReadResult { @@ -86,27 +90,27 @@ impl ExprReader { // Move forward in the buffer since we peeked it let _ = self.get_char(reader, true); let rest = self.read_expr(reader)?; - Ok(Expr::Cons( + Ok(Expr::Cons(lst::List::::new( Box::new(Expr::Symbol("unquote-splicing".to_string())), Box::new(rest), - )) + ))) } _ => { let rest = self.read_expr(reader)?; - Ok(Expr::Cons( + Ok(Expr::Cons(lst::List::::new( Box::new(Expr::Symbol("unquote".to_string())), Box::new(rest), - )) + ))) } } } fn read_quasiquoted_expr(&mut self, reader: &mut BufReader) -> ReadResult { let rest = self.read_expr(reader)?; - Ok(Expr::Cons( + Ok(Expr::Cons(lst::List::::new( Box::new(Expr::Symbol("quasiquote".to_string())), Box::new(rest), - )) + ))) } // TODO: We might want to replace Cons with an actual List struct @@ -120,6 +124,7 @@ impl ExprReader { _ => return Err(e), }, }; + let rest = match self.get_char(reader, true) { Some(e) => { self.unget_char(e); @@ -128,7 +133,10 @@ impl ExprReader { None => return Err("Unexpected EOF while parsing a list.".to_string()), }; - Ok(Expr::Cons(Box::new(first), Box::new(rest))) + Ok(Expr::Cons(lst::List::::new( + Box::new(first), + Box::new(rest), + ))) } fn is_valid_for_identifier(&self, c: char) -> bool {