go: parse.sx — type assertion v.(T) + minimal type parser + 9 tests [nothing]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 18s

Postfix '.' branch now peeks at the next token to disambiguate:
  .ident   →  selector / member access  (list :select OBJ "field")
  .(TYPE)  →  type assertion            (list :assert OBJ TYPE)

New gp-parse-type covers the minimum types needed for assertions:
  name        →  (list :ty-name "int")
  pkg.Name    →  (list :ty-sel "pkg" "Name")
  *T  / **T   →  (list :ty-ptr (list :ty-ptr ...))

Full type grammar — slice []T, array [N]T, map[K]V, chan, func,
struct, interface — is a separate Phase 2 sub-deliverable.

Type AST shapes are Go-specific tagged lists; the canonical AST kit
has no type-system primitives at all yet. Worth a richer kit
discussion once Phase 3 (bidirectional type checker) lands and the
sister plan static-types-bidirectional has a real surface to react to.

parse 70/70, total 199/199.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 07:57:29 +00:00
parent e64d72f554
commit 503bdf12d6
5 changed files with 116 additions and 10 deletions

View File

@@ -95,6 +95,36 @@
:else nil)))
(gp-args-rest)
args)))))
(define
gp-parse-type
;; Minimal type-expression parser. This iteration handles:
;; *T → (list :ty-ptr T)
;; name → (list :ty-name "name")
;; pkg.Name → (list :ty-sel "pkg" "Name")
;; Full type grammar (slice, array, map, chan, func, struct,
;; interface) is a separate Phase 2 sub-deliverable.
(fn
()
(cond
(and (= (gp-tok-type) "op") (= (gp-tok-value) "*"))
(do
(gp-advance!)
(list :ty-ptr (gp-parse-type)))
(= (gp-tok-type) "ident")
(let ((name (gp-tok-value)))
(gp-advance!)
(cond
(and (= (gp-tok-type) "op") (= (gp-tok-value) "."))
(do
(gp-advance!)
(cond
(= (gp-tok-type) "ident")
(let ((sel-name (gp-tok-value)))
(gp-advance!)
(list :ty-sel name sel-name))
:else (list :ty-name name)))
:else (list :ty-name name)))
:else nil)))
(define
gp-parse-bracket-expr
;; Optional expression inside brackets — returns nil if next token
@@ -159,13 +189,24 @@
(and (= (get tok :type) "op") (= (get tok :value) "."))
(do
(gp-advance!)
(let ((field-tok (gp-cur)))
(let ((next-tok (gp-cur)))
(cond
(= (get field-tok :type) "ident")
;; .(T) — type assertion
(and (= (get next-tok :type) "op")
(= (get next-tok :value) "("))
(do
(gp-advance!)
(let ((ty (gp-parse-type)))
(when (and (= (gp-tok-type) "op")
(= (gp-tok-value) ")"))
(gp-advance!))
(gp-postfix-loop (list :assert base ty))))
;; .ident — selector / member access
(= (get next-tok :type) "ident")
(do
(gp-advance!)
(gp-postfix-loop
(list :select base (get field-tok :value))))
(list :select base (get next-tok :value))))
:else base)))
(and (= (get tok :type) "op") (= (get tok :value) "("))
(do