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.

Reply via email to