M fml/src/parser.rs +25 -19
@@ 512,7 512,7 @@ impl<'input> Parser<'input> {
self.expect(T::RParen);
lhs
}
- // Tuple literal
+ // Tuple or struct literal
T::LBrace => self.parse_constructor(),
// Nominal type literal
// $Foo(3)
@@ 624,9 624,25 @@ impl<'input> Parser<'input> {
ast::ExprNode::new(ast::Expr::Lambda { signature, body })
}
- /// tuple constructor = "{" [expr {"," expr} [","] "}"
+ /// If we see `.foo = bar` in our thing then it's a struct
fn parse_constructor(&mut self) -> ast::ExprNode {
self.expect(T::LBrace);
+ if self.peek_is(T::Period.discr()) {
+ self.parse_struct_literal()
+ } else {
+ self.parse_tuple_literal()
+ }
+ }
+
+ /// struct constructor = "{" "." ident "=" expr {"," ...} "}"
+ fn parse_struct_literal(&mut self) -> ast::ExprNode {
+ let body = self.parse_struct_lit_fields();
+ self.expect(T::RBrace);
+ ast::ExprNode::new(ast::Expr::StructCtor { body })
+ }
+
+ /// tuple constructor = "{" [expr {"," expr} [","] "}"
+ fn parse_tuple_literal(&mut self) -> ast::ExprNode {
let mut body = vec![];
while let Some(expr) = self.parse_expr(0) {
body.push(expr);
@@ 640,27 656,17 @@ impl<'input> Parser<'input> {
ast::ExprNode::new(ast::Expr::TupleCtor { body })
}
- /// struct literal = "struct" "{" ... "}"
- fn parse_struct_literal(&mut self) -> ast::ExprNode {
- self.expect(T::Struct);
- self.expect(T::LBrace);
- let body = self.parse_struct_lit_fields();
- self.expect(T::RBrace);
- ast::ExprNode::new(ast::Expr::StructCtor { body })
- }
-
fn parse_struct_lit_fields(&mut self) -> HashMap<String, ast::ExprNode> {
let mut fields = HashMap::new();
loop {
- match self.lex.peek() {
- Some((T::Ident(_i), _span)) => {
- let name = self.expect_ident();
- self.expect(T::Equals);
- let vl = self.parse_expr(0).unwrap();
- fields.insert(name, vl);
- }
- _ => break,
+ if self.peek_expect(T::Period.discr()) {
+ let name = self.expect_ident();
+ self.expect(T::Equals);
+ let vl = self.parse_expr(0).unwrap();
+ fields.insert(name, vl);
+ } else {
+ break;
}
if self.peek_expect(T::Comma.discr()) {
M fml/tests/test_struct1.gt +4 -4
@@ 10,10 10,10 @@ end
fn main(): I32 =
- let f1: Foo = id($Foo struct {
- a = 3,
- b = false
+ let f1: Foo = id($Foo {
+ .a = 3,
+ .b = false
})
- let f2: struct a: I32, b: Bool end = id(struct { a = 3, b = false })
+ let f2: struct a: I32, b: Bool end = id({ .a = 3, .b = false })
3
end
M fml/tests/test_struct2.gt +6 -6
@@ 5,17 5,17 @@ type Foo = struct
end
fn thing(i: I32): Foo =
- $Foo struct {
- a = i,
- b = false,
+ $Foo {
+ .a = i,
+ .b = false,
}
end
fn main(): I32 =
- let f1: Foo = $Foo struct {
- a = 3,
- b = false
+ let f1: Foo = $Foo {
+ .a = 3,
+ .b = false
}
let f2: Foo = thing(4)
3
M fml/tests/test_struct3.gt +5 -5
@@ 5,16 5,16 @@ type Foo = struct
end
fn thing(i: I32): Foo =
- $Foo struct {
- a = i,
- b = false,
+ $Foo {
+ .a = i,
+ .b = false,
}
end
fn main(): I32 =
- let f1: Foo = $Foo struct {
- a = 3,
+ let f1: Foo = $Foo {
+ .a = 3,
}
let f2: Foo = thing(4)
3
M fml/tests/test_struct4.gt +3 -3
@@ 10,9 10,9 @@ end
fn main(): I32 =
- let f1: Foo(I32) = id($Foo(I32) struct {
- a = 3,
- b = false
+ let f1: Foo(I32) = id($Foo(I32) {
+ .a = 3,
+ .b = false
})
--let f2: struct a: I32, b: Bool end = id(struct { a = 3, b = false })
3