Original Post
I have recently dug up my old "Generate PHP that generates XHTML idea", and though of ways to build static verification of the generated XHTML right into the meta-generator. There are two articles related to this on my web site, an old one (Generating a PHP View) and a newer one (Compile-time syntax validation which I'd recommend reading) to get a better idea. A few quotes:
Quote:
The basic errors are detected by this type system: let _ = ul [ div [] ];; (* ^^^^^^ This expression has type [> `DIV ] Tag.block but is here used with type [ `LI ] Tag.block *)
Quote:I've already used the system (which now incorporates the entire XHTML 1.0 Strict DTD) to generate the view in a model-view-controller environment, and it works wonders : I was able to use OCaml functions to factor away common constructs that appear in several of the views (such as the global page layout) and have the ability to shift from "example views" (HTML-only with mock data) to actual views (XHTML with embedded PHP). The system generates the appropriate html/phtml files with a single line of code in the OCaml source. I'm posting this here to get feedback (and perhaps even people interested in taking a look and proposing changes), and also ideas for implementing the Controller and Model parts of MVC (right now, I'm working on the Model, in particular on the database and accessor/mutator generation). [Edited by - ToohrVyk on August 26, 2008 4:25:30 AM]
As an advanced feature, this also plays well with the Objective Caml type system, allowing the user to define functions which create subexpressions from other subexpressions and still having everything type-safe. For instance, a function which takes a list of blocks and turns it into an XHTML list with one block per . let decorate elts = ul (List.map (fun x -> li [x]) elts);; (* val decorate : [< `DIV | `P | `SPAN | `TEXT ] Tag.block list -> [> `UL ] Tag.block = <fun> *) let _ = decorate [text "Hello"; div [text "world!"]; body []];; (* ^^^^^^^ This expression has type [> `BODY ] Tag.block but is here used with type [< `DIV | `P | `SPAN | `TEXT > `DIV `TEXT ] Tag.block *)