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)); }
/// <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(); }
/// <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); }
/// <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))); }
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); }
/// <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)); }
protected FileModuleLiteral InstantiateModule(FileModuleLiteral module, QualifierValue qualifier) { return(module.InstantiateFileModuleLiteral(FrontEndHost.ModuleRegistry, qualifier)); }
/// <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()); }
/// <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)); } }
/// <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)); }
protected FileModuleLiteral InstantiateModule(FileModuleLiteral module, QualifierValue qualifier) { return(module.InstantiateFileModuleLiteral(SharedModuleRegistry, qualifier)); }
/// <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)); }