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);
        }
        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());
            }
        }
 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}");
     }
 }
        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());
        }
        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);
        }
 public PackageSemanticsBuilder(PackageSyntax packageSyntax, IEnumerable<Package> packages)
 {
     this.packageSyntax = packageSyntax;
     this.packages = packages.ToList();
 }
 public Package Compile(PackageSyntax package, IEnumerable<Package> compiledPackages)
 {
     return new PackageSemanticsBuilder(package, compiledPackages).Build();
 }