diff --git a/src/context.rs b/src/context.rs index 57abc0f..f798ea4 100644 --- a/src/context.rs +++ b/src/context.rs @@ -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()?; diff --git a/src/parser.rs b/src/parser.rs index b16c934..3cf1258 100644 --- a/src/parser.rs +++ b/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, - pub body: Spanned, -} +// #[derive(Clone, Debug, PartialEq)] +// pub struct WhenClause { +// pub cond: Spanned, +// pub body: Spanned, +// } -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, - pub guard: Option>, - pub body: Spanned, -} +// #[derive(Clone, Debug, PartialEq)] +// pub struct MatchClause { +// pub patt: Spanned, +// pub guard: Option>, +// pub body: Spanned, +// } -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>), List(Vec>), Dict(Vec>), - Let(Box>, Box>), - Box(&'static str, Box>), + Let(Box>, Box>), + LBox(&'static str, Box>), Synthetic(Box>, Box>, Vec>), - When(Vec>), - Match(Box>, Vec), - Fn(&'static str, Vec, Option<&'static str>), + When(Vec>), + WhenClause(Box>, Box>), + Match(Box>, Vec>), + MatchClause( + Box>, + Box>>, + Box>, + ), + Fn(&'static str, Vec>, Option<&'static str>), FnDeclaration(&'static str), Panic(Box>), Do(Vec>), Repeat(Box>, Box>), Splat(&'static str), Pair(&'static str, Box>), - Loop(Box>, Vec), + Loop(Box>, Vec>), Recur(Vec>), + + // pattern nodes + NilPattern, + BooleanPattern(bool), + NumberPattern(f64), + StringPattern(&'static str), + InterpolatedPattern(Vec>, StringMatcher), + KeywordPattern(&'static str), + WordPattern(&'static str), + AsPattern(&'static str, &'static str), + Splattern(Box>), + PlaceholderPattern, + TuplePattern(Vec>), + ListPattern(Vec>), + PairPattern(&'static str, Box>), + DictPattern(Vec>), } 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::>() .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::>() .join(", ") ), - Ast::List(l) => write!( + List(l) => write!( f, "List: [{}]", l.iter() @@ -137,7 +164,7 @@ impl fmt::Display for Ast { .collect::>() .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::>() .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::>() .join("\n") ), - Ast::When(clauses) => write!( + When(clauses) => write!( f, "When: [{}]", clauses @@ -164,35 +191,35 @@ impl fmt::Display for Ast { .collect::>() .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::>() .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::>() .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::>() .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::>() + .join(", ") + ), + ListPattern(l) => write!( + f, + "({})", + l.iter() + .map(|x| x.0.to_string()) + .collect::>() + .join(", ") + ), + DictPattern(entries) => write!( + f, + "#{{{}}}", + entries + .iter() + .map(|(pair, _)| pair.to_string()) + .collect::>() + .join(", ") + ), + PairPattern(key, value) => write!(f, ":{} {}", key, value.0), + InterpolatedPattern(strprts, _) => write!( + f, + "interpolated: \"{}\"", + strprts + .iter() + .map(|part| part.0.to_string()) + .collect::>() + .join("") + ), } } } -#[derive(Clone, Debug, PartialEq)] -pub struct PairPattern { - pub key: &'static str, - pub patt: Spanned, -} - -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 Option>>); 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>, StringMatcher), - Keyword(&'static str), - Word(&'static str), - As(&'static str, &'static str), - Splattern(Box>), - Placeholder, - Tuple(Vec>), - List(Vec>), - Pair(&'static str, Box>), - Dict(Vec>), -} +// #[derive(Clone, Debug, PartialEq)] +// pub enum Pattern { +// Nil, +// Boolean(bool), +// Number(f64), +// String(&'static str), +// Interpolated(Vec>, StringMatcher), +// Keyword(&'static str), +// Word(&'static str), +// As(&'static str, &'static str), +// Splattern(Box>), +// Placeholder, +// Tuple(Vec>), +// List(Vec>), +// Pair(&'static str, Box>), +// Dict(Vec>), +// } -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::>() - .join(", ") - ), - Pattern::List(l) => write!( - f, - "({})", - l.iter() - .map(|x| x.0.to_string()) - .collect::>() - .join(", ") - ), - Pattern::Dict(entries) => write!( - f, - "#{{{}}}", - entries - .iter() - .map(|(pair, _)| pair.to_string()) - .collect::>() - .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::>() - .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::>() +// .join(", ") +// ), +// Pattern::List(l) => write!( +// f, +// "({})", +// l.iter() +// .map(|x| x.0.to_string()) +// .collect::>() +// .join(", ") +// ), +// Pattern::Dict(entries) => write!( +// f, +// "#{{{}}}", +// entries +// .iter() +// .map(|(pair, _)| pair.to_string()) +// .collect::>() +// .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::>() +// .join("") +// ), +// } +// } +// } fn is_word_char(c: char) -> bool { if c.is_ascii_alphanumeric() { @@ -476,6 +546,8 @@ pub fn parser( 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 } diff --git a/src/validator.rs b/src/validator.rs index f73a5e4..bd279db 100644 --- a/src/validator.rs +++ b/src/validator.rs @@ -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 {