go: parse.sx — func + method declarations + 8 tests [shapes-static-types-bidirectional]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 28s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 28s
Adds Go func and method declarations:
func main() {}
func add(x, y int) int { return x + y }
func mix(x int, y string) {}
func divmod(a, b int) (int, int) {}
func sig(x int) int (no body)
func (p *Point) String() string { ... } (method, pointer recv)
func (s Stack) Len() int { ... } (method, value recv)
func nested() { if true { x := 1; { y := 2 } } } (nested braces)
New gp-parse-decl-param-group implements named-greedy disambiguation:
collects consecutive 'ident [, ident]*' then parses a type. Anonymous
mixed lists like 'func(int, string)' are a known limitation (parser
treats first ident as a name); flagged in plan.
gp-skip-block! brace-balances over the body; the AST stores ':body'
as a sentinel until statement parsing lands. Methods use the receiver
parameter shape directly.
AST:
(list :func-decl NAME PARAMS RESULTS BODY)
(list :method-decl RECV NAME PARAMS RESULTS BODY)
**All five `:field` binding-group consumers now exist** across the
parser: struct fields, var, const, func params, method receivers.
That's strong cross-deliverable validation of the ast-binding-group
proposal from Blockers — five different declaration contexts, one
shared shape.
This is the chisel-relevant insight for sister plan static-types-
bidirectional: an entry has been appended to its design diary
describing how `:field` will be the load-bearing input shape for
the bidirectional checker's `check Γ e T` judgment across these
contexts.
parse 132/132, total 261/261.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
132
lib/go/parse.sx
132
lib/go/parse.sx
@@ -594,6 +594,133 @@
|
||||
(let ((t (gp-parse-type)))
|
||||
(list :type-decl name t)))
|
||||
:else nil)))
|
||||
(define
|
||||
gp-parse-decl-param-group
|
||||
;; Parses one parameter binding group inside a func decl param list.
|
||||
;; Returns (list :field NAMES TYPE). Named-greedy: collects all
|
||||
;; consecutive idents separated by commas, then a type. Fails for
|
||||
;; mixed anonymous lists like func(int, string) — flagged in plan.
|
||||
(fn
|
||||
()
|
||||
(cond
|
||||
(not (= (gp-tok-type) "ident"))
|
||||
(list :field (list) (gp-parse-type))
|
||||
:else
|
||||
(let ((names (list)) (candidate (gp-tok-value)))
|
||||
(gp-advance!)
|
||||
(define
|
||||
gp-dpg-loop
|
||||
(fn
|
||||
()
|
||||
(when (and (= (gp-tok-type) "op") (= (gp-tok-value) ","))
|
||||
(let ((saved-idx gp-idx))
|
||||
(gp-advance!)
|
||||
(cond
|
||||
(= (gp-tok-type) "ident")
|
||||
(do
|
||||
(append! names candidate)
|
||||
(set! candidate (gp-tok-value))
|
||||
(gp-advance!)
|
||||
(gp-dpg-loop))
|
||||
:else
|
||||
(set! gp-idx saved-idx))))))
|
||||
(gp-dpg-loop)
|
||||
(cond
|
||||
(and (= (gp-tok-type) "op")
|
||||
(or (= (gp-tok-value) ")") (= (gp-tok-value) ",")))
|
||||
(list :field names (list :ty-name candidate))
|
||||
:else
|
||||
(do
|
||||
(append! names candidate)
|
||||
(list :field names (gp-parse-type))))))))
|
||||
(define
|
||||
gp-parse-func-decl-params
|
||||
;; Func-decl parameter list — comma-separated binding groups.
|
||||
;; Caller positioned BEFORE '('. Consumes ')'.
|
||||
(fn
|
||||
()
|
||||
(when (and (= (gp-tok-type) "op") (= (gp-tok-value) "("))
|
||||
(gp-advance!))
|
||||
(let ((groups (list)))
|
||||
(cond
|
||||
(and (= (gp-tok-type) "op") (= (gp-tok-value) ")"))
|
||||
(do (gp-advance!) groups)
|
||||
:else
|
||||
(do
|
||||
(append! groups (gp-parse-decl-param-group))
|
||||
(define
|
||||
gp-fdp-rest
|
||||
(fn
|
||||
()
|
||||
(cond
|
||||
(and (= (gp-tok-type) "op") (= (gp-tok-value) ","))
|
||||
(do
|
||||
(gp-advance!)
|
||||
(append! groups (gp-parse-decl-param-group))
|
||||
(gp-fdp-rest))
|
||||
(and (= (gp-tok-type) "op") (= (gp-tok-value) ")"))
|
||||
(gp-advance!)
|
||||
:else nil)))
|
||||
(gp-fdp-rest)
|
||||
groups)))))
|
||||
(define
|
||||
gp-skip-block!
|
||||
;; Brace-balanced skip. Caller has consumed the opening '{'.
|
||||
;; Statement parsing arrives in a later iteration; for now the
|
||||
;; body is opaque and stored as the keyword :body in the AST.
|
||||
(fn
|
||||
()
|
||||
(let ((depth 1))
|
||||
(define
|
||||
gp-block-loop
|
||||
(fn
|
||||
()
|
||||
(cond
|
||||
(= (gp-tok-type) "eof") nil
|
||||
(and (= (gp-tok-type) "op") (= (gp-tok-value) "{"))
|
||||
(do (set! depth (+ depth 1)) (gp-advance!) (gp-block-loop))
|
||||
(and (= (gp-tok-type) "op") (= (gp-tok-value) "}"))
|
||||
(do
|
||||
(set! depth (- depth 1))
|
||||
(gp-advance!)
|
||||
(when (> depth 0) (gp-block-loop)))
|
||||
:else (do (gp-advance!) (gp-block-loop)))))
|
||||
(gp-block-loop))))
|
||||
(define
|
||||
gp-parse-func-decl
|
||||
;; Caller has consumed 'func'.
|
||||
;; func NAME (params) [results] { body }
|
||||
;; func (recv) NAME (params) [results] { body } — method
|
||||
;; AST:
|
||||
;; (list :func-decl NAME PARAMS RESULTS BODY)
|
||||
;; (list :method-decl RECV NAME PARAMS RESULTS BODY)
|
||||
;; BODY is :body (opaque) if a block was present, else nil.
|
||||
(fn
|
||||
()
|
||||
(let ((recv nil))
|
||||
(when (and (= (gp-tok-type) "op") (= (gp-tok-value) "("))
|
||||
(gp-advance!)
|
||||
(set! recv (gp-parse-decl-param-group))
|
||||
(when (and (= (gp-tok-type) "op") (= (gp-tok-value) ")"))
|
||||
(gp-advance!)))
|
||||
(cond
|
||||
(= (gp-tok-type) "ident")
|
||||
(let ((name (gp-tok-value)))
|
||||
(gp-advance!)
|
||||
(let ((params (gp-parse-func-decl-params)))
|
||||
(let ((results (gp-parse-func-type-results)))
|
||||
(let ((body nil))
|
||||
(when (and (= (gp-tok-type) "op")
|
||||
(= (gp-tok-value) "{"))
|
||||
(gp-advance!)
|
||||
(gp-skip-block!)
|
||||
(set! body :body))
|
||||
(cond
|
||||
(= recv nil)
|
||||
(list :func-decl name params results body)
|
||||
:else
|
||||
(list :method-decl recv name params results body))))))
|
||||
:else nil))))
|
||||
(define
|
||||
gp-parse-decl
|
||||
;; Single declaration: package / import / var / const / type.
|
||||
@@ -625,6 +752,8 @@
|
||||
(do (gp-advance!) (gp-parse-var-or-const :const-decl))
|
||||
(and (= (gp-tok-type) "keyword") (= (gp-tok-value) "type"))
|
||||
(do (gp-advance!) (gp-parse-type-decl))
|
||||
(and (= (gp-tok-type) "keyword") (= (gp-tok-value) "func"))
|
||||
(do (gp-advance!) (gp-parse-func-decl))
|
||||
:else nil)))
|
||||
(define
|
||||
gp-parse-top
|
||||
@@ -641,7 +770,8 @@
|
||||
(= (gp-tok-value) "import")
|
||||
(= (gp-tok-value) "var")
|
||||
(= (gp-tok-value) "const")
|
||||
(= (gp-tok-value) "type")))
|
||||
(= (gp-tok-value) "type")
|
||||
(= (gp-tok-value) "func")))
|
||||
(gp-parse-decl)
|
||||
:else (gp-parse-expr 1))))
|
||||
(gp-parse-top))))
|
||||
|
||||
Reference in New Issue
Block a user