Example #1
0
        private static EvaluationResult Sum(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            // The checker should make sure that the function takes numbers.
            var values = Args.AsArrayLiteral(args, 0).Values.Select(v => (int)v.Value).ToList();

            return(DoMath(() => checked (values.Sum())));
        }
Example #2
0
        private static EvaluationResult ReadGraphFragment(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            var file        = Args.AsFile(args, 0);
            var deps        = Args.AsArrayLiteral(args, 1).Values.Select(v => (AbsolutePath)v.Value).ToArray();
            var description = Args.AsStringOptional(args, 2) ?? file.Path.ToString(context.PathTable);

            if (!file.IsSourceFile)
            {
                // Do not read output file.
                throw new FileOperationException(
                          new Exception(
                              I($"Failed adding pip graph fragment file '{file.Path.ToString(context.PathTable)}' because the file is not a source file")));
            }

            if (!context.FrontEndContext.FileSystem.Exists(file.Path))
            {
                throw new FileOperationException(new FileNotFoundException(I($"File '{file.Path.ToString(context.PathTable)}' does not exist")));
            }

            // Record the file, so that its content is tracked by input tracker.
            context.FrontEndHost.Engine.RecordFrontEndFile(file.Path, "DScript");

            int id = Interlocked.Increment(ref s_uniqueFragmentId);
            var readFragmentResult = context.FrontEndHost.PipGraphFragmentManager.AddFragmentFileToGraph(file, description, deps);

            if (!readFragmentResult)
            {
                return(EvaluationResult.Error);
            }

            return(EvaluationResult.Create(file.Path));
        }
Example #3
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));
        }
        private static EvaluationResult WriteFileHelper(Context context, ModuleLiteral env, EvaluationStackFrame args, WriteFileMode mode)
        {
            var path        = Args.AsPath(args, 0, false);
            var tags        = Args.AsStringArrayOptional(args, 2);
            var description = Args.AsStringOptional(args, 3);

            PipData pipData;

            switch (mode)
            {
            case WriteFileMode.WriteFile:
                var fileContent = Args.AsIs(args, 1);
                // WriteFile has a separator argument with default newline
                var separator = Args.AsStringOptional(args, 3) ?? Environment.NewLine;
                description = Args.AsStringOptional(args, 4);

                pipData = CreatePipDataForWriteFile(context, fileContent, separator);
                break;

            case WriteFileMode.WriteData:
                var data = Args.AsIs(args, 1);
                pipData = DataProcessor.ProcessData(context, context.FrontEndContext.PipDataBuilderPool, EvaluationResult.Create(data), new ConversionContext(pos: 1));
                break;

            case WriteFileMode.WriteAllLines:
                var lines   = Args.AsArrayLiteral(args, 1);
                var entry   = context.TopStack;
                var newData = ObjectLiteral.Create(
                    new List <Binding>
                {
                    new Binding(context.Names.DataSeparator, Environment.NewLine, entry.InvocationLocation),
                    new Binding(context.Names.DataContents, lines, entry.InvocationLocation),
                },
                    lines.Location,
                    entry.Path);

                pipData = DataProcessor.ProcessData(context, context.FrontEndContext.PipDataBuilderPool, EvaluationResult.Create(newData), new ConversionContext(pos: 1));
                break;

            case WriteFileMode.WriteAllText:
                var text = Args.AsString(args, 1);
                pipData = DataProcessor.ProcessData(context, context.FrontEndContext.PipDataBuilderPool, EvaluationResult.Create(text), new ConversionContext(pos: 1));
                break;

            default:
                throw Contract.AssertFailure("Unknown WriteFileMode.");
            }

            FileArtifact result;

            if (!context.GetPipConstructionHelper().TryWriteFile(path, pipData, WriteFileEncoding.Utf8, tags, description, out result))
            {
                // Error has been logged
                return(EvaluationResult.Error);
            }

            return(new EvaluationResult(result));
        }
Example #5
0
        /// <summary>
        ///     Implements string interpolation.
        /// </summary>
        private static EvaluationResult Interpolate(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            var firstArgument = ToStringConverter.ObjectToString(context, args[0]);

            var rest = Args.AsArrayLiteral(args, 1);

            return(EvaluationResult.Create(string.Concat(
                                               firstArgument,
                                               string.Join(string.Empty, rest.Values.Select(v => ToStringConverter.ObjectToString(context, v))))));
        }
        private EvaluationResult ComposeSharedOpaqueDirectories(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            AbsolutePath root;
            ArrayLiteral contents;
            SealDirectoryContentFilter?contentFilter;

            if (args.Length > 0 && args[0].Value is ObjectLiteral)
            {
                var obj       = Args.AsObjectLiteral(args, 0);
                var directory = Converter.ExtractDirectory(obj, m_sealRoot, allowUndefined: false);
                root     = directory.Path;
                contents = Converter.ExtractArrayLiteral(obj, m_sealDirectories, allowUndefined: false);
                var filterObj = Converter.ExtractObjectLiteral(obj, m_sealDirectoryContentFilter, allowUndefined: true);
                extractContentFilter(filterObj, out contentFilter);
            }
            else
            {
                root     = Args.AsPath(args, 0, false);
                contents = Args.AsArrayLiteral(args, 1);
                var filterObj = Args.AsObjectLiteralOptional(args, 2);
                extractContentFilter(filterObj, out contentFilter);
            }

            var directories = new DirectoryArtifact[contents.Length];

            for (int i = 0; i < contents.Length; ++i)
            {
                directories[i] = Converter.ExpectSharedOpaqueDirectory(contents[i], context: new ConversionContext(pos: i, objectCtx: contents)).Root;
            }

            if (!context.GetPipConstructionHelper().TryComposeSharedOpaqueDirectory(root, directories, contentFilter, description: null, tags: null, out var compositeSharedOpaque))
            {
                // Error should have been logged
                return(EvaluationResult.Error);
            }

            var result = new StaticDirectory(compositeSharedOpaque, SealDirectoryKind.SharedOpaque, s_emptySealContents.WithCompatibleComparer(OrdinalPathOnlyFileArtifactComparer.Instance));

            return(new EvaluationResult(result));

            void extractContentFilter(ObjectLiteral obj, out SealDirectoryContentFilter?filter)
            {
                filter = null;

                if (obj != null)
                {
                    var regex        = Converter.ExtractRegex(obj, m_sealDirectoryContentFilterRegex, allowUndefined: false);
                    var kindAsString = Converter.ExtractString(obj, m_sealDirectoryContentFilterKind, allowUndefined: false);

                    filter = new SealDirectoryContentFilter(
                        (SealDirectoryContentFilter.ContentFilterKind)Enum.Parse(typeof(SealDirectoryContentFilter.ContentFilterKind), kindAsString),
                        regex.ToString());
                }
            }
        }
Example #7
0
        private static EvaluationResult Min(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            // The checker should make sure that the function takes numbers.
            var values = Args.AsArrayLiteral(args, 0).Values.Select(v => (int)v.Value).ToList();

            if (values.Count == 0)
            {
                return(EvaluationResult.Undefined);
            }

            return(DoMath(() => values.Min()));
        }
        private EvaluationResult SealDirectoryHelper(Context context, ModuleLiteral env, EvaluationStackFrame args, SealDirectoryKind sealDirectoryKind)
        {
            AbsolutePath path;
            ArrayLiteral contents;

            string[] tags;
            string   description;
            bool     scrub;

            if (args.Length > 0 && args[0].Value is ObjectLiteral)
            {
                var obj       = Args.AsObjectLiteral(args, 0);
                var directory = Converter.ExtractDirectory(obj, m_sealRoot, allowUndefined: false);
                path        = directory.Path;
                contents    = Converter.ExtractArrayLiteral(obj, m_sealFiles, allowUndefined: false);
                tags        = Converter.ExtractStringArray(obj, m_sealTags, allowUndefined: true);
                description = Converter.ExtractString(obj, m_sealDescription, allowUndefined: true);
                scrub       = sealDirectoryKind.IsFull()
                    ? Converter.ExtractOptionalBoolean(obj, m_sealScrub) ?? false
                    : false;
            }
            else
            {
                path        = Args.AsPath(args, 0, false);
                contents    = Args.AsArrayLiteral(args, 1);
                tags        = Args.AsStringArrayOptional(args, 2);
                description = Args.AsStringOptional(args, 3);
                // Only do scrub for fully seal directory
                scrub = sealDirectoryKind.IsFull() ? Args.AsBoolOptional(args, 4) : false;
            }

            var fileContents = new FileArtifact[contents.Length];

            for (int i = 0; i < contents.Length; ++i)
            {
                fileContents[i] = Converter.ExpectFile(contents[i], strict: false, context: new ConversionContext(pos: i, objectCtx: contents));
            }

            var sortedFileContents = SortedReadOnlyArray <FileArtifact, OrdinalFileArtifactComparer> .CloneAndSort(fileContents, OrdinalFileArtifactComparer.Instance);

            DirectoryArtifact sealedDirectoryArtifact;

            if (!context.GetPipConstructionHelper().TrySealDirectory(path, sortedFileContents, sealDirectoryKind, tags, description, null, out sealedDirectoryArtifact, scrub))
            {
                // Error has been logged
                return(EvaluationResult.Error);
            }

            var result = new StaticDirectory(sealedDirectoryArtifact, sealDirectoryKind, sortedFileContents.WithCompatibleComparer(OrdinalPathOnlyFileArtifactComparer.Instance));

            return(new EvaluationResult(result));
        }
Example #9
0
        private static EvaluationResult DumpArgs(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            var cmdLineArgs = Args.AsArrayLiteral(args, 0);
            var pathTable   = context.FrontEndContext.PathTable;

            using (var processBuilder = ProcessBuilder.Create(pathTable, context.FrontEndContext.GetPipDataBuilder(), context.FrontEndHost.Configuration))
            {
                TransformerExecuteArgumentsProcessor.ProcessArguments(context, processBuilder, cmdLineArgs);

                var pipData = processBuilder.ArgumentsBuilder.ToPipData(" ", PipDataFragmentEscaping.NoEscaping);
                return(EvaluationResult.Create(pipData.ToString(pathTable)));
            }
        }
Example #10
0
        private static EvaluationResult FromCharCode(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            var codes = Args.AsArrayLiteral(args, 0);
            var chars = codes.Values.Select((elem, idx) =>
            {
                int code = Converter.ExpectNumber(elem, strict: true, context: new ConversionContext(objectCtx: codes, pos: idx));
                unchecked
                {
                    return((char)code);
                }
            }).ToArray();

            return(EvaluationResult.Create(new string(chars)));
        }
Example #11
0
        private EvaluationResult AddIf(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            var condition = Args.AsBool(args, 0);

            if (!condition)
            {
                // Return empty Array
                var entry = context.TopStack;
                return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(new EvaluationResult[0], entry.InvocationLocation, entry.Path)));
            }

            var items = Args.AsArrayLiteral(args, 1);

            return(EvaluationResult.Create(items));
        }
Example #12
0
        private static EvaluationResult FromPathAtoms(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            var arrayLit     = Args.AsArrayLiteral(args, 0);
            var arrayOfAtoms = new PathAtom[arrayLit.Length];

            for (int i = 0; i < arrayLit.Length; ++i)
            {
                arrayOfAtoms[i] = Converter.ExpectPathAtomFromStringOrPathAtom(
                    context.FrontEndContext.StringTable,
                    arrayLit[i],
                    new ConversionContext(pos: i, objectCtx: arrayLit));
            }

            return(EvaluationResult.Create(RelativePath.Create(arrayOfAtoms)));
        }
Example #13
0
        private EvaluationResult ExpectFailure(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            var closure         = Args.AsClosure(args, 0);
            var expectedResults = Args.AsArrayLiteral(args, 1);

            using (var frame = EvaluationStackFrame.Create(closure.Function, args.Frame))
            {
                var result = context.InvokeClosure(closure, frame);
                if (!result.IsErrorValue)
                {
                    Assert.True(false, "Expected the code under test to throw a failure, but none was returned.");
                }

                if (!m_getDiagnostics().Any(diagnostic => diagnostic.Level == EventLevel.Error))
                {
                    Assert.True(false, "Expected to see at least one reported error, but none encountered.");
                }

                for (int i = 0; i < expectedResults.Count; i++)
                {
                    if (expectedResults[i].Value is string expectedContent)
                    {
                        // String case
                        Assert.False(string.IsNullOrEmpty(expectedContent), "Empty strings are not supported as expected error messages");
                        ValidateExpectedMessageLogged(null, expectedContent);
                    }
                    else
                    {
                        // Object case
                        var obj = Converter.ExpectObjectLiteral(
                            expectedResults[i],
                            new ConversionContext(pos: i, objectCtx: expectedResults));

                        var code = Converter.ExtractInt(obj, m_testingExpectedMessageCode);
                        expectedContent = Converter.ExtractString(obj, m_testingExpectedMessageContent);

                        ValidateExpectedMessageLogged(code, expectedContent);
                    }
                }

                return(EvaluationResult.Undefined);
            }
        }
        private static EvaluationResult ReadGraphFragment(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            var file        = Args.AsFile(args, 0);
            var deps        = Args.AsArrayLiteral(args, 1).Values.Select(v => (int)v.Value).ToArray();
            var description = Args.AsStringOptional(args, 2) ?? file.Path.ToString(context.PathTable);

            if (!file.IsSourceFile)
            {
                // Do not read output file.
                throw new FileOperationException(
                          new Exception(
                              I($"Failed adding pip graph fragment file '{file.Path.ToString(context.PathTable)}' because the file is not a source file")));
            }

            Contract.Assert(context.FrontEndContext.FileSystem.Exists(file.Path), "Fragment file does not exist");
            int id = Interlocked.Increment(ref s_uniqueFragmentId);
            var readFragmentTask = context.FrontEndHost.PipGraphFragmentManager.AddFragmentFileToGraph(id, file, deps, description);

            return(EvaluationResult.Create(id));
        }
Example #15
0
        private static EvaluationResult StaticMerge(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            ObjectLiteral result = null;

            var arrayOfObjects = Args.AsArrayLiteral(args, 0);

            for (int i = 0; i < arrayOfObjects.Length; i++)
            {
                if (arrayOfObjects[i].IsUndefined)
                {
                    continue;
                }

                var arg = Converter.ExpectObjectLiteral(
                    arrayOfObjects[i],
                    new ConversionContext(pos: i, objectCtx: arrayOfObjects));
                if (result == null)
                {
                    result = arg;
                }
                else
                {
                    var merged = result.Merge(context, EvaluationStackFrame.UnsafeFrom(new EvaluationResult[0]), EvaluationResult.Create(arg));
                    // Merge can fail due to custom merge functions failing.
                    if (merged.IsErrorValue)
                    {
                        return(merged);
                    }

                    // Left and right are guaranteed to be objects so the result must be object.
                    result = (ObjectLiteral)merged.Value;
                }
            }

            if (result == null)
            {
                return(EvaluationResult.Undefined);
            }

            return(EvaluationResult.Create(result));
        }
Example #16
0
        /// <summary>
        /// Implements relative path interpolation
        /// </summary>
        private static EvaluationResult Interpolate(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            Args.CheckArgumentIndex(args, 1);

            var stringTable = context.FrontEndContext.StringTable;

            PathAtom pathAtom = Converter.ExpectPathAtomFromStringOrPathAtom(stringTable, args[0], new ConversionContext(pos: 1));
            var      rest     = Args.AsArrayLiteral(args, 1);

            for (int i = 0; i < rest.Length; i++)
            {
                pathAtom = pathAtom.Concat(
                    stringTable,
                    Converter.ExpectPathAtomFromStringOrPathAtom(
                        stringTable,
                        rest[i],
                        new ConversionContext(pos: i + 1, objectCtx: rest)));
            }

            return(EvaluationResult.Create(pathAtom));
        }
Example #17
0
        private static EvaluationResult Join(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            var separator      = Args.AsString(args, 0);
            var arrayOfStrings = Args.AsArrayLiteral(args, 1);

            using (var pooledInstance = Pools.StringBuilderPool.GetInstance())
            {
                var builder = pooledInstance.Instance;
                for (var i = 0; i < arrayOfStrings.Length; ++i)
                {
                    var s = Converter.ExpectString(
                        arrayOfStrings[i],
                        new ConversionContext(pos: i, objectCtx: arrayOfStrings));
                    builder.Append(s);

                    if (i < arrayOfStrings.Length - 1)
                    {
                        builder.Append(separator);
                    }
                }

                return(EvaluationResult.Create(builder.ToString()));
            }
        }
        private static EvaluationResult ComposeSharedOpaqueDirectories(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            AbsolutePath root        = Args.AsPath(args, 0, false);
            ArrayLiteral contents    = Args.AsArrayLiteral(args, 1);
            var          tags        = Args.AsStringArrayOptional(args, 2);
            var          description = Args.AsStringOptional(args, 3);

            var directories = new DirectoryArtifact[contents.Length];

            for (int i = 0; i < contents.Length; ++i)
            {
                directories[i] = Converter.ExpectSharedOpaqueDirectory(contents[i], context: new ConversionContext(pos: i, objectCtx: contents)).Root;
            }

            if (!context.GetPipConstructionHelper().TryComposeSharedOpaqueDirectory(root, directories, description, tags, out var compositeSharedOpaque))
            {
                // Error should have been logged
                return(EvaluationResult.Error);
            }

            var result = new StaticDirectory(compositeSharedOpaque, SealDirectoryKind.SharedOpaque, s_emptySealContents.WithCompatibleComparer(OrdinalPathOnlyFileArtifactComparer.Instance));

            return(new EvaluationResult(result));
        }
Example #19
0
        private EvaluationResult WriteFileHelper(Context context, ModuleLiteral env, EvaluationStackFrame args, WriteFileMode mode)
        {
            AbsolutePath path;

            string[] tags;
            string   description;
            PipData  pipData;

            if (args.Length > 0 && args[0].Value is ObjectLiteral)
            {
                var obj = Args.AsObjectLiteral(args, 0);
                path        = Converter.ExtractPath(obj, m_writeOutputPath, allowUndefined: false);
                tags        = Converter.ExtractStringArray(obj, m_writeTags, allowUndefined: true);
                description = Converter.ExtractString(obj, m_writeDescription, allowUndefined: true);
                switch (mode)
                {
                case WriteFileMode.WriteData:
                    var data = obj[m_writeContents];
                    pipData = ProcessData(context, data, new ConversionContext(pos: 1));
                    break;

                case WriteFileMode.WriteAllLines:
                    var lines   = Converter.ExtractArrayLiteral(obj, m_writeLines);
                    var entry   = context.TopStack;
                    var newData = ObjectLiteral.Create(
                        new List <Binding>
                    {
                        new Binding(m_dataSeparator, Environment.NewLine, entry.InvocationLocation),
                        new Binding(m_dataContents, lines, entry.InvocationLocation),
                    },
                        lines.Location,
                        entry.Path);

                    pipData = ProcessData(context, EvaluationResult.Create(newData), new ConversionContext(pos: 1));
                    break;

                case WriteFileMode.WriteAllText:
                    var text = Converter.ExtractString(obj, m_writeText);
                    pipData = ProcessData(context, EvaluationResult.Create(text), new ConversionContext(pos: 1));
                    break;

                default:
                    throw Contract.AssertFailure("Unknown WriteFileMode.");
                }
            }
            else
            {
                path        = Args.AsPath(args, 0, false);
                tags        = Args.AsStringArrayOptional(args, 2);
                description = Args.AsStringOptional(args, 3);

                switch (mode)
                {
                case WriteFileMode.WriteFile:
                    var fileContent = Args.AsIs(args, 1);
                    // WriteFile has a separator argument with default newline
                    var separator = Args.AsStringOptional(args, 3) ?? Environment.NewLine;
                    description = Args.AsStringOptional(args, 4);

                    pipData = CreatePipDataForWriteFile(context, fileContent, separator);
                    break;

                case WriteFileMode.WriteData:
                    var data = Args.AsIs(args, 1);
                    pipData = ProcessData(context, EvaluationResult.Create(data), new ConversionContext(pos: 1));
                    break;

                case WriteFileMode.WriteAllLines:
                    var lines   = Args.AsArrayLiteral(args, 1);
                    var entry   = context.TopStack;
                    var newData = ObjectLiteral.Create(
                        new List <Binding>
                    {
                        new Binding(m_dataSeparator, Environment.NewLine, entry.InvocationLocation),
                        new Binding(m_dataContents, lines, entry.InvocationLocation),
                    },
                        lines.Location,
                        entry.Path);

                    pipData = ProcessData(context, EvaluationResult.Create(newData), new ConversionContext(pos: 1));
                    break;

                case WriteFileMode.WriteAllText:
                    var text = Args.AsString(args, 1);
                    pipData = ProcessData(context, EvaluationResult.Create(text), new ConversionContext(pos: 1));
                    break;

                default:
                    throw Contract.AssertFailure("Unknown WriteFileMode.");
                }
            }

            FileArtifact result;

            if (!context.GetPipConstructionHelper().TryWriteFile(path, pipData, WriteFileEncoding.Utf8, tags, description, out result))
            {
                // Error has been logged
                return(EvaluationResult.Error);
            }

            return(new EvaluationResult(result));
        }