Re: Fwd: [racket-users] Writing a "command-line front-end" for a language

2022-09-08 Thread 'Reuben Thomas' via Racket Users
On Sun, 4 Sept 2022 at 19:39, Philip McGrath 
wrote:

>
> 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 exactly it!


> 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.
>

This is very cool! I didn't know until now. In particular, pleasing to this
Emacs user!

>
>- (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.)
>
> I think I've already said I found it a good introduction; I will reiterate
that recommendation!

Thanks very much for the further advice.

-- 
https://rrt.sc3d.org

-- 
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 
https://groups.google.com/d/msgid/racket-users/CAOnWdogXJ1grax-KJw8SDvmCbEK0QsbrmCvrMt_BJ0ygpv0ApQ%40mail.gmail.com.


Re: Fwd: [racket-users] Writing a "command-line front-end" for a language

2022-09-04 Thread Philip McGrath
On Sun, Sep 4, 2022, at 10:00 AM, Reuben Thomas wrote:
> On Sun, 4 Sept 2022 at 10:31, Reuben Thomas  wrote:
>> On Sun, 4 Sept 2022 at 04:13, Philip McGrath  
>> 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 
>>> ,
>>>  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 
>>> .)
>> 
>> 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 
.
 * 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 
. 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 
), which uses 
`get-module-code` from 

 and similar functions to control low-level evaluation and compilation. See 
more details about plt-r6rs at 
 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 
 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. 

Re: Fwd: [racket-users] Writing a "command-line front-end" for a language

2022-09-04 Thread 'Reuben Thomas' via Racket Users
On Sun, 4 Sept 2022 at 10:31, Reuben Thomas  wrote:

> On Sun, 4 Sept 2022 at 04:13, Philip McGrath 
> 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!
>

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?

-- 
https://rrt.sc3d.org

-- 
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 
https://groups.google.com/d/msgid/racket-users/CAOnWdojuQbYuUAkGmN-thwSzq4iEyV%2BA20QzEj1FxUgoRKr5CA%40mail.gmail.com.


Re: Fwd: [racket-users] Writing a "command-line front-end" for a language

2022-09-04 Thread 'Reuben Thomas' via Racket Users
On Sun, 4 Sept 2022 at 04:13, Philip McGrath 
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!

There are many possible ways to organize this…


Thanks for this, that's exactly what I was after.

-- 
https://rrt.sc3d.org

-- 
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 
https://groups.google.com/d/msgid/racket-users/CAOnWdogTj%3DzMsqCZJhBv%2BiS8zpU2nqETgsiOOt7Wr7aAOmzNzA%40mail.gmail.com.


Re: Fwd: [racket-users] Writing a "command-line front-end" for a language

2022-09-03 Thread Philip McGrath
On Sat, Sep 3, 2022, at 2:09 PM, Shu-Hung You wrote:
> -- Forwarded message -
> From: Shu-Hung You 
> 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 
>
>
> 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: 
https://docs.racket-lang.org/guide/scripts.html

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
>  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
>  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: 
 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