public QualifierValue GetQualifierValue()
        {
            var qualifierTable = new QualifierTable(m_stringTable);
            var qualifierId    = qualifierTable.CreateQualifier(new Tuple <string, string>("hey", "hello"));

            return(QualifierValue.Create(qualifierId, qualifierTable, m_stringTable));
        }
Пример #2
0
 /// <nodoc/>
 public virtual void InitializeInterpreter(FrontEndHost host, FrontEndContext context, IConfiguration configuration)
 {
     FrontEndHost    = host;
     Context         = context;
     m_configuration = configuration;
     EmptyQualifier  = QualifierValue.CreateEmpty(context.QualifierTable);
     IsBeingDebugged = configuration.FrontEnd.DebugScript();
 }
Пример #3
0
        /// <summary>
        /// Adds a given <paramref name="value"/> to the cache if the corresponding qualifier id is less then a size of the cache.
        /// </summary>
        public bool TryAdd([NotNull] QualifierValue value)
        {
            if (value.QualifierId.Id < CacheSize)
            {
                Volatile.Write(ref m_qualifierValuesCache[value.QualifierId.Id], value);
                return(true);
            }

            return(false);
        }
Пример #4
0
        /// <inheritdoc />
        public async Task <bool?> TryEvaluateModuleAsync([NotNull] IEvaluationScheduler scheduler, [NotNull] ModuleDefinition module, QualifierId qualifierId)
        {
            // Abstraction between SDK/Workspace/Core/Resolvers is broken here...
            var moduleDefinition = (ModuleDefinition)module;

            if (!string.Equals(moduleDefinition.Descriptor.ResolverName, Name, StringComparison.Ordinal))
            {
                return(null);
            }

            var downloadData = m_workspaceResolver.Downloads[module.Descriptor.Name];

            // Make sure evaluating is guarded by the semaphore, so it only happens one at a time
            // There is no need to make sure we don't evaluate duplicate work here since module evaluation
            // happens once per qualifier.
            await m_evaluationSemaphore.WaitAsync();

            try
            {
                // Modules of the download resolver are always instantiated with the empty qualifier
                var moduleRegistry = (ModuleRegistry)m_frontEndHost.ModuleRegistry;
                var moduleLiteral  = moduleRegistry
                                     .GetUninstantiatedModuleInfoByPath(downloadData.ModuleSpecFile)
                                     .FileModuleLiteral
                                     .InstantiateFileModuleLiteral(moduleRegistry, QualifierValue.CreateEmpty(m_context.QualifierTable));

                // Evaluate all values of the module
                using (var contextTree = new ContextTree(
                           m_frontEndHost,
                           m_context,
                           m_logger,
                           m_evaluationStatistics,
                           new QualifierValueCache(),
                           isBeingDebugged: false,
                           decorator: null,
                           moduleLiteral,
                           new EvaluatorConfiguration(trackMethodInvocations: false, cycleDetectorStartupDelay: TimeSpanUtilities.MillisecondsToTimeSpan(10)),
                           scheduler,
                           FileType.Project))
                {
                    var moduleTracker = VisitedModuleTracker.Create(isDebug: false);
                    var success       = await moduleLiteral.EvaluateAllAsync(contextTree.RootContext, moduleTracker, ModuleEvaluationMode.None);

                    return(success);
                }
            }
            finally
            {
                m_evaluationSemaphore.Release();
            }
        }
        /// <inheritdoc />
        protected override EvaluationResult DoEval(Context context, ModuleLiteral env, EvaluationStackFrame frame)
        {
            var moduleCandidate = TargetExpression.Eval(context, env, frame);

            if (moduleCandidate.IsErrorValue || moduleCandidate.IsUndefined)
            {
                return(moduleCandidate);
            }

            // Qualifier type coercion could happen on both namespaces and files when importFrom is used.
            var module = moduleCandidate.Value as ModuleLiteral;

            // Moving Assert into the if block to avoid relatively expensive message computation for non-error case.
            if (module == null)
            {
                Contract.Assert(
                    false,
                    I($"TargetExpression '{TargetExpression.ToDisplayString(context)}' should produce 'ModuleLiteral' but produced '{moduleCandidate.Value.GetType()}'"));
            }

            var pathTable = context.FrontEndContext.PathTable;

            // TODO: Consider if it is possible to use QualifierUtilities.CoerceQualifierValue instead.
            QualifierValue oldQualifierValue = module.Qualifier;

            if (
                !oldQualifierValue.TryCoerce(
                    TargetQualifierSpaceId,
                    context.FrontEndContext.QualifierTable,
                    context.QualifierValueCache,
                    pathTable,
                    context.FrontEndContext.StringTable,
                    context.FrontEndContext.LoggingContext,
                    out QualifierValue coercedQualifier,
                    Location,
                    ShouldUseDefaultsOnCoercion,
                    context.LastActiveUsedPath))
            {
                context.Errors.ReportQualifierCannotBeCoarcedToQualifierSpaceWithProvenance(
                    oldQualifierValue.QualifierId,
                    TargetQualifierSpaceId,
                    ReferencedLocation.AsLoggingLocation(),
                    Location.AsLoggingLocation(env, context));

                return(EvaluationResult.Error);
            }

            return(EvaluationResult.Create(module.Instantiate(context.ModuleRegistry, coercedQualifier)));
        }
Пример #6
0
        private async Task <bool> DoTryEvaluateModuleAsync(IEvaluationScheduler scheduler, ModuleDefinition module, QualifierId qualifierId)
        {
            var qualifier = QualifierValue.Create(qualifierId, QualifierValueCache, Context.QualifierTable, Context.StringTable);

            // We don't want to evaluate the transitive closure of the import/export relationship, just the package.
            var evalJobs = module.Specs.Select(
                spec => EvaluateAsync(scheduler, spec, qualifier, asPackageEvaluation: false));

            var allTasks = await Task.WhenAll(evalJobs);

            var result = allTasks.All(t => t.Success);

            if (m_evaluationDecorator != null)
            {
                foreach (var evaluationResult in allTasks)
                {
                    m_evaluationResults.Enqueue(evaluationResult);
                }
            }

            return(result);
        }
Пример #7
0
        /// <inheritdoc />
        protected override EvaluationResult DoEval(Context context, ModuleLiteral env, EvaluationStackFrame frame)
        {
            // There is some code duplication between this type and the CoerceQualifierTypeExpression.
            // But there is not clear how to reuse this because steps are 'slightly' different.
            var moduleCandidate = ModuleReference.Eval(context, env, frame);

            if (moduleCandidate.IsErrorValue || moduleCandidate.IsUndefined)
            {
                return(moduleCandidate);
            }

            // The type checker should make sure that 'this expression' evaluates to a module literal.
            var module = moduleCandidate.Value as ModuleLiteral;

            Contract.Assert(
                module != null,
                I($"The left hand-side of a withQualifier expression should evaluates to 'TypeOrNamespaceModuleLiteral' but got '{moduleCandidate.Value.GetType()}'"));

            Contract.Assert(module.CurrentFileModule != null, "module.CurrentFileModule != null");

            // QualifierExpression can be an object literal or anything that ended up as an object literal.
            EvaluationResult objectQualifier;

            using (var emptyFrame = EvaluationStackFrame.Empty())
            {
                objectQualifier = QualifierExpression.Eval(context, env, emptyFrame);
            }

            if (objectQualifier.IsErrorValue)
            {
                // Error has been reported.
                return(EvaluationResult.Error);
            }

            var qualifierLiteral = objectQualifier.Value as ObjectLiteral;

            Contract.Assert(
                qualifierLiteral != null,
                I($"The right hand-side of a withQualifier expression should evaluates to 'ObjectLiteral' but got '{objectQualifier.Value.GetType()}'"));

            if (!QualifierValue.TryCreate(context, env, qualifierLiteral, out QualifierValue qualifierValue, qualifierLiteral.Location))
            {
                // Error has been reported.
                return(EvaluationResult.Error);
            }

            // Coercing qualifier with a given value
            if (
                !QualifierUtilities.CoerceQualifierValueForV2(
                    context,
                    qualifierValue,
                    SourceQualifierSpaceId,
                    TargetQualifierSpaceId,
                    referencingLocation: Location.AsUniversalLocation(env, context),
                    referencedLocation: module.CurrentFileModule.Location.AsUniversalLocation(module.CurrentFileModule, context),
                    coercedQualifierValue: out QualifierValue coercedQualifierValue))
            {
                // Error has been reported
                return(EvaluationResult.Error);
            }

            var result = module.Instantiate(context.ModuleRegistry, coercedQualifierValue);

            return(EvaluationResult.Create(result));
        }
Пример #8
0
 protected FileModuleLiteral InstantiateModule(FileModuleLiteral module, QualifierValue qualifier)
 {
     return(module.InstantiateFileModuleLiteral(FrontEndHost.ModuleRegistry, qualifier));
 }
Пример #9
0
        /// <summary>
        /// Evaluates a single package, and all projects that the package owns.
        /// </summary>
        private IReadOnlyList <Task <EvaluationResult> > EvaluatePackage(IEvaluationScheduler scheduler, Package package, QualifierValue qualifier)
        {
            Contract.Requires(package != null);
            Contract.Requires(qualifier != null);

            var projectsToEvaluate            = GetProjectsOfPackage(package);
            var shouldEvaluateLocalTransitive = ShouldEvaluateLocalTransitivePackage(package);

            // Note that, if package does not explicitly specifies the projects that it owns, then
            // we only evaluate the package's main file, and rely on the import/export relation to evaluate all
            // specs in the package. Another alternative is to glob all projects in the package's cone, and
            // evaluate those projects as well. Globbing involves IO, and can be expensive in a spinning disk.
            // For a consideration, WDG may only have one package, and may not specifiy all projects that the package
            // owns. Globbing the entire WDG tree will be very costly.
            return(projectsToEvaluate.Select(project => EvaluateAsync(scheduler, project, qualifier, asPackageEvaluation: shouldEvaluateLocalTransitive)).ToList());
        }
Пример #10
0
        /// <summary>
        /// Evaluates a file given the file path and a qualifier.
        /// </summary>
        /// <remarks>
        /// If the evaluation is part of package evaluation, then all files in the transitive closure of
        /// local import/export relation will be evaluated as well.
        /// </remarks>
        private async Task <EvaluationResult> EvaluateAsync(IEvaluationScheduler scheduler, AbsolutePath fullPath, QualifierValue qualifier, bool asPackageEvaluation)
        {
            Contract.Requires(fullPath.IsValid);
            Contract.Requires(qualifier != null);

            // Get an uninstantiated module.
            if (!((ModuleRegistry)FrontEndHost.ModuleRegistry).TryGetUninstantiatedModuleInfoByPath(fullPath, out UninstantiatedModuleInfo moduleInfo))
            {
                Logger.ReportSourceResolverFailEvaluateUnregisteredFileModule(Context.LoggingContext, Name, fullPath.ToString(Context.PathTable));
                return(CreateResult(false));
            }

            // If this spec belongs to a V1 module, then coercion happens at this point, since in V1 the qualifier space is always defined at the file level
            // and we want an explicit failure if coercion fails, to keep V1 modules back compat
            // Otherwise, we don't coerce, since coercion will happen on a namespace level in FileModuleLiteral.EvaluateAllNamedValues
            if (!FrontEndHost.SpecBelongsToImplicitSemanticsModule(fullPath))
            {
                // Coerce qualifier.
                if (!qualifier.TryCoerce(
                        moduleInfo.QualifierSpaceId,
                        Context.QualifierTable,
                        QualifierValueCache,
                        Context.PathTable,
                        Context.StringTable,
                        Context.LoggingContext,
                        out QualifierValue coercedQualifier,
                        default(LineInfo),
                        FrontEndHost.ShouldUseDefaultsOnCoercion(moduleInfo.ModuleLiteral.Path),
                        fullPath))
                {
                    string qualifierName  = Context.QualifierTable.GetQualifier(qualifier.QualifierId).ToDisplayString(Context.StringTable);
                    string qualifierSpace =
                        Context.QualifierTable.GetQualifierSpace(moduleInfo.QualifierSpaceId).ToDisplayString(Context.StringTable);

                    Logger.ReportQualifierCannotBeCoarcedToQualifierSpace(
                        Context.LoggingContext,
                        new Location
                    {
                        // Ideally the referencing location is used for this error, but that is a big replumbing effort.
                        // Task 615531
                        File = fullPath.ToString(Context.PathTable),
                    },
                        qualifierName,
                        qualifierSpace);
                    return(CreateResult(false));
                }

                qualifier = coercedQualifier;
            }

            // Instantiate module with the coerced qualifier.
            var module = InstantiateModule(moduleInfo.FileModuleLiteral, qualifier);

            // Create an evaluation context tree and root context.
            using (var contextTree = CreateContext(module, scheduler, m_evaluationDecorator, CreateEvaluatorConfiguration(), FileType.Project))
                using (FrontEndStatistics.SpecEvaluation.Start(fullPath.ToString(Context.PathTable)))
                {
                    var context = contextTree.RootContext;

                    // Evaluate module.
                    var moduleTracker = VisitedModuleTracker.Create(IsBeingDebugged);
                    var mode          = asPackageEvaluation ? ModuleEvaluationMode.LocalImportExportTransitive : ModuleEvaluationMode.None;
                    var success       = await module.EvaluateAllAsync(context, moduleTracker, mode);

                    return(CreateResult(success, moduleTracker));
                }
        }
Пример #11
0
 /// <summary>
 /// Instantiate current module literal.
 /// </summary>
 /// <remarks>
 /// TODO: Current instantiation logic is not very DScript V2 friendly.
 /// Even to get a namespace, the whole file is intstantiated.
 /// This needs to be addressed.
 /// </remarks>
 public ModuleLiteral Instantiate(ModuleRegistry moduleRegistry, QualifierValue qualifier)
 {
     return(ModuleLiteral.Instantiate(moduleRegistry, qualifier));
 }
Пример #12
0
 protected FileModuleLiteral InstantiateModule(FileModuleLiteral module, QualifierValue qualifier)
 {
     return(module.InstantiateFileModuleLiteral(SharedModuleRegistry, qualifier));
 }
Пример #13
0
        /// <inheritdoc />
        protected override EvaluationResult DoEval(Context context, ModuleLiteral env, EvaluationStackFrame frame)
        {
            // There is some code duplication between this type and the CoerceQualifierTypeExpression.
            // But there is not clear how to reuse this because steps are 'slightly' different.
            var moduleCandidate = ModuleReference.Eval(context, env, frame);

            if (moduleCandidate.IsErrorValue || moduleCandidate.IsUndefined)
            {
                return(moduleCandidate);
            }

            // The type checker should make sure that 'this expression' evaluates to a module literal.
            var module = moduleCandidate.Value as ModuleLiteral;

            Contract.Assert(
                module != null,
                I($"The left hand-side of a withQualifier expression should evaluates to 'TypeOrNamespaceModuleLiteral' but got '{moduleCandidate.Value.GetType()}'"));

            Contract.Assert(module.CurrentFileModule != null, "module.CurrentFileModule != null");
            var currentQualifier = env.CurrentFileModule.Qualifier.Qualifier;

            // QualifierExpression can be an object literal or anything that ended up as an object literal.
            EvaluationResult objectQualifier;

            using (var emptyFrame = EvaluationStackFrame.Empty())
            {
                objectQualifier = QualifierExpression.Eval(context, env, emptyFrame);
            }

            if (objectQualifier.IsErrorValue)
            {
                // Error has been reported.
                return(EvaluationResult.Error);
            }

            var requestedQualifier = objectQualifier.Value as ObjectLiteral;

            Contract.Assert(
                requestedQualifier != null,
                I($"The right hand-side of a withQualifier expression should evaluates to 'ObjectLiteral' but got '{objectQualifier.Value.GetType()}'"));

            // TODO: This can be made more efficient by talking with the qualifier table directly
            // and maintaining a global map of qualifier id to object literal rather than have many copies of
            // object literal floating around, but that would be more changes than warranted at the moment
            // since withqualifier is not used that heavily at the moment, when this starts showing up on profiles
            // we should consider improving the logic here.
            var qualifierBindings = new Dictionary <StringId, Binding>();

            foreach (var member in currentQualifier.Members)
            {
                qualifierBindings[member.Key] = new Binding(member.Key, member.Value, requestedQualifier.Location);
            }

            foreach (var member in requestedQualifier.Members)
            {
                if (member.Value.IsUndefined)
                {
                    // setting a value to undefined implies explicitly removing they qualifier key.
                    qualifierBindings.Remove(member.Key);
                }
                else
                {
                    qualifierBindings[member.Key] = new Binding(member.Key, member.Value, requestedQualifier.Location);
                }
            }
            var qualifierToUse = ObjectLiteral.Create(qualifierBindings.Values.ToArray());


            if (!QualifierValue.TryCreate(context, env, qualifierToUse, out QualifierValue qualifierValue, requestedQualifier.Location))
            {
                // Error has been reported.
                return(EvaluationResult.Error);
            }

            // Coercing qualifier with a given value
            if (
                !QualifierUtilities.CoerceQualifierValueForV2(
                    context,
                    qualifierValue,
                    SourceQualifierSpaceId,
                    TargetQualifierSpaceId,
                    referencingLocation: Location.AsUniversalLocation(env, context),
                    referencedLocation: module.CurrentFileModule.Location.AsUniversalLocation(module.CurrentFileModule, context),
                    coercedQualifierValue: out QualifierValue coercedQualifierValue))
            {
                // Error has been reported
                return(EvaluationResult.Error);
            }

            var result = module.Instantiate(context.ModuleRegistry, coercedQualifierValue);

            return(EvaluationResult.Create(result));
        }