diff --git a/compiler/hash-ast-utils/src/pretty/mod.rs b/compiler/hash-ast-utils/src/pretty/mod.rs index 4f6c8cea1..d5dc3854b 100644 --- a/compiler/hash-ast-utils/src/pretty/mod.rs +++ b/compiler/hash-ast-utils/src/pretty/mod.rs @@ -154,7 +154,7 @@ where &mut self, node: ast::AstNodeRef, ) -> Result { - let ast::Declaration { pat, ty, value } = node.body(); + let ast::Declaration { pat, ty, value, is_constant } = node.body(); self.visit_pat(pat.ast_ref())?; @@ -168,7 +168,12 @@ where } // Visit the initialiser - self.write("= ")?; + if *is_constant { + self.write(": ")?; + } else { + self.write("= ")?; + } + self.visit_expr(value.ast_ref()) } @@ -1140,13 +1145,9 @@ where &mut self, node: ast::AstNodeRef, ) -> Result { - let ast::AccessExpr { subject, property, kind } = node.body(); + let ast::AccessExpr { subject, property } = node.body(); self.visit_expr(subject.ast_ref())?; - - match kind { - ast::AccessKind::Namespace => self.write("::")?, - ast::AccessKind::Property => self.write(".")?, - } + self.write(".")?; self.visit_property_kind(property.ast_ref()) } @@ -1432,7 +1433,6 @@ where Ty, Pat, Visibility, - AccessKind, Mutability, RefKind, UnOp, diff --git a/compiler/hash-ast-utils/src/tree.rs b/compiler/hash-ast-utils/src/tree.rs index c45a0eb96..84d248e57 100644 --- a/compiler/hash-ast-utils/src/tree.rs +++ b/compiler/hash-ast-utils/src/tree.rs @@ -184,22 +184,10 @@ impl AstVisitor for AstTreePrinter { vec![ TreeNode::branch("subject", vec![subject]), TreeNode::branch("property", vec![property]), - TreeNode::leaf(labelled("kind", node.kind, "\"")), ], )) } - type AccessKindRet = TreeNode; - fn visit_access_kind( - &self, - node: ast::AstNodeRef, - ) -> Result { - match node.body() { - ast::AccessKind::Property => Ok(TreeNode::leaf("property")), - ast::AccessKind::Namespace => Ok(TreeNode::leaf("namespace")), - } - } - type RefExprRet = TreeNode; fn visit_ref_expr( &self, diff --git a/compiler/hash-ast/src/ast.rs b/compiler/hash-ast/src/ast.rs index 7c20d92e2..f8e265c69 100644 --- a/compiler/hash-ast/src/ast.rs +++ b/compiler/hash-ast/src/ast.rs @@ -1150,7 +1150,7 @@ define_tree! { pub enum Pat { /// An access pattern is one that denotes the access of a property from /// another pattern. This is used to denote namespace accesses like - /// `a::b::c` + /// `a.b.c` Access(AccessPat), /// A simple binding pattern, assign some value to the name of the pattern @@ -1269,6 +1269,9 @@ define_tree! { /// Any value that is assigned to the binding, simply /// an expression. pub value: Child!(Expr), + + /// Whether the declaration is constant or not. + pub is_constant: bool, } /// Unary operators that are defined within the core of the language. @@ -1974,25 +1977,6 @@ define_tree! { pub args: Children!(ExprArg), } - /// A the kind of access an [AccessExpr] has - #[derive(Debug, PartialEq, Eq, Clone, Copy)] - #[node] - pub enum AccessKind { - /// A namespace access, i.e. `a::b` - Namespace, - /// A property access, i.e. `a.b` - Property, - } - - impl Display for AccessKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - AccessKind::Namespace => write!(f, "namespace"), - AccessKind::Property => write!(f, "property"), - } - } - } - /// The kind of property that's being accessed, either being /// named or numeric, e.g `foo.x`, `foo.1`, etc. #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -2013,8 +1997,6 @@ define_tree! { pub subject: Child!(Expr), /// The property of the subject to access. pub property: Child!(PropertyKind), - /// The kind of access, either namespacing or property - pub kind: AccessKind, } /// A typed expression, e.g. `foo as int`. diff --git a/compiler/hash-parser/src/parser/expr.rs b/compiler/hash-parser/src/parser/expr.rs index 7bbadd71e..e31247575 100644 --- a/compiler/hash-parser/src/parser/expr.rs +++ b/compiler/hash-parser/src/parser/expr.rs @@ -58,10 +58,7 @@ impl<'s> AstGen<'s> { // pattern which is then followed by a `:` to denote that this is a // declaration. if self.begins_pat() { - let pat = self.parse_singular_pat()?; - self.parse_token(TokenKind::Colon)?; - let decl = self.parse_declaration(pat)?; - + let decl = self.parse_declaration()?; let expr = self.node_with_joined_span(Expr::Declaration(decl), start); let semi = maybe_eat_semi(self); return Ok(Some((semi, expr))); @@ -365,7 +362,6 @@ impl<'s> AstGen<'s> { subject = match token.kind { // Property access or method call TokenKind::Dot => self.parse_property_access(subject, subject_span)?, - TokenKind::Access => self.parse_ns_access(subject, subject_span)?, TokenKind::Lt => match self.maybe_parse_implicit_call(subject, subject_span) { (subject, true) => subject, // Essentially break because the type_args failed @@ -581,19 +577,53 @@ impl<'s> AstGen<'s> { /// ```text /// some_var: f64 = ...; /// ^^^^^^^^ ^^^ ^^^─────┐ - /// pattern type the right hand-side expr + /// pattern annotation the right hand-side expr /// ``` - pub(crate) fn parse_declaration(&mut self, pat: AstNode) -> ParseResult { - // Attempt to parse an optional type... + pub(crate) fn parse_declaration(&mut self) -> ParseResult { + let pat = self.parse_singular_pat()?; + let mut is_constant = false; + + // Figure out if this declaration has an annotation or not... let ty = match self.peek_kind() { - Some(TokenKind::Eq) => None, - _ => Some(self.parse_ty()?), + Some(TokenKind::Access) => { + self.skip_fast(TokenKind::Access); // `::` + is_constant = true; + None + } + _ => { + self.parse_token(TokenKind::Colon)?; // `:` + + if self.peek_kind() == Some(TokenKind::Eq) { + self.skip_fast(TokenKind::Eq); // `=` + None + } else { + Some(self.parse_ty()?) + } + } }; // Now parse the initialiser... - self.parse_token(TokenKind::Eq)?; + if !is_constant && ty.is_some() { + match self.peek_kind() { + Some(TokenKind::Eq) => { + self.skip_fast(TokenKind::Eq); // `=` + } + Some(TokenKind::Colon) => { + self.skip_fast(TokenKind::Colon); // `=` + is_constant = true; + } + tok => { + return self.err( + ParseErrorKind::UnExpected, + ExpectedItem::Colon | ExpectedItem::Eq, + tok, + ) + } + } + } + let value = self.parse_expr_with_precedence(0)?; - Ok(Declaration { pat, ty, value }) + Ok(Declaration { pat, ty, value, is_constant }) } /// Given a initial left-hand side expression, attempt to parse a @@ -636,8 +666,7 @@ impl<'s> AstGen<'s> { } } - /// Parse a property access expression, in other words an [AccessExpr] with - /// the [AccessKind::Property] variant. + /// Parse a property access expression, in other words an [AccessExpr]. pub(crate) fn parse_property_access( &mut self, subject: AstNode, @@ -675,32 +704,14 @@ impl<'s> AstGen<'s> { let property = self.node_with_span(PropertyKind::NumericField(value), token.span); return Ok(self.node_with_joined_span( - Expr::Access(AccessExpr { subject, property, kind: AccessKind::Property }), + Expr::Access(AccessExpr { subject, property }), subject_span, )); } } let property = self.parse_named_field(ParseErrorKind::ExpectedPropertyAccess)?; - Ok(self.node_with_joined_span( - Expr::Access(AccessExpr { subject, property, kind: AccessKind::Property }), - subject_span, - )) - } - - /// Parse a [AccessExpr] with a `namespace` access kind. - pub(crate) fn parse_ns_access( - &mut self, - subject: AstNode, - subject_span: ByteRange, - ) -> ParseResult> { - self.skip_fast(TokenKind::Access); // `::` - - let property = self.parse_named_field(ParseErrorKind::ExpectedName)?; - Ok(self.node_with_joined_span( - Expr::Access(AccessExpr { subject, property, kind: AccessKind::Namespace }), - subject_span, - )) + Ok(self.node_with_joined_span(Expr::Access(AccessExpr { subject, property }), subject_span)) } /// Function to either parse an expression that is wrapped in parentheses or diff --git a/compiler/hash-parser/src/parser/pat.rs b/compiler/hash-parser/src/parser/pat.rs index f9e49885f..d6d623e2d 100644 --- a/compiler/hash-parser/src/parser/pat.rs +++ b/compiler/hash-parser/src/parser/pat.rs @@ -112,8 +112,8 @@ impl<'s> AstGen<'s> { } // An access pattern which accesses the `subject` with a particular `property` // denotes with a name. - TokenKind::Access => { - self.skip_fast(TokenKind::Access); // `::` + TokenKind::Dot => { + self.skip_fast(TokenKind::Dot); // `.` let property = self.parse_name()?; self.node_with_joined_span(Pat::Access(AccessPat { subject, property }), span) } @@ -554,9 +554,11 @@ impl<'s> AstGen<'s> { } fn peek_pat(&self) -> bool { - macro_rules! peek_colon( + // This is a macro that is used to simplify the lookahead for the pattern + // boundary, which can either be a `:` or a `::` token. + macro_rules! peek_pat_boundary( () => { - matches!(self.peek_kind(), Some(TokenKind::Colon)) + matches!(self.peek_kind(), Some(TokenKind::Colon | TokenKind::Access)) } ); @@ -575,7 +577,7 @@ impl<'s> AstGen<'s> { && kind.is_range_lit() { self.skip_fast(kind); - peek_colon!() + peek_pat_boundary!() } else { false } @@ -587,12 +589,12 @@ impl<'s> AstGen<'s> { // Other general literal patterns. Some(kind) if kind.is_lit() => { self.skip_fast(kind); - peek_colon!() + peek_pat_boundary!() } // Module, Array, Tuple patterns. Some(TokenKind::Tree(_, _)) => { self.skip_token(); - peek_colon!() + peek_pat_boundary!() } // Identifier or constructor pattern. Some(ident @ TokenKind::Ident(_)) => { @@ -606,8 +608,8 @@ impl<'s> AstGen<'s> { TokenKind::Tree(Delimiter::Paren, _) => self.skip_token(), // Handle the `access` pattern case. We're looking for the next // three tokens to be `::Ident` - TokenKind::Access => { - self.skip_fast(TokenKind::Access); + TokenKind::Dot => { + self.skip_fast(TokenKind::Dot); // `.` match self.peek_kind() { Some(ident @ TokenKind::Ident(_)) => { @@ -620,7 +622,7 @@ impl<'s> AstGen<'s> { } } - peek_colon!() + peek_pat_boundary!() } // This is the case for a bind that has a visibility modifier at the beginning. In // this scenario, it can be followed by a `mut` modifier and then a identifier or diff --git a/compiler/hash-parser/src/parser/ty.rs b/compiler/hash-parser/src/parser/ty.rs index b8cf65991..6b738988d 100644 --- a/compiler/hash-parser/src/parser/ty.rs +++ b/compiler/hash-parser/src/parser/ty.rs @@ -219,8 +219,8 @@ impl<'s> AstGen<'s> { Ty::Fn(FnTy { params: self.make_params(params, ParamOrigin::Fn), return_ty }) } - TokenKind::Access => { - self.skip_fast(TokenKind::Access); + TokenKind::Dot => { + self.skip_fast(TokenKind::Dot); // . Ty::Access(AccessTy { subject: self.node_with_joined_span(ty, span), diff --git a/compiler/hash-semantics/src/passes/resolution/exprs.rs b/compiler/hash-semantics/src/passes/resolution/exprs.rs index da216fc2a..e63447f5e 100644 --- a/compiler/hash-semantics/src/passes/resolution/exprs.rs +++ b/compiler/hash-semantics/src/passes/resolution/exprs.rs @@ -246,27 +246,24 @@ impl ResolutionPass<'_, E> { &self, node: AstNodeRef<'a, ast::AccessExpr>, ) -> SemanticResult>> { - match node.kind { - ast::AccessKind::Namespace => match node.property.body() { - ast::PropertyKind::NamedField(name) => { - let mut root = - self.expr_as_ast_path(node.body.subject.ast_ref())?.ok_or_else(|| { - SemanticError::InvalidNamespaceSubject { location: node.span() } - })?; - root.push(AstPathComponent { - name: *name, - name_node_id: node.property.id(), - args: Node::at(vec![], NodeOrigin::Given(node.id())), - node_id: node.id(), - }); - Ok(Some(root)) - } - ast::PropertyKind::NumericField(_) => { - // Should have been caught at semantics - panic_on_span!(node.span(), "Namespace followed by numeric field found") - } - }, - ast::AccessKind::Property => Ok(None), + match node.property.body() { + ast::PropertyKind::NamedField(name) => { + let mut root = + self.expr_as_ast_path(node.body.subject.ast_ref())?.ok_or_else(|| { + SemanticError::InvalidNamespaceSubject { location: node.span() } + })?; + root.push(AstPathComponent { + name: *name, + name_node_id: node.property.id(), + args: Node::at(vec![], NodeOrigin::Given(node.id())), + node_id: node.id(), + }); + Ok(Some(root)) + } + ast::PropertyKind::NumericField(_) => { + // Should have been caught at semantics + panic_on_span!(node.span(), "Namespace followed by numeric field found") + } } } @@ -422,9 +419,6 @@ impl ResolutionPass<'_, E> { self.make_term_from_resolved_ast_path(&resolved_path, node.id()) } None => { - // Namespace handled above. - assert!(matches!(node.kind, ast::AccessKind::Property)); - let subject = self.make_term_from_ast_expr(node.subject.ast_ref())?; let field = match node.property.body() { ast::PropertyKind::NamedField(name) => ParamIndex::Name(*name), diff --git a/stdlib/eq.hash b/stdlib/eq.hash index 44c26f12d..340623cfc 100644 --- a/stdlib/eq.hash +++ b/stdlib/eq.hash @@ -1,23 +1,23 @@ subst := => #pure (P: A -> Type, p: a ~ b, m: {P(a)}) -> {P(b)} => { match p { - Equal::Refl(x) => m + Equal.Refl(x) => m } } transport := => (P: (y: A) -> C, p: a ~ b) -> {P(a)} ~ {P(b)} => { match p { - Equal::Refl(x) => Equal::Refl(P(x)) + Equal.Refl(x) => Equal.Refl(P(x)) } } sym := => (p: a ~ b) -> b ~ a => { match p { - Equal::Refl(_) => p + Equal.Refl(_) => p } } trans := => (p: a ~ b, q: b ~ c) -> a ~ c => { match p { - Equal::Refl(_) => q + Equal.Refl(_) => q } } diff --git a/stdlib/prelude.hash b/stdlib/prelude.hash index 39516bc5a..99ba99e54 100644 --- a/stdlib/prelude.hash +++ b/stdlib/prelude.hash @@ -6,7 +6,7 @@ eq := import("eq") /// The `cast(..)` function is used to cast some value into another /// type provided that the types are cast compatible. cast := => (item: T) -> U => { - Intrinsics::cast(T, U, item) + Intrinsics.cast(T, U, item) } /// This is powerful mechanism that @@ -25,7 +25,7 @@ cast := => (item: T) -> U => { /// allows for the program to now read the `bytes` and `length` fields of the /// `SizedPointer` type. transmute := => (item: T) -> U => { - Intrinsics::transmute(T, U, item) + Intrinsics.transmute(T, U, item) } #[repr("c")] @@ -42,12 +42,12 @@ print := (msg: str, /* end: char = '\n' */) => { // stdout. SizedPointer(bytes, len) := transmute(msg); - libc::write(STDOUT, bytes, len); + libc.write(STDOUT, bytes, len); // @@Todo: un-comment this when default parameters are working // write the end character - // end_sep := Intrinsics::cast(type char, type u8, '\n'); - // libc::write(1, &raw end_sep, 1); + // end_sep := Intrinsics.cast(type char, type u8, '\n'); + // libc.write(1, &raw end_sep, 1); } println := (message: str) => { @@ -56,17 +56,17 @@ println := (message: str) => { } refl := => () -> {a ~ a} => { - Equal::Refl(a) + Equal.Refl(a) } dbg := => (item: T) -> T => { - Intrinsics::debug_print(T, item) + Intrinsics.debug_print(T, item) item } #lang panic := (msg: str) -> ! => { print(msg); - Intrinsics::abort() + Intrinsics.abort() } #lang @@ -74,29 +74,29 @@ str_eq := (left: str, right: str) => { SizedPointer(left_data, left_len) := transmute<_, SizedPointer>(left); SizedPointer(right_data, right_len) := transmute<_, SizedPointer>(right); - left_len == right_len && Intrinsics::memcmp(left_data, right_data, left_len) == 0 + left_len == right_len && Intrinsics.memcmp(left_data, right_data, left_len) == 0 } libc := mod { /// The `char` is equivalent to an `i32` but avoid having to make the cast. - #foreign putwchar := (c: char) -> i32 => { Intrinsics::abort() } + #foreign putwchar := (c: char) -> i32 => { Intrinsics.abort() } - #foreign write := (fd: i32, buf: &raw u8, len: usize) -> isize => { Intrinsics::abort() } + #foreign write := (fd: i32, buf: &raw u8, len: usize) -> isize => { Intrinsics.abort() } - #foreign read := (fd: i32, buf: &raw u8, len: usize) -> isize => { Intrinsics::abort() } + #foreign read := (fd: i32, buf: &raw u8, len: usize) -> isize => { Intrinsics.abort() } - #foreign open := (path: &raw u8, flags: i32, mode: i32) -> i32 => { Intrinsics::abort() } + #foreign open := (path: &raw u8, flags: i32, mode: i32) -> i32 => { Intrinsics.abort() } - #foreign close := (fd: i32) -> i32 => { Intrinsics::abort() } + #foreign close := (fd: i32) -> i32 => { Intrinsics.abort() } - #foreign exit := (status: i32) => { Intrinsics::abort() } + #foreign exit := (status: i32) => { Intrinsics.abort() } - #foreign malloc := (size: usize) -> &raw u8 => { Intrinsics::abort() } + #foreign malloc := (size: usize) -> &raw u8 => { Intrinsics.abort() } - #foreign free := (ptr: &raw u8) -> () => { Intrinsics::abort() } + #foreign free := (ptr: &raw u8) -> () => { Intrinsics.abort() } - #foreign memcpy := (dest: &raw u8, src: &raw u8, n: usize) -> &raw u8 => { Intrinsics::abort() } + #foreign memcpy := (dest: &raw u8, src: &raw u8, n: usize) -> &raw u8 => { Intrinsics.abort() } - #foreign memcmp := (s1: &raw u8, s2: &raw u8, n: usize) -> i32 => { Intrinsics::abort() } + #foreign memcmp := (s1: &raw u8, s2: &raw u8, n: usize) -> i32 => { Intrinsics.abort() } } diff --git a/tests/cases/codegen/discriminants.hash b/tests/cases/codegen/discriminants.hash index 1b36dd29b..96b828559 100644 --- a/tests/cases/codegen/discriminants.hash +++ b/tests/cases/codegen/discriminants.hash @@ -12,9 +12,9 @@ Direction := enum( ) main := () => { - east := Direction::Right; + east := Direction.Right; foo(east); - south := Direction::Down; + south := Direction.Down; bar(south); } @@ -33,10 +33,10 @@ bar := (dir: Direction) => { foo := (dir: Direction) => { match dir { - Direction::Up => { + Direction.Up => { println("Up"); }, - Direction::Right => { + Direction.Right => { t := transmute<_, i8>(dir); if t == 63 { @@ -45,10 +45,10 @@ foo := (dir: Direction) => { println("Not 63"); } }, - Direction::Down => { + Direction.Down => { println("Down"); }, - Direction::Left => { + Direction.Left => { println("Left"); }, } diff --git a/tests/cases/exhaustiveness/enums.hash b/tests/cases/exhaustiveness/enums.hash index 7974fc474..25ce753b1 100644 --- a/tests/cases/exhaustiveness/enums.hash +++ b/tests/cases/exhaustiveness/enums.hash @@ -14,11 +14,11 @@ Pos := struct( next_pos := (pos: Pos, dir: Direction, end: Pos) -> Option => { match dir { - Direction::South if pos.y != end.y => Option::Some(Pos(pos.x, pos.y + 1)), - Direction::North if pos.y != 0 => Option::Some(Pos(pos.x, pos.y - 1)), - Direction::East if pos.x != end.x => Option::Some(Pos(pos.x + 1, pos.y)), - Direction::West if pos.x != 0 => Option::Some(Pos(pos.x - 1, pos.y)), - _ => Option::None + Direction.South if pos.y != end.y => Option.Some(Pos(pos.x, pos.y + 1)), + Direction.North if pos.y != 0 => Option.Some(Pos(pos.x, pos.y - 1)), + Direction.East if pos.x != end.x => Option.Some(Pos(pos.x + 1, pos.y)), + Direction.West if pos.x != 0 => Option.Some(Pos(pos.x - 1, pos.y)), + _ => Option.None } } diff --git a/tests/cases/exhaustiveness/missing_enums.hash b/tests/cases/exhaustiveness/missing_enums.hash index e393edb5d..b386daf2b 100644 --- a/tests/cases/exhaustiveness/missing_enums.hash +++ b/tests/cases/exhaustiveness/missing_enums.hash @@ -4,9 +4,9 @@ maybe_add := (left: Option, right: Option) -> i32 => { loop { return match (left, right) { - (Option::Some(a), Option::Some(b)) => a + b, - (Option::Some(a), Option::None) => a, - (Option::None, Option::Some(a)) => {a}, + (Option.Some(a), Option.Some(b)) => a + b, + (Option.Some(a), Option.None) => a, + (Option.None, Option.Some(a)) => {a}, } }; @@ -23,17 +23,17 @@ Direction := enum( // ~ERROR: patterns not covered direction_to_int := (dir: Direction) -> i32 => { return match dir { - Direction::North => 1, - Direction::West => 2, + Direction.North => 1, + Direction.West => 2, } } // ~ERROR: patterns not covered join_directions := (dir: Direction, other: Direction) -> Direction => { match (dir, other) { - (Direction::North, Direction::South) => Direction::North, - (Direction::South, Direction::North) => Direction::North, - (Direction::West, Direction::East) => Direction::West, - (Direction::East, Direction::West) => Direction::West, + (Direction.North, Direction.South) => Direction.North, + (Direction.South, Direction.North) => Direction.North, + (Direction.West, Direction.East) => Direction.West, + (Direction.East, Direction.West) => Direction.West, } } diff --git a/tests/cases/exhaustiveness/missing_enums.stderr b/tests/cases/exhaustiveness/missing_enums.stderr index de8f1ec06..782851e97 100644 --- a/tests/cases/exhaustiveness/missing_enums.stderr +++ b/tests/cases/exhaustiveness/missing_enums.stderr @@ -3,18 +3,18 @@ error[0083]: non-exhaustive patterns: `(Option::None, Option::None)` not covered 5 | loop { 6 | return match (left, right) { | ^^^^^^^^^^^^^ pattern `(Option::None, Option::None)` not covered -7 | (Option::Some(a), Option::Some(b)) => a + b, +7 | (Option.Some(a), Option.Some(b)) => a + b, error[0083]: non-exhaustive patterns: `Direction::South`, and `Direction::East` not covered --> $DIR/missing_enums.hash:25:16 24 | direction_to_int := (dir: Direction) -> i32 => { 25 | return match dir { | ^^^ patterns `Direction::South`, and `Direction::East` not covered -26 | Direction::North => 1, +26 | Direction.North => 1, error[0083]: non-exhaustive patterns: `(Direction::South, Direction::South)`, `(Direction::South, Direction::West)`, `(Direction::South, Direction::East)` and 9 more not covered --> $DIR/missing_enums.hash:33:11 32 | join_directions := (dir: Direction, other: Direction) -> Direction => { 33 | match (dir, other) { | ^^^^^^^^^^^^ patterns `(Direction::South, Direction::South)`, `(Direction::South, Direction::West)`, `(Direction::South, Direction::East)` and 9 more not covered -34 | (Direction::North, Direction::South) => Direction::North, +34 | (Direction.North, Direction.South) => Direction.North, diff --git a/tests/cases/lowering/constructor_matches.hash b/tests/cases/lowering/constructor_matches.hash index 560df2fe2..4c105c415 100644 --- a/tests/cases/lowering/constructor_matches.hash +++ b/tests/cases/lowering/constructor_matches.hash @@ -2,9 +2,9 @@ maybe_add := (left: Option, right: Option) -> i32 => { match (left, right) { - (Option::Some(a), Option::Some(b)) => a + b, - (Option::Some(a), Option::None) => a, - (Option::None, Option::Some(a)) => a, - (Option::None, Option::None) => 0 + (Option.Some(a), Option.Some(b)) => a + b, + (Option.Some(a), Option.None) => a, + (Option.None, Option.Some(a)) => a, + (Option.None, Option.None) => 0 } } diff --git a/tests/cases/parser/constructors/struct_literal_init.hash b/tests/cases/parser/constructors/struct_literal_init.hash index a3757591e..984faccdb 100644 --- a/tests/cases/parser/constructors/struct_literal_init.hash +++ b/tests/cases/parser/constructors/struct_literal_init.hash @@ -3,7 +3,7 @@ my_dog := MyDog ( name = "Viktor", age = 17.2, - breed = DogBreed::Husky + breed = DogBreed.Husky ); // Test auto-assigning the same name field as a variable in scope diff --git a/tests/cases/parser/declarations/constants.hash b/tests/cases/parser/declarations/constants.hash new file mode 100644 index 000000000..08d2dc646 --- /dev/null +++ b/tests/cases/parser/declarations/constants.hash @@ -0,0 +1,24 @@ +// stage=parse + + +m: i32 : 0 +k :: 0 + +foo :: () => { + k + m +} + +bar :: () => { + l :: foo() + t := 1 + l + + l + t +} + + +fizz :: () => { + l: i32 : foo() + t: i32 = 1 + l + + l + t +} diff --git a/tests/cases/parser/literals/double_colon_in_map_literal.stderr b/tests/cases/parser/literals/double_colon_in_map_literal.stderr index 0fc23d546..d21400cf3 100644 --- a/tests/cases/parser/literals/double_colon_in_map_literal.stderr +++ b/tests/cases/parser/literals/double_colon_in_map_literal.stderr @@ -1,6 +1,5 @@ -error: expected a name here - --> $DIR/double_colon_in_map_literal.hash:3:15 +error: expected an expression, however received a `::` + --> $DIR/double_colon_in_map_literal.hash:3:13 2 | 3 | k := map!{ 1::2 }; - | ^ - = help: expected a `identifier` + | ^^ diff --git a/tests/cases/parser/literals/enum_literals.hash b/tests/cases/parser/literals/enum_literals.hash index b951f1e91..8d749439b 100644 --- a/tests/cases/parser/literals/enum_literals.hash +++ b/tests/cases/parser/literals/enum_literals.hash @@ -1,4 +1,4 @@ // run=pass, stage=parse -k := MyEnum::Variant(1, 2, 3); -k := MyEnum::Variant(Some(MyEnum::Variant(None, 2, 1)), 2, 3); +k := MyEnum.Variant(1, 2, 3); +k := MyEnum.Variant(Some(MyEnum.Variant(None, 2, 1)), 2, 3); diff --git a/tests/cases/parser/misc/triple_colon_in_access_name.hash b/tests/cases/parser/misc/triple_colon_in_access_name.hash index aed691f50..a2a18a32b 100644 --- a/tests/cases/parser/misc/triple_colon_in_access_name.hash +++ b/tests/cases/parser/misc/triple_colon_in_access_name.hash @@ -1,3 +1,3 @@ // run=fail, stage=parse -a::b:::c(); +a.b.:c(); diff --git a/tests/cases/parser/misc/triple_colon_in_access_name.stderr b/tests/cases/parser/misc/triple_colon_in_access_name.stderr index d54f0adc8..6d04632c3 100644 --- a/tests/cases/parser/misc/triple_colon_in_access_name.stderr +++ b/tests/cases/parser/misc/triple_colon_in_access_name.stderr @@ -1,6 +1,6 @@ -error: expected a name here - --> $DIR/triple_colon_in_access_name.hash:3:7 +error: expected field name access or a method call + --> $DIR/triple_colon_in_access_name.hash:3:5 2 | -3 | a::b:::c(); - | ^ +3 | a.b.:c(); + | ^ = help: expected a `identifier` diff --git a/tests/cases/parser/patterns/decl_pats.hash b/tests/cases/parser/patterns/decl_pats.hash index 0d8ec1f69..821d10bf2 100644 --- a/tests/cases/parser/patterns/decl_pats.hash +++ b/tests/cases/parser/patterns/decl_pats.hash @@ -1,14 +1,14 @@ // run=pass, stage=parse // De-structure the `dog` into `age` and `name` -animals::Dog(name, age) := dog; +animals.Dog(name, age) := dog; (a, b, c) := (2, 3, 4); // This wouldn't be allowed but would parse -animals::ModuleVariable := 3; -animals::ModuleVariable: i32 = 3; +animals.ModuleVariable := 3; +animals.ModuleVariable: i32 = 3; // Multiple constructors on the pattern -animals::Dog()() := dog; +animals.Dog()() := dog; diff --git a/tests/cases/parser/types/access_tys.hash b/tests/cases/parser/types/access_tys.hash index bfa7c2566..9f8bba397 100644 --- a/tests/cases/parser/types/access_tys.hash +++ b/tests/cases/parser/types/access_tys.hash @@ -1,4 +1,4 @@ // run=pass, stage=parse -t: animals::Dog = animals::Dog(name = "Viktor", age = 12); -t: animals::Dog = animals::Dog(name = "Viktor", age = 12); +t: animals.Dog = animals.Dog(name = "Viktor", age = 12); +t: animals.Dog = animals.Dog(name = "Viktor", age = 12); diff --git a/tests/cases/parser/types/issue_394.hash b/tests/cases/parser/types/issue_394.hash index 3bbc7ea10..82e821645 100644 --- a/tests/cases/parser/types/issue_394.hash +++ b/tests/cases/parser/types/issue_394.hash @@ -1,5 +1,5 @@ // stage=parse, warnings=ignore main := () => { - ((a.v)::c); + ((a.v).c); }; diff --git a/tests/cases/parser/types/malformed_function_type.stderr b/tests/cases/parser/types/malformed_function_type.stderr index d21b314ca..8d3149650 100644 --- a/tests/cases/parser/types/malformed_function_type.stderr +++ b/tests/cases/parser/types/malformed_function_type.stderr @@ -1,6 +1,6 @@ error: unexpectedly encountered a `>` - --> $DIR/malformed_function_type.hash:3:20 + --> $DIR/malformed_function_type.hash:3:21 2 | 3 | str_eq: (str, str) > str; - | ^ - = help: expected a `=` + | ^ + = help: expected either `:`, or `=` diff --git a/tests/cases/semantics/pats/intrinsics_in_pats.hash b/tests/cases/semantics/pats/intrinsics_in_pats.hash index 9794805bd..2e1ca5b25 100644 --- a/tests/cases/semantics/pats/intrinsics_in_pats.hash +++ b/tests/cases/semantics/pats/intrinsics_in_pats.hash @@ -2,6 +2,6 @@ main := () => { match 1 { - Intrinsics::user_error => {} + Intrinsics.user_error => {} } } diff --git a/tests/cases/semantics/pats/intrinsics_in_pats.stderr b/tests/cases/semantics/pats/intrinsics_in_pats.stderr index 19e03e1c1..0c8464bcb 100644 --- a/tests/cases/semantics/pats/intrinsics_in_pats.stderr +++ b/tests/cases/semantics/pats/intrinsics_in_pats.stderr @@ -1,7 +1,7 @@ error[0024]: cannot use an intrinsic in pattern position --> $DIR/intrinsics_in_pats.hash:5:5 4 | match 1 { -5 | Intrinsics::user_error => {} - | ^^^^^^^^^^^^^^^^^^^^^^ +5 | Intrinsics.user_error => {} + | ^^^^^^^^^^^^^^^^^^^^^ 6 | } = info: cannot use this in pattern position as it refers to a compiler intrinsic diff --git a/tests/cases/typecheck/enums/adt.hash b/tests/cases/typecheck/enums/adt.hash index 53823c501..230540dcc 100644 --- a/tests/cases/typecheck/enums/adt.hash +++ b/tests/cases/typecheck/enums/adt.hash @@ -5,7 +5,7 @@ Vote := enum(Left(usize), Right(usize), Abstain); ensure := => (t: T) => {}; main := () => { - ensure(Vote::Left(1usize)); - ensure(Vote::Abstain); - ensure<(usize) -> Vote>((x: usize) => Vote::Left(x)); + ensure(Vote.Left(1usize)); + ensure(Vote.Abstain); + ensure<(usize) -> Vote>((x: usize) => Vote.Left(x)); }; diff --git a/tests/cases/typecheck/enums/basic.hash b/tests/cases/typecheck/enums/basic.hash index f57889ca4..deb0558aa 100644 --- a/tests/cases/typecheck/enums/basic.hash +++ b/tests/cases/typecheck/enums/basic.hash @@ -5,14 +5,14 @@ PrimaryColour := enum(Red, Green, Blue); ensure := => (t: T) => {}; main := () => { - ensure(PrimaryColour::Red); - ensure(PrimaryColour::Green); - ensure(PrimaryColour::Blue); + ensure(PrimaryColour.Red); + ensure(PrimaryColour.Green); + ensure(PrimaryColour.Blue); - red := PrimaryColour::Red; + red := PrimaryColour.Red; ensure(red); - many := [PrimaryColour::Red as PrimaryColour, PrimaryColour::Blue as PrimaryColour, PrimaryColour::Green as PrimaryColour]; + many := [PrimaryColour.Red as PrimaryColour, PrimaryColour.Blue as PrimaryColour, PrimaryColour.Green as PrimaryColour]; ensure>(many); }; diff --git a/tests/cases/typecheck/enums/indexed.hash b/tests/cases/typecheck/enums/indexed.hash index 4c8f90539..265c93555 100644 --- a/tests/cases/typecheck/enums/indexed.hash +++ b/tests/cases/typecheck/enums/indexed.hash @@ -7,13 +7,13 @@ Nat := enum( Fin := enum ( Zero(n: Nat): Fin, - Succ(n: Nat, f: Fin): Fin<{Nat::Succ(n)}>, + Succ(n: Nat, f: Fin): Fin<{Nat.Succ(n)}>, ) add := (a: Nat, b: Nat) -> Nat => { match a { - Nat::Zero => b, - Nat::Succ(a) => Nat::Succ(add(a, b)) + Nat.Zero => b, + Nat.Succ(a) => Nat.Succ(add(a, b)) } } @@ -23,11 +23,11 @@ Lt := enum ( sub := (n: Nat, m: Nat, p: Lt) -> Nat => { match p { - Lt::Diff(_, d) => d + Lt.Diff(_, d) => d } } Vec := enum ( - Nil: Vec, - Cons(n: Nat, x: A, xs: Vec): Vec<{Nat::Succ(n)}, A>, + Nil: Vec, + Cons(n: Nat, x: A, xs: Vec): Vec<{Nat.Succ(n)}, A>, ) diff --git a/tests/cases/typecheck/misc/expr.hash b/tests/cases/typecheck/misc/expr.hash index fe1164430..6f7563b9e 100644 --- a/tests/cases/typecheck/misc/expr.hash +++ b/tests/cases/typecheck/misc/expr.hash @@ -21,20 +21,20 @@ Expr := enum ( /// Evaluate an expression of i32. eval := (e: Expr) -> i32 => { match e { - Expr::Const(t) => t, - Expr::BinOp(op, e1, e2) => match op { - BinOp::Add => eval(e1) + eval(e2), - BinOp::Mul => eval(e1) * eval(e2), - BinOp::Sub => eval(e1) - eval(e2), - BinOp::Div => eval(e1) / eval(e2), + Expr.Const(t) => t, + Expr.BinOp(op, e1, e2) => match op { + BinOp.Add => eval(e1) + eval(e2), + BinOp.Mul => eval(e1) * eval(e2), + BinOp.Sub => eval(e1) - eval(e2), + BinOp.Div => eval(e1) / eval(e2), }, - Expr::UnOp(op, e1) => match op { - UnOp::Neg => -eval(e1), + Expr.UnOp(op, e1) => match op { + UnOp.Neg => -eval(e1), }, } } main := () => { - e := Expr::BinOp(BinOp::Add, Expr::Const(41), Expr::Const(1)) + e := Expr.BinOp(BinOp.Add, Expr.Const(41), Expr.Const(1)) n := eval(e) } diff --git a/tests/cases/typecheck/misc/monad.hash b/tests/cases/typecheck/misc/monad.hash index 66148f9fe..463ef1b7b 100644 --- a/tests/cases/typecheck/misc/monad.hash +++ b/tests/cases/typecheck/misc/monad.hash @@ -38,10 +38,10 @@ option_monad := () => { b: U -> Option ) -> Option => { match a { - Option::Some(x) => b(x), - Option::None => Option::None + Option.Some(x) => b(x), + Option.None => Option.None } }, - ret = => (x: U) -> Option => Option::Some(x) + ret = => (x: U) -> Option => Option.Some(x) ) } diff --git a/tests/cases/typecheck/misc/nat.hash b/tests/cases/typecheck/misc/nat.hash index 498108b60..e26747800 100644 --- a/tests/cases/typecheck/misc/nat.hash +++ b/tests/cases/typecheck/misc/nat.hash @@ -9,8 +9,8 @@ Nat := enum( /// Add two natural numbers. add := (a: Nat, b: Nat) -> Nat => { match a { - Nat::Zero => b, - Nat::Succ(a) => Nat::Succ(add(a, b)) + Nat.Zero => b, + Nat.Succ(a) => Nat.Succ(add(a, b)) } } @@ -18,21 +18,21 @@ add := (a: Nat, b: Nat) -> Nat => { succ_id := < a: Nat, b: Nat, - p: {Nat::Succ(a)} ~ {Nat::Succ(b)} + p: {Nat.Succ(a)} ~ {Nat.Succ(b)} > -> a ~ b => { match p { - Equal::Refl(_) => refl() + Equal.Refl(_) => refl() } } /// Nat induction. nat_induction := ( P: -> Type, - pzero: P, - psucc: (m: Nat, p: P) -> P<{Nat::Succ(m)}>, + pzero: P, + psucc: (m: Nat, p: P) -> P<{Nat.Succ(m)}>, ) => (n: Nat) -> P => { match n { - Nat::Zero => pzero, - Nat::Succ(m) => psucc(m, nat_induction(P, pzero, psucc)(m)) + Nat.Zero => pzero, + Nat.Succ(m) => psucc(m, nat_induction(P, pzero, psucc)(m)) } }