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((
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))
.or_not()
.then(
@ -635,35 +635,29 @@ pub fn expr_parser(
.map_with_span(|name, span| (name, span)),
)
.then(
select! {Token::Name {name} => name}
.then_ignore(just(Token::Colon))
.or_not()
.then(r.clone())
.validate(|(label_opt, value), span, emit| {
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 {
choice((
select! {Token::Name {name} => name}
.then_ignore(just(Token::Colon))
.then(r.clone())
.map_with_span(|(label, value), span| ast::CallArg {
location: span,
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))
.allow_trailing()
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
}),
))
.separated_by(just(Token::Comma))
.allow_trailing()
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
),
select! {Token::Name { name } => name}
.map_with_span(|module, span| (module, span))
@ -918,29 +912,23 @@ pub fn expr_parser(
);
let if_parser = just(Token::If)
.ignore_then(
r.clone()
.then_ignore(just(Token::Then))
.then(block_parser.clone())
.map_with_span(|(condition, body), span| ast::IfBranch {
condition,
body,
location: span,
}),
)
.ignore_then(r.clone().then(block_parser.clone()).map_with_span(
|(condition, body), span| ast::IfBranch {
condition,
body,
location: span,
},
))
.then(
just(Token::Else)
.ignore_then(just(Token::If))
.ignore_then(
r.clone()
.then_ignore(just(Token::Then))
.then(block_parser.clone())
.map_with_span(|(condition, body), span| ast::IfBranch {
condition,
body,
location: span,
}),
)
.ignore_then(r.clone().then(block_parser.clone()).map_with_span(
|(condition, body), span| ast::IfBranch {
condition,
body,
location: span,
},
))
.repeated(),
)
.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,
"if" => Token::If,
"else" => Token::Else,
"then" => Token::Then,
"is" => Token::Is,
"let" => Token::Let,
"opaque" => Token::Opaque,

View File

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

View File

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