text: "use strict";
  
  var arrays  = require("./utils/arrays"),
      objects = require("./utils/objects");
  
  var compiler = {
    /*
     * Compiler passes.
     *
     * Each pass is a function that is passed the AST. It can perform checks on it
     * or modify it as needed. If the pass encounters a semantic error, it throws
     * |PEG.GrammarError|.
     */
    passes: {
      check: {
        reportMissingRules:  require("./compiler/passes/report-missing-rules"),
  	  // HACK: this should really be in transform, and reportLeftRecursion should
  	  // know about it.
        materializeTemplates:require("./compiler/passes/materialize-templates"),
        reportLeftRecursion: require("./compiler/passes/report-left-recursion"),
        // reportInfiniteLoops: require("./compiler/passes/report-infinite-loops")
      },
      transform: {
        removeProxyRules:    require("./compiler/passes/remove-proxy-rules")
      },
      generate: {
        generateBytecode:    require("./compiler/passes/generate-bytecode"),
        generateJavascript:  require("./compiler/passes/generate-javascript")
      }
    },
  
    /*
     * Generates a parser from a specified grammar AST. Throws |PEG.GrammarError|
     * if the AST contains a semantic error. Note that not all errors are detected
     * during the generation and some may protrude to the generated parser and
     * cause its malfunction.
     */
    compile: function(ast, passes) {
      var options = arguments.length > 2 ? objects.clone(arguments[2]) : {},
          stage;
  
      objects.defaults(options, {
        allowedStartRules:  [ast.rules[0].name],
        cache:              false,
        trace:              false,
        optimize:           "speed",
        output:             "parser"
      });
  
      for (stage in passes) {
        if (passes.hasOwnProperty(stage)) {
          arrays.each(passes[stage], function(p) { p(ast, options); });
        }
      }
      switch (options.output) {
        case "parser": return eval(ast.code);
        case "source": return ast.code;
      }
    }
  };
  
  module.exports = compiler;
  