⚡ Sangsakala Proxy 🏠 Home
Skip to content

add support for $/require string literals of relative racketscript modules #278

Open

Description

@kurinoku

Right now the intents seems to just use $/require for javascript modules wether installed or relative, but support could be added to catch literals ending in .rkt, replace their extension to .rkt.js and add them to the dependency tree.

Activity

  1. stchang commented on Dec 8, 2021

    @stchang
    Member

    Anything in the interop library (with a $ prefix) is equivalent to directly writing plain js. It shouldnt know anything about Racket.

    So if something like this were to be added, it should be a new form I think, rather than a change to $/require.

    But in this case, is there a reason why the .rkt.js file could not be directly imported? (Is the use case to improve compile time?)

  2. kurinoku commented on Dec 8, 2021

    @kurinoku
    Author

    You are right that since it's part of the ffi it shouldn't know about Racket, but I think there should be then some form/procedure to tell the compiler to load certain modules.

    My use case it has to do with this, evobot handling of command loading, it loads all the commands in a file, so one does not have to reference each one of the names.

    const commandFiles = readdirSync(join(__dirname, "commands")).filter((file) => file.endsWith(".js"));
    for (const file of commandFiles) {
      const command = require(join(__dirname, "commands", `${file}`));
      client.commands.set(command.name, command);
    }

    I got this

    #lang racketscript/base
    (require (for-syntax racket/base
                         racket/syntax
                         racket/path
                         syntax/parse))
    
    (define-syntax (require+save-commands stx)
      (syntax-parse stx
        [(_ path:string save-to:id)
         #:with name-bind (format-id this-syntax "command")
         (let ([base-src (syntax-source #'path)]
               [path/string (syntax-e #'path)])
           (let-values ([(base _name _dir?) (split-path base-src)])
             (with-syntax*
                 ([(mod-paths ...)
                   (for/list ([p (in-list (directory-list (build-path base path/string)))]
                              #:when (path-has-extension? p #".rkt"))
                     (path->string (build-path path/string p)))]
                  [(tmp ...) (generate-temporaries #'(mod-paths ...))])
               #'(begin
                   (require (only-in mod-paths [name-bind tmp]) ...)
                   (provide save-to)
                   (define save-to
                     ($/array tmp ...))))))]))
    
    (require+save-commands "commands" commands)

    And it works perfectly fine, I was just wondering if a more straighforward way of doing this was worth implementing.
    For example

    (define-syntax (require+save-commands stx)
      (syntax-parse stx
        [(_ path:string save-to:id)
         #:with (mod-paths ...) (for/list ([p (in-list (directory-list (syntax-e #'path)))] 
                                                        #:when (path-has-extension? p #".rkt"))
                                              (path->string p))
         #'(begin
               (provide save-to)
               (define save-to
                 ($/array ($/require mod-paths) ...)))]))
    
    require+save-commands "commands" commands)

    Now, I realize now that I know a bit more of racketscript and nodejs with ES modules, that this might just not work at all (because the require function is not used in ES modules and if I recall correctly $/require is for the syntax require not the function).

    I still think an easy way to do the same should be provided, but I realize that it may be outside the scope of the project.

  3. stchang commented on Dec 8, 2021

    @stchang
    Member

    $/require should correspond to nodejs require function, so it should be possible to write that js code snippet directly using the ffi.

    But is the issue that the files in the directory will now be racket files so they would need to be compiled first?

  4. kurinoku commented on Dec 8, 2021

    @kurinoku
    Author

    Yes, that would be the issue, since the compiler does not consider usages of $/require with racket files to be a dependency that has to compile.

  5. stchang commented on Dec 16, 2021

    @stchang
    Member

    I would support adding something like $/require/rkt, but could you fill in some more use case details? I still have a disconnect between the js use case and what the analogous racket would look like.

    From what I understand, the result of calling (require "command.js") in js is an exports object that gets explicitly constructed in command.js?

    So if I call ($/require/rkt "commands.rkt"), what does commands.rkt look like? Is there an explicit exports object? Or is exports generated as part of the call/compilation (and gets implicitly populated with all the provides)? Or something else?

  6. kurinoku commented on Dec 16, 2021

    @kurinoku
    Author

    I would implement it as just a compilation hook that add the dependency of that file into the process, and it just translates in javascript to require("<name-of-file>.js").

  7. stchang commented on Dec 16, 2021

    @stchang
    Member

    Ok that's pretty straightforward then

  8. stchang commented on Dec 17, 2021

    @stchang
    Member

    I tried to add the requested $/require/rkt, see #286

    But I think I'm running into the problem I alluded to above, which is that the required library doesn't have the expected exports?

    The specific error I'm getting is SyntaxError: The requested module './rktlib.rkt.js' does not provide an export named 'default'

    @kurinoku If you have a chance, could you try out that branch and see if it does what you want? If not feel free to modify

  9. vishesh commented on Dec 17, 2021

    @vishesh
    Member

    Seems like its doing something like import default from mod.js which is probably not right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions