Re: [BUG] Eval sets incorrect runtime metainformation

2024-06-28 Thread Andrew Tropin
On 2024-06-26 18:06, Philip McGrath wrote:

> On 6/26/24 07:41, Andrew Tropin wrote:>
 That said, the evaluator does attach so-called "meta-data" information
 to procedures, such as the procedure name.
 https://www.gnu.org/software/guile/manual/html_node/Procedure-Properties.html.
 If you know that you are making a procedure you can insert some
 meta-data for use by your run-time, in an initial vector alist.  See
 https://www.gnu.org/software/guile/manual/html_node/Procedure-Properties.html.
 But that's limited and doesn't take macros, etc into account.
>> 
>> Yep, that's is why I wrote:
>> 
>> --8<---cut here---start->8---
>> The another related problem is that the metainformation is stored in
>> prodecures properties, but not in variables, which makes it impossible
>> to implement a proper goto definition in general case.
>> --8<---cut here---end--->8---
>> 
>> How hard is to make a generic metainformation, which is attachable to
>> macros, symbols and other objects of the language, not only to
>> procedures?
>> 
>
> Instead of run-time reflection on values, I think an IDE implementing 
> jump to definition should use source location and binding information 
> from syntax objects. That's how DrRacket does it.

If you could share a snippet of code or link to related library or docs,
it could help to understand better the idea.  I still relatively newbie
in questions related to snyntax objects and overall scheme's expand.

>
> The attached DrRacket screenshot (of [1]), in which I've tacked a bunch 
> of binding arrows, shows how local definitions and complex 
> macro-introduced binding structures are supported. It also works across 
> modules, even with renaming: in the program `#lang racket (define one 
> 1)`, right-clicking on `define` and choosing "Jump to Binding 
> Occurrence" will highlight `racket`, because the initial import of the 
> racket language establishes the applicable binding of define, whereas 
> choosing "Open Defining File" will open the racket/private/kw module, 
> and then choosing "Jump to Definition (in Other File)" will jump to the 
> definition of `new-define` on line 1171 of kw.rkt, which is renamed 
> elsewhere to become the `define` of `#lang racket`.
>
> Since syntax objects from the expander encode all the details of scope, 
> this works mostly automatically. DrRacket makes this functionality 
> available as a library, so navigation features can also be used from 
> Emacs with racket-xp-mode [2] or other editors with the Language Server 
> Protocol [3].
>
> That said, if you do want to associate extra information with values at
> runtime, Guile has object properties [4], or of course you could always 
> keep your own hash table on the side.

Thank you for pointing to object properties!

I guess we can implement our own eval, to attach location information to
corresponding objects, I just expected it to be a part of the guile,
because we already have this information for procedures anyway.  The
another problem with our own eval is that information for already loaded
code won't be enriched with our custom stuff :/

>
> Philip
>
> [1]: 
> https://github.com/racket/racket/blob/6105332045595f8324985d7a34acc68fa5a61dcf/pkgs/racket-test/tests/json/indent.rkt#L244-L276
> [2]: https://www.racket-mode.com/#racket_002dxp_002dmode
> [3]: https://github.com/jeapostrophe/racket-langserver/
> [4]: 
> https://www.gnu.org/software/guile/manual/html_node/Object-Properties.html
> x

-- 
Best regards,
Andrew Tropin


signature.asc
Description: PGP signature


Re: [BUG] Eval sets incorrect runtime metainformation

2024-06-28 Thread Andrew Tropin
On 2024-06-26 18:04, Andy Wingo wrote:

> On Wed 26 Jun 2024 11:36, Maxime Devos  writes:
>
>> IIRC, the question wasn’t about debugging in general, it was about
>> source locations in particular. Surely program-sources (or, in this
>> case, procedure-source maybe?) (why are the procedures in this family
>> even named program-whatever, this prevents doing the same for
>> interpreted code later) could be adjusted to also work for ‘eval’. For
>> example, ‘eval’ could set the ‘source’ (*) procedure property when a
>> closure is made.
>
> I think it's really valuable to imagine how things should be but if you
> are going to argue they should be different, you should first try to
> understand how they are.
>
> `program-sources` is a mapping from bytecode offsets to source
> locations.  For compiled procedures we can make this mapping because
> each bytecode position has a single source.  For interpreted procedures,
> what you end up getting is the bytecode-to-source mapping *for eval*,
> not for the code being interpreted.
>
> Is it a great thing that there is a debugging (I use the term on purpose
> to mean all kinds of run-time reflection etc) difference between eval
> and compile?  No, of course not.  I would rather there not be a
> difference and not have to document something that is at best
> extraneous.  There are differing pressures on eval: for bootstrap times
> (and macro expansion time) you want it to have the least amount of
> overhead possible, whereas for debugging you want to attach meta-data
> that isn't strictly needed at run-time.  Attaching that meta-data has
> memory and time overheads.

Does it mean, we could want another eval implementation, which is a bit
havier, but will preserve additional meta-data?

not-that-primitive-and-a-bit-fancier-eval :)

>
> If we are looking to get the source location *just of the interpreted
> closure* -- that is possible; see eval.scm:581, there you would attach
> some other properties.  You would have to define a different debugging
> interface that looks for source location information in a way different
> from program-sources.  For me it's not worth it but I encourage you to
> experiment with (ice-9 eval); it's just another Scheme program.  (You
> would need to take a different approach to memoization, in order to pass
> through source location information.)
>
> Andy

-- 
Best regards,
Andrew Tropin


signature.asc
Description: PGP signature


RE: [PATCH 1/3] Make string-length documentation more correct

2024-06-28 Thread Andrew Tropin
On 2024-06-26 13:46, Maxime Devos wrote:

>>>  >-Returns the number of characters in the given @var{string}.
>>> +Returns the number of bytes in the given @var{string}.
>>>  
>>> This is false. For example, (string-length "😀") is 1, whereas in all 
>>> encodings I know of it is >more than one byte. Also, R5RS says: [...]
>>
>>Maybe `the number of codepoints` will work here.
>>
>>(string-length "👨‍🏭") ;; => 3
>>(string-length "é") ;; => 2
>>
>>The number of characters here is 1 in both cases.
>
> No, in Unicode (and Guile equates character=Unicode character) all characters 
> correspond to a single codepoint.
>
> You need to fix your setup, that’s not what Guile does. Are you sure you have 
> set the encoding of current-input-port correctly? (Probably by setting LC_ALL 
> or the like to a UTF-8 locale.) Otherwise the 3 bytes in the UTF-8 encoding 
> might be interpreted in terms of some 8-bit encoding.
>
> Here’s a test: if you can input #\👨‍🏭 without errors and it evaluates to 
> #\👨‍🏭, then the encoding should be set up correctly.

(setlocale LC_ALL) ;; => "en_US.utf8"
(display #\👨‍🏭) ;; => /home/bob/guile-ares-rs/dev/guile/tmp.scm:84:15: unknown 
character name 👨‍🏭

The same hapenning if I do it in usual REPL: 
LC_ALL=en_US.utf8 guile

-- 
Best regards,
Andrew Tropin


signature.asc
Description: PGP signature


RE: [PATCH 1/3] Make string-length documentation more correct

2024-06-28 Thread Andrew Tropin
On 2024-06-26 14:26, Maxime Devos wrote:

>>No; he wrote é, U+0065 LATIN SMALL LETTER E + U+0301 COMBINING ACUTE ACCENT,
>>which is two characters unlike é, LATIN SMALL LETTER E WITH ACUTE.
>>
>>Likewise 👨‍🏭 is U+1F468 MAN + U+200D ZERO WIDTH JOINER + U+1F3ED FACTORY.
>
> Right, I should have tested that instead of assuming it’s the
> pre-combined é and a single-codepoint emoji.
>

Let's keep string-length documentation intact :)

It would be cool if somebody apply the rest two patches.

-- 
Best regards,
Andrew Tropin


signature.asc
Description: PGP signature


[PATCH] Add nondestructive delq1, delv1, and delete1.

2024-06-28 Thread Richard Sent
* libguile/list.c: (delq1): Create.
(delv1): Create.
(delete1): Create.
* doc/ref/api-data.texi (List Modification): Document it.
---

Hi Guile,

There was some discussion on IRC a while back about how it was odd
there were destructive delete1! and similar functions, but no
nondestructive variants. This patch aims to fix that.

 doc/ref/api-data.texi | 52 ---
 libguile/list.c   | 36 ++
 libguile/list.h   |  3 +++
 3 files changed, 68 insertions(+), 23 deletions(-)

diff --git a/doc/ref/api-data.texi b/doc/ref/api-data.texi
index 3b9933d97..c94846842 100644
--- a/doc/ref/api-data.texi
+++ b/doc/ref/api-data.texi
@@ -6000,39 +6000,45 @@ Deleting}), and also an @code{lset-difference} which 
can delete
 multiple @var{item}s in one call (@ref{SRFI-1 Set Operations}).
 @end deffn
 
-@deffn {Scheme Procedure} delq! item lst
-@deffnx {Scheme Procedure} delv! item lst
-@deffnx {Scheme Procedure} delete! item lst
-@deffnx {C Function} scm_delq_x (item, lst)
-@deffnx {C Function} scm_delv_x (item, lst)
-@deffnx {C Function} scm_delete_x (item, lst)
-These procedures are destructive versions of @code{delq}, @code{delv}
-and @code{delete}: they modify the pointers in the existing @var{lst}
-rather than creating a new list.  Caveat evaluator: Like other
-destructive list functions, these functions cannot modify the binding of
-@var{lst}, and so cannot be used to delete the first element of
-@var{lst} destructively.
-@end deffn
-
-@deffn {Scheme Procedure} delq1! item lst
+@deffn {Scheme Procedure} delq1 item lst
 @deffnx {C Function} scm_delq1_x (item, lst)
-Like @code{delq!}, but only deletes the first occurrence of
+Like @code{delq}, but only deletes the first occurrence of
 @var{item} from @var{lst}.  Tests for equality using
-@code{eq?}.  See also @code{delv1!} and @code{delete1!}.
+@code{eq?}.  See also @code{delv1} and @code{delete1}.
 @end deffn
 
-@deffn {Scheme Procedure} delv1! item lst
+@deffn {Scheme Procedure} delv1 item lst
 @deffnx {C Function} scm_delv1_x (item, lst)
-Like @code{delv!}, but only deletes the first occurrence of
+Like @code{delv}, but only deletes the first occurrence of
 @var{item} from @var{lst}.  Tests for equality using
-@code{eqv?}.  See also @code{delq1!} and @code{delete1!}.
+@code{eqv?}.  See also @code{delq1} and @code{delete1}.
 @end deffn
 
-@deffn {Scheme Procedure} delete1! item lst
+@deffn {Scheme Procedure} delete1 item lst
 @deffnx {C Function} scm_delete1_x (item, lst)
-Like @code{delete!}, but only deletes the first occurrence of
+Like @code{delete}, but only deletes the first occurrence of
 @var{item} from @var{lst}.  Tests for equality using
-@code{equal?}.  See also @code{delq1!} and @code{delv1!}.
+@code{equal?}.  See also @code{delq1} and @code{delv1}.
+@end deffn
+
+@deffn {Scheme Procedure} delq! item lst
+@deffnx {Scheme Procedure} delv! item lst
+@deffnx {Scheme Procedure} delete! item lst
+@deffnx {Scheme Procedure} delq1! item lst
+@deffnx {Scheme Procedure} delv1! item lst
+@deffnx {Scheme Procedure} delete1! item lst
+@deffnx {C Function} scm_delq_x (item, lst)
+@deffnx {C Function} scm_delv_x (item, lst)
+@deffnx {C Function} scm_delete_x (item, lst)
+@deffnx {C Function} scm_delq1_x (item, lst)
+@deffnx {C Function} scm_delv1_x (item, lst)
+@deffnx {C Function} scm_delete1_x (item, lst)
+These procedures are destructive versions of @code{delq}, @code{delv},
+@code{delete}, @code{delq1}, @code{delv1}, and @code{delete1}: they
+modify the pointers in the existing @var{lst} rather than creating a new
+list. Caveat evaluator: Like other destructive list functions, these
+functions cannot modify the binding of @var{lst}, and so cannot be used
+to delete the first element of @var{lst} destructively.
 @end deffn
 
 @deffn {Scheme Procedure} filter pred lst
diff --git a/libguile/list.c b/libguile/list.c
index 8063a15d1..af8e6222e 100644
--- a/libguile/list.c
+++ b/libguile/list.c
@@ -949,6 +949,42 @@ SCM_DEFINE (scm_delete1_x, "delete1!", 2, 0, 0,
 }
 #undef FUNC_NAME
 
+SCM_DEFINE (scm_delq1, "delq1", 2, 0, 0,
+(SCM item, SCM lst),
+   "Like @code{delq}, but only deletes the first occurrence of\n"
+   "@var{item} from @var{lst}.  Tests for equality using\n"
+   "@code{eq?}.  See also @code{delv1} and @code{delete1}.")
+#define FUNC_NAME s_scm_delq1
+{
+  SCM copy = scm_list_copy (lst);
+  return scm_delq1_x (item, copy);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_delv1, "delv1", 2, 0, 0,
+(SCM item, SCM lst),
+   "Like @code{delv}, but only deletes the first occurrence of\n"
+   "@var{item} from @var{lst}.  Tests for equality using\n"
+   "@code{eqv?}.  See also @code{delq1} and @code{delete1}.")
+#define FUNC_NAME s_scm_delv1
+{
+  SCM copy = scm_list_copy (lst);
+  return scm_delv1_x (item, copy);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_delete1, "delete1", 2, 0, 0,
+(SCM item, SCM lst),
+   "Like @co

The Guile junk drawer and a C plea (was: [PATCH] Add nondestructive delq1, delv1, and delete1.)

2024-06-28 Thread Thompson, David
Hi Richard and all other Guilers, too,

What follows is not code review, but your patch felt like an
opportunity to provide some commentary about the trajectory of Guile
development that I've wanted to share for awhile.

First, I think Guile's default environment is a total mess.  It's the
very definition of a junk drawer.  There's over 1000 names in the
(guile) module!  Contrast this with R7RS-small's (scheme base) module
that only has 200ish.  Guile is an old project and I'm sure stuff just
accumulated over the years, but having so much in the default
environment makes it hard to know what a program actually uses because
many things that ought to be explicit imports are not. This makes it a
challenge to move Guile in a more "least authority" direction.  As a
rule, I think Guile should *not* add any additional names to the
default environment without an extremely good reason. Because (guile)
is imported implicitly, new names can cause clashes with existing code
that require #:replace to suppress the warning about shadowing core
bindings.  For example, the newish 'spawn' procedure collides with
'spawn' in (goblins core) in the Goblins project.  I think Guile needs
a (multi-year, multi-major version) plan to deprecate cruft and move
the good stuff into different modules.  Give a hoot, don't pollute
(the default environment)!

Second, please please please, no more C! Guile's substantial amount of
C code is a legacy of its origins decades ago, and we need to make it
clear to new users and contributors that new code should be written in
Scheme! The procedures in Richard's patch would be much more elegantly
written in Scheme and it would allow the compiler to gnaw on the code,
too.  Those experienced with Guile know that writing Scheme procedures
in C has all sorts of issues, like non-resumable continuations if a C
stack frame is captured, but we could probably do more to discourage
writing C in the docs and stuff.  It's also just no fun at all.  Who
actually wants to use that C API?  Furthermore, every procedure
implemented in C is a challenge for bringing Guile to new places like,
say, WebAssembly. Hoot is unable to import any module from Guile that
loads a C extension. Did you know that (srfi srfi-1) loads a C
extension?  Argh!  I'm hoping we on the Hoot team will fix that
particular issue soon.

Okay I should be going to bed instead of writing emails. That's all for now!

- Dave