[plt-scheme] Reexpansion of modules

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Sat Aug 19 13:29:01 EDT 2006

Reexpansion of modules
======================

The recent thread on MzScheme and Larceny were thought provoking.
Even though Matthias has lost hope to see a bridge between MzScheme
and Larceny, maybe it is possible cross the gap using a tightrope?
Intended not for the masses, but for the adventurous.

Making a subset of MzScheme compilable via Larceny would still
be an improvement over the present situation, where one needs
to dust of the C compiler, when extra speed is needed.

The ideal situation would be a solution that made it possible to
develop code using DrScheme and the standard set of tools. One way
would be to make a module based language "larceny", such that

   (module A larceny
     <...>)

would run directly in DrScheme, and at the press of a button,
one could generate corresponding Larceny code.

A small core language combined with the full module and macro
system of MzScheme would be enough for most speed challenged
programs. These pieces could then be reintroduced to MzScheme
through Eli's FFI.


Ray Racine writes:

 > Just the other day I was wondering what it would take to write an
 > MzScheme to Scheme compiler (or translator). :)
 >
 > What I mean is hooking into the MzScheme interpreter and/or mzc to
 > emit basic Scheme as an IL.  Said IL scheme is then compiled by
 > Larceny.
 > (Fully expand all syntax, unroll modules by prefixing all symbols,
 > emit scheme.)

This reminded me of some old code I wrote, which used that idea.
Instead of reimplementing the MzScheme macro expander (a daunting task
for non-Flatts) it piggybacks on the MzScheme expander.

It were old enough to expect paths represented as strings (and
pre-unicode too?). Nevertheless it seems to work at least on simple
examples. Maybe the following description will tell whether the idea
is sound?

The idea is first to use MzScheme's EXPAND to expand all modules. This
brings the code in a known form (NB: the code were written before
require-template). Then all modules are "reexpanded" - all identifiers
are renamed to include module name, phase and their original name. If
a module is instantiated in multiple phases the code will thus appear
multiple times in the resulting code.

Is the idea sound?

Would it be worthwhile to revive this code - or is there a
better approach?


Example 1
---------

; a.scm
(module a mzscheme
   (provide x inc-x! mx)
   (define x 0)
   (define-syntax mx (lambda (stx) #'x))
   (define (inc-x!) (set! x (+ x 1))))

Reexpanding "a.scm" results in:

(begin
   '(module a mzscheme)
   '(require-for-syntax mzscheme)
   '(provide x inc-x! mx)
   (define-values (a:0:x) 0)
   (define-syntaxes (a:0:mx) (lambda (stx) (quote-syntax a:0:x)))
   (define-values (a:0:inc-x!) (lambda () (set! a:0:x (+ a:0:x 1)))))


Example 2
---------

; a.scm as before

; b.scm
(module b mzscheme
   (require "a.scm")
   (inc-x!)
   (display (mx)) (newline))

Reexpanding "b.scm" results in:

(begin
   '(module a mzscheme)
   '(require-for-syntax mzscheme)
   '(provide x inc-x! mx)
   (define-values (a:0:x) 0)
   (define-syntaxes (a:0:mx) (lambda (stx) (quote-syntax a:0:x)))
   (define-values (a:0:inc-x!) (lambda () (set! a:0:x (+ a:0:x 1)))))

(begin
   '(module b mzscheme)
   '(require-for-syntax mzscheme)
   '(require "a.scm")
   (a:0:inc-x!)
   (display a:0:x)
   (newline))

Example 3
---------
; a.scm as before
; b.scm as before

; c.scm
(module c mzscheme
   (provide mx2)
   (require "b.scm")
   (require "a.scm")
   (require-for-syntax "a.scm")
   (define-syntax mx2 (lambda (stx) (datum->syntax-object stx (mx))))
   (display "phase 1: ") (display (mx2)) (newline)
   (display "phase 0: ") (display (mx))  (newline)

   (+)
   (- 1))

Reexpanding "c.scm" results in:

(begin
   '(module a mzscheme)
   '(require-for-syntax mzscheme)
   '(provide x inc-x! mx)
   (define-values (a:1:x) 0)
   (define-syntaxes (a:1:mx) (lambda (stx) (quote-syntax a:1:x)))
   (define-values (a:1:inc-x!) (lambda () (set! a:1:x (+ a:1:x 1)))))

(begin
   '(module a mzscheme)
   '(require-for-syntax mzscheme)
   '(provide x inc-x! mx)
   (define-values (a:0:x) 0)
   (define-syntaxes (a:0:mx) (lambda (stx) (quote-syntax a:0:x)))
   (define-values (a:0:inc-x!) (lambda () (set! a:0:x (+ a:0:x 1)))))

(begin
   '(module b mzscheme)
   '(require-for-syntax mzscheme)
   '(require "a.scm")
   (a:0:inc-x!)
   (display a:0:x)
   (newline))

(begin
   '(module c mzscheme)
   '(require-for-syntax mzscheme)
   '(provide mx2)
   '(require "b.scm")
   '(require "a.scm")
   '(require-for-syntax "a.scm")
   (define-syntaxes (c:0:mx2) (lambda (stx) (datum->syntax-object stx 
a:1:x)))
   (display "phase 1: ")
   (display 0)
   (newline)
   (display "phase 0: ")
   (display a:0:x)
   (newline)
   (+)
   (- 1))


The code is attached in a zip-file. My mail server rejected plain
Scheme files.

-- 
Jens Axel Søgaard
Planet Scheme      -  <http://www.scheme.dk/planet/>
Everything Scheme  -  <http://www.scheme.dk/blog/>


-------------- next part --------------
A non-text attachment was scrubbed...
Name: reexpand.zip
Type: application/x-zip-compressed
Size: 9226 bytes
Desc: not available
URL: <http://lists.racket-lang.org/users/archive/attachments/20060819/4eeff5c3/attachment.bin>

Posted on the users mailing list.