On Sat, Sep 3, 2022, at 2:09 PM, Shu-Hung You wrote:
> ---------- Forwarded message ---------
> From: Shu-Hung You <shh...@u.northwestern.edu>
> Date: Sat, Sep 3, 2022 at 1:03 PM
> Subject: Re: [racket-users] Writing a "command-line front-end" for a language
> To: Reuben Thomas <r...@sc3d.org>
> Running `racket foo.asm` will produce the desired output, so a shell
> script that directly passes the arguments to Racket could work.
> Otherwise, just use (dynamic-require filename #f) in main.rkt.
> At the technical level, foo.asm is in fact an ordinary Racket module,
> just like any other .rkt file. Therefore it can be run in the same way
> using APIs that require and instantiate modules.
> -----------
> On a side note, the forum has mostly moved to Discourse
> (https://racket.discourse.group/).

This is all correct, and you can also make just `./foo.asm` work: 

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 
and the associated "info.rkt" file 
 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 

A couple additional details:

> On Sat, Sep 3, 2022 at 6:01 AM 'Reuben Thomas' via Racket Users
> <racket-users@googlegroups.com> wrote:
>> I have a partial implementation up and running using #lang lines. I would 
>> like to add a more traditional command-line interface, so I can (eventually) 
>> say:
>> hackasm foo.asm
>> on a file without a #lang line.
>> My code is available at https://github.com/rrthomas/hackasm
>> [...]
>> So far, all I've worked out how to do is run the language's read-syntax 
>> function (imported from parser.rkt), and thereby return the parsed syntax 
>> object as the result.
>> What I'd like to do is call the evaluator on the parse tree, but after a lot 
>> of scratching my head over the Racket documentation and search results, I 
>> cannot work out how to do that.

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. For example, the whole family of languages supported by the 
`scribble` command-line tool use #lang. (Indeed, #lang is how the tool can 
support a whole *family* of languages.)

> On Sat, Sep 3, 2022 at 6:01 AM 'Reuben Thomas' via Racket Users
> <racket-users@googlegroups.com> wrote:
>> I have implemented the language as a dialect, so that the "main.rkt" module 
>> is "free" to be used for the command-line interface. (Perhaps this can be 
>> fixed too, that would be nice!)
>> [...]
>> The contents of my main.rkt looks like this:
>> #lang br/quicklang
>> (require "parser.rkt" "tokenizer.rkt" (submod "asm.rkt" reader))
>> (module+ main
>>   (require racket/cmdline)
>>   (let ((filename
>>          (command-line
>>           #:program "hackasm" ;
>>           #:args (filename)
>>           filename)))
>>     (read-syntax filename (open-input-file filename))))

There are many possible ways to organize this: to some extent it's a matter of 
how you expect your language and cli to be used, and to some extent it's a 
matter of taste. I wouldn't consider your current organization "wrong", 
necessarily. But, if you'd like hackasm to be a multi-purpose entry point, one 
way to do that would be:

 1. Move "expander.rkt" to "main.rkt"

 2. Add a reader submodule like the one in "asm.rkt", but using just hackasm 
where you currently have hackasm/expander in the result of read-systax. 
Optionally, you might consider using syntax/module-reader (Guide: 
<https://docs.racket-lang.org/guide/syntax_module-reader.html> Reference: 
 with the #:whole-body-readers? option for your reader submodule.

 3. Add a main submodule like the one in the current version of "main.rkt", but 
implemented more like scribble/run. You might want to write it as `(module* 
main racket/base ...)` unless you want to implement the command line tool in 
your hackasm language.

If you do that, `(require hackasm)`, `(module foo hackasm)` and `#lang hackasm` 
will all access your language, and running the file will run your command-line 

Personally, I might instead combine "expander.rkt" and "asm.rkt" into 
"main.rkt", but put the cli tool in "cli.rkt". The name you give the tool via 
racket-launcher-names doesn't have to match the file name of the 
implementation, and I might find it easier to experiment with the language in 
DrRacket if the tool were separate. But it all depends on what seems most 
useful to you and your users.


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 racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 

Reply via email to