On Tue, 18 Mar 2008 13:50:02 -0400, Bradley Lucier lucier@math.purdue.edu wrote:
On Mar 18, 2008, at 12:25 PM, Ken Dickey wrote:
Dimitris Vyzovitis wrote:
...
One of the problems I have with these systems (including the modules produced by the orignal portable syntax-case) is that they produce mutable bindings for module/library exported identifiers.
Note that R6RS library bindings are immutable.
Yes, but as your next comment might imply, either the module implementation needs to change or Gambit's compiler implementation needs to change so that the compiler can exploit that information.
True. The expander has to communicate that information to the compiler somehow. The way psyntax is structured allows for providing this information on a per compiler basis by customizing the way the output is generated. The language of the output of the expander can be customized in many ways in psyntax.
1. For some forms, there is a simple flag that allows you to select how one piece of core syntax is expanded. Take lambda and case- lambda for example. One implementation can select not to generate any case-lambdas, consequently, case-lambdas will be expanded to a lambda with a dispatch code based on the number of arguments. Another implementation can select not to generate any lambdas, and in that case, all lambdas are converted to a one-clause case-lambda forms in the output. Whether the underlying implementation supports letrec, letrec*, and so on can be customized this way. [look at psyntax.config.ss (1)]
2. References to primitive procedure can be customized so that it looks like "cons", "#%cons", "##sys#cons", or whatever the underlying implementation wants it to look. The out-of-the-box expander just outputs "cons" because it's the lowest common denominator between all the targeted R5RS implementations but it's by no means a limitation of the expander. As a matter of fact, you can get away with not generating an s-expression output at all and by generating whatever the compiler accepts as input directly from the expander by customizing how the "build-*" procedures work. [look at psyntax.builders.ss (2)]
As far as the immutability of the library exports, there is a hook for how the output of the run-time components of the library should be generated (see build-library-letrec* in psyntax.builders.ss). In ikarus, I generate this library-letrec* form that looks like:
(library-letrec* ([local-name exported-name expression] ...) body)
A portable implementation would generate:
(letrec* ([local-name expression] ...) (begin (set! exported-name local-name) ... body))
A gambit-specific generator would add the declarations that you mentioned in your message (e.g., (safe) (standard-bindings) ...) and shape the output to look in a way that the gambit compiler likes.
I hope that no one hacks/forks the core of the expander (i.e., psyntax.expand.ss and psyntax.library-manager.ss) since newer versions of these come out all the time and you don't want to repatch your modified version any time a new version is released. If there is any limitation in the core of the expander (e.g., if these are things that you wish you could customize but neither psyntax.config.ss nor psyntax.builders.ss provides the hooks), then I would be happy to fix it.
Aziz,,,
[1] http://bazaar.launchpad.net/~aghuloum/ikarus/ikarus.dev/annotate/ aghuloum%40cs.indiana.edu-20080318044924-uvf4daqro1sj8gvx? file_id=psyntax.config.ss-20071009125425-0emiakw98pjacfzu-2
[2] http://bazaar.launchpad.net/~aghuloum/ikarus/ikarus.dev/annotate/ aghuloum%40cs.indiana.edu-20080318044924-uvf4daqro1sj8gvx? file_id=psyntax.builders.ss-20071009125425-0emiakw98pjacfzu-1
Afficher les réponses par date
Thank you for your reply.
On Mar 19, 2008, at 12:05 AM, Abdulaziz Ghuloum wrote:
As far as the immutability of the library exports, there is a hook for how the output of the run-time components of the library should be generated (see build-library-letrec* in psyntax.builders.ss). In ikarus, I generate this library-letrec* form that looks like:
(library-letrec* ([local-name exported-name expression] ...) body)
A portable implementation would generate:
(letrec* ([local-name expression] ...) (begin (set! exported-name local-name) ... body))
A gambit-specific generator would add the declarations that you mentioned in your message (e.g., (safe) (standard-bindings) ...) and shape the output to look in a way that the gambit compiler likes.
The core issue might be that even with (declare (block)) in Gambit, when it sees
(define foo 'wait)
(letrec ((bar values)) (set! foo bar))
it won't treat foo as immutable (because it's just been mutated ;-).
Maybe gambit needs a define-values form or something like it.
Brad
On Mar 19, 2008, at 3:10 PM, Bradley Lucier wrote:
The core issue might be that even with (declare (block)) in Gambit, when it sees
(define foo 'wait)
(letrec ((bar values)) (set! foo bar))
it won't treat foo as immutable (because it's just been mutated ;-).
I understand.
Maybe gambit needs a define-values form or something like it.
Or something like (init foo bar) which says that I'm defining this and swear not to change it ever. Note that this only affects inter- module connections. The variables within a module are still local, allowing copy propagation, constant folding, and inlining within a module. This works nicely for separately-compiled modules. At some point I will target whole-program expansion, which facilitates whole- program optimizations---just not today.
Aziz,,,
On Mar 19, 2008, at 3:10 PM, Bradley Lucier wrote:
(define foo 'wait)
(letrec ((bar values)) (set! foo bar))
I want to add that I know nothing about what (block) entails in gambit or what forms gambit recognizes as good code. The system is flexible enough though. You can easily arrange for the generated code to look like:
(define local* expr*) ... (define global* local*) ... expr* ...
instead of:
(define global* 'wait) ... (letrec* ([local* expr*] ...) (set! global* local*) ... expr* ...)
if that yields better results.
On Mar 19, 2008, at 5:05 PM, Abdulaziz Ghuloum wrote:
On Mar 19, 2008, at 3:10 PM, Bradley Lucier wrote:
(define foo 'wait)
(letrec ((bar values)) (set! foo bar))
I want to add that I know nothing about what (block) entails in gambit or what forms gambit recognizes as good code.
(block) tells the compiler that any global defined but not set! in that file will never be set! in a different file.
The system is flexible enough though. You can easily arrange for the generated code to look like:
(define local* expr*) ... (define global* local*) ... expr* ...
(block) would recognize global* as immutable code, yes.
instead of:
(define global* 'wait) ... (letrec* ([local* expr*] ...) (set! global* local*) ... expr* ...)
if that yields better results.
On Mar 19, 2008, at 6:32 PM, Bradley Lucier wrote:
(define local* expr*) ... (define global* local*) ... expr* ...
(block) would recognize global* as immutable code, yes.
Cool. I don't think one needs to worry about how the output looks like as it can easily change. What matters more is integration: does anybody want to take it and integrate it with gambit and identify any potential problems, or not?
I have already integrated it nicely with Ikarus, and some other guy integrated it in his compiler IronScheme and he said it was straightforward. The screenshot at http://www.codeplex.com/ IronScheme shows calling CLR methods from an R6RS library using a platform-specific (ironscheme clr) library. So, it is possible to integrate nicely with any implementation. But then again, it's not up to me to decide for gambit.
Aziz,,,