go: parse.sx — go/defer/send/for-range + 9 tests [shapes-scheduler]
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's concurrency + iteration primitives to the statement parser:
go EXPR → (list :go EXPR)
defer EXPR → (list :defer EXPR)
ch <- v → (list :send CHAN VALUE)
for range COLL { ... } → (list :range-for nil nil nil COLL BODY)
for k := range C { ... } → (list :range-for :short-decl KEY nil COLL BODY)
for k, v := range C { } → (list :range-for :short-decl KEY VAL COLL BODY)
for k, v = range C { ... } → (list :range-for :assign KEY VAL COLL BODY)
gp-for-find-range pre-scans the for-header (to '{' or eof) looking
for the 'range' keyword; if present, dispatches to gp-parse-for-range
which handles the four range shapes. C-style and while-like and
infinite are now in gp-parse-for-c-style — gp-parse-for is just a
dispatcher.
Send statement detection lives in the LHS-list branch of gp-parse-stmt:
after parsing a single LHS expression, '<-' triggers (:send LHS RHS).
Channel-recv (`<-ch`) was already parsed as unary `<-` in the expression
layer, so both directions cover.
This is the **chiselling-relevant iteration** for the scheduler sister
kit: the AST shapes Go-on-SX will eventually feed into the kit's
scheduler primitives (sched-spawn, sched-defer, chan-op) have landed.
Sister-plan diary updated with three design insights:
* :go / :defer both wrap a single expr — kit's sched-spawn should
accept a thunk uniformly across Erlang's spawn(M,F,A) and Go's
go fn().
* :send carries CHAN+VALUE symmetrically with the unary <- recv —
both reduce to (chan-op direction chan value) in the kit.
* `for v := range ch` uses the same :range-for shape as range-over-
slice; the scheduler kit's range dispatch is where chan-recv ⇄
iteration polymorphism lives.
parse 161/161, total 290/290.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -977,6 +977,76 @@
|
||||
(go-parse "if Foo {}")
|
||||
(list :if (ast-var "Foo") (list :block (list)) nil))
|
||||
|
||||
(go-parse-test
|
||||
"stmt: go f()"
|
||||
(go-parse "go f()")
|
||||
(list :go (ast-app (ast-var "f") (list))))
|
||||
|
||||
(go-parse-test
|
||||
"stmt: go method(x, y)"
|
||||
(go-parse "go obj.method(x, y)")
|
||||
(list
|
||||
:go (ast-app
|
||||
(list :select (ast-var "obj") "method")
|
||||
(list (ast-var "x") (ast-var "y")))))
|
||||
|
||||
(go-parse-test
|
||||
"stmt: defer cleanup()"
|
||||
(go-parse "defer cleanup()")
|
||||
(list :defer (ast-app (ast-var "cleanup") (list))))
|
||||
|
||||
(go-parse-test
|
||||
"stmt: send ch <- v"
|
||||
(go-parse "ch <- 42")
|
||||
(list :send (ast-var "ch") (ast-literal "42")))
|
||||
|
||||
(go-parse-test
|
||||
"for-range: no kv — for range coll { }"
|
||||
(go-parse "for range coll { }")
|
||||
(list :range-for nil nil nil (ast-var "coll") (list :block (list))))
|
||||
|
||||
(go-parse-test
|
||||
"for-range: key only — for k := range m { }"
|
||||
(go-parse "for k := range m { }")
|
||||
(list
|
||||
:range-for :short-decl
|
||||
(ast-var "k")
|
||||
nil
|
||||
(ast-var "m")
|
||||
(list :block (list))))
|
||||
|
||||
(go-parse-test
|
||||
"for-range: k, v := range m"
|
||||
(go-parse "for k, v := range m { }")
|
||||
(list
|
||||
:range-for :short-decl
|
||||
(ast-var "k")
|
||||
(ast-var "v")
|
||||
(ast-var "m")
|
||||
(list :block (list))))
|
||||
|
||||
(go-parse-test
|
||||
"for-range: assign form k = range coll"
|
||||
(go-parse "for k = range coll { }")
|
||||
(list
|
||||
:range-for :assign
|
||||
(ast-var "k")
|
||||
nil
|
||||
(ast-var "coll")
|
||||
(list :block (list))))
|
||||
|
||||
(go-parse-test
|
||||
"concurrency: defer + go in func body"
|
||||
(go-parse "func main() { defer cleanup(); go worker() }")
|
||||
(list
|
||||
:func-decl "main"
|
||||
(list)
|
||||
(list)
|
||||
(list
|
||||
:block (list
|
||||
(list :defer (ast-app (ast-var "cleanup") (list)))
|
||||
(list :go (ast-app (ast-var "worker") (list)))))))
|
||||
|
||||
(go-parse-test "non-primary: '+'" (go-parse "+") nil)
|
||||
|
||||
(go-parse-test "non-primary: empty" (go-parse "") nil)
|
||||
|
||||
Reference in New Issue
Block a user