go: parse.sx — struct type expressions + 8 tests [proposes-ast]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
Adds Go struct types to gp-parse-type:
struct {} → (list :ty-struct ())
struct { x int } → (list :ty-struct [(:field [x] (:ty-name int))])
struct { x int; y string } → multiple field rows
struct { x, y int } → shared-type row (NAMES is a list)
struct { inner struct { x int } } → nested struct types
gp-parse-struct-fields walks field rows tolerating ASI-inserted semis
(from newlines between fields). Each row collects 1+ names separated
by commas, then a single type that all the names share. Embedded
fields, field tags, and methods are deferred.
The :field shape (NAMES + TYPE) is a recurring multi-language pattern —
struct fields, func params, method receivers, var decls all map to it.
Logged in Blockers as a canonical-AST candidate
(ast-binding-group / ast-named-of-type); worth promoting once a second
consumer (parser of another statically-typed guest, or Go func decls)
exercises the same shape.
parse 98/98, total 227/227.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -507,6 +507,76 @@
|
||||
:ty-chan :both
|
||||
(list :ty-func (list) (list (list :ty-name "int"))))))
|
||||
|
||||
(go-parse-test
|
||||
"ty: struct {} (empty)"
|
||||
(go-parse "v.(struct {})")
|
||||
(list :assert (ast-var "v") (list :ty-struct (list))))
|
||||
|
||||
(go-parse-test
|
||||
"ty: struct { x int }"
|
||||
(go-parse "v.(struct { x int })")
|
||||
(list
|
||||
:assert (ast-var "v")
|
||||
(list :ty-struct (list (list :field (list "x") (list :ty-name "int"))))))
|
||||
|
||||
(go-parse-test
|
||||
"ty: struct { x int; y string } (multiple fields)"
|
||||
(go-parse "v.(struct { x int; y string })")
|
||||
(list
|
||||
:assert (ast-var "v")
|
||||
(list
|
||||
:ty-struct (list
|
||||
(list :field (list "x") (list :ty-name "int"))
|
||||
(list :field (list "y") (list :ty-name "string"))))))
|
||||
|
||||
(go-parse-test
|
||||
"ty: struct { x, y int } (shared type)"
|
||||
(go-parse "v.(struct { x, y int })")
|
||||
(list
|
||||
:assert (ast-var "v")
|
||||
(list
|
||||
:ty-struct (list (list :field (list "x" "y") (list :ty-name "int"))))))
|
||||
|
||||
(go-parse-test
|
||||
"ty: struct { p *T } (pointer field)"
|
||||
(go-parse "v.(struct { p *T })")
|
||||
(list
|
||||
:assert (ast-var "v")
|
||||
(list
|
||||
:ty-struct (list (list :field (list "p") (list :ty-ptr (list :ty-name "T")))))))
|
||||
|
||||
(go-parse-test
|
||||
"ty: struct { items []int } (slice field)"
|
||||
(go-parse "v.(struct { items []int })")
|
||||
(list
|
||||
:assert (ast-var "v")
|
||||
(list
|
||||
:ty-struct (list
|
||||
(list :field (list "items") (list :ty-slice (list :ty-name "int")))))))
|
||||
|
||||
(go-parse-test
|
||||
"ty: struct { a int; b, c string; d *T } (mixed)"
|
||||
(go-parse "v.(struct { a int; b, c string; d *T })")
|
||||
(list
|
||||
:assert (ast-var "v")
|
||||
(list
|
||||
:ty-struct (list
|
||||
(list :field (list "a") (list :ty-name "int"))
|
||||
(list :field (list "b" "c") (list :ty-name "string"))
|
||||
(list :field (list "d") (list :ty-ptr (list :ty-name "T")))))))
|
||||
|
||||
(go-parse-test
|
||||
"ty: nested struct { inner struct { x int } }"
|
||||
(go-parse "v.(struct { inner struct { x int } })")
|
||||
(list
|
||||
:assert (ast-var "v")
|
||||
(list
|
||||
:ty-struct (list
|
||||
(list
|
||||
:field (list "inner")
|
||||
(list
|
||||
:ty-struct (list (list :field (list "x") (list :ty-name "int")))))))))
|
||||
|
||||
(go-parse-test "non-primary: '+'" (go-parse "+") nil)
|
||||
|
||||
(go-parse-test "non-primary: empty" (go-parse "") nil)
|
||||
|
||||
Reference in New Issue
Block a user