/// <summary> /// If a given resolved entry points to a namespace, then new uninstantiated <see cref="TypeOrNamespaceModuleLiteral"/> will be created. /// </summary> /// <remarks> /// This method plays a crucial role in qualifiers implementation. /// In V1 the current qualifier of a nested namespace is searched by looking up until the current qualifier of the parent file /// module literal is found. So when instantiating a new module, its child namespaces need to be chained to it. /// </remarks> private ResolvedEntry CreateResolvedEntryWithNewlyCreatedModuleIfNeeded(ResolvedEntry resolvedEntry, QualifierValue qualifier) { if (!(resolvedEntry.Expression is TypeOrNamespaceModuleLiteral typeOrNamespace)) { return(resolvedEntry); } var newM = new TypeOrNamespaceModuleLiteral(typeOrNamespace.Id, qualifier, this, typeOrNamespace.Location); return(new ResolvedEntry(FullSymbol.Invalid, newM)); }
/// <inheritdoc /> internal override void AddNamespace(FullSymbol name, UniversalLocation location, QualifierSpaceId?qualifierSpaceId, out TypeOrNamespaceModuleLiteral module) { module = CreateTypeOrNamespaceModule(name, outerScope: this, location: location.AsLineInfo()); Contract.Assert(qualifierSpaceId != null, "Qualifier type should be provided for a semantic evaluation"); m_moduleRegistry.AddUninstantiatedModuleInfo(new UninstantiatedModuleInfo(sourceFile: null, typeOrNamespaceLiteral: module, qualifierSpaceId: qualifierSpaceId.Value)); AddResolvedEntry(location.AsFilePosition(), new ResolvedEntry(name, module)); }
/// <inheritdoc /> internal override void AddType(FullSymbol name, UniversalLocation location, QualifierSpaceId?qualifierSpaceId, out TypeOrNamespaceModuleLiteral module) { module = CreateTypeOrNamespaceModule(name, outerScope: this, location: location.AsLineInfo()); Contract.Assert(qualifierSpaceId == null, "Only namespace support qualifier types"); AddResolvedEntry(location.AsFilePosition(), new ResolvedEntry(name, module)); }
private TypeOrNamespaceModuleLiteral DoInstantiate(ModuleRegistry moduleRegistry, TypeOrNamespaceModuleLiteral module, QualifierValue qualifier, FileModuleLiteral outerScope) { Contract.Requires(module != null); Contract.Requires(qualifier != QualifierValue.Unqualified); Interlocked.CompareExchange(ref m_qualifier, qualifier, QualifierValue.Unqualified); // The outer scope of this should have the same qualifier. So if that's not the case we instantiate one and set the parent appropriately if (outerScope.Qualifier.QualifierId != qualifier.QualifierId) { var newOuterScope = moduleRegistry.InstantiateModule( (outerScope, moduleRegistry, qualifier), QualifiedModuleId.Create(outerScope.Id, qualifier.QualifierId), (state, qualifiedModuleId) => { var capturedOuterScope = state.outerScope; var capturedModuleRegistry = state.moduleRegistry; var capturedQualifier = state.qualifier; return(capturedOuterScope.InstantiateFileModuleLiteral(capturedModuleRegistry, capturedQualifier)); }); return(new TypeOrNamespaceModuleLiteral(module.Id, qualifier, newOuterScope, module.Location)); } if (m_qualifier.QualifierId == qualifier.QualifierId) { // Uninstantiated module becomes the first instance. return(this); } // Create a new file module instance. return(new TypeOrNamespaceModuleLiteral(module.Id, qualifier, outerScope, module.Location)); }
/// <summary> /// Adds a namespace with a given name. /// </summary> internal virtual void AddNamespace(FullSymbol name, UniversalLocation location, QualifierSpaceId?qualifierSpaceId, out TypeOrNamespaceModuleLiteral module) { Contract.Requires(name.IsValid); Contract.Requires(Qualifier == QualifierValue.Unqualified); Contract.Assert(IsFileOrGlobal, "Current instance should be a file module or global ambient module"); lock (m_syncRoot) { m_nsBindings = m_nsBindings ?? new NsBindingDictionary(); if (m_nsBindings.ContainsKey(name)) { var moduleBinding = m_nsBindings[name]; Contract.Assert(moduleBinding.Body is TypeOrNamespaceModuleLiteral); module = (TypeOrNamespaceModuleLiteral)moduleBinding.Body; return; } module = CreateTypeOrNamespaceModule(name, outerScope: this, location: location.AsLineInfo()); // Module is always exported. m_nsBindings.Add(name, new ModuleBinding(module, Declaration.DeclarationFlags.Export, location.AsLineInfo())); } }
/// <summary> /// Adds a type with a given name. /// qualifierSpaceId is null for V1 and not null for v2. /// This is needed for a semantic-based evaluation and helps to filter nested variable declarations from the evaluation. /// </summary> internal virtual void AddType(FullSymbol name, UniversalLocation location, QualifierSpaceId?qualifierSpaceId, out TypeOrNamespaceModuleLiteral module) { AddNamespace(name, location, qualifierSpaceId, out module); }