Moved things around, removed unused stuff
This commit is contained in:
parent
45bc514a49
commit
bb50f1e450
|
@ -1,4 +1,4 @@
|
|||
use crate::lexer::Token;
|
||||
use crate::syntax::lexer::Token;
|
||||
use ariadne::{Color, Fmt, Label, Report, ReportKind, Source};
|
||||
use chumsky::error::{Simple, SimpleReason};
|
||||
use std::fmt::Display;
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
pub mod error;
|
||||
pub mod lexer;
|
||||
pub mod list;
|
||||
pub mod parser;
|
||||
pub mod repl;
|
||||
pub mod value;
|
||||
pub mod syntax;
|
||||
|
|
76
src/list.rs
76
src/list.rs
|
@ -1,76 +0,0 @@
|
|||
use crate::value::{write_seq, Value};
|
||||
use std::fmt::Display;
|
||||
|
||||
/// Single-linked list
|
||||
#[derive(Debug, Default, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum List<'a> {
|
||||
Cons(Value<'a>, Box<Self>),
|
||||
#[default]
|
||||
Nil,
|
||||
}
|
||||
|
||||
impl<'a> List<'a> {
|
||||
pub fn from_vec(vec: Vec<Value<'a>>) -> Self {
|
||||
vec.into_iter()
|
||||
.rev()
|
||||
.fold(Self::Nil, |list, next| Self::Cons(next, Box::new(list)))
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> Iter<'_, 'a> {
|
||||
Iter(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Display for List<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write_seq(f, self, "(", ")")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l, 'v> IntoIterator for &'l List<'v> {
|
||||
type Item = &'l Value<'v>;
|
||||
type IntoIter = Iter<'l, 'v>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Iter<'l, 'v>(&'l List<'v>);
|
||||
impl<'l, 'v> Iterator for Iter<'l, 'v> {
|
||||
type Item = &'l Value<'v>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.0 {
|
||||
List::Cons(head, rest) => {
|
||||
self.0 = &**rest;
|
||||
Some(head)
|
||||
}
|
||||
List::Nil => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for List<'a> {
|
||||
type Item = Value<'a>;
|
||||
type IntoIter = IntoIter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
IntoIter(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IntoIter<'a>(List<'a>);
|
||||
impl<'a> Iterator for IntoIter<'a> {
|
||||
type Item = Value<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match std::mem::take(&mut self.0) {
|
||||
List::Cons(first, mut rest) => {
|
||||
std::mem::swap(&mut self.0, rest.as_mut());
|
||||
Some(first)
|
||||
}
|
||||
List::Nil => None,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
use crate::{lexer::Token, list::List, value::Value};
|
||||
use chumsky::{prelude::*, Stream};
|
||||
use logos::Logos;
|
||||
|
||||
/// Parse source string into a value
|
||||
pub fn read(src: &str) -> Result<Vec<Value>, Vec<Simple<Token<'_>>>> {
|
||||
let lexer = Token::lexer(src);
|
||||
let len = lexer.source().len();
|
||||
parser().parse(Stream::from_iter(len..len + 1, lexer.spanned()))
|
||||
}
|
||||
|
||||
fn parser<'a>() -> impl Parser<Token<'a>, Vec<Value<'a>>, Error = Simple<Token<'a>>> {
|
||||
recursive(|value| {
|
||||
let atom = select! {
|
||||
Token::Symbol("true") => Value::Bool(true),
|
||||
Token::Symbol("false") => Value::Bool(false),
|
||||
Token::Symbol("nil") => Value::Nil,
|
||||
Token::Symbol(s) => Value::Symbol(s.into()),
|
||||
Token::Keyword(k) => Value::Keyword(k.into()),
|
||||
Token::String(s) => Value::String(s.into()),
|
||||
Token::Number(n) => Value::Number(n),
|
||||
};
|
||||
|
||||
let list = value
|
||||
.clone()
|
||||
.repeated()
|
||||
.map(List::from_vec)
|
||||
.map(Box::new)
|
||||
.map(Value::List)
|
||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen));
|
||||
|
||||
let vector = value
|
||||
.clone()
|
||||
.repeated()
|
||||
.map(Value::Vector)
|
||||
.delimited_by(just(Token::LeftBracket), just(Token::RightBracket));
|
||||
|
||||
let map = value
|
||||
.clone()
|
||||
.then(value.clone())
|
||||
.repeated()
|
||||
.collect()
|
||||
.map(Value::Map)
|
||||
.delimited_by(just(Token::LeftCurly), just(Token::RightCurly));
|
||||
|
||||
let quote = just(Token::Quote).ignore_then(value).map(|value| {
|
||||
Value::List(Box::new(List::Cons(
|
||||
Value::Symbol("quote".into()),
|
||||
Box::new(List::Cons(value, Box::new(List::Nil))),
|
||||
)))
|
||||
});
|
||||
|
||||
atom.or(list).or(vector).or(map).or(quote)
|
||||
})
|
||||
.repeated()
|
||||
.then_ignore(end())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn assert_parse<'a>(src: &'a str, expected: &'a [Value<'a>]) {
|
||||
assert_eq!(read(src).unwrap(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_fn() {
|
||||
assert_parse(
|
||||
"(defn test [] (println \"Hello, world!\"))",
|
||||
&[Value::List(Box::new(List::from_vec(vec![
|
||||
Value::Symbol("defn".into()),
|
||||
Value::Symbol("test".into()),
|
||||
Value::Vector(vec![]),
|
||||
Value::List(Box::new(List::from_vec(vec![
|
||||
Value::Symbol("println".into()),
|
||||
Value::String("Hello, world!".into()),
|
||||
]))),
|
||||
])))],
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
use crate::{error::Error, syntax::parser::read};
|
||||
use rustyline::{error::ReadlineError, Editor};
|
||||
|
||||
use crate::{error::Error, parser::read};
|
||||
|
||||
pub fn repl() -> rustyline::Result<()> {
|
||||
let prompt = "#=> ";
|
||||
let mut rl = Editor::<()>::new()?;
|
||||
|
|
57
src/syntax/ast.rs
Normal file
57
src/syntax/ast.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
use ordered_float::OrderedFloat;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
fmt::{Display, Write},
|
||||
};
|
||||
|
||||
/// A Wisp AST
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Expr<'a> {
|
||||
List(Vec<Self>),
|
||||
Vector(Vec<Self>),
|
||||
Map(Vec<(Self, Self)>),
|
||||
Symbol(Cow<'a, str>),
|
||||
Keyword(Cow<'a, str>),
|
||||
Bool(bool),
|
||||
Number(OrderedFloat<f64>),
|
||||
String(Cow<'a, str>),
|
||||
Nil,
|
||||
}
|
||||
|
||||
impl<'a> Display for Expr<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::List(list) => write_seq(f, list, "(", ")"),
|
||||
Self::Vector(vec) => write_seq(f, vec, "[", "]"),
|
||||
Self::Map(map) => write_seq(
|
||||
f,
|
||||
map.into_iter().map(|(k, v)| format!("{k} {v}")),
|
||||
"[",
|
||||
"]",
|
||||
),
|
||||
Self::Symbol(sym) => write!(f, "{sym}"),
|
||||
Self::Keyword(kw) => write!(f, ":{kw}"),
|
||||
Self::Bool(b) => write!(f, "{b}"),
|
||||
Self::Number(n) => write!(f, "{n}"),
|
||||
Self::String(s) => write!(f, "\"{s}\""),
|
||||
Self::Nil => write!(f, "nil"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn write_seq(
|
||||
f: &mut impl Write,
|
||||
iterable: impl IntoIterator<Item = impl Display>,
|
||||
delimiter_left: &str,
|
||||
delimiter_right: &str,
|
||||
) -> std::fmt::Result {
|
||||
let mut iter = iterable.into_iter();
|
||||
write!(f, "{delimiter_left}")?;
|
||||
if let Some(x) = iter.next() {
|
||||
write!(f, "{x}")?;
|
||||
}
|
||||
for x in iter {
|
||||
write!(f, " {x}")?;
|
||||
}
|
||||
write!(f, "{delimiter_right}")
|
||||
}
|
3
src/syntax/mod.rs
Normal file
3
src/syntax/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub mod ast;
|
||||
pub mod lexer;
|
||||
pub mod parser;
|
61
src/syntax/parser.rs
Normal file
61
src/syntax/parser.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use super::{ast::Expr, lexer::Token};
|
||||
use chumsky::{prelude::*, Stream};
|
||||
use logos::Logos;
|
||||
|
||||
/// Parse source string into a Expr
|
||||
pub fn read(src: &str) -> Result<Vec<Expr>, Vec<Simple<Token<'_>>>> {
|
||||
let lexer = Token::lexer(src);
|
||||
let len = lexer.source().len();
|
||||
parser().parse(Stream::from_iter(len..len + 1, lexer.spanned()))
|
||||
}
|
||||
|
||||
fn parser<'a>() -> impl Parser<Token<'a>, Vec<Expr<'a>>, Error = Simple<Token<'a>>> {
|
||||
recursive(|expr| {
|
||||
let atom = select! {
|
||||
Token::Symbol("true") => Expr::Bool(true),
|
||||
Token::Symbol("false") => Expr::Bool(false),
|
||||
Token::Symbol("nil") => Expr::Nil,
|
||||
Token::Symbol(s) => Expr::Symbol(s.into()),
|
||||
Token::Keyword(k) => Expr::Keyword(k.into()),
|
||||
Token::String(s) => Expr::String(s.into()),
|
||||
Token::Number(n) => Expr::Number(n),
|
||||
};
|
||||
|
||||
let list = expr
|
||||
.clone()
|
||||
.repeated()
|
||||
.map(Expr::List)
|
||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen));
|
||||
|
||||
let vector = expr
|
||||
.clone()
|
||||
.repeated()
|
||||
.map(Expr::Vector)
|
||||
.delimited_by(just(Token::LeftBracket), just(Token::RightBracket));
|
||||
|
||||
let map = expr
|
||||
.clone()
|
||||
.then(expr.clone())
|
||||
.repeated()
|
||||
.collect()
|
||||
.map(Expr::Map)
|
||||
.delimited_by(just(Token::LeftCurly), just(Token::RightCurly));
|
||||
|
||||
let quote = just(Token::Quote)
|
||||
.ignore_then(expr)
|
||||
.map(|expr| Expr::List(vec![Expr::Symbol("quote".into()), expr]));
|
||||
|
||||
atom.or(list).or(vector).or(map).or(quote)
|
||||
})
|
||||
.repeated()
|
||||
.then_ignore(end())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn assert_parse<'a>(src: &'a str, expected: &'a [Expr<'a>]) {
|
||||
assert_eq!(read(src).unwrap(), expected);
|
||||
}
|
||||
}
|
114
src/value.rs
114
src/value.rs
|
@ -1,114 +0,0 @@
|
|||
use crate::list::List;
|
||||
use ordered_float::OrderedFloat;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::BTreeMap,
|
||||
fmt::{Debug, Display, Write},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
/// A Wisp value
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Value<'a> {
|
||||
List(Box<List<'a>>),
|
||||
Vector(Vec<Self>),
|
||||
Map(BTreeMap<Self, Self>),
|
||||
Module(Module<'a>),
|
||||
Function(Function<'a>),
|
||||
InternalFn(fn(&'a List<'a>) -> Value<'a>),
|
||||
Macro(/* TODO: Bytecode */),
|
||||
Symbol(Symbol<'a>),
|
||||
Keyword(Cow<'a, str>),
|
||||
Bool(bool),
|
||||
Number(OrderedFloat<f64>),
|
||||
String(Cow<'a, str>),
|
||||
Nil,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Module<'a> {
|
||||
members: BTreeMap<u64, Rc<Value<'a>>>,
|
||||
symbol_table: BTreeMap<String, u64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Function<'a> {
|
||||
// TODO: bytecode
|
||||
captures: Box<[Capture<'a>]>,
|
||||
symbol_table: BTreeMap<Symbol<'a>, SymbolMapping>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Capture<'a> {
|
||||
Reference(Rc<Value<'a>>),
|
||||
Owned(Value<'a>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum SymbolMapping {
|
||||
Local(u64),
|
||||
Capture(u64),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Symbol<'a> {
|
||||
Interned(u64),
|
||||
String(Cow<'a, str>),
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Symbol<'a> {
|
||||
fn from(s: &'a str) -> Self {
|
||||
Self::String(Cow::Borrowed(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Display for Symbol<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Symbol::Interned(n) => write!(f, "#{n}"),
|
||||
Symbol::String(s) => write!(f, "{s}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Display for Value<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Value::List(list) => write!(f, "{list}"),
|
||||
Value::Vector(vec) => write_seq(f, vec, "[", "]"),
|
||||
Value::Map(map) => write_seq(
|
||||
f,
|
||||
map.into_iter().map(|(k, v)| format!("{k} {v}")),
|
||||
"[",
|
||||
"]",
|
||||
),
|
||||
Value::Module(_) => write!(f, "#module#"),
|
||||
Value::Symbol(sym) => write!(f, "{sym}"),
|
||||
Value::Keyword(kw) => write!(f, ":{kw}"),
|
||||
Value::Function { .. } => write!(f, "#fn#"),
|
||||
Value::InternalFn(function) => write!(f, "#internal-fn@{function:p}"),
|
||||
Value::Macro() => write!(f, "#macro#"),
|
||||
Value::Bool(b) => write!(f, "{b}"),
|
||||
Value::Number(n) => write!(f, "{n}"),
|
||||
Value::String(s) => write!(f, "\"{s}\""),
|
||||
Value::Nil => write!(f, "nil"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn write_seq(
|
||||
f: &mut impl Write,
|
||||
iterable: impl IntoIterator<Item = impl Display>,
|
||||
delimiter_left: &str,
|
||||
delimiter_right: &str,
|
||||
) -> std::fmt::Result {
|
||||
let mut iter = iterable.into_iter();
|
||||
write!(f, "{delimiter_left}")?;
|
||||
if let Some(x) = iter.next() {
|
||||
write!(f, "{x}")?;
|
||||
}
|
||||
for x in iter {
|
||||
write!(f, " {x}")?;
|
||||
}
|
||||
write!(f, "{delimiter_right}")
|
||||
}
|
Loading…
Reference in a new issue