Пример #1
0
        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));
                }
            }
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
 /// <nodoc/>
 protected ModuleLiteral(ModuleLiteralId id, QualifierValue qualifier, ModuleLiteral outerScope, LineInfo location)
     : base(location)
 {
     Id          = id;
     m_qualifier = qualifier;
     OuterScope  = outerScope;
 }
Пример #4
0
        /// <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;
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        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));
            }
        }
Пример #7
0
        /// <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);
        }
Пример #8
0
        /// <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;
        }
Пример #9
0
        /// <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);
        }
Пример #10
0
        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));
        }
Пример #11
0
        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);
        }
Пример #12
0
        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);
        }
Пример #13
0
        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);
        }
Пример #14
0
        /// <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);
            }));
        }
Пример #15
0
        /// <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);
            }));
        }
Пример #16
0
        /// <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);
        }
Пример #17
0
        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));
        }
Пример #18
0
 /// <inheritdoc/>
 public override ModuleLiteral Instantiate(ModuleRegistry moduleRegistry, QualifierValue qualifier)
 {
     Contract.Assert(false, "GlobalModuleLiteral cannot be instantiated");
     throw new NotImplementedException();
 }
Пример #19
0
 /// <summary>
 /// Instantiates the module literal with the provided qualifier
 /// </summary>
 public abstract ModuleLiteral Instantiate(ModuleRegistry moduleRegistry, QualifierValue qualifier);
Пример #20
0
        /// <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));
        }
Пример #21
0
 /// <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));
 }
Пример #22
0
 /// <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));
 }