public static IEnumerable <Diagnostic> BindAndAnalyze(PhpCompilation compilation, CancellationToken cancellationToken) { var manager = compilation.GetBoundReferenceManager(); // ensure the references are resolved! (binds ReferenceManager) var diagnostics = new DiagnosticBag(); var compiler = new SourceCompiler(compilation, null, true, diagnostics, cancellationToken); using (compilation.StartMetric("bind")) { // 1. Bind Syntax & Symbols to Operations (CFG) // a. construct CFG, bind AST to Operation // b. declare table of local variables compiler.WalkMethods(compiler.EnqueueRoutine, allowParallel: true); compiler.WalkTypes(compiler.EnqueueType, allowParallel: true); } // Repeat analysis and transformation until either the limit is met or there are no more changes int transformation = 0; do { using (compilation.StartMetric("analysis")) { // 2. Analyze Operations // a. type analysis (converge type - mask), resolve symbols // b. lower semantics, update bound tree, repeat compiler.AnalyzeMethods(); } using (compilation.StartMetric("bind types")) { // 3. Resolve operators and types compiler.BindTypes(); } using (compilation.StartMetric(nameof(ForwardLateStaticBindings))) { // 4. forward the late static type if needed compiler.ForwardLateStaticBindings(); } // 5. Transform Semantic Trees for Runtime Optimization } while ( transformation++ < compiler.MaxTransformCount && // limit number of lowering cycles !cancellationToken.IsCancellationRequested && // user canceled ? compiler.RewriteMethods()); // try lower the semantics // Track the number of actually performed transformations compilation.TrackMetric("transformations", transformation - 1); using (compilation.StartMetric("diagnostic")) { // 6. Collect diagnostics compiler.DiagnoseMethods(); compiler.DiagnoseTypes(); compiler.DiagnoseFiles(); } // return(diagnostics.AsEnumerable()); }