public static EPCompiled Compile( Compilable compilable, ModuleCompileTimeServices services, CompilerArguments args) { var compileTimeServices = new StatementCompileTimeServices(0, services); var walkResult = CompilerHelperSingleEPL.ParseCompileInlinedClassesWalk(compilable, compileTimeServices); var raw = walkResult.StatementSpecRaw; var statementType = StatementTypeUtil.GetStatementType(raw); if (statementType != StatementType.SELECT) { // the fire-and-forget spec is null for "select" and populated for I/U/D throw new StatementSpecCompileException( "Provided EPL expression is a continuous query expression (not an on-demand query)", compilable.ToEPL()); } var annotations = AnnotationUtil.CompileAnnotations( raw.Annotations, services.ImportServiceCompileTime, compilable); // walk subselects, alias expressions, declared expressions, dot-expressions var visitor = StatementSpecRawWalkerSubselectAndDeclaredDot.WalkSubselectAndDeclaredDotExpr(raw); // compile context descriptor ContextCompileTimeDescriptor contextDescriptor = null; var optionalContextName = raw.OptionalContextName; if (optionalContextName != null) { var detail = services.ContextCompileTimeResolver.GetContextInfo(optionalContextName); if (detail == null) { throw new StatementSpecCompileException( "Context by name '" + optionalContextName + "' could not be found", compilable.ToEPL()); } contextDescriptor = new ContextCompileTimeDescriptor( optionalContextName, detail.ContextModuleName, detail.ContextVisibility, new ContextPropertyRegistry(detail), detail.ValidationInfos); } var statementNameFromAnnotation = GetNameFromAnnotation(annotations); var statementName = statementNameFromAnnotation == null ? GetDefaultStatementName() : statementNameFromAnnotation.Trim(); var statementRawInfo = new StatementRawInfo( 0, statementName, annotations, statementType.Value, contextDescriptor, null, compilable, null); StatementSpecCompiledDesc compiledDesc = StatementRawCompiler.Compile( raw, compilable, false, true, annotations, visitor.Subselects, new List<ExprTableAccessNode>(raw.TableExpressions), statementRawInfo, compileTimeServices); StatementSpecCompiled specCompiled = compiledDesc.Compiled; var fafSpec = specCompiled.Raw.FireAndForgetSpec; //var @namespace = "generated"; var classPostfix = IdentifierUtil.GetIdentifierMayStartNumeric(statementName); EPCompiledManifest manifest; Assembly assembly; FAFQueryMethodForge query; if (specCompiled.Raw.InsertIntoDesc != null) { query = new FAFQueryMethodIUDInsertIntoForge( specCompiled, compilable, statementRawInfo, compileTimeServices); } else if (fafSpec == null) { // null indicates a select-statement, same as continuous query var desc = new FAFQueryMethodSelectDesc( specCompiled, compilable, statementRawInfo, compileTimeServices); var classNameResultSetProcessor = CodeGenerationIDGenerator.GenerateClassNameSimple( typeof(ResultSetProcessorFactoryProvider), classPostfix); query = new FAFQueryMethodSelectForge(desc, classNameResultSetProcessor, statementRawInfo); } else if (fafSpec is FireAndForgetSpecDelete) { query = new FAFQueryMethodIUDDeleteForge( specCompiled, compilable, statementRawInfo, compileTimeServices); } else if (fafSpec is FireAndForgetSpecUpdate) { query = new FAFQueryMethodIUDUpdateForge( specCompiled, compilable, statementRawInfo, compileTimeServices); } else { throw new IllegalStateException("Unrecognized FAF code " + fafSpec); } // verify substitution parameters VerifySubstitutionParams(raw.SubstitutionParameters); try { manifest = CompileToAssembly(query, classPostfix, args.Options, services, out assembly); } catch (EPCompileException) { throw; } catch (Exception ex) { throw new EPCompileException( "Unexpected exception compiling module: " + ex.Message, ex, new EmptyList<EPCompileExceptionItem>()); } return new EPCompiled(new [] { assembly }, manifest); }
public static CompilableItem CompileItem( Compilable compilable, string optionalModuleName, string moduleIdentPostfix, int statementNumber, ISet<string> statementNames, ModuleCompileTimeServices moduleCompileTimeServices, CompilerOptions compilerOptions, out Assembly assembly) { var compileTimeServices = new StatementCompileTimeServices(statementNumber, moduleCompileTimeServices); // Stage 0 - parse and compile-inline-classes and walk statement var walked = ParseCompileInlinedClassesWalk(compilable, compileTimeServices); var raw = walked.StatementSpecRaw; string classNameCreateClass = null; if (raw.CreateClassProvided != null) { classNameCreateClass = DetermineClassNameCreateClass(walked.ClassesInlined); } try { // Stage 2(a) - precompile: compile annotations var annotations = AnnotationUtil.CompileAnnotations( raw.Annotations, compileTimeServices.ImportServiceCompileTime, compilable); // Stage 2(b) - walk subselects, alias expressions, declared expressions, dot-expressions ExprNodeSubselectDeclaredDotVisitor visitor; try { visitor = StatementSpecRawWalkerSubselectAndDeclaredDot.WalkSubselectAndDeclaredDotExpr(raw); } catch (ExprValidationException ex) { throw new StatementSpecCompileException(ex.Message, compilable.ToEPL()); } var subselectNodes = visitor.Subselects; // Determine a statement name var statementNameProvided = GetNameFromAnnotation(annotations); if (compilerOptions.StatementName != null) { var assignedName = compilerOptions.StatementName.Invoke( new StatementNameContext( () => compilable.ToEPL(), statementNameProvided, optionalModuleName, annotations, statementNumber)); if (assignedName != null) { statementNameProvided = assignedName; } } var statementName = statementNameProvided ?? Convert.ToString(statementNumber); if (statementNames.Contains(statementName)) { var count = 1; var newStatementName = statementName + "-" + count; while (statementNames.Contains(newStatementName)) { count++; newStatementName = statementName + "-" + count; } statementName = newStatementName; } statementName = statementName.Trim(); statementNames.Add(statementName); // Determine table access nodes var tableAccessNodes = DetermineTableAccessNodes(raw.TableExpressions, visitor); // compile scripts once in this central place, may also compile later in expression ScriptValidationPrecompileUtil.ValidateScripts( raw.ScriptExpressions, raw.ExpressionDeclDesc, compileTimeServices); // Determine subselects for compilation, and lambda-expression shortcut syntax for named windows if (!visitor.ChainedExpressionsDot.IsEmpty()) { RewriteNamedWindowSubselect( visitor.ChainedExpressionsDot, subselectNodes, compileTimeServices.NamedWindowCompileTimeResolver); } // Stage 2(c) compile context descriptor ContextCompileTimeDescriptor contextDescriptor = null; var optionalContextName = raw.OptionalContextName; if (optionalContextName != null) { var detail = compileTimeServices.ContextCompileTimeResolver.GetContextInfo(optionalContextName); if (detail == null) { throw new StatementSpecCompileException( "Context by name '" + optionalContextName + "' could not be found", compilable.ToEPL()); } contextDescriptor = new ContextCompileTimeDescriptor( optionalContextName, detail.ContextModuleName, detail.ContextVisibility, new ContextPropertyRegistry(detail), detail.ValidationInfos); } // Stage 2(d) compile raw statement spec var statementType = StatementTypeUtil.GetStatementType(raw).Value; var statementRawInfo = new StatementRawInfo( statementNumber, statementName, annotations, statementType, contextDescriptor, raw.IntoTableSpec?.Name, compilable, optionalModuleName); var compiledDesc = StatementRawCompiler.Compile( raw, compilable, false, false, annotations, subselectNodes, tableAccessNodes, statementRawInfo, compileTimeServices); var specCompiled = compiledDesc.Compiled; var statementIdentPostfix = IdentifierUtil.GetIdentifierMayStartNumeric(statementName); // get compile-time user object object userObjectCompileTime = null; if (compilerOptions.StatementUserObject != null) { userObjectCompileTime = compilerOptions.StatementUserObject.Invoke( new StatementUserObjectContext( () => compilable.ToEPL(), statementName, optionalModuleName, annotations, statementNumber)); } // handle hooks HandleStatementCompileHook(annotations, compileTimeServices, specCompiled); // Stage 3(a) - statement-type-specific forge building var @base = new StatementBaseInfo( compilable, specCompiled, userObjectCompileTime, statementRawInfo, optionalModuleName); StmtForgeMethod forgeMethod; if (raw.UpdateDesc != null) { forgeMethod = new StmtForgeMethodUpdate(@base); } else if (raw.OnTriggerDesc != null) { forgeMethod = new StmtForgeMethodOnTrigger(@base); } else if (raw.CreateIndexDesc != null) { forgeMethod = new StmtForgeMethodCreateIndex(@base); } else if (raw.CreateVariableDesc != null) { forgeMethod = new StmtForgeMethodCreateVariable(@base); } else if (raw.CreateDataFlowDesc != null) { forgeMethod = new StmtForgeMethodCreateDataflow(@base); } else if (raw.CreateTableDesc != null) { forgeMethod = new StmtForgeMethodCreateTable(@base); } else if (raw.CreateExpressionDesc != null) { forgeMethod = new StmtForgeMethodCreateExpression(@base); } else if (raw.CreateClassProvided != null) { forgeMethod = new StmtForgeMethodCreateClass(@base, walked.ClassesInlined, classNameCreateClass); } else if (raw.CreateWindowDesc != null) { forgeMethod = new StmtForgeMethodCreateWindow(@base); } else if (raw.CreateContextDesc != null) { forgeMethod = new StmtForgeMethodCreateContext(@base); } else if (raw.CreateSchemaDesc != null) { forgeMethod = new StmtForgeMethodCreateSchema(@base); } else { forgeMethod = new StmtForgeMethodSelect(@base); } // check context-validity conditions for this statement if (contextDescriptor != null) { try { foreach (var validator in contextDescriptor.ValidationInfos) { validator.ValidateStatement( contextDescriptor.ContextName, specCompiled, compileTimeServices); } } catch (ExprValidationException ex) { throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL()); } } // Stage 3(b) - forge-factory-to-forge var classPostfix = moduleIdentPostfix + "_" + statementIdentPostfix; var forgeables = new List<StmtClassForgeable>(); // add forgeables from filter-related processing i.e. multikeys foreach (var additional in compiledDesc.AdditionalForgeables) { var namespaceScope = new CodegenNamespaceScope(compileTimeServices.Namespace, null, false); forgeables.Add(additional.Make(namespaceScope, classPostfix)); } var filterSpecCompileds = new List<FilterSpecCompiled>(); var scheduleHandleCallbackProviders = new List<ScheduleHandleCallbackProvider>(); var namedWindowConsumers = new List<NamedWindowConsumerStreamSpec>(); var filterBooleanExpressions = new List<FilterSpecParamExprNodeForge>(); var result = forgeMethod.Make(compileTimeServices.Namespace, classPostfix, compileTimeServices); forgeables.AddAll(result.Forgeables); VerifyForgeables(forgeables); filterSpecCompileds.AddAll(result.Filtereds); scheduleHandleCallbackProviders.AddAll(result.Scheduleds); namedWindowConsumers.AddAll(result.NamedWindowConsumers); filterBooleanExpressions.AddAll(result.FilterBooleanExpressions); // Stage 3(c) - filter assignments: assign filter callback ids and filter-path-num for boolean expressions var filterId = -1; foreach (var provider in filterSpecCompileds) { var assigned = ++filterId; provider.FilterCallbackId = assigned; } // Stage 3(d) - schedule assignments: assign schedule callback ids var scheduleId = 0; foreach (var provider in scheduleHandleCallbackProviders) { provider.ScheduleCallbackId = scheduleId++; } // Stage 3(e) - named window consumers: assign consumer id var namedWindowConsumerId = 0; foreach (var provider in namedWindowConsumers) { provider.NamedWindowConsumerId = namedWindowConsumerId++; } // Stage 3(f) - filter boolean expression id assignment var filterBooleanExprNum = 0; foreach (var expr in filterBooleanExpressions) { expr.FilterBoolExprId = filterBooleanExprNum++; } // Stage 3(f) - verify substitution parameters VerifySubstitutionParams(raw.SubstitutionParameters); // Stage 4 - forge-to-class (forge with statement-fields last) var classes = forgeables .Select(forgeable => forgeable.Forge(true, false)) .ToList(); // Stage 5 - refactor methods to make sure the constant pool does not grow too large for any given class CompilerHelperRefactorToStaticMethods.RefactorMethods( classes, compileTimeServices.Configuration.Compiler.ByteCode.MaxMethodsPerClass); // Stage 6 - sort to make the "fields" class first and all the rest later var sorted = classes .OrderBy(c => c.ClassType.GetSortCode()) .ToList(); // We are making sure JsonEventType receives the underlying class itself CompilableItemPostCompileLatch postCompile = CompilableItemPostCompileLatchDefault.INSTANCE; foreach (var eventType in compileTimeServices.EventTypeCompileTimeRegistry.NewTypesAdded) { if (eventType is JsonEventType) { postCompile = new CompilableItemPostCompileLatchJson( compileTimeServices.EventTypeCompileTimeRegistry.NewTypesAdded, compileTimeServices.ParentClassLoader); break; } } var container = compileTimeServices.Container; var compiler = container .RoslynCompiler() .WithCodeLogging(compileTimeServices.Configuration.Compiler.Logging.IsEnableCode) .WithCodeAuditDirectory(compileTimeServices.Configuration.Compiler.Logging.AuditDirectory) .WithCodegenClasses(sorted); assembly = compiler.Compile(); string statementProviderClassName = CodeGenerationIDGenerator.GenerateClassNameWithNamespace( compileTimeServices.Namespace, typeof(StatementProvider), classPostfix); var additionalClasses = new HashSet<Type>(); additionalClasses.AddAll(walked.ClassesInlined.Classes); compileTimeServices.ClassProvidedCompileTimeResolver.AddTo(additionalClasses); compileTimeServices.ClassProvidedCompileTimeRegistry.AddTo(additionalClasses); return new CompilableItem( statementProviderClassName, classes, postCompile, additionalClasses); } catch (StatementSpecCompileException) { throw; } catch (ExprValidationException ex) { throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL()); } catch (EPException ex) { throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL()); } catch (Exception ex) { var text = ex.Message ?? ex.GetType().FullName; throw new StatementSpecCompileException(text, ex, compilable.ToEPL()); } }