I'm working on the Beautiful Racket "wires" DSL without looking at his solution, or using the various br
libraries -- I want to get things working using standard Racket and not rely on BR's syntactic sugar / setup.
I have a macro that correctly expands the DSL code into working Racket code. But I'm struggling with the boilerplate of making the wires
code work with #lang wires
and getting the reader and expander working.
I'm trying to get the simplest, most straightforward way of taking some wires
code with #lang wires
at the top and executing it.
I installed wires
as a package using raco
, but in main.rkt
, I'm struggling with read-syntax
and various module-begin
stuff.
I have this right now:
#lang racket
(require racket/port)
(define (read-syntax path port)
(define src-lines (port->lines port))
(define src-datums
(for/list ([line src-lines ])
(read (open-input-string (format "(wires-operator ~a)" line)))))
(define module-datum `(module wires "main.rkt"
,@src-datums))
(datum->syntax #f module-datum))
(provide read-syntax)
(provide (rename-out [wires-expander %#module-begin]))
(define-syntax-rule (wires-expander EXPR ...)
#'(#%module-begin
(displayln "wires expander ")
EXPR ...))
And in the REPL, if I do (read-syntax "wires-test.rkt" (open-input-file "wires-test.rkt") )
, I get something that looks good:
#<syntax (module wires "main.rkt"
(wires-operator)
(wires-operator)
(wires-operator // I am also allowing comments!)
(wires-operator)
(wires-operator x AND y -> d)
(wires-operator x OR y -> e)
(wires-operator x LSHIFT 2 -> f)
(wires-operator y RSHIFT 2 -> g)
(wires-operator NOT x -> h)
(wires-operator NOT y -> i)
(wires-operator 123 -> x)
(wires-operator 456 -> y))>
(Here wires-operator
is my macro, and it works the want I want for those inputs.)
But if I try to execute that code from the command line, I get:
$ racket wires-test.rkt
module: no #%module-begin binding in the module's language
in: (module wires "main.rkt" (wires-operator ...
I'm confused about all these modules, module-begins, and so on.
- What exactly does
read-syntax
need to put in its output? What kind of module should it output? - How do I provide the expander for that, so Racket can take the
read-syntax
output, run it to convert it into valid Racket code, and execute that? I thought I was doing that with myprovide
.