On Sun, Sep 4, 2022, at 10:00 AM, Reuben Thomas wrote: > On Sun, 4 Sept 2022 at 10:31, Reuben Thomas <[email protected]> wrote: >> On Sun, 4 Sept 2022 at 04:13, Philip McGrath <[email protected]> >> wrote: >>> >>> However, in some cases you might really want a program other than `racket` >>> as the entry point for your language: for instance, maybe you want to have >>> flags for controlling where the output goes. One example of such a program >>> is the `scribble` executable included in the main Racket distribution. The >>> implementation is in >>> <https://github.com/racket/scribble/blob/master/scribble-lib/scribble/run.rkt>, >>> and the associated "info.rkt" file >>> (<https://github.com/racket/scribble/blob/master/scribble-lib/scribble/info.rkt>) >>> arranges for `raco setup` to create a `scribble` to run it. (This example >>> uses the old mzscheme-launcher-names/mzscheme-launcher-libraries instead of >>> the newer racket-launcher-names/racket-launcher-libraries: see >>> documentation at >>> <https://docs.racket-lang.org/raco/setup-info.html#%28idx._%28gentag._18._%28lib._scribblings%2Fraco%2Fraco..scrbl%29%29%29>.) >> >> Thanks for the pointer. >> >>> It is possible to use Racket to implement languages that don't use #lang, >>> but you would loose many advantages like IDE support and well-defined >>> separate compilation, and you would need to use some fairly low-level >>> mechanisms. Unless there is a hard requirement, I'd recommend that you just >>> use #lang in your programs. >> >> I'm trying to write a standalone assembler (nothing to do with Racket), so >> I'm happy to lose this advantage!
You may indeed want a tool that supports files without #lang if you are working with an existing language and there isn't a way to make the #lang line acceptable to its existing grammar. That's about the only situation I can think of. Almost always, things will work better in the long run if you can make #lang work somehow, even for languages that have "nothing to do with Racket". For example: * Zuo programs start with #lang, even though the primary implementation of `#lang zuo/kernel` is written in C and runs without Racket. (IIUC Sam Tobin-Hochstadt has an almost-complete implementation of zuo/kernel in Racket, but the C implementation is needed to build Racket itself.) See <https://docs.racket-lang.org/zuo/>. * The `jsonic` and BASIC languages from Beautiful Racket have fairly little to do with Racket, but #lang is the basis for the syntax coloring and indentation mechanisms introduced in <https://beautifulracket.com/jsonic-2/drracket-integration.html>. Despite the title of the chapter, this isn't limited to DrRacket: you also get editor support for your language in Emacs' racket-mode, VSCode, and other clients of the Language Server Protocol. (Small caveat: I have not actually read Beautiful Racket, just looked at it admiringly, recommended it to others, and wished MB had written it a year earlier than he did.) > OK, I've had another look, and I still can't see how to do this, so I would > appreciate a hint. I have updated my repo to add a launcher script, but again > this only works with files that have a #lang line. As I said before, I have > worked out how to parse a file without a #lang line (just pass it to my > language's read-syntax), but I can't work out how to turn that into a module > and execute it. I guess I need something like dynamic-require that takes a > syntax-object and an expander module or #%begin-module macro as arguments? For running a file without a #lang, you will need to use `eval`. Probably the right example to follow is the implementation of the plt-r6rs command-line tool (part of the main Racket distribution; source at <https://github.com/racket/r6rs/blob/master/r6rs-lib/r6rs/run.rkt>), which uses `get-module-code` from <https://docs.racket-lang.org/syntax/module-helpers.html#%28def._%28%28lib._syntax%2Fmodcode..rkt%29._get-module-code%29%29> and similar functions to control low-level evaluation and compilation. See more details about plt-r6rs at <https://docs.racket-lang.org/r6rs/Running_Top-Level_Programs.html> and in its --help output. A different way to use eval would be to use `define-namespace-anchor` in the module that provides your hackasm language, explicitly read-syntax the given file, and evaluate the expressions with current-namespace parameterized to a namespace created using namespace-anchor->namespace. Yet another option would be to split your files in two: have files in your language without #lang and separate files in a wrapper #lang that uses include-at/relative-to/reader <https://docs.racket-lang.org/reference/include.html> to get the contents of the non-#lang files. A simple approach would have a wrapper file for every #lang-less file, and it could automatically include a file of the same name but a different extension. More elaborate wrapper languages would also be possible: it could work like a sort of linker specification. I mention this because it can be a useful technique sometimes, though I don't think it's what you want. For an example of how this sort of thing can be useful, see `#lang s-exp srfi/provider`, which simplifies making SRFI libraries available under several different names, for compatibility: it's implemented in <https://github.com/racket/srfi/blob/master/srfi-lite-lib/srfi/provider.rkt> and used e.g. in <https://github.com/racket/srfi/blob/master/srfi-lite-lib/srfi/1.rkt> and <https://github.com/racket/srfi/blob/master/srfi-lib/srfi/%253a63/arrays.rkt>. Hope this helps! -Philip -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/c97601c4-22ae-44d6-a464-30a032fd36fc%40www.fastmail.com.

