Support (and default to) parenthesis for block expressions
This changes allow to use parenthesis `(` `)` to encapsulate expressions in addition to braces `{` `}` used to define blocks. The main use-case is for arithmetic and boolean expressions for which developers are used to using parenthesis. For example: ``` { 14 + 42 } * 1337 ``` can now be written as: ``` ( 14 + 42 ) * 1337 ``` This may sound straightforward at first but wasn't necessarily trivial in Aiken given that (a) everything is an expression, (b) whitespaces do not generally matter and (c) there's no symbol indicating the end of a 'statement' (because there's no statement). Thus, we have to properly disambiguate between: ``` let foo = bar(14 + 42) ``` and ``` let foo = bar (14 + 42) ``` Before this commit, the latter would be interpreted as a function call and would lead to a somewhat puzzling error. Now, the newline serves as a delimiting symbol. The trade-off being that for a function call, the left parenthesis has to be on the same line as the function name identifier -- which is a fair trade off. So this is still allowed: ``` let foo = bar( 14 + 42 ) ``` As there's very little ambiguity about it. This fixes #236 and would seemingly allow us to get rid of the leading `#` in front of tuples.
This commit is contained in:
parent
b791131fd0
commit
2d99c07dd3
|
@ -1008,11 +1008,11 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
pub fn operator_side<'a>(&mut self, doc: Document<'a>, op: u8, side: u8) -> Document<'a> {
|
pub fn operator_side<'a>(&mut self, doc: Document<'a>, op: u8, side: u8) -> Document<'a> {
|
||||||
if op > side {
|
if op > side {
|
||||||
break_("{", "{ ")
|
break_("(", "( ")
|
||||||
.append(doc)
|
.append(doc)
|
||||||
.nest(INDENT)
|
.nest(INDENT)
|
||||||
.append(break_("", " "))
|
.append(break_("", " "))
|
||||||
.append("}")
|
.append(")")
|
||||||
.group()
|
.group()
|
||||||
} else {
|
} else {
|
||||||
doc
|
doc
|
||||||
|
|
|
@ -30,25 +30,39 @@ pub fn module(
|
||||||
|
|
||||||
let mut extra = ModuleExtra::new();
|
let mut extra = ModuleExtra::new();
|
||||||
|
|
||||||
let tokens = tokens.into_iter().filter(|(token, span)| match token {
|
let mut previous_is_newline = false;
|
||||||
Token::ModuleComment => {
|
|
||||||
extra.module_comments.push(*span);
|
let tokens = tokens.into_iter().filter_map(|(token, ref span)| {
|
||||||
false
|
let current_is_newline = token == Token::NewLine;
|
||||||
}
|
let result = match token {
|
||||||
Token::DocComment => {
|
Token::ModuleComment => {
|
||||||
extra.doc_comments.push(*span);
|
extra.module_comments.push(*span);
|
||||||
false
|
None
|
||||||
}
|
}
|
||||||
Token::Comment => {
|
Token::DocComment => {
|
||||||
extra.comments.push(*span);
|
extra.doc_comments.push(*span);
|
||||||
false
|
None
|
||||||
}
|
}
|
||||||
Token::EmptyLine => {
|
Token::Comment => {
|
||||||
extra.empty_lines.push(span.start);
|
extra.comments.push(*span);
|
||||||
false
|
None
|
||||||
}
|
}
|
||||||
Token::NewLine => false,
|
Token::EmptyLine => {
|
||||||
_ => true,
|
extra.empty_lines.push(span.start);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Token::NewLine => None,
|
||||||
|
Token::LeftParen => {
|
||||||
|
if previous_is_newline {
|
||||||
|
Some((Token::NewLineLeftParen, *span))
|
||||||
|
} else {
|
||||||
|
Some((Token::LeftParen, *span))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Some((token, *span)),
|
||||||
|
};
|
||||||
|
previous_is_newline = current_is_newline;
|
||||||
|
result
|
||||||
});
|
});
|
||||||
|
|
||||||
let definitions = module_parser().parse(chumsky::Stream::from_iter(span(len), tokens))?;
|
let definitions = module_parser().parse(chumsky::Stream::from_iter(span(len), tokens))?;
|
||||||
|
@ -942,9 +956,15 @@ pub fn expr_parser(
|
||||||
tail,
|
tail,
|
||||||
});
|
});
|
||||||
|
|
||||||
let block_parser = seq_r
|
let block_parser = choice((
|
||||||
.clone()
|
seq_r
|
||||||
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace));
|
.clone()
|
||||||
|
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
|
||||||
|
seq_r.clone().delimited_by(
|
||||||
|
choice((just(Token::LeftParen), just(Token::NewLineLeftParen))),
|
||||||
|
just(Token::RightParen),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
let anon_fn_parser = just(Token::Fn)
|
let anon_fn_parser = just(Token::Fn)
|
||||||
.ignore_then(
|
.ignore_then(
|
||||||
|
|
|
@ -10,12 +10,13 @@ pub enum Token {
|
||||||
Int { value: String },
|
Int { value: String },
|
||||||
String { value: String },
|
String { value: String },
|
||||||
// Groupings
|
// Groupings
|
||||||
LeftParen, // (
|
NewLineLeftParen, // ↳(
|
||||||
RightParen, // )
|
LeftParen, // (
|
||||||
LeftSquare, // [
|
RightParen, // )
|
||||||
RightSquare, // }
|
LeftSquare, // [
|
||||||
LeftBrace, // {
|
RightSquare, // }
|
||||||
RightBrace, // }
|
LeftBrace, // {
|
||||||
|
RightBrace, // }
|
||||||
// Int Operators
|
// Int Operators
|
||||||
Plus,
|
Plus,
|
||||||
Minus,
|
Minus,
|
||||||
|
@ -95,6 +96,7 @@ impl fmt::Display for Token {
|
||||||
Token::DiscardName { name } => name,
|
Token::DiscardName { name } => name,
|
||||||
Token::Int { value } => value,
|
Token::Int { value } => value,
|
||||||
Token::String { value } => value,
|
Token::String { value } => value,
|
||||||
|
Token::NewLineLeftParen => "↳(",
|
||||||
Token::LeftParen => "(",
|
Token::LeftParen => "(",
|
||||||
Token::RightParen => ")",
|
Token::RightParen => ")",
|
||||||
Token::LeftSquare => "[",
|
Token::LeftSquare => "[",
|
||||||
|
|
|
@ -231,3 +231,28 @@ fn test_negate() {
|
||||||
|
|
||||||
assert_fmt(src, expected)
|
assert_fmt(src, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_block_expr() {
|
||||||
|
let src = indoc! {r#"
|
||||||
|
fn foo() {
|
||||||
|
( 14 + 42 ) * 1337
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar() {
|
||||||
|
{ 14 + 42 } * 1337
|
||||||
|
}
|
||||||
|
"#};
|
||||||
|
|
||||||
|
let expected = indoc! {r#"
|
||||||
|
fn foo() {
|
||||||
|
( 14 + 42 ) * 1337
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar() {
|
||||||
|
( 14 + 42 ) * 1337
|
||||||
|
}
|
||||||
|
"#};
|
||||||
|
|
||||||
|
assert_fmt(src, expected);
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
expr, parser,
|
expr, parser,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn assert_definition(code: &str, definition: ast::UntypedDefinition) {
|
fn assert_definitions(code: &str, definitions: Vec<ast::UntypedDefinition>) {
|
||||||
let (module, _extra) = parser::module(code, ast::ModuleKind::Validator).unwrap();
|
let (module, _extra) = parser::module(code, ast::ModuleKind::Validator).unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -17,7 +17,7 @@ fn assert_definition(code: &str, definition: ast::UntypedDefinition) {
|
||||||
kind: ast::ModuleKind::Validator,
|
kind: ast::ModuleKind::Validator,
|
||||||
name: "".to_string(),
|
name: "".to_string(),
|
||||||
type_info: (),
|
type_info: (),
|
||||||
definitions: vec![definition]
|
definitions,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -28,15 +28,15 @@ fn import() {
|
||||||
use std/list
|
use std/list
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Use(Use {
|
vec![ast::UntypedDefinition::Use(Use {
|
||||||
location: Span::new((), 0..12),
|
location: Span::new((), 0..12),
|
||||||
module: vec!["std".to_string(), "list".to_string()],
|
module: vec!["std".to_string(), "list".to_string()],
|
||||||
as_name: None,
|
as_name: None,
|
||||||
unqualified: vec![],
|
unqualified: vec![],
|
||||||
package: (),
|
package: (),
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,9 +46,9 @@ fn unqualified_imports() {
|
||||||
use std/address.{Address as A, thing as w}
|
use std/address.{Address as A, thing as w}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Use(Use {
|
vec![ast::UntypedDefinition::Use(Use {
|
||||||
location: Span::new((), 0..42),
|
location: Span::new((), 0..42),
|
||||||
module: vec!["std".to_string(), "address".to_string()],
|
module: vec!["std".to_string(), "address".to_string()],
|
||||||
as_name: None,
|
as_name: None,
|
||||||
|
@ -67,7 +67,7 @@ fn unqualified_imports() {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
package: (),
|
package: (),
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,15 +77,15 @@ fn import_alias() {
|
||||||
use std/tx as t
|
use std/tx as t
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Use(Use {
|
vec![ast::UntypedDefinition::Use(Use {
|
||||||
location: Span::new((), 0..15),
|
location: Span::new((), 0..15),
|
||||||
module: vec!["std".to_string(), "tx".to_string()],
|
module: vec!["std".to_string(), "tx".to_string()],
|
||||||
as_name: Some("t".to_string()),
|
as_name: Some("t".to_string()),
|
||||||
unqualified: vec![],
|
unqualified: vec![],
|
||||||
package: (),
|
package: (),
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,9 +99,9 @@ fn custom_type() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::DataType(DataType {
|
vec![ast::UntypedDefinition::DataType(DataType {
|
||||||
constructors: vec![
|
constructors: vec![
|
||||||
ast::RecordConstructor {
|
ast::RecordConstructor {
|
||||||
location: Span::new((), 19..31),
|
location: Span::new((), 19..31),
|
||||||
|
@ -180,7 +180,7 @@ fn custom_type() {
|
||||||
parameters: vec!["a".to_string()],
|
parameters: vec!["a".to_string()],
|
||||||
public: false,
|
public: false,
|
||||||
typed_parameters: vec![],
|
typed_parameters: vec![],
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,9 +192,9 @@ fn opaque_type() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::DataType(DataType {
|
vec![ast::UntypedDefinition::DataType(DataType {
|
||||||
constructors: vec![ast::RecordConstructor {
|
constructors: vec![ast::RecordConstructor {
|
||||||
location: Span::new((), 21..35),
|
location: Span::new((), 21..35),
|
||||||
name: "User".to_string(),
|
name: "User".to_string(),
|
||||||
|
@ -218,7 +218,7 @@ fn opaque_type() {
|
||||||
parameters: vec![],
|
parameters: vec![],
|
||||||
public: true,
|
public: true,
|
||||||
typed_parameters: vec![],
|
typed_parameters: vec![],
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,9 +228,9 @@ fn type_alias() {
|
||||||
type Thing = Option<Int>
|
type Thing = Option<Int>
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::TypeAlias(TypeAlias {
|
vec![ast::UntypedDefinition::TypeAlias(TypeAlias {
|
||||||
alias: "Thing".to_string(),
|
alias: "Thing".to_string(),
|
||||||
annotation: ast::Annotation::Constructor {
|
annotation: ast::Annotation::Constructor {
|
||||||
location: Span::new((), 13..24),
|
location: Span::new((), 13..24),
|
||||||
|
@ -248,7 +248,7 @@ fn type_alias() {
|
||||||
parameters: vec![],
|
parameters: vec![],
|
||||||
public: false,
|
public: false,
|
||||||
tipo: (),
|
tipo: (),
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,9 +258,9 @@ fn pub_type_alias() {
|
||||||
pub type Me = Option<String>
|
pub type Me = Option<String>
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::TypeAlias(TypeAlias {
|
vec![ast::UntypedDefinition::TypeAlias(TypeAlias {
|
||||||
alias: "Me".to_string(),
|
alias: "Me".to_string(),
|
||||||
annotation: ast::Annotation::Constructor {
|
annotation: ast::Annotation::Constructor {
|
||||||
location: Span::new((), 14..28),
|
location: Span::new((), 14..28),
|
||||||
|
@ -278,7 +278,7 @@ fn pub_type_alias() {
|
||||||
parameters: vec![],
|
parameters: vec![],
|
||||||
public: true,
|
public: true,
|
||||||
tipo: (),
|
tipo: (),
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,9 +288,9 @@ fn empty_function() {
|
||||||
pub fn run() {}
|
pub fn run() {}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Todo {
|
body: expr::UntypedExpr::Todo {
|
||||||
kind: ast::TodoKind::EmptyFunction,
|
kind: ast::TodoKind::EmptyFunction,
|
||||||
|
@ -304,7 +304,7 @@ fn empty_function() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 14,
|
end_position: 14,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,9 +316,9 @@ fn plus_binop() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
arguments: vec![ast::Arg {
|
arguments: vec![ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
|
@ -353,7 +353,7 @@ fn plus_binop() {
|
||||||
}),
|
}),
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 35,
|
end_position: 35,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,9 +367,9 @@ fn pipeline() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
arguments: vec![ast::Arg {
|
arguments: vec![ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
|
@ -416,7 +416,7 @@ fn pipeline() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 63,
|
end_position: 63,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,9 +436,9 @@ fn if_expression() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::If {
|
body: expr::UntypedExpr::If {
|
||||||
location: Span::new((), 13..106),
|
location: Span::new((), 13..106),
|
||||||
|
@ -513,7 +513,7 @@ fn if_expression() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 107,
|
end_position: 107,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,9 +534,9 @@ fn let_bindings() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
arguments: vec![ast::Arg {
|
arguments: vec![ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
|
@ -641,7 +641,7 @@ fn let_bindings() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 122,
|
end_position: 122,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,9 +659,9 @@ fn block() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
arguments: vec![ast::Arg {
|
arguments: vec![ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
|
@ -732,7 +732,7 @@ fn block() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 67,
|
end_position: 67,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,9 +753,9 @@ fn when() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
arguments: vec![ast::Arg {
|
arguments: vec![ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
|
@ -878,7 +878,7 @@ fn when() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 139,
|
end_position: 139,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,9 +892,9 @@ fn anonymous_function() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 25..83),
|
location: Span::new((), 25..83),
|
||||||
|
@ -971,7 +971,7 @@ fn anonymous_function() {
|
||||||
}),
|
}),
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 84,
|
end_position: 84,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -983,9 +983,9 @@ fn field_access() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
arguments: vec![ast::Arg {
|
arguments: vec![ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
label: "user".to_string(),
|
label: "user".to_string(),
|
||||||
|
@ -1016,7 +1016,7 @@ fn field_access() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 34,
|
end_position: 34,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1032,9 +1032,9 @@ fn call() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 15..108),
|
location: Span::new((), 15..108),
|
||||||
|
@ -1177,7 +1177,7 @@ fn call() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 109,
|
end_position: 109,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1189,9 +1189,9 @@ fn record_update() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
arguments: vec![
|
arguments: vec![
|
||||||
ast::Arg {
|
ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
|
@ -1268,7 +1268,7 @@ fn record_update() {
|
||||||
}),
|
}),
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 89,
|
end_position: 89,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1280,9 +1280,9 @@ fn record_create_labeled() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(ast::Function {
|
vec![ast::UntypedDefinition::Fn(ast::Function {
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Call {
|
body: expr::UntypedExpr::Call {
|
||||||
arguments: vec![
|
arguments: vec![
|
||||||
|
@ -1324,7 +1324,7 @@ fn record_create_labeled() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 54,
|
end_position: 54,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1336,9 +1336,9 @@ fn record_create_labeled_with_field_access() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(ast::Function {
|
vec![ast::UntypedDefinition::Fn(ast::Function {
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Call {
|
body: expr::UntypedExpr::Call {
|
||||||
arguments: vec![
|
arguments: vec![
|
||||||
|
@ -1384,7 +1384,7 @@ fn record_create_labeled_with_field_access() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 66,
|
end_position: 66,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1396,9 +1396,9 @@ fn record_create_unlabeled() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(ast::Function {
|
vec![ast::UntypedDefinition::Fn(ast::Function {
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Call {
|
body: expr::UntypedExpr::Call {
|
||||||
arguments: vec![
|
arguments: vec![
|
||||||
|
@ -1436,7 +1436,7 @@ fn record_create_unlabeled() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 40,
|
end_position: 40,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1449,9 +1449,9 @@ fn parse_tuple() {
|
||||||
}
|
}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 13..86),
|
location: Span::new((), 13..86),
|
||||||
|
@ -1539,7 +1539,7 @@ fn parse_tuple() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
end_position: 87,
|
end_position: 87,
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1549,9 +1549,9 @@ fn plain_bytearray_literals() {
|
||||||
pub const my_policy_id = #[0, 170, 255]
|
pub const my_policy_id = #[0, 170, 255]
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::ModuleConstant(ModuleConstant {
|
vec![ast::UntypedDefinition::ModuleConstant(ModuleConstant {
|
||||||
doc: None,
|
doc: None,
|
||||||
location: Span::new((), 0..39),
|
location: Span::new((), 0..39),
|
||||||
public: true,
|
public: true,
|
||||||
|
@ -1562,7 +1562,7 @@ fn plain_bytearray_literals() {
|
||||||
bytes: vec![0, 170, 255],
|
bytes: vec![0, 170, 255],
|
||||||
}),
|
}),
|
||||||
tipo: (),
|
tipo: (),
|
||||||
}),
|
})],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1572,9 +1572,9 @@ fn base16_bytearray_literals() {
|
||||||
pub const my_policy_id = #"00aaff"
|
pub const my_policy_id = #"00aaff"
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
ast::UntypedDefinition::ModuleConstant(ModuleConstant {
|
vec![ast::UntypedDefinition::ModuleConstant(ModuleConstant {
|
||||||
doc: None,
|
doc: None,
|
||||||
location: Span::new((), 0..34),
|
location: Span::new((), 0..34),
|
||||||
public: true,
|
public: true,
|
||||||
|
@ -1585,6 +1585,263 @@ fn base16_bytearray_literals() {
|
||||||
bytes: vec![0, 170, 255],
|
bytes: vec![0, 170, 255],
|
||||||
}),
|
}),
|
||||||
tipo: (),
|
tipo: (),
|
||||||
}),
|
})],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn function_def() {
|
||||||
|
let code = indoc! {r#"
|
||||||
|
fn foo() {}
|
||||||
|
"#};
|
||||||
|
|
||||||
|
assert_definitions(
|
||||||
|
code,
|
||||||
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
doc: None,
|
||||||
|
arguments: vec![],
|
||||||
|
body: expr::UntypedExpr::Todo {
|
||||||
|
kind: ast::TodoKind::EmptyFunction,
|
||||||
|
location: Span::new((), 0..11),
|
||||||
|
label: None,
|
||||||
|
},
|
||||||
|
location: Span::new((), 0..8),
|
||||||
|
name: "foo".to_string(),
|
||||||
|
public: false,
|
||||||
|
return_annotation: None,
|
||||||
|
return_type: (),
|
||||||
|
end_position: 10,
|
||||||
|
})],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn function_invoke() {
|
||||||
|
let code = indoc! {r#"
|
||||||
|
fn foo() {
|
||||||
|
let a = bar(42)
|
||||||
|
}
|
||||||
|
"#};
|
||||||
|
|
||||||
|
assert_definitions(
|
||||||
|
code,
|
||||||
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
doc: None,
|
||||||
|
arguments: vec![],
|
||||||
|
body: expr::UntypedExpr::Assignment {
|
||||||
|
location: Span::new((), 13..28),
|
||||||
|
kind: ast::AssignmentKind::Let,
|
||||||
|
annotation: None,
|
||||||
|
pattern: ast::Pattern::Var {
|
||||||
|
location: Span::new((), 17..18),
|
||||||
|
name: "a".to_string(),
|
||||||
|
},
|
||||||
|
value: Box::new(expr::UntypedExpr::Call {
|
||||||
|
location: Span::new((), 24..28),
|
||||||
|
fun: Box::new(expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 21..24),
|
||||||
|
name: "bar".to_string(),
|
||||||
|
}),
|
||||||
|
arguments: vec![ast::CallArg {
|
||||||
|
label: None,
|
||||||
|
location: Span::new((), 25..27),
|
||||||
|
value: expr::UntypedExpr::Int {
|
||||||
|
location: Span::new((), 25..27),
|
||||||
|
value: "42".to_string(),
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
location: Span::new((), 0..8),
|
||||||
|
name: "foo".to_string(),
|
||||||
|
public: false,
|
||||||
|
return_annotation: None,
|
||||||
|
return_type: (),
|
||||||
|
end_position: 29,
|
||||||
|
})],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn function_ambiguous_sequence() {
|
||||||
|
let code = indoc! {r#"
|
||||||
|
fn foo_1() {
|
||||||
|
let a = bar
|
||||||
|
(40)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo_2() {
|
||||||
|
let a = bar
|
||||||
|
{40}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo_3() {
|
||||||
|
let a = (40+2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo_4() {
|
||||||
|
let a = bar(42)
|
||||||
|
(a + 14) * 42
|
||||||
|
}
|
||||||
|
"#};
|
||||||
|
|
||||||
|
assert_definitions(
|
||||||
|
code,
|
||||||
|
vec![
|
||||||
|
ast::UntypedDefinition::Fn(Function {
|
||||||
|
arguments: vec![],
|
||||||
|
body: expr::UntypedExpr::Sequence {
|
||||||
|
location: Span::new((), 15..32),
|
||||||
|
expressions: vec![
|
||||||
|
expr::UntypedExpr::Assignment {
|
||||||
|
location: Span::new((), 15..26),
|
||||||
|
value: Box::new(expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 23..26),
|
||||||
|
name: "bar".to_string(),
|
||||||
|
}),
|
||||||
|
pattern: ast::Pattern::Var {
|
||||||
|
location: Span::new((), 19..20),
|
||||||
|
name: "a".to_string(),
|
||||||
|
},
|
||||||
|
kind: ast::AssignmentKind::Let,
|
||||||
|
annotation: None,
|
||||||
|
},
|
||||||
|
expr::UntypedExpr::Int {
|
||||||
|
location: Span::new((), 30..32),
|
||||||
|
value: "40".to_string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
doc: None,
|
||||||
|
location: Span::new((), 0..10),
|
||||||
|
name: "foo_1".to_string(),
|
||||||
|
public: false,
|
||||||
|
return_annotation: None,
|
||||||
|
return_type: (),
|
||||||
|
end_position: 34,
|
||||||
|
}),
|
||||||
|
ast::UntypedDefinition::Fn(Function {
|
||||||
|
arguments: vec![],
|
||||||
|
body: expr::UntypedExpr::Sequence {
|
||||||
|
location: Span::new((), 52..69),
|
||||||
|
expressions: vec![
|
||||||
|
expr::UntypedExpr::Assignment {
|
||||||
|
location: Span::new((), 52..63),
|
||||||
|
value: Box::new(expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 60..63),
|
||||||
|
name: "bar".to_string(),
|
||||||
|
}),
|
||||||
|
pattern: ast::Pattern::Var {
|
||||||
|
location: Span::new((), 56..57),
|
||||||
|
name: "a".to_string(),
|
||||||
|
},
|
||||||
|
kind: ast::AssignmentKind::Let,
|
||||||
|
annotation: None,
|
||||||
|
},
|
||||||
|
expr::UntypedExpr::Int {
|
||||||
|
location: Span::new((), 67..69),
|
||||||
|
value: "40".to_string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
doc: None,
|
||||||
|
location: Span::new((), 37..47),
|
||||||
|
name: "foo_2".to_string(),
|
||||||
|
public: false,
|
||||||
|
return_annotation: None,
|
||||||
|
return_type: (),
|
||||||
|
end_position: 71,
|
||||||
|
}),
|
||||||
|
ast::UntypedDefinition::Fn(Function {
|
||||||
|
arguments: vec![],
|
||||||
|
body: expr::UntypedExpr::Assignment {
|
||||||
|
location: Span::new((), 89..103),
|
||||||
|
value: Box::new(expr::UntypedExpr::BinOp {
|
||||||
|
location: Span::new((), 98..102),
|
||||||
|
name: ast::BinOp::AddInt,
|
||||||
|
left: Box::new(expr::UntypedExpr::Int {
|
||||||
|
location: Span::new((), 98..100),
|
||||||
|
value: "40".to_string(),
|
||||||
|
}),
|
||||||
|
right: Box::new(expr::UntypedExpr::Int {
|
||||||
|
location: Span::new((), 101..102),
|
||||||
|
value: "2".to_string(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
pattern: ast::Pattern::Var {
|
||||||
|
location: Span::new((), 93..94),
|
||||||
|
name: "a".to_string(),
|
||||||
|
},
|
||||||
|
kind: ast::AssignmentKind::Let,
|
||||||
|
annotation: None,
|
||||||
|
},
|
||||||
|
doc: None,
|
||||||
|
location: Span::new((), 74..84),
|
||||||
|
name: "foo_3".to_string(),
|
||||||
|
public: false,
|
||||||
|
return_annotation: None,
|
||||||
|
return_type: (),
|
||||||
|
end_position: 104,
|
||||||
|
}),
|
||||||
|
ast::UntypedDefinition::Fn(Function {
|
||||||
|
arguments: vec![],
|
||||||
|
body: expr::UntypedExpr::Sequence {
|
||||||
|
location: Span::new((), 122..153),
|
||||||
|
expressions: vec![
|
||||||
|
expr::UntypedExpr::Assignment {
|
||||||
|
location: Span::new((), 122..137),
|
||||||
|
value: Box::new(expr::UntypedExpr::Call {
|
||||||
|
arguments: vec![ast::CallArg {
|
||||||
|
label: None,
|
||||||
|
location: Span::new((), 134..136),
|
||||||
|
value: expr::UntypedExpr::Int {
|
||||||
|
location: Span::new((), 134..136),
|
||||||
|
value: "42".to_string(),
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
fun: Box::new(expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 130..133),
|
||||||
|
name: "bar".to_string(),
|
||||||
|
}),
|
||||||
|
location: Span::new((), 133..137),
|
||||||
|
}),
|
||||||
|
pattern: ast::Pattern::Var {
|
||||||
|
location: Span::new((), 126..127),
|
||||||
|
name: "a".to_string(),
|
||||||
|
},
|
||||||
|
kind: ast::AssignmentKind::Let,
|
||||||
|
annotation: None,
|
||||||
|
},
|
||||||
|
expr::UntypedExpr::BinOp {
|
||||||
|
location: Span::new((), 141..153),
|
||||||
|
name: ast::BinOp::MultInt,
|
||||||
|
left: Box::new(expr::UntypedExpr::BinOp {
|
||||||
|
location: Span::new((), 141..147),
|
||||||
|
name: ast::BinOp::AddInt,
|
||||||
|
left: Box::new(expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 141..142),
|
||||||
|
name: "a".to_string(),
|
||||||
|
}),
|
||||||
|
right: Box::new(expr::UntypedExpr::Int {
|
||||||
|
location: Span::new((), 145..147),
|
||||||
|
value: "14".to_string(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
right: Box::new(expr::UntypedExpr::Int {
|
||||||
|
location: Span::new((), 151..153),
|
||||||
|
value: "42".to_string(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
doc: None,
|
||||||
|
location: Span::new((), 107..117),
|
||||||
|
name: "foo_4".to_string(),
|
||||||
|
public: false,
|
||||||
|
return_annotation: None,
|
||||||
|
return_type: (),
|
||||||
|
end_position: 154,
|
||||||
|
}),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue