feat: handle punning in a non-ambiguous way
This commit is contained in:
parent
391849bf37
commit
9ebc836b89
|
@ -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))
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue