in reply to Code that writes code
The approach is a little different for each.
With Everything, there are pages with embedded code, embedded HTML, and calls to other nodes with embedded code. In the normal Engine, there's a regex that grabs token-delimited sections out and parses them accordingly, eventually finding and calling eval() on the embedded text.
A normal superdoc may end up calling eval() a dozen or more times. That can get expensive.
I have some experimental patches that pull out embedded code sections and construct an anonymous subroutine out of the whole document. It's compiled, once, and stored in a cache. (Luckily, the cache already had code to update the document text if someone edits it -- I got that for free!) All subsequent calls, while the node containing the embedded code is still in the cache, only have the overhead of a method call.
The tricky part is dealing with all of the different types of stuff. Embedded code is supposed to execute as a single unit (one entry point, returns a simple string), so I have to wrap it in eval blocks. (That's eval BLOCK not eval STRING.)
Within Jellybean, we don't allow embedded code. We have the beginnings of a scripting system where you build a method from named snippets. For example, you could open a form, display a message, use a textfield to get a parameter, show a submit button, and end a form with a recipe like the following:
Jellybean uses these as keys into a hash. The values are strings that can be concatenated into an anonymous subroutine as well. A simple my $sub_ref = eval $sub_code; will do what we want. (Yes, there's error checking.)startform hello textfield submit closeform
All of a sudden, we have a new method. It doesn't have to be parsed each time. It's as fast as a built-in method. Users can't execute arbitrary code, because someone has to make it available for them to use in this method.
This is a powerful technique -- with not a few pitfalls -- but it's certainly an elegant solution for a few situations.
|
---|