/** <summary> * To write out the value of a condition expr, invoke the evaluator in eval.g * to walk the condition tree computing the boolean value. If result * is true, then write subtemplate. * </summary> */ public override int Write(StringTemplate self, IStringTemplateWriter @out) { if (AST == null || self == null || @out == null) { return(0); } //System.Console.Out.WriteLine( "evaluating conditional tree: " + AST.ToStringTree() ); #if !COMPILE_EXPRESSIONS ActionEvaluator eval = null; #endif int n = 0; try { bool testedTrue = false; // get conditional from tree and compute result #if COMPILE_EXPRESSIONS if (EvaluateCondition == null) { EvaluateCondition = GetEvaluator(this, AST.GetChild(0)); } bool includeSubtemplate = EvaluateCondition(self, @out); // eval and write out tree #else ITree cond = AST.GetChild(0); eval = new ActionEvaluator(self, this, @out, cond); // eval and write out trees bool includeSubtemplate = eval.ifCondition(); #endif //System.Console.Out.WriteLine( "subtemplate " + _subtemplate ); // IF if (includeSubtemplate) { n = WriteSubTemplate(self, @out, _subtemplate); testedTrue = true; } // ELSEIF else if (_elseIfSubtemplates != null && _elseIfSubtemplates.Count > 0) { for (int i = 0; i < _elseIfSubtemplates.Count; i++) { ElseIfClauseData elseIfClause = _elseIfSubtemplates[i]; #if COMPILE_EXPRESSIONS if (elseIfClause.EvaluateCondition == null) { elseIfClause.EvaluateCondition = GetEvaluator(this, elseIfClause.expr.AST); } includeSubtemplate = elseIfClause.EvaluateCondition(self, @out); #else eval = new ActionEvaluator(self, this, @out, elseIfClause.expr.AST); includeSubtemplate = eval.ifCondition(); #endif if (includeSubtemplate) { WriteSubTemplate(self, @out, elseIfClause.st); testedTrue = true; break; } } } // ELSE if (!testedTrue && _elseSubtemplate != null) { // evaluate ELSE clause if present and IF condition failed StringTemplate s = _elseSubtemplate.GetInstanceOf(); s.EnclosingInstance = self; s.Group = self.Group; s.NativeGroup = self.NativeGroup; n = s.Write(@out); } // cond==false and no else => Missing output not empty if (!testedTrue && _elseSubtemplate == null) { n = Missing; } } catch (RecognitionException re) { self.Error("can't evaluate tree: " + AST.ToStringTree(), re); } return(n); }
static System.Func <StringTemplate, IStringTemplateWriter, bool> GetEvaluator(ASTExpr chunk, ITree condition) { if (EnableDynamicMethods) { try { DynamicMethod method = null; #if CACHE_FUNCTORS if (!_methods.TryGetValue(condition, out method)) #endif { Type[] parameterTypes = { typeof(ASTExpr), typeof(StringTemplate), typeof(IStringTemplateWriter) }; method = new DynamicMethod("ConditionEvaluator" + _evaluatorNumber, typeof(bool), parameterTypes, typeof(ConditionalExpr), true); #if !NETSTANDARD2_0 method.DefineParameter(1, ParameterAttributes.None, "chunk"); method.DefineParameter(2, ParameterAttributes.None, "self"); method.DefineParameter(3, ParameterAttributes.None, "writer"); #endif _evaluatorNumber++; var gen = method.GetILGenerator(); ActionEvaluator evalCompiled = new ActionEvaluator(null, chunk, null, condition); evalCompiled.ifConditionCompiled(gen); gen.Emit(OpCodes.Ret); #if CACHE_FUNCTORS _methods[condition] = method; #endif } var dynamicEvaluator = (System.Func <StringTemplate, IStringTemplateWriter, bool>)method.CreateDelegate(typeof(System.Func <StringTemplate, IStringTemplateWriter, bool>), chunk); return(dynamicEvaluator); } catch { // fall back to functional (or interpreted) version } } if (EnableFunctionalMethods) { try { ActionEvaluator evalFunctional = new ActionEvaluator(null, chunk, null, condition); var functionalEvaluator = evalFunctional.ifConditionFunctional(); HoldsConditionFuncAndChunk holder = new HoldsConditionFuncAndChunk() { func = functionalEvaluator, chunk = chunk }; return((System.Func <StringTemplate, IStringTemplateWriter, bool>)System.Delegate.CreateDelegate(typeof(System.Func <StringTemplate, IStringTemplateWriter, bool>), holder, typeof(ConditionalExpr).GetMethod("CallFunctionalConditionEvaluator"))); } catch { // fall back to interpreted version } } return(new System.Func <StringTemplate, IStringTemplateWriter, bool>((self, @out) => { ActionEvaluator eval = new ActionEvaluator(self, chunk, @out, condition); return eval.ifCondition(); })); }