コード例 #1
0
        private static FixedList <NonMemberSymbol> GetAllNonMemberDeclarationSymbols(PackageSyntax package)
        {
            var primitiveSymbols = Primitive.SymbolTree.Symbols
                                   .Where(s => s.ContainingSymbol is null)
                                   .Select(s => new NonMemberSymbol(s));

            var packageNamespaces = package.SymbolTree.Symbols
                                    .OfType <NamespaceSymbol>()
                                    .Select(s => new NonMemberSymbol(s));

            var packageSymbols = package.AllEntityDeclarations
                                 .OfType <INonMemberEntityDeclarationSyntax>()
                                 .Select(d => new NonMemberSymbol(d));

            // TODO it might be better to go to the declarations and get their symbols (once that is implemented)
            var referencedSymbols = package.ReferencedPackages
                                    .SelectMany(p => p.SymbolTree.Symbols)
                                    .Concat(Intrinsic.SymbolTree.Symbols)
                                    .Where(s => s.ContainingSymbol is NamespaceOrPackageSymbol)
                                    .Select(s => new NonMemberSymbol(s));

            return(primitiveSymbols
                   .Concat(packageNamespaces)
                   .Concat(packageSymbols)
                   .Concat(referencedSymbols)
                   .ToFixedList());
        }
コード例 #2
0
        public PackageIL Check(PackageSyntax packageSyntax)
        {
            // If there are errors from the lex and parse phase, don't continue on
            packageSyntax.Diagnostics.ThrowIfFatalErrors();

            NamespaceSymbolBuilder.BuildNamespaceSymbols(packageSyntax);

            // Build up lexical scopes down to the declaration level
            new LexicalScopesBuilder().BuildFor(packageSyntax);

            // Check the semantics of the package
            var packageAbstractSyntax = CheckSemantics(packageSyntax);

            // If there are errors from the semantics phase, don't continue on
            packageAbstractSyntax.Diagnostics.ThrowIfFatalErrors();

            // --------------------------------------------------
            // This is where the representation transitions to IR
            var declarationsIL = BuildIL(packageAbstractSyntax);

            // --------------------------------------------------

            // If there are errors from the previous phase, don't continue on
            // TODO can the BuildIL() step introduce errors?
            packageAbstractSyntax.Diagnostics.ThrowIfFatalErrors();

            var entryPointIL = DetermineEntryPoint(declarationsIL, packageAbstractSyntax.Diagnostics);

            var references = packageSyntax.ReferencedPackages.ToFixedSet();

            return(new PackageIL(packageAbstractSyntax.SymbolTree, packageAbstractSyntax.Diagnostics.Build(), references, declarationsIL, entryPointIL));
        }
コード例 #3
0
        public CompilationUnitSyntax Parse(PackageSyntax package, SourceText sourceText)
        {
            // TODO make use of the package.  We don't currently use the package, but we
            // are taking it as an argument becuase we should be for things like:
            //   * Language Version
            //   * Dependency Names
            //   * Defined Preprocessor Symbols
            var builder = new ParseDiagnosticsBuilder(sourceText);
            var parser  = sourceText.NewParser();

            // Stupid ANTLR makes it difficult to do this in the constructor
            parser.RemoveErrorListeners();
            var errorsListener = new GatherErrorsListener(builder);

            parser.AddErrorListener(errorsListener);
            parser.Interpreter.PredictionMode = PredictionMode.LlExactAmbigDetection;

            var tree        = parser.compilationUnit();
            var syntaxCheck = new SyntaxCheckVisitor(builder);

            tree.Accept(syntaxCheck);

            var diagnostics = builder.Complete();

            if (diagnostics.Any())
            {
                return(new CompilationUnitSyntax(sourceText, Enumerable.Empty <UsingSyntax>(), Enumerable.Empty <DeclarationSyntax>(), diagnostics));
            }

            var compilationUnitBuilder = new CompilationUnitBuilder(sourceText, diagnostics);

            return(tree.Accept(compilationUnitBuilder));
        }
コード例 #4
0
        public void Test(TestCaseConfig config, TextReader reader)
        {
            var dependencies = config.Runtime ? new[] { runtimeDependency } : Enumerable.Empty <PackageReferenceSyntax>();
            var package      = new PackageSyntax($"Adamant.Exploratory.Compiler.Tests.{config.TestName}", true, dependencies);
            var unit         = compiler.Parse(package, new SourceReader(config.FileName, reader));

            package = package.With(new[] { unit });
            if (package.Diagnostics.Count > 0)
            {
                Assert.Fail(ToString(package.Diagnostics));
            }
            var compiledPackage = compiler.Compile(package, Enumerable.Empty <Package>());

            if (compiledPackage.Diagnostics.Count > 0)
            {
                Assert.Fail(ToString(compiledPackage.Diagnostics));
            }

            var cppSource     = compiler.EmitCpp(compiledPackage);
            var cppSourceName = compiledPackage.Name + ".cpp";

            CreateFile(cppSourceName, cppSource);
            CreateFile(CppRuntime.FileName, CppRuntime.Source);
            var targetPath = Path.Combine(WorkPath, compiledPackage.Name + ".exe");
            var result     = CppCompiler.Invoke(Path.Combine(WorkPath, cppSourceName), targetPath);

            if (result.ExitCode != 0)
            {
                result.WriteOutputToConsole();
                Assert.Fail("C++ compiler error");
            }

            // Execute the app
            using (var process = new Process())
            {
                process.StartInfo.FileName               = targetPath;
                process.StartInfo.WorkingDirectory       = Path.GetDirectoryName(WorkPath);
                process.StartInfo.CreateNoWindow         = true;
                process.StartInfo.UseShellExecute        = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;
                var outputBuffer = new StringBuilder();
                var errorBuffer  = new StringBuilder();
                process.OutputDataReceived += (s, e) => outputBuffer.AppendLine(e.Data);
                process.ErrorDataReceived  += (s, e) => errorBuffer.AppendLine(e.Data);
                process.Start();
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
                process.WaitForExit();

                if (config.Result != null)
                {
                    Assert.AreEqual(config.Result, process.ExitCode, "Exit Code");
                }
                if (config.VerifyConsoleOutput)
                {
                    Assert.AreEqual(config.ExpectedConsoleOutput, outputBuffer.ToString());
                }
            }
        }
コード例 #5
0
 public void BuildScopesInPackage(PackageSyntax package)
 {
     foreach (var compilationUnit in package.CompilationUnits)
     {
         BuildScopesInCompilationUnit(compilationUnit);
     }
 }
コード例 #6
0
        public PackageIL CompilePackage(
            string name,
            IEnumerable <CodeFile> files,
            FixedDictionary <Name, PackageIL> references)
        {
            var lexer            = new Lexer();
            var parser           = new CompilationUnitParser();
            var compilationUnits = files
                                   .Select(file =>
            {
                var context = new ParseContext(file, new Diagnostics());
                var tokens  = lexer.Lex(context).WhereNotTrivia();
                return(parser.Parse(tokens));
            })
                                   .ToFixedSet();
            var packageSyntax = new PackageSyntax(name, compilationUnits, references);

            var analyzer = new SemanticAnalyzer()
            {
                SaveLivenessAnalysis   = SaveLivenessAnalysis,
                SaveReachabilityGraphs = SaveReachabilityGraphs,
            };

            return(analyzer.Check(packageSyntax));
        }
コード例 #7
0
        public void Test(TestCaseConfig config, TextReader reader)
        {
            var dependencies = config.Runtime ? new[] { runtimeDependency } : Enumerable.Empty <PackageReferenceSyntax>();
            var package      = new PackageSyntax($"Adamant.Exploratory.Compiler.Tests.{config.TestName}", true, dependencies);
            var unit         = compiler.Parse(package, new SourceReader(config.FileName, reader));

            package = package.With(new[] { unit });
            if (package.Diagnostics.Count > 0)
            {
                Assert.Fail(ToString(package.Diagnostics));
            }
            var compiledPackage = compiler.Compile(package, Enumerable.Empty <Package>());

            if (compiledPackage.Diagnostics.Count > 0)
            {
                Assert.Fail(ToString(compiledPackage.Diagnostics));
            }

            var interpreter  = new AdamantInterpreter(compiledPackage);
            var entryPoint   = compiledPackage.EntryPoints.Single();
            var outputBuffer = new StringBuilder();
            var errorBuffer  = new StringBuilder();
            var exitCode     = interpreter.Invoke(entryPoint, new string[0], new StringWriter(outputBuffer), new StringWriter(errorBuffer));

            Assert.AreEqual(config.Result, exitCode, "Exit Code");
            if (config.VerifyConsoleOutput)
            {
                Assert.AreEqual(config.ExpectedConsoleOutput, outputBuffer.ToString());
            }
        }
コード例 #8
0
        private static PackagesScope BuildPackagesScope(PackageSyntax package)
        {
            var packageAliases = package.References
                                 .ToDictionary(p => p.Key, p => p.Value.Symbol)
                                 .ToFixedDictionary();

            return(new PackagesScope(package.Symbol, packageAliases));
        }
        public static void BuildNamespaceSymbols(PackageSyntax package)
        {
            var builder = new NamespaceSymbolBuilder(package.SymbolTree);

            foreach (var compilationUnit in package.CompilationUnits)
            {
                builder.Walk(compilationUnit, package.Symbol);
            }
        }
コード例 #10
0
 public LexicalScopesBuilder(
     Diagnostics diagnostics,
     PackageSyntax packageSyntax,
     FixedDictionary <string, Package> references)
 {
     this.diagnostics = diagnostics;
     allSymbols       = GetAllSymbols(packageSyntax, references);
     globalScope      = new GlobalScope(GetAllGlobalSymbols(), allSymbols);
 }
コード例 #11
0
 private static FixedList <ISymbol> GetAllSymbols(
     PackageSyntax packageSyntax,
     FixedDictionary <string, Package> references)
 {
     return(references.Values
            .SelectMany(p => p.Declarations.Where(d => !d.IsMember))
            .Concat(packageSyntax.CompilationUnits.SelectMany(GetAllNonMemberDeclarations))
            .ToFixedList());
 }
コード例 #12
0
        private static Diagnostics AllDiagnostics(PackageSyntax packageSyntax)
        {
            var diagnostics = new Diagnostics();

            foreach (var compilationUnit in packageSyntax.CompilationUnits)
            {
                diagnostics.Add(compilationUnit.Diagnostics);
            }
            return(diagnostics);
        }
コード例 #13
0
        public Package BuildPackage(PackageSyntax packageSyntax)
        {
            var nonMemberDeclarations = packageSyntax.AllEntityDeclarations
                                        .OfType <INonMemberEntityDeclarationSyntax>()
                                        .Select(BuildNonMemberDeclaration).ToFixedList();

            var symbolTree = packageSyntax.SymbolTree.Build();

            return(new Package(nonMemberDeclarations, symbolTree, packageSyntax.Diagnostics, packageSyntax.References));
        }
コード例 #14
0
        public async Task <PackageIL> CompilePackageAsync(
            Name name,
            IEnumerable <ICodeFileSource> fileSources,
            FixedDictionary <Name, Task <PackageIL> > referenceTasks,
            TaskScheduler taskScheduler)
        {
            var lexer      = new Lexer();
            var parser     = new CompilationUnitParser();
            var parseBlock = new TransformBlock <ICodeFileSource, ICompilationUnitSyntax>(
                async(fileSource) =>
            {
                var file    = await fileSource.LoadAsync().ConfigureAwait(false);
                var context = new ParseContext(file, new Diagnostics());
                var tokens  = lexer.Lex(context).WhereNotTrivia();
                return(parser.Parse(tokens));
            }, new ExecutionDataflowBlockOptions()
            {
                TaskScheduler = taskScheduler,
                EnsureOrdered = false,
            });

            foreach (var fileSource in fileSources)
            {
                parseBlock.Post(fileSource);
            }

            parseBlock.Complete();

            await parseBlock.Completion.ConfigureAwait(false);

            if (!parseBlock.TryReceiveAll(out var compilationUnits))
            {
                throw new Exception("Not all compilation units are ready");
            }

            var referencePairs = await Task
                                 .WhenAll(referenceTasks.Select(async kv =>
                                                                (alias: kv.Key, package: await kv.Value.ConfigureAwait(false))))
                                 .ConfigureAwait(false);

            var references = referencePairs.ToFixedDictionary(r => r.alias, r => r.package);

            // TODO add the references to the package syntax
            var packageSyntax = new PackageSyntax(name, compilationUnits.ToFixedSet(), references);

            var analyzer = new SemanticAnalyzer()
            {
                SaveLivenessAnalysis   = SaveLivenessAnalysis,
                SaveReachabilityGraphs = SaveReachabilityGraphs,
            };

            return(analyzer.Check(packageSyntax));
        }
コード例 #15
0
        public void BuildFor(PackageSyntax package)
        {
            var declarationSymbols = GetAllNonMemberDeclarationSymbols(package);
            var namespaces         = BuildNamespaces(declarationSymbols);
            var packagesScope      = BuildPackagesScope(package);
            var globalScope        = BuildGlobalScope(packagesScope, namespaces[NamespaceName.Global]);

            foreach (var compilationUnit in package.CompilationUnits)
            {
                var builder = new LexicalScopesBuilderWalker(globalScope, namespaces);
                builder.BuildFor(compilationUnit, globalScope);
            }
        }
コード例 #16
0
        private static Package CheckSemantics(PackageSyntax packageSyntax)
        {
            DeclarationNumberAssigner.AssignIn(packageSyntax.AllEntityDeclarations);

            // Resolve symbols for the entities
            EntitySymbolBuilder.BuildFor(packageSyntax);

            var stringSymbol = packageSyntax.SymbolTrees
                               .GlobalSymbols
                               .OfType <ObjectTypeSymbol>()
                               .SingleOrDefault(s => s.Name == "String");

            // Basic Analysis includes: Name Binding, Type Checking, Constant Folding
            BasicAnalyzer.Check(packageSyntax, stringSymbol);

            // If there are errors from the basic analysis phase, don't continue on
            packageSyntax.Diagnostics.ThrowIfFatalErrors();

#if DEBUG
            new SymbolValidator(packageSyntax.SymbolTree).Validate(packageSyntax.AllEntityDeclarations);
            new TypeFulfillmentValidator().Validate(packageSyntax.AllEntityDeclarations);
            new TypeKnownValidator().Validate(packageSyntax.AllEntityDeclarations);
            new ExpressionSemanticsValidator().Validate(packageSyntax.AllEntityDeclarations);
#endif

            var package = new ASTBuilder().BuildPackage(packageSyntax);

            // From this point forward, analysis focuses on executable declarations (i.e. invocables and field initializers)
            var executableDeclarations = package.AllDeclarations.OfType <IExecutableDeclaration>().ToFixedSet();

            ShadowChecker.Check(executableDeclarations, package.Diagnostics);

            DataFlowAnalysis.Check(DefiniteAssignmentAnalyzer.Instance, executableDeclarations, package.SymbolTree, package.Diagnostics);

            DataFlowAnalysis.Check(BindingMutabilityAnalyzer.Instance, executableDeclarations, package.SymbolTree, package.Diagnostics);

            DataFlowAnalysis.Check(UseOfMovedValueAnalyzer.Instance, executableDeclarations, package.SymbolTree, package.Diagnostics);

            // TODO use DataFlowAnalysis to check for unused variables and report use of variables starting with `_`

            // Compute variable liveness needed by reachability analyzer
            DataFlowAnalysis.Check(LivenessAnalyzer.Instance, executableDeclarations, package.SymbolTree, package.Diagnostics);

            ReachabilityAnalyzer.Analyze(executableDeclarations, package.SymbolTree, package.Diagnostics);

            // TODO remove live variables if SaveLivenessAnalysis is false

            return(package);
        }
コード例 #17
0
        public Package Analyze(
            PackageSyntax packageSyntax,
            FixedDictionary <string, Package> references)
        {
            // First pull over all the lexer and parser errors from the compilation units
            var diagnostics = AllDiagnostics(packageSyntax);

            var scopesBuilder = new LexicalScopesBuilder(diagnostics, packageSyntax, references);

            scopesBuilder.BuildScopesInPackage(packageSyntax);

            // Make a list of all the member declarations (i.e. not namespaces)
            var memberDeclarations = packageSyntax.CompilationUnits
                                     .SelectMany(cu => cu.AllMemberDeclarations).ToFixedList();

            // TODO we can't do full type checking without some IL gen and code execution, how to handle that?

            // Do type checking
            TypeResolver.Check(memberDeclarations, diagnostics);

#if DEBUG
            TypeResolutionValidator.Validate(memberDeclarations);
            // TODO validate that all ReferencedSymbols lists have a single value non-errored code
#endif
            MoveChecker.Check(memberDeclarations, diagnostics);

            ShadowChecker.Check(memberDeclarations, diagnostics);

            // TODO we need to check definite assignment as part of this
            BindingMutabilityChecker.Check(memberDeclarations, diagnostics);

            // --------------------------------------------------
            // This is where the representation transitions to IR
            ControlFlowAnalyzer.BuildGraphs(memberDeclarations);
            // --------------------------------------------------

            var liveness = LivenessAnalyzer.Analyze(memberDeclarations);

            DeleteInserter.Transform(memberDeclarations, liveness);

            BorrowChecker.Check(memberDeclarations, diagnostics);

            // Build final declaration objects and find the entry point
            var declarationBuilder = new DeclarationBuilder();
            var declarations       = declarationBuilder.Build(memberDeclarations);
            var entryPoint         = DetermineEntryPoint(declarations, diagnostics);

            return(new Package(packageSyntax.Name, diagnostics.Build(), references, declarations, entryPoint));
        }
コード例 #18
0
        private static void PrintDiagnostics(PackageSyntax package)
        {
            ISourceText file = null;

            foreach (var diagnostic in package.Diagnostics)
            {
                if (file != diagnostic.File)
                {
                    file = diagnostic.File;
                    Console.WriteLine($"In {file.Name}");
                }
                var level  = diagnostic.Level.ToString();
                var line   = diagnostic.Position.Line + 1;
                var column = diagnostic.Position.Column + 1;
                Console.WriteLine($"{level} on line {line} at character {column}: ");
                Console.WriteLine($"    {diagnostic.Message}");
            }
        }
コード例 #19
0
        public Package CompilePackage(
            string name,
            IEnumerable <CodeFile> files,
            FixedDictionary <string, Package> references)
        {
            var lexer            = new Lexer();
            var parser           = new CompilationUnitParser();
            var compilationUnits = files
                                   .Select(file =>
            {
                var context = new ParseContext(file, new Diagnostics());
                var tokens  = lexer.Lex(context).WhereNotTrivia();
                return(parser.Parse(tokens));
            })
                                   .ToFixedList();
            var packageSyntax = new PackageSyntax(name, compilationUnits);

            var analyzer = new SemanticAnalyzer();

            return(analyzer.Analyze(packageSyntax, references));
        }
コード例 #20
0
        private void CompileProject(string projectDirPath, ProjectConfig projectConfig, CompiledProjects projects)
        {
            Console.WriteLine($"Compiling {projectConfig.Name} ...");

            var sourceFiles = new DirectoryInfo(Path.Combine(projectDirPath, "src")).GetFiles("*.adam", SearchOption.AllDirectories);
            var isApp       = projectConfig.Template == "app";
            // TODO read trusted from config
            var package = new PackageSyntax(projectConfig.Name, isApp, projectConfig.Dependencies.Select(d => new PackageReferenceSyntax(d.Key, null, true)));

            package = package.With(sourceFiles.Select(fileInfo => compiler.Parse(package, new SourceFile(fileInfo))));
            if (package.Diagnostics.Count > 0)
            {
                PrintDiagnostics(package);
                return;
            }
            var compiledPackage = compiler.Compile(package, projects.Select(p => p.Package));
            var compiledProject = new CompiledProject(projectDirPath, compiledPackage);

            projects.Add(compiledProject);
            OnProjectCompiled(compiledProject, projects);
        }
コード例 #21
0
 public Package(PackageSyntax syntax)
     : base(syntax, Accessibility.NotApplicable, syntax?.Name)
 {
     GlobalNamespace = new Namespace(this);
 }
コード例 #22
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PackageSymbol"/> class.
 /// </summary>
 /// <param name="name">The name of the package.</param>
 /// <param name="declaration">The declaration.</param>
 public PackageSymbol(string name, PackageSyntax declaration)
     : base(name)
 {
     Declaration = declaration;
 }
コード例 #23
0
        public static void BuildFor(PackageSyntax package)
        {
            var builder = new EntitySymbolBuilder(package.Diagnostics, package.SymbolTree);

            builder.Build(package.AllEntityDeclarations);
        }
 public DeclarationBuilder(PackageSyntax package)
 {
     this.package = package;
 }
コード例 #25
0
 public Package Compile(PackageSyntax package, IEnumerable <Package> compiledPackages)
 {
     return(new PackageSemanticsBuilder(package, compiledPackages).Build());
 }
コード例 #26
0
 public PackageSemanticsBuilder(PackageSyntax packageSyntax, IEnumerable <Package> packages)
 {
     this.packageSyntax = packageSyntax;
     this.packages      = packages.ToList();
 }
コード例 #27
0
        public static void Check(PackageSyntax package, ObjectTypeSymbol?stringSymbol)
        {
            var analyzer = new BasicAnalyzer(package.SymbolTree, package.SymbolTrees, stringSymbol, package.Diagnostics);

            analyzer.Check(package.AllEntityDeclarations);
        }