public Package Analyze( PackageSyntax packageSyntax, FixedDictionary <string, Package> references) { // First pull over all the lexer and parser errors from the compilation units var diagnostics = AllDiagnostics(packageSyntax); var scopesBuilder = new LexicalScopesBuilder(diagnostics, packageSyntax, references); scopesBuilder.BuildScopesInPackage(packageSyntax); // Make a list of all the member declarations (i.e. not namespaces) var memberDeclarations = packageSyntax.CompilationUnits .SelectMany(cu => cu.AllMemberDeclarations).ToFixedList(); // TODO we can't do full type checking without some IL gen and code execution, how to handle that? // Do type checking TypeResolver.Check(memberDeclarations, diagnostics); #if DEBUG TypeResolutionValidator.Validate(memberDeclarations); // TODO validate that all ReferencedSymbols lists have a single value non-errored code #endif MoveChecker.Check(memberDeclarations, diagnostics); ShadowChecker.Check(memberDeclarations, diagnostics); // TODO we need to check definite assignment as part of this BindingMutabilityChecker.Check(memberDeclarations, diagnostics); // -------------------------------------------------- // This is where the representation transitions to IR ControlFlowAnalyzer.BuildGraphs(memberDeclarations); // -------------------------------------------------- var liveness = LivenessAnalyzer.Analyze(memberDeclarations); DeleteInserter.Transform(memberDeclarations, liveness); BorrowChecker.Check(memberDeclarations, diagnostics); // Build final declaration objects and find the entry point var declarationBuilder = new DeclarationBuilder(); var declarations = declarationBuilder.Build(memberDeclarations); var entryPoint = DetermineEntryPoint(declarations, diagnostics); return(new Package(packageSyntax.Name, diagnostics.Build(), references, declarations, entryPoint)); }
private static Package CheckSemantics(PackageSyntax packageSyntax) { DeclarationNumberAssigner.AssignIn(packageSyntax.AllEntityDeclarations); // Resolve symbols for the entities EntitySymbolBuilder.BuildFor(packageSyntax); var stringSymbol = packageSyntax.SymbolTrees .GlobalSymbols .OfType <ObjectTypeSymbol>() .SingleOrDefault(s => s.Name == "String"); // Basic Analysis includes: Name Binding, Type Checking, Constant Folding BasicAnalyzer.Check(packageSyntax, stringSymbol); // If there are errors from the basic analysis phase, don't continue on packageSyntax.Diagnostics.ThrowIfFatalErrors(); #if DEBUG new SymbolValidator(packageSyntax.SymbolTree).Validate(packageSyntax.AllEntityDeclarations); new TypeFulfillmentValidator().Validate(packageSyntax.AllEntityDeclarations); new TypeKnownValidator().Validate(packageSyntax.AllEntityDeclarations); new ExpressionSemanticsValidator().Validate(packageSyntax.AllEntityDeclarations); #endif var package = new ASTBuilder().BuildPackage(packageSyntax); // From this point forward, analysis focuses on executable declarations (i.e. invocables and field initializers) var executableDeclarations = package.AllDeclarations.OfType <IExecutableDeclaration>().ToFixedSet(); ShadowChecker.Check(executableDeclarations, package.Diagnostics); DataFlowAnalysis.Check(DefiniteAssignmentAnalyzer.Instance, executableDeclarations, package.SymbolTree, package.Diagnostics); DataFlowAnalysis.Check(BindingMutabilityAnalyzer.Instance, executableDeclarations, package.SymbolTree, package.Diagnostics); DataFlowAnalysis.Check(UseOfMovedValueAnalyzer.Instance, executableDeclarations, package.SymbolTree, package.Diagnostics); // TODO use DataFlowAnalysis to check for unused variables and report use of variables starting with `_` // Compute variable liveness needed by reachability analyzer DataFlowAnalysis.Check(LivenessAnalyzer.Instance, executableDeclarations, package.SymbolTree, package.Diagnostics); ReachabilityAnalyzer.Analyze(executableDeclarations, package.SymbolTree, package.Diagnostics); // TODO remove live variables if SaveLivenessAnalysis is false return(package); }