
I would like to parse racket code in order to find code matching some templates. What’s the best way to go about this? The point here is to check that my code is consistent and remind me of things that I might have forgotten. For example, for for/vector
I would like to add a note that I should be using the #:length
keyword, if possible. This in turn means that I cannot have a purely regexp parser. I need to ensure that the for/vector
I am looking at comes from racket/base
lang. Any suggestions on how to deal with this?

Use read-syntax in a loop? And use syntax-parse to analyze each expression?

Or … just thinking aloud … redefine for/vector to log any notes.

But how does one redefine it - without actually changing the defintion … hmm.

Maybe one can use the module name resolver ?

using read-syntax
makes sense. From the syntax output I should be able to inspect where it comes from. Will give it a go and see.

@pocmatos You’ll need to expand the expression first, to get the binding information.

Wait - this would be similar to the optimization coach. Maybe you there is something you can reuse?

hummm, good idea.

You’re right: https://github.com/stamourv/optimization-coach/blob/1b4da0b88ed31ee2e254201eab7c2ccb4b339864/optimization-coach/instrumentation.rkt has the combination ready-syntax
and expand
.


Also at RacketCon N years ago @notjack demoed something like this.



@notjack Can this be used in the for/vector example pocmatos mentioned?

Hi, I noticed this the other day
It provides a nice file viewer panel for DrRacket. It’s still new but I like it. (Does what is says on the tin)
I don’t know the author, but they promptly accepted my PR to add a very basic scribble file —- http://docs.racket-lang.org/files-viewer/index.html https://pkgs.racket-lang.org/package/files-viewer https://github.com/MatrixForChange/files-viewer File Manager for DrRacket
From the readme: The project is under LGPL LICENSE (same as Racket).
Issues and pull requests are welcomed.

Neat.

in Emacs likes to use neotree for this: https://github.com/greghendershott/.emacs.d/blob/master/init.el#L440-L458

also uses projectile and sets a keybinding to toggle neotree for the current project: https://github.com/greghendershott/.emacs.d/blob/master/init.el#L510-L533

@mflatt Is there any way to resolve the ‘self’ module path index?

Obviously (resolve-module-path-index (module-path-index-join #f #f))
results in an error…

@leif I think that’s a question where you need to back up at least one step

@samth Okay, how about this: “I want to serialize a reference to ‘this’ module, and later (as in within a different VM), expand to the referenced identifier.

(Obviously relative to the current module at the time of expansion.)

So by being a ‘this’ reference, it will expand to the identifier in the expanding module.

"

@leif depending on what you mean, there are parts of TR that do things like that

see, for example, the #%contract-defs-reference
module that TR generates

@samth Sure, that seems to use define-runtime-module-path-index
, which, iirc, can only be used at the top/module level, yes?

yes, although I don’t really see how it would work otherwise — you can’t expand to a lexical identifier from another module

Fair point.

I’m okay with limiting the definitions to top/module level (in fact, they already are), but the uses need to be lexical.

the uses of that are lexical

OH! It looks like module path indexes actually change when provided and then required into a different module…odd..

(or at least how they are printed….odd…)

@michael.ballantyne Seems to think this is because of syntax-module-path-index-shift
, but we can’t seem to find much else about it.

I don’t think the indexes change

the evaluation of #%variable-reference
produces different things, I think

That would make sense.

@samth Hmm….this still doesn’t seem to properly serialize. For example:

#lang racket
(require racket/runtime-path
racket/serialize)
(define-runtime-module-path-index x ".")
(serialize x)

’((3) 0 () 0 () () (mpi “.” mpi (p+ #“/Users/leif/test/foo.rkt” . unix) . #f)

And when I deserialize it, (and resolve it), I still get the absolute path.

Meaning that it would be hard to store it in a file. :disappointed:

that sounds like a different issue than where we started

but I don’t understand why that’s hard to store in a file

Its hard because the file could have moved.

So, the original (stepped back) question was: “I want to serialize a reference to ‘this’ module, and later (as in within a different VM), expand to the referenced identifier.“, as such, what I’m imagining is something like:

Did you mean to pass #:relative-directory
to serialize
?

that doesn’t seem fixable — you can’t expand to a reference to a file that isn’t there any more

@mflatt AH!!! That’s why you wanted to split out #:relative-directory
and #:deserialize-relative-directory
! That makes so much more sense now.

(And yes, that does seem to work. Thanks. :slightly_smiling_face: )

@samth Nah, I don’t want a reference to the same instance of that file, I want a reference to the relative location of that file.

But what @mflatt pointed out works. So thanks to both of you. :smile:

right, but “relative location” isn’t necessarily going to work in the future either

Yup, you are correct.

But it does mirror Racket’s existing binding system, which is what I was going for. :slightly_smiling_face:

Hello! I’m experimenting with message passing between processes written in /= languages. Like a “ping-pong” app written in 2 different languages. Is there anything that compares to zeromq for such a task? Thx.

Hi all, anyone have a handy guide on the preferred way to use bibtex with scribble?



@krismicinski Also if you have an existing bibtex file: http://matt.might.net/articles/parsing-bibtex/

@soegaard2 Thx ! But is there something else that compares to that in the Racket world? w/o ZeroMQ, how would a racket program send and receive messages with other processes? In other words, is ZeroMQ a necessary dependency or not?

@contact if you want something super simple, I’d just use a pipe and read
/write

obviously 0MQ is both more heavyweight and more featureful than that

hmm… this lets me know how to parse, but doesn’t really let me just use bibtex as a database without a racket-based representation of it, I think?

How can I get read-syntax
to read a normal racket file without chocking on #lang racket
?

Is there an automated way to transform it into a module, without the #lang
line?

@samth OK, thx!

@pocmatos read-language can handle the first line

@soegaard2 interesting, it does. The description for it looks menacing. :slightly_smiling_face:

@pocmatos you should just call read-syntax

that’s how you transform it into a module

read syntax is chocking on it. read: #lang not enabled in the current context

right, you should enable that — see http://docs.racket-lang.org/reference/Reading.html?q=enable-lang#%28def._%28%28quote._~23~25kernel%29._read-accept-lang%29%29

you have to enable it because it potentially executes arbitrary code

ah, yes, I needed read-accept-lang
and read-accept-reader
. Thanks

I am reading source with read-syntax
and then using expand-syntax
on the result parameterzied wtih make-base-namespace
. However, I get module: unbound identifier;
also, no #%app syntax transformer is bound in: module

Basically I have (define source-syntax
(with-input-from-file file
(lambda () (read-syntax file))
#:mode 'text))
(define expanded-syntax
(parameterize ([current-namespace (make-base-namespace)])
(expand-syntax source-syntax)))

@pocmatos You could use a namespace that has module
bound, but I recommend adjusting the result of read-syntax
with check-module-form
, instead.

Thanks. (expand (check-module-form ...
works.

@mflatt Oh wait, never mind, that won’t properly solve it. While it will handle relative module movements, it won’t handle ‘self’ if ‘self’ is a renamed file. For example:

#lang racket ;; /Users/leif/test/renamed.rkt
(require racket/serialize
racket/runtime-path)
(define-runtime-module-path-index here ".")
(serialize here
#:relative-directory (current-directory))

Will evaluate to: '((4) 0 () 0 () () (mpi "." mpi (p* #"renamed.rkt") . #f))

But if I store that into the current file, rename the file, and then try to deserialize it, I’ll still get the old module-path-index.

(Which would be what you expect for a different relative file, but not for a ‘self’ reference.)

I guess it boils down to, ’is there any way to distinguish a relative module path from a ‘self’ module path.)

Oh wait, I guess #:relative-directory
doesn’t actually need to be a directory at all, just any path:
(define-runtime-module-path-index here ".")
(serialize here
#:relative-directory (build-path (current-directory) "renamed.rkt"))

@mflatt This seems like a pretty good indicator we should actually make the keywords be #:relative-path
and #:deserialize-relative-path
, thoughts?

I don’t think that will work in general. "<dir>/x.rkt" is not "../x.rkt" relative to "<dir>/y.rkt".

Mmm…good point. :disappointed:

It seems possible that you want a hook to replace module reference in serialize
to complement the hook to replace module references in deserialize
.

Possibly Are you referring to the dir
argument in make-serialize-info
?

(Or possible the deserialize-id
argument?)

@pocmatos @soegaard2 to get syntax warnings about for/vector
you could write your own for/vector
macro that just adds warnings if needed while expanding to the regular for/vector
. You’d have to make sure you use your wrapper macro everywhere instead of the regular one though.

@notjack I want an external tool that can be extended and used across software that you might not have control of.

@mflatt Thinking about it a bit more, should #:relative-directory
also refer to directories that are ..
from the one you gave?

(And not only subdirectories.)

@leif No when a single dir is given. The pair form of relative directories lets you pick an enclosing directory whose contents will be recorded as relative.

For deserialize, I mean deserialize-module-guard
.

@notjack thanks for the explanation

Oh, you just mean a parameter like serialize-module-guard
, which gets applied to any dynamic-require
type of path that gets written into the serialize data? If so that would probably work.

So, then something like this should maybe work in general?:
(define-runtime-module-path-index here ".")
(serialize here
#:relative-directory (cons (variable-reference->module-source (#%variable-reference))
(build-path "/")))

(cc @soegaard2) in my experience (mostly via Google’s tooling around large-scale refactorings and code cleanups across their monorepo) tools that find problems in code are far less useful when they’re external to the code

Good point.

Well, you really can’t use a file path (like the result of variable-reference->module-source
) where a directory path is expected for determining relative paths. Few of our existing tools support file-relative instead of directory-relative references, although I guess you could extend serialize
and deserialize
further.
Also, beware that "/" isn’t an absolute path on Windows. The idea of making all paths relative can’t work on Windows, since there can be any number of roots.

Acknowledged.

Also, when you say /
can’t be an absolute path on windows, do you mean it can’t be a complete path, or it can’t be a complete path as well as an absolute path?

(I thought that Racket’s definition of an absolute path did not contain the drive name for windows, and the complete path was for that. But maybe I’m mistaken?)

@mflatt @leif so I’ve been following the serialization module paths discussion and wondering something: would it make sense for module paths to be URIs? that’s a hypothetical I’ve been curious about (I don’t mean to distract from the actual problems you’re both trying to solve right now, and “that’s nonsense” is an acceptable response)