示例#1
0
        /// <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));
        }
示例#2
0
        /// <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));
        }
示例#3
0
 /// <nodoc />
 public void Track(ModuleLiteral module, ImmutableContextBase context)
 {
     if (m_trackingKind == TrackingKind.TrackEverything)
     {
         VisitedModules.TryAdd(module, context);
     }
 }
示例#4
0
        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, '`');
        }
示例#5
0
        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);
        }
示例#6
0
        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, '`');
        }
示例#7
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);
        }
示例#8
0
        /// <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}'"));
            }
        }
示例#9
0
        private static void WriteOrderedSet(ScriptWriter writer, ImmutableContextBase context, object value)
        {
            var set = (OrderedSet)value;

            writer.AppendItems(set, "<Set>[", "]", ",",
                               item => WriteObject(writer, context, item.Value));
        }
示例#10
0
        private static void WriteArrayLiteral(ScriptWriter writer, ImmutableContextBase context, object value)
        {
            var arrayLiteral = (ArrayLiteral)value;

            writer.AppendItems(arrayLiteral.Values, "[", "]", ",",
                               item => WriteObject(writer, context, item.Value));
        }
示例#11
0
        /// <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));
        }
示例#12
0
        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, '`');
        }
示例#13
0
        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, '`');
        }
示例#14
0
        /// <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));
        }
示例#15
0
        /// <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));
        }
示例#16
0
        /// <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);
        }
示例#17
0
        /// <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));
        }
示例#18
0
        private DataProcessor(ImmutableContextBase context, ObjectPool <PipDataBuilder> pipDataBuilderPool)
        {
            Contract.Requires(context != null);
            Contract.Requires(pipDataBuilderPool != null);

            m_context            = context;
            m_pipDataBuilderPool = pipDataBuilderPool;
        }
示例#19
0
        /// <nodoc />
        public static string ToDisplayString(this AbsolutePath path, ImmutableContextBase context)
        {
            if (!path.IsValid)
            {
                return("undefined");
            }

            return(path.ToString(context.FrontEndContext.PathTable));
        }
示例#20
0
        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));
        }
示例#21
0
        /// <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))));
        }
示例#22
0
        /// <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));
        }
示例#23
0
 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));
     }
 }
示例#24
0
        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));
            }
        }
示例#25
0
        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);
            });
        }
示例#26
0
        /// <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));
        }
示例#27
0
        /// <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)));
        }
示例#28
0
        /// <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));
        }
示例#29
0
        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("}");
            });
        }
示例#30
0
 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);
     }
 }