start moving Patterns into Ast
This commit is contained in:
parent
dde9ac4bff
commit
cab1b3f173
|
@ -441,7 +441,7 @@ impl<'src> Context<'src> {
|
|||
self.ast = parent;
|
||||
Ok(Value::Dict(dict))
|
||||
}
|
||||
Ast::Box(name, expr) => {
|
||||
Ast::LBox(name, expr) => {
|
||||
let parent = self.ast;
|
||||
self.ast = &expr.0;
|
||||
let val = self.eval()?;
|
||||
|
|
512
src/parser.rs
512
src/parser.rs
|
@ -4,34 +4,34 @@ use chumsky::{input::ValueInput, prelude::*, recursive::Recursive};
|
|||
use std::fmt;
|
||||
use struct_scalpel::Dissectible;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct WhenClause {
|
||||
pub cond: Spanned<Ast>,
|
||||
pub body: Spanned<Ast>,
|
||||
}
|
||||
// #[derive(Clone, Debug, PartialEq)]
|
||||
// pub struct WhenClause {
|
||||
// pub cond: Spanned<Ast>,
|
||||
// pub body: Spanned<Ast>,
|
||||
// }
|
||||
|
||||
impl fmt::Display for WhenClause {
|
||||
fn fmt(self: &WhenClause, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "cond: {}, body: {}", self.cond.0, self.body.0)
|
||||
}
|
||||
}
|
||||
// impl fmt::Display for WhenClause {
|
||||
// fn fmt(self: &WhenClause, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// write!(f, "cond: {}, body: {}", self.cond.0, self.body.0)
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct MatchClause {
|
||||
pub patt: Spanned<Pattern>,
|
||||
pub guard: Option<Spanned<Ast>>,
|
||||
pub body: Spanned<Ast>,
|
||||
}
|
||||
// #[derive(Clone, Debug, PartialEq)]
|
||||
// pub struct MatchClause {
|
||||
// pub patt: Spanned<Pattern>,
|
||||
// pub guard: Option<Spanned<Ast>>,
|
||||
// pub body: Spanned<Ast>,
|
||||
// }
|
||||
|
||||
impl fmt::Display for MatchClause {
|
||||
fn fmt(self: &MatchClause, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"pattern: {}, guard: {:?} body: {}",
|
||||
self.patt.0, self.guard, self.body.0
|
||||
)
|
||||
}
|
||||
}
|
||||
// impl fmt::Display for MatchClause {
|
||||
// fn fmt(self: &MatchClause, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// write!(
|
||||
// f,
|
||||
// "pattern: {}, guard: {:?} body: {}",
|
||||
// self.patt.0, self.guard, self.body.0
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum StringPart {
|
||||
|
@ -53,7 +53,11 @@ impl fmt::Display for StringPart {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, Dissectible)]
|
||||
pub enum Ast {
|
||||
// a special Error node
|
||||
// may come in handy?
|
||||
Error,
|
||||
|
||||
// expression nodes
|
||||
Placeholder,
|
||||
Nil,
|
||||
Boolean(bool),
|
||||
|
@ -68,29 +72,52 @@ pub enum Ast {
|
|||
Arguments(Vec<Spanned<Self>>),
|
||||
List(Vec<Spanned<Self>>),
|
||||
Dict(Vec<Spanned<Self>>),
|
||||
Let(Box<Spanned<Pattern>>, Box<Spanned<Self>>),
|
||||
Box(&'static str, Box<Spanned<Self>>),
|
||||
Let(Box<Spanned<Self>>, Box<Spanned<Self>>),
|
||||
LBox(&'static str, Box<Spanned<Self>>),
|
||||
Synthetic(Box<Spanned<Self>>, Box<Spanned<Self>>, Vec<Spanned<Self>>),
|
||||
When(Vec<Spanned<WhenClause>>),
|
||||
Match(Box<Spanned<Self>>, Vec<MatchClause>),
|
||||
Fn(&'static str, Vec<MatchClause>, Option<&'static str>),
|
||||
When(Vec<Spanned<Self>>),
|
||||
WhenClause(Box<Spanned<Self>>, Box<Spanned<Self>>),
|
||||
Match(Box<Spanned<Self>>, Vec<Spanned<Self>>),
|
||||
MatchClause(
|
||||
Box<Spanned<Self>>,
|
||||
Box<Option<Spanned<Self>>>,
|
||||
Box<Spanned<Self>>,
|
||||
),
|
||||
Fn(&'static str, Vec<Spanned<Self>>, Option<&'static str>),
|
||||
FnDeclaration(&'static str),
|
||||
Panic(Box<Spanned<Self>>),
|
||||
Do(Vec<Spanned<Self>>),
|
||||
Repeat(Box<Spanned<Self>>, Box<Spanned<Self>>),
|
||||
Splat(&'static str),
|
||||
Pair(&'static str, Box<Spanned<Self>>),
|
||||
Loop(Box<Spanned<Self>>, Vec<MatchClause>),
|
||||
Loop(Box<Spanned<Self>>, Vec<Spanned<Self>>),
|
||||
Recur(Vec<Spanned<Self>>),
|
||||
|
||||
// pattern nodes
|
||||
NilPattern,
|
||||
BooleanPattern(bool),
|
||||
NumberPattern(f64),
|
||||
StringPattern(&'static str),
|
||||
InterpolatedPattern(Vec<Spanned<StringPart>>, StringMatcher),
|
||||
KeywordPattern(&'static str),
|
||||
WordPattern(&'static str),
|
||||
AsPattern(&'static str, &'static str),
|
||||
Splattern(Box<Spanned<Self>>),
|
||||
PlaceholderPattern,
|
||||
TuplePattern(Vec<Spanned<Self>>),
|
||||
ListPattern(Vec<Spanned<Self>>),
|
||||
PairPattern(&'static str, Box<Spanned<Self>>),
|
||||
DictPattern(Vec<Spanned<Self>>),
|
||||
}
|
||||
|
||||
impl fmt::Display for Ast {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use Ast::*;
|
||||
match self {
|
||||
Ast::Error => write!(f, "Error"),
|
||||
Ast::Nil => write!(f, "nil"),
|
||||
Ast::String(s) => write!(f, "String: \"{}\"", s),
|
||||
Ast::Interpolated(strs) => {
|
||||
Error => write!(f, "Error"),
|
||||
Nil => write!(f, "nil"),
|
||||
String(s) => write!(f, "String: \"{}\"", s),
|
||||
Interpolated(strs) => {
|
||||
write!(
|
||||
f,
|
||||
"Interpolated: \"{}\"",
|
||||
|
@ -100,11 +127,11 @@ impl fmt::Display for Ast {
|
|||
.join("")
|
||||
)
|
||||
}
|
||||
Ast::Boolean(b) => write!(f, "Boolean: {}", b),
|
||||
Ast::Number(n) => write!(f, "Number: {}", n),
|
||||
Ast::Keyword(k) => write!(f, "Keyword: :{}", k),
|
||||
Ast::Word(w) => write!(f, "Word: {}", w),
|
||||
Ast::Block(b) => write!(
|
||||
Boolean(b) => write!(f, "Boolean: {}", b),
|
||||
Number(n) => write!(f, "Number: {}", n),
|
||||
Keyword(k) => write!(f, "Keyword: :{}", k),
|
||||
Word(w) => write!(f, "Word: {}", w),
|
||||
Block(b) => write!(
|
||||
f,
|
||||
"Block: <{}>",
|
||||
b.iter()
|
||||
|
@ -112,15 +139,15 @@ impl fmt::Display for Ast {
|
|||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
),
|
||||
Ast::If(cond, then_branch, else_branch) => write!(
|
||||
If(cond, then_branch, else_branch) => write!(
|
||||
f,
|
||||
"If: {} Then: {} Else: {}",
|
||||
cond.0, then_branch.0, else_branch.0
|
||||
),
|
||||
Ast::Let(pattern, expression) => {
|
||||
Let(pattern, expression) => {
|
||||
write!(f, "Let: {} = {}", pattern.0, expression.0)
|
||||
}
|
||||
Ast::Dict(entries) => write!(
|
||||
Dict(entries) => write!(
|
||||
f,
|
||||
"#{{{}}}",
|
||||
entries
|
||||
|
@ -129,7 +156,7 @@ impl fmt::Display for Ast {
|
|||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
Ast::List(l) => write!(
|
||||
List(l) => write!(
|
||||
f,
|
||||
"List: [{}]",
|
||||
l.iter()
|
||||
|
@ -137,7 +164,7 @@ impl fmt::Display for Ast {
|
|||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
),
|
||||
Ast::Tuple(t) | Ast::Arguments(t) => write!(
|
||||
Tuple(t) | Ast::Arguments(t) => write!(
|
||||
f,
|
||||
"Tuple: ({})",
|
||||
t.iter()
|
||||
|
@ -145,7 +172,7 @@ impl fmt::Display for Ast {
|
|||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
),
|
||||
Ast::Synthetic(root, first, rest) => write!(
|
||||
Synthetic(root, first, rest) => write!(
|
||||
f,
|
||||
"Synth: [{}, {}, {}]",
|
||||
root.0,
|
||||
|
@ -155,7 +182,7 @@ impl fmt::Display for Ast {
|
|||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
),
|
||||
Ast::When(clauses) => write!(
|
||||
When(clauses) => write!(
|
||||
f,
|
||||
"When: [{}]",
|
||||
clauses
|
||||
|
@ -164,35 +191,35 @@ impl fmt::Display for Ast {
|
|||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
),
|
||||
Ast::Placeholder => todo!(),
|
||||
Ast::Box(_name, _rhs) => todo!(),
|
||||
Ast::Match(value, clauses) => {
|
||||
Placeholder => todo!(),
|
||||
LBox(_name, _rhs) => todo!(),
|
||||
Match(value, clauses) => {
|
||||
write!(
|
||||
f,
|
||||
"match: {} with {}",
|
||||
&value.0.to_string(),
|
||||
clauses
|
||||
.iter()
|
||||
.map(|clause| clause.to_string())
|
||||
.map(|clause| clause.0.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
)
|
||||
}
|
||||
Ast::Fn(name, clauses, _) => {
|
||||
Fn(name, clauses, _) => {
|
||||
write!(
|
||||
f,
|
||||
"fn: {}\n{}",
|
||||
name,
|
||||
clauses
|
||||
.iter()
|
||||
.map(|clause| clause.to_string())
|
||||
.map(|clause| clause.0.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
)
|
||||
}
|
||||
Ast::FnDeclaration(_name) => todo!(),
|
||||
Ast::Panic(_expr) => todo!(),
|
||||
Ast::Do(terms) => {
|
||||
FnDeclaration(_name) => todo!(),
|
||||
Panic(_expr) => todo!(),
|
||||
Do(terms) => {
|
||||
write!(
|
||||
f,
|
||||
"do: {}",
|
||||
|
@ -203,25 +230,25 @@ impl fmt::Display for Ast {
|
|||
.join(" > ")
|
||||
)
|
||||
}
|
||||
Ast::Repeat(_times, _body) => todo!(),
|
||||
Ast::Splat(word) => {
|
||||
Repeat(_times, _body) => todo!(),
|
||||
Splat(word) => {
|
||||
write!(f, "splat: {}", word)
|
||||
}
|
||||
Ast::Pair(k, v) => {
|
||||
Pair(k, v) => {
|
||||
write!(f, "pair: {} {}", k, v.0)
|
||||
}
|
||||
Ast::Loop(init, body) => {
|
||||
Loop(init, body) => {
|
||||
write!(
|
||||
f,
|
||||
"loop: {} with {}",
|
||||
init.0,
|
||||
body.iter()
|
||||
.map(|clause| clause.to_string())
|
||||
.map(|clause| clause.0.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
)
|
||||
}
|
||||
Ast::Recur(args) => {
|
||||
Recur(args) => {
|
||||
write!(
|
||||
f,
|
||||
"recur: {}",
|
||||
|
@ -231,22 +258,65 @@ impl fmt::Display for Ast {
|
|||
.join(", ")
|
||||
)
|
||||
}
|
||||
MatchClause(pattern, guard, body) => {
|
||||
write!(
|
||||
f,
|
||||
"match clause: {} if {:?} -> {}",
|
||||
pattern.0, guard, body.0
|
||||
)
|
||||
}
|
||||
WhenClause(cond, body) => {
|
||||
write!(f, "when clause: {} -> {}", cond.0, body.0)
|
||||
}
|
||||
|
||||
NilPattern => write!(f, "nil"),
|
||||
BooleanPattern(b) => write!(f, "{}", b),
|
||||
NumberPattern(n) => write!(f, "{}", n),
|
||||
StringPattern(s) => write!(f, "{}", s),
|
||||
KeywordPattern(k) => write!(f, ":{}", k),
|
||||
WordPattern(w) => write!(f, "{}", w),
|
||||
AsPattern(w, t) => write!(f, "{} as {}", w, t),
|
||||
Splattern(p) => write!(f, "...{}", p.0),
|
||||
PlaceholderPattern => write!(f, "_"),
|
||||
TuplePattern(t) => write!(
|
||||
f,
|
||||
"({})",
|
||||
t.iter()
|
||||
.map(|x| x.0.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
ListPattern(l) => write!(
|
||||
f,
|
||||
"({})",
|
||||
l.iter()
|
||||
.map(|x| x.0.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
DictPattern(entries) => write!(
|
||||
f,
|
||||
"#{{{}}}",
|
||||
entries
|
||||
.iter()
|
||||
.map(|(pair, _)| pair.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
PairPattern(key, value) => write!(f, ":{} {}", key, value.0),
|
||||
InterpolatedPattern(strprts, _) => write!(
|
||||
f,
|
||||
"interpolated: \"{}\"",
|
||||
strprts
|
||||
.iter()
|
||||
.map(|part| part.0.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct PairPattern {
|
||||
pub key: &'static str,
|
||||
pub patt: Spanned<Pattern>,
|
||||
}
|
||||
|
||||
impl fmt::Display for PairPattern {
|
||||
fn fmt(self: &PairPattern, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "pair pattern: {}: {}", self.key, self.patt.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StringMatcher(pub Box<dyn Fn(String) -> Option<Vec<(String, String)>>>);
|
||||
|
||||
impl PartialEq for StringMatcher {
|
||||
|
@ -273,74 +343,74 @@ impl fmt::Debug for StringMatcher {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Pattern {
|
||||
Nil,
|
||||
Boolean(bool),
|
||||
Number(f64),
|
||||
String(&'static str),
|
||||
Interpolated(Vec<Spanned<StringPart>>, StringMatcher),
|
||||
Keyword(&'static str),
|
||||
Word(&'static str),
|
||||
As(&'static str, &'static str),
|
||||
Splattern(Box<Spanned<Self>>),
|
||||
Placeholder,
|
||||
Tuple(Vec<Spanned<Self>>),
|
||||
List(Vec<Spanned<Self>>),
|
||||
Pair(&'static str, Box<Spanned<Self>>),
|
||||
Dict(Vec<Spanned<Self>>),
|
||||
}
|
||||
// #[derive(Clone, Debug, PartialEq)]
|
||||
// pub enum Pattern {
|
||||
// Nil,
|
||||
// Boolean(bool),
|
||||
// Number(f64),
|
||||
// String(&'static str),
|
||||
// Interpolated(Vec<Spanned<StringPart>>, StringMatcher),
|
||||
// Keyword(&'static str),
|
||||
// Word(&'static str),
|
||||
// As(&'static str, &'static str),
|
||||
// Splattern(Box<Spanned<Self>>),
|
||||
// Placeholder,
|
||||
// Tuple(Vec<Spanned<Self>>),
|
||||
// List(Vec<Spanned<Self>>),
|
||||
// Pair(&'static str, Box<Spanned<Self>>),
|
||||
// Dict(Vec<Spanned<Self>>),
|
||||
// }
|
||||
|
||||
impl fmt::Display for Pattern {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Pattern::Nil => write!(f, "nil"),
|
||||
Pattern::Boolean(b) => write!(f, "{}", b),
|
||||
Pattern::Number(n) => write!(f, "{}", n),
|
||||
Pattern::String(s) => write!(f, "{}", s),
|
||||
Pattern::Keyword(k) => write!(f, ":{}", k),
|
||||
Pattern::Word(w) => write!(f, "{}", w),
|
||||
Pattern::As(w, t) => write!(f, "{} as {}", w, t),
|
||||
Pattern::Splattern(p) => write!(f, "...{}", p.0),
|
||||
Pattern::Placeholder => write!(f, "_"),
|
||||
Pattern::Tuple(t) => write!(
|
||||
f,
|
||||
"({})",
|
||||
t.iter()
|
||||
.map(|x| x.0.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
Pattern::List(l) => write!(
|
||||
f,
|
||||
"({})",
|
||||
l.iter()
|
||||
.map(|x| x.0.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
Pattern::Dict(entries) => write!(
|
||||
f,
|
||||
"#{{{}}}",
|
||||
entries
|
||||
.iter()
|
||||
.map(|(pair, _)| pair.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
Pattern::Pair(key, value) => write!(f, ":{} {}", key, value.0),
|
||||
Pattern::Interpolated(strprts, _) => write!(
|
||||
f,
|
||||
"interpolated: \"{}\"",
|
||||
strprts
|
||||
.iter()
|
||||
.map(|part| part.0.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
// impl fmt::Display for Pattern {
|
||||
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// match self {
|
||||
// Pattern::Nil => write!(f, "nil"),
|
||||
// Pattern::Boolean(b) => write!(f, "{}", b),
|
||||
// Pattern::Number(n) => write!(f, "{}", n),
|
||||
// Pattern::String(s) => write!(f, "{}", s),
|
||||
// Pattern::Keyword(k) => write!(f, ":{}", k),
|
||||
// Pattern::Word(w) => write!(f, "{}", w),
|
||||
// Pattern::As(w, t) => write!(f, "{} as {}", w, t),
|
||||
// Pattern::Splattern(p) => write!(f, "...{}", p.0),
|
||||
// Pattern::Placeholder => write!(f, "_"),
|
||||
// Pattern::Tuple(t) => write!(
|
||||
// f,
|
||||
// "({})",
|
||||
// t.iter()
|
||||
// .map(|x| x.0.to_string())
|
||||
// .collect::<Vec<_>>()
|
||||
// .join(", ")
|
||||
// ),
|
||||
// Pattern::List(l) => write!(
|
||||
// f,
|
||||
// "({})",
|
||||
// l.iter()
|
||||
// .map(|x| x.0.to_string())
|
||||
// .collect::<Vec<_>>()
|
||||
// .join(", ")
|
||||
// ),
|
||||
// Pattern::Dict(entries) => write!(
|
||||
// f,
|
||||
// "#{{{}}}",
|
||||
// entries
|
||||
// .iter()
|
||||
// .map(|(pair, _)| pair.to_string())
|
||||
// .collect::<Vec<_>>()
|
||||
// .join(", ")
|
||||
// ),
|
||||
// Pattern::Pair(key, value) => write!(f, ":{} {}", key, value.0),
|
||||
// Pattern::Interpolated(strprts, _) => write!(
|
||||
// f,
|
||||
// "interpolated: \"{}\"",
|
||||
// strprts
|
||||
// .iter()
|
||||
// .map(|part| part.0.to_string())
|
||||
// .collect::<Vec<_>>()
|
||||
// .join("")
|
||||
// ),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
fn is_word_char(c: char) -> bool {
|
||||
if c.is_ascii_alphanumeric() {
|
||||
|
@ -476,6 +546,8 @@ pub fn parser<I>(
|
|||
where
|
||||
I: ValueInput<'static, Token = Token, Span = Span>,
|
||||
{
|
||||
use Ast::*;
|
||||
|
||||
let mut expr = Recursive::declare();
|
||||
|
||||
let mut pattern = Recursive::declare();
|
||||
|
@ -497,16 +569,15 @@ where
|
|||
});
|
||||
|
||||
let placeholder_pattern =
|
||||
select! {Token::Punctuation("_") => Pattern::Placeholder}.map_with(|p, e| (p, e.span()));
|
||||
select! {Token::Punctuation("_") => PlaceholderPattern}.map_with(|p, e| (p, e.span()));
|
||||
|
||||
let word_pattern =
|
||||
select! { Token::Word(w) => Pattern::Word(w) }.map_with(|w, e| (w, e.span()));
|
||||
let word_pattern = select! { Token::Word(w) => WordPattern(w) }.map_with(|w, e| (w, e.span()));
|
||||
|
||||
let atom_pattern = select! {
|
||||
Token::Nil => Pattern::Nil,
|
||||
Token::Boolean(b) => Pattern::Boolean(b),
|
||||
Token::Number(n) => Pattern::Number(n),
|
||||
Token::Keyword(k) => Pattern::Keyword(k),
|
||||
Token::Nil => NilPattern,
|
||||
Token::Boolean(b) => BooleanPattern(b),
|
||||
Token::Number(n) => NumberPattern(n),
|
||||
Token::Keyword(k) => KeywordPattern(k),
|
||||
}
|
||||
.map_with(|a, e| (a, e.span()));
|
||||
|
||||
|
@ -514,9 +585,9 @@ where
|
|||
let parsed = parse_string(s, e.span());
|
||||
match parsed {
|
||||
Ok(parts) => match parts[0] {
|
||||
(StringPart::Inline(_), _) => Ok((Pattern::String(s), e.span())),
|
||||
(StringPart::Inline(_), _) => Ok((StringPattern(s), e.span())),
|
||||
_ => Ok((
|
||||
Pattern::Interpolated(parts.clone(), compile_string_pattern(parts)),
|
||||
InterpolatedPattern(parts.clone(), compile_string_pattern(parts)),
|
||||
e.span(),
|
||||
)),
|
||||
},
|
||||
|
@ -526,7 +597,7 @@ where
|
|||
|
||||
let bare_splat = just(Token::Punctuation("...")).map_with(|_, e| {
|
||||
(
|
||||
Pattern::Splattern(Box::new((Pattern::Placeholder, e.span()))),
|
||||
Splattern(Box::new((PlaceholderPattern, e.span()))),
|
||||
e.span(),
|
||||
)
|
||||
});
|
||||
|
@ -535,7 +606,7 @@ where
|
|||
|
||||
let patt_splat = just(Token::Punctuation("..."))
|
||||
.ignore_then(splattable)
|
||||
.map_with(|x, e| (Pattern::Splattern(Box::new(x)), e.span()));
|
||||
.map_with(|x, e| (Splattern(Box::new(x)), e.span()));
|
||||
|
||||
let splattern = patt_splat.or(bare_splat);
|
||||
|
||||
|
@ -547,7 +618,7 @@ where
|
|||
.allow_trailing()
|
||||
.collect()
|
||||
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
|
||||
.map_with(|tuple, e| (Pattern::Tuple(tuple), e.span()))
|
||||
.map_with(|tuple, e| (TuplePattern(tuple), e.span()))
|
||||
.labelled("tuple pattern");
|
||||
|
||||
let list_pattern = pattern
|
||||
|
@ -558,15 +629,15 @@ where
|
|||
.allow_trailing()
|
||||
.collect()
|
||||
.delimited_by(just(Token::Punctuation("[")), just(Token::Punctuation("]")))
|
||||
.map_with(|list, e| (Pattern::List(list), e.span()));
|
||||
.map_with(|list, e| (ListPattern(list), e.span()));
|
||||
|
||||
let pair_pattern = select! {Token::Keyword(k) => k}
|
||||
.then(pattern.clone())
|
||||
.map_with(|(key, patt), e| (Pattern::Pair(key, Box::new(patt)), e.span()));
|
||||
.map_with(|(key, patt), e| (PairPattern(key, Box::new(patt)), e.span()));
|
||||
|
||||
let shorthand_pattern = select! {Token::Word(w) => w}.map_with(|w, e| {
|
||||
(
|
||||
Pattern::Pair(w, Box::new((Pattern::Word(w), e.span()))),
|
||||
PairPattern(w, Box::new((WordPattern(w), e.span()))),
|
||||
e.span(),
|
||||
)
|
||||
});
|
||||
|
@ -582,14 +653,14 @@ where
|
|||
just(Token::Punctuation("#{")),
|
||||
just(Token::Punctuation("}")),
|
||||
)
|
||||
.map_with(|dict, e| (Pattern::Dict(dict), e.span()));
|
||||
.map_with(|dict, e| (DictPattern(dict), e.span()));
|
||||
|
||||
let keyword = select! {Token::Keyword(k) => Ast::Keyword(k),}.map_with(|k, e| (k, e.span()));
|
||||
let keyword = select! {Token::Keyword(k) => Keyword(k),}.map_with(|k, e| (k, e.span()));
|
||||
|
||||
let as_pattern = select! {Token::Word(w) => w}
|
||||
.then_ignore(just(Token::Reserved("as")))
|
||||
.then(select! {Token::Keyword(k) => k})
|
||||
.map_with(|(w, t), e| (Pattern::As(w, t), e.span()));
|
||||
.map_with(|(w, t), e| (AsPattern(w, t), e.span()));
|
||||
|
||||
pattern.define(
|
||||
atom_pattern
|
||||
|
@ -604,16 +675,16 @@ where
|
|||
);
|
||||
|
||||
let placeholder =
|
||||
select! {Token::Punctuation("_") => Ast::Placeholder}.map_with(|p, e| (p, e.span()));
|
||||
select! {Token::Punctuation("_") => Placeholder}.map_with(|p, e| (p, e.span()));
|
||||
|
||||
let word = select! { Token::Word(w) => Ast::Word(w) }
|
||||
let word = select! { Token::Word(w) => Word(w) }
|
||||
.map_with(|w, e| (w, e.span()))
|
||||
.labelled("word");
|
||||
|
||||
let value = select! {
|
||||
Token::Nil => Ast::Nil,
|
||||
Token::Boolean(b) => Ast::Boolean(b),
|
||||
Token::Number(n) => Ast::Number(n),
|
||||
Token::Nil => Nil,
|
||||
Token::Boolean(b) => Boolean(b),
|
||||
Token::Number(n) => Number(n),
|
||||
}
|
||||
.map_with(|v, e| (v, e.span()));
|
||||
|
||||
|
@ -621,8 +692,8 @@ where
|
|||
let parsed = parse_string(s, e.span());
|
||||
match parsed {
|
||||
Ok(parts) => match parts[0] {
|
||||
(StringPart::Inline(_), _) => Ok((Ast::String(s), e.span())),
|
||||
_ => Ok((Ast::Interpolated(parts), e.span())),
|
||||
(StringPart::Inline(_), _) => Ok((String(s), e.span())),
|
||||
_ => Ok((Interpolated(parts), e.span())),
|
||||
},
|
||||
Err(msg) => Err(Rich::custom(e.span(), msg)),
|
||||
}
|
||||
|
@ -635,7 +706,7 @@ where
|
|||
.allow_trailing()
|
||||
.collect()
|
||||
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
|
||||
.map_with(|tuple, e| (Ast::Tuple(tuple), e.span()));
|
||||
.map_with(|tuple, e| (Tuple(tuple), e.span()));
|
||||
|
||||
let args = simple
|
||||
.clone()
|
||||
|
@ -645,7 +716,7 @@ where
|
|||
.allow_trailing()
|
||||
.collect()
|
||||
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
|
||||
.map_with(|args, e| (Ast::Arguments(args), e.span()));
|
||||
.map_with(|args, e| (Arguments(args), e.span()));
|
||||
|
||||
let synth_root = word.or(keyword);
|
||||
|
||||
|
@ -655,21 +726,14 @@ where
|
|||
.then(synth_term.clone())
|
||||
.then(synth_term.clone().repeated().collect())
|
||||
.map_with(|((root, first), rest), e| {
|
||||
(
|
||||
Ast::Synthetic(Box::new(root), Box::new(first), rest),
|
||||
e.span(),
|
||||
)
|
||||
(Synthetic(Box::new(root), Box::new(first), rest), e.span())
|
||||
});
|
||||
|
||||
let splat = just(Token::Punctuation("..."))
|
||||
.ignore_then(word)
|
||||
.map_with(|(w, _), e| {
|
||||
(
|
||||
Ast::Splat(if let Ast::Word(w) = w {
|
||||
w
|
||||
} else {
|
||||
unreachable!()
|
||||
}),
|
||||
Splat(if let Word(w) = w { w } else { unreachable!() }),
|
||||
e.span(),
|
||||
)
|
||||
});
|
||||
|
@ -682,14 +746,14 @@ where
|
|||
.allow_trailing()
|
||||
.collect()
|
||||
.delimited_by(just(Token::Punctuation("[")), just(Token::Punctuation("]")))
|
||||
.map_with(|list, e| (Ast::List(list), e.span()));
|
||||
.map_with(|list, e| (List(list), e.span()));
|
||||
|
||||
let pair = select! {Token::Keyword(k) => k}
|
||||
.then(simple.clone())
|
||||
.map_with(|(key, value), e| (Ast::Pair(key, Box::new(value)), e.span()));
|
||||
.map_with(|(key, value), e| (Pair(key, Box::new(value)), e.span()));
|
||||
|
||||
let shorthand = select! {Token::Word(w) => w}
|
||||
.map_with(|w, e| (Ast::Pair(w, Box::new((Ast::Word(w), e.span()))), e.span()));
|
||||
.map_with(|w, e| (Pair(w, Box::new((Word(w), e.span()))), e.span()));
|
||||
|
||||
let dict = pair
|
||||
.or(shorthand)
|
||||
|
@ -702,15 +766,15 @@ where
|
|||
just(Token::Punctuation("#{")),
|
||||
just(Token::Punctuation("}")),
|
||||
)
|
||||
.map_with(|dict, e| (Ast::Dict(dict), e.span()));
|
||||
.map_with(|dict, e| (Dict(dict), e.span()));
|
||||
|
||||
let recur = just(Token::Reserved("recur"))
|
||||
.ignore_then(tuple.clone())
|
||||
.map_with(|args, e| {
|
||||
let (Ast::Tuple(args), _) = args else {
|
||||
let (Tuple(args), _) = args else {
|
||||
unreachable!()
|
||||
};
|
||||
(Ast::Recur(args), e.span())
|
||||
(Recur(args), e.span())
|
||||
});
|
||||
|
||||
let block = expr
|
||||
|
@ -720,7 +784,7 @@ where
|
|||
.allow_trailing()
|
||||
.collect()
|
||||
.delimited_by(just(Token::Punctuation("{")), just(Token::Punctuation("}")))
|
||||
.map_with(|block, e| (Ast::Block(block), e.span()))
|
||||
.map_with(|block, e| (Block(block), e.span()))
|
||||
.recover_with(via_parser(nested_delimiters(
|
||||
Token::Punctuation("{"),
|
||||
Token::Punctuation("}"),
|
||||
|
@ -728,7 +792,7 @@ where
|
|||
(Token::Punctuation("("), Token::Punctuation(")")),
|
||||
(Token::Punctuation("["), Token::Punctuation("]")),
|
||||
],
|
||||
|span| (Ast::Error, span),
|
||||
|span| (Error, span),
|
||||
)));
|
||||
|
||||
let if_ = just(Token::Reserved("if"))
|
||||
|
@ -741,7 +805,7 @@ where
|
|||
.then(expr.clone())
|
||||
.map_with(|((condition, then_branch), else_branch), e| {
|
||||
(
|
||||
Ast::If(
|
||||
If(
|
||||
Box::new(condition),
|
||||
Box::new(then_branch),
|
||||
Box::new(else_branch),
|
||||
|
@ -754,7 +818,7 @@ where
|
|||
.clone()
|
||||
.then_ignore(just(Token::Punctuation("->")))
|
||||
.then(expr.clone())
|
||||
.map_with(|(cond, body), e| (WhenClause { cond, body }, e.span()));
|
||||
.map_with(|(cond, body), e| (WhenClause(Box::new(cond), Box::new(body)), e.span()));
|
||||
|
||||
let when = just(Token::Reserved("when"))
|
||||
.ignore_then(
|
||||
|
@ -765,7 +829,7 @@ where
|
|||
.collect()
|
||||
.delimited_by(just(Token::Punctuation("{")), just(Token::Punctuation("}"))),
|
||||
)
|
||||
.map_with(|clauses, e| (Ast::When(clauses), e.span()));
|
||||
.map_with(|clauses, e| (When(clauses), e.span()));
|
||||
|
||||
let guarded_clause = pattern
|
||||
.clone()
|
||||
|
@ -773,23 +837,25 @@ where
|
|||
.then(simple.clone())
|
||||
.then_ignore(just(Token::Punctuation("->")))
|
||||
.then(expr.clone())
|
||||
.map_with(|((patt, guard), body), _| MatchClause {
|
||||
patt,
|
||||
guard: Some(guard),
|
||||
body,
|
||||
.map_with(|((patt, guard), body), e| {
|
||||
(
|
||||
MatchClause(Box::new(patt), Box::new(Some(guard)), Box::new(body)),
|
||||
e.span(),
|
||||
)
|
||||
});
|
||||
|
||||
let match_clause = pattern
|
||||
.clone()
|
||||
.then_ignore(just(Token::Punctuation("->")))
|
||||
.then(expr.clone())
|
||||
.map_with(|(patt, body), _| MatchClause {
|
||||
patt,
|
||||
guard: None,
|
||||
body,
|
||||
.map_with(|(patt, body), e| {
|
||||
(
|
||||
MatchClause(Box::new(patt), Box::new(None), Box::new(body)),
|
||||
e.span(),
|
||||
)
|
||||
});
|
||||
|
||||
let match_ = just(Token::Reserved("match"))
|
||||
let r#match = just(Token::Reserved("match"))
|
||||
.ignore_then(simple.clone())
|
||||
.then_ignore(just(Token::Reserved("with")))
|
||||
.then(
|
||||
|
@ -802,13 +868,13 @@ where
|
|||
.collect()
|
||||
.delimited_by(just(Token::Punctuation("{")), just(Token::Punctuation("}"))),
|
||||
)
|
||||
.map_with(|(expr, clauses), e| (Ast::Match(Box::new(expr), clauses), e.span()));
|
||||
.map_with(|(expr, clauses), e| (Match(Box::new(expr), clauses), e.span()));
|
||||
|
||||
let conditional = when.or(if_).or(match_);
|
||||
let conditional = when.or(if_).or(r#match);
|
||||
|
||||
let panic = just(Token::Reserved("panic!"))
|
||||
.ignore_then(nonbinding.clone())
|
||||
.map_with(|expr, e| (Ast::Panic(Box::new(expr)), e.span()));
|
||||
.map_with(|expr, e| (Panic(Box::new(expr)), e.span()));
|
||||
|
||||
let do_ = just(Token::Reserved("do"))
|
||||
.ignore_then(
|
||||
|
@ -819,12 +885,12 @@ where
|
|||
)
|
||||
.collect(),
|
||||
)
|
||||
.map_with(|exprs, e| (Ast::Do(exprs), e.span()));
|
||||
.map_with(|exprs, e| (Do(exprs), e.span()));
|
||||
|
||||
let repeat = just(Token::Reserved("repeat"))
|
||||
.ignore_then(simple.clone())
|
||||
.then(block.clone())
|
||||
.map_with(|(count, body), e| (Ast::Repeat(Box::new(count), Box::new(body)), e.span()));
|
||||
.map_with(|(count, body), e| (Repeat(Box::new(count), Box::new(body)), e.span()));
|
||||
|
||||
let fn_guarded = tuple_pattern
|
||||
.clone()
|
||||
|
@ -832,10 +898,11 @@ where
|
|||
.then(simple.clone())
|
||||
.then_ignore(just(Token::Punctuation("->")))
|
||||
.then(nonbinding.clone())
|
||||
.map_with(|((patt, guard), body), _| MatchClause {
|
||||
patt,
|
||||
body,
|
||||
guard: Some(guard),
|
||||
.map_with(|((patt, guard), body), e| {
|
||||
(
|
||||
MatchClause(Box::new(patt), Box::new(Some(guard)), Box::new(body)),
|
||||
e.span(),
|
||||
)
|
||||
})
|
||||
.labelled("function clause");
|
||||
|
||||
|
@ -843,10 +910,11 @@ where
|
|||
.clone()
|
||||
.then_ignore(just(Token::Punctuation("->")))
|
||||
.then(nonbinding.clone())
|
||||
.map_with(|(patt, body), _| MatchClause {
|
||||
patt,
|
||||
body,
|
||||
guard: None,
|
||||
.map_with(|(patt, body), e| {
|
||||
(
|
||||
MatchClause(Box::new(patt), Box::new(None), Box::new(body)),
|
||||
e.span(),
|
||||
)
|
||||
})
|
||||
.labelled("function clause");
|
||||
|
||||
|
@ -854,7 +922,7 @@ where
|
|||
|
||||
let lambda = just(Token::Reserved("fn"))
|
||||
.ignore_then(fn_unguarded.clone())
|
||||
.map_with(|clause, e| (Ast::Fn("anonymous", vec![clause], None), e.span()));
|
||||
.map_with(|clause, e| (Fn("anonymous", vec![clause], None), e.span()));
|
||||
|
||||
let fn_clauses = fn_clause
|
||||
.clone()
|
||||
|
@ -873,7 +941,7 @@ where
|
|||
.ignore_then(tuple.clone())
|
||||
.then_ignore(just(Token::Reserved("with")))
|
||||
.then(loop_multiclause.clone().or(fn_single_clause.clone()))
|
||||
.map_with(|(init, body), e| (Ast::Loop(Box::new(init), body), e.span()));
|
||||
.map_with(|(init, body), e| (Loop(Box::new(init), body), e.span()));
|
||||
|
||||
simple.define(
|
||||
synthetic
|
||||
|
@ -906,7 +974,7 @@ where
|
|||
.then_ignore(just(Token::Punctuation("=")))
|
||||
.then(nonbinding.clone())
|
||||
.map_with(|(pattern, expression), e| {
|
||||
(Ast::Let(Box::new(pattern), Box::new(expression)), e.span())
|
||||
(Let(Box::new(pattern), Box::new(expression)), e.span())
|
||||
});
|
||||
|
||||
let box_ = just(Token::Reserved("box"))
|
||||
|
@ -914,35 +982,35 @@ where
|
|||
.then_ignore(just(Token::Punctuation("=")))
|
||||
.then(nonbinding.clone())
|
||||
.map_with(|(word, expr), e| {
|
||||
let name = if let Ast::Word(w) = word.0 {
|
||||
let name = if let Word(w) = word.0 {
|
||||
w
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
(Ast::Box(name, Box::new(expr)), e.span())
|
||||
(LBox(name, Box::new(expr)), e.span())
|
||||
});
|
||||
|
||||
let fn_decl = just(Token::Reserved("fn"))
|
||||
.ignore_then(word)
|
||||
.map_with(|(word, _), e| {
|
||||
let name = if let Ast::Word(w) = word {
|
||||
let name = if let Word(w) = word {
|
||||
w
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
(Ast::FnDeclaration(name), e.span())
|
||||
(FnDeclaration(name), e.span())
|
||||
});
|
||||
|
||||
let fn_named = just(Token::Reserved("fn"))
|
||||
.ignore_then(word)
|
||||
.then(fn_unguarded.clone())
|
||||
.map_with(|(word, clause), e| {
|
||||
let name = if let Ast::Word(word) = word.0 {
|
||||
let name = if let Word(word) = word.0 {
|
||||
word
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
(Ast::Fn(name, vec![clause], None), e.span())
|
||||
(Fn(name, vec![clause], None), e.span())
|
||||
});
|
||||
|
||||
let docstr = select! {Token::String(s) => s};
|
||||
|
@ -959,12 +1027,12 @@ where
|
|||
.ignore_then(word)
|
||||
.then(fn_multiclause)
|
||||
.map_with(|(word, (docstr, clauses, _)), e| {
|
||||
let name = if let Ast::Word(word) = word.0 {
|
||||
let name = if let Word(word) = word.0 {
|
||||
word
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
(Ast::Fn(name, clauses, docstr), e.span())
|
||||
(Fn(name, clauses, docstr), e.span())
|
||||
});
|
||||
|
||||
let fn_ = fn_named.or(fn_compound).or(fn_decl);
|
||||
|
@ -978,7 +1046,7 @@ where
|
|||
.allow_trailing()
|
||||
.allow_leading()
|
||||
.collect()
|
||||
.map_with(|exprs, e| (Ast::Block(exprs), e.span()));
|
||||
.map_with(|exprs, e| (Block(exprs), e.span()));
|
||||
|
||||
script
|
||||
}
|
||||
|
|
|
@ -315,7 +315,7 @@ impl<'a> Validator<'a> {
|
|||
|
||||
// binding forms
|
||||
// TODO: set up errors to include original binding
|
||||
Ast::Box(name, boxed) => {
|
||||
Ast::LBox(name, boxed) => {
|
||||
if self.bound(name).is_some() {
|
||||
self.err(format!("box name `{name}` is already bound"));
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue
Block a user