Add Expression trait and new cons implementation

This commit is contained in:
Sameer Rahmani 2020-06-20 15:20:05 +01:00
parent 30a7dbfce5
commit 0065c2edf1
5 changed files with 52 additions and 18 deletions

View File

@ -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<Expr>),
//List(list::List<Expr>),
Symbol(String),
Str(String),
Quote(Box<Expr>),
Num(Number),
Comment,
Error(String),
Cons(Box<Expr>, Box<Expr>),
// Cons(Box<Expr>, Box<Expr>),
Cons(list::List<Expr>),
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::<Expr>::new(Box::new(first), Box::new(rest)))
}
}
impl Expression for Expr {
fn eval() {}
fn code_gen() {}
}

View File

@ -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<T: Expression> {
first: Box<T>,
rest: Box<T>,
}
impl<T: Expression> List<T> {
pub fn new<S: Expression>(first: Box<S>, rest: Box<S>) -> List<S> {
List { first, rest }
}
}
impl<T: Expression> Expression for List<T> {
fn eval() {}
fn code_gen() {}
}

4
src/expr.rs Normal file
View File

@ -0,0 +1,4 @@
pub trait Expression {
fn eval();
fn code_gen();
}

View File

@ -7,6 +7,7 @@ use std::string::String;
pub mod ast;
pub mod collections;
pub mod expr;
pub mod reader;
fn main() -> io::Result<()> {

View File

@ -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<Expr, String>;
@ -74,10 +78,10 @@ impl ExprReader {
fn read_quoted_expr<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult {
let rest = self.read_expr(reader)?;
Ok(Expr::Cons(
Ok(Expr::Cons(lst::List::<Expr>::new(
Box::new(Expr::Symbol("quote".to_string())),
Box::new(rest),
))
)))
}
fn read_unquoted_expr<T: Read>(&mut self, reader: &mut BufReader<T>) -> 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::<Expr>::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::<Expr>::new(
Box::new(Expr::Symbol("unquote".to_string())),
Box::new(rest),
))
)))
}
}
}
fn read_quasiquoted_expr<T: Read>(&mut self, reader: &mut BufReader<T>) -> ReadResult {
let rest = self.read_expr(reader)?;
Ok(Expr::Cons(
Ok(Expr::Cons(lst::List::<Expr>::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::<Expr>::new(
Box::new(first),
Box::new(rest),
)))
}
fn is_valid_for_identifier(&self, c: char) -> bool {