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()); }
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)); }
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()); } } }
public void BuildScopesInPackage(PackageSyntax package) { foreach (var compilationUnit in package.CompilationUnits) { BuildScopesInCompilationUnit(compilationUnit); } }
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)); }
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 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); } }
public LexicalScopesBuilder( Diagnostics diagnostics, PackageSyntax packageSyntax, FixedDictionary <string, Package> references) { this.diagnostics = diagnostics; allSymbols = GetAllSymbols(packageSyntax, references); globalScope = new GlobalScope(GetAllGlobalSymbols(), allSymbols); }
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()); }
private static Diagnostics AllDiagnostics(PackageSyntax packageSyntax) { var diagnostics = new Diagnostics(); foreach (var compilationUnit in packageSyntax.CompilationUnits) { diagnostics.Add(compilationUnit.Diagnostics); } return(diagnostics); }
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)); }
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)); }
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); } }
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); }
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)); }
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 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)); }
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 Package(PackageSyntax syntax) : base(syntax, Accessibility.NotApplicable, syntax?.Name) { GlobalNamespace = new Namespace(this); }
/// <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; }
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; }
public Package Compile(PackageSyntax package, IEnumerable <Package> compiledPackages) { return(new PackageSemanticsBuilder(package, compiledPackages).Build()); }
public PackageSemanticsBuilder(PackageSyntax packageSyntax, IEnumerable <Package> packages) { this.packageSyntax = packageSyntax; this.packages = packages.ToList(); }
public static void Check(PackageSyntax package, ObjectTypeSymbol?stringSymbol) { var analyzer = new BasicAnalyzer(package.SymbolTree, package.SymbolTrees, stringSymbol, package.Diagnostics); analyzer.Check(package.AllEntityDeclarations); }