/// Tuesday, October 25

custom preprocessor idea for Boo

I remember reading the possibility of adding language directives to Boo. If they do, then I propose a feature which I have not seen in other compilers---the ability to invoke a custom preprocessor.

Imagine the possibilities. You could include an ORM XML mapping file, preprocess it to automatically generate accessors within the class. You could include a XAML file and bind events. There are so many more neat things you could do.

Here's an example applied to my yet to be released MVC framework. A view is comprised of a template and code-behind much like ASP.NET. What's the advantage? There is no run-time compilation, no parsing, no reflection, etc. The view and template merge and compile into a single type. I realize ASP.NET gets compiled as well but it's a separate framework, this becomes a first class feature of the language.

# MyTemplate.html - maintainted by a designer. Rows between <%=* %> and <%*%>
# are omitted when rendering. It's an aid for designers.
<html>
    <table>
        <%=* Cycle([EvenRow, OddRow], Model['Items']) %>
        <tr class='even'><td>even row omitted when compiled</td></tr>
        <tr class='odd'><td>odd row omitted when compiled</td></tr> 
        <tr class='even'><td>even row omitted when compiled</td></tr>
        <%*%>
    </table>
</html>

# MyView.boo - code-upfront (code-behind)
class MyView(ViewBase):
    def OddRow(s as string) as string:
        return "<tr class='odd'><td>${s}</td></tr>\n"

    def EvenRow(s as string) as string:
        return "<tr class='even'><td>${s}</td></tr>\n"
        
    #include "MyTemplate.html", TemplateProcessor

The line above means preprocess MyTemplate.html using a custom preprocessor TemplateProcessor. Here's the pseudocode:

#converts an html template into a boo snippet
class TemplateProcessor(Boo.IPreProcessor):
    def Process(filename as string) as string:
        // read the contents of the file
        // convert html template into code
        // return BuildOutput() code

After preprocessing the class contains the generated BuildOutput()

# class with generated function
class MyView(ViewBase):
    ... 
    
    // called by ViewBase.Render()
    def BuildOutput() as string:
        out = StringBuilder()
        out.Append("html\n\t<table>\n")
        Indent("\t\t")
        out.Append(Cycle([OddRow, EvenRow], Model['Items'])
        Dedent()
        out.Append("\t</table></html>")
        return out.ToString()

The view simply cycles between OddRow() and EvenRow() applying values from Items resulting in an HTML table with alternating row styles.

Comments:

Have you seen Brail?

http://www.castleproject.org/index.php/MonoRail:Brail

Feel free to join the Castle mailing list and jump in the coversations about the engine. Maybe the projects have something in common!

Cheers,

Jason
 
Yes, it appears to be very much like Brail. I'm not however trying to build a view engine. I'm creating a facility whereby text in any abstract format (XML, XUL, XAML ...) may be transformed into Boo code and injected during compile time into a Boo class. The resuling assembly/executable does not require my library to run.
 
Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?