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

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:
2026-05-27 08:16:24 +00:00
parent a94ffa0feb
commit 48379e04bc
5 changed files with 153 additions and 11 deletions

View File

@@ -95,6 +95,58 @@
:else nil)))
(gp-args-rest)
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
gp-parse-struct-fields
;; Caller positioned BEFORE '{'. Parses fields until '}'.
@@ -251,6 +303,10 @@
(do
(gp-advance!)
(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")
(let ((name (gp-tok-value)))
(gp-advance!)

View File

@@ -1,10 +1,10 @@
{
"language": "go",
"total_pass": 227,
"total": 227,
"total_pass": 235,
"total": 235,
"suites": [
{"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":"eval","pass":0,"total":0,"status":"pending"},
{"name":"runtime","pass":0,"total":0,"status":"pending"},

View File

@@ -1,11 +1,11 @@
# Go-on-SX Scoreboard
**Total: 227 / 227 tests passing**
**Total: 235 / 235 tests passing**
| | Suite | Pass | Total |
|---|---|---|---|
| ✅ | lex | 129 | 129 |
| ✅ | parse | 98 | 98 |
| ✅ | parse | 106 | 106 |
| ⬜ | types | 0 | 0 |
| ⬜ | eval | 0 | 0 |
| ⬜ | runtime | 0 | 0 |

View File

@@ -577,6 +577,79 @@
(list
: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: empty" (go-parse "") nil)