Moved things around, removed unused stuff

main
ondra05 2022-07-24 21:49:02 +02:00
parent 2934ac5e90
commit 880291d2cf
10 changed files with 124 additions and 279 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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,
}
}
}

View File

@ -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()),
]))),
])))],
)
}
}

View File

@ -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
View 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
View File

@ -0,0 +1,3 @@
pub mod ast;
pub mod lexer;
pub mod parser;

61
src/syntax/parser.rs Normal file
View 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);
}
}

View File

@ -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}")
}