public static TopLevelConstruct[] Resolve(ParserContext parser, ICollection <CompilationScope> compilationScopesRaw)
        {
            List <TopLevelConstruct> originalCode = new List <TopLevelConstruct>();

            foreach (CompilationScope scope in compilationScopesRaw.OrderBy(scope => scope.ScopeKey))
            {
                originalCode.AddRange(scope.GetExecutables_HACK());
            }
            TopLevelConstruct[] code = originalCode.ToArray();

            parser.VerifyNoBadImports();

            LibraryCompilationScope[] librariesInDependencyOrder = LibraryDependencyResolver.GetLibraryResolutionOrder(parser);
            List <CompilationScope>   compilationScopes          = new List <CompilationScope>(librariesInDependencyOrder);

            compilationScopes.Add(parser.UserCodeCompilationScope);

            using (new PerformanceSection("ResolveNames for compilation scopes"))
            {
                // Resolve raw names into the actual things they refer to based on namespaces and imports.
                foreach (CompilationScope scope in compilationScopes)
                {
                    using (new PerformanceSection("Resolve Names for: " + scope.ScopeKey))
                    {
                        NameResolver.Resolve(parser, scope);
                    }
                }
            }

            SpecialFunctionFinder.Run(parser);

            code = SimpleFirstPass.Run(parser, code);

            parser.InlinableLibraryFunctions = InlineableLibraryFunctionFinder.Find(code);

            code = DependencyBasedClassSorter.Run(code);

            LocalScopeVariableIdAllocator.Run(parser, code);
            LocaleIdAllocator.Run(parser, compilationScopes);

            return(code);
        }
Example #2
0
        public static TopLevelEntity[] Resolve(ParserContext parser, ICollection<CompilationScope> compilationScopesRaw)
        {
            List<TopLevelEntity> originalCode = new List<TopLevelEntity>();
            Dictionary<string, CompilationScope> compilationScopeLookup = new Dictionary<string, CompilationScope>();
            foreach (CompilationScope scope in compilationScopesRaw.OrderBy(scope => scope.ScopeKey))
            {
                originalCode.AddRange(scope.GetExecutables_HACK());
                compilationScopeLookup[scope.Metadata.ID] = scope;
            }
            TopLevelEntity[] code = originalCode.ToArray();

            parser.VerifyNoBadImports();

            AssemblyMetadata[] assembliesInDependencyOrder = AssemblyDependencyResolver.GetAssemblyResolutionOrder(parser.ScopeManager.ImportedAssemblyScopes.Select(scope => scope.Metadata));
            List<CompilationScope> compilationScopes = new List<CompilationScope>(
                assembliesInDependencyOrder.Select(asm => compilationScopeLookup[asm.ID]));
            compilationScopes.Add(parser.RootScope);

            using (new PerformanceSection("ResolveNames for compilation scopes"))
            {
                // Resolve raw names into the actual things they refer to based on namespaces and imports.
                foreach (CompilationScope scope in compilationScopes)
                {
                    using (new PerformanceSection("Resolve Names for: " + scope.ScopeKey))
                    {
                        EntityNameResolver.Resolve(parser, scope);
                    }
                }
            }

            LocalScopeVariableIdAllocator.Run(parser, code.Where(tle => !(tle is ConstDefinition || tle is EnumDefinition)));

            using (new PerformanceSection("Resolve Types"))
            {
                foreach (CompilationScope scope in compilationScopes)
                {
                    using (new PerformanceSection("Resolve types for: " + scope.ScopeKey))
                    {
                        TopLevelEntity[] topLevelEntities = scope.GetTopLevelConstructs();
                        ConstDefinition[] consts = topLevelEntities.OfType<ConstDefinition>().ToArray();
                        EnumDefinition[] enums = topLevelEntities.OfType<EnumDefinition>().ToArray();
                        ClassDefinition[] classes = topLevelEntities.OfType<ClassDefinition>().ToArray();
                        FunctionDefinition[] functions = topLevelEntities.OfType<FunctionDefinition>().ToArray();

                        // Constants are provided in dependency order. Type resolution running in this order
                        // will not encounter anything unknown. Const dependency loops are found by .SortConstants()
                        // Note that this sorting is for the purposes of type resolution. All enums are automatically
                        // known to be integers, so there's possibly still some dependency loops there, which are
                        // caught during the consolidation in the Resolve() phase.

                        TopLevelEntity[] topLevelEntitiesWithoutConstants = new TopLevelEntity[0]
                            .Concat(enums)
                            .Concat(functions)
                            .Concat(classes)
                            .ToArray();

                        // The type of the overall constant is dependent on the expression's type when there are
                        // no type declarations (i.e. Crayon). Because signature types need to be resolved before
                        // the expression itself, these are sorted in dependency order. Enum values, even though
                        // a const expression can depend on them, are always an integer, so they don't need to be
                        // type-resolved at this time.
                        ConstDefinition[] dependencySortedConstants = new ConstantDependencySorter(consts).SortConstants();
                        foreach (ConstDefinition cnst in dependencySortedConstants)
                        {
                            TypeResolver typeResolver = new TypeResolver(cnst);

                            // This shouldn't pick anything up, but it'll fire any errors when undeclared variable-like expressions are used.
                            cnst.Expression.ResolveVariableOrigins(parser, VariableScope.NewEmptyScope(false), VariableIdAllocPhase.REGISTER_AND_ALLOC);

                            cnst.ResolveTypes(parser, typeResolver);
                            cnst.ValidateConstTypeSignature();
                        }

                        foreach (TopLevelEntity tle in topLevelEntitiesWithoutConstants)
                        {
                            TypeResolver typeResolver = new TypeResolver(tle);
                            tle.ResolveSignatureTypes(parser, typeResolver);
                        }

                        foreach (TopLevelEntity tle in topLevelEntitiesWithoutConstants.Where(t => !(t is EnumDefinition)))
                        {
                            tle.EnsureModifierAndTypeSignatureConsistency();
                        }

                        foreach (TopLevelEntity tle in topLevelEntitiesWithoutConstants)
                        {
                            TypeResolver typeResolver = new TypeResolver(tle);
                            tle.ResolveTypes(parser, typeResolver);
                        }
                    }
                }
            }

            SpecialFunctionFinder.Run(parser);

            List<TopLevelEntity> newCode = new List<TopLevelEntity>();
            foreach (CompilationScope scope in compilationScopes)
            {
                TopLevelEntity[] everything = scope.GetTopLevelConstructs();
                TopLevelEntity[] constsAndEnums = new TopLevelEntity[0]
                    .Concat(everything.OfType<ConstDefinition>())
                    .Concat(everything.OfType<EnumDefinition>())
                    .ToArray();
                TopLevelEntity[] codeContainers = new TopLevelEntity[0]
                    .Concat(everything.OfType<FunctionDefinition>())
                    .Concat(everything.OfType<ClassDefinition>())
                    .ToArray();
                foreach (TopLevelEntity tle in everything.Concat(codeContainers))
                {
                    tle.Resolve(parser);
                }
                newCode.AddRange(DependencyBasedClassSorter.Run(codeContainers));
            }

            code = newCode.ToArray();

            parser.InlinableLibraryFunctions = InlineableLibraryFunctionFinder.Find(code);

            return code;
        }