7 Mar 2010 joolean   » (Journeyer)


wingo just patched a pretty interesting issue I discovered in Guile's psyntax implementation. Guile uses a modified version of the expander that's module aware, so that lookups and bindings are done -- and hygiene is maintained -- with respect to module eval closures. Top-level definition forms, for example, such as `define' or `define-syntax', create bindings in whatever Guile thinks the "current" module is.

This works great, but there's a wrinkle added by the fact that the expansion process can change the current module. `define-module', for example, does this, by way of an `eval-when' -- after creating a new module, the modules system makes it current, so that if you've got a sequence of expressions like:

(define-module (foo))

(define foo 'foo) (define bar 'bar) (define baz 'baz)

...then `foo', `bar', and `baz' will be visible to `(foo)' and not to whatever module was current when you called `define-module'. The issue I found involved a slight modification to this pattern, wrapping everything in a `begin' form:

  (define-module (foo))
  (define-foo 'foo)
Semantically, this should be equivalent to the first form -- at the top level, `begin' splices its contents into the surrounding code as if it weren't even there, enabling you to produce multi-expression, uh, expressions, even in contexts where you're only allowed to produce one, like in the syntax transformer I was writing. But what I was seeing was that my definitions weren't creating bindings in the modules I'd placed them "within" -- particularly hard to troubleshoot when it came syntax definition, since the expander just allowed unbound custom syntax expressions to pass through to the evaluator, assuming they were procedure applications.

The root cause was that Guile didn't anticipate changes to the current module during the expansion of a single top-level form -- so the first form I described would be fine, since the expander would be re-initialized with the current module for each expression; but the second form would only check the current module once, for the `begin', and not after any of the expressions inside it. After Andy's patch, the part of the expander that handles top-level `begin' forms (`chi-top-sequence') checks the current module after each expression in the sequence to see if it's changed and updates the expansion environment appropriately.


All of the above has allowed me to make a fair bit of headway on the R6RS front. A while back I'd gotten started on implementations of the R6RS "standard libraries" and started merging them (along with test suites as appropriate) into Guile's module set (see the wip-r6rs-libraries branch), but I'd had to stop because of the difficulties caused by the issue above (which took me a very long time to isolate and properly articulate). Now I can start again!

Latest blog entries     Older blog entries

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!