I am using Beautiful Racket to draft a new DSL, bleir, based on s-expressions. I first install a new racket package using the Master Recipe.
raco pkg new bleir
cd bleir
raco pkg install
I then set up a vestigial reader and expander in the madatory file, main.rkt:
#lang br/quicklang
(module+ reader
(provide read-syntax)
(require br/quicklang))
(provide (rename-out [bleir-expander #%module-begin]))
(define-macro (bleir-expander PARSE-TREE)
#'(#%module-begin
(display PARSE-TREE)))
I then write a test file, tyst-bleir.rkt [intentional misspelling, to sidestep potential problems with the string name "test"]:
#lang bleir
42
I get a problem:
Module Language: only a module expression is allowed, either #lang <language-name> or (module <name> <language> ...) in: 42
I can fix it in two ways, "disgusting" and "mysterious". First, the disgusting fix, in tyst-bleir.rkt:
(module tyst-bleir bleir
42)
This works, invoking both the doubly exported reader from br/quicklang and my custom expander, displaying 42.
QUESTION 1: the #lang bleir syntax is supposed to be identical to the verbose (module ...) syntax is it not? Why does #lang bleir not work to import the reader from br/quicklang?
Now, the mysterious fix:
#lang s-exp bleir
42
This evidently uses an alternative s-exp reader from module (package?) s-exp and it's ok, I guess. At least I'm not blocked. HOWEVER, I do not understand why I can't use the reader from br/quicklang in the same way.
#lang br/quicklang bleir
42
bleir: unbound identifier in: bleir
QUESTION 2: Why doesn't this work? Can I fix it? If so, how?
Here is another failed attempt, going the other way, trying to import the reader from s-exp in main-rkt:
(module+ reader
(provide read-syntax)
(require s-exp))
main.rkt:11:11: cannot open module file module path: s-exp path: /usr/share/racket/collects/s-exp/main.rkt system error: no such file or directory; rkt_err=3 in: s-exp no package suggestions are available .
QUESTION 3: Why doesn't this work? Can I fix it? If so, how?
Question 1
You didn't fully follow the master recipe that you reference. If you continue reading, you will see:
In other words, your
read-syntaxneeds to return(strip-bindings #'(module ...)).Question 2
I think you are confusing "languages that users use" and "languages that language designers use" together.
"languages that users use" are something like
#lang bleir,#lang slideshow,#lang pollen, etc. These languages provide constructs to do domain-specific tasks. For example,#lang slideshowis a language for creating presentations.#lang pollenis a language for creating books."languages that language designers use" are a kind of "languages that users use", where the users are language designers. These languages provide constructs to make language creation easier.
#lang br/quicklangis in this category.So you, as a language designer, would use
#lang br/quicklanginternally in yourbleir/main.rktfor constructing a languagebleir. But your users, who are not language designers, should not need to write (or even be aware of)#lang br/quicklang.The master recipe talks about two things: the reader and the expander. In a fully developed language, you would provide both the reader and the expander.
s-expcan be seen as a convenient hack language to "run" non-fully developed languages that only have the expander, but don't have the reader yet.So, the reason why
#lang s-exp bleirworks is that you have a functioning expander, so#lang s-exp bleiruses your expander but completely ignores yourreadersubmodule. The reason why#lang bleirdoesn't work is that yourreadersubmodule is buggy (see Question 1). The reason why#lang br/quicklang bleirdoesn't work is that it doesn't make any sense for users to write#lang br/quicklang.I suggest that you simply forget about
s-expand fix your reader. AFAIK, Beautiful Racket didn't really talk abouts-exp, and if you are following the book, usings-expwill simply make you confused.Question 3
If you want a technical answer, https://docs.racket-lang.org/guide/hash-lang_syntax.html (or more generally https://docs.racket-lang.org/reference/reader.html#%28part._parse-reader%29) answers your question: