* 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-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-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-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).