/// <summary> /// Evaluates this thunk in a new named context /// </summary> /// <remarks> /// V1-specific. Still used to evaluate configuration-related files in V2 (and for the whole V1 legacy evaluation). /// </remarks> public EvaluationResult LegacyEvaluateWithNewNamedContext(ImmutableContextBase context, ModuleLiteral module, FullSymbol contextName, LineInfo location) { // There is no captured template value in V1 var factory = MutableContextFactory.Create(this, contextName, module, templateValue: null, location: location); return(EvaluateWithNewNamedContextAndTemplate(context, ref factory)); }
/// <summary> /// Evaluates this thunk in a new named context /// </summary> /// <remarks> /// V1-specific. Still used to evaluate configuration-related files in V2 (and for the whole V1 legacy evaluation). /// </remarks> public EvaluationResult LegacyEvaluateWithNewNamedContext(ImmutableContextBase context, ModuleLiteral module, FullSymbol contextName, LineInfo location, bool forceWaitForResult = false) { // There is no captured template value in V1 var factory = new MutableContextFactory(this, contextName, module, templateValue: null, location: location, forceWaitForResult: forceWaitForResult); return(EvaluateWithNewNamedContextAndTemplate(context, ref factory)); }
/// <nodoc /> public void Track(ModuleLiteral module, ImmutableContextBase context) { if (m_trackingKind == TrackingKind.TrackEverything) { VisitedModules.TryAdd(module, context); } }
private static void WriteStaticDirectory(ScriptWriter writer, ImmutableContextBase context, object value) { var directory = (StaticDirectory)value; writer.AppendToken(Constants.Names.DirectoryInterpolationFactory.ToString()); writer.AppendQuotedString(directory.Path.ToString(context.PathTable, PathFormat.Script), true, '`'); }
internal bool TryResolveExtendedName(ImmutableContextBase context, FullSymbol enclosingName, FullSymbol requestedName, out ModuleBinding result) { // Semantically nested namespaces forms hierarchical structure, when nested namespace is stored in the outer namespace. // For performance reasons, file module stores all names in one big map with combined keys. // This means that when looking for A.B we should look at the current scope for A, then need to combine A and B // and look for A.B in the file module. // This means that extended (or partial) names are only allowed if the enclosing name is valid. // In this case we will combine requested name with the enclosing one and look in the current file module. result = null; if (!enclosingName.IsValid) { return(false); } if (m_partialSymbolsCache.Value.TryGetValue(requestedName, out result)) { return(true); } var extendedFullName = enclosingName.Combine(context.FrontEndContext.SymbolTable, requestedName); // Now trying to resolve extended name in the current file. result = GetNamespaceBinding(context, extendedFullName, recurs: false); // If resolution was successful, saving it in the cache. if (result != null) { m_partialSymbolsCache.Value.GetOrAdd(requestedName, result); return(true); } return(false); }
private static void WriteRelativePath(ScriptWriter writer, ImmutableContextBase context, object value) { var relativePath = (RelativePath)value; writer.AppendToken(Constants.Names.RelativePathInterpolationFactory.ToString()); writer.AppendQuotedString(relativePath.ToString(context.StringTable, PathFormat.Script), true, '`'); }
/// <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 /> public static void WriteObject(ScriptWriter writer, ImmutableContextBase context, object value) { if (value == null) { writer.AppendToken("undefined"); return; } if (value is EvaluationResult result) { WriteObject(writer, context, result.Value); return; } // One of the types in the map is generic (ObjectLiteralLight<>). // To get a match from the dictionary we need to get open generic type // from already constructed type that would be provided by value.GetType(). var type = value.GetType(); if (type.IsGenericType) { type = type.GetGenericTypeDefinition(); } if (s_toStringMap.TryGetValue(type, out WriteObjectFunction writeFunction)) { writeFunction(writer, context, value); } else { writer.AppendLine(I($"Don't know how to get a string representation of '{type}'")); } }
private static void WriteOrderedSet(ScriptWriter writer, ImmutableContextBase context, object value) { var set = (OrderedSet)value; writer.AppendItems(set, "<Set>[", "]", ",", item => WriteObject(writer, context, item.Value)); }
private static void WriteArrayLiteral(ScriptWriter writer, ImmutableContextBase context, object value) { var arrayLiteral = (ArrayLiteral)value; writer.AppendItems(arrayLiteral.Values, "[", "]", ",", item => WriteObject(writer, context, item.Value)); }
/// <summary> /// Implements path interpolation /// </summary> internal static EvaluationResult Interpolate(ImmutableContextBase context, EvaluationResult root, IReadOnlyList <EvaluationResult> pathFragments) { var pathTable = context.FrontEndContext.PathTable; var strTable = context.FrontEndContext.StringTable; // Root must have a characteristic as an absolute path. var result = Converter.ExpectPath(root, strict: false, context: new ConversionContext(pos: 1)); // Non-root expressions must be path fragments for (int i = 0; i < pathFragments.Count; i++) { Converter.ExpectPathFragment( strTable, pathFragments[i], out PathAtom pathAtom, out RelativePath relativePath, context: new ConversionContext(objectCtx: pathFragments, pos: i)); if (pathAtom.IsValid) { result = result.Combine(pathTable, pathAtom); } else if (relativePath.IsValid) { result = result.Combine(pathTable, relativePath); } } return(EvaluationResult.Create(result)); }
private static void WriteFileArtifact(ScriptWriter writer, ImmutableContextBase context, object value) { var file = (FileArtifact)value; writer.AppendToken(Constants.Names.FileInterpolationFactory.ToString()); writer.AppendQuotedString(file.Path.ToString(context.PathTable, PathFormat.Script), true, '`'); }
private static void WritePathAtom(ScriptWriter writer, ImmutableContextBase context, object value) { var atom = (PathAtom)value; writer.AppendToken(Constants.Names.PathAtomInterpolationFactory.ToString()); writer.AppendQuotedString(atom.ToString(context.StringTable), false, '`'); }
/// <summary> /// Implements path interpolation /// </summary> public static EvaluationResult CreateFromAbsolutePathString(ImmutableContextBase context, ModuleLiteral env, EvaluationStackFrame args) { var absolutePath = Args.AsString(args, 0); var result = AbsolutePath.TryCreate(context.PathTable, absolutePath, out var resultPath, out var characterWithError); if (result == AbsolutePath.ParseResult.Success) { return(EvaluationResult.Create(resultPath)); } string message = string.Format(CultureInfo.CurrentCulture, $"Invalid Absolute path at character: {characterWithError}. "); switch (result) { case AbsolutePath.ParseResult.DevicePathsNotSupported: message += "Device Paths are not supported."; break; case AbsolutePath.ParseResult.FailureDueToInvalidCharacter: message += "Character is not a valid path character."; break; case AbsolutePath.ParseResult.UnknownPathStyle: message += "This is not an absolute path."; break; default: throw Contract.AssertFailure("Unexpected path tryparse result type"); } throw new InvalidPathOperationException(message, new ErrorContext(pos: 1)); }
/// <summary> /// Combines multiple paths: 'receiver' and 'arg as AbsolutePath[]' /// </summary> protected static EvaluationResult CombinePaths(ImmutableContextBase context, AbsolutePath receiver, EvaluationResult arg, EvaluationStackFrame captures) { Contract.Requires(context != null); Contract.Requires(receiver.IsValid); Contract.Requires(captures != null); var pathTable = context.FrontEndContext.PathTable; var stringTable = context.FrontEndContext.StringTable; var argArray = Converter.ExpectArrayLiteral(arg, new ConversionContext(pos: 1)); AbsolutePath currentPath = receiver; for (int i = 0; i < argArray.Length; i++) { Converter.ExpectPathFragment( stringTable, argArray[i], out PathAtom pathAtom, out RelativePath relativePath, new ConversionContext(pos: i + 1, objectCtx: argArray)); currentPath = pathAtom.IsValid ? currentPath.Combine(pathTable, pathAtom) : currentPath.Combine(pathTable, relativePath); } return(EvaluationResult.Create(currentPath)); }
/// <summary> /// Gets module binding based on module full symbol name. /// </summary> protected internal ModuleBinding GetNamespaceBinding(ImmutableContextBase context, FullSymbol fullName, bool recurs) { // Namespace resolution performs in 3 steps: // 1. Trying resolve namespace locally using local namespace table // 2. Trying resolve by looking into imported namespaces // 3. Trying resolve by creating partial name and looking in the file module. ModuleLiteral current = this; while (current != null) { ModuleBinding binding = null; // Trying to resolve in the local table if (current.m_nsBindings?.TryGetValue(fullName, out binding) == true) { return(binding); } // Local namespace table doesn't have a requested name. Looking in forwared... // The same logic could be achieved using virtual dispatch, but this implementation // keep all the logic in one place. if (current is FileModuleLiteral currentAsFile) { if (currentAsFile.TryResolveExtendedName(context, Name, fullName, out binding)) { return(binding); } } current = recurs ? current.OuterScope : null; } return(null); }
/// <summary> /// Implements path interpolation /// </summary> public static EvaluationResult Interpolate(ImmutableContextBase context, ModuleLiteral env, EvaluationStackFrame args) { // TODO: Path.interpolate(x, y, z) is similar to x.combinePaths(y, z). The latter can be slightly more efficient because no look-up for "Path" identifier. Args.CheckArgumentIndex(args, 1); var rest = Args.AsArrayLiteral(args, 1); return(Interpolate(context, args[0], rest.Values)); }
private DataProcessor(ImmutableContextBase context, ObjectPool <PipDataBuilder> pipDataBuilderPool) { Contract.Requires(context != null); Contract.Requires(pipDataBuilderPool != null); m_context = context; m_pipDataBuilderPool = pipDataBuilderPool; }
/// <nodoc /> public static string ToDisplayString(this AbsolutePath path, ImmutableContextBase context) { if (!path.IsValid) { return("undefined"); } return(path.ToString(context.FrontEndContext.PathTable)); }
private EvaluationResult GetOrEvalFieldBindingThunk(ImmutableContextBase context, SymbolAtom name, ModuleBinding binding, Thunk thunk) { // Keep this call in a separate method to avoid always creating a closure object on the heap in the caller // If the thunk hasn't been evaluated yet for the current qualifier, then its evaluation gets kicked off in a newly allocated mutable named context. // We must not mutate the context at hand directly, as there might be other concurrent child contexts alive. var contextName = GetFullyQualifiedBindingName(context.FrontEndContext.SymbolTable, this, name); return(thunk.LegacyEvaluateWithNewNamedContext(context, this, contextName, binding.Location)); }
/// <summary> /// Returns specified number raised to specified power. /// Performs required conversion to numbers. /// </summary> public static EvaluationResult Power(ImmutableContextBase context, int left, int right, Location location) { if (right < 0) { context.Logger.ReportArgumentForPowerOperationShouldNotBeNegative(context.LoggingContext, location); return(EvaluationResult.Error); } return(EvaluationResult.Create(checked ((int)Math.Pow(left, right)))); }
/// <summary> /// Evaluates all. /// </summary> public Task <bool> EvaluateAllAsync(ImmutableContextBase context, VisitedModuleTracker moduleTracker, ModuleEvaluationMode mode = ModuleEvaluationMode.None) { if (mode == ModuleEvaluationMode.None) { moduleTracker.Track(this, context); return(EvaluateAllNamedValuesAsync(context)); } return(EvaluateAllTransitiveClosureAsync(context, mode, moduleTracker)); }
private EvaluationResult EvaluateWithNewNamedContextAndTemplate(ImmutableContextBase context, ref MutableContextFactory factory) { using (var frame = EvaluationStackFrame.Empty()) { return(Evaluate( context: context, env: factory.Module, args: frame, factory: ref factory)); } }
private void AddGetOrEvalFieldTasks(ImmutableContextBase context, List <Task <object> > list, ModuleLiteral origin) { Contract.Requires(origin.m_bindings != null); foreach (var binding in origin.m_bindings) { SymbolAtom name = binding.Key; ModuleBinding bindingValue = binding.Value; list.Add(RunGetOrEvalFieldAsync(context, origin, name, bindingValue)); } }
private static void WriteObjectLiteral(ScriptWriter writer, ImmutableContextBase context, object value) { var objLiteral = (ObjectLiteral)value; writer.AppendItems(objLiteral.Members, "{", "}", ",", member => { writer.AppendToken(member.Key.ToString(context.StringTable)); writer.AppendToken(": "); WriteObject(writer, context, member.Value.Value); }); }
/// <summary> /// Gets module or namespace based on module id. /// </summary> public EvaluationResult GetNamespace(ImmutableContextBase context, FullSymbol fullName, bool recurs, ModuleLiteral origin, LineInfo location) { ModuleBinding binding = GetNamespaceBinding(context, fullName, recurs); if (binding == null) { context.Errors.ReportMissingNamespace(origin ?? this, fullName, this, location); return(EvaluationResult.Error); } return(EvaluationResult.Create(binding.Body)); }
/// <summary> /// Combines two paths: 'receiver' and 'arg as AbsolutePath' /// </summary> protected static EvaluationResult Combine(ImmutableContextBase context, AbsolutePath receiver, EvaluationResult arg, EvaluationStackFrame captures) { Contract.Requires(context != null); Contract.Requires(receiver.IsValid); Contract.Requires(captures != null); var stringTable = context.FrontEndContext.StringTable; var pathTable = context.FrontEndContext.PathTable; Converter.ExpectPathFragment(stringTable, arg, out PathAtom pathAtom, out RelativePath relativePath, context: new ConversionContext(pos: 1)); return(EvaluationResult.Create(pathAtom.IsValid ? receiver.Combine(pathTable, pathAtom) : receiver.Combine(pathTable, relativePath))); }
/// <nodoc /> public static string ToDisplayString(this QualifierSpaceId qualifierSpaceId, ImmutableContextBase context) { Contract.Requires(context != null); if (!qualifierSpaceId.IsValid) { return("Invalid"); } QualifierSpace qualifierSpace = context.FrontEndContext.QualifierTable.GetQualifierSpace(qualifierSpaceId); return(qualifierSpace.ToDisplayString(context.FrontEndContext.StringTable)); }
private static void WriteOrderedMap(ScriptWriter writer, ImmutableContextBase context, object value) { var objLiteralN = (OrderedMap)value; writer.AppendItems(objLiteralN, "<Map>[", "]", ",", item => { writer.AppendToken("{ key: "); WriteObject(writer, context, item.Key.Value); writer.AppendToken(", value: "); WriteObject(writer, context, item.Value.Value); writer.AppendToken("}"); }); }
private object GetOrEvalField(ImmutableContextBase context, ModuleLiteral origin, SymbolAtom name, ModuleBinding bindingValue) { // This method may be invoked concurrently on the same context. Thus we may not mutate the context at hand, but must create a local mutable child context. using (var localMutableContext = context.CreateWithModule(this)) { var result = origin.GetOrEvalField( localMutableContext, name, recurs: true, origin: origin, location: bindingValue.Location); Contract.Assert(!localMutableContext.HasChildren); // just before the newly created context get disposed, we want to assert that all of its child contexts have already been disposed return(result.Value); } }