FIX.org, NEXT.md, DISCUSS.org, docs/DISCUSS.md and the session handoff at the root are one TODO.org now: 293 entries under seven subsystem headings, each carrying an org keyword that says where it stands. A DONE entry is a few lines saying what was decided and what that rules out; the reasoning that would not compress — the embedding spike and the four reports the hand-written x86 backend was built from — moved into docs/BUILT.md instead, and its entries point there in one line. Every entry was checked against the tree before it got a keyword, and the prose was wrong in both directions. Things the deleted files called open were built: the first-evaluation stall, main being redefinable, macro parameter lists, the type-limit constants, the array constructors, the byte fills, inc/dec, the discard's fontification, the Emacs buffers, rt_die's _exit, the backtrace surface, and the acceptance failure that could print and still exit zero. Things they called done were not: the backend reports' no-plan buckets had gone stale in the other direction, the value-dependent defvar was superseded rather than built, and macro-expansion source locations are on an unmerged lane, so that entry is NEXT and names the branch. Every comment that cited one of the five by name now cites a heading that exists, in TODO.org or in docs/BUILT.md. The session reports under docs/handoffs/ keep naming the files they worked on, because rewriting them would falsify what those sessions did; each carries a note saying where the content went.
72 lines
2.9 KiB
Plaintext
72 lines
2.9 KiB
Plaintext
;;;; A macro's parameter list: positional names, [ ] patterns, and &.
|
|
;;;;
|
|
;;;; macros.flan is the other half of this and is deliberately not merged with
|
|
;;;; it: everything there is written [& args] and picks its arguments apart by
|
|
;;;; hand, which is what every macro in the tree looked like before this. Here
|
|
;;;; the parameter list does the picking, and the two files together are the
|
|
;;;; claim that both spellings are the same grammar rather than two.
|
|
;;;;
|
|
;;;; Nothing below checks its own arity. It cannot be reached with the wrong
|
|
;;;; one: lib/expand.ml's check_call runs over the call *before* the macro is
|
|
;;;; expanded, so a miscount is refused at the call with the call's own
|
|
;;;; location — see macro-arity.flan and the three beside it.
|
|
|
|
;; The shape the feature was asked for (TODO.org, "A macro has a parameter list, and [args] is the first argument"):
|
|
;; a binding vector destructured in the signature, and & for the body. Without
|
|
;; a parameter list this is (at args 0), a match on Form.Vec to unwrap it, four
|
|
;; more (at ...) inside that, and (form-rest args 1) for the body.
|
|
(defmacro do-grid [[r rows c cols] & body]
|
|
`(dotimes [~r ~rows]
|
|
(dotimes [~c ~cols]
|
|
~@body)))
|
|
|
|
;; One positional parameter, which is where the grammar changed: [x] used to
|
|
;; bind the whole argument list and now binds the first argument. The gensym is
|
|
;; the ordinary reason it is there — expansion is not hygienic — and not
|
|
;; anything to do with the parameter list.
|
|
(defmacro doubled [x]
|
|
(let [v (gensym)]
|
|
`(let [~v ~x] (+ ~v ~v))))
|
|
|
|
;; Patterns nest, because a pattern's elements are patterns. And & is not only
|
|
;; the top level's: the tail of a pattern is the tail of that vector.
|
|
(defmacro nested [[a [b c]] & body]
|
|
`(do (print ~a) (print ~b) (print ~c) ~@body))
|
|
|
|
;; & inside a pattern, which is the same & and means the same thing one level
|
|
;; down: the tail of the vector written at the call.
|
|
(defmacro first-of [[a & more]]
|
|
`(do (print ~a) ~@more))
|
|
|
|
;; & with nothing after it at the call: the rest is an empty slice, ~@ splices
|
|
;; nothing, and the expansion is the wrapper alone. The arity check says "at
|
|
;; least 1" and one is what this is given.
|
|
(defmacro shout [label & body]
|
|
`(do (print ~label) ~@body (println "!")))
|
|
|
|
;; The whole argument list, which is what [args] used to mean and is now spelled
|
|
;; [& args]. Every macro in the tree was migrated to this line, so it is the
|
|
;; one that has to keep working unchanged.
|
|
(defmacro all-of [& args]
|
|
(if (= (length args) 0)
|
|
`true
|
|
`(if ~(at args 0) (all-of ~@(form-rest args 1)) false)))
|
|
|
|
(defn main [] i32
|
|
(do-grid [i 2 j 3]
|
|
(print i) (print j))
|
|
(println "")
|
|
|
|
(print (doubled 21)) (println "")
|
|
|
|
(nested [1 [2 3]] (println " nested"))
|
|
(first-of [4 (print " and") (println " more")])
|
|
|
|
(shout "alone")
|
|
(shout "with" (print " body"))
|
|
|
|
(print (all-of)) (print " ")
|
|
(print (all-of true true true)) (print " ")
|
|
(print (all-of true false true)) (println "")
|
|
0)
|