Re: Reference documentation of modules and library

2012-01-15 Thread Ludovic Courtès
Hi Mike,

I think “Standard Library” should eventually be merged into “Guile
Modules”.  The reason it’s separate currently is that its contents are
automatically extracted from the module comments, which is inherited
from Guile-Lib.  But merging them also means improving their integration
with the rest of the manual, possibly rewriting parts, IMO.  Would you
like to work on it?  :-)

Regarding standard/extended/3rd-party library, how about adding
second-level sections to sort by theme?

For instance, formatted output, pretty-printing, and expect could be
grouped together; sxml, and (sxml match), and perhaps Texinfo ditto;
etc.

WDYT?

As for SLIB and Jacal, I’m not sure they even run with Guile 2.0.  Has
anyone tried lately?

Thanks,
Ludo’.




Re: Reference documentation of modules and library

2012-01-15 Thread Mike Gran
 From: Ludovic Courtès l...@gnu.org
 Hi Mike,
 
 I think “Standard Library” should eventually be merged into “Guile
 Modules”.  
 
I could try it.  It'll take me a few weeks to geto to it, though.

 Regarding standard/extended/3rd-party library, how about adding
 second-level sections to sort by theme?
 
 For instance, formatted output, pretty-printing, and expect could be
 grouped together; sxml, and (sxml match), and perhaps Texinfo ditto;
 etc.

They could definitly use a better ordering: sxml and sxml-match
should be together.
 
Second-level sections might help, but they might feel excessive.
 
 As for SLIB and Jacal, I’m not sure they even run with Guile 2.0.  Has
 anyone tried lately?
 
Much of Slib still works.  It does use some removed functions.
 
The installation has problems.  Its makefile installs slib into
a directory that Guile doesn't search, and the makefile needs to be
modified to run at all if Jaffer's scm is not installed.
 
I ended up writing my own autotools wrapper for slib to get it to
install.
 
Thanks,
 
Mike



Re: [PATCH] local-eval, local-compile, and the-environment (v3)

2012-01-15 Thread David Kastrup
Mark H Weaver m...@netris.org writes:

 Here's the third version of my simple `local-eval' patch.
 Notable changes from last time:

 * Pattern variables are now captured properly.
 * `the-environment' now works as advertised within macro definitions.
 * Added doc strings for `local-eval' and `local-compile'.

 I am open to reimplementing this in a different way for 2.0.5, along the
 lines suggested by Andy.  I'd like to capture all bindings, not just the
 ones reachable by symbols.  I'd like to support _all_ lexical bindings,
 including local syntax transformers.  I'm also warming to the idea of
 standardizing on variable objects as a way to represent mutable
 lexicals.  However, there's no time to do this for 2.0.4.  That job
 depends on other big jobs, notably a major overhaul of the evaluator.

 Nonetheless, I think it is very important to include this simple
 implementation in 2.0.4.  This is a BUG FIX, the bug being that
 `local-eval' was removed from underneath Lilypond's feet.  A partial
 implementation (that almost certainly does everything they need) is
 _far_ better than none at all.  Lilypond can only depend on `local-eval'
 if installations of Guile without it are quite rare.  If we can get this
 in 2.0.4, there's hope that we can make Guile 2.0.[0-3] rare.

 Please consider it.  This implementation is quite robust.

I am not altogether comfortable with pushing a temporary fix for the
sake of LilyPond when we'll get another behavioral change with the next
version.  LilyPond would be mostly left in the rain for older versions
unless we made that implementation a fallback within our own sources.
However, there would be no point in adopting a fallback implementation
that would not also work with 2.0.0-2.0.3.

As far as I understand, this implementation could be pulled into a
separate file and used for bridging the 2.0.0-2.0.3 gap.  If it is solid
enough to be maintained as 2.0.4, it would likely be a reasonably good
bet.

Of course, a version that would be tighter integrated with the compiler
and optimizer would seem like a more powerful prospect, but it also
sounds that it would need more thorough maintenance to not fall into bit
rot.

I am not sure that the reasons for not permitting definition context in
local-eval are not of somewhat more theoretical than practical nature,
and in particular it sounds to me like I'm also warming to the idea of
standardizing on variable objects as a way to represent mutable
lexicals could suggest that the strength of even the theoretical
reasons might get eroded further.  Of course, _calling_ mutual recursive
functions in execution before the second part has been defined will
remain unfeasible.

-- 
David Kastrup



syntax-local-binding

2012-01-15 Thread Andy Wingo
Hi list,

Attached is a patch that implements a new accessor,
syntax-local-binding.  It's like syntax-local-value, but can also
determine if an identifier is a pattern var or a normal lexical.

   (define-syntax local-binding
  (lambda (x)
(syntax-case x ()
  ((_ id) (identifier? #'id)
   (call-with-values (lambda () (syntax-local-binding #'id))
 (lambda (x y)
   (with-syntax ((type (datum-syntax #'here x)))
 #''type)))
   (let-syntax ((x (lambda (x) 10))) (local-binding x))
  $3 = local-macro
   (syntax-case #'(foo) () ((id) (local-binding id)))
  $4 = pattern-variable
   (let ((x 10)) (local-binding x))
  $5 = lexical

It returns two values.  The first is a symbol, either `local-macro',
`lexical', or `pattern-variable'.  The second is specific to the type.
For local-macro it is the transformer binding.  For lexical it is the
gensym name of the lexical.  For pattern variables, it is something
opaque that identifies that pattern var.

Inspired by a patch by Stefan Israelsson Tampe.

I'm going to try to implement the-environment with this.  We'll see how
it goes!

Andy
-- 
http://wingolog.org/



Re: GNU Guile branch, master, updated. v2.1.0-102-g0f9f51a

2012-01-15 Thread Andy Wingo
Hi Mark,

On Sat 14 Jan 2012 21:37, Mark H Weaver m...@netris.org writes:

 If a top-level variable needs to be expanded in user code, then you'd
 better explicitly choose a stable name for it.

Indeed, this is the best solution, for interface stability.

But what should happen when users do introduce top-level variables in
their macros, against our recommendations?  My point is that the answer
cannot be, generate a truly random identifier.  Simply advising users
not to introduce bindings is not a great answer.

 In the general case, where a macro may have been considerably reworked
 from one version to the next, it's _impossible_, even in principle,
 for the system to reliably decide the correspondence between top-level
 gensyms in the new code vs the old code.  Even your method is only a
 heuristic that will often do the wrong thing, in both directions: it
 will cause unintended name collisions in R5RS standard code, and it
 will also sometimes change the name of a top-level when you didn't
 want it to.

Of course.  It's a heuristic.  We document the heuristic and move on,
no?  If users really find themselves caring about this, they will have
to learn the heuristic.

 There's another option: we could properly track the compile-time
 dependencies of each module, and automatically consider a .go file stale
 if _any_ of its compile-time dependencies are newer than it.

We do need to do this, yes.  This would be a great thing to add, once we
switch to ELF as our format of compiled files.  (You would add a section
for this.)

 Furthermore, we could provide distros with the necessary infrastructure
 to automatically recompile guile modules as needed after package
 upgrades.

That is orthogonal to this question.  Recompilation can be triggered on
package dependencies, instead of embedded expansion dependencies.
That's what I was planning on doing for the guildhall, for example.

Regards,

Andy
-- 
http://wingolog.org/



Re: [PATCH] local-eval, local-compile, and the-environment (v3)

2012-01-15 Thread Mark H Weaver
David Kastrup d...@gnu.org writes:
 I am not altogether comfortable with pushing a temporary fix for the
 sake of LilyPond when we'll get another behavioral change with the next
 version.

But there would _not_ be a behavioral change in the next version.
It would only be a change in the internal implementation.

 As far as I understand, this implementation could be pulled into a
 separate file and used for bridging the 2.0.0-2.0.3 gap.

Unfortunately, any implementation of `local-eval' requires changes to
psyntax.scm, which is not something that you could reasonably do as an
external package.

 I am not sure that the reasons for not permitting definition context in
 local-eval are not of somewhat more theoretical than practical nature,

There's at least one practical reason not to allow it, namely that it is
_impossible_ to implement.  Consider this:

  (let ((x 1))
(define (get-x) x)
(the-environment))

If we allow (the-environment) to add definitions to the implicit
`letrec', then (get-x) cannot know which binding of `x' to use.  In
fact, it cannot lookup _any_ bindings, because absolutely any identifier
(even syntactic keywords) could be redefined within this implicit
`letrec'.

This means that it's impossible to compile or evaluate anything within
the body of the outer `let', which means it's not even possible to
evaluate (the-environment) itself.  So there's no way to run the code
above if we allow (the-environment) to add definitions.

 Mark



Re: syntax-local-binding

2012-01-15 Thread Andy Wingo
On Sun 15 Jan 2012 18:00, Andy Wingo wi...@pobox.com writes:

 Attached is a patch that implements a new accessor,
 syntax-local-binding.

Here 'tis!

From 09ba44abeb47cdf4ec61df6f7386217f0cbe30c7 Mon Sep 17 00:00:00 2001
From: Andy Wingo wi...@pobox.com
Date: Sun, 15 Jan 2012 17:51:02 +0100
Subject: [PATCH] add syntax-local-binding

* module/ice-9/boot-9.scm (syntax-local-binding): New binding.

* module/ice-9/psyntax.scm: Locally define a fluid that holds the
  transformer environment.  with-transformer-environment calls a
  procedure with the transformer environment, or raises an error if
  called outside the extent of a transformer.  Bind
  transformer-environment in expand-macro.
  (syntax-local-binding): New procedure to return binding information of
  a lexially bound identifier (a lexical, local macro, or pattern
  variable).
---
 module/ice-9/boot-9.scm  |1 +
 module/ice-9/psyntax.scm |   39 +--
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index f661d08..9cdd8d1 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -389,6 +389,7 @@ If there is no handler at all, Guile prints an error and then exits.
 (define generate-temporaries #f)
 (define bound-identifier=? #f)
 (define free-identifier=? #f)
+(define syntax-local-binding #f)
 
 ;; $sc-dispatch is an implementation detail of psyntax. It is used by
 ;; expanded macros, to dispatch an input against a set of patterns.
diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm
index 1bf3c32..dcabafe 100644
--- a/module/ice-9/psyntax.scm
+++ b/module/ice-9/psyntax.scm
@@ -786,6 +786,14 @@
   id))
  (else (syntax-violation 'id-var-name invalid id id)
 
+(define transformer-environment
+  (make-fluid
+   (lambda (k)
+ (error called outside the dynamic extent of a syntax transformer
+
+(define (with-transformer-environment k)
+  ((fluid-ref transformer-environment) k))
+
 ;; free-id=? must be passed fully wrapped ids since (free-id=? x y)
 ;; may be true even if (free-id=? (wrap x w) (wrap y w)) is not.
 
@@ -1321,8 +1329,10 @@
(syntax-violation #f encountered raw symbol in macro output
  (source-wrap e w (wrap-subst w) mod) x))
   (else (decorate-source x s)
-(rebuild-macro-output (p (source-wrap e (anti-mark w) s mod))
-  (new-mark
+(with-fluids ((transformer-environment
+   (lambda (k) (k e r w s rib mod
+  (rebuild-macro-output (p (source-wrap e (anti-mark w) s mod))
+(new-mark)
 
 (define expand-body
   ;; In processing the forms of the body, we create a new, empty wrap.
@@ -2435,6 +2445,31 @@
 (set! syntax-source
   (lambda (x) (source-annotation x)))
 
+(set! syntax-local-binding
+  (lambda (id)
+(arg-check nonsymbol-id? id 'syntax-local-value)
+(with-transformer-environment
+ (lambda (e r w s rib mod)
+   (define (strip-anti-mark w)
+ (let ((ms (wrap-marks w)) (s (wrap-subst w)))
+   (if (and (pair? ms) (eq? (car ms) the-anti-mark))
+   ;; output is from original text
+   (make-wrap (cdr ms) (if rib (cons rib (cdr s)) (cdr s)))
+   ;; output introduced by macro
+   (error what!!!
+   (let ((label (id-var-name (syntax-object-expression id)
+ (strip-anti-mark (syntax-object-wrap id)
+ (if (not (string? label))
+ (error identifier not lexically bound id))
+ (let ((b (assq-ref r label)))
+   (if (not b)
+   (error displaced lexical id))
+   (case (binding-type b)
+ ((lexical) (values 'lexical (binding-value b)))
+ ((macro) (values 'local-macro (binding-value b)))
+ ((syntax) (values 'pattern-variable (binding-value b)))
+ (else (error unpossible! b)
+
 (set! generate-temporaries
   (lambda (ls)
 (arg-check list? ls 'generate-temporaries)
-- 
1.7.8.3


-- 
http://wingolog.org/


Throw without catch before boot:

2012-01-15 Thread David Kastrup

Well, deciding to use my guile checkout not just for reference, I tried
./autogen.sh, ./configure and make on master.

For one thing it is an aggravation that configure stops at the first
unfound library dependency instead of going on and creating a report for
all of them.  That means that it takes O(n^2) time to get n dependencies
in place.

For another, I end up with

make[3]: Entering directory `/usr/local/tmp/guile/libguile'
  GENguile-procedures.texi
Throw without catch before boot:
Throw to key misc-error with args (module-transformer no module, and 
`macroexpand' unbound () #f)Aborting.
/bin/bash: line 1:  8604 Broken pipe cat alist.doc arbiters.doc 
array-handle.doc array-map.doc arrays.doc async.doc backtrace.doc boolean.doc 
bitvectors.doc bytevectors.doc chars.doc control.doc continuations.doc 
debug.doc deprecated.doc deprecation.doc dynl.doc dynwind.doc eq.doc error.doc 
eval.doc evalext.doc expand.doc extensions.doc feature.doc filesys.doc 
fluids.doc foreign.doc fports.doc gc-malloc.doc gc.doc gettext.doc 
generalized-arrays.doc generalized-vectors.doc goops.doc gsubr.doc 
guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc ioext.doc 
keywords.doc list.doc load.doc macros.doc mallocs.doc memoize.doc modules.doc 
numbers.doc objprop.doc options.doc pairs.doc ports.doc print.doc procprop.doc 
procs.doc promises.doc r6rs-ports.doc random.doc rdelim.doc read.doc root.doc 
rw.doc scmsigs.doc script.doc simpos.doc smob.doc sort.doc srcprop.doc 
srfi-1.doc srfi-4.doc srfi-13.doc srfi-14.doc srfi-60.doc stackchk.doc 
stacks.doc stime.doc strings.doc strorder.doc strports.doc struct.doc 
symbols.doc threads.doc throw.doc trees.doc uniform.doc values.doc variable.doc 
vectors.doc version.doc vports.doc weak-set.doc weak-table.doc weak-vector.doc 
dynl.doc posix.doc net_db.doc socket.doc regex-posix.doc
  8605 Aborted | GUILE_AUTO_COMPILE=0 
../meta/uninstalled-env guild snarf-check-and-output-texi  
guile-procedures.texi
make[3]: *** [guile-procedures.texi] Error 1
make[3]: Leaving directory `/usr/local/tmp/guile/libguile'
make[2]: *** [all] Error 2
make[2]: Leaving directory `/usr/local/tmp/guile/libguile'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/usr/local/tmp/guile'
make: *** [all] Error 2

Is that expected?

-- 
David Kastrup




Re: Throw without catch before boot:

2012-01-15 Thread Mark H Weaver
David Kastrup d...@gnu.org writes:
 Well, deciding to use my guile checkout not just for reference, I tried
 ./autogen.sh, ./configure and make on master.

For now, it's best to stay on the stable-2.0 branch.
That's our current focus.

 Mark



Re: [PATCH] local-eval, local-compile, and the-environment (v3)

2012-01-15 Thread David Kastrup
Mark H Weaver m...@netris.org writes:

 David Kastrup d...@gnu.org writes:

 Mark H Weaver m...@netris.org writes:

 David Kastrup d...@gnu.org writes:

 I am not sure that the reasons for not permitting definition context in
 local-eval are not of somewhat more theoretical than practical nature,

 There's at least one practical reason not to allow it, namely that it is
 _impossible_ to implement.  Consider this:

   (let ((x 1))
 (define (get-x) x)
 (the-environment))

 If we allow (the-environment) to add definitions to the implicit
 `letrec',

 Then just let's not allow it.  Consider the body of local-eval to be
 wrapped inside of an implicit (begin ...).

 I think you mean an implicit (let () ...).  If that's what you want,
 then you can do it yourself, and the result will be less likely to
 confuse.

What is confusing here?  Obviously, definitions made in the scope of
local-eval can't retroactively affect the environment where
the-environment was called.  And now instead of continuing with the
unfriendly For this reason, they are prohibited. we continue with You
may consider the local-eval body as being wrapped inside of an implicit
(let () ...).

I repeat: is there any valid construct under the currently proposed
local-eval code that would change its behavior?

 Is there any currently valid construct that would change its
 behavior?  If not, you _gain_ functionality, and the resulting
 semantics are still straightforward to explain as far as I can see.

 I don't understand this at all.  Change what behavior?

The behavior of local-eval given arbitrary expressions.  Are there any
expressions currently valid that would change their behavior if the body
of local-eval were wrapped in an implicit (let () ...)?

 What functionality do you gain?

The ability to make definitions valid in the local-eval without having
to write (let () ...).  Again: any drawback that is more substantial
than I just don't want you to do that?

-- 
David Kastrup




Re: Throw without catch before boot:

2012-01-15 Thread David Kastrup
Mark H Weaver m...@netris.org writes:

 David Kastrup d...@gnu.org writes:
 Well, deciding to use my guile checkout not just for reference, I tried
 ./autogen.sh, ./configure and make on master.

 For now, it's best to stay on the stable-2.0 branch.
 That's our current focus.

Interesting.

-- 
David Kastrup




Re: [PATCH] local-eval, local-compile, and the-environment (v3)

2012-01-15 Thread Mark H Weaver
David Kastrup d...@gnu.org writes:

 Mark H Weaver m...@netris.org writes:

 David Kastrup d...@gnu.org writes:

 Mark H Weaver m...@netris.org writes:

 David Kastrup d...@gnu.org writes:

 I am not sure that the reasons for not permitting definition context in
 local-eval are not of somewhat more theoretical than practical nature,

 There's at least one practical reason not to allow it, namely that it is
 _impossible_ to implement.  Consider this:

   (let ((x 1))
 (define (get-x) x)
 (the-environment))

 If we allow (the-environment) to add definitions to the implicit
 `letrec',

 Then just let's not allow it.  Consider the body of local-eval to be
 wrapped inside of an implicit (begin ...).

 I think you mean an implicit (let () ...).  If that's what you want,
 then you can do it yourself, and the result will be less likely to
 confuse.

 What is confusing here?  Obviously, definitions made in the scope of
 local-eval can't retroactively affect the environment where
 the-environment was called.  And now instead of continuing with the
 unfriendly For this reason, they are prohibited. we continue with You
 may consider the local-eval body as being wrapped inside of an implicit
 (let () ...).

If you want to include local definitions, then you'll need to wrap the
form passed to `local-eval' within (begin ...) anyway.  If you're doing
that, why not just wrap them in (let () ...) instead?  Is it really more
work to type #`(let () #,@forms) than #`(begin #,@forms) ?

I would like for users to be able to use the simple mental model that
the local expression is simply put in place of (the-environment).
I'd also like to achieve the following source-level equivalence:

  expr == (local-eval 'expr (the-environment))

You are suggesting that we wrap the expression within a (let () ...),
for the dubious benefit of allowing you to wrap the local forms in
(begin ...) instead of (let () ...).

I don't see any compelling benefit to this.  On the other hand, I see
less elegant semantics and potential confusion among users, who might
reasonably expect the definitions in their (begin ...) to be added to
the implicit `letrec', as would happen if the (begin ...) were put in
place of (the-environment).

 Mark



Re: [PATCH] local-eval, local-compile, and the-environment (v3)

2012-01-15 Thread Mark H Weaver
David Kastrup d...@gnu.org writes:

 You are suggesting that we wrap the expression within a (let () ...),
 for the dubious benefit of allowing you to wrap the local forms in
 (begin ...) instead of (let () ...).

 Are there even situations where you could put definitions after begin?
 How are they different from the situation where you can't?

 I don't see any compelling benefit to this.  On the other hand, I see
 less elegant semantics and potential confusion among users, who might
 reasonably expect the definitions in their (begin ...) to be added to
 the implicit `letrec', as would happen if the (begin ...) were put in
 place of (the-environment).

 begin can start with definitions, but not always?  But (let () ...) can?

 Scheme is weird.

`begin' is indeed quite weird in Scheme.  Its meaning depends on the
context where it is found:

* In expression context, it is like `progn' in Lisp.  It evaluates the
  expressions in order from left to right, and returns the value(s) of
  the last expression.

* At the top-level, or within an internal body where local definitions
  are allowed (i.e. if every form above it in the internal body is a
  definition), it is a _splicing_ operator: it acts as if the contents
  of the begin were spliced into the surrounding context.  This is
  mainly for the benefit of macros, so that they may expand into
  multiple definitions.

For example:

  (let ((x 1))
(define (get-x) x)
(begin
  (define x 2)
  (get-x)))

is equivalent to:

  (let ((x 1))
(define (get-x) x)
(define x 2)
(get-x))

which is equivalent to:

  (let ((x 1))
(letrec ((get-x (lambda () x))
 (x 2))
  (get-x)))

and therefore the result is 2, because the reference to `x' within
(get-x) refers to the inner binding of `x'.

 Mark



Re: [PATCH] local-eval, local-compile, and the-environment (v3)

2012-01-15 Thread David Kastrup
Mark H Weaver m...@netris.org writes:

 David Kastrup d...@gnu.org writes:

 You are suggesting that we wrap the expression within a (let () ...),
 for the dubious benefit of allowing you to wrap the local forms in
 (begin ...) instead of (let () ...).

 Are there even situations where you could put definitions after begin?
 How are they different from the situation where you can't?

 I don't see any compelling benefit to this.  On the other hand, I see
 less elegant semantics and potential confusion among users, who might
 reasonably expect the definitions in their (begin ...) to be added to
 the implicit `letrec', as would happen if the (begin ...) were put in
 place of (the-environment).

 begin can start with definitions, but not always?  But (let () ...) can?

 Scheme is weird.

 `begin' is indeed quite weird in Scheme.  Its meaning depends on the
 context where it is found:

 * In expression context, it is like `progn' in Lisp.  It evaluates the
   expressions in order from left to right, and returns the value(s) of
   the last expression.

 * At the top-level, or within an internal body where local definitions
   are allowed (i.e. if every form above it in the internal body is a
   definition), it is a _splicing_ operator: it acts as if the contents
   of the begin were spliced into the surrounding context.  This is
   mainly for the benefit of macros, so that they may expand into
   multiple definitions.

Well, what if begin were able to splice definitions into the original
lexical context of the-environment?  I think it would be strange if a
continuation taken in that context would get to see new definitions.
And if a continuation there does not get to see it, it would be strange
if successive calls of local-eval on the same environment got to see it.

So there is not much of a sensible option except an implicit (let ()
...) wrapper for the sake of splicing begin, or bugging out for new
definitions.

In the light of local-eval evaluating a _form_ rather than a _body_
(stupid of me to forget), and seeing the weird semantics of begin, I
agree that an implicit (let () ...) wrapper for a single form does not
really appear to add significant gains.  It would be marginally
convenient and marginally confusing.

So one might as well forget about it.

-- 
David Kastrup




Re: [PATCH] local-eval, local-compile, and the-environment (v3)

2012-01-15 Thread David Kastrup
David Kastrup d...@gnu.org writes:

 In the light of local-eval evaluating a _form_ rather than a _body_
 (stupid of me to forget), and seeing the weird semantics of begin, I
 agree that an implicit (let () ...) wrapper for a single form does not
 really appear to add significant gains.  It would be marginally
 convenient and marginally confusing.

 So one might as well forget about it.

Except possibly for symmetry: how does plain eval handle it?

guile (let ((x 2)) (eval '(begin (define x 4) x) (current-module)))
4
guile x
4
guile

Right through to the top.  And we couldn't do that in local-eval.  But
it also has no qualms just because previously evaluated forms would have
used a previous definition of x.  But that's because of top-level.  Eval
is always top-level, and define acts like set! there.

What if the-environment had been taken at top-level (basically just
carrying the information of (current-module))?  Should local-eval then
behave accordingly?  If so, could we not just fold eval and local-eval
into one function?  And one could then define
(define current-module
  (let ((top-level (the-environment)))
(lambda () (eval '(the-environment) top-level
if the-environment just returns the current module when at top level?

Basically, I can accept your reasoning.  This is just putting out a bit
of brainstorming.

-- 
David Kastrup




Re: Reference documentation of modules and library

2012-01-15 Thread Ludovic Courtès
Hi Mike!

Mike Gran spk...@yahoo.com skribis:

 Much of Slib still works.  It does use some removed functions.

Good to know.  Though if it “uses” removed functions, it doesn’t
completely work?  :-)

 The installation has problems.  Its makefile installs slib into
 a directory that Guile doesn't search, and the makefile needs to be
 modified to run at all if Jaffer's scm is not installed.
  
 I ended up writing my own autotools wrapper for slib to get it to
 install.

Perhaps you should submit to SLIB, since SLIB is now a GNU project.

Thanks,
Ludo’.




local-eval on syntax-local-binding, bound-identifiers

2012-01-15 Thread Andy Wingo
Hi Mark,

I had made some noise about preferring an implementation of local-eval
based on primitives from psyntax.  But, I didn't clarify my argument by
providing the primitives.  Here are some patches that provide
syntax-local-binding, as I noted in my previous mail, and also a
procedure to get all identifiers that are visible within the scope of
another identifier.

I then refactored your patch to implement local-eval entirely in terms
of these primitives and other normal macrology.  What do you think?  In
the interests of time and debugging, I removed the support for pattern
variables; it should be easy to add back.

These are preliminary patches, but if this approach proves to be viable,
I would prefer it to one that bakes the-environment into psyntax.

WDYT?

Regards,

Andy

From 48d8e52e316984f2bf9380df85079bb5fa142253 Mon Sep 17 00:00:00 2001
From: Andy Wingo wi...@pobox.com
Date: Sun, 15 Jan 2012 17:51:02 +0100
Subject: [PATCH 1/3] add syntax-local-binding

* module/ice-9/boot-9.scm (syntax-local-binding): New binding.

* module/ice-9/psyntax.scm: Locally define a fluid that holds the
  transformer environment.  with-transformer-environment calls a
  procedure with the transformer environment, or raises an error if
  called outside the extent of a transformer.  Bind
  transformer-environment in expand-macro.
  (syntax-local-binding): New procedure to return binding information of
  a lexically bound identifier (a lexical, local macro, a pattern
  variable, or a displaced lexical).
---
 module/ice-9/boot-9.scm  |1 +
 module/ice-9/psyntax.scm |   39 +--
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index f661d08..9cdd8d1 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -389,6 +389,7 @@ If there is no handler at all, Guile prints an error and then exits.
 (define generate-temporaries #f)
 (define bound-identifier=? #f)
 (define free-identifier=? #f)
+(define syntax-local-binding #f)
 
 ;; $sc-dispatch is an implementation detail of psyntax. It is used by
 ;; expanded macros, to dispatch an input against a set of patterns.
diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm
index 1bf3c32..30685bc 100644
--- a/module/ice-9/psyntax.scm
+++ b/module/ice-9/psyntax.scm
@@ -786,6 +786,14 @@
   id))
  (else (syntax-violation 'id-var-name invalid id id)
 
+(define transformer-environment
+  (make-fluid
+   (lambda (k)
+ (error called outside the dynamic extent of a syntax transformer
+
+(define (with-transformer-environment k)
+  ((fluid-ref transformer-environment) k))
+
 ;; free-id=? must be passed fully wrapped ids since (free-id=? x y)
 ;; may be true even if (free-id=? (wrap x w) (wrap y w)) is not.
 
@@ -1321,8 +1329,10 @@
(syntax-violation #f encountered raw symbol in macro output
  (source-wrap e w (wrap-subst w) mod) x))
   (else (decorate-source x s)
-(rebuild-macro-output (p (source-wrap e (anti-mark w) s mod))
-  (new-mark
+(with-fluids ((transformer-environment
+   (lambda (k) (k e r w s rib mod
+  (rebuild-macro-output (p (source-wrap e (anti-mark w) s mod))
+(new-mark)
 
 (define expand-body
   ;; In processing the forms of the body, we create a new, empty wrap.
@@ -2435,6 +2445,31 @@
 (set! syntax-source
   (lambda (x) (source-annotation x)))
 
+(set! syntax-local-binding
+  (lambda (id)
+(arg-check nonsymbol-id? id 'syntax-local-value)
+(with-transformer-environment
+ (lambda (e r w s rib mod)
+   (define (strip-anti-mark w)
+ (let ((ms (wrap-marks w)) (s (wrap-subst w)))
+   (if (and (pair? ms) (eq? (car ms) the-anti-mark))
+   ;; output is from original text
+   (make-wrap (cdr ms) (if rib (cons rib (cdr s)) (cdr s)))
+   ;; output introduced by macro
+   (make-wrap ms (if rib (cons rib s) s)
+   (let ((label (id-var-name (syntax-object-expression id)
+ (strip-anti-mark (syntax-object-wrap id)
+ (if (not (string? label))
+ (error identifier not lexically bound id))
+ (let ((b (assq-ref r label)))
+   (if b
+   (case (binding-type b)
+ ((lexical) (values 'lexical (binding-value b)))
+ ((macro) (values 'local-macro (binding-value b)))
+ ((syntax) (values 'pattern-variable (binding-value b)))
+ (else (error unpossible! b)))
+   (values 

Re: local-eval on syntax-local-binding, bound-identifiers

2012-01-15 Thread Mark H Weaver
Hi Andy,

Thanks very much for heeding my call for `local-eval' in 2.0.4, and
for putting so much time into this.

For the record, I still think it's better for `the-environment' to be
implemented within psyntax as a core form.  It's a fundamental syntactic
construct with clean semantics, and it belongs in psyntax with its
brethren.  Your desire to remove it from psyntax has caused you to add
far less elegant interfaces that have been hastily designed, and that
may not even be sufficient for a full implementation of
`the-environment' that captures mutually-recursive local macros.

That said, there's a lot to like in your implementation, and it has some
notable improvements over mine.  It also has some problems, not all of
which are trivial.

Please see below, where I have inserted specific questions and comments
into your patch.

  Thanks again,
  Mark


[... skipped the first patch, which looks very well implemented, though
 I'm still not sure that we should be exposing this in our API ...]

 From 2c3da44320019453115811af386febaa7eb241c3 Mon Sep 17 00:00:00 2001
 From: Andy Wingo wi...@pobox.com
 Date: Sun, 15 Jan 2012 18:39:44 +0100
 Subject: [PATCH 2/3] add bound-identifiers

 * module/ice-9/boot-9.scm (bound-identifiers): Declare variable.
 * module/ice-9/psyntax.scm: Add all-bound-identifiers helper, and define
   bound-identifiers.  The identifiers are anti-marked so that syntax
   transformers can introduce them, as-is.
 ---
  module/ice-9/boot-9.scm  |1 +
  module/ice-9/psyntax.scm |   49 
 ++
  2 files changed, 50 insertions(+), 0 deletions(-)

 diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
 index 9cdd8d1..b8aa842 100644
 --- a/module/ice-9/boot-9.scm
 +++ b/module/ice-9/boot-9.scm
 @@ -389,6 +389,7 @@ If there is no handler at all, Guile prints an error and 
 then exits.
  (define generate-temporaries #f)
  (define bound-identifier=? #f)
  (define free-identifier=? #f)
 +(define bound-identifiers #f)
  (define syntax-local-binding #f)
  
  ;; $sc-dispatch is an implementation detail of psyntax. It is used by
 diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm
 index 30685bc..25543e0 100644
 --- a/module/ice-9/psyntax.scm
 +++ b/module/ice-9/psyntax.scm
 @@ -786,6 +786,48 @@
id))
   (else (syntax-violation 'id-var-name invalid id id)
  
 +;;
 +;; all-bound-identifiers returns a list of all lexically bound
 +;; identifiers, as syntax objects.  They are in order from outer to
 +;; inner.
 +;;
 +(define all-bound-identifiers
 +  (lambda (w mod)
 +(define scan
 +  (lambda (subst results)
 +(if (null? subst)
 +results
 +(let ((fst (car subst)))
 +  (if (eq? fst 'shift)
 +  (scan (cdr subst) results)
 +  (let ((symnames (ribcage-symnames fst))
 +(marks (ribcage-marks fst)))
 +(if (vector? symnames)
 +(scan-vector-rib subst symnames marks results)
 +(scan-list-rib subst symnames marks 
 results
 +(define scan-list-rib
 +  (lambda (subst symnames marks results)
 +(let f ((symnames symnames) (marks marks) (results results))
 +  (if (null? symnames)
 +  (scan (cdr subst) results)
 +  (f (cdr symnames) (cdr marks)
 + (cons (wrap (car symnames)
 + (anti-mark (make-wrap (car marks) subst))

* Why are you adding anti-marks here?

 + mod)
 +   results))
 +(define scan-vector-rib
 +  (lambda (subst symnames marks results)
 +(let ((n (vector-length symnames)))
 +  (let f ((i 0) (results results))
 +(if (fx= i n)
 +(scan (cdr subst) results)
 +(f (fx+ i 1)
 +   (cons (wrap (vector-ref symnames i)
 +   (anti-mark (make-wrap (vector-ref marks 
 i) subst))

* Ditto.

 +   mod)
 + results)))
 +(scan (wrap-subst w) '(
 +
  (define transformer-environment
(make-fluid
 (lambda (k)
 @@ -2470,6 +2512,13 @@
   (else (error unpossible! b)))
 (values 'displaced-lexical #f
  
 +(set! bound-identifiers
 +  (lambda (x)
 +(arg-check nonsymbol-id? x 'bound-identifiers)
 +(reverse
 + (all-bound-identifiers (syntax-object-wrap x)
 +(syntax-object-module x)
 +
  (set! generate-temporaries
(lambda (ls)
  (arg-check list? ls 'generate-temporaries)
 -- 
 

Re: [PATCH] local-eval, local-compile, and the-environment (v3)

2012-01-15 Thread David Kastrup
Mark H Weaver m...@netris.org writes:

 What if the-environment had been taken at top-level (basically just
 carrying the information of (current-module))?  Should local-eval then
 behave accordingly?  If so, could we not just fold eval and local-eval
 into one function?

 This is a good question.  Unfortunately, there is a non-trivial
 difference in the semantics of `eval' vs `local-eval'.

 `eval' temporarily sets the (current-module) to its second argument
 during evaluation of the expression.

 `local-eval' does not do this, and as I recall that was something you
 felt strongly about (and I agree).

I don't think I would feel as strong about it if the argument was a
module, implicating top-level.  It is probably not all that easy to get
the-environment at top level.

 And one could then define
 (define current-module
   (let ((top-level (the-environment)))
 (lambda () (eval '(the-environment) top-level
 if the-environment just returns the current module when at top level?

 I see what you're getting at, but this would be a bad idea, because it
 still makes sense to have `module' be an independent type.

It might come handy to have local-eval not balk upon getting a module,
but without letting it set the current module.  At times, this
functionality might come in handy.  It would also be clear then why eval
would have to balk on every non-module (== non-top-level) environment.

 Also, in the code above, `top-level' would not actually be a top-level
 environment, because (the-environment) is not a top-level form.  If you
 put (define x 5) in place of (the-environment), it would not set a
 top-level variable; it would produce an error.

I am not saying that the actual code would need to work.  It was more
intended as a show of equivalences.

-- 
David Kastrup



Re: [PATCH] local-eval, local-compile, and the-environment (v3)

2012-01-15 Thread Mark H Weaver
David Kastrup d...@gnu.org writes:
 It might come handy to have local-eval not balk upon getting a module,
 but without letting it set the current module.

Agreed, and my implementation of `local-eval' does exactly that.

 Mark