
@notjack Thanks for pointing that out! I’ll give it a closer read. One I notice quickly: LSIF seems line:column
oriented. Whereas the relevant drracket/check-syntax
annotations are reported (only) as beginning and end positions — and IME actually that’s more convenient and faster, at least wrt using such info in Emacs.

Maybe I’m just selfish. After all, there’s no “I” in LSP. ;)

@kellysmith12.21 If you have symbols from say module->imports
, I think you can use them to synthesize identifiers with the lexical context of the module body. If you have syntax for the expanded module, then (syntax-property exp-mod-stx 'module-body-context)
can be the first argument to datum->syntax
.


I’m not sure if that’s on point for what you’re trying to do.

I put together a proof-of-concept based on the require-transformer+mutation approach you described earlier, @kellysmith12.21. Not sure if it’s exactly what you’re looking for, though it seems to work: https://gist.github.com/97jaz/0b631811b5819b401a5db39885ca2fff

@greg this might be just a problem I have to live with, but racket-mode and especially racket-xp-mode are very laggy if the file is gigantic

How gigantic? My favorite worst-case example is drracket/private/unit.rkt which is 5600 lines. On my machine it take about 16 seconds for macro-expansion plus drracket/check-syntax to finish. Then more seconds for Emacs to propertize the buffer.

Which is not great, but, > 5000 lines is a bit more than the Racket coding guidelines recommend. :stuck_out_tongue:

This one is 86k lines (it’s the expanded-and-flattened expander).

That is somewhat more than 5K. Huh.

running it at the command line takes about 3.5 seconds

Running what, raco expand
?

no, just racket
. raco expand
is about 4.5

I mean I think the short answer is that 86K lines is at least 80K more lines than I envisioned as something to test for.

It would be interesting for me to break that down into sub timings.

the big problem is that doing racket-mode operations locks up emacs itself

How much is drracket/check-syntax, how much is marshaling Racket values to s-expressions and reading them into Emacs, how much is propertizing text in the buffer, and so on.

The file is here: https://gist.github.com/samth/25bb9eb5d0b36983bae48efb5a032402


Is it possible to invoke a parent struct’s generic method from the child struct’s method of the same name? i.e is there a super
counterpart for structs’ generic methods?

OK. I’ll try to take a look. I suspect the answer might turn out to be that a file that big would need a new design, where the annotations are “streamed” from the Racket back end to the Emacs front end, rather than being collected and returned as one s-expression.

Also I’m curious how DrRacket handles this. The syncheck
interface is more or less “streaming” oriented, and it needn’t marshal values across process boundaries. So I imagine it’s faster. But I wonder how much faster. So I’ll try to find time to try that, too.


Now I have both Emacs and DrRacket “frozen”. :tada:

DrRacket shows “Check syntax: expanding expression” and is responsive for awhile, but then freezes. It might be getting farther and that message is misleading.

Anyway I’ll focus on Emacs and Racket Mode at first and see what I can see.

I don’t think there is.

@jaz Thanks, but I don’t think define/generic
can be used in this case. For example, https://gist.github.com/capfredf/ee0d7553e47e4f0ed65d5078b4a26f9e this program diverges.
define/generic
binds a local id to a generic method, so one can use the id to call the generic method inside definitions of generic methods. Directly invocation might not work because the identifier could be shadowed, i.e. one could be calling the local method. see
https://gist.github.com/capfredf/e2375151ad3c2c19209daa5f63db643d

@samth To back up a step. It sounds like what would help you most, immediately, is if racket-xp-mode
were not automatically enabled for files that are “too big”.
If so: I could give you some Elisp code to put in your config instead of (add-hook 'racket-mode-hook #'racket-xp-mode)
. i.e. A hook function that only enables racket-xp-mode if the file is smaller than TBD bytes.
I could give you that probably within an hour, if you need it that soon.
Or, if you don’t mind waiting a day, I could update racket-xp-mode
itself to do this check, push to MELPA, and you could get it that way.

Preference?

(Of course I’ll still think about how to make it work for very large files. But my preliminary thinking, is there are trade-offs, and I need more thinking. I think.)

@capfredf Ah, got it. Yeah, no built-in support for that. I guess you need to define the parent’s method implementation separately and call it directly from the child’s implementation.


I don’t really need anything right now

I mostly wanted to give you something to think about

OK. If you did want a guard rail to prevent opening a file like this causing racket-xp-mode to be enabled and freeze Emacs, you could do in your Emacs init file:
(require 'racket-xp)
- (add-hook 'racket-mode-hook #'racket-xp-mode)
+ (remove-hook 'racket-mode-hook #'racket-xp-mode)
+ (add-hook 'racket-mode-hook
+ (lambda ()
+ (if (< (buffer-size) 128000)
+ (racket-xp-mode)
+ (message "File too large; not enabling racket-xp-mode"))))

Does this work with racket 8.0? https://github.com/jeapostrophe/racket-android If not, would adapting be a small change?