go: parse.sx — func type expressions (anonymous params) + 9 tests [nothing]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 20s

Adds Go func-type parsing to gp-parse-type:
  func()                  →  (list :ty-func () ())
  func() int              →  (list :ty-func () [int])
  func(int, string)       →  (list :ty-func [int string] ())
  func(int) string        →  (list :ty-func [int] [string])
  func() (int, error)     →  (list :ty-func () [int error])

gp-parse-func-type-params handles the param list inside (...);
gp-parse-func-type-results dispatches between bare single-return,
multi-return parenthesised list, or no return.

Anonymous-only — named params (`func(a int, b string)`) require a
different shape and are mainly needed for func DECLARATIONS, not for
pure func-type expressions in type position. Variadic ('...T')
deferred.

Covers nested cases: func returning func, chan of func, func with
pointer/slice operands.

parse 90/90, total 219/219.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 08:06:53 +00:00
parent 8ba66e0dc9
commit 9acdbcb8d8
5 changed files with 147 additions and 8 deletions

View File

@@ -95,6 +95,57 @@
:else nil)))
(gp-args-rest)
args)))))
(define
gp-parse-func-type-params
;; Anonymous-only func-type params: caller is positioned BEFORE
;; the opening "(". Returns a list of type AST nodes.
;; Named params (a int, b string) are deferred — they're needed
;; for func DECLARATIONS, not pure func-type expressions.
(fn
()
(let ((params (list)))
(when (and (= (gp-tok-type) "op") (= (gp-tok-value) "("))
(gp-advance!))
(cond
(and (= (gp-tok-type) "op") (= (gp-tok-value) ")"))
(do (gp-advance!) params)
:else
(do
(let ((first (gp-parse-type)))
(when (not (= first nil)) (append! params first)))
(define
gp-params-rest
(fn
()
(cond
(and (= (gp-tok-type) "op") (= (gp-tok-value) ","))
(do
(gp-advance!)
(let ((t (gp-parse-type)))
(when (not (= t nil)) (append! params t)))
(gp-params-rest))
(and (= (gp-tok-type) "op") (= (gp-tok-value) ")"))
(gp-advance!)
:else nil)))
(gp-params-rest)
params)))))
(define
gp-parse-func-type-results
;; Zero, one, or many return types. Caller is positioned after
;; the closing ')' of params.
;; no return — next token is not a type-starter
;; single return — bare type follows
;; multi return — '(' T, T, ... ')'
(fn
()
(cond
(and (= (gp-tok-type) "op") (= (gp-tok-value) "("))
(gp-parse-func-type-params)
:else
(let ((t (gp-parse-type)))
(cond
(= t nil) (list)
:else (list t))))))
(define
gp-parse-type
;; Go type-expression parser. Covers:
@@ -147,6 +198,12 @@
(and (= (gp-tok-type) "op") (= (gp-tok-value) "<-"))
(do (gp-advance!) (list :ty-chan :send (gp-parse-type)))
:else (list :ty-chan :both (gp-parse-type))))
(and (= (gp-tok-type) "keyword") (= (gp-tok-value) "func"))
(do
(gp-advance!)
(let ((params (gp-parse-func-type-params)))
(let ((results (gp-parse-func-type-results)))
(list :ty-func params results))))
(= (gp-tok-type) "ident")
(let ((name (gp-tok-value)))
(gp-advance!)

View File

@@ -1,10 +1,10 @@
{
"language": "go",
"total_pass": 210,
"total": 210,
"total_pass": 219,
"total": 219,
"suites": [
{"name":"lex","pass":129,"total":129,"status":"ok"},
{"name":"parse","pass":81,"total":81,"status":"ok"},
{"name":"parse","pass":90,"total":90,"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: 210 / 210 tests passing**
**Total: 219 / 219 tests passing**
| | Suite | Pass | Total |
|---|---|---|---|
| ✅ | lex | 129 | 129 |
| ✅ | parse | 81 | 81 |
| ✅ | parse | 90 | 90 |
| ⬜ | types | 0 | 0 |
| ⬜ | eval | 0 | 0 |
| ⬜ | runtime | 0 | 0 |

View File

@@ -436,6 +436,77 @@
:assert (ast-var "v")
(list :ty-ptr (list :ty-slice (list :ty-name "int")))))
(go-parse-test
"ty: func() (no params, no return)"
(go-parse "v.(func())")
(list :assert (ast-var "v") (list :ty-func (list) (list))))
(go-parse-test
"ty: func() int (no params, one return)"
(go-parse "v.(func() int)")
(list
:assert (ast-var "v")
(list :ty-func (list) (list (list :ty-name "int")))))
(go-parse-test
"ty: func(int)"
(go-parse "v.(func(int))")
(list
:assert (ast-var "v")
(list :ty-func (list (list :ty-name "int")) (list))))
(go-parse-test
"ty: func(int, string)"
(go-parse "v.(func(int, string))")
(list
:assert (ast-var "v")
(list
:ty-func (list (list :ty-name "int") (list :ty-name "string"))
(list))))
(go-parse-test
"ty: func(int) string"
(go-parse "v.(func(int) string)")
(list
:assert (ast-var "v")
(list
:ty-func (list (list :ty-name "int"))
(list (list :ty-name "string")))))
(go-parse-test
"ty: func() (int, error) (multi return)"
(go-parse "v.(func() (int, error))")
(list
:assert (ast-var "v")
(list
:ty-func (list)
(list (list :ty-name "int") (list :ty-name "error")))))
(go-parse-test
"ty: func(*T) []int (pointer param, slice return)"
(go-parse "v.(func(*T) []int)")
(list
:assert (ast-var "v")
(list
:ty-func (list (list :ty-ptr (list :ty-name "T")))
(list (list :ty-slice (list :ty-name "int"))))))
(go-parse-test
"ty: func() func() (nested func type as return)"
(go-parse "v.(func() func())")
(list
:assert (ast-var "v")
(list :ty-func (list) (list (list :ty-func (list) (list))))))
(go-parse-test
"ty: chan func() int (chan of func type)"
(go-parse "v.(chan func() int)")
(list
:assert (ast-var "v")
(list
:ty-chan :both
(list :ty-func (list) (list (list :ty-name "int"))))))
(go-parse-test "non-primary: '+'" (go-parse "+") nil)
(go-parse-test "non-primary: empty" (go-parse "") nil)

View File

@@ -176,8 +176,9 @@ Progress-log line → push `origin/loops/go`.
`*T` / `**T`); full type grammar still pending below.
- [/] Type expressions: **slice `[]T`, array `[N]T`, map `map[K]V`, chan
`chan T` / `chan<- T` / `<-chan T`, pointer `*T`, named `T`,
qualified `pkg.T`** all done — kit has no type primitives.
func / struct / interface / generics deferred.
qualified `pkg.T`, func `func(...) ...` (anonymous params, single
or multi return)** all done — kit has no type primitives.
struct / interface / variadic / named-params / generics deferred.
- [ ] Composite literals: `T{...}`, `[]T{...}`, `map[K]V{...}`,
`struct{...}{...}`.
- [ ] Declarations: `package`, `import`, `var`, `const`, `type`, `func`
@@ -188,7 +189,7 @@ Progress-log line → push `origin/loops/go`.
- [ ] End-to-end: hello-world, fibonacci, FizzBuzz, goroutine ping-pong,
struct + method.
- **Acceptance:** parse/ suite at 80+ tests. **Acceptance bar crossed:
81/81.** Remaining sub-items (func/struct/interface types, composite
90/90.** Remaining sub-items (struct/interface types, composite
literals, decls, stmts, e2e) still keep Phase 2 open ⬜.
### Phase 3 — Bidirectional type checker, MVP (`lib/go/types.sx`) ⬜
@@ -491,6 +492,16 @@ Minimal repro: see `lib/go/lex.sx#gl-oct-digit?` and `#gl-match-op`.
_Newest first. Append one dated entry per commit._
- 2026-05-27 — Phase 2 cont.: func-type expressions. `func()`,
`func() int`, `func(int, string)`, `func(int) string`,
`func() (int, error)`. AST shape `(list :ty-func PARAMS RESULTS)`
where both are lists of type nodes. Results parsing reuses param
parser for the multi-return `(T, T, ...)` case. Anonymous-only
params for now — named params (`func(a int, b string)`) need a
different shape and are required mainly for func DECLARATIONS not
pure func-type expressions. Variadic deferred. Covers nested
func-as-return and chan-of-func. +9 tests, parse 90/90, total 219/219.
`[nothing]` — pure Go parser; type AST proposals already in Blockers.
- 2026-05-27 — Phase 2 cont.: type expressions — slice `[]T`, array
`[N]T`, map `map[K]V`, chan in all three directions (`chan T`,
`chan<- T`, `<-chan T`). `gp-parse-type` now dispatches on