drracket icon indicating copy to clipboard operation
drracket copied to clipboard

No current-load-relative-directory in expander

Open shhyou opened this issue 1 year ago • 6 comments

It seems like (current-load-relative-directory) is unavailable during background expansion and no working REPL loaded, while the code runs and compiles just fine from the command line:

#lang racket

(require (for-syntax syntax/parse/pre
                     compiler/cm-accomplice))

(define-syntax (require/phantom stx)
  (syntax-parse stx
    [(_ relpath:string)
     (register-external-module (path->complete-path (syntax-e #'relpath)
                               (current-load-relative-directory)))
     #'(begin)]))

(require/phantom "test.rkt")

#|
Welcome to DrRacket, version 8.15.0.12 [cs].
Language: racket, with debugging [custom]; memory limit: 128 MB.
. . ../../racket/gitdev/racket/collects/syntax/wrap-modbeg.rkt:46:4: path->complete-path: contract violation
  expected: (and/c (or/c path-string? path-for-some-system?) complete-path?)
  given: #f
> 
|#

Here, (current-load-relative-directory) returns #f in DrRacket but not in Racket REPL:

● [Jan10 20:47:44] $ racket
Welcome to Racket v8.15.0.12 [cs].
> (enter! "phantom-require.rkt")
"phantom-require.rkt"> 

During compilation, (current-load-relative-directory) also returns the load path:

● [Jan10 20:47:54] $ raco make -v phantom-require.rkt 
"phantom-require.rkt":
  making #<path:....../phantom-require.rkt>
 [output to "compiled/phantom-require_rkt.zo"]
● [Jan10 20:48:04] $ raco make -v phantom-require.rkt
"phantom-require.rkt":
  making #<path:....../test.rkt>
test.rkt:(syntax-local-phase-level 0)
  making #<path:....../phantom-require.rkt>
 [output to "compiled/phantom-require_rkt.zo"]
● [Jan10 20:48:06] $ 

shhyou avatar Jan 11 '25 02:01 shhyou

I don't know what the right behavior for DrRacket is, but the difference seems to be that when you do "racket phantom-require.rkt" or use enter! it is apparently using one of the functions listed in the current-load-relative-directory docs but DrRacket isn't.

You can see more along these lines if you make two files:

;;; tmp2.rkt
#lang racket
(define-syntax (m stx)
  (printf "clrd: ~s\n" (current-load-relative-directory))
  #'(void))
(#%expression m)
;;; tmp.rkt
#lang racket
(require "tmp2.rkt")

If you run "tmp2.rkt" in DrRacket, it prints false (even though the REPL isn't doing anything for this part). But, if you run "tmp.rkt" in DrRacket, you see the directory being required.

It might be the case that DrRacket should be setting current-load-relative-directory while expanding the definitions window, as if it were being required, but I'm not sure what the full ramifications of that would be.

I do see that on line 184 of expanding-place.rkt, that current-load-relative-directory is explicitly set to #f, and this commit seems relevant. Has something changed at the racket level since version 5.2.1!? 🙃

rfindler avatar Jan 11 '25 03:01 rfindler

Hmm, could setting things to #f be a reaction to loading code from an unsaved buffer?

I thought .rkt modules on the disk, before they are declared/expanded/instantiated, would be loaded from the disk via current-load[/use-compiled and so that's the reason why running things from the command line works. So it really depends on whether DrRacket intends to replicate the entire process or not.

Given that DrRacket sets the current directory from the commit, using (or (current-load-relative-path) (current-directory)) seems like a way to work around the differences.

shhyou avatar Jan 11 '25 15:01 shhyou

I think it is a fair question to ask "what exactly does the 'Run' button do?" in comparison to things like "racket file.rkt". In the case of "racket file.rkt", that's going to implicit add the "-t" option (among other things!) and so there is an actual require happening and if you read over the require docs carefully, you'll see it ends up deferring to one of the functions listed in the current-load-relative-directory documentation.

I'm still a little curious if anything has happened since 5.2.1, since apparently DrRacket used to set this parameter the exact way you were wanting it to be set and then that got changed! I guess we could change it back and then run the test suites and see if that sheds any light on anything. Or maybe @mflatt remembers?

rfindler avatar Jan 11 '25 15:01 rfindler

Maybe current-load-relative-directory should be set only during the expansion of the definitions window (as opposed to set and left alone even after expansion completes)? That would seem to be kind of similar to what's happening with "racket file.rkt" at the command-line.

rfindler avatar Jan 11 '25 21:01 rfindler

Maybe current-load-relative-directory should be set only during the expansion of the definitions window (as opposed to set and left alone even after expansion completes)? That would seem to be kind of similar to what's happening with "racket file.rkt" at the command-line.

It could be! When the module is being instantiated, current-load-relative-directory is indeed #f.

@rfindler I edited the first post. I should be clear that by "in REPL" in the post, I actually mean that there's no working REPL after clicking "Run".

shhyou avatar Jan 12 '25 01:01 shhyou

I tried C-c C-c in Racket Mode and I also see current-load-relative-directory set while the program is being expanded. Maybe that's because it is using require under the hood, but it does offer more evidence that DrRacket should be doing something different with the parameter.

rfindler avatar Jan 12 '25 22:01 rfindler