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> {
|
||||
if op > side {
|
||||
break_("{", "{ ")
|
||||
break_("(", "( ")
|
||||
.append(doc)
|
||||
.nest(INDENT)
|
||||
.append(break_("", " "))
|
||||
.append("}")
|
||||
.append(")")
|
||||
.group()
|
||||
} else {
|
||||
doc
|
||||
|
|
|
@ -30,25 +30,39 @@ pub fn module(
|
|||
|
||||
let mut extra = ModuleExtra::new();
|
||||
|
||||
let tokens = tokens.into_iter().filter(|(token, span)| match token {
|
||||
Token::ModuleComment => {
|
||||
extra.module_comments.push(*span);
|
||||
false
|
||||
}
|
||||
Token::DocComment => {
|
||||
extra.doc_comments.push(*span);
|
||||
false
|
||||
}
|
||||
Token::Comment => {
|
||||
extra.comments.push(*span);
|
||||
false
|
||||
}
|
||||
Token::EmptyLine => {
|
||||
extra.empty_lines.push(span.start);
|
||||
false
|
||||
}
|
||||
Token::NewLine => false,
|
||||
_ => true,
|
||||
let mut previous_is_newline = false;
|
||||
|
||||
let tokens = tokens.into_iter().filter_map(|(token, ref span)| {
|
||||
let current_is_newline = token == Token::NewLine;
|
||||
let result = match token {
|
||||
Token::ModuleComment => {
|
||||
extra.module_comments.push(*span);
|
||||
None
|
||||
}
|
||||
Token::DocComment => {
|
||||
extra.doc_comments.push(*span);
|
||||
None
|
||||
}
|
||||
Token::Comment => {
|
||||
extra.comments.push(*span);
|
||||
None
|
||||
}
|
||||
Token::EmptyLine => {
|
||||
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))?;
|
||||
|
@ -942,9 +956,15 @@ pub fn expr_parser(
|
|||
tail,
|
||||
});
|
||||
|
||||
let block_parser = seq_r
|
||||
.clone()
|
||||
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace));
|
||||
let block_parser = choice((
|
||||
seq_r
|
||||
.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)
|
||||
.ignore_then(
|
||||
|
|
|
@ -10,12 +10,13 @@ pub enum Token {
|
|||
Int { value: String },
|
||||
String { value: String },
|
||||
// Groupings
|
||||
LeftParen, // (
|
||||
RightParen, // )
|
||||
LeftSquare, // [
|
||||
RightSquare, // }
|
||||
LeftBrace, // {
|
||||
RightBrace, // }
|
||||
NewLineLeftParen, // ↳(
|
||||
LeftParen, // (
|
||||
RightParen, // )
|
||||
LeftSquare, // [
|
||||
RightSquare, // }
|
||||
LeftBrace, // {
|
||||
RightBrace, // }
|
||||
// Int Operators
|
||||
Plus,
|
||||
Minus,
|
||||
|
@ -95,6 +96,7 @@ impl fmt::Display for Token {
|
|||
Token::DiscardName { name } => name,
|
||||
Token::Int { value } => value,
|
||||
Token::String { value } => value,
|
||||
Token::NewLineLeftParen => "↳(",
|
||||
Token::LeftParen => "(",
|
||||
Token::RightParen => ")",
|
||||
Token::LeftSquare => "[",
|
||||
|
|
|
@ -231,3 +231,28 @@ fn test_negate() {
|
|||
|
||||
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,
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
assert_eq!(
|
||||
|
@ -17,7 +17,7 @@ fn assert_definition(code: &str, definition: ast::UntypedDefinition) {
|
|||
kind: ast::ModuleKind::Validator,
|
||||
name: "".to_string(),
|
||||
type_info: (),
|
||||
definitions: vec![definition]
|
||||
definitions,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -28,15 +28,15 @@ fn import() {
|
|||
use std/list
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Use(Use {
|
||||
vec![ast::UntypedDefinition::Use(Use {
|
||||
location: Span::new((), 0..12),
|
||||
module: vec!["std".to_string(), "list".to_string()],
|
||||
as_name: None,
|
||||
unqualified: vec![],
|
||||
package: (),
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -46,9 +46,9 @@ fn unqualified_imports() {
|
|||
use std/address.{Address as A, thing as w}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Use(Use {
|
||||
vec![ast::UntypedDefinition::Use(Use {
|
||||
location: Span::new((), 0..42),
|
||||
module: vec!["std".to_string(), "address".to_string()],
|
||||
as_name: None,
|
||||
|
@ -67,7 +67,7 @@ fn unqualified_imports() {
|
|||
},
|
||||
],
|
||||
package: (),
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -77,15 +77,15 @@ fn import_alias() {
|
|||
use std/tx as t
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Use(Use {
|
||||
vec![ast::UntypedDefinition::Use(Use {
|
||||
location: Span::new((), 0..15),
|
||||
module: vec!["std".to_string(), "tx".to_string()],
|
||||
as_name: Some("t".to_string()),
|
||||
unqualified: vec![],
|
||||
package: (),
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -99,9 +99,9 @@ fn custom_type() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::DataType(DataType {
|
||||
vec![ast::UntypedDefinition::DataType(DataType {
|
||||
constructors: vec![
|
||||
ast::RecordConstructor {
|
||||
location: Span::new((), 19..31),
|
||||
|
@ -180,7 +180,7 @@ fn custom_type() {
|
|||
parameters: vec!["a".to_string()],
|
||||
public: false,
|
||||
typed_parameters: vec![],
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -192,9 +192,9 @@ fn opaque_type() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::DataType(DataType {
|
||||
vec![ast::UntypedDefinition::DataType(DataType {
|
||||
constructors: vec![ast::RecordConstructor {
|
||||
location: Span::new((), 21..35),
|
||||
name: "User".to_string(),
|
||||
|
@ -218,7 +218,7 @@ fn opaque_type() {
|
|||
parameters: vec![],
|
||||
public: true,
|
||||
typed_parameters: vec![],
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -228,9 +228,9 @@ fn type_alias() {
|
|||
type Thing = Option<Int>
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::TypeAlias(TypeAlias {
|
||||
vec![ast::UntypedDefinition::TypeAlias(TypeAlias {
|
||||
alias: "Thing".to_string(),
|
||||
annotation: ast::Annotation::Constructor {
|
||||
location: Span::new((), 13..24),
|
||||
|
@ -248,7 +248,7 @@ fn type_alias() {
|
|||
parameters: vec![],
|
||||
public: false,
|
||||
tipo: (),
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -258,9 +258,9 @@ fn pub_type_alias() {
|
|||
pub type Me = Option<String>
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::TypeAlias(TypeAlias {
|
||||
vec![ast::UntypedDefinition::TypeAlias(TypeAlias {
|
||||
alias: "Me".to_string(),
|
||||
annotation: ast::Annotation::Constructor {
|
||||
location: Span::new((), 14..28),
|
||||
|
@ -278,7 +278,7 @@ fn pub_type_alias() {
|
|||
parameters: vec![],
|
||||
public: true,
|
||||
tipo: (),
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -288,9 +288,9 @@ fn empty_function() {
|
|||
pub fn run() {}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(Function {
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::Todo {
|
||||
kind: ast::TodoKind::EmptyFunction,
|
||||
|
@ -304,7 +304,7 @@ fn empty_function() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 14,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -316,9 +316,9 @@ fn plus_binop() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(Function {
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![ast::Arg {
|
||||
arg_name: ast::ArgName::Named {
|
||||
label: "a".to_string(),
|
||||
|
@ -353,7 +353,7 @@ fn plus_binop() {
|
|||
}),
|
||||
return_type: (),
|
||||
end_position: 35,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -367,9 +367,9 @@ fn pipeline() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(Function {
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![ast::Arg {
|
||||
arg_name: ast::ArgName::Named {
|
||||
name: "a".to_string(),
|
||||
|
@ -416,7 +416,7 @@ fn pipeline() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 63,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -436,9 +436,9 @@ fn if_expression() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(Function {
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::If {
|
||||
location: Span::new((), 13..106),
|
||||
|
@ -513,7 +513,7 @@ fn if_expression() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 107,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -534,9 +534,9 @@ fn let_bindings() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(Function {
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![ast::Arg {
|
||||
arg_name: ast::ArgName::Named {
|
||||
label: "a".to_string(),
|
||||
|
@ -641,7 +641,7 @@ fn let_bindings() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 122,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -659,9 +659,9 @@ fn block() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(Function {
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![ast::Arg {
|
||||
arg_name: ast::ArgName::Named {
|
||||
label: "a".to_string(),
|
||||
|
@ -732,7 +732,7 @@ fn block() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 67,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -753,9 +753,9 @@ fn when() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(Function {
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![ast::Arg {
|
||||
arg_name: ast::ArgName::Named {
|
||||
label: "a".to_string(),
|
||||
|
@ -878,7 +878,7 @@ fn when() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 139,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -892,9 +892,9 @@ fn anonymous_function() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(Function {
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::Sequence {
|
||||
location: Span::new((), 25..83),
|
||||
|
@ -971,7 +971,7 @@ fn anonymous_function() {
|
|||
}),
|
||||
return_type: (),
|
||||
end_position: 84,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -983,9 +983,9 @@ fn field_access() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(Function {
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![ast::Arg {
|
||||
arg_name: ast::ArgName::Named {
|
||||
label: "user".to_string(),
|
||||
|
@ -1016,7 +1016,7 @@ fn field_access() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 34,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1032,9 +1032,9 @@ fn call() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(Function {
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::Sequence {
|
||||
location: Span::new((), 15..108),
|
||||
|
@ -1177,7 +1177,7 @@ fn call() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 109,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1189,9 +1189,9 @@ fn record_update() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(Function {
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![
|
||||
ast::Arg {
|
||||
arg_name: ast::ArgName::Named {
|
||||
|
@ -1268,7 +1268,7 @@ fn record_update() {
|
|||
}),
|
||||
return_type: (),
|
||||
end_position: 89,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1280,9 +1280,9 @@ fn record_create_labeled() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(ast::Function {
|
||||
vec![ast::UntypedDefinition::Fn(ast::Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::Call {
|
||||
arguments: vec![
|
||||
|
@ -1324,7 +1324,7 @@ fn record_create_labeled() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 54,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1336,9 +1336,9 @@ fn record_create_labeled_with_field_access() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(ast::Function {
|
||||
vec![ast::UntypedDefinition::Fn(ast::Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::Call {
|
||||
arguments: vec![
|
||||
|
@ -1384,7 +1384,7 @@ fn record_create_labeled_with_field_access() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 66,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1396,9 +1396,9 @@ fn record_create_unlabeled() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(ast::Function {
|
||||
vec![ast::UntypedDefinition::Fn(ast::Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::Call {
|
||||
arguments: vec![
|
||||
|
@ -1436,7 +1436,7 @@ fn record_create_unlabeled() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 40,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1449,9 +1449,9 @@ fn parse_tuple() {
|
|||
}
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::Fn(Function {
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::Sequence {
|
||||
location: Span::new((), 13..86),
|
||||
|
@ -1539,7 +1539,7 @@ fn parse_tuple() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 87,
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1549,9 +1549,9 @@ fn plain_bytearray_literals() {
|
|||
pub const my_policy_id = #[0, 170, 255]
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::ModuleConstant(ModuleConstant {
|
||||
vec![ast::UntypedDefinition::ModuleConstant(ModuleConstant {
|
||||
doc: None,
|
||||
location: Span::new((), 0..39),
|
||||
public: true,
|
||||
|
@ -1562,7 +1562,7 @@ fn plain_bytearray_literals() {
|
|||
bytes: vec![0, 170, 255],
|
||||
}),
|
||||
tipo: (),
|
||||
}),
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1572,9 +1572,9 @@ fn base16_bytearray_literals() {
|
|||
pub const my_policy_id = #"00aaff"
|
||||
"#};
|
||||
|
||||
assert_definition(
|
||||
assert_definitions(
|
||||
code,
|
||||
ast::UntypedDefinition::ModuleConstant(ModuleConstant {
|
||||
vec![ast::UntypedDefinition::ModuleConstant(ModuleConstant {
|
||||
doc: None,
|
||||
location: Span::new((), 0..34),
|
||||
public: true,
|
||||
|
@ -1585,6 +1585,263 @@ fn base16_bytearray_literals() {
|
|||
bytes: vec![0, 170, 255],
|
||||
}),
|
||||
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