summaryrefslogtreecommitdiff
path: root/html/notes/macros.md
diff options
context:
space:
mode:
Diffstat (limited to 'html/notes/macros.md')
-rw-r--r--html/notes/macros.md151
1 files changed, 0 insertions, 151 deletions
diff --git a/html/notes/macros.md b/html/notes/macros.md
deleted file mode 100644
index 3169c49..0000000
--- a/html/notes/macros.md
+++ /dev/null
@@ -1,151 +0,0 @@
-# Does the decoder implement macros?
-
-I've written about the [parser/decoder dualism](reader.html) in a
-previous article. Long story short, the parser takes care of syntax
-sugar, like turning `#(...)` into `(#HASH ...)`, and the decoder takes
-care of turning that into a vector or whatever.
-
-Now, since the job of the decoder seems superficially quite similar to
-that of a macro expander, I've been agonizing for the past two days or
-so whether it *is* the macro expander.
-
-(Warning: This post is probably going to be very rambly, as I'm trying
-to gather my thoughts by writing it.)
-
-On one hand, sure:
-
- (define-syntax #HASH
- (syntax-rules ()
- (#HASH <element> ...)
- (vector '<element> ...)))
-
-Or something like that. You know what I mean? I mean, in Scheme you
-can't return a vector from a macro, but in Zisp the idea is that you
-can very well do that if you want, because why not.
-
-It's very much possible that I will eventually realize that this is a
-bad idea in some way, but we'll see. So far I really like the idea of
-a macro just returning objects, like a procedure, rather than having
-to return a syntax object that has a binding to that procedure.
-
-This may be similar to John Shutt's "vau calculus" from his language
-Kernel. Maybe Zisp will even end up being an implementation of the
-vau calculus. But I don't know; I've never fully grokked the vau
-calculus, so if I end up implementing it, it will be by accident.
-
-In any case, I want the user to be able to bind transformers to runes,
-and doing so feels like it's pretty much the same thing as defining a
-macro, so maybe the decoder should also be the macro expander.
-
-But then there's an issue with quoting. Consider the following:
-
- (define stuff '(foo #(0 1 2)))
-
-In Zisp, this would first of all be parsed into:
-
- (define stuff (#QUOTE foo (#HASH 0 1 2)))
-
-Now, if #QUOTE didn't decode its operand, we'd end up seeing #HASH in
-the result, never creating the vector we meant to create.
-
-But if #QUOTE calls decode on its operand, and the decoder is also the
-macro expander, whoops:
-
- (let-syntax ((foo (syntax-rules () ((_ x) (bar x)))))
- '(foo #(0 1 2)))
-
- ;; => (bar #(0 1 2))
-
-I mean... MAYBE that should happen, actually?! Probably not, though.
-What Scheme does isn't gospel; Zisp isn't Scheme and it will do some
-things differently, but we *probably* don't want anything inside a
-quoted expression to be macro expanded. Probably.
-
-The thought that I might actually want that to happen sent me down a
-whole rabbit whole, and made me question "runes" altogether. If they
-just make the decoder invoke a predefined macro, well, why not ditch
-runes and have the parser emit macro calls?
-
-So instead of:
-
- #(x y z) -> (#HASH x y z)
-
-(Which is then "decoded" into a vector...) Why not just:
-
- #(x y z) -> (VECTOR x y z)
-
-And then `VECTOR` is, I don't know, a macro in the standard library I
-guess. If the decoder is the macro expander, then sure, it will know
-about the standard library; it will have a full-blown environment that
-it uses to macro expand, to look up macro names.
-
-But no, I think this conflates everything too much. Even just on the
-level of comprehensibility of code containing literals, I think it's
-good for there to be something that you just know will turn into an
-object of some type, no matter what; that's what a literal is.
-
-(In Zisp, it's not the reader that immediately turns the literal into
-an object of the correct type, but the decoder still runs before the
-evaluator so it's almost the same.)
-
-Then again, maybe this intuition just comes from having worked with
-Scheme for such a long time, and maybe it's not good. Perhaps it's
-more elegant if everything is a macro. Don't pile feature on top of
-feature, remember?
-
-Booleans, by the way, would just be identifier syntax then. Just
-`true` and `false` without the hash sign. In Zisp, you can't shadow
-identifiers anyway, so now they're like keywords in other languages,
-also a bit like `t` and `nil` in CL and Elisp.
-
-IF we are fine with the quote issue described above, then I *think*
-everything being a macro would be the right thing to do. Although
-I've said the decoder could be used for things other than code, like
-for configuration files containing user-defined data types, you could
-still do that by defining macros and calling the macro expander on the
-config file.
-
-It's just that you would either not be able to have stuff like vectors
-in a quoted list (you'd just get a list like `(VECTOR ...)` in it if
-you tried), or you'd have to be expanding any macros encountered
-within the quoted list. Either both, or neither.
-
-Not getting a choice, you say... That's not very expressive. That
-seems like a limitation in the language. Remember: remove the
-limitations that make additional features seem necessary.
-
-Next thing we will have two variants of quote: One which quotes for
-real, and one that expands macros. Or maybe some mechanism to mark
-macros as being meant to be run inside a quote or not, but then we
-re-invented runes in a different way.
-
-Which brings me back to runes, and how `#QUOTE` could handle them,
-even if the decoder is the macro expander.
-
-Encountering `#QUOTE` could tell the decoder that while decoding the
-operand, it should only honor runes, not macros bound to identifiers.
-
-That would probably be a fine way to solve the quote problem, should
-the decoder also be the macro expander: Macros are bound to runes or
-identifiers, and the rune-bound macros are those that are expanded
-even inside a quote.
-
-I think that would be the same as having completely separate decode
-and macro-expand phases.
-
-(The reason we would want them merged, by the way, is that it would
-presumably prevent duplication of code, since what they do is so
-similar.)
-
-It's possible that I'm agonizing for no reason at all because maybe
-the decoder cannot be the macro expander anyway.
-
-We will see.
-
-For now, I think it's best to proceed by implementing the decoder, and
-once I've come to the macro expander I can see if it makes sense to
-merge the two or not.
-
-But I'll probably keep runes one way or another, since they're a nice
-way of marking things that should be processed "no matter what" such
-that they can function as object literals within code.