[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] add language/wisp to Guile?

From: Maxime Devos
Subject: Re: [PATCH] add language/wisp to Guile?
Date: Sun, 5 Feb 2023 16:08:00 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.7.0

On 04-02-2023 22:35, Dr. Arne Babenhauserheide wrote:

Maxime Devos <> writes:

This needs an addition to the extensions via guile -x .w — I wrote
in the documentation. I didn’t want to do that unconditionally, because
detecting a wisp file as scheme import would cause errors.

If done carefully, I don't think this situations would happen.
More precisely:

   * .w would be in the file extensions list.

   * Instead of a list, it would actually be a map from extensions to

       .scm -> scheme
       .w -> wisp

     With this change, (use-modules (foo)) will load 'foo.scm' as Scheme
     and 'foo.w' as Wisp.  (Assuming that foo.go is out-of-date or
     doesn't exist.)

     (For backwards compatibility, I think %load-extensions needs to
     remain a list of strings, but a %extension-language variable could
     be defined.)

   * "guile --language=whatever foo" loads foo as whatever, regardless
     of the extension of 'foo' (if a specific language is requested,
     then the user knows best).

   * "guile foo" without --language will look up the extension of foo in
     the extension map. If an entry exists, it would use the
     corresponding language.  If no entry exists, it would use
     a default language (scheme).

This sounds good, though a bit more complex than I think it should be.

I think this should stick to only load Scheme if no language is detected
to keep Scheme the default language for Guile

To my knowledge, this is the case in my proposal. Detecting the language is done via the file extension, and if no known mapping exists, it defaults to Scheme.

— and also to avoid
stumbling over files that just take that extension.

While I suppose it is theoretically possible someone will write a .w file that contains Scheme code instead of Wisp, I'm not convinced by this argument. It sounds very unlikely, and also a 'don't do that, then' situation.

Checking more files
could slow down startup and I think having multiple languages fully
equal would risk splintering the development community.

Guile is first and foremost Scheme and fast startup time is essential.

More complicated is what should be done if a *.go file is detected
during import. There I could see Guile check if a file with any
supported extension is up to date.

Maybe the .go could contain some information on what the corresponding source code file name is, and Guile could read the .go without checking first checking for up-to-dateness. (But only reading; not loading yet!)

(There is already debugging information with such information, but to my
understanding that's for individual procedures, not the .go as a whole, and by using stuff like 'include' or macros there can be multiple source files.)

Once read, it should be easy to look up the source code file name from the .go and then verify whether the .go is up to date, and proceed with actually loading the .go (as in, put stuff in the module system, run top-level code, ...).

IIUC, that would be fully backwards compatible, and not cause any non-negligible slowdowns.

I also have an alternative proposal, more complicated and backwards-incompatible -- I wouldn't recommend it, but for completeness:

 * when doing (use-module (foo)) and foo.go exists in the
   $GUILE_LOAD_COMPILED_PATH, load it, and don't
   bother checking whether foo.scm, foo.w or foo.whatever exists
   or is up-to-date.  (If not done already in Guile.)

That should solve the 'I don't care what language the library Foo is written in, and my library Bar isn't written in Wisp so it seems unreasonable to have to add -x w.’, and would also avoid the need for a 'extension -> language map' thing. It should also be a little faster than what we had before.

That's for "make install", "apt-get install", "guix install" ...-like uses of compiled .go -- let's call them 'installed .go'. It won't work for ~/.cache/guile/ccache/3.0-LE-8-4 (‘cached .go’) as for that it's actually important to check up-to-dateness because, well, cache.

Additionally, to support compiling software that is already installed, there needs to be an option to treat certain modules with the 'cache' behaviour even if not in the actual ~/.cache, maybe with some '--local-module=(stuff ...)' option (name pending).

This would be backwards-incompatible, but it could be done.

readable uses

This sentence appears to be incomplete; I might have misinterpreted it
below (I don't know what you mean with 'readable' -- its an adjective
and you are using it as a noun?).

readable is a noun, yes: the readable lisp project.

Looks like you meant this: <>.
Can I write it into a string and then read it back?

No.  [...]

This sounds like I cannot go that way, because there’s a necessary
pre-processing step in wisp-read via (match-charlist-to-repr peeked):
[...] > This actually needs to be able to write the replacement symbols back
into the port.

..., for which I proposed a replacement, so do you still need to turn
it in a string & back?

Sadly yes. Otherwise the normal reader will play tricks on the code,
because it does not know where a symbol needs to be interpreted
differently (i.e. where ` needs to be treated as `() even though that’s
not in the string).

OK, too bad.  Looks like the REPR-... stuff is to stay for now.
I meant this:

(define (foo)
   #((bar . baz))
(procedure-properties foo)
=> ((name . foo) (bar . baz))

I use that for doctests: [...]

I didn't know that these literal vectors get turned into procedure properties ... looks interesting.

Also, about wisp-unescape-underscore-and-colon and the 'only unescapes up to 12 leading underscores at line start (\____________)' limitation: I have found a solution: you can use a combination of string-every, symbol->string, string->symbol, substring and string-ref:

(cond ((list? code) (map wisp-... code))
      ((eq? code '\:) ':)
      ;; Look for symbols like \____ and remove the \.
      ((symbol? code)
       (let ((as-string (symbol->string code)))
(if (and (>= (string-length as-string) 2) ; at least a single underscore
                  (char=? (string-ref as-string 0) #\\)
                  (string-every #\_ (substring as-string 1)))
             (string->symbol (substring as-string 1))
     (#true code))


Attachment: OpenPGP_0x49E3EE22191725EE.asc
Description: OpenPGP public key

Attachment: OpenPGP_signature
Description: OpenPGP digital signature

reply via email to

[Prev in Thread] Current Thread [Next in Thread]