public void Init( int?streamOfProviderIfApplicable, EnumMethodEnum enumMethodEnum, String enumMethodUsedName, EPType typeInfo, IList <ExprNode> parameters, ExprValidationContext validationContext) { var eventTypeColl = EPTypeHelper.GetEventTypeMultiValued(typeInfo); var eventTypeBean = EPTypeHelper.GetEventTypeSingleValued(typeInfo); var collectionComponentType = EPTypeHelper.GetClassMultiValued(typeInfo); _enumMethodEnum = enumMethodEnum; _enumMethodUsedName = enumMethodUsedName; _streamCountIncoming = validationContext.StreamTypeService.EventTypes.Length; if (eventTypeColl == null && collectionComponentType == null && eventTypeBean == null) { throw new ExprValidationException( "Invalid input for built-in enumeration method '" + enumMethodUsedName + "', expecting collection of event-type or scalar values as input, received " + EPTypeHelper.ToTypeDescriptive(typeInfo)); } // compile parameter abstract for validation against available footprints var footprintProvided = DotMethodUtil.GetProvidedFootprint(parameters); // validate parameters DotMethodInputTypeMatcher inputTypeMatcher = new ProxyDotMethodInputTypeMatcher { ProcMatches = fp => { if (fp.Input == DotMethodFPInputEnum.EVENTCOLL && eventTypeBean == null && eventTypeColl == null) { return(false); } if (fp.Input == DotMethodFPInputEnum.SCALAR_ANY && collectionComponentType == null) { return(false); } return(true); } }; var footprint = DotMethodUtil.ValidateParametersDetermineFootprint( enumMethodEnum.GetFootprints(), DotMethodTypeEnum.ENUM, enumMethodUsedName, footprintProvided, inputTypeMatcher); // validate input criteria met for this footprint if (footprint.Input != DotMethodFPInputEnum.ANY) { var message = "Invalid input for built-in enumeration method '" + enumMethodUsedName + "' and " + footprint.Parameters.Length + "-parameter footprint, expecting collection of "; var received = " as input, received " + EPTypeHelper.ToTypeDescriptive(typeInfo); if (footprint.Input == DotMethodFPInputEnum.EVENTCOLL && eventTypeColl == null) { throw new ExprValidationException(message + "events" + received); } if (footprint.Input.IsScalar() && collectionComponentType == null) { throw new ExprValidationException(message + "values (typically scalar values)" + received); } if (footprint.Input == DotMethodFPInputEnum.SCALAR_NUMERIC && !collectionComponentType.IsNumeric()) { throw new ExprValidationException(message + "numeric values" + received); } } // manage context of this lambda-expression in regards to outer lambda-expression that may call this one. ExpressionResultCacheForEnumerationMethod enumerationMethodCache = validationContext.ExprEvaluatorContext.ExpressionResultCacheService.AllocateEnumerationMethod; enumerationMethodCache.PushStack(this); var bodiesAndParameters = new List <ExprDotEvalParam>(); var count = 0; var inputEventType = eventTypeBean ?? eventTypeColl; foreach (var node in parameters) { var bodyAndParameter = GetBodyAndParameter( enumMethodUsedName, count++, node, inputEventType, collectionComponentType, validationContext, bodiesAndParameters, footprint); bodiesAndParameters.Add(bodyAndParameter); } _enumEval = GetEnumEval( validationContext.EngineImportService, validationContext.EventAdapterService, validationContext.StreamTypeService, validationContext.StatementId, enumMethodUsedName, bodiesAndParameters, inputEventType, collectionComponentType, _streamCountIncoming, validationContext.IsDisablePropertyExpressionEventCollCache); _enumEvalNumRequiredEvents = _enumEval.StreamNumSize; // determine the stream ids of event properties asked for in the Evaluator(s) var streamsRequired = new HashSet <int>(); var visitor = new ExprNodeIdentifierCollectVisitor(); foreach (var desc in bodiesAndParameters) { desc.Body.Accept(visitor); foreach (var ident in visitor.ExprProperties) { streamsRequired.Add(ident.StreamId); } } if (streamOfProviderIfApplicable != null) { streamsRequired.Add(streamOfProviderIfApplicable.Value); } // We turn on caching if the stack is not empty (we are an inner lambda) and the dependency does not include the stream. var isInner = !enumerationMethodCache.PopLambda(); if (isInner) { // If none of the properties that the current lambda uses comes from the ultimate Parent(s) or subsequent streams, then cache. var parents = enumerationMethodCache.GetStack(); var found = false; foreach (var req in streamsRequired) { var first = (ExprDotEvalEnumMethodBase)parents.First; var parentIncoming = first._streamCountIncoming - 1; var selfAdded = _streamCountIncoming; // the one we use ourselfs if (req > parentIncoming && req < selfAdded) { found = true; } } _cache = !found; } }
private ExprDotEvalParam GetBodyAndParameter( String enumMethodUsedName, int parameterNum, ExprNode parameterNode, EventType inputEventType, Type collectionComponentType, ExprValidationContext validationContext, IList <ExprDotEvalParam> priorParameters, DotMethodFP footprint) { // handle an expression that is a constant or other (not =>) if (!(parameterNode is ExprLambdaGoesNode)) { // no node subtree validation is required here, the chain parameter validation has taken place in ExprDotNode.validate // validation of parameter types has taken place in footprint matching return(new ExprDotEvalParamExpr(parameterNum, parameterNode, parameterNode.ExprEvaluator)); } var goesNode = (ExprLambdaGoesNode)parameterNode; // Get secondary var additionalTypes = GetAddStreamTypes( enumMethodUsedName, goesNode.GoesToNames, inputEventType, collectionComponentType, priorParameters, validationContext.EventAdapterService); var additionalStreamNames = goesNode.GoesToNames.ToArray(); ValidateDuplicateStreamNames(validationContext.StreamTypeService.StreamNames, additionalStreamNames); // add name and type to list of known types var addTypes = (EventType[]) CollectionUtil.ArrayExpandAddElements( validationContext.StreamTypeService.EventTypes, additionalTypes); var addNames = (String[]) CollectionUtil.ArrayExpandAddElements( validationContext.StreamTypeService.StreamNames, additionalStreamNames); var types = new StreamTypeServiceImpl( addTypes, addNames, new bool[addTypes.Length], null, false); // validate expression body var filter = goesNode.ChildNodes[0]; try { var filterValidationContext = new ExprValidationContext(types, validationContext); filter = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.DECLAREDEXPRBODY, filter, filterValidationContext); } catch (ExprValidationException ex) { throw new ExprValidationException( "Error validating enumeration method '" + enumMethodUsedName + "' parameter " + parameterNum + ": " + ex.Message, ex); } var filterEvaluator = filter.ExprEvaluator; var expectedType = footprint.Parameters[parameterNum].ParamType; // Lambda-methods don't use a specific expected return-type, so passing null for type is fine. DotMethodUtil.ValidateSpecificType( enumMethodUsedName, DotMethodTypeEnum.ENUM, expectedType, null, filterEvaluator.ReturnType, parameterNum, filter); var numStreamsIncoming = validationContext.StreamTypeService.EventTypes.Length; return(new ExprDotEvalParamLambda( parameterNum, filter, filterEvaluator, numStreamsIncoming, goesNode.GoesToNames, additionalTypes)); }
public static ExprDotEvalDTMethodDesc ValidateMake( StreamTypeService streamTypeService, Deque <ExprChainedSpec> chainSpecStack, DatetimeMethodEnum dtMethod, String dtMethodName, EPType inputType, IList <ExprNode> parameters, ExprDotNodeFilterAnalyzerInput inputDesc, TimeZoneInfo timeZone) { // verify input String message = "Date-time enumeration method '" + dtMethodName + "' requires either a DateTime or long value as input or events of an event type that declares a timestamp property"; if (inputType is EventEPType) { if (((EventEPType)inputType).EventType.StartTimestampPropertyName == null) { throw new ExprValidationException(message); } } else { if (!(inputType is ClassEPType || inputType is NullEPType)) { throw new ExprValidationException(message + " but received " + EPTypeHelper.ToTypeDescriptive(inputType)); } if (inputType is ClassEPType) { ClassEPType classEPType = (ClassEPType)inputType; if (!TypeHelper.IsDateTime(classEPType.Clazz)) { throw new ExprValidationException( message + " but received " + classEPType.Clazz.GetTypeNameFullyQualPretty()); } } } IList <CalendarOp> calendarOps = new List <CalendarOp>(); ReformatOp reformatOp = null; IntervalOp intervalOp = null; DatetimeMethodEnum currentMethod = dtMethod; IList <ExprNode> currentParameters = parameters; String currentMethodName = dtMethodName; // drain all calendar ops ExprDotNodeFilterAnalyzerDesc filterAnalyzerDesc = null; while (true) { // handle the first one only if its a calendar op var evaluators = GetEvaluators(currentParameters); var opFactory = currentMethod.MetaData().OpFactory; // compile parameter abstract for validation against available footprints var footprintProvided = DotMethodUtil.GetProvidedFootprint(currentParameters); // validate parameters DotMethodUtil.ValidateParametersDetermineFootprint( currentMethod.Footprints(), DotMethodTypeEnum.DATETIME, currentMethodName, footprintProvided, DotMethodInputTypeMatcherImpl.DEFAULT_ALL); if (opFactory is CalendarOpFactory) { CalendarOp calendarOp = ((CalendarOpFactory)opFactory).GetOp(currentMethod, currentMethodName, currentParameters, evaluators); calendarOps.Add(calendarOp); } else if (opFactory is ReformatOpFactory) { reformatOp = ((ReformatOpFactory)opFactory).GetOp(timeZone, currentMethod, currentMethodName, currentParameters); // compile filter analyzer information if there are no calendar ops in the chain if (calendarOps.IsEmpty()) { filterAnalyzerDesc = reformatOp.GetFilterDesc(streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc); } else { filterAnalyzerDesc = null; } } else if (opFactory is IntervalOpFactory) { intervalOp = ((IntervalOpFactory)opFactory).GetOp(streamTypeService, currentMethod, currentMethodName, currentParameters, evaluators); // compile filter analyzer information if there are no calendar ops in the chain if (calendarOps.IsEmpty()) { filterAnalyzerDesc = intervalOp.GetFilterDesc(streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc); } else { filterAnalyzerDesc = null; } } else { throw new IllegalStateException("Invalid op factory class " + opFactory); } // see if there is more if (chainSpecStack.IsEmpty() || !DatetimeMethodEnumExtensions.IsDateTimeMethod(chainSpecStack.First.Name)) { break; } // pull next var next = chainSpecStack.RemoveFirst(); currentMethod = DatetimeMethodEnumExtensions.FromName(next.Name); currentParameters = next.Parameters; currentMethodName = next.Name; if ((reformatOp != null || intervalOp != null)) { throw new ExprValidationException("Invalid input for date-time method '" + next.Name + "'"); } } ExprDotEval dotEval; EPType returnType; dotEval = new ExprDotEvalDT(calendarOps, timeZone, reformatOp, intervalOp, EPTypeHelper.GetClassSingleValued(inputType), EPTypeHelper.GetEventTypeSingleValued(inputType)); returnType = dotEval.TypeInfo; return(new ExprDotEvalDTMethodDesc(dotEval, returnType, filterAnalyzerDesc)); }
public void Init( int? streamOfProviderIfApplicable, EnumMethodDesc enumMethodDesc, string enumMethodUsedName, EPType typeInfo, IList<ExprNode> parameters, ExprValidationContext validationContext) { var eventTypeColl = typeInfo.GetEventTypeMultiValued(); var eventTypeBean = typeInfo.GetEventTypeSingleValued(); var collectionComponentType = typeInfo.GetClassMultiValued(); _enumMethodDesc = enumMethodDesc; _enumMethodUsedName = enumMethodUsedName; _streamCountIncoming = validationContext.StreamTypeService.EventTypes.Length; if (eventTypeColl == null && collectionComponentType == null && eventTypeBean == null) { throw new ExprValidationException( "Invalid input for built-in enumeration method '" + enumMethodUsedName + "', expecting collection of event-type or scalar values as input, received " + typeInfo.ToTypeDescriptive()); } // compile parameter abstract for validation against available footprints var footprintProvided = DotMethodUtil.GetProvidedFootprint(parameters); // validate parameters DotMethodInputTypeMatcher inputTypeMatcher = new ProxyDotMethodInputTypeMatcher { ProcMatches = footprint => { if (footprint.Input == DotMethodFPInputEnum.EVENTCOLL && eventTypeBean == null && eventTypeColl == null) { return false; } if (footprint.Input == DotMethodFPInputEnum.SCALAR_ANY && collectionComponentType == null) { return false; } return true; }, }; var footprint = DotMethodUtil.ValidateParametersDetermineFootprint( enumMethodDesc.Footprints, DotMethodTypeEnum.ENUM, enumMethodUsedName, footprintProvided, inputTypeMatcher); // validate input criteria met for this footprint if (footprint.Input != DotMethodFPInputEnum.ANY) { var message = "Invalid input for built-in enumeration method '" + enumMethodUsedName + "' and " + footprint.Parameters.Length + "-parameter footprint, expecting collection of "; var received = " as input, received " + typeInfo.ToTypeDescriptive(); if (footprint.Input == DotMethodFPInputEnum.EVENTCOLL && eventTypeColl == null) { throw new ExprValidationException(message + "events" + received); } if (footprint.Input.IsScalar() && collectionComponentType == null) { throw new ExprValidationException(message + "values (typically scalar values)" + received); } if (footprint.Input == DotMethodFPInputEnum.SCALAR_NUMERIC && !collectionComponentType.IsNumeric()) { throw new ExprValidationException(message + "numeric values" + received); } } // manage context of this lambda-expression in regards to outer lambda-expression that may call this one. var enumCallStackHelper = validationContext.EnumMethodCallStackHelper; enumCallStackHelper.PushStack(this); try { // initialize var inputEventType = eventTypeBean ?? eventTypeColl; Initialize( footprint, enumMethodDesc.EnumMethod, enumMethodUsedName, inputEventType, collectionComponentType, parameters, validationContext.StreamTypeService, validationContext.StatementRawInfo, validationContext.StatementCompileTimeService); // get-forge-desc-factory var forgeDescFactory = GetForgeFactory( footprint, parameters, enumMethodDesc.EnumMethod, enumMethodUsedName, inputEventType, collectionComponentType, validationContext); // handle body and parameter list var bodiesAndParameters = new List<ExprDotEvalParam>(); var count = 0; foreach (var node in parameters) { var bodyAndParameter = GetBodyAndParameter(forgeDescFactory, enumMethodUsedName, count++, node, validationContext, footprint); bodiesAndParameters.Add(bodyAndParameter); } var forgeDesc = forgeDescFactory.MakeEnumForgeDesc( bodiesAndParameters, _streamCountIncoming, validationContext.StatementCompileTimeService); EnumForge = forgeDesc.Forge; _typeInfo = forgeDesc.Type; EnumEvalNumRequiredEvents = EnumForge.StreamNumSize; // determine the stream ids of event properties asked for in the evaluator(s) var streamsRequired = new HashSet<int?>(); var visitor = new ExprNodeIdentifierCollectVisitor(); foreach (var desc in bodiesAndParameters) { desc.Body.Accept(visitor); foreach (var ident in visitor.ExprProperties) { streamsRequired.Add(ident.StreamId); } } if (streamOfProviderIfApplicable != null) { streamsRequired.Add(streamOfProviderIfApplicable); } // We turn on caching if the stack is not empty (we are an inner lambda) and the dependency does not include the stream. var isInner = !enumCallStackHelper.PopLambda(); if (isInner) { // If none of the properties that the current lambda uses comes from the ultimate parent(s) or subsequent streams, then cache. var parents = enumCallStackHelper.GetStack(); var found = false; foreach (int req in streamsRequired) { var first = (ExprDotForgeEnumMethodBase) parents.First; var parentIncoming = first._streamCountIncoming - 1; var selfAdded = _streamCountIncoming; // the one we use ourselfs if (req > parentIncoming && req < selfAdded) { found = true; } } IsCache = !found; } } catch (ExprValidationException) { enumCallStackHelper.PopLambda(); throw; } }
public static ExprDotDTMethodDesc ValidateMake( StreamTypeService streamTypeService, Deque<Chainable> chainSpecStack, DatetimeMethodDesc dtMethod, string dtMethodName, EPType inputType, IList<ExprNode> parameters, ExprDotNodeFilterAnalyzerInput inputDesc, TimeAbacus timeAbacus, TableCompileTimeResolver tableCompileTimeResolver, ImportServiceCompileTime importService, StatementRawInfo statementRawInfo) { // verify input var message = "Date-time enumeration method '" + dtMethodName + "' requires either a DateTimeEx, DateTimeOffset, DateTime, or long value as input or events of an event type that declares a timestamp property"; if (inputType is EventEPType eventEpType) { if (eventEpType.EventType.StartTimestampPropertyName == null) { throw new ExprValidationException(message); } } else { if (!(inputType is ClassEPType || inputType is NullEPType)) { throw new ExprValidationException( message + " but received " + inputType.ToTypeDescriptive()); } if (inputType is ClassEPType classEpType) { if (!TypeHelper.IsDateTime(classEpType.Clazz)) { throw new ExprValidationException( message + " but received " + classEpType.Clazz.CleanName()); } } } IList<CalendarForge> calendarForges = new List<CalendarForge>(); ReformatForge reformatForge = null; IntervalForge intervalForge = null; var currentMethod = dtMethod; var currentParameters = parameters; var currentMethodName = dtMethodName; // drain all calendar op FilterExprAnalyzerAffector filterAnalyzerDesc = null; while (true) { // handle the first one only if its a calendar op var forges = GetForges(currentParameters); var opFactory = currentMethod.ForgeFactory; // compile parameter abstract for validation against available footprints var footprintProvided = DotMethodUtil.GetProvidedFootprint(currentParameters); // validate parameters var footprintFound = DotMethodUtil.ValidateParametersDetermineFootprint( currentMethod.Footprints, DotMethodTypeEnum.DATETIME, currentMethodName, footprintProvided, DotMethodInputTypeMatcherImpl.DEFAULT_ALL); if (opFactory is CalendarForgeFactory calendarForgeFactory) { var calendarForge = calendarForgeFactory.GetOp( currentMethod, currentMethodName, currentParameters, forges); calendarForges.Add(calendarForge); } else if (opFactory is ReformatForgeFactory reformatForgeFactory) { reformatForge = reformatForgeFactory.GetForge( inputType, timeAbacus, currentMethod, currentMethodName, currentParameters); // compile filter analyzer information if there are no calendar op in the chain if (calendarForges.IsEmpty()) { filterAnalyzerDesc = reformatForge.GetFilterDesc( streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc); } else { filterAnalyzerDesc = null; } } else if (opFactory is IntervalForgeFactory intervalForgeFactory) { intervalForge = intervalForgeFactory.GetForge( streamTypeService, currentMethod, currentMethodName, currentParameters, timeAbacus, tableCompileTimeResolver); // compile filter analyzer information if there are no calendar op in the chain if (calendarForges.IsEmpty()) { filterAnalyzerDesc = intervalForge.GetFilterDesc( streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc); } } else if (opFactory is DTMPluginForgeFactory dtmPluginForgeFactory) { var usageDesc = new DateTimeMethodValidateContext( footprintFound, streamTypeService, currentMethod, currentParameters, statementRawInfo); var ops = dtmPluginForgeFactory.Validate(usageDesc); if (ops == null) { throw new ExprValidationException( "Plug-in datetime method provider " + dtmPluginForgeFactory.GetType() + " returned a null-value for the operations"); } var input = EPTypeHelper.GetClassSingleValued(inputType); if (ops is DateTimeMethodOpsModify dateTimeMethodOpsModify) { calendarForges.Add(new DTMPluginValueChangeForge(input, dateTimeMethodOpsModify, usageDesc.CurrentParameters)); } else if (ops is DateTimeMethodOpsReformat dateTimeMethodOpsReformat) { reformatForge = new DTMPluginReformatForge(input, dateTimeMethodOpsReformat, usageDesc.CurrentParameters); } else { throw new ExprValidationException("Plug-in datetime method ops " + ops.GetType() + " is not recognized"); } // no action } else { throw new IllegalStateException("Invalid op factory class " + opFactory); } // see if there is more if (chainSpecStack.IsEmpty() || !DatetimeMethodResolver.IsDateTimeMethod(chainSpecStack.First.GetRootNameOrEmptyString(), importService)) { break; } // pull next var next = chainSpecStack.RemoveFirst(); currentMethodName = next.GetRootNameOrEmptyString(); currentMethod = DatetimeMethodResolver.FromName(currentMethodName, importService); currentParameters = next.GetParametersOrEmpty(); if (reformatForge != null || intervalForge != null) { throw new ExprValidationException("Invalid input for date-time method '" + currentMethodName + "'"); } } var dotForge = new ExprDotDTForge( calendarForges, timeAbacus, reformatForge, intervalForge, inputType.GetClassSingleValued(), inputType.GetEventTypeSingleValued()); var returnType = dotForge.TypeInfo; return new ExprDotDTMethodDesc(dotForge, returnType, filterAnalyzerDesc); }
public static ExprDotDTMethodDesc ValidateMake( StreamTypeService streamTypeService, Deque<ExprChainedSpec> chainSpecStack, DateTimeMethodEnum dtMethod, string dtMethodName, EPType inputType, IList<ExprNode> parameters, ExprDotNodeFilterAnalyzerInput inputDesc, TimeAbacus timeAbacus, ExprEvaluatorContext exprEvaluatorContext, TableCompileTimeResolver tableCompileTimeResolver) { // verify input var message = "Date-time enumeration method '" + dtMethodName + "' requires either a DateTimeEx, DateTimeOffset, DateTime, or long value as input or events of an event type that declares a timestamp property"; if (inputType is EventEPType) { if (((EventEPType) inputType).EventType.StartTimestampPropertyName == null) { throw new ExprValidationException(message); } } else { if (!(inputType is ClassEPType || inputType is NullEPType)) { throw new ExprValidationException( message + " but received " + inputType.ToTypeDescriptive()); } if (inputType is ClassEPType) { var classEPType = (ClassEPType) inputType; if (!TypeHelper.IsDateTime(classEPType.Clazz)) { throw new ExprValidationException( message + " but received " + classEPType.Clazz.CleanName()); } } } IList<CalendarForge> calendarForges = new List<CalendarForge>(); ReformatForge reformatForge = null; IntervalForge intervalForge = null; var currentMethod = dtMethod; var currentParameters = parameters; var currentMethodName = dtMethodName; // drain all calendar op FilterExprAnalyzerAffector filterAnalyzerDesc = null; while (true) { // handle the first one only if its a calendar op var forges = GetForges(currentParameters); var opFactory = currentMethod.GetForgeFactory(); // compile parameter abstract for validation against available footprints DotMethodFPProvided footprintProvided = DotMethodUtil.GetProvidedFootprint(currentParameters); // validate parameters DotMethodUtil.ValidateParametersDetermineFootprint( currentMethod.GetFootprints(), DotMethodTypeEnum.DATETIME, currentMethodName, footprintProvided, DotMethodInputTypeMatcherImpl.DEFAULT_ALL); if (opFactory is CalendarForgeFactory) { var calendarForge = ((CalendarForgeFactory) currentMethod.GetForgeFactory()).GetOp( currentMethod, currentMethodName, currentParameters, forges); calendarForges.Add(calendarForge); } else if (opFactory is ReformatForgeFactory) { reformatForge = ((ReformatForgeFactory) opFactory).GetForge( inputType, timeAbacus, currentMethod, currentMethodName, currentParameters, exprEvaluatorContext); // compile filter analyzer information if there are no calendar op in the chain if (calendarForges.IsEmpty()) { filterAnalyzerDesc = reformatForge.GetFilterDesc( streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc); } else { filterAnalyzerDesc = null; } } else if (opFactory is IntervalForgeFactory) { intervalForge = ((IntervalForgeFactory) opFactory).GetForge( streamTypeService, currentMethod, currentMethodName, currentParameters, timeAbacus, tableCompileTimeResolver); // compile filter analyzer information if there are no calendar op in the chain if (calendarForges.IsEmpty()) { filterAnalyzerDesc = intervalForge.GetFilterDesc( streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc); } else { filterAnalyzerDesc = null; } } else { throw new IllegalStateException("Invalid op factory class " + opFactory); } // see if there is more if (chainSpecStack.IsEmpty() || !DatetimeMethodEnumHelper.IsDateTimeMethod(chainSpecStack.First.Name)) { break; } // pull next var next = chainSpecStack.RemoveFirst(); currentMethod = DatetimeMethodEnumHelper.FromName(next.Name); currentParameters = next.Parameters; currentMethodName = next.Name; if (reformatForge != null || intervalForge != null) { throw new ExprValidationException("Invalid input for date-time method '" + next.Name + "'"); } } ExprDotForge dotForge; EPType returnType; dotForge = new ExprDotDTForge( calendarForges, timeAbacus, reformatForge, intervalForge, inputType.GetClassSingleValued(), inputType.GetEventTypeSingleValued()); returnType = dotForge.TypeInfo; return new ExprDotDTMethodDesc(dotForge, returnType, filterAnalyzerDesc); }