feat: handle punning in a non-ambiguous way

This commit is contained in:
rvcas 2022-12-04 18:49:21 -05:00 committed by Lucas
parent 391849bf37
commit 9ebc836b89
5 changed files with 56 additions and 71 deletions

View File

@ -627,7 +627,7 @@ pub fn expr_parser(
let record_parser = choice(( let record_parser = choice((
select! {Token::Name { name } => name} select! {Token::Name { name } => name}
.map_with_span(|module, span| (module, span)) .map_with_span(|module, span: Span| (module, span))
.then_ignore(just(Token::Dot)) .then_ignore(just(Token::Dot))
.or_not() .or_not()
.then( .then(
@ -635,32 +635,26 @@ pub fn expr_parser(
.map_with_span(|name, span| (name, span)), .map_with_span(|name, span| (name, span)),
) )
.then( .then(
choice((
select! {Token::Name {name} => name} select! {Token::Name {name} => name}
.then_ignore(just(Token::Colon)) .then_ignore(just(Token::Colon))
.or_not()
.then(r.clone()) .then(r.clone())
.validate(|(label_opt, value), span, emit| { .map_with_span(|(label, value), span| ast::CallArg {
dbg!(&label_opt);
let label = if label_opt.is_some() {
label_opt
} else if let expr::UntypedExpr::Var { name, .. } = &value {
Some(name.clone())
} else {
emit(ParseError::expected_input_found(
value.location(),
None,
Some(error::Pattern::RecordPunning),
));
None
};
ast::CallArg {
location: span, location: span,
value, value,
label, label: Some(label),
}),
select! {Token::Name {name} => name}.map_with_span(|name, span| {
ast::CallArg {
location: span,
value: expr::UntypedExpr::Var {
name: name.clone(),
location: span,
},
label: Some(name),
} }
}) }),
))
.separated_by(just(Token::Comma)) .separated_by(just(Token::Comma))
.allow_trailing() .allow_trailing()
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)), .delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
@ -918,29 +912,23 @@ pub fn expr_parser(
); );
let if_parser = just(Token::If) let if_parser = just(Token::If)
.ignore_then( .ignore_then(r.clone().then(block_parser.clone()).map_with_span(
r.clone() |(condition, body), span| ast::IfBranch {
.then_ignore(just(Token::Then))
.then(block_parser.clone())
.map_with_span(|(condition, body), span| ast::IfBranch {
condition, condition,
body, body,
location: span, location: span,
}), },
) ))
.then( .then(
just(Token::Else) just(Token::Else)
.ignore_then(just(Token::If)) .ignore_then(just(Token::If))
.ignore_then( .ignore_then(r.clone().then(block_parser.clone()).map_with_span(
r.clone() |(condition, body), span| ast::IfBranch {
.then_ignore(just(Token::Then))
.then(block_parser.clone())
.map_with_span(|(condition, body), span| ast::IfBranch {
condition, condition,
body, body,
location: span, location: span,
}), },
) ))
.repeated(), .repeated(),
) )
.then_ignore(just(Token::Else)) .then_ignore(just(Token::Else))

View File

@ -69,7 +69,6 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = ParseError> {
"fn" => Token::Fn, "fn" => Token::Fn,
"if" => Token::If, "if" => Token::If,
"else" => Token::Else, "else" => Token::Else,
"then" => Token::Then,
"is" => Token::Is, "is" => Token::Is,
"let" => Token::Let, "let" => Token::Let,
"opaque" => Token::Opaque, "opaque" => Token::Opaque,

View File

@ -72,7 +72,6 @@ pub enum Token {
Trace, Trace,
Type, Type,
When, When,
Then,
} }
impl fmt::Display for Token { impl fmt::Display for Token {
@ -146,7 +145,6 @@ impl fmt::Display for Token {
Token::Todo => "todo", Token::Todo => "todo",
Token::Trace => "try", Token::Trace => "try",
Token::Type => "type", Token::Type => "type",
Token::Then => "then",
}; };
write!(f, "\"{}\"", s) write!(f, "\"{}\"", s)
} }

View File

@ -423,11 +423,11 @@ fn pipeline() {
fn if_expression() { fn if_expression() {
let code = indoc! {r#" let code = indoc! {r#"
fn ifs() { fn ifs() {
if True then { if True {
1 + 1 1 + 1
} else if a < 4 then { } else if a < 4 {
5 5
} else if a || b then { } else if a || b {
6 6
} else { } else {
3 3
@ -440,7 +440,7 @@ fn if_expression() {
ast::UntypedDefinition::Fn(Function { ast::UntypedDefinition::Fn(Function {
arguments: vec![], arguments: vec![],
body: expr::UntypedExpr::If { body: expr::UntypedExpr::If {
location: Span::new((), 13..121), location: Span::new((), 13..106),
branches: vec1::vec1![ branches: vec1::vec1![
ast::IfBranch { ast::IfBranch {
condition: expr::UntypedExpr::Var { condition: expr::UntypedExpr::Var {
@ -448,60 +448,60 @@ fn if_expression() {
name: "True".to_string(), name: "True".to_string(),
}, },
body: expr::UntypedExpr::BinOp { body: expr::UntypedExpr::BinOp {
location: Span::new((), 32..37), location: Span::new((), 27..32),
name: ast::BinOp::AddInt, name: ast::BinOp::AddInt,
left: Box::new(expr::UntypedExpr::Int { left: Box::new(expr::UntypedExpr::Int {
location: Span::new((), 32..33), location: Span::new((), 27..28),
value: "1".to_string(), value: "1".to_string(),
}), }),
right: Box::new(expr::UntypedExpr::Int { right: Box::new(expr::UntypedExpr::Int {
location: Span::new((), 36..37), location: Span::new((), 31..32),
value: "1".to_string(), value: "1".to_string(),
}), }),
}, },
location: Span::new((), 16..41), location: Span::new((), 16..36),
}, },
ast::IfBranch { ast::IfBranch {
condition: expr::UntypedExpr::BinOp { condition: expr::UntypedExpr::BinOp {
location: Span::new((), 50..55), location: Span::new((), 45..50),
name: ast::BinOp::LtInt, name: ast::BinOp::LtInt,
left: Box::new(expr::UntypedExpr::Var { left: Box::new(expr::UntypedExpr::Var {
location: Span::new((), 50..51), location: Span::new((), 45..46),
name: "a".to_string(), name: "a".to_string(),
}), }),
right: Box::new(expr::UntypedExpr::Int { right: Box::new(expr::UntypedExpr::Int {
location: Span::new((), 54..55), location: Span::new((), 49..50),
value: "4".to_string(), value: "4".to_string(),
}), }),
}, },
body: expr::UntypedExpr::Int { body: expr::UntypedExpr::Int {
location: Span::new((), 67..68), location: Span::new((), 57..58),
value: "5".to_string(), value: "5".to_string(),
}, },
location: Span::new((), 50..72), location: Span::new((), 45..62),
}, },
ast::IfBranch { ast::IfBranch {
condition: expr::UntypedExpr::BinOp { condition: expr::UntypedExpr::BinOp {
location: Span::new((), 81..87), location: Span::new((), 71..77),
name: ast::BinOp::Or, name: ast::BinOp::Or,
left: Box::new(expr::UntypedExpr::Var { left: Box::new(expr::UntypedExpr::Var {
location: Span::new((), 81..82), location: Span::new((), 71..72),
name: "a".to_string(), name: "a".to_string(),
}), }),
right: Box::new(expr::UntypedExpr::Var { right: Box::new(expr::UntypedExpr::Var {
location: Span::new((), 86..87), location: Span::new((), 76..77),
name: "b".to_string(), name: "b".to_string(),
}), }),
}, },
body: expr::UntypedExpr::Int { body: expr::UntypedExpr::Int {
location: Span::new((), 99..100), location: Span::new((), 84..85),
value: "6".to_string(), value: "6".to_string(),
}, },
location: Span::new((), 81..104), location: Span::new((), 71..89),
}, },
], ],
final_else: Box::new(expr::UntypedExpr::Int { final_else: Box::new(expr::UntypedExpr::Int {
location: Span::new((), 116..117), location: Span::new((), 101..102),
value: "3".to_string(), value: "3".to_string(),
}), }),
}, },
@ -511,7 +511,7 @@ fn if_expression() {
public: false, public: false,
return_annotation: None, return_annotation: None,
return_type: (), return_type: (),
end_position: 122, end_position: 107,
}), }),
) )
} }

View File

@ -32,7 +32,7 @@ pub fn final_check(z: Int) {
} }
pub fn incrementor(counter: Int, target: Int) -> Int { pub fn incrementor(counter: Int, target: Int) -> Int {
if counter == target then { if counter == target {
target target
} else { } else {
incrementor(counter + 1, target) incrementor(counter + 1, target)