This is related to my struggles with getting a new #lang
to work. I've discovered a bug in my code, but I am not sure how to modify my macro to make it work as expected.
The key parts of my macro and supporting code are:
(define-syntax wires-operator
;; literals:
(syntax-rules (AND OR LSHIFT RSHIFT NOT -> // SHOW)
[(wires-operator lhs OR rhs -> dest)
(define (dest) (wires-or (lhs) (rhs)))]
[(wires-operator input -> dest)
(define (dest) input)]
[(wires-operator SHOW wire)
(printf "wire ~s = ~s\n" (object-name wire)
(if (number? wire)
wire
(wire)))]
))
(define (wires-or x y) (bitwise-ior x y))
and it's expanding something like this:
(wires-operator 5 -> a)
(wires-operator a -> b)
(wires-operator 15 OR a -> c)
(wires-operator SHOW a)
(wires-operator SHOW b)
(wires-operator SHOW c)
the SHOW a
works fine. But the SHOW b
results in wire b = #<procedure:a>
.
Okay, so I need to detect whether I have a number or a function that I need to evaluate. That's what the printf
is trying to do.
I know that the problem here is related to pattern variables or macro hygiene or compile-time versus run-time, but I don't know what I don't know.
The OR
also fails, but more dramatically: the 15 OR a -> c
results in:
application: not a procedure;
expected a procedure that can be applied to arguments
given: 15
And I understand what's going wrong: it's trying to evaluate something like (15).
This is confusing. It seems like:
- the
printf
thinks that(number? wire)
is true, but it's a function and prints that way! - the
OR
expansion tries to expand something equivalent to(15)
and of course fails.
So my macro needs to either (1) figure out at compile-time whether the actual text of the pattern variable is a numerical constant or some sequence of letters, or (2) expand into something that will do the same at run-time.
How can I do that?