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));
        }
Example #2
0
        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);
        }