go: parse.sx — interface type expressions + 8 tests; type expressions DONE [nothing]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Adds Go interface type expressions:
interface {} → empty
interface { Close() } → no-param method
interface { String() string } → with single return
interface { Read([]byte) (int, error) } → multi-return method
interface { Stringer } → embedded named iface
interface { io.Reader } → qualified embedded
interface { io.Reader; Close() error } → mixed
gp-parse-interface-elems walks elements tolerating ASI semis. Each
element is either:
(list :method NAME PARAMS RESULTS)
(list :embed TYPE)
Method params/results reuse gp-parse-func-type-params/results — the
shape is identical to a free-standing func type. Go 1.18+ type sets
(interface { ~int | ~float64 }) are deferred until the generics
sub-deliverable.
With this, the full Phase 2 **type expressions** sub-deliverable is
complete (pending only field tags, struct/iface embeds details,
variadic, named func params, generics — all flagged later).
parse 106/106, total 235/235.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -95,6 +95,58 @@
|
|||||||
:else nil)))
|
:else nil)))
|
||||||
(gp-args-rest)
|
(gp-args-rest)
|
||||||
args)))))
|
args)))))
|
||||||
|
(define
|
||||||
|
gp-parse-interface-elems
|
||||||
|
;; Caller positioned BEFORE '{'. Parses elements until '}'.
|
||||||
|
;; Two element shapes:
|
||||||
|
;; M(params) [results] → (list :method "M" PARAMS RESULTS)
|
||||||
|
;; T or pkg.T → (list :embed TYPE)
|
||||||
|
;; Type sets (Go 1.18+: ~int | ~float64) deferred.
|
||||||
|
(fn
|
||||||
|
()
|
||||||
|
(when (and (= (gp-tok-type) "op") (= (gp-tok-value) "{"))
|
||||||
|
(gp-advance!))
|
||||||
|
(let ((elems (list)))
|
||||||
|
(define
|
||||||
|
gp-iface-loop
|
||||||
|
(fn
|
||||||
|
()
|
||||||
|
(cond
|
||||||
|
(= (gp-tok-type) "semi")
|
||||||
|
(do (gp-advance!) (gp-iface-loop))
|
||||||
|
(and (= (gp-tok-type) "op") (= (gp-tok-value) "}"))
|
||||||
|
(gp-advance!)
|
||||||
|
(= (gp-tok-type) "ident")
|
||||||
|
(do
|
||||||
|
(let ((name (gp-tok-value)))
|
||||||
|
(gp-advance!)
|
||||||
|
(cond
|
||||||
|
(and (= (gp-tok-type) "op")
|
||||||
|
(= (gp-tok-value) "("))
|
||||||
|
(let ((params (gp-parse-func-type-params)))
|
||||||
|
(let ((results (gp-parse-func-type-results)))
|
||||||
|
(append! elems
|
||||||
|
(list :method name params results))))
|
||||||
|
(and (= (gp-tok-type) "op")
|
||||||
|
(= (gp-tok-value) "."))
|
||||||
|
(do
|
||||||
|
(gp-advance!)
|
||||||
|
(cond
|
||||||
|
(= (gp-tok-type) "ident")
|
||||||
|
(let ((sel-name (gp-tok-value)))
|
||||||
|
(gp-advance!)
|
||||||
|
(append! elems
|
||||||
|
(list :embed
|
||||||
|
(list :ty-sel name sel-name))))
|
||||||
|
:else
|
||||||
|
(append! elems
|
||||||
|
(list :embed (list :ty-name name)))))
|
||||||
|
:else
|
||||||
|
(append! elems (list :embed (list :ty-name name)))))
|
||||||
|
(gp-iface-loop))
|
||||||
|
:else nil)))
|
||||||
|
(gp-iface-loop)
|
||||||
|
elems)))
|
||||||
(define
|
(define
|
||||||
gp-parse-struct-fields
|
gp-parse-struct-fields
|
||||||
;; Caller positioned BEFORE '{'. Parses fields until '}'.
|
;; Caller positioned BEFORE '{'. Parses fields until '}'.
|
||||||
@@ -251,6 +303,10 @@
|
|||||||
(do
|
(do
|
||||||
(gp-advance!)
|
(gp-advance!)
|
||||||
(list :ty-struct (gp-parse-struct-fields)))
|
(list :ty-struct (gp-parse-struct-fields)))
|
||||||
|
(and (= (gp-tok-type) "keyword") (= (gp-tok-value) "interface"))
|
||||||
|
(do
|
||||||
|
(gp-advance!)
|
||||||
|
(list :ty-interface (gp-parse-interface-elems)))
|
||||||
(= (gp-tok-type) "ident")
|
(= (gp-tok-type) "ident")
|
||||||
(let ((name (gp-tok-value)))
|
(let ((name (gp-tok-value)))
|
||||||
(gp-advance!)
|
(gp-advance!)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"language": "go",
|
"language": "go",
|
||||||
"total_pass": 227,
|
"total_pass": 235,
|
||||||
"total": 227,
|
"total": 235,
|
||||||
"suites": [
|
"suites": [
|
||||||
{"name":"lex","pass":129,"total":129,"status":"ok"},
|
{"name":"lex","pass":129,"total":129,"status":"ok"},
|
||||||
{"name":"parse","pass":98,"total":98,"status":"ok"},
|
{"name":"parse","pass":106,"total":106,"status":"ok"},
|
||||||
{"name":"types","pass":0,"total":0,"status":"pending"},
|
{"name":"types","pass":0,"total":0,"status":"pending"},
|
||||||
{"name":"eval","pass":0,"total":0,"status":"pending"},
|
{"name":"eval","pass":0,"total":0,"status":"pending"},
|
||||||
{"name":"runtime","pass":0,"total":0,"status":"pending"},
|
{"name":"runtime","pass":0,"total":0,"status":"pending"},
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
# Go-on-SX Scoreboard
|
# Go-on-SX Scoreboard
|
||||||
|
|
||||||
**Total: 227 / 227 tests passing**
|
**Total: 235 / 235 tests passing**
|
||||||
|
|
||||||
| | Suite | Pass | Total |
|
| | Suite | Pass | Total |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| ✅ | lex | 129 | 129 |
|
| ✅ | lex | 129 | 129 |
|
||||||
| ✅ | parse | 98 | 98 |
|
| ✅ | parse | 106 | 106 |
|
||||||
| ⬜ | types | 0 | 0 |
|
| ⬜ | types | 0 | 0 |
|
||||||
| ⬜ | eval | 0 | 0 |
|
| ⬜ | eval | 0 | 0 |
|
||||||
| ⬜ | runtime | 0 | 0 |
|
| ⬜ | runtime | 0 | 0 |
|
||||||
|
|||||||
@@ -577,6 +577,79 @@
|
|||||||
(list
|
(list
|
||||||
:ty-struct (list (list :field (list "x") (list :ty-name "int")))))))))
|
:ty-struct (list (list :field (list "x") (list :ty-name "int")))))))))
|
||||||
|
|
||||||
|
(go-parse-test
|
||||||
|
"ty: interface {} (empty)"
|
||||||
|
(go-parse "v.(interface {})")
|
||||||
|
(list :assert (ast-var "v") (list :ty-interface (list))))
|
||||||
|
|
||||||
|
(go-parse-test
|
||||||
|
"ty: interface { Close() } (single method, no params, no return)"
|
||||||
|
(go-parse "v.(interface { Close() })")
|
||||||
|
(list
|
||||||
|
:assert (ast-var "v")
|
||||||
|
(list :ty-interface (list (list :method "Close" (list) (list))))))
|
||||||
|
|
||||||
|
(go-parse-test
|
||||||
|
"ty: interface { String() string } (single return)"
|
||||||
|
(go-parse "v.(interface { String() string })")
|
||||||
|
(list
|
||||||
|
:assert (ast-var "v")
|
||||||
|
(list
|
||||||
|
:ty-interface (list (list :method "String" (list) (list (list :ty-name "string")))))))
|
||||||
|
|
||||||
|
(go-parse-test
|
||||||
|
"ty: interface { Read([]byte) (int, error) } (multi return)"
|
||||||
|
(go-parse "v.(interface { Read([]byte) (int, error) })")
|
||||||
|
(list
|
||||||
|
:assert (ast-var "v")
|
||||||
|
(list
|
||||||
|
:ty-interface (list
|
||||||
|
(list
|
||||||
|
:method "Read"
|
||||||
|
(list (list :ty-slice (list :ty-name "byte")))
|
||||||
|
(list (list :ty-name "int") (list :ty-name "error")))))))
|
||||||
|
|
||||||
|
(go-parse-test
|
||||||
|
"ty: interface { Stringer } (embedded interface)"
|
||||||
|
(go-parse "v.(interface { Stringer })")
|
||||||
|
(list
|
||||||
|
:assert (ast-var "v")
|
||||||
|
(list :ty-interface (list (list :embed (list :ty-name "Stringer"))))))
|
||||||
|
|
||||||
|
(go-parse-test
|
||||||
|
"ty: interface { io.Reader } (qualified embedded)"
|
||||||
|
(go-parse "v.(interface { io.Reader })")
|
||||||
|
(list
|
||||||
|
:assert (ast-var "v")
|
||||||
|
(list :ty-interface (list (list :embed (list :ty-sel "io" "Reader"))))))
|
||||||
|
|
||||||
|
(go-parse-test
|
||||||
|
"ty: interface with embed + methods (io.ReadWriter style)"
|
||||||
|
(go-parse "v.(interface { io.Reader; Close() error })")
|
||||||
|
(list
|
||||||
|
:assert (ast-var "v")
|
||||||
|
(list
|
||||||
|
:ty-interface (list
|
||||||
|
(list :embed (list :ty-sel "io" "Reader"))
|
||||||
|
(list :method "Close" (list) (list (list :ty-name "error")))))))
|
||||||
|
|
||||||
|
(go-parse-test
|
||||||
|
"ty: interface with multiple methods"
|
||||||
|
(go-parse "v.(interface { Read([]byte) int; Write([]byte) int; Close() })")
|
||||||
|
(list
|
||||||
|
:assert (ast-var "v")
|
||||||
|
(list
|
||||||
|
:ty-interface (list
|
||||||
|
(list
|
||||||
|
:method "Read"
|
||||||
|
(list (list :ty-slice (list :ty-name "byte")))
|
||||||
|
(list (list :ty-name "int")))
|
||||||
|
(list
|
||||||
|
:method "Write"
|
||||||
|
(list (list :ty-slice (list :ty-name "byte")))
|
||||||
|
(list (list :ty-name "int")))
|
||||||
|
(list :method "Close" (list) (list))))))
|
||||||
|
|
||||||
(go-parse-test "non-primary: '+'" (go-parse "+") nil)
|
(go-parse-test "non-primary: '+'" (go-parse "+") nil)
|
||||||
|
|
||||||
(go-parse-test "non-primary: empty" (go-parse "") nil)
|
(go-parse-test "non-primary: empty" (go-parse "") nil)
|
||||||
|
|||||||
@@ -174,12 +174,13 @@ Progress-log line → push `origin/loops/go`.
|
|||||||
- [x] Type assertion `v.(T)`. `(list :assert OBJ TYPE)`. Includes a
|
- [x] Type assertion `v.(T)`. `(list :assert OBJ TYPE)`. Includes a
|
||||||
minimal `gp-parse-type` (named / qualified `pkg.T` / pointer
|
minimal `gp-parse-type` (named / qualified `pkg.T` / pointer
|
||||||
`*T` / `**T`); full type grammar still pending below.
|
`*T` / `**T`); full type grammar still pending below.
|
||||||
- [/] Type expressions: **slice `[]T`, array `[N]T`, map `map[K]V`, chan
|
- [x] Type expressions: **slice `[]T`, array `[N]T`, map `map[K]V`, chan
|
||||||
`chan T` / `chan<- T` / `<-chan T`, pointer `*T`, named `T`,
|
`chan T` / `chan<- T` / `<-chan T`, pointer `*T`, named `T`,
|
||||||
qualified `pkg.T`, func `func(...) ...`, struct `struct{...}` with
|
qualified `pkg.T`, func `func(...) ...`, struct `struct{...}` with
|
||||||
shared-type field rows (`x, y int`)** all done — kit has no type
|
shared-type field rows (`x, y int`), interface `interface{...}`
|
||||||
primitives. Interface, embedded fields, field tags, variadic,
|
with methods + embedded interfaces (named and qualified)** all
|
||||||
named func-params, generics deferred.
|
done — kit has no type primitives. Field tags, struct embeds,
|
||||||
|
variadic, named func-params, Go 1.18 type sets, generics deferred.
|
||||||
- [ ] Composite literals: `T{...}`, `[]T{...}`, `map[K]V{...}`,
|
- [ ] Composite literals: `T{...}`, `[]T{...}`, `map[K]V{...}`,
|
||||||
`struct{...}{...}`.
|
`struct{...}{...}`.
|
||||||
- [ ] Declarations: `package`, `import`, `var`, `const`, `type`, `func`
|
- [ ] Declarations: `package`, `import`, `var`, `const`, `type`, `func`
|
||||||
@@ -190,8 +191,8 @@ Progress-log line → push `origin/loops/go`.
|
|||||||
- [ ] End-to-end: hello-world, fibonacci, FizzBuzz, goroutine ping-pong,
|
- [ ] End-to-end: hello-world, fibonacci, FizzBuzz, goroutine ping-pong,
|
||||||
struct + method.
|
struct + method.
|
||||||
- **Acceptance:** parse/ suite at 80+ tests. **Acceptance bar crossed:
|
- **Acceptance:** parse/ suite at 80+ tests. **Acceptance bar crossed:
|
||||||
98/98.** Remaining sub-items (interface types, composite literals,
|
106/106.** Remaining sub-items (composite literals, decls, stmts,
|
||||||
decls, stmts, e2e) still keep Phase 2 open ⬜.
|
e2e) still keep Phase 2 open ⬜.
|
||||||
|
|
||||||
### Phase 3 — Bidirectional type checker, MVP (`lib/go/types.sx`) ⬜
|
### Phase 3 — Bidirectional type checker, MVP (`lib/go/types.sx`) ⬜
|
||||||
- **Independent implementation.** Do NOT use lib/guest/static-types-
|
- **Independent implementation.** Do NOT use lib/guest/static-types-
|
||||||
@@ -508,6 +509,18 @@ Minimal repro: see `lib/go/lex.sx#gl-oct-digit?` and `#gl-match-op`.
|
|||||||
|
|
||||||
_Newest first. Append one dated entry per commit._
|
_Newest first. Append one dated entry per commit._
|
||||||
|
|
||||||
|
- 2026-05-27 — Phase 2 cont.: interface-type expressions. `interface {}`,
|
||||||
|
`interface { Close() }`, `interface { String() string }`,
|
||||||
|
`interface { Read([]byte) (int, error) }`, plus embedded interfaces
|
||||||
|
(`Stringer`, `io.Reader`). AST shape:
|
||||||
|
`(list :ty-interface ELEMS)` where each element is either
|
||||||
|
`(list :method NAME PARAMS RESULTS)` or `(list :embed TYPE)`. Method
|
||||||
|
params reuse `gp-parse-func-type-params` — same anonymous-only shape
|
||||||
|
as func types. Go 1.18+ type sets (`~int | ~float64`) deferred to
|
||||||
|
generics work. With this, all Phase-2 **type expressions** are
|
||||||
|
complete. +8 tests, parse 106/106, total 235/235. `[nothing]` — pure
|
||||||
|
Go parser; the field-binding-group kit-gap proposal from the previous
|
||||||
|
commit covers the cross-language angle.
|
||||||
- 2026-05-27 — Phase 2 cont.: struct-type expressions. `struct {}`,
|
- 2026-05-27 — Phase 2 cont.: struct-type expressions. `struct {}`,
|
||||||
`struct { x int }`, `struct { x int; y string }`, `struct { x, y int }`
|
`struct { x int }`, `struct { x int; y string }`, `struct { x, y int }`
|
||||||
(shared type), nested struct fields. `gp-parse-struct-fields` walks
|
(shared type), nested struct fields. `gp-parse-struct-fields` walks
|
||||||
|
|||||||
Reference in New Issue
Block a user