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

2022-09-08 Thread 'Reuben Thomas' via Racket Users
On Mon, 5 Sept 2022 at 02:20, Shu-Hung You 
wrote:

>
> Okay, if you want to bypass the #lang protocol entirely, here is the
> needed code. As you have expected, it uses eval and then calls
> dynamic-require.
>

Thanks very much for this code and detailed explanation, that was a great
help.

-- 
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/CAOnWdojbFzJeD63jKeciqY0Zqq7WdXB5v%2B__qpwH2N9uEEJHFQ%40mail.gmail.com.


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

2022-09-04 Thread Shu-Hung You
On Sun, Sep 4, 2022 at 4:21 AM Reuben Thomas  wrote:
>
> On Sat, 3 Sept 2022 at 19:10, Shu-Hung You  wrote:
>>
>> 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.
>
>
> Thanks for helping!
>
> Don't both of these methods require a #lang line in the input file? That's 
> not part of the assembly format, so I want to be able to specify the language 
> in the main module. Indeed, when I try it with a file with a #lang line, 
> dynamic-require works; when I remove that line, I get an error about a 
> missing module declaration (no surprise). I can see an obvious workaround, 
> namely to slurp the file and prepend a module declaration before 
> dynamic-requiring it, but that's ugly.
>
> So it seems that in fact what I want is to call something like 
> dynamic-require with a module object. But I'm not sure what to call or how to 
> get one of those: read-syntax returns a syntax object, not a module, while I 
> don't (yet) know how to apply my expander's #%module-begin to it to obtain a 
> module.
>

Okay, if you want to bypass the #lang protocol entirely, here is the
needed code. As you have expected, it uses eval and then calls
dynamic-require.

diff --git a/asm.rkt b/asm.rkt
index f2f1e89..4d024d8 100644
--- a/asm.rkt
+++ b/asm.rkt
@@ -6,6 +6,7 @@

 (define (read-syntax path port)
   (define parse-tree (parse path (make-tokenizer port path)))
-  (strip-bindings
-   #`(module hackasm-mod hackasm/expander
-   #,parse-tree)))
+  (datum->syntax
+   #f
+   `(,#'module hackasm-mod hackasm/expander
+  ,parse-tree)))
diff --git a/main.rkt b/main.rkt
index 9f2af0b..9cccf22 100644
--- a/main.rkt
+++ b/main.rkt
@@ -8,4 +8,6 @@
   #:program "hackasm" ; FIXME: get name from project
   #:args (filename)
   filename)))
-(dynamic-require filename #f)))
\ No newline at end of file
+(parameterize ([current-namespace (make-base-empty-namespace)])
+  (eval (read-syntax filename (open-input-file filename)))
+  (dynamic-require '(quote hackasm-mod) #f

There are two technical details. The eval function takes pretty much
everything --- plain values, syntax objects, or just S-expressions,
etc. For eval, the difference between syntax objects and S-expressions
is that syntax objects carry binding information with them, therefore
eval can correctly run the code without the risk of misinterpreting
identifiers. The syntax object that your read-syntax returns is almost
runnable, so I use eval to evaluate the resulting module form (i.e.
#'(module hackasm-mod hackasm/expander ...)). This will declare a
module called ‘hackasm-mod’ together with its code in the current
namespace's module registry. Subsequently, dynamic-require
instantiates the module ‘hackasm-mod’ to run its body. The reference
https://docs.racket-lang.org/reference/module.html#%28form._%28%28quote._~23~25kernel%29._module%29%29
specifies what evaluating a module form results in (search for
"evaluation"). In dynamic-require, the module path (quote hackasm-mod)
refers to the module declared with the name ‘hackasm-mod’. In the more
common cases, module paths would be complete file paths. The page
https://docs.racket-lang.org/guide/module-paths.html explains the
syntax of module paths.

In the original read-syntax, I suppose strip-bindings removes all
binding information associated with the given syntax objects.
Consequently, eval would fail to interpret the resulting module form
because the "module" identifier in it is unbound and thus has no
meaning. To fix the issue, I explicitly use the #'module identifier
found in asm.rkt (which is the Racket binding of ‘module’, brought
into context by #lang br/quicklang). Then datum->syntax turns the
entire list into a syntax object with no binding information.
Equivalently, instead of changing read-syntax you can manually fix the
#'module identifier before `eval` using the low-level APIs syntax-e
and datum->syntax.

>> 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.
>
>
> Right! That's what I've obviously not fully understood yet.
>
> (Thanks for the side node about moving to Discourse—it's a while since I've 
> been active on the list!)
>
> --
> 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/CAMTzy%2BavnPCDvR8wHN3O_9BgnpQK%2BtamD9PqmBwd%2B9j-YGHUqg%40mail.gmail.com.


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

2022-09-04 Thread 'Reuben Thomas' via Racket Users
On Sat, 3 Sept 2022 at 19:10, Shu-Hung You 
wrote:

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

Thanks for helping!

Don't both of these methods require a #lang line in the input file? That's
not part of the assembly format, so I want to be able to specify the
language in the main module. Indeed, when I try it with a file with a #lang
line, dynamic-require works; when I remove that line, I get an error about
a missing module declaration (no surprise). I can see an obvious
workaround, namely to slurp the file and prepend a module declaration
before dynamic-requiring it, but that's ugly.

So it seems that in fact what I want is to call something like
dynamic-require with a module object. But I'm not sure what to call or how
to get one of those: read-syntax returns a syntax object, not a module,
while I don't (yet) know how to apply my expander's #%module-begin to it to
obtain a module.

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

Right! That's what I've obviously not fully understood yet.

(Thanks for the side node about moving to Discourse—it's a while since I've
been active on the list!)

-- 
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/CAOnWdojngwzQRGz0dj1QpA4OJixOKGMXGLrepdae08D8dhpJfQ%40mail.gmail.com.