go: types.sx — func-decl + stmt-level dispatch + 7 tests [nothing]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 31s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 31s
Phase 3 cont. Adds:
* go-check-func-decl — binds the function in the outer ctx (recursive
self-reference will work once call-checking lands), extends the
body's ctx with each :field param group via go-ctx-extend-field
(the binding-group shape's *third* consumer in the type checker;
five total across parser+typer when counted with struct fields,
var-decls, const-decls, func params, method receivers).
* go-check-stmt — dispatches on :return / :assign / :var-decl /
:const-decl / :short-decl / :type-decl / :block; falls back to
go-synth for expression statements.
* go-check-block — threads ctx through stmts so that decls inside
the block extend the ctx for subsequent stmts.
* go-check-return-list — each return expr assignable to the
corresponding declared result type; mismatch counts are typed.
* go-check-assign / go-check-assign-pairs — RHS assignable to LHS
synthesised type, count mismatch typed.
* Helpers: go-decl-params-to-ty-list (flattens :field NAMES TYPE to
a flat list of N types), go-extend-with-params (folds extend-field
over a param-group list), go-repeat-ty.
Coverage tests:
func empty() {} → ok
func add(x, y int) int { return x + y } → ok
func bad() int { return "hi" } → typed error
func sig(x int) int → signature-only binds
func sumsq(x, y int) int { return x*x + y*y } → params visible
func two() int { var x int = 1; var y int = 2; → nested decl
return x + y }
func g() int { var x int; x = 5; return x } → assign verified
types 47/47, total 352/352.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"language": "go",
|
||||
"total_pass": 345,
|
||||
"total": 345,
|
||||
"total_pass": 352,
|
||||
"total": 352,
|
||||
"suites": [
|
||||
{"name":"lex","pass":129,"total":129,"status":"ok"},
|
||||
{"name":"parse","pass":176,"total":176,"status":"ok"},
|
||||
{"name":"types","pass":40,"total":40,"status":"ok"},
|
||||
{"name":"types","pass":47,"total":47,"status":"ok"},
|
||||
{"name":"eval","pass":0,"total":0,"status":"pending"},
|
||||
{"name":"runtime","pass":0,"total":0,"status":"pending"},
|
||||
{"name":"stdlib","pass":0,"total":0,"status":"pending"},
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Go-on-SX Scoreboard
|
||||
|
||||
**Total: 345 / 345 tests passing**
|
||||
**Total: 352 / 352 tests passing**
|
||||
|
||||
| | Suite | Pass | Total |
|
||||
|---|---|---|---|
|
||||
| ✅ | lex | 129 | 129 |
|
||||
| ✅ | parse | 176 | 176 |
|
||||
| ✅ | types | 40 | 40 |
|
||||
| ✅ | types | 47 | 47 |
|
||||
| ⬜ | eval | 0 | 0 |
|
||||
| ⬜ | runtime | 0 | 0 |
|
||||
| ⬜ | stdlib | 0 | 0 |
|
||||
|
||||
@@ -264,6 +264,68 @@
|
||||
(list (go-ctx-lookup ctx "a") (go-ctx-lookup ctx "b")))
|
||||
(list (list :ty-name "int") (list :ty-name "int")))
|
||||
|
||||
(go-types-test
|
||||
"fdecl: func empty() — binds empty to func type"
|
||||
(go-ctx-lookup
|
||||
(go-check-decl go-ctx-empty (go-parse "func empty() {}"))
|
||||
"empty")
|
||||
(list :ty-func (list) (list)))
|
||||
|
||||
(go-types-test
|
||||
"fdecl: func add(x, y int) int { return x + y } — ok"
|
||||
(go-ctx-lookup
|
||||
(go-check-decl
|
||||
go-ctx-empty
|
||||
(go-parse "func add(x, y int) int { return x + y }"))
|
||||
"add")
|
||||
(list
|
||||
:ty-func (list (list :ty-name "int") (list :ty-name "int"))
|
||||
(list (list :ty-name "int"))))
|
||||
|
||||
(go-types-test
|
||||
"fdecl: func bad() int { return \"hi\" } — type error"
|
||||
(go-check-decl go-ctx-empty (go-parse "func bad() int { return \"hi\" }"))
|
||||
(list
|
||||
:type-error :mismatch
|
||||
(list :ty-name "int")
|
||||
(list :ty-untyped-string)))
|
||||
|
||||
(go-types-test
|
||||
"fdecl: signature-only (no body)"
|
||||
(go-ctx-lookup
|
||||
(go-check-decl go-ctx-empty (go-parse "func sig(x int) int"))
|
||||
"sig")
|
||||
(list :ty-func (list (list :ty-name "int")) (list (list :ty-name "int"))))
|
||||
|
||||
(go-types-test
|
||||
"fdecl: param-bound — body sees x and y"
|
||||
(go-ctx-lookup
|
||||
(go-check-decl
|
||||
go-ctx-empty
|
||||
(go-parse "func sumsq(x, y int) int { return x*x + y*y }"))
|
||||
"sumsq")
|
||||
(list :ty-func
|
||||
(list (list :ty-name "int") (list :ty-name "int"))
|
||||
(list (list :ty-name "int"))))
|
||||
|
||||
(go-types-test
|
||||
"fdecl: nested decl in body extends ctx for later stmts"
|
||||
(go-ctx-lookup
|
||||
(go-check-decl
|
||||
go-ctx-empty
|
||||
(go-parse "func two() int { var x int = 1; var y int = 2; return x + y }"))
|
||||
"two")
|
||||
(list :ty-func (list) (list (list :ty-name "int"))))
|
||||
|
||||
(go-types-test
|
||||
"fdecl: assign inside body — type-checks RHS vs LHS"
|
||||
(go-ctx-lookup
|
||||
(go-check-decl
|
||||
go-ctx-empty
|
||||
(go-parse "func g() int { var x int; x = 5; return x }"))
|
||||
"g")
|
||||
(list :ty-func (list) (list (list :ty-name "int"))))
|
||||
|
||||
(define
|
||||
go-types-test-summary
|
||||
(str "types " go-types-test-pass "/" go-types-test-count))
|
||||
|
||||
144
lib/go/types.sx
144
lib/go/types.sx
@@ -415,4 +415,148 @@
|
||||
(and (list? decl) (= (first decl) :type-decl))
|
||||
(let ((name (nth decl 1)) (ty (nth decl 2)))
|
||||
(go-ctx-extend ctx name ty))
|
||||
(and (list? decl) (= (first decl) :func-decl))
|
||||
(go-check-func-decl ctx decl)
|
||||
:else ctx)))
|
||||
|
||||
;; ── function-decl checking ──────────────────────────────────────
|
||||
|
||||
(define
|
||||
go-repeat-ty
|
||||
(fn (n ty acc)
|
||||
(cond
|
||||
(<= n 0) acc
|
||||
:else (go-repeat-ty (- n 1) ty (cons ty acc)))))
|
||||
|
||||
(define
|
||||
go-decl-params-to-ty-list
|
||||
;; Flatten (:field NAMES TYPE) param groups into a list of types,
|
||||
;; one entry per name. For func-type signatures.
|
||||
(fn (params)
|
||||
(cond
|
||||
(or (= params nil) (= (len params) 0)) (list)
|
||||
:else
|
||||
(let ((field (first params)))
|
||||
(let ((names (nth field 1)) (ty (nth field 2)))
|
||||
(let ((rest-tys (go-decl-params-to-ty-list (rest params))))
|
||||
(go-repeat-ty (len names) ty rest-tys)))))))
|
||||
|
||||
(define
|
||||
go-extend-with-params
|
||||
;; Extend CTX with every binding in every (:field NAMES TYPE) param group.
|
||||
(fn (ctx params)
|
||||
(cond
|
||||
(or (= params nil) (= (len params) 0)) ctx
|
||||
:else
|
||||
(go-extend-with-params
|
||||
(go-ctx-extend-field ctx (first params))
|
||||
(rest params)))))
|
||||
|
||||
(define
|
||||
go-check-return-list
|
||||
;; Each EXPR assignable to the corresponding RESULTS type.
|
||||
;; v0: lengths must match; multi-return funcs deferred.
|
||||
(fn (ctx exprs results)
|
||||
(cond
|
||||
(and (= (len exprs) 0) (= (len results) 0)) :ok
|
||||
(not (= (len exprs) (len results)))
|
||||
(list :type-error :return-count-mismatch
|
||||
(len exprs) (len results))
|
||||
:else
|
||||
(let ((r (go-check ctx (first exprs) (first results))))
|
||||
(cond
|
||||
(go-type-error? r) r
|
||||
:else (go-check-return-list ctx (rest exprs) (rest results)))))))
|
||||
|
||||
(define
|
||||
go-check-assign
|
||||
(fn (ctx stmt)
|
||||
(let ((lhs-list (nth stmt 1)) (rhs-list (nth stmt 2)))
|
||||
(cond
|
||||
(not (= (len lhs-list) (len rhs-list)))
|
||||
(list :type-error :assign-count-mismatch
|
||||
(len lhs-list) (len rhs-list))
|
||||
:else (go-check-assign-pairs ctx lhs-list rhs-list)))))
|
||||
|
||||
(define
|
||||
go-check-assign-pairs
|
||||
(fn (ctx lhs-list rhs-list)
|
||||
(cond
|
||||
(= (len lhs-list) 0) :ok
|
||||
:else
|
||||
(let ((lhs-ty (go-synth ctx (first lhs-list))))
|
||||
(cond
|
||||
(go-type-error? lhs-ty) lhs-ty
|
||||
:else
|
||||
(let ((r (go-check ctx (first rhs-list) lhs-ty)))
|
||||
(cond
|
||||
(go-type-error? r) r
|
||||
:else
|
||||
(go-check-assign-pairs ctx (rest lhs-list)
|
||||
(rest rhs-list)))))))))
|
||||
|
||||
(define
|
||||
go-check-stmt
|
||||
;; Returns either an extended CTX (decls), :ok (sealed stmts), or
|
||||
;; :type-error. RESULTS is the enclosing func's declared return types
|
||||
;; (used by :return).
|
||||
(fn (ctx stmt results)
|
||||
(cond
|
||||
(and (list? stmt) (= (first stmt) :var-decl))
|
||||
(go-check-decl ctx stmt)
|
||||
(and (list? stmt) (= (first stmt) :const-decl))
|
||||
(go-check-decl ctx stmt)
|
||||
(and (list? stmt) (= (first stmt) :short-decl))
|
||||
(go-check-decl ctx stmt)
|
||||
(and (list? stmt) (= (first stmt) :type-decl))
|
||||
(go-check-decl ctx stmt)
|
||||
(and (list? stmt) (= (first stmt) :return))
|
||||
(let ((exprs (nth stmt 1)))
|
||||
(let ((err (go-check-return-list ctx exprs results)))
|
||||
(cond (go-type-error? err) err :else ctx)))
|
||||
(and (list? stmt) (= (first stmt) :block))
|
||||
(let ((err (go-check-block ctx (nth stmt 1) results)))
|
||||
(cond (go-type-error? err) err :else ctx))
|
||||
(and (list? stmt) (= (first stmt) :assign))
|
||||
(let ((err (go-check-assign ctx stmt)))
|
||||
(cond (go-type-error? err) err :else ctx))
|
||||
:else
|
||||
(let ((t (go-synth ctx stmt)))
|
||||
(cond (go-type-error? t) t :else ctx)))))
|
||||
|
||||
(define
|
||||
go-check-block
|
||||
;; Thread ctx through stmts; if any stmt is a decl, its extension
|
||||
;; propagates to subsequent stmts. Returns :ok or :type-error.
|
||||
(fn (ctx stmts results)
|
||||
(cond
|
||||
(or (= stmts nil) (= (len stmts) 0)) :ok
|
||||
:else
|
||||
(let ((r (go-check-stmt ctx (first stmts) results)))
|
||||
(cond
|
||||
(go-type-error? r) r
|
||||
:else (go-check-block r (rest stmts) results))))))
|
||||
|
||||
(define
|
||||
go-check-func-decl
|
||||
;; Bind the function in the outer ctx (so recursion works), extend
|
||||
;; ctx with params, check the body. Returns the outer ctx with the
|
||||
;; function bound, or :type-error.
|
||||
(fn (ctx decl)
|
||||
(let ((name (nth decl 1)) (params (nth decl 2))
|
||||
(results (nth decl 3)) (body (nth decl 4)))
|
||||
(let ((fn-ty
|
||||
(list :ty-func
|
||||
(go-decl-params-to-ty-list params) results)))
|
||||
(let ((ctx-with-fn (go-ctx-extend ctx name fn-ty)))
|
||||
(cond
|
||||
(= body nil) ctx-with-fn
|
||||
(and (list? body) (= (first body) :block))
|
||||
(let ((body-ctx
|
||||
(go-extend-with-params ctx-with-fn params)))
|
||||
(let ((err
|
||||
(go-check-block body-ctx (nth body 1) results)))
|
||||
(cond
|
||||
(go-type-error? err) err
|
||||
:else ctx-with-fn)))
|
||||
:else ctx-with-fn))))))
|
||||
|
||||
@@ -234,8 +234,11 @@ Progress-log line → push `origin/loops/go`.
|
||||
the extended context or a `:type-error`. Untyped synthesized types
|
||||
get their default-type (`untyped-int → int`, `untyped-float →
|
||||
float64`, etc.) when bound in inferred-type decls.
|
||||
- [ ] Function declaration: extend ctx with params via `:field` group,
|
||||
check body, verify return-list types match signature.
|
||||
- [x] Function declaration: extends ctx with each `:field` param group,
|
||||
checks block body (decls thread through, returns verify against
|
||||
signature, assignments verify RHS assignable to LHS). The function
|
||||
itself is bound in the body's ctx so recursion will work once
|
||||
call-checking lands. Signature-only (no body) just binds.
|
||||
- [ ] Call type-checking (synth callee, check args against param types,
|
||||
synth result).
|
||||
- [ ] Composite type element checking (slice / map / chan).
|
||||
@@ -243,7 +246,7 @@ Progress-log line → push `origin/loops/go`.
|
||||
- [ ] Short variable declaration `:=` (synth RHS into LHS bindings).
|
||||
- Defer: generics (Phase 7), full conversion rules, type assertions,
|
||||
type switches.
|
||||
- **Acceptance:** types/ suite at 60+ tests. Current: 40/40. Chisel note
|
||||
- **Acceptance:** types/ suite at 60+ tests. Current: 47/47. Chisel note
|
||||
`shapes-static-types-bidirectional` — sister-plan design diary is the
|
||||
cross-language record.
|
||||
|
||||
@@ -544,6 +547,19 @@ 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 3 cont.: function-declaration checking +
|
||||
statement-level dispatch. `go-check-func-decl` binds the function in
|
||||
the outer ctx (so the body can see itself), extends the body's ctx
|
||||
with each `:field` param group via `go-ctx-extend-field` (the
|
||||
binding-group shape's third consumer in the type checker — now
|
||||
five total across parser+typer combined), then runs `go-check-block`
|
||||
through every statement. `go-check-stmt` dispatches on `:return`,
|
||||
`:assign`, `:var-decl`/`:const-decl`/`:short-decl`/`:type-decl`,
|
||||
`:block`, falling back to `go-synth` for expression statements.
|
||||
Return-list and assign-pair count mismatches are typed errors. +7
|
||||
tests, types 47/47, total 352/352. `[nothing]` — pure Go-side
|
||||
composition; the kit-relevant insights are already in the sister-
|
||||
plan diary.
|
||||
- 2026-05-27 — Phase 3 cont.: declaration checking — `var`/`const`/`type`
|
||||
+ short-decl `:=`. `go-check-decl` returns the extended context (or a
|
||||
`:type-error`). New helpers: `go-default-type` (untyped-int → int,
|
||||
|
||||
Reference in New Issue
Block a user