public String evaluate(Query query, int traceLevel) {
        // TODO: This is O(query size*rule base size). We'll eventually need to create indices
        //       on rules to look up rule candidates per term to make it O(query size) instead
        //       Probably create indices on the first term like Prolog implementations use to

        boolean matchedAnything = false;
        Evaluation evaluation = new Evaluation(query, rules, traceLevel);
        if (traceLevel >= 2)
            evaluation.trace(2,"Evaluating query '" + evaluation.getQuery().getModel().getQueryTree().getRoot() + "':");
        for (ListIterator<ProductionRule> i = rules.ruleIterator(); i.hasNext(); ) {
            evaluation.reset();
            ProductionRule rule = i.next();
            boolean matched = matchRuleAtAllStartPoints(evaluation,rule);
            matchedAnything |= matched;
        }

        if ( ! matchedAnything) return null;

        String error = QueryCanonicalizer.canonicalize(query);
        query.trace("SemanticSearcher: Rewrote query",true,1);
        return error;
    }
Evaluates a rule base over a query

@param query the query to evaluate
@param traceLevel the level of tracing to do
@return the error caused by analyzing the query, or null if there was no error
        If there is an error, this query is destroyed (unusable)
container-search/src/main/java/com/yahoo/prelude/semantics/engine/RuleEngine.java