Add nested types

This commit is contained in:
Richard Feldman 2025-10-05 12:56:25 -04:00
parent 3d7ebd3df4
commit f265318700
No known key found for this signature in database
9 changed files with 289 additions and 8 deletions

View file

@ -1014,6 +1014,21 @@ pub const Statement = union(enum) {
try ast.store.getTypeAnno(a.anno).pushToSExprTree(gpa, env, ast, tree);
// Add associated block if present
if (a.associated) |assoc| {
const assoc_begin = tree.beginNode();
try tree.pushStaticAtom("associated");
try ast.appendRegionInfoToSexprTree(env, tree, assoc.region);
const assoc_attrs = tree.beginNode();
for (ast.store.statementSlice(assoc.statements)) |stmt_idx| {
const stmt = ast.store.getStatement(stmt_idx);
try stmt.pushToSExprTree(gpa, env, ast, tree);
}
try tree.endNode(assoc_begin, assoc_attrs);
}
try tree.endNode(begin, attrs);
},
.crash => |a| {

View file

@ -930,7 +930,7 @@ pub fn parseExposedItem(self: *Parser) Error!AST.ExposedItem.Idx {
}
}
const StatementType = enum { top_level, in_body };
const StatementType = enum { top_level, in_body, in_associated_block };
/// Parse a top level roc statement
///
@ -1170,7 +1170,7 @@ fn parseStmtByType(self: *Parser, statementType: StatementType) Error!AST.Statem
// Type Annotation (e.g. `Foo a : (a,a)`)
.UpperIdent => {
const start = self.pos;
if (statementType == .top_level) {
if (statementType == .top_level or statementType == .in_associated_block) {
const header = try self.parseTypeHeader();
if (self.peek() != .OpColon and self.peek() != .OpColonEqual) {
// Point to the unexpected token (e.g., "U8" in "List U8")
@ -2969,7 +2969,7 @@ pub fn parseStatementOnlyBlock(self: *Parser, start: u32) Error!AST.Associated {
while (self.peek() != .EndOfFile and self.peek() != .CloseCurly) {
const statement_pos = self.pos;
const statement = try self.parseStmt();
const statement = try self.parseStmtByType(.in_associated_block);
// Check if this is an expression statement (the last statement must not be an expression)
const stmt = self.store.getStatement(statement);

View file

@ -41,7 +41,12 @@ EndOfFile(3:1-3:1),
(tags
(ty @1.9-1.10 (name "A"))
(ty @1.12-1.13 (name "B"))
(ty @1.15-1.16 (name "C")))))))
(ty @1.15-1.16 (name "C"))))
(associated @1.18-2.4
(s-decl @1.20-1.25
(p-ident @1.20-1.21 (raw "x"))
(e-int @1.24-1.25 (raw "5")))
(e-ident @2.1-2.2 (raw "x"))))))
~~~
# FORMATTED
~~~roc

View file

@ -0,0 +1,143 @@
# META
~~~ini
description=Deeply nested types (3+ levels) in associated blocks
type=file
~~~
# SOURCE
~~~roc
Foo := [Whatever].{
Bar := [Something].{
Baz := [Else].{
Qux := [Deep].{
w = 1
}
z = 2
}
y = 3
}
x = 4
}
~~~
# EXPECTED
TYPE MODULE MISSING MATCHING TYPE - nominal_deeply_nested_types.md:1:1:12:2
# PROBLEMS
**TYPE MODULE MISSING MATCHING TYPE**
Type modules must have a type declaration matching the module name.
This file is named `nominal_deeply_nested_types`.roc, but no top-level type declaration named `nominal_deeply_nested_types` was found.
Add either:
`nominal_deeply_nested_types := ...` (nominal type)
or:
`nominal_deeply_nested_types : ...` (type alias)
**nominal_deeply_nested_types.md:1:1:12:2:**
```roc
Foo := [Whatever].{
Bar := [Something].{
Baz := [Else].{
Qux := [Deep].{
w = 1
}
z = 2
}
y = 3
}
x = 4
}
```
# TOKENS
~~~zig
UpperIdent(1:1-1:4),OpColonEqual(1:5-1:7),OpenSquare(1:8-1:9),UpperIdent(1:9-1:17),CloseSquare(1:17-1:18),Dot(1:18-1:19),OpenCurly(1:19-1:20),
UpperIdent(2:5-2:8),OpColonEqual(2:9-2:11),OpenSquare(2:12-2:13),UpperIdent(2:13-2:22),CloseSquare(2:22-2:23),Dot(2:23-2:24),OpenCurly(2:24-2:25),
UpperIdent(3:9-3:12),OpColonEqual(3:13-3:15),OpenSquare(3:16-3:17),UpperIdent(3:17-3:21),CloseSquare(3:21-3:22),Dot(3:22-3:23),OpenCurly(3:23-3:24),
UpperIdent(4:13-4:16),OpColonEqual(4:17-4:19),OpenSquare(4:20-4:21),UpperIdent(4:21-4:25),CloseSquare(4:25-4:26),Dot(4:26-4:27),OpenCurly(4:27-4:28),
LowerIdent(5:17-5:18),OpAssign(5:19-5:20),Int(5:21-5:22),
CloseCurly(6:13-6:14),
LowerIdent(7:13-7:14),OpAssign(7:15-7:16),Int(7:17-7:18),
CloseCurly(8:9-8:10),
LowerIdent(9:9-9:10),OpAssign(9:11-9:12),Int(9:13-9:14),
CloseCurly(10:5-10:6),
LowerIdent(11:5-11:6),OpAssign(11:7-11:8),Int(11:9-11:10),
CloseCurly(12:1-12:2),
EndOfFile(13:1-13:1),
~~~
# PARSE
~~~clojure
(file @1.1-12.2
(type-module @1.1-1.4)
(statements
(s-type-decl @1.1-12.2
(header @1.1-1.4 (name "Foo")
(args))
(ty-tag-union @1.8-1.18
(tags
(ty @1.9-1.17 (name "Whatever"))))
(associated @1.19-12.2
(s-type-decl @2.5-10.6
(header @2.5-2.8 (name "Bar")
(args))
(ty-tag-union @2.12-2.23
(tags
(ty @2.13-2.22 (name "Something"))))
(associated @2.24-10.6
(s-type-decl @3.9-8.10
(header @3.9-3.12 (name "Baz")
(args))
(ty-tag-union @3.16-3.22
(tags
(ty @3.17-3.21 (name "Else"))))
(associated @3.23-8.10
(s-type-decl @4.13-6.14
(header @4.13-4.16 (name "Qux")
(args))
(ty-tag-union @4.20-4.26
(tags
(ty @4.21-4.25 (name "Deep"))))
(associated @4.27-6.14
(s-decl @5.17-5.22
(p-ident @5.17-5.18 (raw "w"))
(e-int @5.21-5.22 (raw "1")))))
(s-decl @7.13-7.18
(p-ident @7.13-7.14 (raw "z"))
(e-int @7.17-7.18 (raw "2")))))
(s-decl @9.9-9.14
(p-ident @9.9-9.10 (raw "y"))
(e-int @9.13-9.14 (raw "3")))))
(s-decl @11.5-11.10
(p-ident @11.5-11.6 (raw "x"))
(e-int @11.9-11.10 (raw "4")))))))
~~~
# FORMATTED
~~~roc
Foo := [Whatever].{
Bar := [Something].{
Baz := [Else].{
Qux := [Deep].{
w = 1
}
z = 2
}
y = 3
}
x = 4
}
~~~
# CANONICALIZE
~~~clojure
(can-ir
(s-nominal-decl @1.1-12.2
(ty-header @1.1-1.4 (name "Foo"))
(ty-tag-union @1.8-1.18
(ty-tag-name @1.9-1.17 (name "Whatever")))))
~~~
# TYPES
~~~clojure
(inferred-types
(defs)
(type_decls
(nominal @1.1-12.2 (type "Foo")
(ty-header @1.1-1.4 (name "Foo"))))
(expressions))
~~~

View file

@ -0,0 +1,99 @@
# META
~~~ini
description=Nested types in associated blocks
type=file
~~~
# SOURCE
~~~roc
Foo := [Whatever].{
Bar := [Something].{
y = 6
}
x = 5
}
~~~
# EXPECTED
TYPE MODULE MISSING MATCHING TYPE - nominal_nested_types.md:1:1:6:2
# PROBLEMS
**TYPE MODULE MISSING MATCHING TYPE**
Type modules must have a type declaration matching the module name.
This file is named `nominal_nested_types`.roc, but no top-level type declaration named `nominal_nested_types` was found.
Add either:
`nominal_nested_types := ...` (nominal type)
or:
`nominal_nested_types : ...` (type alias)
**nominal_nested_types.md:1:1:6:2:**
```roc
Foo := [Whatever].{
Bar := [Something].{
y = 6
}
x = 5
}
```
# TOKENS
~~~zig
UpperIdent(1:1-1:4),OpColonEqual(1:5-1:7),OpenSquare(1:8-1:9),UpperIdent(1:9-1:17),CloseSquare(1:17-1:18),Dot(1:18-1:19),OpenCurly(1:19-1:20),
UpperIdent(2:5-2:8),OpColonEqual(2:9-2:11),OpenSquare(2:12-2:13),UpperIdent(2:13-2:22),CloseSquare(2:22-2:23),Dot(2:23-2:24),OpenCurly(2:24-2:25),
LowerIdent(3:9-3:10),OpAssign(3:11-3:12),Int(3:13-3:14),
CloseCurly(4:5-4:6),
LowerIdent(5:5-5:6),OpAssign(5:7-5:8),Int(5:9-5:10),
CloseCurly(6:1-6:2),
EndOfFile(7:1-7:1),
~~~
# PARSE
~~~clojure
(file @1.1-6.2
(type-module @1.1-1.4)
(statements
(s-type-decl @1.1-6.2
(header @1.1-1.4 (name "Foo")
(args))
(ty-tag-union @1.8-1.18
(tags
(ty @1.9-1.17 (name "Whatever"))))
(associated @1.19-6.2
(s-type-decl @2.5-4.6
(header @2.5-2.8 (name "Bar")
(args))
(ty-tag-union @2.12-2.23
(tags
(ty @2.13-2.22 (name "Something"))))
(associated @2.24-4.6
(s-decl @3.9-3.14
(p-ident @3.9-3.10 (raw "y"))
(e-int @3.13-3.14 (raw "6")))))
(s-decl @5.5-5.10
(p-ident @5.5-5.6 (raw "x"))
(e-int @5.9-5.10 (raw "5")))))))
~~~
# FORMATTED
~~~roc
Foo := [Whatever].{
Bar := [Something].{
y = 6
}
x = 5
}
~~~
# CANONICALIZE
~~~clojure
(can-ir
(s-nominal-decl @1.1-6.2
(ty-header @1.1-1.4 (name "Foo"))
(ty-tag-union @1.8-1.18
(ty-tag-name @1.9-1.17 (name "Whatever")))))
~~~
# TYPES
~~~clojure
(inferred-types
(defs)
(type_decls
(nominal @1.1-6.2 (type "Foo")
(ty-header @1.1-1.4 (name "Foo"))))
(expressions))
~~~

View file

@ -36,7 +36,17 @@ EndOfFile(6:1-6:1),
(tags
(ty @1.9-1.10 (name "A"))
(ty @1.12-1.13 (name "B"))
(ty @1.15-1.16 (name "C")))))))
(ty @1.15-1.16 (name "C"))))
(associated @1.18-5.2
(s-decl @2.5-2.10
(p-ident @2.5-2.6 (raw "x"))
(e-int @2.9-2.10 (raw "5")))
(s-decl @3.5-3.11
(p-ident @3.5-3.6 (raw "y"))
(e-int @3.9-3.11 (raw "10")))
(s-decl @4.5-4.11
(p-ident @4.5-4.6 (raw "z"))
(e-int @4.9-4.11 (raw "15")))))))
~~~
# FORMATTED
~~~roc

View file

@ -28,7 +28,11 @@ EndOfFile(2:1-2:1),
(tags
(ty @1.9-1.10 (name "A"))
(ty @1.12-1.13 (name "B"))
(ty @1.15-1.16 (name "C")))))))
(ty @1.15-1.16 (name "C"))))
(associated @1.18-1.27
(s-decl @1.20-1.25
(p-ident @1.20-1.21 (raw "x"))
(e-int @1.24-1.25 (raw "5")))))))
~~~
# FORMATTED
~~~roc

View file

@ -28,7 +28,8 @@ EndOfFile(2:1-2:1),
(tags
(ty @1.9-1.10 (name "A"))
(ty @1.12-1.13 (name "B"))
(ty @1.15-1.16 (name "C")))))))
(ty @1.15-1.16 (name "C"))))
(associated @1.18-1.20))))
~~~
# FORMATTED
~~~roc

View file

@ -39,7 +39,11 @@ EndOfFile(2:1-2:1),
(tags
(ty @1.8-1.9 (name "A"))
(ty @1.11-1.12 (name "B"))
(ty @1.14-1.15 (name "C")))))))
(ty @1.14-1.15 (name "C"))))
(associated @1.17-1.26
(s-decl @1.19-1.24
(p-ident @1.19-1.20 (raw "x"))
(e-int @1.23-1.24 (raw "5")))))))
~~~
# FORMATTED
~~~roc