unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* comments on new-model.txt
@ 2002-09-05  1:22 Lynn Winebarger
  2002-09-05 19:06 ` Marius Vollmer
  0 siblings, 1 reply; 16+ messages in thread
From: Lynn Winebarger @ 2002-09-05  1:22 UTC (permalink / raw)



   Marius has written a detailed proposal for a new model, most of
which is dedicated to the nature of modules and scoping rules.
I'm glad he did, because Guile needs some clear direction on
this front.  That said, I'm a little distressed by the proposed
module/variable semantics.
    Before directly commenting, I would like to point out that there
are at least 3(*) orthogonal choices to be made in defining a type of 
environment:

(1)  Is the environment lexically closed or open?  That is, can
      new bindings be added to it, or is the set of
      bindings immutable once initialized?
(2)  Is it a black box to code defined externally?  In other words,
      can values be exported or not?
(3)  Is the code that uses the environment a body or interactive?
      In a (lambda) body, there is a well-defined lexographic 
      boundary between definitions (both variable and syntax)
      and other code (both before and after macro expansion).  
      In an interactive environment, executing
      a lambda at one point in time can result in a "variable not bound"
      error, when at other times it might not.

  Environments that are open in sense (1) are usually referred to as
top-level, though there is no absolute reason such an environment
must in fact be at the top-level. 
   The properties described by (2) could also be called closed and
open.  Indeed, compiler writers refer to exported values as ones
that have escaped (from the optimizer, perhaps).  Unfortunately,
that nomenclature is easily confused with (1).
    Marius' proposed system makes choices <open,open,interactive>.
If by a module we mean a set of code that is meant as a unit for
separate compilation, I believe the right choices are <closed,open,body>
It may be desirable to have other types of environments readily available
as well (perhaps "top-level" environments for each thread that inherit
from a global "top-level" environment?), but I don't believe they should
be considered part of the module system.
    There is no reason to require macros to always be macros.  R5RS does
not have any such requirement and there are plenty of compilers for it.
     I do not agree with the stated use of the word "variable".  That term
has such a standard definition that I believe it is only confusing to
recast it to mean "generic box" (in the "smart variable" case).  A
(global/top-level) variable is precisely its name in a program.  If you
want to make a special generic kind of box that, when bound to
a variable is, let's call it "transparently generic", go for it, but don't
say variables don't have names.
    Rather than tying imported variables to solely to modules, I believe
GUILE should adopt 2 new types of variables, extloc and extvar (or
whatever) corresponding to ilocs and variables, but carrying a reference
to their environment with them.  Space might be conserved by
pointing into a table of environments rather than using a whole
pointer.  In this way we can untie option 2 from options 1 and 3.
    To handle optimization, I believe we could adopt special forms
that import values and bind them to local (possibly immutable) variables.
So (import <module> <variable> ...) would give you a variable such
that side-effects on it are seen by <module>'s code. 
import->local would bind the variable locally to its value in <module>,
                     preserving (im)mutability
import->local/mutable would bind a locally mutable copy.
import->local/immutable would bind a locally immutable copy.
    I believe these would be sufficient for compiler optimizations.  
A "core" module would contain all the basic scheme forms (immutable)
and these could be imported/localized into the top-level interaction
environment, while most modules would just import them directly.

Lynn


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt
  2002-09-05  1:22 comments on new-model.txt Lynn Winebarger
@ 2002-09-05 19:06 ` Marius Vollmer
  2002-09-08 23:47   ` Lynn Winebarger
  2002-09-14  3:18   ` comments on new-model.txt [long] Lynn Winebarger
  0 siblings, 2 replies; 16+ messages in thread
From: Marius Vollmer @ 2002-09-05 19:06 UTC (permalink / raw)
  Cc: guile-devel

Lynn Winebarger <owinebar@free-expression.org> writes:

>    Marius has written a detailed proposal for a new model, most of
> which is dedicated to the nature of modules and scoping rules.

Ick, it's in CVS (workbook/compilation/), but I'm not yet really
prepared to defend it! ;)

Actually, I have tried to keep the module system out of the model as
much as possible.  The interface between the module system and a
hypthetical compiler is quite minimal.  The module system is very
important for the overall behavior of the system, but my intention is
to allow large changes to the module system without having to change
the compiler.

The biggest requirement that the proposal puts on the module system is
that modules can only ever grow; you can not remove bindings or change
existing ones.  I expect this to be a popular point for debate, and I
don't know if I can defend it successfully.  But the current model
rests on this requirement.

(When you want to change a module in a way that is not allowed, like
removing a binding, or importing a name from a different module, you
need to make a new module with the same name and fill it from scratch,
probably by recompiling/reloading it.  Modules that depend on your
module might also need to be recompiled/reloaded to pick up the
changes.  Maybe we can have support for constructing new modules in a
way that they export the exact same bindings that a given other module
does.  That way, the recompile avalanche could be stopped early.)

>     Marius' proposed system makes choices <open,open,interactive>.
> If by a module we mean a set of code that is meant as a unit for
> separate compilation, I believe the right choices are
> <closed,open,body>.

I hope that the model is 'open' enough to allow all variants.  I'd say
that when you have a model that allows <open, open, interactive>, you
can get the other variants via additional, external restrictions that
don't require changes to the model.

For example, the lexical option for (1) can be implemented within the
module system by allowing a module to be 'sealed' so that no further
bindings can be added to it.  That is compatible with the model.

Option 'closed' for (2) can likewise be implemented within the module
system by simply not offering any way to export names.  The model
doesn't care.

Option 'body' for (3) is harder to enforce in the module system, but
it is easy to add in the macro expansion pass which is also not
treated in detail in the proposal.

My goal for the new model was to specify something that would be
straightforward to implement, offer enough opportunities for a smart
compiler to optimize things, and still be reasonably flexible for
interactive use.

>     There is no reason to require macros to always be macros.  R5RS does
> not have any such requirement and there are plenty of compilers for it.

You can change a macro into a function, but you need to
recompile/reload your code for it to take effect.  That's about all
that the model implies.  Also, you can't redefine a name in a module,
but I think that is reasonable.

>      I do not agree with the stated use of the word "variable".  That term
> has such a standard definition that I believe it is only confusing to
> recast it to mean "generic box" (in the "smart variable" case).

Well, it's only terminology.  What you seem to call "variable", I
would call "identifier".  I agree that terminology is important,
ultimately, and I can change the word "variable" to "box" or
"location", but I don't want to be distracted by this just yet.

>     Rather than tying imported variables to solely to modules, I
> believe GUILE should adopt 2 new types of variables, extloc and
> extvar (or whatever) corresponding to ilocs and variables, but
> carrying a reference to their environment with them.  Space might be
> conserved by pointing into a table of environments rather than using
> a whole pointer.  In this way we can untie option 2 from options 1
> and 3.

I don't understand.  Can you explain?

>     To handle optimization, I believe we could adopt special forms
> that import values and bind them to local (possibly immutable)
> variables. [...]

This sounds more complicated than the 'declarations' feature of the
proposal.  The declarations have the advantage that you don't need to
do anything special when importing a name, the burdon is on the
definer of the name.

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt
  2002-09-05 19:06 ` Marius Vollmer
@ 2002-09-08 23:47   ` Lynn Winebarger
  2002-09-09 22:55     ` Marius Vollmer
  2002-09-14  3:18   ` comments on new-model.txt [long] Lynn Winebarger
  1 sibling, 1 reply; 16+ messages in thread
From: Lynn Winebarger @ 2002-09-08 23:47 UTC (permalink / raw)
  Cc: guile-devel

On Thursday 05 September 2002 14:06, Marius Vollmer wrote:
> Lynn Winebarger <owinebar@free-expression.org> writes:
> Ick, it's in CVS (workbook/compilation/), but I'm not yet really
> prepared to defend it! ;)
    Well, when I saw it appear on guile-cvs, I had to check it out.
I'm surprised there haven't been other responses, but maybe
the beginning of the academic year affects a lot of people here. 
     I'm not ready to respond completely, but I can clarify something.

> >     Rather than tying imported variables to solely to modules, I
> > believe GUILE should adopt 2 new types of variables, extloc and
> > extvar (or whatever) corresponding to ilocs and variables, but
> > carrying a reference to their environment with them.  Space might be
> > conserved by pointing into a table of environments rather than using
> > a whole pointer.  In this way we can untie option 2 from options 1
> > and 3.
> 
      So, we have two SCM types, ilocs and variables (actually variable bindings,
but we can leave that for later).   ilocs always look up their values in the
data environment of their closure, and variables are just pointers to a
storage location.  An extloc would be like an iloc (that is, a frame offset
and distance in a frame), but would be stored in a cell where the second
word pointed to the data environment to look it up in (the first word would
contain the frame offset and distance).  Likewise an extvarref would 
contain both the pointer to the binding and some way of identifying
what top-level environment it's from.
     This would be a convenient way to represent imported variables.
The only concrete reason I can offer for including a pointer (of some 
form) to the top level environment of an external variable (actually
any top-level variable) is for ones that aren't bound at the time
of parsing (recalling that correct macro expansion can't be lazy in
the presence of side-effects, as some of the syntax-case examples
I've been posting should demonstrate).  I have a feeling that the pointer
to the top-level environment might turn out to be useful in some other
way, but I couldn't say what that would be.
     
Lynn


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt
  2002-09-08 23:47   ` Lynn Winebarger
@ 2002-09-09 22:55     ` Marius Vollmer
  2002-09-10  0:30       ` Lynn Winebarger
  2002-09-11  7:28       ` Lynn Winebarger
  0 siblings, 2 replies; 16+ messages in thread
From: Marius Vollmer @ 2002-09-09 22:55 UTC (permalink / raw)
  Cc: guile-devel

Lynn Winebarger <owinebar@free-expression.org> writes:

>       So, we have two SCM types, ilocs and variables (actually
> variable bindings, but we can leave that for later).  ilocs always
> look up their values in the data environment of their closure, and
> variables are just pointers to a storage location.  An extloc would
> be like an iloc (that is, a frame offset and distance in a frame),
> but would be stored in a cell where the second word pointed to the
> data environment to look it up in (the first word would contain the
> frame offset and distance).

What use would be an extloc?  Do you want to export lexical variables?
Or would they be useful for hygienic macro expansion?  Can you give
example code that illustrates their use?

> Likewise an extvarref would contain both the pointer to the binding
> and some way of identifying what top-level environment it's from.

If we need to, we could find the originating module for a imported
variable also from the module that the current code is executed in.
This would be slower, but we would not need the extra pointer in
extvarrefs or variables.

> This would be a convenient way to represent imported variables.  The
> only concrete reason I can offer for including a pointer (of some
> form) to the top level environment of an external variable (actually
> any top-level variable) is for ones that aren't bound at the time of
> parsing (recalling that correct macro expansion can't be lazy in the
> presence of side-effects, as some of the syntax-case examples I've
> been posting should demonstrate).

What would you do with that pointer?

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt
  2002-09-09 22:55     ` Marius Vollmer
@ 2002-09-10  0:30       ` Lynn Winebarger
  2002-09-10  0:32         ` Lynn Winebarger
  2002-09-10 19:56         ` Marius Vollmer
  2002-09-11  7:28       ` Lynn Winebarger
  1 sibling, 2 replies; 16+ messages in thread
From: Lynn Winebarger @ 2002-09-10  0:30 UTC (permalink / raw)
  Cc: guile-devel

On Monday 09 September 2002 17:55, Marius Vollmer wrote:
> Lynn Winebarger <owinebar@free-expression.org> writes:
> 
> >       So, we have two SCM types, ilocs and variables (actually
> > variable bindings, but we can leave that for later).  ilocs always
> > look up their values in the data environment of their closure, and
> > variables are just pointers to a storage location.  An extloc would
> > be like an iloc (that is, a frame offset and distance in a frame),
> > but would be stored in a cell where the second word pointed to the
> > data environment to look it up in (the first word would contain the
> > frame offset and distance).
> 
> What use would be an extloc?  Do you want to export lexical variables?
     Yes
> Or would they be useful for hygienic macro expansion? 
      Not exactly, but the process of writing my own version of syntax-case
has made me think of variables in this way.
> Can you give
> example code that illustrates their use?
     Ok, I'll make up some incredibly bad notation
(exporting-lambda () 
   (define-exportable foo  'whatever)
   (define-exportable-syntax (lambda (x) (syntax-case x () ((_ f ...) (syntax 'xyzzy)))))
   ....)
       If we have extlocs, this can be just a plain lambda that happens
to let import take references to some of its variables.  Then we can
use the keyword "module" instead.

> > Likewise an extvarref would contain both the pointer to the binding
> > and some way of identifying what top-level environment it's from.
> 
> If we need to, we could find the originating module for a imported
> variable also from the module that the current code is executed in.
> This would be slower, but we would not need the extra pointer in
> extvarrefs or variables.

     Part of the disagreement is that I don't think we should
"evaluate in" modules. Partly this is a terminology issue:  I think
"module" should be reserved for separately compilable units of
code that won't be invisibly dependent on whatever code happens
to be currently loaded ("invisibly" is because imports are clearly
visible to the module-using programmer, so are not prohibited).
    We should have some other terminology to describe other types
of namespaces.  Being able to import/export variables is just one
knob on a namespace/environment/whatever.
    And then there's Dirk's view of modules as parameterizable to
get a handle on too.

> > This would be a convenient way to represent imported variables.  The
> > only concrete reason I can offer for including a pointer (of some
> > form) to the top level environment of an external variable (actually
> > any top-level variable) is for ones that aren't bound at the time of
> > parsing (recalling that correct macro expansion can't be lazy in the
> > presence of side-effects, as some of the syntax-case examples I've
> > been posting should demonstrate).
> 
> What would you do with that pointer?

     I'm thinking about it.

Lynn


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt
  2002-09-10  0:30       ` Lynn Winebarger
@ 2002-09-10  0:32         ` Lynn Winebarger
  2002-09-10 19:56         ` Marius Vollmer
  1 sibling, 0 replies; 16+ messages in thread
From: Lynn Winebarger @ 2002-09-10  0:32 UTC (permalink / raw)
  Cc: guile-devel


Doh!

On Monday 09 September 2002 19:30, Lynn Winebarger wrote:
> (exporting-lambda () 
>    (define-exportable foo  'whatever)
>    (define-exportable-syntax (lambda (x) (syntax-case x () ((_ f ...) (syntax 'xyzzy)))))
                                            ^bar                                            
>    ....)

Lynn


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt
  2002-09-10  0:30       ` Lynn Winebarger
  2002-09-10  0:32         ` Lynn Winebarger
@ 2002-09-10 19:56         ` Marius Vollmer
  2002-09-10 23:15           ` Tom Lord
  1 sibling, 1 reply; 16+ messages in thread
From: Marius Vollmer @ 2002-09-10 19:56 UTC (permalink / raw)
  Cc: guile-devel

Lynn Winebarger <owinebar@free-expression.org> writes:

> > Can you give example code that illustrates their use?
>
>      Ok, I'll make up some incredibly bad notation
>
> (exporting-lambda () 
>    (define-exportable foo  'whatever)
>    (define-exportable-syntax (lambda (x) (syntax-case x () ((_ f ...) (syntax 'xyzzy)))))
>    ....)
>
>        If we have extlocs, this can be just a plain lambda that
> happens to let import take references to some of its variables.
> Then we can use the keyword "module" instead.

Is this related to the 'module' feature of recent versions of Dybvig's
syntax-case implementation?  If so, I think that it is implemented
solely with renaming of identifiers and needs no support from the
interpreter.  Also, I think that the syntax-case modules are less
powerful than ours since their semantics are fixed while ours can be
cleanly extended.

>      Part of the disagreement is that I don't think we should
> "evaluate in" modules. Partly this is a terminology issue:  I think
> "module" should be reserved for separately compilable units of
> code that won't be invisibly dependent on whatever code happens
> to be currently loaded ("invisibly" is because imports are clearly
> visible to the module-using programmer, so are not prohibited).

You can use our current modules that way, but the new model is not
restricted to such a use.  The concept of "evaluating in a module" is
still there, even when modules are sealed compilation units.  It's not
strictly "evaluating" in a module, but the module is part of the
compile time environment and determines the meaning of identifiers
just as with our current situation, where modules are part of the
run-time environment.

>     We should have some other terminology to describe other types of
> namespaces.  Being able to import/export variables is just one knob
> on a namespace/environment/whatever.

Yes, and that's why there are little module system specifics in the
new model.  You can implement a wide variety of modules that are
compatible with it.

>     And then there's Dirk's view of modules as parameterizable to
> get a handle on too.

They are possible as well.

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt
  2002-09-10 19:56         ` Marius Vollmer
@ 2002-09-10 23:15           ` Tom Lord
  2002-09-11 17:38             ` Marius Vollmer
  0 siblings, 1 reply; 16+ messages in thread
From: Tom Lord @ 2002-09-10 23:15 UTC (permalink / raw)




MVO: you said your paper wasn't ready yet, and I'm taking you at your
word.

Please announce on this list when and if you'd like people in wildly
different contexts to review it.

-t




_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt
  2002-09-09 22:55     ` Marius Vollmer
  2002-09-10  0:30       ` Lynn Winebarger
@ 2002-09-11  7:28       ` Lynn Winebarger
  2002-09-11 18:11         ` Marius Vollmer
  1 sibling, 1 reply; 16+ messages in thread
From: Lynn Winebarger @ 2002-09-11  7:28 UTC (permalink / raw)
  Cc: guile-devel

On Monday 09 September 2002 17:55, Marius Vollmer wrote:
> > This would be a convenient way to represent imported variables.  The
> > only concrete reason I can offer for including a pointer (of some
> > form) to the top level environment of an external variable (actually
> > any top-level variable) is for ones that aren't bound at the time of
> > parsing (recalling that correct macro expansion can't be lazy in the
> > presence of side-effects, as some of the syntax-case examples I've
> > been posting should demonstrate).
> 
> What would you do with that pointer?

    Actually, I believe I was originally thinking of using it for macro
expansion purposes (so if a macro was bound to an external variable,
that top-level environment could be stacked on whatever the top-level
environment "currently" is for macro lookups.

Lynn


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt
  2002-09-10 23:15           ` Tom Lord
@ 2002-09-11 17:38             ` Marius Vollmer
  0 siblings, 0 replies; 16+ messages in thread
From: Marius Vollmer @ 2002-09-11 17:38 UTC (permalink / raw)
  Cc: guile-devel

Tom Lord <lord@regexps.com> writes:

> MVO: you said your paper wasn't ready yet, and I'm taking you at
> your word.

I said I wasn't ready to defend it :-) I will look over it once more
and probably clarify what it wants to address and what not, but feel
free to comment on it anyway.

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt
  2002-09-11  7:28       ` Lynn Winebarger
@ 2002-09-11 18:11         ` Marius Vollmer
  0 siblings, 0 replies; 16+ messages in thread
From: Marius Vollmer @ 2002-09-11 18:11 UTC (permalink / raw)
  Cc: guile-devel

Lynn Winebarger <owinebar@free-expression.org> writes:

> > What would you do with that pointer?
> 
>     Actually, I believe I was originally thinking of using it for macro
> expansion purposes (so if a macro was bound to an external variable,
> that top-level environment could be stacked on whatever the top-level
> environment "currently" is for macro lookups.

I plan to use the :module-ref 'assembly instruction' for this.  Macro
expanders would use it to refer to specific top-levels aka modules.
We need to be able to encode these references in object files, so we
need to use the names of modules, not pointers to the run-time objects
that implement modules.

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt [long]
  2002-09-05 19:06 ` Marius Vollmer
  2002-09-08 23:47   ` Lynn Winebarger
@ 2002-09-14  3:18   ` Lynn Winebarger
  2002-09-22 22:13     ` Marius Vollmer
  2002-09-24 20:03     ` Marius Vollmer
  1 sibling, 2 replies; 16+ messages in thread
From: Lynn Winebarger @ 2002-09-14  3:18 UTC (permalink / raw)
  Cc: guile-devel


Ok, I've had some time to think more, and so I want
to go back the beginning.  I've also included two
other emails I haven't yet responded to in chronological
order for completeness.

On Thursday 05 September 2002 14:06, Marius Vollmer wrote:
> Actually, I have tried to keep the module system out of the model as
> much as possible.  The interface between the module system and a
> hypthetical compiler is quite minimal.  The module system is very
> important for the overall behavior of the system, but my intention is
> to allow large changes to the module system without having to change
> the compiler.

     The problem is the very definition of what modules are.  That's what
I'm objecting to, and it is in there.  I can only assume this is in preservation
of the current module system, which is way too dynamic in nature.
"interactive-namespace" or "interactive-environment" would be a more
accurate term (as I've noted before).  Well, actually even that's not
quite accurate as an "interactive-namespace" would just be a type
of environment that might occur near the top of a lexical closure
- and that would be fixed for that closure (there would be no
changing the top-level of a particular closure in "interactive-namespace").

> The biggest requirement that the proposal puts on the module system is
> that modules can only ever grow; you can not remove bindings or change
> existing ones.  I expect this to be a popular point for debate, and I
> don't know if I can defend it successfully.  But the current model
> rests on this requirement.
      The biggest one is that there's a "current module" at evaluation
time and that it can be changed.  That's a _huge_ requirement.

> Option 'body' for (3) is harder to enforce in the module system, but
> it is easy to add in the macro expansion pass which is also not
> treated in detail in the proposal.
      But, as I understand it, this is one of the problems that has
been encountered in practice (the interaction between macro expansion
and the "module" system).

> >     There is no reason to require macros to always be macros.  R5RS does
> > not have any such requirement and there are plenty of compilers for it.
> 
> You can change a macro into a function, but you need to
> recompile/reload your code for it to take effect.  That's about all
> that the model implies.  Also, you can't redefine a name in a module,
> but I think that is reasonable.
      You see, I think this especially shows where my mental model of a
module differs from yours (and perhaps others).  A module should not
have anything to do with the current (interactive, or whatever) top-level
environment.  It's environment should have at its root its own top-level
environment (or not, if the compiler can determine it does not need one).
It might interact with the current environment by explicitly importing from
it (using some sort of reserved identifier for that purpose), and the 
linker/loader could decide (at run time) what top-level environment
to link it to (for example, if each thread has its own top-level environment
besides the thread-global top-level environment, the user might specify
linking to some specific thread, or might specify a fresh environment to use.
    So part of the miscommunication is that I've stopped thinking of
"top-level" (lexically open) environments necessarily being at the actual
top-level of a lexical environment.  It complicates define a little, but not
much.  

> >     To handle optimization, I believe we could adopt special forms
> > that import values and bind them to local (possibly immutable)
> > variables. [...]
> 
> This sounds more complicated than the 'declarations' feature of the
> proposal.  The declarations have the advantage that you don't need to
> do anything special when importing a name, the burdon is on the
> definer of the name.

     I almost always prefer code I'm using not to have some oddball
implicit semantics.  If it's going to do something weird, I should specify
that it does something weird.  Of course, you might provide special
forms to handle some of these things implicitly, but the core
mechanisms should not (and particularly, it should be the library
user's choice and not the library implementers about what is
done with the user's variables).  I object to global dynamic scoping
in general on the same grounds.
    I don't think it will hurt to reflect on this statement from R5RS either:

Following Algol, Scheme is a statically scoped programming language.
Each use of a variable is associated with a lexically apparent binding
of that variable.

   Now you may think I'm being pedantic, but I think discarding
that second sentence should at least give pause.

>>        If we have extlocs, this can be just a plain lambda that
>> happens to let import take references to some of its variables.
>> Then we can use the keyword "module" instead.
>
>Is this related to the 'module' feature of recent versions of Dybvig's
>syntax-case implementation?  If so, I think that it is implemented
>solely with renaming of identifiers and needs no support from the
>interpreter.  Also, I think that the syntax-case modules are less
>powerful than ours since their semantics are fixed while ours can be
>cleanly extended.

   To the extent that we're talking about lexically scoped closures
with exportable bindings, yes I suppose.  Though I'm not sure
what you mean by "cleanly extended".  Maybe you can give
an example of what you mean.
    Otherwise, see below.

>>     And then there's Dirk's view of modules as parameterizable to
>> get a handle on too.
>
> Lynn Winebarger <owinebar@free-expression.org> writes:
>
>> > What would you do with that pointer?
>> 
>>     Actually, I believe I was originally thinking of using it for macro
>> expansion purposes (so if a macro was bound to an external variable,
>> that top-level environment could be stacked on whatever the top-level
>> environment "currently" is for macro lookups.
>
>I plan to use the :module-ref 'assembly instruction' for this.  Macro
>expanders would use it to refer to specific top-levels aka modules.
>We need to be able to encode these references in object files, so we
>need to use the names of modules, not pointers to the run-time objects
>that implement modules.
           
    No.  There's no (good) reason for modules to have inherent names.   
There are good reasons for them to have fixed file names, but not
names that inhere in the module itself (any more than there is for functions, 
at least).  Indeed, if you have parameterized modules (that is, 1st there's
possibly a parameter of "current top-level enviroment to link to", and then
there are explicit imports (by the module) to be specified by the module
user, that will result in an instantiation of the module's data environment
that links to those.  Indeed, there's no particular reason to disallow modules
from being loaded multiple times with independent instantiations.  Like this;

(define a (load-module "foo"))
(define b (load-module "foo"))
(import a (prefix "a->"))
(import b (prefix "b->"))
(set! a->bar 5) 
(set! b->bar 7)
a->bar => 5
b->bar => 7

  So in this model, you could use modules you object with compiled methods
if you like.
   Heck, it might even be as simple as this to create a (trivial) module (in shell)
cat >"foo.ss" <<EOF
(import core)
(define a 5)
(export a)
EOF
cat >"compile-foo.ss" <<EOF
(compile-module "foo.ss" foo)
EOF
cat >"use-foo.ss" <<EOF
(load-module foo ((a -> b))
b => 5
(set! b 18)
b => 18
EOF

   If you can't tell, I think Guile should handle its own linking and loading, at least
as far as its own compiled modules go.      
   As regards syntax-case and macros/modules:  I don't believe Guile should use
Dybvig's portable Scheme implementation.  Even if it we had a compiler, it does
explicitly use symbols for renaming that somehow have to be unique across
compiler runs.  This may be necessary for a portable implementation, but I
think it's pretty undesirable.  The "renaming" doesn't have to involve
actual new names.  
   In my (unfinished) implementation, I represent syntax objects with
explicit lexical (here I mean compile-time lexical - no data) environments
and marks, and when an identifier is encountered, it gets resolved to a
frame in its lexical environment, and this frame is stored as part of the
syntax-object.  This is sufficient for comparing identifiers for free and bound 
equality.  In expanding macros, newly introduced identifiers are labeled with
the environment of the macro instantiation (actually, of the "syntax" form)
(which can result in what Dybvig calls "displaced lexicals" but I prefer to think 
of as a simple attempt at importing variables).   For those who don't know
what I'm talking about:
(define foo-macro 
   (lambda (x) 
     (syntax-case x ()
         ((_ y ...)
          (let ((z +))
             (syntax (z y ...)))))))
(let-syntax ((foo foo-macro))
   (foo 10 11)) => "Error: identifier out of context z"  (or a similar error message)

   Really, this is just an attempt to import z from the let inside of foo-macro
into the environment in which "foo" is expanded.
   Now, what should happen when a macro imported from the module is
used is the same:  newly introduced identifiers should get labeled by 
the module environment, and everything else should retain whatever
lexical environment it had.  This will avoid both capturing syntax from the
interactive top-level, and missing syntax from the module.  Since
macros are perfectly capable of relying on values of imported variables
(and side-effects on those and resulting dynamic macro behaviour), 
And macros can introduce macros they imported from yet another
module, it will all work (I think, anyway).
    That's how I think all this should work, anyhow.  It's a lot of work
to get there, though.
     I still haven't read Mattew Flatt's paper, maybe he's got something
better.
    Pshew!

Lynn


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt [long]
  2002-09-14  3:18   ` comments on new-model.txt [long] Lynn Winebarger
@ 2002-09-22 22:13     ` Marius Vollmer
  2002-09-24 20:03     ` Marius Vollmer
  1 sibling, 0 replies; 16+ messages in thread
From: Marius Vollmer @ 2002-09-22 22:13 UTC (permalink / raw)
  Cc: guile-devel

Lynn Winebarger <owinebar@free-expression.org> writes:

>      The problem is the very definition of what modules are.  That's
> what I'm objecting to, and it is in there.  I can only assume this
> is in preservation of the current module system,

Yes.

> which is way too dynamic in nature.

Others will disagree.  If we _can_ have meaningful compilation
together with our current, dynamic module system, we should offer it.
A more static module system might allow better compilation, and we
should try to not prohibit such a module system.

Pretend that you have a Guile that implements the model as written
down, with our current dynamic module system (or a slight variant of
it).  Assume that you have a specification for a new, static module
system that you want to use with Guile.  Is it possible to implement
the new module system in such a way that the old compiler can generate
code for it?  (The code must only be correct, it must not be very
good.)  If not, what parts of the model stand in the way?

What do you need so that the new module system can communicate with a
new compiler, so that the new compiler can generate better code or
produce better error messages, and can still generate correct code for
the old module system?


In any way, I don't see how we can proceed when we first need to agree
on a new module system.  The current system is widely used and we can
only improve upon it in small steps.  The 'new model' is a somewhat
big small step, but I'm afraid we will not move at all when we don't
make that step "because it is too small".

> > The biggest requirement that the proposal puts on the module
> > system is that modules can only ever grow; you can not remove
> > bindings or change existing ones.  I expect this to be a popular
> > point for debate, and I don't know if I can defend it
> > successfully.  But the current model rests on this requirement.
>
>       The biggest one is that there's a "current module" at evaluation
> time and that it can be changed.  That's a _huge_ requirement.

I can't cleary see how you can do without a current module.  It might
not be an explicit global variable, but just as there is always a
current lexical environment, there will be an associated current
module, in my view.

Can you sketch how the module system would work without a current
module?

> > Option 'body' for (3) is harder to enforce in the module system, but
> > it is easy to add in the macro expansion pass which is also not
> > treated in detail in the proposal.
>
>       But, as I understand it, this is one of the problems that has
> been encountered in practice (the interaction between macro expansion
> and the "module" system).

As far as I know, the problems stem from our imperfect integration of
the macro expander and the module system, and because we currently
expand macros lazily.  Although this issue is not addressed directly,
the new-model does not prohibit us to get it right.

> > >     To handle optimization, I believe we could adopt special forms
> > > that import values and bind them to local (possibly immutable)
> > > variables. [...]
> > 
> > This sounds more complicated than the 'declarations' feature of the
> > proposal.  The declarations have the advantage that you don't need to
> > do anything special when importing a name, the burdon is on the
> > definer of the name.
> 
>      I almost always prefer code I'm using not to have some oddball
> implicit semantics.  If it's going to do something weird, I should specify
> that it does something weird.

Yes, I agree.  The declarations should not be used to do something
weird.  The declarations can carry information about types of returned
values when you want to allow the compiler to make use of this
information.  The most concrete declaration that I have in mind right
now would be used to tell the compiler things like "this variable
always holds R5RS 'car', feel free to produce inline code".

But I start to think that we should allow declarations in other
places, not just when defining a variable.  You might want to import a
binding and tell the compiler that it should/should not inline the
contained function, say.

So what about moving declarations from variables to bindings?  When
you import a binding, you get a new copy and can add to the
declarations without affecting the declarations of the original
binding.

>     I don't think it will hurt to reflect on this statement from
> R5RS either:
> 
> Following Algol, Scheme is a statically scoped programming language.
> Each use of a variable is associated with a lexically apparent
> binding of that variable.
> 
>    Now you may think I'm being pedantic, but I think discarding that
> second sentence should at least give pause.

Yes.  But is R5RS true to this sentence itself?  What about 'eval' and
'load'?  Is it appearant to what variables a free reference in a form
passed to 'eval' is associated with?  What about a loading two files
in succession where the second file uses a variable defined in the
first?

> >Is this related to the 'module' feature of recent versions of Dybvig's
> >syntax-case implementation?  If so, I think that it is implemented
> >solely with renaming of identifiers and needs no support from the
> >interpreter.  Also, I think that the syntax-case modules are less
> >powerful than ours since their semantics are fixed while ours can be
> >cleanly extended.
> 
>    To the extent that we're talking about lexically scoped closures
> with exportable bindings, yes I suppose.  Though I'm not sure
> what you mean by "cleanly extended".  Maybe you can give
> an example of what you mean.

Hmm, scratch the "cleanly extensible".  I was thinking about how our
modules are implented as some data structures with associated
operations and how you can work on these data structures and operation
as long as you maintain the interface to the interpreter/compiler.
Dybvig's macros are hackable as well, of course, and maybe more
cleanly.


I'll reply to the rest in a separate mail.

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt [long]
  2002-09-14  3:18   ` comments on new-model.txt [long] Lynn Winebarger
  2002-09-22 22:13     ` Marius Vollmer
@ 2002-09-24 20:03     ` Marius Vollmer
  2002-09-28 23:01       ` Lynn Winebarger
  1 sibling, 1 reply; 16+ messages in thread
From: Marius Vollmer @ 2002-09-24 20:03 UTC (permalink / raw)
  Cc: guile-devel

Lynn Winebarger <owinebar@free-expression.org> writes:

> So part of the miscommunication is that I've stopped thinking of
> "top-level" (lexically open) environments necessarily being at the
> actual top-level of a lexical environment.

What is there instead, then?  Or, where would the open environments
be, if not at the top of lexical environments?

> It complicates define a little, but not much.

Can you spell out this complication?  I think that will help me to
understand better.

> > [...]
>     No.  There's no (good) reason for modules to have inherent
> names.  There are good reasons for them to have fixed file names,
> but not names that inhere in the module itself (any more than there
> is for functions, at least).

Yes, good point.  The model does rely on module names only for the
'module-ref' statement.  That statement is meant to be used by macro
expanders so that a macro expansion can refer to names from the module
of the macro definition without having to export/import those names.
It would be a win if we can make that connection in a way that doesn't
rely on module names.

We can change ':module-ref' to allow arbitrary code to be executed for
retrieving the module.  That is

  (:module-ref MODULE ID)

would refer to the binding named ID in the module returned by
evaluating the expression MODULE.

But how are the identifiers of the expression MODULE looked up?  Maybe
it will work to specify that it is always evaluated in the "(guile)"
module.

That is quite a complicated scenario, in my opinion.  I think it is OK
to just require that modules that are used in a ':module-ref'
statement must be findable via names.  Parameterized modules can
embedd the parameter values in their names, like
(scheme-report-environment 5).  When parameterization gets more
complicated, we probably should use GOOPS instead of modules for this.

> (define a (load-module "foo"))
> (define b (load-module "foo"))
> (import a (prefix "a->"))
> (import b (prefix "b->"))
> (set! a->bar 5) 
> (set! b->bar 7)
> a->bar => 5
> b->bar => 7

How would this work with macros?  'a->switch' might be a macro, but
the compiler might not be able to figure this out since it can not
know in general what 'a' refers to.

A solution would be to say that you can't _only_ compile some code,
you can only execute it and (optionally) compile it at the same time.
This is something to keep in mind, I'd say.

>   So in this model, you could use modules you object with compiled
> methods if you like.

I don't understand.  Come again? ;)

>    If you can't tell, I think Guile should handle its own linking
> and loading, at least as far as its own compiled modules go.

Yes.  I want 'load' to load compiled code as well.

>    As regards syntax-case and macros/modules: I don't believe Guile
> should use Dybvig's portable Scheme implementation.

If we get something better, great!  But this is a separate issue, I'd
say.  (Larceny has a nice compiler front-end, I think.)

> Even if it we had a compiler, it does explicitly use symbols for
> renaming that somehow have to be unique across compiler runs.

Hmm, the renaming is only done for local variables, not for the global
ones.  We have a problem right now because the renamed local
identifiers might clash with the not-renamed globale ones, tho...

> (define foo-macro 
>   (lambda (x)
>     (syntax-case x ()
>       ((_ y ...)
>        (let ((z +))
>          (syntax (z y ...)))))))

Shouldn't that be 'define-syntax' instead of 'define', or am I missing
something?

>   Really, this is just an attempt to import z from the let inside of
> foo-macro into the environment in which "foo" is expanded.
>
>    Now, what should happen when a macro imported from the module is
> used is the same: newly introduced identifiers should get labeled by
> the module environment, and everything else should retain whatever
> lexical environment it had.  This will avoid both capturing syntax
> from the interactive top-level, and missing syntax from the module.
> Since macros are perfectly capable of relying on values of imported
> variables (and side-effects on those and resulting dynamic macro
> behaviour), And macros can introduce macros they imported from yet
> another module, it will all work (I think, anyway).

Could your macro expander be made to work with the new-model?  I.e.,
assume you need to produce macro-free Scheme plus a few extensions
like ':module-ref'.  Could it do that?  You can assume that you can
use real uninterned symbols for local variables (so that there wont be
any clashes between renamed local variables and global variables).

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt [long]
  2002-09-24 20:03     ` Marius Vollmer
@ 2002-09-28 23:01       ` Lynn Winebarger
  2002-10-12 13:35         ` Marius Vollmer
  0 siblings, 1 reply; 16+ messages in thread
From: Lynn Winebarger @ 2002-09-28 23:01 UTC (permalink / raw)
  Cc: guile-devel

On Tuesday 24 September 2002 15:03, Marius Vollmer wrote:
> Lynn Winebarger <owinebar@free-expression.org> writes:
> 
> > So part of the miscommunication is that I've stopped thinking of
> > "top-level" (lexically open) environments necessarily being at the
> > actual top-level of a lexical environment.
> 
> What is there instead, then?  Or, where would the open environments
> be, if not at the top of lexical environments?

    Well, the clearest example I can think of is in a threaded model. 
Each thread could have its own top-level, _above_ the thread-global
top-level environment.  These would essentially play the role dynamic roots
play now, but hopefully with cleaner (or at least uniform) semantics.  
     You might also think about loading guile compiled executables and
setting up their top-level in a thread of a larger program/process.

> > It complicates define a little, but not much.
> 
> Can you spell out this complication?  I think that will help me to
> understand better.

    Well, it's just _where_ will a define do its business.  Let's say
I am interpreting `(define x 5) in the environment 
`(,toplevel-B ,toplevel-A).   If x isn't bound in either A or B, it's
clear (I think) you want to create a binding for x in B (not A).
Likewise, if x is bound in B, then the define should just act
as a set! on that binding.  Now what happens if x is bound
in A?  Should the define just be a set! on the binding in A, or
create a binding in B?
   In the executable example above, I think it's clear you want
it to create the binding in B.  On the other hand, there are clearly
situations in thread programming where you'd really want it to
set! the binding in A (although it's arguable that you'd really use
set! for that purpose and not define).
   I think if we were compiling an executable, the define would
clearly be hard-coded to create a binding in what would become
B when loaded into a thread.  In modules, of course, define's
should create bindings inside the module, but there might
be a "top-level-define" form that would have to deal with these
worries.

> It would be a win if we can make that connection in a way that doesn't
> rely on module names.
   We can.  As I mentioned before I'm re-implementing syntax-case
in a meta-circular interpreter (but one that resembles Guile's internal
eval, i.e. tree-coded and eventually CPS'ed).
   In this system, all code coming into the evaluator is made into syntax
objects which store the lexical environment in which they were created.
As the code is parsed, the syntax objects are broken down into
new syntax objects for the appropriate pieces; binding forms extend
the lexical environment(s) of their component syntax-objects by the
frame they introduce.  When a syntax object consisting of only a symbol
is seen by the initial parser, it first resolves the identifier in the lexical environment
of the syntax-object.  This yields a lexical frame (if it's not bound in the
lexical environment yet, this is the first top-level frame encountered during
the lookup).  If the binding found is to a macro, that macro is applied to
whatever expression is being parsed (i.e. it could be a combination
with the identifier as keyword, _or_ a bare occurence of the identifier),
and the result is reparsed.  Otherwise, a "variable" is created for later
resolution as either a lexical reference (deBrujin indices) or a variable
reference (in the case of a top-level binding).  [I'm putting my current
parse at the bottom of this message].
    Then when the full parser sees the variable refence, it looks up the
environment frame in the lexical environment it's parsing in.  Maybe
I should explain that.  See, forms have to be initially parsed into
just the outer form.  This allows the proper parsing of internal define-syntax's,
because you have to find the boundary between definitions in a body
and regular code, and you are not allowed to parse more than once
because macro definitions may cause side-effects (I posted examples
of these before).   So you have to be able to "peek" at whether the
result is a begin, define, define-syntax, or "other" prior to parsing any
sub-forms.  Of course any previously defined macros are applied
during the initial parse (as described above), keeping in mind it is
an error for an internal define(-syntax) to do anything to obscure
the boundary between definitions and the rest of the body. 
    There is a separate procedure I call fully-parse that handles
parsing the subforms.  Fully-parse carries a lexical environment
made in the conventional way (i.e. when you fully parse a lambda,
the new frame is consed onto the existing lexical environment when
you fully-parse the body of the lambda).  When it encounters a "variable"
made by parse, it looks for the resolving frame (found in the lexical
environment stored in the syntax object) in the lexical environment
of fully-parse.  If it can't be found, you have an "identifier out of context"
error that occurs, e.g. in the following:
(let ((x +))
  (let-syntax ((foo (lambda (exp)
                               (syntax-case exp ()
                                   ((_ y ...)
                                    (let ((x -))
                                       (syntax (x y ...))))))))
         (foo 8 9 10)))
    The x will get resolved by the "syntax" keyword to be the one that refers to "-".
That frame, however, is not in the lexical environment in which (foo 8 9 10) is
parsed (which contains 2 frames, one with x bound to + and one with foo in
a macro binding).
      Anyway, macros are looked up in the lexical environment in which they were
defined.  Dybvig/Waddell's implementation (I believe) uses opaque symbols where I'm
using resolving frames.  I believe that Waddell's implementation of modules in
syntax-case does end up using an explicit lexical frame, but I haven't analyzed their
code very closely.  It's pretty clear from writing the code that you can make modules
simply by making a blessed class of those identifiers that would be out of context 
otherwise.  Only I would suggest that precompiled modules actually have a completely
distinct lexical environment embedded in its exported identifiers.  That is, the "current"
top-level environment of the compiled module when it was compiled is clearly not the 
same as the top-level environment when it gets loaded, and should really be different.
The only exceptions being identifiers that the module explicitly imports from run-time
environment (via a special form).

> > (define a (load-module "foo"))
> > (define b (load-module "foo"))
> > (import a (prefix "a->"))
> > (import b (prefix "b->"))
> > (set! a->bar 5) 
> > (set! b->bar 7)
> > a->bar => 5
> > b->bar => 7
> 
> How would this work with macros?  'a->switch' might be a macro, but
> the compiler might not be able to figure this out since it can not
> know in general what 'a' refers to.
     As long as you can assume that "foo" refers to the same compiled
module at compile time (on the developer machine) as at run-time
(on the user machine), or some reasonable variant thereof (via some
versioning mechanism), then I think the compiler can know whether
its a macro or not.  The real question is to what extent "foo" depends
on the user's run-time environment (as opposed to the developers 
run-time environment).  It looks as though Flatt has some nice forms
for module loading, but they do not strike me as being the lambda of modules
(but something that should be implementable by macros).

> >   So in this model, you could use modules you object with compiled
> > methods if you like.
> 
> I don't understand.  Come again? ;)
     As I get older, my typing gets worse and worse.  I meant you could
use modules as an object system with compiled methods.

> >    As regards syntax-case and macros/modules: I don't believe Guile
> > should use Dybvig's portable Scheme implementation.
> 
> If we get something better, great!  But this is a separate issue, I'd
> say.  (Larceny has a nice compiler front-end, I think.)
> 
> > Even if it we had a compiler, it does explicitly use symbols for
> > renaming that somehow have to be unique across compiler runs.
> 
> Hmm, the renaming is only done for local variables, not for the global
> ones.  We have a problem right now because the renamed local
> identifiers might clash with the not-renamed globale ones, tho...

   The nice thing about the explicit lexical frames is that you can store
that representation of them, and then reconstruct it when you reload, and
always use eq? to compare them.
    
> > (define foo-macro 
> >   (lambda (x)
> >     (syntax-case x ()
> >       ((_ y ...)
> >        (let ((z +))
> >          (syntax (z y ...)))))))
> 
> Shouldn't that be 'define-syntax' instead of 'define', or am I missing
> something?
    No, I really meant define.  syntax-case and syntax are just macros,
there's no requirement that they appear only inside macros.  One thing
that they do that is special is that syntax-case binds pattern variables
(that have an attached depth) that only syntax can dereference.  Any
non-pattern variable syntax encounters, it just generates a syntax
object with that symbol as the object and captures lexical context in
which the syntax form appears.  
    Think about how this should get computed:
(let-syntax ((foo (begin
                            (pretty-print 1)
                            (lambda (x)
                              (syntax-case x ()
                                  ((_ y ...) 
                                   (let-syntax ((dummy1 (begin
                                                                        (pretty-print 2)
                                                                        (lambda (x) x)))) ;; don't ever actually use this macro!
                                       (syntax (y ...))))))))
   (let-syntax ((bar (begin
                               (pretty-print 3)
                               (lambda (x)
                                 (syntax-case x ()
                                     ((_ y ...) 
                                      (let-syntax ((dummy2 (begin
                                                                           (pretty-print 4)
                                                                           (lambda (x) x)))) ;; don't ever actually use this macro!
                                          (syntax (y ...))))))))
        0))
Hint:  You should see
2
1 
4 
3
0

> Could your macro expander be made to work with the new-model?  I.e.,
> assume you need to produce macro-free Scheme plus a few extensions
> like ':module-ref'.  Could it do that?  You can assume that you can
> use real uninterned symbols for local variables (so that there wont be
> any clashes between renamed local variables and global variables).
      It is difficult, I think, because (if I'm not mistaken) the reason the current
module system is "interesting" is precisely because variables aren't looked up
until they're actually used (part of the "lazy" macro expansion, except "lazy" 
usually refers to something that has the same outcome whether you were lazy 
or not, except not halting).   Once they're resolved, aren't top-level variable 
occurences replaced with references to bindings in the current module 
environment?  Or do top-level variables get repeatedly looked up?
   That said, it's not impossible.  The main property (other than the lazy lookup)
is that modules are implemented by set!-ing the last frame on the lexical stack.
You could do this, I think, and make top-level variable references such that
the evaluator looks them up on their first evaluation (the parser just placing
a "look me up later" tree code varref where the variable reference was), and
then either hard code them in (ala the memoizing macro expansion) or
does the lookup repeatedly.
   That's assuming my understanding of the current module system is 
generally correct.  It would be good to get a better understanding of how
people use the current module system.  Do they actively make use of
the fact there is a "current" module, or 
    I am still working out some bugs.  The meta-interpreter chokes on itself
at the moment.  (but the interpreter manages Jaffer's test.scm using syntax-case
defined cond/case/etc - my datatype macro is just really hairy, and thus a strenuous
test of syntax-case).  A lot of the bugs have to do with side effects, naturally.  
I can post it on guile-sources when it's reasonably bug free (i.e. when it can interpret
itself interpreting test.scm, and possibly one more level of indirection).
     Once I get it to that stage, by the way, I can factor out all the anonymous closures
I create into named procedures, then make all primitive operation represented as 
data structures.  Once I have that, it would not be a far step to write out the fully
parsed code into a file along with lexical information in a reloadable format.  While 
this isn't particularly great as compilation goes, it would be sufficient to play 
around with the distinction between run-time and compile time and their
 interaction with a prototyped module system.   (Although
if this macro expansion algorithm were put into core, writing out preparsed 
code would be wise to do - all the lexical analysis it does isn't as cheap as
the current method).

Lynn
------------------------------
;;;;  $<something> generally constructs a tree-code that does <something>
;;;;   with-type actually interposes the fixed fields of a data stucture into the
;;;; environment, so (wrap-literal obj) at the end actually refers to  the obj field 
;;;; of the syntax-object lit.

(define check-macro
  (lambda (m exp)
    (define mb #f)
    (define pre-resolved (resolving-frame-of m))
    (resolve-identifier m)
    ;;; this looks for macros in the lexical environment where the operator
    ;;; was created (i.e. possibly inside a macro somewhere).
    (set! mb (lookup-id m (lexical-env-of m)))
    (let ((res (if mb
		   (if (macro-binding? (cdr mb))
		       (let ((mv (get-macro (cdr mb))))
			 (if (uninitialized? mv)
			     ;; this _should_ only occur at the boundary
			     ;; between definitions and expressions inside
			     ;; a body - throw it back undone so body-macro
			     ;; can define the macro it needs.
			     exp
			     ($apply mv ($quote exp))))
		       #f)
		   #f)))
      ;; this is a result of the evil of using side effects  We don't want premature resolution
      (if res
          res
         (begin
            (if (not pre-resolved)
	   (reset-resolving-frame m))
            #f)))))

;;; note parse just takes a baby step and then returns - this allows
;;; body-builder to do its magic.
(define (parse exp)
  (let ((redo #f))
    (let ((v (call/cc (lambda (k) k))))
      (if (not redo)
	  (set! redo v)
	  (set! exp v))
      (if (expression? exp)
	  exp  ;;; when a primitive macro has gotten it
	  (syntax-pattern-case exp ()
	    ((rator rands ...)
	     (if (id? rator)
		 (let ((r (check-macro rator exp)))
		   (if r
		       (let ((res (interpret r global-env)))
			 (redo res))
		       ($apply-apply rator rands)))
		 ($apply-apply rator rands)))
	    (lit
	      (if (id? lit)
		  ;;; allow for identifier macros
		  (let ((r (check-macro lit lit)))
		    (if r
			(let ((res (interpret r global-env)))
			  (redo res))
			($variable lit)))
	      (with-type syntax-object lit
	          (wrap-literal obj)))))



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: comments on new-model.txt [long]
  2002-09-28 23:01       ` Lynn Winebarger
@ 2002-10-12 13:35         ` Marius Vollmer
  0 siblings, 0 replies; 16+ messages in thread
From: Marius Vollmer @ 2002-10-12 13:35 UTC (permalink / raw)
  Cc: guile-devel

Lynn Winebarger <owinebar@free-expression.org> writes:

> On Tuesday 24 September 2002 15:03, Marius Vollmer wrote:
> > Lynn Winebarger <owinebar@free-expression.org> writes:
> > 
> > > So part of the miscommunication is that I've stopped thinking of
> > > "top-level" (lexically open) environments necessarily being at the
> > > actual top-level of a lexical environment.
> > 
> > What is there instead, then?  Or, where would the open environments
> > be, if not at the top of lexical environments?
> 
>     Well, the clearest example I can think of is in a threaded model. 
> Each thread could have its own top-level, _above_ the thread-global
> top-level environment.

Thus, in such a model, a identifier could reference different
variables depending on the thread that executes the code that contains
the identifier?

This would indeed be something that is not covered by new-model.txt,
but I don't really want to go there.  I think we should not get too
dynamic with variable lookups.  Instead, we might have smart variables
that do fancy things upon access.

> These would essentially play the role dynamic roots play now, but
> hopefully with cleaner (or at least uniform) semantics.

How are our current dynamic roots related to variables and modules?

> > > It complicates define a little, but not much.
> > 
> > Can you spell out this complication?  I think that will help me to
> > understand better.
> 
>     Well, it's just _where_ will a define do its business.  Let's say
> I am interpreting `(define x 5) in the environment 
> `(,toplevel-B ,toplevel-A).

Aha!  I think I get it now.  In my model, a chain of environment
frames always ends in a single 'toplevel' frame that points to a
module.  In your model, frames which point to modules are not
restricted to be at the end of the chain, right?  There can also be
two frames pointing to different modules, like in your example above,
right?

Is there a system that works like your example?

Could we achieve the important eefects of your example by creating
modules that mimic them?  That is, instead of allowing more than one
module-frame at the end of a frame chain, could we implement a module
that, when put at the end of a chain, would behave as if two
module-frames would there?

>   If x isn't bound in either A or B, it's clear (I think) you want
> to create a binding for x in B (not A).  Likewise, if x is bound in
> B, then the define should just act as a set! on that binding.  Now
> what happens if x is bound in A?  Should the define just be a set!
> on the binding in A, or create a binding in B?

We have already a situation that is similar to this: importing
bindings from one module into another.  The new-model.txt is not
really affected by this; this needs to be addressed by the module
system (which I don't really want to talk about here).

> > [connection between a module mentioned at compile time, and the
> > corresponding module used at run-time.]
> >
> > It would be a win if we can make that connection in a way that doesn't
> > rely on module names.
>
> We can. [...]

Sorry, I don't see how from your explanation.

> > > (define a (load-module "foo"))
> > > (define b (load-module "foo"))
> > > (import a (prefix "a->"))
> > > (import b (prefix "b->"))
> > > (set! a->bar 5) 
> > > (set! b->bar 7)
> > > a->bar => 5
> > > b->bar => 7
> > 
> > How would this work with macros?  'a->switch' might be a macro, but
> > the compiler might not be able to figure this out since it can not
> > know in general what 'a' refers to.
>
>      As long as you can assume that "foo" refers to the same
> compiled module at compile time (on the developer machine) as at
> run-time (on the user machine),

(I think we can assume this.)

> or some reasonable variant thereof (via some versioning mechanism),
> then I think the compiler can know whether its a macro or not.

In your example, yes.  But what about code like

    (define a (load-module (string-append "fo" "o")))

Is the compiler required to figure out what the string-append form
evaluates to?  I think it is easy to see that this does not work in
general, for more complicated code.

>      I meant you could use modules as an object system with compiled
> methods.

Do we want that?  That seems like a too large step to me.

> > Could your macro expander be made to work with the new-model?  I.e.,
> > assume you need to produce macro-free Scheme plus a few extensions
> > like ':module-ref'.  Could it do that?  You can assume that you can
> > use real uninterned symbols for local variables (so that there wont be
> > any clashes between renamed local variables and global variables).

>       It is difficult, I think, because (if I'm not mistaken) the
> reason the current module system is "interesting" is precisely
> because variables aren't looked up until they're actually used

No, I don't think so.  In any case, the lazy lookup is not required by
new-model.txt.

> (part of the "lazy" macro expansion, except "lazy" usually refers to
> something that has the same outcome whether you were lazy or not,
> except not halting).  Once they're resolved, aren't top-level
> variable occurences replaced with references to bindings in the
> current module environment?  Or do top-level variables get
> repeatedly looked up?

They are replaced with references to 'variable' objects.

>    That said, it's not impossible.

Ok.  Can you modify new-model.txt so that it is to your liking?

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2002-10-12 13:35 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-09-05  1:22 comments on new-model.txt Lynn Winebarger
2002-09-05 19:06 ` Marius Vollmer
2002-09-08 23:47   ` Lynn Winebarger
2002-09-09 22:55     ` Marius Vollmer
2002-09-10  0:30       ` Lynn Winebarger
2002-09-10  0:32         ` Lynn Winebarger
2002-09-10 19:56         ` Marius Vollmer
2002-09-10 23:15           ` Tom Lord
2002-09-11 17:38             ` Marius Vollmer
2002-09-11  7:28       ` Lynn Winebarger
2002-09-11 18:11         ` Marius Vollmer
2002-09-14  3:18   ` comments on new-model.txt [long] Lynn Winebarger
2002-09-22 22:13     ` Marius Vollmer
2002-09-24 20:03     ` Marius Vollmer
2002-09-28 23:01       ` Lynn Winebarger
2002-10-12 13:35         ` Marius Vollmer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).