Example #1
0
                public override void Visit(BreakExpressionNode node)
                {
                    var kw = node.BreakKeywordToken;

                    if (!kw.IsMissing)
                    {
                        var func = _scope.Function !;

                        if (func.GetLoop() is PrimaryExpressionNode loop)
                        {
                            var block = loop switch
                            {
                                ForExpressionNode f => f.Body,
                                WhileExpressionNode w => w.Body,
                                _ => throw DebugAssert.Unreachable(),
                            };

                            node.SetAnnotation("Target", loop);
                            node.SetAnnotation("Uses", func.GetUses(func.GetDepth(block)));
                        }
                        else
                        {
                            Error(node, SyntaxDiagnosticKind.InvalidLoopTarget, kw.Location,
                                  "No enclosing 'while' or 'for' expression for this 'break' expression");
                        }
                    }

                    base.Visit(node);
                }
Example #2
0
        static FlareTestEnvironment()
        {
            var os = "unix";

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                os = "windows";
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                os = "darwin";
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD))
            {
                os = "freebsd";
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                os = "linux";
            }

            var(arch, bits) = RuntimeInformation.ProcessArchitecture switch
            {
                Architecture.X86 => ("x86", "32"),
                Architecture.X64 => ("x86", "64"),
                Architecture.Arm => ("arm", "32"),
                Architecture.Arm64 => ("arm", "64"),
                _ => throw DebugAssert.Unreachable(),
            };

            Symbols = ImmutableHashSet.Create(os, $"{os}-{arch}", $"{os}-{bits}", $"{os}-{arch}-{bits}", arch,
                                              $"{arch}-{bits}", bits);
        }
Example #3
0
        public override IEnumerable <(SyntaxNode, SyntaxDiagnostic)> Run(NamedDeclarationNode node)
        {
            if (node.VisibilityKeywordToken?.Kind != SyntaxTokenKind.PubKeyword)
            {
                yield break;
            }

            var type = node switch
            {
                ConstantDeclarationNode _ => "constant",
                FunctionDeclarationNode _ => "function",
                ExternalDeclarationNode _ => "function",
                _ => throw DebugAssert.Unreachable(),
            };

            var ident = node.NameToken;

            if (ident.IsMissing)
            {
                yield break;
            }

            var diag = CheckDocAttribute(node.Attributes, ident.Location, $"Public {type} {ident} is undocumented");

            if (diag != null)
            {
                yield return(node, diag);
            }
        }
Example #4
0
            /// <summary>
            /// Consumes a symbol from oldSymbols, and puts it into destination and/or tails of oldSymbols. Handles overlapping with newSymbols.
            /// The head of a symbol is the part from start of the *old* symbol till the start of the *new* one.
            /// The tail of the symbol is the part from the end of the *new* symbol till the end of the *old*.
            /// This function copies over the head to the destination and adds a tail to the tail set (of course
            /// when it makes sense).
            /// </summary>
            /// <param name="newSymbols">Provider of new symbols.</param>
            /// <param name="destination">Destination container.</param>
            /// <param name="oldSymbols">OldSymbolsProvider, symbols provider.</param>
            /// <param name="createdSymbols">Container with the symbols that got created during merging.</param>
            /// <param name="deletedSymbols">Container with the symbols that got got replaced/deleted during merging.</param>
            private void AddSymbolWithHashing(OldSymbolProvider oldSymbols, ISymbolProvider newSymbols, ICollection <Symbol> destination, ICollection <Symbol> createdSymbols, ICollection <Symbol> deletedSymbols)
            {
                var consumedSymbolType = oldSymbols.CurrentType;
                var symbolToAdd        = oldSymbols.Consume();

                //If there is no symbol to potentially overlap just copy the orignal one
                if (newSymbols.Empty)
                {
                    destination.Add(symbolToAdd);
                    return;
                }

                if (consumedSymbolType == OldSymbolProvider.SymbolType.Original)
                {
                    deletedSymbols.Add(symbolToAdd);
                }

                //If the symbol to add starts before the new one, add its head to the destination.
                if (symbolToAdd.Start < newSymbols.Current.Start)
                {
                    Symbol symbolHead;
                    symbolToAdd.TryGetRightTrimmed(newSymbols.Current.Start, out symbolHead);
                    //If there are symbols on the tail list, check if the trimming would produce the same interval.
                    //If so, we skip the current addition. We do so, because in such case we want to preserve the top (most inner-one) former symbol.
                    //We need, however, to process the possible remainder, a new tail might be generated.
                    Symbol trimmedTail;
                    if (!oldSymbols.HasNextTail ||
                        !oldSymbols.NextTail.TryGetRightTrimmed(newSymbols.Current.Start, out trimmedTail) ||
                        comparer.Compare(symbolHead, trimmedTail) != 0)
                    {
                        destination.Add(symbolHead);
                        createdSymbols.Add(symbolHead);
                    }
                }

                if (newSymbols.Current.Length == 0 && symbolToAdd.Start == newSymbols.Current.Start)
                {
                    destination.Add(symbolToAdd);
                    return;
                }

                //if there is something behind it add it to the new symbols list
                if (symbolToAdd.End > newSymbols.Current.End)
                {
                    Symbol symbolTail;
                    symbolToAdd.TryGetLeftTrimmed(newSymbols.Current.End, out symbolTail);
                    oldSymbols.AddTail(symbolTail);
                    #if DEBUG
                    DebugAssert.AssertFalse(
                        newSymbols.Current.Overlaps(symbolTail),
                        "New symbol overlaps with created tail! Old and new symbols should not overlap."
                        );
                    #endif
                    return;
                }

                //There is one another case. Where the overlapping candidate completely overshadows the symbol.
                //Don't do anything, the overshadowed symbol got deleted anyways and no new symbol gets created.
            }
Example #5
0
 public override void ToString(IndentedTextWriter writer)
 {
     writer.Write(Value switch
     {
         null => "nil",
         bool b => b ? "true" : "false",
         string a => $":{a}",
         BigInteger i => i.ToString(),
         double d => d.ToString(),
         ReadOnlyMemory <byte> s => $"\"{Encoding.UTF8.GetString(s.Span)}\"",
         _ => throw DebugAssert.Unreachable(),
     });
Example #6
0
        public override TreeReference Visit(LogicalExpressionNode node, TreeReference state)
        {
            var loc   = node.OperatorToken.Location;
            var left  = Visit(node.LeftOperand);
            var right = Visit(node.RightOperand);

            return(node.OperatorToken.Kind switch
            {
                SyntaxTokenKind.AndKeyword => new TreeLogicalAndNode(_context, loc, left, right),
                SyntaxTokenKind.OrKeyword => new TreeLogicalOrNode(_context, loc, left, right),
                _ => throw DebugAssert.Unreachable(),
            });
Example #7
0
        public override string ToString()
        {
            var value = Value switch
            {
                null => "nil",
                bool b => b ? "true" : "false",
                string a => $":{a}",
                BigInteger i => i.ToString(),
                double d => d.ToString(),
                ReadOnlyMemory <byte> s => $"\"{Encoding.UTF8.GetString(s.Span)}\"",
                _ => throw DebugAssert.Unreachable(),
            };

            return($"{Name} = {value}");
        }
Example #8
0
        public override void ToString(IndentedTextWriter writer)
        {
            writer.Write("(");
            Left.ToString(writer);

            writer.Write(" {0} ", Operator switch
            {
                TreeRelationalOperator.Equal => "==",
                TreeRelationalOperator.NotEqual => "!=",
                TreeRelationalOperator.LessThan => "<",
                TreeRelationalOperator.LessThanOrEqual => "<=",
                TreeRelationalOperator.GreaterThan => ">",
                TreeRelationalOperator.GreaterThanOrEqual => ">=",
                _ => throw DebugAssert.Unreachable(),
            });
Example #9
0
        Project(string path)
        {
            ProjectDirectory    = new DirectoryInfo(Path.GetDirectoryName(path) !);
            DependencyDirectory = new DirectoryInfo(Path.Combine(ProjectDirectory.FullName, "dep"));
            SourceDirectory     = new DirectoryInfo(Path.Combine(ProjectDirectory.FullName, "src"));
            BuildDirectory      = new DirectoryInfo(Path.Combine(ProjectDirectory.FullName, "bin"));

            // TODO: make this parsing more robust in general, and add error reporting.

            var table   = Toml.ReadFile(path);
            var project = (TomlTable)table.Get("project");

            Type       = (ProjectType)Enum.Parse(typeof(ProjectType), project.Get <string>("type"), true);
            Name       = project.Get <string>("name");
            MainModule = new FileInfo(Path.Combine(SourceDirectory.FullName, Path.ChangeExtension(Name,
                                                                                                  StandardModuleLoader.ModuleFileNameExtension) !));
            ExecutableFileName = table.TryGetValue("executable")?.Get <string>();
            Version            = SemanticVersion.Parse(project.Get <string>("version"));
            License            = project.TryGetValue("license")?.Get <string>();
            Description        = project.TryGetValue("description")?.Get <string>();
            ProjectUri         = project.TryGetValue("url") is TomlObject o1 ? new Uri(o1.Get <string>()) : null;
            DocumentationUri   = project.TryGetValue("url-doc") is TomlObject o2 ? new Uri(o2.Get <string>()) : null;
            SourceUri          = project.TryGetValue("url-src") is TomlObject o3 ? new Uri(o3.Get <string>()) : null;

            var cfg = new SyntaxLintConfiguration();

            if (table.TryGetValue("lints") is TomlTable lints)
            {
                foreach (var kvp in lints)
                {
                    cfg = cfg.Set(kvp.Key, kvp.Value.Get <string>().ToLowerInvariant() switch
                    {
                        LanguageLinter.NoneSeverityName => (SyntaxDiagnosticSeverity?)null,
                        LanguageLinter.SuggestionSeverityName => SyntaxDiagnosticSeverity.Suggestion,
                        LanguageLinter.WarninngSeverityName => SyntaxDiagnosticSeverity.Warning,
                        LanguageLinter.ErrorSeverityName => SyntaxDiagnosticSeverity.Error,
                        _ => throw DebugAssert.Unreachable(),
                    });
Example #10
0
        internal Module(ModuleLoader loader, ModulePath path, ProgramNode node)
            : base(node.Attributes)
        {
            Loader = loader;
            Path   = path;

            var decls = ImmutableArray <Declaration> .Empty;

            foreach (var decl in node.Declarations)
            {
                if (decl is UseDeclarationNode)
                {
                    continue;
                }

                decls = decls.Add(decl switch
                {
                    ConstantDeclarationNode c => (Declaration) new Constant(this, c),
                    FunctionDeclarationNode f => new Function(this, f),
                    ExternalDeclarationNode e => new External(this, e),
                    TestDeclarationNode t => new Test(this, t),
                    _ => throw DebugAssert.Unreachable(),
                });
Example #11
0
        public FlareTestResult Run()
        {
            var syms = FlareTestEnvironment.Symbols;

            foreach (var filter in Filters)
            {
                var ok = filter.Kind switch
                {
                    FlareTestFilterKind.IfSet => syms.Contains(filter.Value),
                    FlareTestFilterKind.IfUnset => !syms.Contains(filter.Value),
                    _ => throw DebugAssert.Unreachable(),
                };

                if (!ok)
                {
                    return(new FlareTestResult());
                }
            }

            var vars = new Dictionary <string, string>();

            foreach (var elem in Environment.GetEnvironmentVariables())
            {
                var(key, value) = (DictionaryEntry)elem !;

                vars.Add((string)key, (string)value !);
            }

            // Note that we might need to overwrite existing variables here.
            foreach (var(key, value) in Variables)
            {
                vars[key] = value;
            }

            var stdout = new StringBuilder();
            var stderr = new StringBuilder();
Example #12
0
            (SourceLocation, SyntaxTokenKind) LexOperator(SourceLocation location)
            {
                var c1 = ((Rune)MoveNext() !).Value;
                var r2 = PeekNext();
                var c2 = r2?.Value;

                // Handle most of the special operators first, where the runes can't possibly be
                // part of a longer custom operator.

                if (c1 == '!')
                {
                    if (c2 == '=')
                    {
                        ConsumeNext();
                    }
                    else
                    {
                        Error(SyntaxDiagnosticKind.IncompleteOperator, _location,
                              $"Expected '=', but found {(r2 != null ? $"'{r2}'" : "end of input")}");
                    }

                    return(location, SyntaxTokenKind.ExclamationEquals);
                }

                if (c1 == '<' && c2 == '=')
                {
                    ConsumeNext();

                    return(location, SyntaxTokenKind.OpenAngleEquals);
                }

                if (c1 == '=')
                {
                    if (c2 == '=')
                    {
                        ConsumeNext();

                        return(location, SyntaxTokenKind.EqualsEquals);
                    }
                    else if (c2 == '>')
                    {
                        ConsumeNext();

                        return(location, SyntaxTokenKind.EqualsCloseAngle);
                    }

                    return(location, SyntaxTokenKind.Equals);
                }

                if (c1 == '>' && c2 == '=')
                {
                    ConsumeNext();

                    return(location, SyntaxTokenKind.OpenAngleEquals);
                }

                var parts = 1;

                // Lex the full operator.
                while (PeekNext() is Rune cur)
                {
                    switch (cur.Value)
                    {
                    case '%':
                    case '&':
                    case '*':
                    case '+':
                    case '-':
                    case '/':
                    case '<':
                    case '>':
                    case '^':
                    case '|':
                    case '~':
                        ConsumeNext();
                        parts++;
                        continue;

                    default:
                        break;
                    }

                    break;
                }

                // Handle remaining special operators.
                switch (parts)
                {
                case 1:
                    if (c1 == '<')
                    {
                        return(location, SyntaxTokenKind.OpenAngle);
                    }

                    if (c1 == '>')
                    {
                        return(location, SyntaxTokenKind.CloseAngle);
                    }

                    break;

                case 2:
                    if (c1 == '-' && c2 == '>')
                    {
                        return(location, SyntaxTokenKind.MinusCloseAngle);
                    }

                    if (c1 == '<' && c2 == '-')
                    {
                        return(location, SyntaxTokenKind.OpenAngleMinus);
                    }

                    break;
                }

                SyntaxTokenKind kind;

                // At this point, it's definitely a custom operator, so determine the category.
                switch (c1)
                {
                case '%':
                case '*':
                case '/':
                    kind = SyntaxTokenKind.MultiplicativeOperator;
                    break;

                case '+':
                case '-':
                case '~':
                    kind = SyntaxTokenKind.AdditiveOperator;
                    break;

                case '<':
                case '>':
                    kind = SyntaxTokenKind.ShiftOperator;
                    break;

                case '&':
                case '^':
                case '|':
                    kind = SyntaxTokenKind.BitwiseOperator;
                    break;

                default:
                    throw DebugAssert.Unreachable();
                }

                return(location, kind);
            }
Example #13
0
            static BigInteger CreateInteger(string value)
            {
                var radix = 10;

                if (value.StartsWith("0B") || value.StartsWith("0b"))
                {
                    radix = 2;
                }
                else if (value.StartsWith("0O") || value.StartsWith("0o"))
                {
                    radix = 8;
                }
                else if (value.StartsWith("0X") || value.StartsWith("0x"))
                {
                    radix = 16;
                }

                var str = value.AsSpan();

                // Strip base prefix.
                if (radix != 10)
                {
                    str = str.Slice(2);
                }

                // Avoid BigInteger allocations/calculations for some very common cases.

                if (str.Trim('0').IsEmpty)
                {
                    return(BigInteger.Zero);
                }

                if (str.TrimStart('0').SequenceEqual("1"))
                {
                    return(BigInteger.One);
                }

                var result = BigInteger.Zero;

                foreach (var c in str)
                {
                    int digit;

                    if (c - '0' <= 9)
                    {
                        digit = c - '0';
                    }
                    else if (c - 'A' <= 'Z' - 'A')
                    {
                        digit = c - 'A' + 10;
                    }
                    else if (c - 'a' <= 'z' - 'a')
                    {
                        digit = c - 'a' + 10;
                    }
                    else
                    {
                        throw DebugAssert.Unreachable();
                    }

                    result = result * radix + digit;
                }

                return(result);
            }
Example #14
0
 protected override TreePattern DefaultVisit(SyntaxNode node, TreePattern state)
 {
     throw DebugAssert.Unreachable();
 }