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 [email protected].
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. I

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 [email protected].
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 [email protected].
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 command-lin