[plt-scheme] unit/sig question

From: Matt Jadud (mcj4 at kent.ac.uk)
Date: Sun Apr 10 14:11:15 EDT 2005

I recently wrote a toy compiler to demonstrate a few things about using 
a functional language with pattern matching for traversing grammars to 
some colleagues in my department.

I ended up with too much code duplication; so, I read up on units, and 
in having a clear (good?) use for them, I finally saw how I might use 
them in putting together a program using them. For some reason, I never 
quite saw what they could be used for.

I took my grammar and created a unit for each production rule; I then 
define a "pass" in the compiler as a compound unit that composes the 
production rules. This way, I can reuse most of the production rules 
from one pass to another, but can also introduce new production rules 
for handling, say, just one part of the grammar (a la [1], but without 
all of the fancy grammar macro extension---this is more of a 'micro-' 
than 'nano-pass' approach).

For example, the top level of my grammar looks like

   (define-signature top^ (<top>))

   (define top-lang0@
     (unit/sig top^
       (import id^ variable^ process^)

       (define (<top> exp)
         (match exp
           [(struct proc (meta id variables process))
             (<id> id)
             (map <variable> variables)
             (<process> process))]
            (error '<top-lang0> "Bad proc form.")]))

And a pass that validates the input grammar looks like

   (define verify-lang0@
        (TOP          : top^           (top-lang0@ ID VARIABLE PROCESS))
        (PROCESS      : process^       (process-lang0@ ACTION
        (ACTION       : action^        (action-lang0@ ID EXPRESSION))
        (CONSTRUCTION : construction^  (construction-lang0@ PROCESS
                                          EXPRESSION VARIABLE GUARD))
        (GUARD        : guard^         (guard-lang0@ ID))
        (EXPRESSION   : expression^    (expression-lang0@ OPERAND))
        (OPERAND      : operand^       (operand-lang0@ ID))
        (VARIABLE     : variable^      (variable-lang0@ ID TYPE))
        (TYPE         : type^          (type-lang0@))
        (ID           : id^            (id-lang0@)))
       (export (var (TOP <top>)))

What I don't understand is how I can turn this compound unit into 
something I can use. For example, I thought that something like

(define pass0 (invoke-unit/sig verify-lang0@))

would bind pass0 to the export of verify-lang0@ (and therefore an 
expression that parses the top-level form in the language), but that's 
not the case. Or, if it is, I've got the export of top-lang0@ wrong as 
well, and somehow I just end up with #void.

I have a small example that seemed to work the way I'm expecting, but it 
used 'unit' instead of 'unit/sig', which may account for the difference 
in behavior and also my misunderstanding.

What is it that I should do to get the behavior I seem to think I want?


[1] A nanopass infrastructure for compiler education
     Dipanwita Sarkar, Oscar Waddell, R. Kent Dybvig

Posted on the users mailing list.