private SemanticModel GetSemanticModelInternal(SyntaxTree syntaxTree) { var builtinNamespaces = new NamespaceSymbol[] { new SystemNamespaceSymbol(), new AzNamespaceSymbol() } .ToImmutableDictionary(property => property.Name, property => property, LanguageConstants.IdentifierComparer); var bindings = new Dictionary <SyntaxBase, Symbol>(); var cyclesBySymbol = new Dictionary <DeclaredSymbol, ImmutableArray <DeclaredSymbol> >(); var hierarchy = new SyntaxHierarchy(); hierarchy.AddRoot(syntaxTree.ProgramSyntax); // create this in locked mode by default // this blocks accidental type or binding queries until binding is done // (if a type check is done too early, unbound symbol references would cause incorrect type check results) var symbolContext = new SymbolContext(new TypeManager(resourceTypeProvider, bindings, cyclesBySymbol, hierarchy), bindings, this); // collect declarations var declarations = new List <DeclaredSymbol>(); var declarationVisitor = new DeclarationVisitor(symbolContext, declarations); declarationVisitor.Visit(syntaxTree.ProgramSyntax); // in cases of duplicate declarations we will see multiple declaration symbols in the result list // for simplicitly we will bind to the first one // it may cause follow-on type errors, but there will also be errors about duplicate identifiers as well var uniqueDeclarations = declarations .ToLookup(x => x.Name, LanguageConstants.IdentifierComparer) .ToImmutableDictionary(x => x.Key, x => x.First(), LanguageConstants.IdentifierComparer); // bind identifiers to declarations var binder = new NameBindingVisitor(uniqueDeclarations, bindings, builtinNamespaces); binder.Visit(syntaxTree.ProgramSyntax); var shortestCycleBySymbol = CyclicCheckVisitor.FindCycles(syntaxTree.ProgramSyntax, uniqueDeclarations, bindings); foreach (var kvp in shortestCycleBySymbol) { cyclesBySymbol.Add(kvp.Key, kvp.Value); } // TODO: Avoid looping 5 times? var file = new FileSymbol( syntaxTree.FilePath, syntaxTree.ProgramSyntax, builtinNamespaces, declarations.OfType <ParameterSymbol>(), declarations.OfType <VariableSymbol>(), declarations.OfType <ResourceSymbol>(), declarations.OfType <ModuleSymbol>(), declarations.OfType <OutputSymbol>()); // name binding is done // allow type queries now symbolContext.Unlock(); return(new SemanticModel(file, symbolContext.TypeManager, bindings)); }
private SemanticModel GetSemanticModelInternal() { var builtinNamespaces = new NamespaceSymbol[] { new SystemNamespaceSymbol(), new AzNamespaceSymbol() }.ToImmutableArray(); var bindings = new Dictionary <SyntaxBase, Symbol>(); // create this in locked mode by default // this blocks accidental type or binding queries until binding is done // (if a type check is done too early, unbound symbol references would cause incorrect type check results) var symbolContext = new SymbolContext(new TypeManager(bindings), bindings); // collect declarations var declarations = new List <DeclaredSymbol>(); var declarationVisitor = new DeclarationVisitor(symbolContext, declarations); declarationVisitor.Visit(this.ProgramSyntax); // in cases of duplicate declarations we will see multiple declaration symbols in the result list // for simplicitly we will bind to the first one // it may cause follow-on type errors, but there will also be errors about duplicate identifiers as well var uniqueDeclarations = declarations .ToLookup(x => x.Name, LanguageConstants.IdentifierComparer) .ToImmutableDictionary(x => x.Key, x => x.First(), LanguageConstants.IdentifierComparer); // bind identifiers to declarations var binder = new NameBindingVisitor(uniqueDeclarations, bindings, builtinNamespaces); binder.Visit(this.ProgramSyntax); // name binding is done // allow type queries now symbolContext.Unlock(); // TODO: Avoid looping 4 times? var file = new FileSymbol("main", this.ProgramSyntax, builtinNamespaces, declarations.OfType <ParameterSymbol>(), declarations.OfType <VariableSymbol>(), declarations.OfType <ResourceSymbol>(), declarations.OfType <OutputSymbol>()); return(new SemanticModel(file, symbolContext.TypeManager, bindings)); }