private void CopyBindings(FileModuleLiteral file, QualifierValue qualifier) { // Need to copy resolved bindings from a given module. // This requires direct copy for all resolved symbol except namespaces. // In that case new uninstantiated namespace instance is created. if (file.m_resolvedEntries != null) { // Current instance is still under construction, so no locking is needed for m_resolvedEntries field // ReSharper disable once InconsistentlySynchronizedField m_resolvedEntries = new Dictionary <FilePosition, ResolvedEntry>(); foreach (var kvp in file.m_resolvedEntries) { AddResolvedEntry( kvp.Key, CreateResolvedEntryWithNewlyCreatedModuleIfNeeded(kvp.Value, qualifier)); } } if (file.m_resolvedEntriesByFullName != null) { // Current instance is still under construction, so no locking is needed for m_resolvedEntriesByFullName field // ReSharper disable once InconsistentlySynchronizedField m_resolvedEntriesByFullName = new Dictionary <FullSymbol, ResolvedEntry>(); foreach (var kvp in file.m_resolvedEntriesByFullName) { AddResolvedEntry( kvp.Key, CreateResolvedEntryWithNewlyCreatedModuleIfNeeded(kvp.Value, qualifier)); } } }
/// <summary> /// Tries create a qualifier value given an object literal. /// </summary> public static bool TryCreate( ImmutableContextBase context, ModuleLiteral env, object potentialLiteral, out QualifierValue qualifierValue, LineInfo lineInfo = default(LineInfo)) { Contract.Requires(context != null); Contract.Requires(env != null); Contract.Requires(potentialLiteral != null); qualifierValue = null; if (potentialLiteral is ObjectLiteral0) { qualifierValue = CreateEmpty(context.FrontEndContext.QualifierTable); return(true); } if (potentialLiteral is ObjectLiteralSlim || potentialLiteral is ObjectLiteralN) { return(TryCreate(context, env, out qualifierValue, lineInfo, (ObjectLiteral)potentialLiteral)); } var location = lineInfo.AsUniversalLocation(env, context); context.Logger.ReportQualifierMustEvaluateToObjectLiteral(context.LoggingContext, location.AsLoggingLocation(), context.GetStackTraceAsErrorMessage(location)); return(false); }
/// <nodoc/> protected ModuleLiteral(ModuleLiteralId id, QualifierValue qualifier, ModuleLiteral outerScope, LineInfo location) : base(location) { Id = id; m_qualifier = qualifier; OuterScope = outerScope; }
/// <nodoc/> internal FileModuleLiteral(AbsolutePath path, QualifierValue qualifier, GlobalModuleLiteral outerScope, Package package, ModuleRegistry moduleRegistry, LineMap lineMap) : this(ModuleLiteralId.Create(path), qualifier, outerScope, package, lineMap) { Contract.Requires(path.IsValid); Contract.Requires(lineMap != null); m_moduleRegistry = moduleRegistry; }
/// <nodoc/> public TypeOrNamespaceModuleLiteral(ModuleLiteralId id, QualifierValue qualifier, ModuleLiteral outerScope, LineInfo location) : base(id, qualifier, outerScope, location) { Contract.Requires(id.Name.IsValid, "id.Name.IsValid"); Contract.Requires(outerScope != null, "outerScope != null"); // Only in V1 type or namespace module literals are unqualified. In V2 unqualified is never used for type or namespace literals. Contract.Requires(qualifier == QualifierValue.Unqualified || outerScope.Qualifier.QualifierId == qualifier.QualifierId); }
private async Task <object> EvaluateResolverCallback(Context context, QualifierId qualifier, FilePosition filePosition, ResolvedEntry resolvedEntry) { var qualifierValue = QualifierValue.Create(qualifier, context.QualifierValueCache, context.FrontEndContext.QualifierTable, context.StringTable); var env = InstantiateFileModuleLiteral(context.ModuleRegistry, qualifierValue); using (var args = EvaluationStackFrame.Empty()) { return(await resolvedEntry.ResolverCallback(context, env, args)); } }
/// <summary> /// Tries coercing qualifier. /// </summary> public bool TryCoerce( QualifierSpaceId targetQualifierSpaceId, QualifierTable qualifierTable, QualifierValueCache cache, PathTable pathTable, StringTable stringTable, LoggingContext loggingContext, out QualifierValue qualifierValue, LineInfo location, bool useDefaultsForCoercion, AbsolutePath path) { Contract.Requires(targetQualifierSpaceId.IsValid); Contract.Requires(qualifierTable != null); Contract.Requires(qualifierTable.IsValidQualifierSpaceId(targetQualifierSpaceId)); Contract.Requires(pathTable != null); Contract.Requires(stringTable != null); Contract.Requires(loggingContext != null); #if DEBUG Contract.Ensures(Contract.ValueAtReturn(out qualifierValue) == null || Contract.Result <bool>() == true, "expected 'qualifierValue' to be set to null when return value is 'false'"); Contract.Ensures(Contract.ValueAtReturn(out qualifierValue) != null || Contract.Result <bool>() == false, "expected 'qualifierValue' to be set to non-null when return value is 'true'"); #endif qualifierValue = null; if (targetQualifierSpaceId == qualifierTable.EmptyQualifierSpaceId) { qualifierValue = CreateEmpty(qualifierTable); return(true); } if (qualifierTable.TryCreateQualifierForQualifierSpace( pathTable, loggingContext, QualifierId, targetQualifierSpaceId, useDefaultsForCoercion, out QualifierId resultingQualifierId, out UnsupportedQualifierValue error)) { qualifierValue = Create(resultingQualifierId, cache, qualifierTable, stringTable); return(true); } var errorLocation = LocationData.Create(path, location.Line, location.Position); error.Location = errorLocation.ToLogLocation(pathTable); Logger.Log.ErrorUnsupportedQualifierValue( loggingContext, error.Location, error.QualifierKey, error.InvalidValue, error.LegalValues); return(false); }
/// <nodoc/> internal FileModuleLiteral(ModuleLiteralId id, QualifierValue qualifier, GlobalModuleLiteral outerScope, Package package, LineMap lineMap) : base(id, qualifier, outerScope, location: default(LineInfo)) { Contract.Requires(id.Path.IsValid); Contract.Requires(package != null); Contract.Requires(lineMap != null); Package = package; m_partialSymbolsCache = Lazy.Create(() => new ConcurrentDictionary <FullSymbol, ModuleBinding>()); LineMap = lineMap; }
/// <summary> /// Tries coercing qualifier. /// </summary> public bool TryCoerce( QualifierSpaceId targetQualifierSpaceId, QualifierTable qualifierTable, QualifierValueCache cache, PathTable pathTable, StringTable stringTable, LoggingContext loggingContext, out QualifierValue qualifierValue, LineInfo location, bool useDefaultsForCoercion, AbsolutePath path) { Contract.Requires(targetQualifierSpaceId.IsValid); Contract.Requires(qualifierTable != null); Contract.Requires(qualifierTable.IsValidQualifierSpaceId(targetQualifierSpaceId)); Contract.Requires(pathTable != null); Contract.Requires(stringTable != null); Contract.Requires(loggingContext != null); qualifierValue = null; if (targetQualifierSpaceId == qualifierTable.EmptyQualifierSpaceId) { qualifierValue = CreateEmpty(qualifierTable); return(true); } if (qualifierTable.TryCreateQualifierForQualifierSpace( pathTable, loggingContext, QualifierId, targetQualifierSpaceId, useDefaultsForCoercion, out QualifierId resultingQualifierId, out UnsupportedQualifierValue error)) { qualifierValue = Create(resultingQualifierId, cache, qualifierTable, stringTable); return(true); } var errorLocation = LocationData.Create(path, location.Line, location.Position); error.Location = errorLocation.ToLogLocation(pathTable); Logger.Log.ErrorUnsupportedQualifierValue( loggingContext, error.Location, error.QualifierKey, error.InvalidValue, error.LegalValues); return(false); }
private EvaluationResult EvaluateResolvedEntry(Context context, QualifierId qualifier, FilePosition filePosition, ResolvedEntry resolvedEntry) { var qualifierValue = QualifierValue.Create(qualifier, context.QualifierValueCache, context.FrontEndContext.QualifierTable, context.StringTable); var instantiatedModule = InstantiateFileModuleLiteral(context.ModuleRegistry, qualifierValue); if (resolvedEntry.Thunk == null) { return(instantiatedModule.EvaluateNonThunkedResolvedSymbol(context, instantiatedModule, resolvedEntry)); } var name = resolvedEntry.ThunkContextName; return(instantiatedModule.EvaluateByLocation(context, filePosition, name, resolvedEntry.Location)); }
private FileModuleLiteral GetFileModuleInstanceFromImportOrExportDeclaration( ModuleRegistry moduleRegistry, AbsolutePath referencedPath) { var importedModuleId = ModuleLiteralId.Create(referencedPath); // Get the uninstantiated version of this file module. UninstantiatedModuleInfo importedModuleInfo = moduleRegistry.GetUninstantiatedModuleInfoByModuleId(importedModuleId); // Evaluate qualifier if specified. QualifierValue qualifierValue = Qualifier; // Instantiate this file module according to the qualifier. FileModuleLiteral importedModule = importedModuleInfo.FileModuleLiteral.InstantiateFileModuleLiteral(moduleRegistry, qualifierValue); return(importedModule); }
private static bool TryCreate( ImmutableContextBase context, ModuleLiteral env, out QualifierValue qualifierValue, LineInfo lineInfo, ObjectLiteral objectLiteral) { Contract.Requires(context != null); Contract.Requires(env != null); Contract.Requires(objectLiteral != null); qualifierValue = null; if (objectLiteral.Count == 0) { qualifierValue = CreateEmpty(context.FrontEndContext.QualifierTable); return(true); } Tuple <StringId, StringId>[] qualifierKvps = new Tuple <StringId, StringId> [objectLiteral.Count]; int i = 0; foreach (var kvp in objectLiteral.Members) { if (!(kvp.Value.Value is string value)) { var location = lineInfo.AsUniversalLocation(env, context); var error = new ErrorContext(name: kvp.Key, objectCtx: objectLiteral).ToErrorString(context); context.Logger.ReportQualifierValueMustEvaluateToString(context.LoggingContext, location.AsLoggingLocation(), error, context.GetStackTraceAsErrorMessage(location)); return(false); } qualifierKvps[i] = Tuple.Create(kvp.Key, context.FrontEndContext.StringTable.AddString(value)); ++i; } QualifierId qualifierId = context.FrontEndContext.QualifierTable.CreateQualifier(qualifierKvps); qualifierValue = new QualifierValue(objectLiteral, qualifierId); return(true); }
private FileModuleLiteral DoInstantiate(FileModuleLiteral module, QualifierValue qualifier, GlobalModuleLiteral outerScope) { Contract.Requires(module != null); Contract.Requires(qualifier != QualifierValue.Unqualified); Interlocked.CompareExchange(ref m_qualifier, qualifier, QualifierValue.Unqualified); if (m_qualifier.QualifierId == qualifier.QualifierId) { // Uninstantiated module becomes the first instance. return(this); } // Create a new file module instance. var newModule = CreateInstantiatedFileModule(module.Id.Path, qualifier, outerScope, module.Package, module.m_moduleRegistry, LineMap); newModule.CopyBindings(module, qualifier); return(newModule); }
/// <nodoc /> public override ModuleLiteral Instantiate(ModuleRegistry moduleRegistry, QualifierValue qualifier) { Contract.Assert(moduleRegistry != null); Contract.Assert(qualifier != QualifierValue.Unqualified); // Due to sharing the following contract no longer holds: Contract.Requires(Qualifier == Unqualified); var moduleKey = QualifiedModuleId.Create(Id, qualifier.QualifierId); return(moduleRegistry.InstantiateModule( (moduleRegistry, @this: this, qualifier, CurrentFileModule), moduleKey, (state, k) => { var localModuleRegistry = state.moduleRegistry; var @this = state.@this; var localQualifier = state.qualifier; var localCurrentFileModule = state.CurrentFileModule; return @this.DoInstantiate(localModuleRegistry, @this, localQualifier, localCurrentFileModule); })); }
/// <summary> /// Instantiates this file module for with a given qualifier. /// </summary> public override ModuleLiteral Instantiate(ModuleRegistry moduleRegistry, QualifierValue qualifier) { Contract.Assert(moduleRegistry != null); Contract.Assert(qualifier != QualifierValue.Unqualified); // Due to sharing the following contract no longer holds: Contract.Requires(Qualifier == Unqualified); var moduleKey = QualifiedModuleId.Create(Id, qualifier.QualifierId); var globalOuterScope = OuterScope as GlobalModuleLiteral; Contract.Assert(globalOuterScope != null, "For a FileModuleLiteral, the outer scope should be always a global module literal"); return(moduleRegistry.InstantiateModule((this, qualifier, globalOuterScope), moduleKey, (state, k) => { // Avoid closure allocation. var @this = state.Item1; var capturedQualifier = state.Item2; var capturedGlobalOuterScope = state.Item3; return @this.DoInstantiate(@this, capturedQualifier, capturedGlobalOuterScope); })); }
/// <summary> /// Evaluates thunk by lazily creating the context only if the thunk has not been evaluated yet. /// </summary> public EvaluationResult Evaluate(ImmutableContextBase context, ModuleLiteral env, EvaluationStackFrame args, ref MutableContextFactory factory) { context.EvaluationScheduler.CancellationToken.ThrowIfCancellationRequested(); QualifierValue qualifier = env.GetFileQualifier() ?? env.Qualifier; // Looking in the optimized map if the qualifier id is small enough. QualifiedValue qualifiedEntry; if (qualifier.QualifierId.IsValid && qualifier.QualifierId.Id < TableSize) { qualifiedEntry = GetQualifiedValue(qualifier.QualifierId.Id); } else { // Falling back to more memory intensive concurrent dictionary. EnsureDictionaryIsInitialized(); qualifiedEntry = m_qualifiedDictionary.GetOrAdd(qualifier.QualifierId, new QualifiedValue()); } var qualifiedValue = qualifiedEntry.Value; var result = (qualifiedValue == null || qualifiedValue is Evaluation) ? QualifiedEvaluate(ref qualifiedEntry.Value, context, env, args, ref factory) : (EvaluationResult)qualifiedValue; // Cancel evaluation if (1) result is an error value, (2) we are configured to cancel evaluation after first failure, and (3) cancellation hasn't already been requested if (result.IsErrorValue && context.FrontEndHost.FrontEndConfiguration.CancelEvaluationOnFirstFailure() && !context.EvaluationScheduler.CancellationToken.IsCancellationRequested) { context.Logger.EvaluationCancellationRequestedAfterFirstFailure(context.LoggingContext); context.EvaluationScheduler.Cancel(); } return(result); }
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)); }
/// <inheritdoc/> public override ModuleLiteral Instantiate(ModuleRegistry moduleRegistry, QualifierValue qualifier) { Contract.Assert(false, "GlobalModuleLiteral cannot be instantiated"); throw new NotImplementedException(); }
/// <summary> /// Instantiates the module literal with the provided qualifier /// </summary> public abstract ModuleLiteral Instantiate(ModuleRegistry moduleRegistry, QualifierValue qualifier);
/// <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)); }
/// <summary> /// Constructs an instantiated file module denoted by a path. /// </summary> /// <remarks> /// The outer scope is typically the global module. /// </remarks> protected static FileModuleLiteral CreateInstantiatedFileModule(AbsolutePath path, QualifierValue qualifier, GlobalModuleLiteral globalScope, Package package, ModuleRegistry moduleRegistry, LineMap lineMap) { return(new FileModuleLiteral(path, qualifier, globalScope, package, moduleRegistry, lineMap)); }
/// <summary> /// Same as <see cref="Instantiate"/>, but the result is presented with a more specific type (FileModuleLiteral) /// </summary> public FileModuleLiteral InstantiateFileModuleLiteral(ModuleRegistry moduleRegistry, QualifierValue qualifier) { return((FileModuleLiteral)Instantiate(moduleRegistry, qualifier)); }