refactor: simplify list

replace/7746dba3cc6b3860afe1faf69e86ed84ee46988d
Natapat Samutpong 2022-02-10 04:44:22 +07:00
parent 1859a9c4bb
commit 7040bbaa12
3 changed files with 42 additions and 74 deletions

0
src/compile/mod.rs Normal file
View File

View File

@ -1,6 +1,7 @@
use std::{process::exit, fs::read_to_string};
pub mod parser;
pub mod compile;
const EXECUTABLE_NAME: &str = env!("CARGO_PKG_NAME");
const HELP_MESSAGE: &str = "\
@ -35,10 +36,19 @@ fn main() {
if args_index < args.len() {
let file_path: &str = &args[args_index];
let file_content: String = read_to_string(file_path).unwrap();
let ast = parser::parse(&file_content);
for node in ast {
println!("{:?}", node);
let parsed = parser::parse(&file_content);
let mut ast = Vec::new();
for node in parsed {
match node {
Ok(node) => { ast.push(node); },
Err(error) => {
eprintln!("ERROR: {}", error);
exit(1);
}
}
}
println!("{:#?}", ast);
} else {
println!("No file provided.");
display_help(1);

View File

@ -2,25 +2,7 @@
// brundonsmith/rust_lisp (https://github.com/brundonsmith/rust_lisp)
// go check them out!
use std::{ rc::Rc, cell::RefCell };
/// A List in Sexpr
#[derive(Debug, Clone)]
pub struct List {
pub value: Option<Rc<RefCell<Cons>>>,
}
impl List {
pub const NIL: List = List { value: None };
}
/// Cons -> (car, [cdr])
#[derive(Debug, Clone)]
pub struct Cons {
pub car: Value,
pub cdr: Option<Rc<RefCell<Cons>>>,
}
use std::{ rc::Rc, fmt };
#[derive(Debug, Clone)]
pub enum Value {
@ -30,11 +12,9 @@ pub enum Value {
Int(i64), Float(f64),
String(String), Symbol(String),
List(List),
}
List(Rc<Value>, Rc<Vec<Value>>),
impl Value {
pub const NIL: Value = Value::List(List::NIL);
Nil,
}
#[derive(Debug, Clone)]
@ -48,36 +28,25 @@ impl Tree {
match self {
Tree::Atom { atom, quote } => {
if quote {
Value::List(List {
value: Some(Rc::new(RefCell::new(Cons {
car: Value::Symbol(String::from("quote")),
cdr: Some(Rc::new(RefCell::new(Cons {
car: atom, // car vroom vroom 🚗
cdr: None,
}))),
}))),
})
Value::List(
Rc::new(Value::Symbol(String::from("quote"))),
Rc::new(vec![atom])
)
} else {
atom
}
},
Tree::List { vec, quote } => {
let list = Value::List(
vec.into_iter()
.map(|tree| tree.into_expr())
.collect::<List>(),
Rc::new(vec[0].clone().into_expr()),
Rc::new(vec[1..].iter().map(|a| a.clone().into_expr()).collect())
);
if quote {
Value::List(List {
value: Some(Rc::new(RefCell::new(Cons {
car: Value::Symbol(String::from("quote")),
cdr: Some(Rc::new(RefCell::new(Cons {
car: list, // car vroom vroom 🚗
cdr: None,
}))),
}))),
})
Value::List(
Rc::new(Value::Symbol(String::from("quote"))),
Rc::new(vec![list])
)
} else {
list
}
@ -86,30 +55,6 @@ impl Tree {
}
}
impl FromIterator<Value> for List {
fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
let mut list = List { value: None };
let mut tail: Option<Rc<RefCell<Cons>>> = None;
for value in iter {
let new_cons = Rc::new(RefCell::new(Cons {
car: value,
cdr: None,
}));
if list.value.is_none() {
list.value = Some(new_cons.clone());
} else if let Some(ref tail_cons) = tail {
tail_cons.as_ref().borrow_mut().cdr = Some(new_cons.clone());
}
tail = Some(new_cons);
}
list
}
}
// --- Start tokenizer ---
const SPECIAL_CHARS: [&str; 4] = ["(", ")", "'", "..."];
@ -205,16 +150,29 @@ pub fn tokenize(src: &str) -> impl Iterator<Item = (&str, (usize, usize))> {
#[derive(Debug)]
pub enum ParseErrorKind {
UnexpectedParenOpen,
UnexpectedParenClose,
}
impl fmt::Display for ParseErrorKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ParseErrorKind::UnexpectedParenClose => write!(f, "Unexpected ')'"),
}
}
}
#[derive(Debug)]
pub struct ParseError {
pub kind: ParseErrorKind,
pub pos: (usize, usize),
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} at {}", self.kind, self.pos.0)
}
}
impl ParseError {
fn new(kind: ParseErrorKind, pos: (usize, usize)) -> Self {
ParseError { kind, pos }
@ -266,7 +224,7 @@ fn read<'a>(
if let Tree::List { vec, quote } = &finished {
if vec.is_empty() {
finished = Tree::Atom {
atom: Value::NIL,
atom: Value::Nil,
quote: *quote,
};
}
@ -305,7 +263,7 @@ fn read_atom(token: &str) -> Value {
match lower.as_str() {
"true" => Value::True,
"false" => Value::False,
"nil" => Value::NIL,
"nil" => Value::Nil,
_ => {
// Parse number
if let Ok(int) = token.parse::<i64>() { Value::Int(int) }