1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-10-16 02:37:40 -05:00

refactor: simplify list

This commit is contained in:
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}; use std::{process::exit, fs::read_to_string};
pub mod parser; pub mod parser;
pub mod compile;
const EXECUTABLE_NAME: &str = env!("CARGO_PKG_NAME"); const EXECUTABLE_NAME: &str = env!("CARGO_PKG_NAME");
const HELP_MESSAGE: &str = "\ const HELP_MESSAGE: &str = "\
@ -35,10 +36,19 @@ fn main() {
if args_index < args.len() { if args_index < args.len() {
let file_path: &str = &args[args_index]; let file_path: &str = &args[args_index];
let file_content: String = read_to_string(file_path).unwrap(); let file_content: String = read_to_string(file_path).unwrap();
let ast = parser::parse(&file_content);
for node in ast { let parsed = parser::parse(&file_content);
println!("{:?}", node); 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 { } else {
println!("No file provided."); println!("No file provided.");
display_help(1); display_help(1);

View file

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