I've been thinking a lot about how PGE implements closures. Right now, the closures are a bit rough -- PGE does heuristic look-ahead to find the end of the closure, saves off the code as a string, and compiles it at runtime like an eval. To make the heuristic look- ahead work, PGE insists that closures must be bound by "{{...}}" instead of "{...}" as Larry has specified. The problems are 1) you don't find syntax errors at compile time, 2) you need a cache to keep the compiler from being re-invoked after every match, 3) PIR is implemented as a special case.

Patrick has mentioned several times that the proper solution to the problem is a representation of the high-level language that PGE can interact with. My thoughts about that HLL mapping:

1) we should invoke the other language's compiler at compile-time and generate an anonymous PIR .sub a) a special version of the compiler that just parses a block, rather than a whole program (for Perl6 for example, I think the distinction is irrelevant) b) the returned PIR might have several subs. In this case, the anonymous one will typically be short and will invoke the others --> so there should be two return values: the library and the entry point
2) the other language should be represented as an object which can:
   a) parse a block
b) pre-process that block to insert boilerplate (see PIR_closure in PGE::Perl6Regex today) for the anonymous entry point

I thought about co-opting the PGE :lang adverb, which is currently a string representing the compreg name. If that were optionally a PGE::HLLMapping instance, then we could conditionally invoke some of the behavior described above.

Remaining questions:
  1) what's the namespace of the generated code?
2) how do we handle languages where embedded code blocks are not equivalent to whole programs? Do we subclass the grammar and redefine TOP to be a statement block?

Chris

Reply via email to